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

bfd.c (316081B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        bfd.c
      8  * Purpose:     XGS5 Bidirectional Forwarding Detection common driver.
      9  *
     10  * Notes:      BFD functions will return BCM_E_UAVAIL unless these conditions
     11  *             are true:
     12  *               - BCM_CMICM_SUPPORT
     13  *               - soc_feature_cmicm
     14  */
     15 
     16 #include <shared/bsl.h>
     17 
     18 #include <soc/defs.h>
     19 
     20 #if defined(INCLUDE_BFD)
     21 #include <sal/core/libc.h>
     22 #include <shared/pack.h>
     23 #include <soc/drv.h>
     24 #include <soc/scache.h>
     25 #include <soc/hash.h>
     26 #include <soc/l3x.h>
     27 #include <soc/higig.h>
     28 #include <soc/uc.h>
     29 #include <soc/uc_msg.h>
     30 #include <soc/shared/mos_msg_common.h>
     31 #include <soc/shared/bfd.h>
     32 #include <soc/shared/bfd_pkt.h>
     33 #include <soc/shared/bfd_msg.h>
     34 #include <soc/shared/bfd_pack.h>
     35 
     36 #include <bcm_int/common/rx.h>
     37 #include <bcm_int/api_xlate_port.h>
     38 #include <bcm_int/esw/bfd.h>
     39 #include <bcm_int/esw/xgs5.h>
     40 #include <bcm_int/esw/l3.h>
     41 #include <bcm_int/esw/port.h>
     42 #include <bcm_int/esw_dispatch.h>
     43 #include <bcm_int/esw/switch.h>
     44 #include <bcm_int/esw/triumph.h>
     45 #include <bcm_int/esw/bfd_sdk_pack.h>
     46 #include <bcm/error.h>
     47 #include <bcm/bfd.h>
     48 #include <soc/trident2.h>
     49 #include <bcm_int/esw/triumph3.h>
     50 
     51 #if defined(BCM_TRIDENT3_SUPPORT)
     52 #include <soc/format.h>
     53 #include <soc/esw/cancun.h>
     54 #include <soc/trident3.h>
     55 #endif
     56 
     57 #if defined(BCM_TOMAHAWK3_SUPPORT)
     58 #include <soc/tomahawk3.h>
     59 #endif
     60 
     61 /* Maximum Memory Entry */
     62 typedef uint32 max_mem_entry_t[SOC_MAX_MEM_WORDS];
     63 
     64 
     65 /*
     66  * BFD Information SW Data
     67  */
     68 
     69 /* BFD Event Handler */
     70 typedef struct bfd_event_handler_s {
     71     struct bfd_event_handler_s *next;
     72     bcm_bfd_event_types_t event_types;
     73     bcm_bfd_event_cb cb;
     74     void *user_data;
     75 } bfd_event_handler_t;
     76 
     77 /* BFD Endpoint Configuration SW Data Structure */
     78 typedef struct bfd_endpoint_config_s {
     79     int endpoint_index;
     80     bcm_module_t  modid;    /* Destination module ID */
     81     bcm_port_t port;        /* Destination port */
     82     bcm_port_t tx_port;     /* Local physical port to TX BFD packet */
     83     int encap_type;         /* Raw, UDP-IPv4/IPv6, used for UDP checksum */
     84     int encap_length;       /* BFD Encapsulation length */
     85     int lkey_etype;         /* Lookup key Ether Type */
     86     int lkey_offset;        /* Lookup key offset */
     87     int lkey_length;        /* Lookup key length */
     88     bcm_bfd_endpoint_info_t info;
     89     int is_l3_vpn;          /* 1 for L3 VPN, 0 for L2 VPN */ 
     90     uint8 is_micro_bfd;     /*1 for Micro BFD session*/
     91     uint8 local_echo;       /*1 for BFD echo session*/
     92 } bfd_endpoint_config_t;
     93 
     94 /* BFD Information SW Data Structure */
     95 typedef struct bfd_info_s {
     96     int unit;                   /* Unit number */
     97     int initialized;            /* If set, BFD has been initialized */
     98     int endpoint_count;         /* Max number of BFD endpoints */
     99     int num_auth_sha1_keys;     /* Max number of sha1 auth keys */
    100     int num_auth_sp_keys;       /* Max number of simple pwd auth keys */
    101     bcm_cos_queue_t cpu_cosq;   /* CPU cos queue for RX BFD packets */
    102     int cosq_spath_index;       /* CPU cos queue map index for good packets */
    103     int cosq_ach_err_index;     /* CPU cos queue map index for ACH error */
    104     int cosq_unknown_version_index; /*CPU cos queue map index for unknown_version*/
    105     int rx_channel;             /* Local RX DMA channel for BFD packets */
    106     int uc_num;                 /* uController number running BFD appl */
    107     int dma_buffer_len;         /* DMA max buffer size */
    108     uint8* dma_buffer;          /* DMA buffer */
    109     SHR_BITDCL *endpoints_in_use;   /* Indicates used endpoint indexes */
    110     bfd_endpoint_config_t *endpoints;  /* Array to Endpoints */
    111     bcm_bfd_auth_sha1_t *auth_sha1; /* Array of sha1 auth keys */
    112     bcm_bfd_auth_simple_password_t *auth_sp; /* Array simple pwd auth keys */
    113     sal_thread_t event_thread_id;            /* Event handler thread id */
    114     bfd_event_handler_t *event_handler_list; /* List of event
    115                                                          handlers */
    116     uint32 event_mask;                       /* Mask of all events */
    117     uint8 bfd_feature_enable;   /* BFD feature enable bit set */
    118     uint8 use_sess_id_as_discr; /* Feature enable/disable to use session id
    119                                  * as local discriminator */
    120     uint8 static_remote_discr :1, /* Enable/disable static remote discr */
    121           bfd_cpi_bit         :1, /* Enable/Disable BFD CPI bit */
    122                               :6; /* Reserved for future use */
    123 #ifdef BCM_WARM_BOOT_SUPPORT
    124     uint16 wb_current_version;
    125     uint16 wb_next_version;
    126 #endif
    127     uint32 trace_addr;            /* Address in the uC holding the stack trace */
    128 } bfd_info_t;
    129 
    130 static bfd_info_t *bcm_xgs5_bfd_info[BCM_MAX_NUM_UNITS] = {0};
    131 
    132 STATIC int
    133 bcmi_xgs5_bfd_encap_create(int unit, bfd_endpoint_config_t *endpoint_config,
    134                            uint8 *encap_data);
    135 
    136 STATIC int
    137 bcmi_xgs5_bfd_endpoint_gport_resolve(int unit,
    138                                 uint8 is_tx,
    139                                 bcm_bfd_endpoint_info_t *endpoint_info,
    140                                 bcm_module_t *module_id,
    141                                 bcm_port_t   *port_id,
    142                                 bcm_trunk_t *trunk_id,
    143                                 int *local_id,
    144                                 uint8 *is_trunk_bfd,
    145                                 uint8 *is_micro_bfd);
    146 
    147 #define BFD_INFO(u_)                     (bcm_xgs5_bfd_info[(u_)])
    148 #define BFD_ENDPOINT_CONFIG(u_, index_)  \
    149     (&(BFD_INFO((u_))->endpoints[(index_)]))
    150 
    151 /*
    152  * Utility macros
    153  */
    154 /* True if BFD module has been initialized */
    155 #define BFD_INIT(u_)                                        \
    156     ((BFD_INFO(u_) != NULL) && (BFD_INFO(u_)->initialized))
    157 
    158 /* Checks for 'null' argument */
    159 #define PARAM_NULL_CHECK(arg_)  \
    160     if ((arg_) == NULL) {       \
    161         return BCM_E_PARAM;     \
    162     }
    163 
    164 /* Checks that required feature(s) is available */
    165 #define FEATURE_CHECK(u_)                        \
    166     if (!((soc_feature((u_), soc_feature_cmicm)) || \
    167           (soc_feature((u_), soc_feature_cmicx)))) { \
    168         return BCM_E_UNAVAIL;                    \
    169     } 
    170 
    171 /* Checks that BFD module has been initialized */
    172 #define BFD_INIT_CHECK(u_)                                          \
    173     if ((BFD_INFO(u_) == NULL) || (!BFD_INFO(u_)->initialized)) {   \
    174         return BCM_E_INIT;                  \
    175     }
    176 
    177 /* Checks that required feature(s) is available and BFD has been initialized */
    178 #define BFD_FEATURE_INIT_CHECK(u_)              \
    179     do {                                        \
    180         FEATURE_CHECK(u_);                      \
    181         BFD_INIT_CHECK(u_);                     \
    182     } while (0)
    183 
    184 
    185 /* Checks that endpoint index is within valid range */
    186 #define ENDPOINT_INDEX_CHECK(u_, index_)                                \
    187     if ((index_) < 0 || (index_) >= BFD_INFO(u_)->endpoint_count) {     \
    188         return BCM_E_PARAM;                                             \
    189     }
    190 
    191 /* Checks that SHA1 Authentication index is valid */
    192 #define AUTH_SHA1_INDEX_CHECK(u_, index_)                               \
    193     if ((index_) >= BFD_INFO(u_)->num_auth_sha1_keys) {                 \
    194         return BCM_E_PARAM;                                             \
    195     }
    196 
    197 /* Checks that Simple Password Authentication index is valid */
    198 #define AUTH_SP_INDEX_CHECK(u_, index_)                                 \
    199     if ((index_) >= BFD_INFO(u_)->num_auth_sp_keys) {                   \
    200         return BCM_E_PARAM;                                             \
    201     }
    202 
    203 #undef BFD_DEBUG_DUMP
    204 
    205 #ifdef BCM_WARM_BOOT_SUPPORT
    206 
    207 /* BFD WB Downgrade is supported till 6.5.7 only */
    208 
    209 static uint32 _bfd_sdk_warmboot_version [][2] = {
    210     {((6 << 16) | (5 << 8) | 7 ), BCM_BFD_WB_VERSION_1_2} ,
    211     {((6 << 16) | (5 << 8) | 8 ), BCM_BFD_WB_VERSION_1_4} ,
    212     {((6 << 16) | (5 << 8) | 9 ), BCM_BFD_WB_VERSION_1_4} ,
    213     {((6 << 16) | (5 << 8) | 10 ), BCM_BFD_WB_VERSION_1_5},
    214     {((6 << 16) | (5 << 8) | 11 ), BCM_BFD_WB_VERSION_1_5},
    215     {((6 << 16) | (5 << 8) | 12 ), BCM_BFD_WB_VERSION_1_5},
    216     {((6 << 16) | (5 << 8) | 13 ), BCM_BFD_WB_VERSION_1_5}
    217 };
    218 
    219 STATIC int
    220 bcmi_xgs5_bfd_scache_alloc(int unit);
    221 
    222 STATIC int
    223 bcmi_xgs5_bfd_reinit(int unit);
    224 
    225 STATIC int
    226 bcmi_xgs5_bfd_mpls_is_l3_vpn_get(int unit,
    227                                  bfd_endpoint_config_t *endpoint_config);
    228 #endif
    229 
    230 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
    231 
    232 /*
    233  * BFD HW Definition Table
    234  */
    235 static bcm_xgs5_bfd_hw_defs_t  *bcm_xgs5_bfd_hw_defs[BCM_MAX_NUM_UNITS] = {0};
    236 
    237 #define BFD_HW(u_)                (bcm_xgs5_bfd_hw_defs[(u_)])
    238 #define BFD_HW_CALL(u_)           (bcm_xgs5_bfd_hw_defs[(u_)]->hw_call)
    239 #define BFD_HW_L2(u_)             (bcm_xgs5_bfd_hw_defs[(u_)]->l2)
    240 #define BFD_HW_L3_IPV4(u_)        (bcm_xgs5_bfd_hw_defs[(u_)]->l3_ipv4)
    241 #define BFD_HW_L3_IPV6(u_)        (bcm_xgs5_bfd_hw_defs[(u_)]->l3_ipv6)
    242 #define BFD_HW_L3_TUNNEL(u_)      (bcm_xgs5_bfd_hw_defs[(u_)]->l3_tunnel)
    243 #define BFD_HW_MPLS(u_)           (bcm_xgs5_bfd_hw_defs[(u_)]->mpls)
    244 #define BFD_HW_L3_TUNNEL_IPV6(u_) (bcm_xgs5_bfd_hw_defs[(u_)]->l3_tunnel_ipv6)
    245 
    246 #define BFD_HW_L2_MEM(u_)         (BFD_HW_L2((u_))->mem)
    247 #define BFD_HW_L3_IPV4_MEM(u_)    (BFD_HW_L3_IPV4((u_))->mem)
    248 #define BFD_HW_L3_IPV6_MEM(u_)    (BFD_HW_L3_IPV6((u_))->mem)
    249 #define BFD_HW_L3_TUNNEL_MEM(u_)  (BFD_HW_L3_TUNNEL((u_))->mem)
    250 #define BFD_HW_MPLS_MEM(u_)       (BFD_HW_MPLS((u_))->mem)
    251 #define BFD_HW_L3_TUNNEL_IPV6_MEM(u_)       (BFD_HW_L3_TUNNEL_IPV6((u_))->mem)
    252 
    253 
    254 #define _BFD_TO_BCM_TUNNEL_TYPE(bfd_tunnel_type,tunnel_type)    \
    255 do {                                                            \
    256     if (bfd_tunnel_type == bcmBFDTunnelTypeIp4in4) {            \
    257         tunnel_type = bcmTunnelTypeIp4In4;                      \
    258     } else if (bfd_tunnel_type == bcmBFDTunnelTypeIp6in4) {     \
    259         tunnel_type = bcmTunnelTypeIp6In4;                      \
    260     } else if (bfd_tunnel_type == bcmBFDTunnelTypeIp4in6) {     \
    261         tunnel_type = bcmTunnelTypeIp4In6;                      \
    262     } else if (bfd_tunnel_type == bcmBFDTunnelTypeIp6in6) {     \
    263         tunnel_type = bcmTunnelTypeIp6In6;                      \
    264     } else if (bfd_tunnel_type == bcmBFDTunnelTypeGre4In4) {    \
    265         tunnel_type = bcmTunnelTypeGre4In4;                     \
    266     } else if (bfd_tunnel_type == bcmBFDTunnelTypeGre6In4) {    \
    267         tunnel_type = bcmTunnelTypeGre6In4;                     \
    268     } else if (bfd_tunnel_type == bcmBFDTunnelTypeGre4In6) {    \
    269         tunnel_type = bcmTunnelTypeGre4In6;                     \
    270     } else if (bfd_tunnel_type == bcmBFDTunnelTypeGre6In6) {    \
    271         tunnel_type = bcmTunnelTypeGre6In6;                     \
    272     }                                                           \
    273     else {                                                      \
    274         return BCM_E_PARAM;                                     \
    275     }                                                           \
    276 } while(0)
    277 
    278 
    279 #define BFD_COSQ_INVALID        0xffff
    280 
    281 #define MPLS_ACTION_POP_L3_IIF   2
    282 
    283 /*
    284  * Maximum number of BFD endpoints
    285  * Endpoint IDs valid range is  [0..2046]
    286  * Entry 0x7FF (2047) is reserved for unknown remote discriminator
    287  */
    288 #define BFD_MAX_NUM_ENDPOINTS             2047
    289 
    290 /* Timeout for Host <--> uC message */
    291 #define BFD_UC_MSG_TIMEOUT_USECS              5000000 /* 5 secs */
    292 #define BFD_UC_MSG_TIMEOUT_USECS_QUICKTURN  300000000 /* 5 mins */
    293 
    294 static sal_usecs_t bfd_uc_msg_timeout_usecs = BFD_UC_MSG_TIMEOUT_USECS;
    295 
    296 
    297 /*
    298  * BFD Encapsulation Format Header flags
    299  *
    300  * Indicates the type of headers/labels present in a BFD packet.
    301  */
    302 #define BFD_ENCAP_PKT_MPLS                    (1 << 0) 
    303 #define BFD_ENCAP_PKT_MPLS_ROUTER_ALERT       (1 << 1) 
    304 #define BFD_ENCAP_PKT_PW                      (1 << 2) 
    305 #define BFD_ENCAP_PKT_GAL                     (1 << 3) 
    306 #define BFD_ENCAP_PKT_G_ACH                   (1 << 4) 
    307 #define BFD_ENCAP_PKT_GRE                     (1 << 5) 
    308 #define BFD_ENCAP_PKT_INNER_IP                (1 << 6)
    309 #define BFD_ENCAP_PKT_IP                      (1 << 7) 
    310 #define BFD_ENCAP_PKT_UDP                     (1 << 8) 
    311 #define BFD_ENCAP_PKT_BFD                     (1 << 9)
    312 #define BFD_ENCAP_PKT_HG                      (1 << 10)
    313 #define BFD_ENCAP_PKT_HG2                     (1 << 11)
    314 
    315 #define BFD_ENCAP_PKT_UDP__MULTI_HOP          (1 << 16) 
    316 #define BFD_ENCAP_PKT_INNER_IP__V6            (1 << 17)
    317 #define BFD_ENCAP_PKT_IP__V6                  (1 << 18) 
    318 #define BFD_ENCAP_PKT_G_ACH__IP               (1 << 19)
    319 #define BFD_ENCAP_PKT_G_ACH__CC               (1 << 20)
    320 #define BFD_ENCAP_PKT_G_ACH__CC_CV            (1 << 21)
    321 #define BFD_ENCAP_PKT_UDP_MICRO_BFD           (1 << 22)
    322 
    323 /*
    324  * BFD Encapsulation Definitions
    325  *
    326  * Defines for building the BFD packet encapsulation
    327  */
    328 
    329 /*
    330  * Macros to pack uint8, uint16, uint32 in Network byte order
    331  */
    332 #define BFD_ENCAP_PACK_U8(buf_, var_)   SHR_BFD_ENCAP_PACK_U8(buf_, var_)
    333 #define BFD_ENCAP_PACK_U16(buf_, var_)  SHR_BFD_ENCAP_PACK_U16(buf_, var_)
    334 #define BFD_ENCAP_PACK_U32(buf_, var_)  SHR_BFD_ENCAP_PACK_U32(buf_, var_)
    335 
    336 #define BFD_MAC_ADDR_LENGTH    (sizeof(bcm_mac_t))
    337 
    338 #define BFD_MPLS_MAX_LABELS    3   /* Max MPLS labels */
    339 
    340 #define BFD_DEFAULT_DETECT_MULTIPLIER   10 /* BFD Default Detection Time multiplier */    
    341 
    342 /* Size of the debug log buffer */
    343 #define BFD_TRACE_LOG_MAX_SIZE 1024 /* 2KB */
    344 
    345 /* UDP Header */
    346 typedef struct bfd_udp_header_s {  /* <num bits>: ... */
    347     uint16  src;         /* 16: Source Port Number */
    348     uint16  dst;         /* 16: Destination Port Number */
    349     uint16  length;      /* 16: Length */
    350     uint16  sum;         /* 16: Checksum */
    351 } bfd_udp_header_t;
    352 
    353 /* IPv4 Header */
    354 typedef struct bfd_ipv4_header_s {
    355     uint8   version;     /*  4: Version */
    356     uint8   h_length;    /*  4: Header length */
    357     uint8   dscp;        /*  6: Differentiated Services Code Point */
    358     uint8   ecn;         /*  2: Explicit Congestion Notification */
    359     uint16  length;      /* 16: Total Length bytes (header + data) */
    360     uint16  id;          /* 16: Identification */
    361     uint8   flags;       /*  3: Flags */
    362     uint16  f_offset;    /* 13: Fragment Offset */
    363     uint8   ttl;         /*  8: Time to Live */
    364     uint8   protocol;    /*  8: Protocol */
    365     uint16  sum;         /* 16: Header Checksum */
    366     uint32  src;         /* 32: Source IP Address */
    367     uint32  dst;         /* 32: Destination IP Address */
    368 } bfd_ipv4_header_t;
    369 
    370 /* IPv6 Header */
    371 typedef struct bfd_ipv6_header_s {
    372     uint8      version;        /*   4: Version */
    373     uint8      t_class;        /*   8: Traffic Class (6:dscp, 2:ecn) */
    374     uint32     f_label;        /*  20: Flow Label */
    375     uint16     p_length;       /*  16: Payload Length */
    376     uint8      next_header;    /*   8: Next Header */
    377     uint8      hop_limit;      /*   8: Hop Limit */
    378     bcm_ip6_t  src;            /* 128: Source IP Address */
    379     bcm_ip6_t  dst;            /* 128: Destination IP Address */
    380 } bfd_ipv6_header_t;
    381 
    382 /* GRE - Generic Routing Encapsulation */
    383 typedef struct bfd_gre_header_s {
    384     uint8   checksum;           /*  1: Checksum present */
    385     uint8   routing;            /*  1: Routing present */
    386     uint8   key;                /*  1: Key present */
    387     uint8   sequence_num;       /*  1: Sequence number present */
    388     uint8   strict_src_route;   /*  1: Strict Source Routing */
    389     uint8   recursion_control;  /*  3: Recursion Control */
    390     uint8   flags;              /*  5: Flags */
    391     uint8   version;            /*  3: Version */
    392     uint16  protocol;           /* 16: Protocol Type */
    393 } bfd_gre_header_t;
    394 
    395 /* ACH - Associated Channel Header */
    396 typedef struct bfd_ach_header_s {
    397     uint8   f_nibble;        /*  4: First nibble, must be 1 */
    398     uint8   version;         /*  4: Version */
    399     uint8   reserved;        /*  8: Reserved */
    400     uint16  channel_type;    /* 16: Channel Type */
    401 } bfd_ach_header_t;
    402 
    403 /* MPLS - Multiprotocol Label Switching Label */
    404 typedef struct bfd_mpls_label_s {
    405     uint32  label;    /* 20: Label */
    406     uint8   exp;      /*  3: Experimental, Traffic Class, ECN */
    407     uint8   s;        /*  1: Bottom of Stack */
    408     uint8   ttl;      /*  8: Time to Live */
    409 } bfd_mpls_label_t;
    410 
    411 /* VLAN Tag - 802.1Q */
    412 typedef struct bfd_vlan_tag_s {
    413     uint16      tpid;    /* 16: Tag Protocol Identifier */
    414     struct {
    415         uint8   prio;    /*  3: Priority Code Point */
    416         uint8   cfi;     /*  1: Canonical Format Indicator */
    417         uint16  vid;     /* 12: Vlan Identifier */
    418     } tci;               /* Tag Control Identifier */
    419 } bfd_vlan_tag_t;
    420 
    421 /* L2 Header */
    422 typedef struct bfd_l2_header_t {
    423     bcm_mac_t       dst_mac;      /* 48: Destination MAC */
    424     bcm_mac_t       src_mac;      /* 48: Source MAC */
    425     bfd_vlan_tag_t  outer_vlan_tag;    /* VLAN Tag */
    426     bfd_vlan_tag_t  inner_vlan_tag;    /* inner VLAN Tag */
    427     uint16          etype;        /* 16: Ether Type */
    428 } bfd_l2_header_t;
    429 
    430 
    431 /*
    432  * UDP Definitions for BFD
    433  */
    434 #define BFD_UDP_SRCPORT_MIN                49152
    435 #define BFD_UDP_SRCPORT_MAX                65535
    436 #define ENCAP_UDP_SRCPORT_VALIDATE(a_)                                  \
    437     if (((a_) < BFD_UDP_SRCPORT_MIN) || ((a_) > BFD_UDP_SRCPORT_MAX)) { \
    438         return BCM_E_PARAM;                                             \
    439     }
    440 
    441 /*
    442  * IPV4
    443  *
    444  * Loopback    127.0.0.0/8         127.0.0.0   - 127.255.255.255
    445  *
    446  * Reserved
    447  *   Class A   10.0.0.0/8          10.0.0.0    - 10.255.255.255
    448  *   Class B   172.16.0.0/12       172.16.0.0  - 172.31.255.255
    449  *   Class C   192.168.0.0/16      192.168.0.0 - 192.168.255.255  
    450  *   Class E   240.0.0.0
    451  */
    452 #define IPV4_LOOPBACK(a_)    (127 == (((a_) >> 24) & 0xff))
    453 
    454 #define IPV4_RESERVED_CLASS_A(a_)  ((((a_) >> 24) & 0xff) == 10)
    455 #define IPV4_RESERVED_CLASS_B(a_)  (((((a_) >> 24) & 0xff) == 172) &&   \
    456                                     ((((a_) >> 16) & 0xf0) == 16))
    457 #define IPV4_RESERVED_CLASS_C(a_)  (((((a_) >> 24) & 0xff) == 192) &&   \
    458                                     ((((a_) >> 16) & 0xff) == 168))
    459 #define IPV4_RESERVED_CLASS_E(a_)  ((((a_) >> 24) & 0xff) == 240)
    460 
    461 #define IPV4_RESERVED(a_)                                               \
    462     (IPV4_RESERVED_CLASS_A(a_) || IPV4_RESERVED_CLASS_B(a_) ||          \
    463      IPV4_RESERVED_CLASS_C(a_) || IPV4_RESERVED_CLASS_E(a_))
    464 
    465 #define ENCAP_IPV4_LOOPBACK_VALIDATE(a_)            \
    466     if (!IPV4_LOOPBACK(a_)) { return BCM_E_PARAM; }
    467 
    468 #define ENCAP_IPV4_ROUTABLE_VALIDATE(a_)            \
    469     if (IPV4_RESERVED(a_)) { return BCM_E_PARAM; } 
    470 
    471 /*
    472  * IPV6
    473  * Loopback    0:0:0:0:0:FFFF:127/104
    474  *
    475  * Reserved
    476  *    fc00::/7
    477  */
    478 #define IPV6_LOOPBACK(a_)                                                    \
    479     (((a_)[0] == 0) && ((a_)[1] == 0) && ((a_)[2] == 0) && ((a_)[3] == 0) && \
    480      ((a_)[4] == 0) && ((a_)[5] == 0) && ((a_)[6] == 0) && ((a_)[7] == 0) && \
    481      ((a_)[8] == 0) && ((a_)[9] == 0) &&                                     \
    482      ((a_)[10] == 0xff) && ((a_)[11] == 0xff) && ((a_)[12] == 127))
    483      
    484 #define ENCAP_IPV6_LOOPBACK_VALIDATE(a_)            \
    485     if (!IPV6_LOOPBACK(a_)) { return BCM_E_PARAM; }
    486 
    487 #define MICRO_BFD_DST_MAC(a_)   \
    488     (((a_)[0] == 0x01) && ((a_)[1] == 0x00) && ((a_)[2] == 0x5E) && \
    489     ((a_)[3] == 0x90) && ((a_)[4] == 0x00) && ((a_)[5] == 0x01))
    490 
    491 
    492 /*
    493  * Function:
    494  *      bcmi_xgs5_bfd_alloc_clear
    495  * Purpose:
    496  *      Allocate memory block and set memory content to zeros.
    497  * Parameters:
    498  *      size        - (IN) Size of memory to allocate.
    499  *      description - (IN) Description of memory block.
    500  * Returns:
    501  *      Pointer to memory block.
    502  */
    503 STATIC void *
    504 bcmi_xgs5_bfd_alloc_clear(unsigned int size, char *description)
    505 {
    506     void *block = NULL;
    507 
    508     if (size) {
    509         block = sal_alloc(size, description);
    510         if (block != NULL) {
    511             sal_memset(block, 0, size);
    512         }
    513     }
    514 
    515     return block;
    516 }
    517 
    518 /*
    519  * Function:
    520  *      bcmi_xgs5_bfd_free_resource
    521  * Purpose:
    522  *      Free memory resources allocated for given unit.
    523  * Parameters:
    524  *      unit       - (IN) Unit number.
    525  * Returns:
    526  *      None
    527  */
    528 STATIC void
    529 bcmi_xgs5_bfd_free_resource(int unit)
    530 {
    531     bfd_info_t *bfd_info = BFD_INFO(unit);;
    532 
    533     if (bcm_xgs5_bfd_info[unit] != NULL) {
    534 
    535         if (bfd_info->dma_buffer != NULL) {
    536             soc_cm_sfree(unit, bfd_info->dma_buffer);
    537         }
    538 
    539         if (bfd_info->auth_sp != NULL) {
    540             sal_free(bfd_info->auth_sp);
    541         }
    542 
    543         if (bfd_info->auth_sha1 != NULL) {
    544             sal_free(bfd_info->auth_sha1);
    545         }
    546 
    547         if (bfd_info->endpoints_in_use != NULL) {
    548             sal_free(bfd_info->endpoints_in_use);
    549         }
    550 
    551         if (bfd_info->endpoints != NULL) {
    552             sal_free(bfd_info->endpoints);
    553         }
    554 
    555         sal_free(bcm_xgs5_bfd_info[unit]);
    556         bcm_xgs5_bfd_info[unit] = NULL;
    557     }
    558 
    559     return;
    560 }
    561 
    562 STATIC int
    563 bcmi_xgs5_bfd_alloc_resource(int unit, int num_sessions,
    564                              int num_auth_sha1_keys, int num_auth_sp_keys)
    565 {
    566     bfd_info_t *bfd_info;
    567 
    568     if (bcm_xgs5_bfd_info[unit] != NULL) {
    569         bcmi_xgs5_bfd_free_resource(unit);
    570     }
    571 
    572     /* Allocate memory for BFD Information Data Structure */
    573     if ((bcm_xgs5_bfd_info[unit] =
    574          bcmi_xgs5_bfd_alloc_clear(sizeof(bfd_info_t),
    575                                    "BFD info")) == NULL) {
    576         return BCM_E_MEMORY;
    577     }
    578 
    579     bfd_info = BFD_INFO(unit);
    580     if ((bfd_info->endpoints =
    581          bcmi_xgs5_bfd_alloc_clear(num_sessions *
    582                                    sizeof(bfd_endpoint_config_t),
    583                                    "BFD endpoints")) == NULL) {
    584         return BCM_E_MEMORY;
    585     }
    586 
    587     if ((bfd_info->endpoints_in_use =
    588          bcmi_xgs5_bfd_alloc_clear(SHR_BITALLOCSIZE(num_sessions),
    589                                    "BFD endpoints in use")) == NULL) {
    590         return BCM_E_MEMORY;
    591     }
    592 
    593     /* Allocate memory for BFD Authentications */
    594     if (num_auth_sha1_keys > 0) {
    595         if ((bfd_info->auth_sha1 =
    596              bcmi_xgs5_bfd_alloc_clear(num_auth_sha1_keys *
    597                                        sizeof(bcm_bfd_auth_sha1_t),
    598                                        "BFD auth sha1")) == NULL) {
    599             return BCM_E_MEMORY;
    600         }
    601     }
    602     if (num_auth_sp_keys > 0) {
    603         if ((bfd_info->auth_sp =
    604              bcmi_xgs5_bfd_alloc_clear(num_auth_sp_keys *
    605                                        sizeof(bcm_bfd_auth_simple_password_t),
    606                                        "BFD auth simple password")) == NULL) {
    607             return BCM_E_MEMORY;
    608         }
    609     }
    610 
    611     /*
    612      * Allocate DMA buffer
    613      *
    614      * DMA buffer will be used to send and receive 'long' messages
    615      * between SDK Host and uController (BTE).
    616      */
    617     bfd_info->dma_buffer_len = sizeof(bfd_sdk_msg_ctrl_t);
    618     bfd_info->dma_buffer = soc_cm_salloc(unit, bfd_info->dma_buffer_len,
    619                                          "BFD DMA buffer");
    620     if (!bfd_info->dma_buffer) {
    621         return BCM_E_MEMORY;
    622     }
    623     sal_memset(bfd_info->dma_buffer, 0, bfd_info->dma_buffer_len);
    624 
    625     return BCM_E_NONE;
    626 }
    627 
    628 /*
    629  * Function:
    630  *      bcmi_xgs5_bfd_event_unregister_all
    631  * Purpose:
    632  *      Free all event handlers.
    633  * Parameters:
    634  *      bfd_info - (IN/OUT) Pointer to BFD info structure.
    635  * Returns:
    636  *      None
    637  */
    638 STATIC void
    639 bcmi_xgs5_bfd_event_unregister_all(int unit)
    640 {
    641     bfd_info_t *bfd_info = BFD_INFO(unit);
    642     bfd_event_handler_t *event_handler;
    643     bfd_event_handler_t *event_handler_to_delete;
    644 
    645     event_handler = bfd_info->event_handler_list;
    646 
    647     while (event_handler != NULL) {
    648         event_handler_to_delete = event_handler;
    649         event_handler = event_handler->next;
    650 
    651         sal_free(event_handler_to_delete);
    652     }
    653 
    654     bfd_info->event_handler_list = NULL;
    655 }
    656 
    657 /*
    658  * Function:
    659  *      bcmi_xgs5_bfd_convert_uc_error
    660  * Purpose:
    661  *      Converts uController error code to corresponding BCM error code.
    662  * Parameters:
    663  *      uc_rv  - (IN) uController error code to convert.
    664  * Returns:
    665  *      BCM_E_XXX   - BCM error code.
    666  * Notes:
    667  */
    668 STATIC int
    669 bcmi_xgs5_bfd_convert_uc_error(uint32 uc_rv)
    670 {
    671     int rv = BCM_E_NONE;
    672 
    673     switch(uc_rv) {
    674     case SHR_BFD_UC_E_NONE:
    675         rv = BCM_E_NONE;
    676         break;
    677     case SHR_BFD_UC_E_INTERNAL:
    678         rv = BCM_E_INTERNAL;
    679         break;
    680     case SHR_BFD_UC_E_MEMORY:
    681         rv = BCM_E_MEMORY;
    682         break;
    683     case SHR_BFD_UC_E_UNIT:
    684         rv = BCM_E_UNIT;
    685         break;
    686     case SHR_BFD_UC_E_PARAM:
    687         rv = BCM_E_PARAM;
    688         break;
    689     case SHR_BFD_UC_E_EMPTY:
    690         rv = BCM_E_EMPTY;
    691         break;
    692     case SHR_BFD_UC_E_FULL:
    693         rv = BCM_E_FULL;
    694         break;
    695     case SHR_BFD_UC_E_NOT_FOUND:
    696         rv = BCM_E_NOT_FOUND;
    697         break;
    698     case SHR_BFD_UC_E_EXISTS:
    699         rv = BCM_E_EXISTS;
    700         break;
    701     case SHR_BFD_UC_E_TIMEOUT:
    702         rv = BCM_E_TIMEOUT;
    703         break;
    704     case SHR_BFD_UC_E_BUSY:
    705         rv = BCM_E_BUSY;
    706         break;
    707     case SHR_BFD_UC_E_FAIL:
    708         rv = BCM_E_FAIL;
    709         break;
    710     case SHR_BFD_UC_E_DISABLED:
    711         rv = BCM_E_DISABLED;
    712         break;
    713     case SHR_BFD_UC_E_BADID:
    714         rv = BCM_E_BADID;
    715         break;
    716     case SHR_BFD_UC_E_RESOURCE:
    717         rv = BCM_E_RESOURCE;
    718         break;
    719     case SHR_BFD_UC_E_CONFIG:
    720         rv = BCM_E_CONFIG;
    721         break;
    722     case SHR_BFD_UC_E_UNAVAIL:
    723         rv = BCM_E_UNAVAIL;
    724         break;
    725     case SHR_BFD_UC_E_INIT:
    726         rv = BCM_E_INIT;
    727         break;
    728     case SHR_BFD_UC_E_PORT:
    729         rv = BCM_E_PORT;
    730         break;
    731     default:
    732         rv = BCM_E_INTERNAL;
    733         break;
    734     }
    735 
    736     return rv;
    737 }
    738 
    739 /*
    740  * Function:
    741  *      bcmi_xgs5_bfd_msg_send_receive
    742  * Purpose:
    743  *      Sends given BFD control message to the uController.
    744  *      Receives and verifies expected reply.
    745  *      Performs DMA operation if required.
    746  * Parameters:
    747  *      unit        - (IN) Unit number.
    748  *      s_subclass  - (IN) BFD message subclass.
    749  *      s_len       - (IN) Value for 'len' field in message struct.
    750  *                         Length of buffer to flush if DMA send is required.
    751  *      s_data      - (IN) Value for 'data' field in message struct.
    752  *                         Ignored if message requires a DMA send/receive
    753  *                         operation.
    754  *      r_subclass  - (IN) Expected reply message subclass.
    755  *      r_len       - (OUT) Returns value in 'len' reply message field.
    756  * Returns:
    757  *      BCM_E_XXX
    758  * Notes:
    759  *     - The uc_msg 'len' and 'data' fields of mos_msg_data_t
    760  *       can take any arbitrary data.
    761  *
    762  *     BFD Long Control message:
    763  *     - BFD control messages that require send/receive of information
    764  *       that cannot fit in the uc_msg 'len' and 'data' fields need to
    765  *       use DMA operations to exchange information (long control message).
    766  *
    767  *     - BFD convention for long control messages for
    768  *        'mos_msg_data_t' fields:
    769  *          'len'    size of the DMA buffer to send to uController
    770  *          'data'   physical DMA memory address to send or receive
    771  *
    772  *      DMA Operations:
    773  *      - DMA read/write operation is performed when a long BFD control
    774  *        message is involved.
    775  *
    776  *      - Messages that require DMA operation (long control message)
    777  *        is indicated by MOS_MSG_DMA_MSG().
    778  *
    779  *      - Callers must 'pack' and 'unpack' corresponding information
    780  *        into/from DMA buffer indicated by BFD_INFO(unit)->dma_buffer.
    781  */
    782 STATIC int
    783 bcmi_xgs5_bfd_msg_send_receive(int unit, uint8 s_subclass,
    784                                uint16 s_len, uint32 s_data,
    785                                uint8 r_subclass, uint16 *r_len,
    786                                sal_usecs_t timeout)
    787 {
    788     int rv;
    789     bfd_info_t *bfd_info = BFD_INFO(unit);
    790     mos_msg_data_t send, reply;
    791     uint8 *dma_buffer;
    792     int dma_buffer_len;
    793     uint32 uc_rv;
    794 
    795     sal_memset(&send, 0, sizeof(send));
    796     sal_memset(&reply, 0, sizeof(reply));
    797     send.s.mclass = MOS_MSG_CLASS_BFD;
    798     send.s.subclass = s_subclass;
    799     send.s.len = bcm_htons(s_len);
    800 
    801     /*
    802      * Set 'data' to DMA buffer address if a DMA operation is
    803      * required for send or receive.
    804      */
    805     dma_buffer = bfd_info->dma_buffer;
    806     dma_buffer_len = bfd_info->dma_buffer_len;
    807     if (MOS_MSG_DMA_MSG(s_subclass) ||
    808         MOS_MSG_DMA_MSG(r_subclass)) {
    809         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
    810     } else {
    811         send.s.data = bcm_htonl(s_data);
    812     }
    813 
    814     /* Flush DMA memory */
    815     if (MOS_MSG_DMA_MSG(s_subclass)) {
    816         soc_cm_sflush(unit, dma_buffer, s_len);
    817     }
    818 
    819     /* Invalidate DMA memory to read */
    820     if (MOS_MSG_DMA_MSG(r_subclass)) {
    821         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
    822     }
    823 
    824     rv = soc_cmic_uc_msg_send_receive(unit, bfd_info->uc_num,
    825                                       &send, &reply,
    826                                       timeout);
    827 
    828     if (rv != SOC_E_NONE){
    829         return BCM_E_INTERNAL;
    830     }
    831 
    832     /* Convert BFD uController error code to BCM */
    833     uc_rv  = bcm_ntohl(reply.s.data);
    834     rv     = bcmi_xgs5_bfd_convert_uc_error(uc_rv);
    835 
    836     *r_len = bcm_ntohs(reply.s.len);
    837 
    838     /*Check reply class and subclass*/
    839     if((rv == SOC_E_NONE) && ((reply.s.mclass != MOS_MSG_CLASS_BFD) ||
    840         (reply.s.subclass != r_subclass)))
    841     {
    842         return BCM_E_INTERNAL;
    843     }
    844     return rv;
    845 }
    846 
    847 /*
    848  * Function:
    849  *      bcmi_xgs5_bfd_msg_status_receive
    850  * Purpose:
    851  *      Sends given BFD control message to the uController.
    852  *      Receives and verifies expected reply.
    853  *      Performs DMA operation if required.
    854  * Parameters:
    855  *      unit        - (IN) Unit number.
    856  *      s_subclass  - (IN) BFD message subclass.
    857  *      s_len       - (IN) Value for 'len' field in message struct.
    858  *                         Length of buffer to flush if DMA send is required.
    859  *      s_data      - (IN) Value for 'data' field in message struct.
    860  *                         Ignored if message requires a DMA send/receive
    861  *                         operation.
    862  *      r_subclass  - (IN) Expected reply message subclass.
    863  *      r_len       - (OUT) Returns value in 'len' reply message field.
    864  *      dma_buffer  - (OUT) Returns data from uC
    865  *      dma_buffer_len - (IN) buffer length
    866  * Returns:
    867  *      BCM_E_XXX
    868  */
    869 STATIC int
    870 bcmi_xgs5_bfd_msg_status_receive(int unit, uint8 s_subclass,
    871                                  uint16 s_len, uint32 s_data,
    872                                  uint8 r_subclass, uint16 *r_len,
    873                                  sal_usecs_t timeout, uint8 *dma_buffer,
    874                                  int dma_buffer_len)
    875 {
    876     int rv;
    877     bfd_info_t *bfd_info = BFD_INFO(unit);
    878     mos_msg_data_t send, reply;
    879     uint32 uc_rv;
    880 
    881     sal_memset(&send, 0, sizeof(send));
    882     sal_memset(&reply, 0, sizeof(reply));
    883     send.s.mclass = MOS_MSG_CLASS_BFD;
    884     send.s.subclass = s_subclass;
    885     send.s.len = bcm_htons(s_len);
    886 
    887     /*
    888      * Set 'data' to DMA buffer address if a DMA operation is
    889      * required for send or receive.
    890      */
    891     if (MOS_MSG_DMA_MSG(s_subclass) ||
    892         MOS_MSG_DMA_MSG(r_subclass)) {
    893         send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer));
    894     } else {
    895         send.s.data = bcm_htonl(s_data);
    896     }
    897 
    898     /* Flush DMA memory */
    899     if (MOS_MSG_DMA_MSG(s_subclass)) {
    900         soc_cm_sflush(unit, dma_buffer, s_len);
    901     }
    902 
    903     /* Invalidate DMA memory to read */
    904     if (MOS_MSG_DMA_MSG(r_subclass)) {
    905         soc_cm_sinval(unit, dma_buffer, dma_buffer_len);
    906     }
    907 
    908     rv = soc_cmic_uc_msg_send_receive(unit, bfd_info->uc_num,
    909                                       &send, &reply,
    910                                       timeout);
    911 
    912     if (rv != SOC_E_NONE){
    913         return BCM_E_INTERNAL;
    914     }
    915 
    916     /* Convert BFD uController error code to BCM */
    917     uc_rv  = bcm_ntohl(reply.s.data);
    918     rv     = bcmi_xgs5_bfd_convert_uc_error(uc_rv);
    919 
    920     *r_len = bcm_ntohs(reply.s.len);
    921 
    922     /*Check reply class and subclass*/
    923     if((rv == SOC_E_NONE) && ((reply.s.mclass != MOS_MSG_CLASS_BFD) ||
    924         (reply.s.subclass != r_subclass)))
    925     {
    926         return BCM_E_INTERNAL;
    927     }
    928     return rv;
    929 }
    930 
    931 /*
    932  * Function:
    933  *      bcmi_xgs5_bfd_event_mask_set
    934  * Purpose:
    935  *      Set the BFD Events mask.
    936  *      Events are set per BFD module.
    937  * Parameters:
    938  *      unit        - (IN) Unit number.
    939  * Returns:
    940  *      BCM_E_NONE Operation completed successfully
    941  *      BCM_E_XXX  Operation failed
    942  * Notes:
    943  */
    944 STATIC int
    945 bcmi_xgs5_bfd_event_mask_set(int unit)
    946 {
    947     bfd_info_t *bfd_info = BFD_INFO(unit);
    948     bfd_event_handler_t *event_handler;
    949     uint32 event_mask = 0;
    950     uint16 reply_len;
    951 
    952     /* Get event mask from all callbacks */
    953     for (event_handler = bfd_info->event_handler_list;
    954          event_handler != NULL;
    955          event_handler = event_handler->next) {
    956 
    957         if (SHR_BITGET(event_handler->event_types.w,
    958                        bcmBFDEventStateChange)) {
    959             event_mask |= BFD_BTE_EVENT_STATE;
    960         }
    961         if (SHR_BITGET(event_handler->event_types.w,
    962                        bcmBFDEventRemoteStateDiag)) {
    963             event_mask |= BFD_BTE_EVENT_REMOTE_STATE_DIAG;
    964         }
    965         if (SHR_BITGET(event_handler->event_types.w,
    966                        bcmBFDEventSessionDiscriminatorChange)) {
    967             event_mask |= BFD_BTE_EVENT_DISCRIMINATOR;
    968         }
    969         if (SHR_BITGET(event_handler->event_types.w,
    970                        bcmBFDEventAuthenticationChange)) {
    971             event_mask |= BFD_BTE_EVENT_AUTHENTICATION;
    972         }
    973         if (SHR_BITGET(event_handler->event_types.w,
    974                        bcmBFDEventParameterChange)) {
    975             event_mask |= BFD_BTE_EVENT_PARAMETER;
    976         }
    977         if (SHR_BITGET(event_handler->event_types.w,
    978                        bcmBFDEventSessionError)) {
    979             event_mask |= BFD_BTE_EVENT_ERROR;
    980         }
    981         if (SHR_BITGET(event_handler->event_types.w,
    982                        bcmBFDEventEndpointFlagsChange)) {
    983             event_mask |= BFD_BTE_EVENT_FLAGS_CHANGE;
    984         }
    985         if (SHR_BITGET(event_handler->event_types.w,
    986                        bcmBFDEventEndpointRemotePollBitSet)) {
    987             event_mask |= BFD_BTE_EVENT_REMOTE_POLL_BIT_SET;
    988         }
    989         if (SHR_BITGET(event_handler->event_types.w,
    990                        bcmBFDEventEndpointRemoteFinalBitSet)) {
    991             event_mask |= BFD_BTE_EVENT_REMOTE_FINAL_BIT_SET;
    992         }
    993          if (SHR_BITGET(event_handler->event_types.w,
    994                        bcmBFDEventEndpointLocalSessionStateAdminDown)) {
    995             event_mask |= BFD_BTE_EVENT_SESSION_STATE_ADMIN_DOWN;
    996         }
    997         if (SHR_BITGET(event_handler->event_types.w,
    998                        bcmBFDEventEndpointLocalSessionStateDown)) {
    999             event_mask |= BFD_BTE_EVENT_SESSION_STATE_DOWN;
   1000         }
   1001         if (SHR_BITGET(event_handler->event_types.w,
   1002                        bcmBFDEventEndpointLocalSessionStateInit)) {
   1003             event_mask |= BFD_BTE_EVENT_SESSION_STATE_INIT;
   1004         }
   1005         if (SHR_BITGET(event_handler->event_types.w,
   1006                        bcmBFDEventEndpointLocalSessionStateUp)) {
   1007             event_mask |= BFD_BTE_EVENT_SESSION_STATE_UP;
   1008         }
   1009         if (SHR_BITGET(event_handler->event_types.w,
   1010                        bcmBFDEventEndpointMisConnectivityDefect)) {
   1011             event_mask |= BFD_BTE_EVENT_SESSION_MISCONN_DEFECT;
   1012         }
   1013         if (SHR_BITGET(event_handler->event_types.w,
   1014                        bcmBFDEventEndpointMisConnectivityDefectClear)) {
   1015             event_mask |= BFD_BTE_EVENT_SESSION_MISCONN_CLEAR;
   1016         }
   1017         if (SHR_BITGET(event_handler->event_types.w,
   1018                        bcmBFDEventEndpoinUnExpectedMeg)) {
   1019             event_mask |= BFD_BTE_EVENT_UNEXPECTED_MEG;
   1020         }
   1021         if (SHR_BITGET(event_handler->event_types.w,
   1022                        bcmBFDEventEndpoinUnExpectedMegClear)) {
   1023             event_mask |= BFD_BTE_EVENT_UNEXPECTED_MEG_CLEAR;
   1024         }
   1025     }
   1026 
   1027     /* Update BFD event mask in uKernel */
   1028     if (event_mask != bfd_info->event_mask) {
   1029         /* Send BFD Event Mask message to uC */
   1030         BCM_IF_ERROR_RETURN
   1031             (bcmi_xgs5_bfd_msg_send_receive
   1032              (unit,
   1033               MOS_MSG_SUBCLASS_BFD_EVENT_MASK_SET,
   1034               0, event_mask,
   1035               MOS_MSG_SUBCLASS_BFD_EVENT_MASK_SET_REPLY,
   1036               &reply_len, bfd_uc_msg_timeout_usecs));
   1037 
   1038         if (reply_len != 0) {
   1039             return BCM_E_INTERNAL;
   1040         }
   1041     }
   1042 
   1043     bfd_info->event_mask = event_mask;
   1044 
   1045     return BCM_E_NONE;
   1046 }
   1047 
   1048 /*
   1049  * Function:
   1050  *      bcmi_xgs5_bfd_callback_thread
   1051  * Purpose:
   1052  *      Thread to listen for event messages from uController.
   1053  * Parameters:
   1054  *      param - Pointer to BFD info structure.
   1055  * Returns:
   1056  *      None
   1057  */
   1058 STATIC void
   1059 bcmi_xgs5_bfd_callback_thread(int unit)
   1060 {
   1061     int rv;
   1062     bfd_info_t *bfd_info = BFD_INFO(unit);
   1063     bfd_event_handler_t *event_handler;
   1064     bcm_bfd_event_types_t events, cb_events;
   1065     bfd_msg_event_t event_msg;
   1066     uint16 sess_id;
   1067     uint32 event_mask;
   1068     int invoke = 0;
   1069     char thread_name[SAL_THREAD_NAME_MAX_LEN];
   1070     
   1071     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1072                 (BSL_META_U(unit,
   1073                             "BFD callback thread starting\n")));
   1074     thread_name[0] = 0x0;
   1075     sal_thread_name(bfd_info->event_thread_id, thread_name, sizeof (thread_name));
   1076     while (1) {
   1077         /* Wait on notifications from uController */
   1078         rv = soc_cmic_uc_msg_receive(bfd_info->unit, bfd_info->uc_num,
   1079                                      MOS_MSG_CLASS_BFD_EVENT, &event_msg,
   1080                                      sal_sem_FOREVER);
   1081 
   1082         if (BCM_FAILURE(rv)) {
   1083             break;   /* Thread exit */
   1084         }
   1085 
   1086         /* Get data from event message */
   1087         sess_id    = bcm_ntohs(event_msg.s.len);
   1088         event_mask = bcm_ntohl(event_msg.s.data);
   1089 
   1090         /* Set events */
   1091         sal_memset(&events, 0, sizeof(events));
   1092         if (event_mask & BFD_BTE_EVENT_STATE) {
   1093             SHR_BITSET(events.w, bcmBFDEventStateChange);
   1094         }
   1095         if (event_mask & BFD_BTE_EVENT_REMOTE_STATE_DIAG) {
   1096             SHR_BITSET(events.w, bcmBFDEventRemoteStateDiag);
   1097         }
   1098         if (event_mask & BFD_BTE_EVENT_DISCRIMINATOR) {
   1099             SHR_BITSET(events.w, bcmBFDEventSessionDiscriminatorChange);
   1100         }
   1101         if (event_mask & BFD_BTE_EVENT_AUTHENTICATION) {
   1102             SHR_BITSET(events.w, bcmBFDEventAuthenticationChange);
   1103         }
   1104         if (event_mask & BFD_BTE_EVENT_PARAMETER) {
   1105             SHR_BITSET(events.w, bcmBFDEventParameterChange);
   1106         }
   1107         if (event_mask & BFD_BTE_EVENT_ERROR) {
   1108             SHR_BITSET(events.w, bcmBFDEventSessionError);
   1109         }
   1110         if (event_mask & BFD_BTE_EVENT_FLAGS_CHANGE) {
   1111             SHR_BITSET(events.w, bcmBFDEventEndpointFlagsChange);
   1112         }
   1113         if (event_mask & BFD_BTE_EVENT_REMOTE_POLL_BIT_SET) {
   1114             SHR_BITSET(events.w, bcmBFDEventEndpointRemotePollBitSet);
   1115         }
   1116         if (event_mask & BFD_BTE_EVENT_REMOTE_FINAL_BIT_SET) {
   1117             SHR_BITSET(events.w, bcmBFDEventEndpointRemoteFinalBitSet);
   1118         }
   1119         if (event_mask & BFD_BTE_EVENT_SESSION_STATE_ADMIN_DOWN) {
   1120             SHR_BITSET(events.w, bcmBFDEventEndpointLocalSessionStateAdminDown);
   1121         }
   1122         if (event_mask & BFD_BTE_EVENT_SESSION_STATE_DOWN) {
   1123             SHR_BITSET(events.w, bcmBFDEventEndpointLocalSessionStateDown);
   1124         }
   1125         if (event_mask & BFD_BTE_EVENT_SESSION_STATE_INIT) {
   1126             SHR_BITSET(events.w, bcmBFDEventEndpointLocalSessionStateInit);
   1127         }
   1128         if (event_mask & BFD_BTE_EVENT_SESSION_STATE_UP) {
   1129             SHR_BITSET(events.w, bcmBFDEventEndpointLocalSessionStateUp);
   1130         }
   1131         if (event_mask & BFD_BTE_EVENT_SESSION_MISCONN_DEFECT) {
   1132             SHR_BITSET(events.w, bcmBFDEventEndpointMisConnectivityDefect);
   1133         }
   1134         if (event_mask & BFD_BTE_EVENT_SESSION_MISCONN_CLEAR) {
   1135             SHR_BITSET(events.w, bcmBFDEventEndpointMisConnectivityDefectClear);
   1136         }
   1137         if (event_mask & BFD_BTE_EVENT_UNEXPECTED_MEG) {
   1138             SHR_BITSET(events.w, bcmBFDEventEndpoinUnExpectedMeg);
   1139         }
   1140         if (event_mask & BFD_BTE_EVENT_UNEXPECTED_MEG_CLEAR) {
   1141             SHR_BITSET(events.w, bcmBFDEventEndpoinUnExpectedMegClear);
   1142         }
   1143 
   1144         /* Loop over registered callbacks,
   1145          * If any match the events field, then invoke
   1146          */
   1147         sal_memset(&cb_events, 0, sizeof(cb_events));
   1148         for (event_handler = bfd_info->event_handler_list;
   1149              event_handler != NULL;
   1150              event_handler = event_handler->next) {
   1151             SHR_BITAND_RANGE(event_handler->event_types.w, events.w,
   1152                              0, bcmBFDEventCount, cb_events.w);
   1153             SHR_BITTEST_RANGE(cb_events.w, 0, bcmBFDEventCount, invoke);
   1154 
   1155             if (invoke) {
   1156                 
   1157                 event_handler->cb(bfd_info->unit, 0,
   1158                                   cb_events, sess_id,
   1159                                   event_handler->user_data);
   1160             }
   1161         }
   1162     }
   1163 
   1164     bfd_info->event_thread_id = NULL;
   1165     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1166                 (BSL_META_U(unit,
   1167                             "BFD callback thread stopped\n")));
   1168     sal_thread_exit(0);
   1169 }
   1170 
   1171 /*
   1172  * Function:
   1173  *      bcmi_xgs5_bfd_find_free_endpoint
   1174  * Purpose:
   1175  *      Find an available endpoint index (endpoint id).
   1176  * Parameters:
   1177  *      unit        - (IN) Unit number.
   1178  *      endpoints_in_use - Current endpoint ids usage bitmap.
   1179  *      endpoint_count   - Max number of endpoints.
   1180  * Returns:
   1181  *      Available endpoint id.
   1182  *      (-1) Indicates no more available endpoint ids.
   1183  * Notes:
   1184  */
   1185 STATIC int
   1186 bcmi_xgs5_bfd_find_free_endpoint(int unit, SHR_BITDCL *endpoints_in_use,
   1187                                  int endpoint_count)
   1188 {
   1189     int endpoint_index, endpoint_start_index = 0;
   1190     
   1191     if (SOC_IS_TRIDENT3X(unit)) {
   1192         endpoint_start_index = 1;
   1193     }
   1194 
   1195     for (endpoint_index = endpoint_start_index; endpoint_index < endpoint_count;
   1196          endpoint_index += 1) {
   1197         if (!SHR_BITGET(endpoints_in_use, endpoint_index)) {
   1198             break;
   1199         }
   1200     }
   1201 
   1202     if (endpoint_index >= endpoint_count) {
   1203         endpoint_index = -1;
   1204     }
   1205 
   1206     return endpoint_index;
   1207 }
   1208 
   1209 /*
   1210  * Function:
   1211  *      bcmi_xgs5_bfd_find_ipv4_entry
   1212  */
   1213 STATIC int
   1214 bcmi_xgs5_bfd_find_ipv4_entry(int unit, bcm_vrf_t vrf,
   1215                               bcm_ip_t ip_addr, int *index)
   1216 {
   1217     max_mem_entry_t  l3_key;
   1218     max_mem_entry_t  l3_entry;
   1219 
   1220     sal_memset(&l3_key, 0, sizeof(l3_key));
   1221 
   1222     soc_mem_field32_set(unit, BFD_HW_L3_IPV4_MEM(unit), &l3_key,
   1223                         BFD_HW_L3_IPV4(unit)->vrf_id, vrf);
   1224 
   1225     soc_mem_field32_set(unit, BFD_HW_L3_IPV4_MEM(unit), &l3_key,
   1226                         BFD_HW_L3_IPV4(unit)->ip_addr, ip_addr);
   1227 
   1228     soc_mem_field32_set(unit, BFD_HW_L3_IPV4_MEM(unit), &l3_key,
   1229                         BFD_HW_L3_IPV4(unit)->key_type,
   1230                         TR_L3_HASH_KEY_TYPE_V4UC);
   1231 
   1232     return soc_mem_search(unit, BFD_HW_L3_IPV4_MEM(unit), MEM_BLOCK_ANY,
   1233                           index, &l3_key, &l3_entry, 0);
   1234 }
   1235 
   1236 /*
   1237  * Function:
   1238  *      bcmi_xgs5_bfd_find_ipv6_entry
   1239  */
   1240 STATIC int
   1241 bcmi_xgs5_bfd_find_ipv6_entry(int unit, bcm_vrf_t vrf,
   1242                               bcm_ip6_t ip6_addr,int *index)
   1243 {
   1244     max_mem_entry_t  l3_key;
   1245     max_mem_entry_t  l3_entry;
   1246 
   1247     sal_memset(&l3_key, 0, sizeof(l3_key));
   1248 
   1249     soc_mem_ip6_addr_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1250                          BFD_HW_L3_IPV6(unit)->ip_addr_lwr_64,
   1251                          ip6_addr, SOC_MEM_IP6_LOWER_ONLY);
   1252 
   1253     soc_mem_ip6_addr_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1254                          BFD_HW_L3_IPV6(unit)->ip_addr_upr_64,
   1255                          ip6_addr, SOC_MEM_IP6_UPPER_ONLY);
   1256 
   1257 #if defined(BCM_TRIDENT3_SUPPORT)
   1258     if (SOC_IS_TRIDENT3X(unit)) {
   1259         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1260                             BFD_HW_L3_IPV6(unit)->base_valid_0, 3);
   1261 
   1262         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1263                             BFD_HW_L3_IPV6(unit)->base_valid_1, 4);
   1264         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1265                             BFD_HW_L3_IPV6(unit)->data_type,
   1266                             TD3_L3_HASH_DATA_TYPE_V6UC);
   1267         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1268                             BFD_HW_L3_IPV6(unit)->key_type,
   1269                             TD3_L3_HASH_KEY_TYPE_V6UC);
   1270     } else
   1271 #endif
   1272 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1273     if (SOC_IS_TOMAHAWK3(unit)) {
   1274         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1275                             BFD_HW_L3_IPV6(unit)->base_valid_0, 1);
   1276 
   1277         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1278                             BFD_HW_L3_IPV6(unit)->base_valid_1, 2);
   1279 
   1280         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1281                             BFD_HW_L3_IPV6(unit)->key_type,
   1282                             TH3_L3_HASH_KEY_TYPE_V6UC);
   1283     } else
   1284 #endif
   1285     {
   1286         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1287                             BFD_HW_L3_IPV6(unit)->key_type_0,
   1288                             TR_L3_HASH_KEY_TYPE_V6UC);
   1289 
   1290         soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1291                             BFD_HW_L3_IPV6(unit)->key_type_1,
   1292                             TR_L3_HASH_KEY_TYPE_V6UC);
   1293     }
   1294 
   1295     soc_mem_field32_set(unit, BFD_HW_L3_IPV6_MEM(unit), &l3_key,
   1296                         BFD_HW_L3_IPV6(unit)->vrf_id, vrf);
   1297 
   1298     return soc_mem_search(unit, BFD_HW_L3_IPV6_MEM(unit), MEM_BLOCK_ANY,
   1299                           index, &l3_key, &l3_entry, 0);
   1300 
   1301 }
   1302 
   1303 
   1304 STATIC int
   1305 bcmi_xgs5_bfd_l2_entry_set(int unit,
   1306                            int endpoint_index,
   1307                            int mpls, int mpls_label, int your_discr,
   1308                            bcm_module_t module_id, bcm_port_t port_id,
   1309                            int int_pri, int cpu_qid)
   1310 {
   1311     int local, rv;
   1312     max_mem_entry_t  l2_entry;
   1313 
   1314     if (BFD_HW_L2_MEM(unit) == INVALIDm) {
   1315         return BCM_E_UNAVAIL;
   1316     }
   1317 
   1318     if (module_id == BCM_MODID_INVALID) {
   1319         local = 1;
   1320     } else {
   1321         BCM_IF_ERROR_RETURN
   1322             (_bcm_esw_modid_is_local(unit, module_id, &local));
   1323     }
   1324 
   1325     /* Insert your discriminator field to L2_ENTRY table. */
   1326     sal_memset(&l2_entry, 0, sizeof(l2_entry));
   1327 
   1328     soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1329                         BFD_HW_L2(unit)->key_type,
   1330                         BFD_HW_L2(unit)->bfd_key_type);
   1331     soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1332                         BFD_HW_L2(unit)->valid, 1);
   1333     soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1334                         BFD_HW_L2(unit)->static_bit, 1);
   1335 
   1336     if (mpls) {
   1337         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1338                             BFD_HW_L2(unit)->session_id_type, 1);
   1339         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1340                             BFD_HW_L2(unit)->label, mpls_label);
   1341     } else {
   1342         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1343                             BFD_HW_L2(unit)->session_id_type, 0);
   1344         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1345                             BFD_HW_L2(unit)->your_discr, your_discr);
   1346     }
   1347 
   1348     if (local) {
   1349         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1350                             BFD_HW_L2(unit)->session_index,
   1351                             endpoint_index);
   1352         if (BFD_HW_L2(unit)->cpu_queue_class != INVALIDf) {
   1353             soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1354                                 BFD_HW_L2(unit)->cpu_queue_class,
   1355                                 cpu_qid);
   1356         }
   1357     } else {
   1358         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1359                             BFD_HW_L2(unit)->remote, 1);
   1360         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1361                             BFD_HW_L2(unit)->dst_module, module_id);
   1362         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1363                             BFD_HW_L2(unit)->dst_port, port_id);
   1364         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_entry,
   1365                             BFD_HW_L2(unit)->int_pri, int_pri);
   1366     }
   1367 
   1368 
   1369     rv = soc_mem_insert(unit, BFD_HW_L2_MEM(unit),MEM_BLOCK_ANY, &l2_entry);
   1370     if (rv == BCM_E_FULL) {
   1371         rv = bcm_bfd_l2_hash_dynamic_replace(unit, (void *)&l2_entry);
   1372     }
   1373 
   1374     return rv;
   1375 }
   1376 
   1377 /*
   1378  * Function:
   1379  *      bcmi_xgs5_bfd_l2_entry_clear
   1380  */
   1381 STATIC int
   1382 bcmi_xgs5_bfd_l2_entry_clear(int unit,
   1383                              int mpls, int mpls_label, int your_discr)
   1384 {
   1385     max_mem_entry_t  l2_key;
   1386     max_mem_entry_t  l2_entry;
   1387     int l2_index;
   1388 
   1389     sal_memset(&l2_key, 0, sizeof(l2_key));
   1390 
   1391     soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_key,
   1392                         BFD_HW_L2(unit)->key_type,
   1393                         BFD_HW_L2(unit)->bfd_key_type);
   1394 
   1395     if (mpls) {
   1396         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_key,
   1397                             BFD_HW_L2(unit)->session_id_type, 1);
   1398         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_key,
   1399                             BFD_HW_L2(unit)->label, mpls_label);
   1400     } else {
   1401         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_key,
   1402                             BFD_HW_L2(unit)->session_id_type, 0);
   1403         soc_mem_field32_set(unit, BFD_HW_L2_MEM(unit), &l2_key,
   1404                             BFD_HW_L2(unit)->your_discr, your_discr);
   1405     }
   1406     
   1407     SOC_IF_ERROR_RETURN
   1408         (soc_mem_search(unit, BFD_HW_L2_MEM(unit), MEM_BLOCK_ANY,
   1409                         &l2_index, &l2_key, &l2_entry, 0));
   1410 
   1411     SOC_IF_ERROR_RETURN
   1412         (soc_mem_delete_index(unit, BFD_HW_L2_MEM(unit), MEM_BLOCK_ANY,
   1413                               l2_index));
   1414 
   1415     return BCM_E_NONE;
   1416 }
   1417 
   1418 /*
   1419  * Function:
   1420  *      bcmi_xgs5_bfd_l2x_entry_set
   1421  */
   1422 STATIC int
   1423 bcmi_xgs5_bfd_l2x_entry_set(int unit,
   1424                             bfd_endpoint_config_t *endpoint_config,
   1425                             int mpls)
   1426 {
   1427     bcm_bfd_endpoint_info_t *endpoint_info;
   1428 
   1429     endpoint_info  = &endpoint_config->info;
   1430 
   1431     return(bcmi_xgs5_bfd_l2_entry_set(unit,
   1432                                       endpoint_config->endpoint_index,
   1433                                       mpls,
   1434                                       endpoint_info->label,
   1435                                       endpoint_info->local_discr,
   1436                                       endpoint_config->modid,
   1437                                       endpoint_config->port,
   1438                                       endpoint_info->int_pri, 
   1439                                       endpoint_info->cpu_qid));
   1440 }
   1441 
   1442 /*
   1443  * Function:
   1444  *      bcmi_xgs5_bfd_l3_entry_set
   1445  */
   1446 STATIC int
   1447 bcmi_xgs5_bfd_l3_entry_set(int unit,
   1448                            bcm_bfd_endpoint_info_t *endpoint_info)
   1449 {
   1450     int rv = BCM_E_NONE;
   1451     int l3_index = 0;
   1452 
   1453     /* Check whether ipv4 or ipv6 */
   1454     if (endpoint_info->flags & BCM_BFD_ENDPOINT_IPV6) {
   1455         BCM_IF_ERROR_RETURN
   1456             (bcmi_xgs5_bfd_find_ipv6_entry(unit,
   1457                                            endpoint_info->vrf_id,
   1458                                            endpoint_info->src_ip6_addr,
   1459                                            &l3_index));
   1460 
   1461         /* Set BFD_ENABLE and LOCAL_ADDRESS */
   1462         rv = soc_mem_field32_modify(unit, BFD_HW_L3_IPV6_MEM(unit), l3_index,
   1463                                     BFD_HW_L3_IPV6(unit)->local_address, 1);
   1464 #if defined(BCM_TRIDENT3_SUPPORT)
   1465         if(!(SOC_IS_TRIDENT3X(unit))) {
   1466 #endif
   1467             rv |= soc_mem_field32_modify(unit, BFD_HW_L3_IPV6_MEM(unit), l3_index,
   1468                                          BFD_HW_L3_IPV6(unit)->bfd_enable, 1);
   1469 #if defined(BCM_TRIDENT3_SUPPORT)
   1470         }
   1471 #endif
   1472     } else {
   1473         BCM_IF_ERROR_RETURN
   1474             (bcmi_xgs5_bfd_find_ipv4_entry(unit,
   1475                                            endpoint_info->vrf_id,
   1476                                            endpoint_info->src_ip_addr,
   1477                                            &l3_index));
   1478         /* Set BFD_ENABLE and LOCAL_ADDRESS */
   1479         rv = soc_mem_field32_modify(unit, BFD_HW_L3_IPV4_MEM(unit), l3_index,
   1480                                     BFD_HW_L3_IPV4(unit)->local_address, 1);
   1481 #if defined(BCM_TRIDENT3_SUPPORT)
   1482         if(!(SOC_IS_TRIDENT3X(unit))) {
   1483 #endif
   1484             rv |= soc_mem_field32_modify(unit, BFD_HW_L3_IPV4_MEM(unit), l3_index,
   1485                                          BFD_HW_L3_IPV4(unit)->bfd_enable, 1);
   1486 #if defined(BCM_TRIDENT3_SUPPORT)
   1487         }
   1488 #endif
   1489     }
   1490 
   1491     return rv;
   1492 }
   1493 
   1494 
   1495 /*
   1496  * Function:
   1497  *      bcmi_xgs5_bfd_l3_entry_status
   1498  */
   1499 STATIC int
   1500 bcmi_xgs5_bfd_l3_entry_status(int unit,
   1501                               bcm_bfd_endpoint_info_t *endpoint_info)
   1502 {
   1503     int l3_index = 0;
   1504 
   1505     /* Check whether ipv4 or ipv6 */
   1506     if (endpoint_info->flags & BCM_BFD_ENDPOINT_IPV6) {
   1507         BCM_IF_ERROR_RETURN
   1508             (bcmi_xgs5_bfd_find_ipv6_entry(unit,
   1509                                            endpoint_info->vrf_id,
   1510                                            endpoint_info->src_ip6_addr,
   1511                                            &l3_index));
   1512     } else {
   1513         BCM_IF_ERROR_RETURN
   1514             (bcmi_xgs5_bfd_find_ipv4_entry(unit,
   1515                                            endpoint_info->vrf_id,
   1516                                            endpoint_info->src_ip_addr,
   1517                                            &l3_index));
   1518     }
   1519 
   1520     return BCM_E_NONE;
   1521 }
   1522 
   1523 /*
   1524  * Function:
   1525  *      bcmi_xgs5_bfd_l3_entry_clear
   1526  */
   1527 STATIC int
   1528 bcmi_xgs5_bfd_l3_entry_clear(int unit,
   1529                              bcm_bfd_endpoint_info_t *endpoint_info)
   1530 {
   1531     int rv = BCM_E_NONE;
   1532     int l3_index = 0;
   1533 
   1534     /* Check whether ipv4 or ipv6 */
   1535     if (endpoint_info->flags & BCM_BFD_ENDPOINT_IPV6) {
   1536         BCM_IF_ERROR_RETURN
   1537             (bcmi_xgs5_bfd_find_ipv6_entry(unit,
   1538                                            endpoint_info->vrf_id,
   1539                                            endpoint_info->src_ip6_addr,
   1540                                            &l3_index));
   1541         /* Reset BFD_ENABLE and LOCAL_ADDRESS */
   1542         rv = soc_mem_field32_modify(unit, BFD_HW_L3_IPV6_MEM(unit), l3_index,
   1543                                     BFD_HW_L3_IPV6(unit)->local_address, 0);
   1544 #if defined(BCM_TRIDENT3_SUPPORT)
   1545         if(!(SOC_IS_TRIDENT3X(unit))) {
   1546 #endif
   1547             rv |= soc_mem_field32_modify(unit, BFD_HW_L3_IPV6_MEM(unit), l3_index,
   1548                                          BFD_HW_L3_IPV6(unit)->bfd_enable, 0);
   1549 #if defined(BCM_TRIDENT3_SUPPORT)
   1550         }
   1551 #endif
   1552     } else {
   1553         BCM_IF_ERROR_RETURN
   1554             (bcmi_xgs5_bfd_find_ipv4_entry(unit,
   1555                                            endpoint_info->vrf_id,
   1556                                            endpoint_info->src_ip_addr,
   1557                                            &l3_index));
   1558         /* Reset BFD_ENABLE and LOCAL_ADDRESS */
   1559         rv = soc_mem_field32_modify(unit, BFD_HW_L3_IPV4_MEM(unit), l3_index,
   1560                                     BFD_HW_L3_IPV4(unit)->local_address, 0);
   1561 #if defined(BCM_TRIDENT3_SUPPORT)
   1562         if(!(SOC_IS_TRIDENT3X(unit))) {
   1563 #endif
   1564             rv |= soc_mem_field32_modify(unit, BFD_HW_L3_IPV4_MEM(unit), l3_index,
   1565                                          BFD_HW_L3_IPV4(unit)->bfd_enable, 0);
   1566 #if defined(BCM_TRIDENT3_SUPPORT)
   1567         }
   1568 #endif
   1569     }
   1570 
   1571     return rv;
   1572 }
   1573 
   1574 /*
   1575  * Function:
   1576  *      bcmi_xgs5_bfd_find_l3_tunnel_entry
   1577  */
   1578 STATIC int
   1579 bcmi_xgs5_bfd_find_l3_tunnel_entry(int unit,
   1580                                    bcm_bfd_endpoint_info_t *endpoint_info,
   1581                                    soc_tunnel_term_t *tunnel_entry)
   1582 {
   1583     bcm_tunnel_type_t tunnel_type;
   1584     bcm_tunnel_terminator_t tunnel;
   1585     soc_tunnel_term_t key;
   1586     int index;
   1587 
   1588     /* Tunnel type */
   1589     if (endpoint_info->type == bcmBFDTunnelTypeIp4in4) {
   1590         tunnel_type = bcmTunnelTypeIp4In4;
   1591     } else if (endpoint_info->type == bcmBFDTunnelTypeIp6in4) {
   1592         tunnel_type = bcmTunnelTypeIp6In4;
   1593     } else if (endpoint_info->type == bcmBFDTunnelTypeIp4in6) {
   1594         tunnel_type = bcmTunnelTypeIp4In6;
   1595     } else if (endpoint_info->type == bcmBFDTunnelTypeIp6in6) {
   1596         tunnel_type = bcmTunnelTypeIp6In6;
   1597     } else if (endpoint_info->type == bcmBFDTunnelTypeGre4In4) {
   1598         tunnel_type = bcmTunnelTypeGre4In4;
   1599     } else if (endpoint_info->type == bcmBFDTunnelTypeGre6In4) {
   1600         tunnel_type = bcmTunnelTypeGre6In4;
   1601     } else if (endpoint_info->type == bcmBFDTunnelTypeGre4In6) {
   1602         tunnel_type = bcmTunnelTypeGre4In6;
   1603     } else if (endpoint_info->type == bcmBFDTunnelTypeGre6In6) {
   1604         tunnel_type = bcmTunnelTypeGre6In6;
   1605     } else {
   1606         return BCM_E_PARAM;
   1607     }
   1608 
   1609     /* Initialize lookup key */
   1610     bcm_tunnel_terminator_t_init(&tunnel);
   1611     tunnel.type = tunnel_type;
   1612     if ((tunnel_type == bcmTunnelTypeIp4In4) ||
   1613         (tunnel_type == bcmTunnelTypeIp6In4) ||
   1614         (tunnel_type == bcmTunnelTypeGre4In4) ||
   1615         (tunnel_type == bcmTunnelTypeGre6In4)) {
   1616         tunnel.sip  = endpoint_info->dst_ip_addr;
   1617         tunnel.dip  = endpoint_info->src_ip_addr;
   1618         tunnel.sip_mask = 0xffffffff;
   1619         tunnel.dip_mask = 0xffffffff;
   1620     } else {
   1621         sal_memcpy(tunnel.sip6, endpoint_info->dst_ip6_addr, BCM_IP6_ADDRLEN);
   1622         sal_memcpy(tunnel.dip6, endpoint_info->src_ip6_addr, BCM_IP6_ADDRLEN);
   1623         sal_memset(tunnel.sip6_mask, 0xff, BCM_IP6_ADDRLEN);
   1624         sal_memset(tunnel.dip6_mask, 0xff, BCM_IP6_ADDRLEN);
   1625     }
   1626 
   1627     if ((BCM_ESW_BFD_DRV(unit) == NULL) ||
   1628         (BFD_HW_CALL(unit)->l3_tnl_term_entry_init == NULL)) {
   1629         return BCM_E_UNAVAIL;
   1630     }
   1631     BCM_IF_ERROR_RETURN
   1632         (BFD_HW_CALL(unit)->l3_tnl_term_entry_init(unit, &tunnel, &key));
   1633 
   1634     /* Find tunnel terminator in TCAM */
   1635     BCM_IF_ERROR_RETURN(soc_tunnel_term_match(unit, &key, tunnel_entry, &index));
   1636 
   1637     return BCM_E_NONE;
   1638 }
   1639 
   1640 STATIC int
   1641 bcmi_xgs5_bfd_l3_tunnel_entry_set(int unit,
   1642                                   bcm_bfd_endpoint_info_t *endpoint_info)
   1643 {
   1644     soc_tunnel_term_t tunnel_entry;
   1645     uint32 *tunnel_entry_ptr;
   1646     uint32 tunnel_index;
   1647     bcm_tunnel_type_t tunnel_type;
   1648     int tnl_outer_hdr_ipv6 = 0;
   1649 
   1650     BCM_IF_ERROR_RETURN
   1651         (bcmi_xgs5_bfd_find_l3_tunnel_entry(unit, endpoint_info,
   1652                                             &tunnel_entry));
   1653 
   1654     tunnel_entry_ptr = (uint32 *)&tunnel_entry.entry_arr[0];
   1655 
   1656     _BFD_TO_BCM_TUNNEL_TYPE(endpoint_info->type, tunnel_type);
   1657 
   1658     tnl_outer_hdr_ipv6 = _BCM_TUNNEL_OUTER_HEADER_IPV6(tunnel_type);
   1659 
   1660     if (tnl_outer_hdr_ipv6 && BFD_HW_L3_TUNNEL_IPV6(unit)) {
   1661         soc_mem_field32_set(unit, BFD_HW_L3_TUNNEL_IPV6_MEM(unit), tunnel_entry_ptr,
   1662                             BFD_HW_L3_TUNNEL_IPV6(unit)->bfd_enable, 1);
   1663     } else {
   1664 
   1665 #if defined(BCM_TRIDENT3_SUPPORT)
   1666     if(!(SOC_IS_TRIDENT3X(unit))) {
   1667 #endif
   1668         soc_mem_field32_set(unit, BFD_HW_L3_TUNNEL_MEM(unit), tunnel_entry_ptr,
   1669                             BFD_HW_L3_TUNNEL(unit)->bfd_enable, 1);
   1670 #if defined(BCM_TRIDENT3_SUPPORT)
   1671     }
   1672 #endif
   1673     }
   1674 
   1675     BCM_IF_ERROR_RETURN
   1676         (soc_tunnel_term_insert(unit, &tunnel_entry, &tunnel_index));
   1677 
   1678     return BCM_E_NONE;
   1679 }
   1680 
   1681 
   1682 STATIC int
   1683 bcmi_xgs5_bfd_l3_tunnel_entry_status(int unit,
   1684                                   bcm_bfd_endpoint_info_t *endpoint_info)
   1685 {
   1686     soc_tunnel_term_t tunnel_entry;
   1687 
   1688     BCM_IF_ERROR_RETURN
   1689         (bcmi_xgs5_bfd_find_l3_tunnel_entry(unit, endpoint_info,
   1690                                             &tunnel_entry));
   1691 
   1692     return BCM_E_NONE;
   1693 }
   1694 
   1695 STATIC int
   1696 bcmi_xgs5_bfd_l3_tunnel_entry_clear(int unit,
   1697                                     bcm_bfd_endpoint_info_t *endpoint_info)
   1698 {
   1699     soc_tunnel_term_t tunnel_entry;
   1700     uint32 *tunnel_entry_ptr;
   1701     uint32 tunnel_index;
   1702     bcm_tunnel_type_t tunnel_type;
   1703     int tnl_outer_hdr_ipv6 = 0;
   1704 
   1705     BCM_IF_ERROR_RETURN
   1706         (bcmi_xgs5_bfd_find_l3_tunnel_entry(unit, endpoint_info,
   1707                                             &tunnel_entry));
   1708 
   1709     tunnel_entry_ptr = (uint32 *)&tunnel_entry.entry_arr[0];
   1710 
   1711     _BFD_TO_BCM_TUNNEL_TYPE(endpoint_info->type, tunnel_type);
   1712     tnl_outer_hdr_ipv6 = _BCM_TUNNEL_OUTER_HEADER_IPV6(tunnel_type);
   1713 
   1714     if (tnl_outer_hdr_ipv6 && BFD_HW_L3_TUNNEL_IPV6(unit)) {
   1715         soc_mem_field32_set(unit, BFD_HW_L3_TUNNEL_IPV6_MEM(unit), tunnel_entry_ptr,
   1716                             BFD_HW_L3_TUNNEL_IPV6(unit)->bfd_enable, 0);
   1717     } else {
   1718 #if defined(BCM_TRIDENT3_SUPPORT)
   1719     if(!(SOC_IS_TRIDENT3X(unit))) {
   1720 #endif
   1721         soc_mem_field32_set(unit, BFD_HW_L3_TUNNEL_MEM(unit), tunnel_entry_ptr,
   1722                             BFD_HW_L3_TUNNEL(unit)->bfd_enable, 0);
   1723 #if defined(BCM_TRIDENT3_SUPPORT)
   1724     }
   1725 #endif
   1726     }
   1727     BCM_IF_ERROR_RETURN
   1728         (soc_tunnel_term_insert(unit, &tunnel_entry, &tunnel_index));
   1729 
   1730     return BCM_E_NONE;
   1731 }
   1732 
   1733 /*
   1734  * Function:
   1735  *      bcmi_xgs5_bfd_mpls_port_resolve
   1736  */
   1737 STATIC int
   1738 bcmi_xgs5_bfd_mpls_port_resolve(int unit,
   1739                                 bcm_bfd_endpoint_info_t *endpoint_info,
   1740                                 int *mod_out, int *port_out)
   1741 {
   1742     bcm_mpls_port_t *mpls_port = NULL;
   1743     bcm_trunk_t trunk_id;
   1744     int local_id;
   1745     int rv = BCM_E_NONE;
   1746 
   1747     if (BCM_GPORT_IS_MPLS_PORT(endpoint_info->gport)) {
   1748         mpls_port = sal_alloc(sizeof(bcm_mpls_port_t), "Mpls port");
   1749         if (mpls_port == NULL) {
   1750             return (BCM_E_MEMORY);
   1751         }
   1752         bcm_mpls_port_t_init(mpls_port);
   1753         mpls_port->mpls_port_id = endpoint_info->gport;
   1754         if (BCM_FAILURE
   1755             (bcm_esw_mpls_port_get(unit, endpoint_info->vpn,
   1756             mpls_port))) {
   1757             sal_free(mpls_port);
   1758             return BCM_E_PARAM;
   1759         }
   1760         rv = _bcm_esw_gport_resolve(unit, mpls_port->port, mod_out,
   1761                                     port_out, &trunk_id, &local_id);
   1762         sal_free(mpls_port);
   1763         BCM_IF_ERROR_RETURN(rv);
   1764     } else if (BCM_GPORT_INVALID != endpoint_info->gport) {
   1765         rv = _bcm_esw_gport_resolve(unit, endpoint_info->gport, mod_out,
   1766                                     port_out, &trunk_id, &local_id);
   1767         BCM_IF_ERROR_RETURN(rv);
   1768     }
   1769 
   1770     return rv;
   1771 }
   1772 
   1773 /*
   1774  * Function:
   1775  *      bcmi_xgs5_bfd_mpls_entry_set
   1776  */
   1777 STATIC int
   1778 bcmi_xgs5_bfd_mpls_entry_set(int unit,
   1779                              bfd_endpoint_config_t *endpoint_config)
   1780 {
   1781 #if defined(BCM_MPLS_SUPPORT)
   1782     bcm_bfd_endpoint_info_t *endpoint_info;
   1783     mpls_entry_entry_t mpls_entry;
   1784     mpls_entry_entry_t mpls_key;
   1785 #if defined(BCM_TRIUMPH3_SUPPORT)
   1786     mpls_entry_extd_entry_t mpls_extd_entry;
   1787     mpls_entry_extd_entry_t mpls_extd_key;
   1788     int key_type_found = 0;
   1789     int rv;
   1790 #endif
   1791     int mpls_index = 0;
   1792     int i, num_entries;
   1793     bcm_l3_egress_t l3_egress;
   1794     int ingress_if;
   1795     int cc_type = 0, hw_cc_type = 0;
   1796     bcm_module_t mod_out;
   1797     bcm_port_t port_out;
   1798     endpoint_info  = &endpoint_config->info;
   1799     
   1800     sal_memset(&mpls_key, 0, sizeof(mpls_key));
   1801 
   1802     /* Add key_type_value 16 for Tr3*/
   1803     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   1804                         BFD_HW_MPLS(unit)->key_type,
   1805                         BFD_HW_MPLS(unit)->key_type_value);
   1806 
   1807     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   1808                         BFD_HW_MPLS(unit)->mpls_label, endpoint_info->label);
   1809 
   1810 #if defined(INCLUDE_L3)
   1811     if (bcm_tr_mpls_port_independent_range(unit, endpoint_info->label,
   1812                                            BCM_GPORT_INVALID) != BCM_E_NONE) {
   1813         mod_out = endpoint_config->modid;
   1814         port_out = endpoint_config->port;
   1815 
   1816         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   1817             BFD_HW_MPLS(unit)->mod_id, mod_out);
   1818         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   1819             BFD_HW_MPLS(unit)->port_num, port_out);
   1820     }
   1821 #endif
   1822     /* coverity[overrun-buffer-val : FALSE]    */
   1823 #if defined(BCM_TRIUMPH3_SUPPORT)
   1824     if (SOC_IS_TRIUMPH3(unit)) {
   1825         /* First Search for key_type 16 */
   1826         rv = soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   1827                             MEM_BLOCK_ANY, &mpls_index,
   1828                             &mpls_key, &mpls_entry, 0);
   1829 
   1830         /* If key_type 16 not found, Search for key_type 17 in MPLS_ENTRY_EXTDm */
   1831         if (rv == BCM_E_NOT_FOUND) {
   1832             sal_memset(&mpls_extd_key, 0, sizeof(mpls_extd_key));
   1833             /* Add key_type_value 17 for Tr3 with conversion */
   1834             BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit,
   1835                                 &mpls_key, &mpls_extd_key));
   1836 
   1837             SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRY_EXTDm,
   1838                                                MEM_BLOCK_ANY, &mpls_index,
   1839                                                &mpls_extd_key, &mpls_extd_entry, 0));
   1840             key_type_found = 1;
   1841         }
   1842 } else
   1843 #endif
   1844 {
   1845     SOC_IF_ERROR_RETURN(soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   1846                                        MEM_BLOCK_ANY, &mpls_index,
   1847                                        &mpls_key, &mpls_entry, 0));
   1848 }
   1849 
   1850 #if defined(BCM_TRIUMPH3_SUPPORT)
   1851 if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   1852       (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   1853       if ((soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1854                               VALID_0f) != 0x1)) {
   1855           return BCM_E_PARAM;
   1856       }
   1857       if ((soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1858                               VALID_1f) != 0x1)) {
   1859            return BCM_E_PARAM;
   1860       }
   1861 } else
   1862 #endif
   1863 {
   1864     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   1865         if (soc_mem_field32_get(unit, MPLS_ENTRYm, &mpls_entry,
   1866                                 BASE_VALID_0f) != 3) {
   1867             return BCM_E_PARAM;
   1868         }
   1869         if (soc_mem_field32_get(unit, MPLS_ENTRYm, &mpls_entry,
   1870                                 BASE_VALID_1f) != 7) {
   1871             return BCM_E_PARAM;
   1872         }
   1873     } else {
   1874         if ((soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   1875                                  BFD_HW_MPLS(unit)->valid) != 0x1)) {
   1876             return BCM_E_PARAM;
   1877         }
   1878     }
   1879 }
   1880 
   1881     /* Set PW CC Type */
   1882     if (endpoint_info->type == bcmBFDTunnelTypePweControlWord) {
   1883         cc_type = 1;
   1884     } else if (endpoint_info->type == bcmBFDTunnelTypePweRouterAlert) {
   1885         cc_type = 2;
   1886     } else if (endpoint_info->type == bcmBFDTunnelTypePweTtl) {
   1887         cc_type = 3;
   1888     }
   1889 
   1890     if ((endpoint_info->type == bcmBFDTunnelTypeMplsTpCc) ||
   1891         (endpoint_info->type == bcmBFDTunnelTypeMplsTpCcCv)) {
   1892 #if defined(BCM_TRIUMPH3_SUPPORT)
   1893         if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   1894              (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   1895               if (soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1896                   MPLS__MPLS_ACTION_IF_BOSf) == MPLS_ACTION_POP_L3_IIF) {
   1897                   endpoint_config->is_l3_vpn = 1;    /* L3 VPN */
   1898               } else {
   1899                   endpoint_config->is_l3_vpn = 0;
   1900                   cc_type = 1;  /* PW */
   1901              }
   1902         } else
   1903 #endif
   1904 {
   1905         if (soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   1906              BFD_HW_MPLS(unit)->mpls_action_if_bos) == MPLS_ACTION_POP_L3_IIF) {
   1907             endpoint_config->is_l3_vpn = 1;    /* L3 VPN */
   1908         } else {
   1909             endpoint_config->is_l3_vpn = 0;    
   1910             cc_type = 1;  /* PW */
   1911         }
   1912 }
   1913 }
   1914 
   1915 #if defined(BCM_TOMAHAWK_SUPPORT)
   1916     if(!(SOC_IS_TOMAHAWKX(unit) ||
   1917          SOC_IS_TRIDENT3X(unit))) {
   1918 #endif
   1919 #if defined(BCM_TRIUMPH3_SUPPORT)
   1920        if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   1921             (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   1922             if (endpoint_info->flags & BCM_BFD_ENDPOINT_KEY_TYPE_USE_YOUR_DISC) {
   1923                 soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1924                                     MPLS__SESSION_IDENTIFIER_TYPEf, 0);
   1925             }else{
   1926                soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1927                                    MPLS__SESSION_IDENTIFIER_TYPEf, 1);
   1928             }
   1929         } else
   1930 #endif
   1931         {
   1932             if (endpoint_info->flags & BCM_BFD_ENDPOINT_KEY_TYPE_USE_YOUR_DISC) {
   1933                 soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   1934                                     BFD_HW_MPLS(unit)->session_id_type, 0);
   1935             }else{
   1936                 soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   1937                                     BFD_HW_MPLS(unit)->session_id_type, 1);
   1938             }
   1939         }
   1940 #if defined(BCM_TOMAHAWK_SUPPORT)
   1941     }
   1942 #endif
   1943 
   1944 #if defined(BCM_TRIUMPH3_SUPPORT)
   1945     if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   1946          (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   1947           soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1948                               MPLS__BFD_ENABLEf, 1);
   1949 
   1950           hw_cc_type = soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1951                                            MPLS__PW_CC_TYPEf);
   1952           if (hw_cc_type == 0) {
   1953               soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   1954                                   MPLS__PW_CC_TYPEf, cc_type);
   1955           } else if (hw_cc_type != cc_type) {
   1956               return BCM_E_PARAM;
   1957           }
   1958     } else
   1959 #endif
   1960 {
   1961 #if defined(BCM_TRIDENT3_SUPPORT)
   1962     if(!(SOC_IS_TRIDENT3X(unit))) {
   1963 #endif
   1964         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   1965                             BFD_HW_MPLS(unit)->bfd_enable, 1);
   1966 #if defined(BCM_TRIDENT3_SUPPORT)
   1967     }
   1968 #endif
   1969     if(cc_type) {
   1970         hw_cc_type = soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   1971                                          BFD_HW_MPLS(unit)->pw_cc_type);
   1972         if (hw_cc_type == 0) {
   1973             soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   1974                                 BFD_HW_MPLS(unit)->pw_cc_type, cc_type);
   1975         } else if (hw_cc_type != cc_type) {
   1976             return BCM_E_PARAM;
   1977         }
   1978     }
   1979 }
   1980 
   1981     /* use MPLS_ENTRY_EXTDm as mem_name for key type 17 */
   1982 #if defined(BCM_TRIUMPH3_SUPPORT)
   1983     if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   1984          (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   1985          SOC_IF_ERROR_RETURN(soc_mem_write(unit, MPLS_ENTRY_EXTDm,
   1986                              MEM_BLOCK_ANY, mpls_index, &mpls_extd_entry));
   1987     } else
   1988 #endif
   1989     {
   1990         SOC_IF_ERROR_RETURN(soc_mem_write(unit, BFD_HW_MPLS_MEM(unit),
   1991                             MEM_BLOCK_ANY, mpls_index, &mpls_entry));
   1992     }
   1993 
   1994     /*
   1995      * PW CC-3
   1996      *
   1997      * Set MPLS entry DECAP_USE_TTL=0 for corresponding
   1998      * Tunnel Terminator label.
   1999      */
   2000     if (endpoint_info->type == bcmBFDTunnelTypePweTtl) {
   2001         BCM_IF_ERROR_RETURN
   2002             (bcm_esw_l3_egress_get(unit, endpoint_info->egress_if,
   2003                                    &l3_egress));
   2004 
   2005         /* Look for Tunnel Terminator label */
   2006 #if defined(BCM_TRIUMPH3_SUPPORT)
   2007     if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   2008          (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   2009           num_entries = soc_mem_index_count(unit, MPLS_ENTRY_EXTDm);
   2010     } else
   2011 #endif
   2012 {
   2013         num_entries = soc_mem_index_count(unit, BFD_HW_MPLS_MEM(unit));
   2014 }
   2015         for (i = 0; i < num_entries; i++) {
   2016 #if defined(BCM_TRIUMPH3_SUPPORT)
   2017     if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   2018          (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   2019           BCM_IF_ERROR_RETURN
   2020                 (soc_mem_read(unit, MPLS_ENTRY_EXTDm,
   2021                               MEM_BLOCK_ANY, i, &mpls_extd_entry));
   2022             if (!soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm,
   2023                                      &mpls_extd_entry, VALIDf)) {
   2024                 continue;
   2025             }
   2026             if (soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   2027                                     MPLS__MPLS_ACTION_IF_BOSf)
   2028                 == 0x1) {
   2029                 continue;    /* L2_SVP */
   2030             }
   2031 
   2032             ingress_if = soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm,
   2033                                              &mpls_extd_entry,
   2034                                              MPLS__L3_IIFf);
   2035             if (ingress_if == l3_egress.intf) {
   2036                 /* Label found */
   2037                 soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm,
   2038                                     &mpls_extd_entry,
   2039                                     MPLS__DECAP_USE_TTLf, 0);
   2040                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, MPLS_ENTRY_EXTDm,
   2041                                                   MEM_BLOCK_ALL, i,
   2042                                                   &mpls_extd_entry));
   2043                 break;
   2044             }
   2045     } else
   2046 #endif
   2047 {
   2048             BCM_IF_ERROR_RETURN
   2049                 (soc_mem_read(unit, BFD_HW_MPLS_MEM(unit),
   2050                               MEM_BLOCK_ANY, i, &mpls_entry));
   2051             if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2052                 if (soc_mem_field32_get(unit, MPLS_ENTRYm, &mpls_entry,
   2053                                         BASE_VALID_0f) != 3) {
   2054                     continue;
   2055                 }
   2056                 if (soc_mem_field32_get(unit, MPLS_ENTRYm, &mpls_entry,
   2057                                         BASE_VALID_1f) != 7) {
   2058                     continue;
   2059                 }
   2060             } else {
   2061                 if (!soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   2062                                          BFD_HW_MPLS(unit)->valid)) {
   2063                     continue;
   2064                 }
   2065             }
   2066             if (soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   2067                                     BFD_HW_MPLS(unit)->mpls_action_if_bos)
   2068                 == 0x1) {
   2069                 continue;    /* L2_SVP */
   2070             }
   2071 
   2072             ingress_if = soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit),
   2073                                              &mpls_entry,
   2074                                              BFD_HW_MPLS(unit)->l3_iif);
   2075             if (ingress_if == l3_egress.intf) {
   2076                 /* Label found */
   2077                 soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit),
   2078                                     &mpls_entry,
   2079                                     BFD_HW_MPLS(unit)->decap_use_ttl, 0);
   2080                 SOC_IF_ERROR_RETURN(soc_mem_write(unit, BFD_HW_MPLS_MEM(unit),
   2081                                                   MEM_BLOCK_ALL, i,
   2082                                                   &mpls_entry));
   2083                 break;
   2084             }
   2085 }
   2086         }
   2087     }
   2088 
   2089     return BCM_E_NONE;
   2090 #else
   2091     return BCM_E_UNAVAIL;
   2092 #endif /* BCM_MPLS_SUPPORT */
   2093 }
   2094 
   2095 /*
   2096  * Function:
   2097  *      bcmi_xgs5_bfd_mpls_entry_clear
   2098  */
   2099 STATIC int
   2100 bcmi_xgs5_bfd_mpls_entry_clear(int unit,
   2101                                bfd_endpoint_config_t *endpoint_config)
   2102 {
   2103 #if defined(BCM_MPLS_SUPPORT)
   2104     bcm_bfd_endpoint_info_t *endpoint_info;
   2105     mpls_entry_entry_t mpls_entry;
   2106     mpls_entry_entry_t mpls_key;
   2107 #if defined(BCM_TRIUMPH3_SUPPORT)
   2108     mpls_entry_extd_entry_t mpls_extd_key;
   2109     mpls_entry_extd_entry_t mpls_extd_entry;
   2110     int key_type_found = 0;
   2111     int rv;
   2112 #endif
   2113     int mpls_index = 0;
   2114     bcm_module_t mod_out;
   2115     bcm_port_t port_out;
   2116     endpoint_info  = &endpoint_config->info;
   2117 
   2118     sal_memset(&mpls_key, 0, sizeof(mpls_key));
   2119 
   2120     /* Clear key_type_value 16 for Tr3*/
   2121     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2122                         BFD_HW_MPLS(unit)->key_type, BFD_HW_MPLS(unit)->key_type_value);
   2123     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2124                         BFD_HW_MPLS(unit)->mpls_label, endpoint_info->label);
   2125 
   2126 #if defined(INCLUDE_L3)
   2127     if (bcm_tr_mpls_port_independent_range(unit, endpoint_info->label,
   2128                                            BCM_GPORT_INVALID) != BCM_E_NONE) {
   2129         mod_out = endpoint_config->modid;
   2130         port_out = endpoint_config->port;
   2131 
   2132         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2133             BFD_HW_MPLS(unit)->mod_id, mod_out);
   2134         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2135             BFD_HW_MPLS(unit)->port_num, port_out);
   2136     }
   2137 #endif
   2138     /* coverity[overrun-buffer-val : FALSE]    */
   2139 #if defined(BCM_TRIUMPH3_SUPPORT)
   2140     if (SOC_IS_TRIUMPH3(unit)) {
   2141         /* First Search for key_type 16 */
   2142         rv = soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   2143                             MEM_BLOCK_ANY, &mpls_index,
   2144                             &mpls_key, &mpls_entry, 0);
   2145 
   2146         /* If key_type 16 not found, Search for key_type 17 in MPLS_ENTRY_EXTDm */
   2147         if (rv == BCM_E_NOT_FOUND) {
   2148             sal_memset(&mpls_extd_key, 0, sizeof(mpls_extd_key));
   2149             /* Add key_type_value 17 for Tr3 with conversion */
   2150             BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit,
   2151                                 &mpls_key, &mpls_extd_key));
   2152 
   2153             SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRY_EXTDm,
   2154                                                MEM_BLOCK_ANY, &mpls_index,
   2155                                                &mpls_extd_key, &mpls_extd_entry, 0));
   2156             key_type_found = 1;
   2157         }
   2158 } else
   2159 #endif
   2160 {
   2161     SOC_IF_ERROR_RETURN(soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   2162                                        MEM_BLOCK_ANY, &mpls_index,
   2163                                        &mpls_key, &mpls_entry, 0));
   2164 }
   2165 
   2166 #if defined(BCM_TRIUMPH3_SUPPORT)
   2167     if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   2168          (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   2169           soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   2170                               MPLS__BFD_ENABLEf, 0);
   2171     } else
   2172 #endif
   2173     {
   2174 #if defined(BCM_TRIDENT3_SUPPORT)
   2175         if(!(SOC_IS_TRIDENT3X(unit))) {
   2176 #endif
   2177             soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   2178                                 BFD_HW_MPLS(unit)->bfd_enable, 0);
   2179 #if defined(BCM_TRIDENT3_SUPPORT)
   2180         }
   2181 #endif
   2182     }
   2183 
   2184     /* use MPLS_ENTRY_EXTDm as mem_name for key type 17 */
   2185 #if defined(BCM_TRIUMPH3_SUPPORT)
   2186     if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   2187          (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   2188          SOC_IF_ERROR_RETURN(soc_mem_write(unit, MPLS_ENTRY_EXTDm,
   2189                              MEM_BLOCK_ANY, mpls_index, &mpls_extd_entry));
   2190     } else
   2191 #endif
   2192     {
   2193         SOC_IF_ERROR_RETURN(soc_mem_write(unit, BFD_HW_MPLS_MEM(unit),
   2194                             MEM_BLOCK_ANY, mpls_index, &mpls_entry));
   2195     }
   2196     return BCM_E_NONE;
   2197 #else
   2198     return BCM_E_UNAVAIL;
   2199 #endif /* BCM_MPLS_SUPPORT */
   2200 }
   2201 
   2202 #ifdef BCM_WARM_BOOT_SUPPORT
   2203 /*
   2204  * Function:
   2205  *      bcmi_xgs5_bfd_mpls_is_l3_vpn_get
   2206  */
   2207 STATIC int
   2208 bcmi_xgs5_bfd_mpls_is_l3_vpn_get(int unit,
   2209                                  bfd_endpoint_config_t *endpoint_config)
   2210 {
   2211 #if defined(BCM_MPLS_SUPPORT)
   2212     bcm_bfd_endpoint_info_t *endpoint_info;
   2213     mpls_entry_entry_t mpls_entry;
   2214     mpls_entry_entry_t mpls_key;
   2215 #if defined(BCM_TRIUMPH3_SUPPORT)
   2216     mpls_entry_extd_entry_t mpls_extd_entry;
   2217     mpls_entry_extd_entry_t mpls_extd_key;
   2218     int key_type_found = 0;
   2219 #endif
   2220     int mpls_index = 0;
   2221     bcm_module_t mod_out;
   2222     bcm_port_t port_out;
   2223     int rv;
   2224     endpoint_info  = &endpoint_config->info;
   2225 
   2226     sal_memset(&mpls_key, 0, sizeof(mpls_key));
   2227 
   2228     /* Add key_type_value 16 for Tr3*/
   2229     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2230                         BFD_HW_MPLS(unit)->key_type,
   2231                         BFD_HW_MPLS(unit)->key_type_value);
   2232 
   2233     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2234                         BFD_HW_MPLS(unit)->mpls_label, endpoint_info->label);
   2235 
   2236 #if defined(INCLUDE_L3)
   2237     if (bcm_tr_mpls_port_independent_range(unit, endpoint_info->label,
   2238                                            BCM_GPORT_INVALID) != BCM_E_NONE) {
   2239         rv = bcmi_xgs5_bfd_mpls_port_resolve(unit, endpoint_info,
   2240                                              &mod_out , &port_out);
   2241         BCM_IF_ERROR_RETURN(rv);
   2242 
   2243         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2244             BFD_HW_MPLS(unit)->mod_id, mod_out);
   2245         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   2246             BFD_HW_MPLS(unit)->port_num, port_out);
   2247     }
   2248 #endif
   2249  /* coverity[overrun-buffer-val : FALSE]    */
   2250 #if defined(BCM_TRIUMPH3_SUPPORT)
   2251     if (SOC_IS_TRIUMPH3(unit)) {
   2252         /* First Search for key_type 16 */
   2253         rv = soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   2254                             MEM_BLOCK_ANY, &mpls_index,
   2255                             &mpls_key, &mpls_entry, 0);
   2256 
   2257         /* If key_type 16 not found, Search for key_type 17 in MPLS_ENTRY_EXTDm */
   2258         if (rv == BCM_E_NOT_FOUND) {
   2259             sal_memset(&mpls_extd_key, 0, sizeof(mpls_extd_key));
   2260             /* Add key_type_value 17 for Tr3 with conversion */
   2261             BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit,
   2262                                 &mpls_key, &mpls_extd_key));
   2263 
   2264             SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRY_EXTDm,
   2265                                                MEM_BLOCK_ANY, &mpls_index,
   2266                                                &mpls_extd_key, &mpls_extd_entry, 0));
   2267             key_type_found = 1;
   2268         }
   2269 } else
   2270 #endif
   2271 {
   2272     SOC_IF_ERROR_RETURN(soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   2273                                        MEM_BLOCK_ANY, &mpls_index,
   2274                                        &mpls_key, &mpls_entry, 0));
   2275 }
   2276 
   2277 #if defined(BCM_TRIUMPH3_SUPPORT)
   2278 if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   2279       (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   2280       if ((soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   2281                               VALID_0f) != 0x1)) {
   2282           return BCM_E_PARAM;
   2283       }
   2284       if ((soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   2285                               VALID_1f) != 0x1)) {
   2286            return BCM_E_PARAM;
   2287       }
   2288 } else
   2289 #endif
   2290 {
   2291     if (soc_feature(unit, soc_feature_td3_style_mpls)) {
   2292         if (soc_mem_field32_get(unit, MPLS_ENTRYm, &mpls_entry,
   2293                                 BASE_VALID_0f) != 3) {
   2294             return BCM_E_PARAM;
   2295         }
   2296         if (soc_mem_field32_get(unit, MPLS_ENTRYm, &mpls_entry,
   2297                                 BASE_VALID_1f) != 7) {
   2298             return BCM_E_PARAM;
   2299         }
   2300     } else {
   2301         if ((soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   2302                                  BFD_HW_MPLS(unit)->valid) != 0x1)) {
   2303             return BCM_E_PARAM;
   2304         }
   2305     }
   2306 }
   2307 
   2308 #if defined(BCM_TRIUMPH3_SUPPORT)
   2309     if (((BFD_HW_MPLS(unit)->key_type_value + 1) == 17) &&
   2310           (key_type_found) && (SOC_IS_TRIUMPH3(unit))) {
   2311           if (soc_mem_field32_get(unit, MPLS_ENTRY_EXTDm, &mpls_extd_entry,
   2312               MPLS__MPLS_ACTION_IF_BOSf) == MPLS_ACTION_POP_L3_IIF) {
   2313               endpoint_config->is_l3_vpn = 1;    /* L3 VPN */
   2314           }
   2315     } else
   2316 #endif
   2317 {
   2318     if (soc_mem_field32_get(unit, BFD_HW_MPLS_MEM(unit), &mpls_entry,
   2319         BFD_HW_MPLS(unit)->mpls_action_if_bos) == MPLS_ACTION_POP_L3_IIF) {
   2320         endpoint_config->is_l3_vpn = 1;    /* L3 VPN */
   2321     }
   2322 }
   2323     return BCM_E_NONE;
   2324 #else
   2325     return BCM_E_UNAVAIL;
   2326 #endif /* BCM_MPLS_SUPPORT */
   2327 }
   2328 #endif
   2329 
   2330 /*
   2331  * Function:
   2332  *      bcmi_xgs5_bfd_hw_init
   2333  * Purpose:
   2334  *      Initialize the HW for BFD packet processing.
   2335  *      Configure:
   2336  *      - Copy to CPU BFD error packets
   2337  *      - Assign RX DMA channel to BFD CPU COS Queue
   2338  *      - Map RX BFD packets to BFD CPU COS Queue
   2339  * Parameters:
   2340  *      unit - (IN) Unit number.
   2341  * Returns:
   2342  *      BCM_E_XXX
   2343  * Notes:
   2344  */
   2345 STATIC int
   2346 bcmi_xgs5_bfd_hw_init(int unit)
   2347 {
   2348     int rv = BCM_E_NONE;
   2349     bfd_info_t *bfd_info = BFD_INFO(unit);
   2350     uint32 val;
   2351     int index;
   2352     int slowpath_index, ach_err_index,unknown_version_index;
   2353     int cosq_map_size;
   2354     bcm_rx_reasons_t reasons, reasons_mask;
   2355     bcm_rx_reasons_t reasons_all;
   2356     uint8 int_prio, int_prio_mask;
   2357     uint32 packet_type, packet_type_mask;
   2358     bcm_cos_queue_t cosq;
   2359     bcm_rx_chan_t chan_id;
   2360     int num_cosq = 0;
   2361     int min_cosq, max_cosq;
   2362     int i;
   2363     uint32 max_rx_channels = 0;
   2364     uint32 num_of_cpu_queues = 0;
   2365 
   2366     /*
   2367      * Send BFD error packet to CPU
   2368      *
   2369      * Configure CPU_CONTROL_0 register
   2370      */
   2371     if (SOC_REG_IS_VALID(unit, CPU_CONTROL_0r)) {
   2372         BCM_IF_ERROR_RETURN(READ_CPU_CONTROL_0r(unit, &val));
   2373         if (SOC_REG_FIELD_VALID(unit, CPU_CONTROL_0r,
   2374                                 BFD_UNKNOWN_VERSION_TOCPUf)) {
   2375             soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2376                               BFD_UNKNOWN_VERSION_TOCPUf, 1);
   2377         }
   2378         if (SOC_REG_FIELD_VALID(unit, CPU_CONTROL_0r,
   2379                                 BFD_YOUR_DISCRIMINATOR_NOT_FOUND_TOCPUf)) {
   2380             soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2381                               BFD_YOUR_DISCRIMINATOR_NOT_FOUND_TOCPUf, 1);
   2382         }
   2383         if (SOC_REG_FIELD_VALID(unit, CPU_CONTROL_0r,
   2384                                 BFD_UNKNOWN_CONTROL_PACKET_TOCPUf)) {
   2385             soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2386                               BFD_UNKNOWN_CONTROL_PACKET_TOCPUf, 0);
   2387         }
   2388         if (SOC_REG_FIELD_VALID(unit, CPU_CONTROL_0r,
   2389                                 BFD_UNKNOWN_ACH_CHANNEL_TYPE_TOCPUf)) {
   2390             soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2391                               BFD_UNKNOWN_ACH_CHANNEL_TYPE_TOCPUf, 1);
   2392         }
   2393         if (SOC_REG_FIELD_VALID(unit, CPU_CONTROL_0r,
   2394                                 BFD_UNKNOWN_ACH_VERSION_TOCPUf)) {
   2395             soc_reg_field_set(unit, CPU_CONTROL_0r, &val,
   2396                               BFD_UNKNOWN_ACH_VERSION_TOCPUf, 1);
   2397         }
   2398         BCM_IF_ERROR_RETURN(WRITE_CPU_CONTROL_0r(unit, val));
   2399     } else {
   2400         return BCM_E_UNAVAIL;
   2401     }
   2402 
   2403     /*
   2404      * Set BFD ACH Channel Types
   2405      * In Saber2 this will be done as part of OAM init
   2406      */
   2407 #if defined(BCM_SABER2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   2408     if(!(SOC_IS_SABER2(unit) ||
   2409          SOC_IS_TRIDENT3X(unit))) {
   2410 #endif
   2411         BCM_IF_ERROR_RETURN(READ_BFD_RX_ACH_TYPE_CONTROL0r(unit, &val));
   2412         soc_reg_field_set(unit, BFD_RX_ACH_TYPE_CONTROL0r, &val,
   2413                           BFD_ACH_TYPE_IPV4f, SHR_BFD_ACH_CHANNEL_TYPE_IPV4);
   2414         soc_reg_field_set(unit, BFD_RX_ACH_TYPE_CONTROL0r, &val,
   2415                           BFD_ACH_TYPE_IPV6f, SHR_BFD_ACH_CHANNEL_TYPE_IPV6);
   2416         BCM_IF_ERROR_RETURN(WRITE_BFD_RX_ACH_TYPE_CONTROL0r(unit, val));
   2417 
   2418         BCM_IF_ERROR_RETURN(READ_BFD_RX_ACH_TYPE_CONTROL1r(unit, &val));
   2419         soc_reg_field_set(unit, BFD_RX_ACH_TYPE_CONTROL1r, &val,
   2420                           BFD_ACH_TYPE_RAWf, SHR_BFD_ACH_CHANNEL_TYPE_RAW);
   2421         BCM_IF_ERROR_RETURN(WRITE_BFD_RX_ACH_TYPE_CONTROL1r(unit, val));
   2422 
   2423         BCM_IF_ERROR_RETURN(READ_BFD_RX_ACH_TYPE_MPLSTPr(unit, &val));
   2424         soc_reg_field_set(unit, BFD_RX_ACH_TYPE_MPLSTPr, &val,
   2425                           BFD_ACH_TYPE_MPLSTP_CCf,
   2426                           SHR_BFD_ACH_CHANNEL_TYPE_MPLS_TP_CC);
   2427         soc_reg_field_set(unit, BFD_RX_ACH_TYPE_MPLSTPr, &val,
   2428                           BFD_ACH_TYPE_MPLSTP_CVf,
   2429                           SHR_BFD_ACH_CHANNEL_TYPE_MPLS_TP_CV);
   2430         BCM_IF_ERROR_RETURN(WRITE_BFD_RX_ACH_TYPE_MPLSTPr(unit, val));
   2431 #if defined(BCM_SABER2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
   2432     }
   2433 #endif
   2434 
   2435     /*
   2436      * Set special Session-ID for Unknown Remote Discriminator
   2437      *
   2438      * This allows initial BFD Control packets, where the remote
   2439      * discriminator is unknown (your_discriminator=0),
   2440      * to be received as 'good packets' and be distinct from
   2441      * other errors (wrong BFD version) that may result
   2442      * in "bcmRxReasonBfdLookupFailure"
   2443      */
   2444 #if defined(BCM_TOMAHAWK_SUPPORT)
   2445     if(!(SOC_IS_TOMAHAWKX(unit) ||
   2446          SOC_IS_TRIDENT3X(unit))) {
   2447 #endif
   2448     BCM_IF_ERROR_RETURN
   2449         (bcmi_xgs5_bfd_l2_entry_set(unit,
   2450                                     SHR_BFD_DISCR_UNKNOWN_SESSION_ID,
   2451                                     0, 0, SHR_BFD_DISCR_UNKNOWN_YOUR_DISCR,
   2452                                     BCM_MODID_INVALID, 0,
   2453                                     0, 0));
   2454 #if defined(BCM_TOMAHAWK_SUPPORT)
   2455     }
   2456 #endif
   2457 
   2458     /*
   2459      * BFD COS Queue
   2460      *
   2461      * BFD COSQ will be set to one of the following:
   2462      * - User configured BFD COSq, if provided
   2463      * - The default BFD COS queue.  This is set to the highest queue
   2464      *   available within the queue range assigned to the uC where
   2465      *   the BFD application is running.
   2466      */
   2467 
   2468     /* Get valid range of COS queues for uC where BFD is loaded */
   2469     min_cosq = 0;
   2470 
   2471 #if defined(BCM_TRIDENT3_SUPPORT)
   2472     if(SOC_IS_TRIDENT3X(unit)) {
   2473         num_of_cpu_queues = SOC_TD3_NUM_CPU_QUEUES;
   2474     } else
   2475 #endif
   2476     {
   2477         num_of_cpu_queues = SOC_CMCS_NUM(unit);
   2478     }
   2479     for (i = 0; i < num_of_cpu_queues; i++) {
   2480         num_cosq = NUM_CPU_ARM_COSQ(unit, i);
   2481         if (i == bfd_info->uc_num + 1) {
   2482             break;
   2483         }
   2484         min_cosq += num_cosq;
   2485     }
   2486     max_cosq = min_cosq + num_cosq - 1;
   2487 
   2488     /* Check that there is at least one COS queue assigned to the CMC */
   2489     if (max_cosq < min_cosq) {
   2490         LOG_ERROR(BSL_LS_BCM_COMMON,
   2491                   (BSL_META_U(unit,
   2492                               "ERROR: No BFD COS Queue available from uC%d\n"),
   2493                    bfd_info->uc_num));
   2494         return BCM_E_CONFIG;
   2495     }
   2496 
   2497     /* Check user provide COSQ */
   2498     if (bfd_info->cpu_cosq != BFD_COSQ_INVALID) {
   2499         if ((bfd_info->cpu_cosq < min_cosq) ||
   2500             (bfd_info->cpu_cosq > max_cosq)) {
   2501             return BCM_E_CONFIG;
   2502         }
   2503         min_cosq = max_cosq = bfd_info->cpu_cosq;
   2504     }
   2505 
   2506     /*
   2507      * Assign RX DMA channel to BFD CPU COS Queue
   2508      * (This is the RX channel to listen on for BFD packets).
   2509      *
   2510      * DMA channels (12) are assigned 4 per processor:
   2511      * (see /src/bcm/common/rx.c)
   2512      *   channels 0..3  --> PCI host
   2513      *   channels 4..7  --> uController 0
   2514      *   chnanels 8..11 --> uController 1
   2515      *
   2516      * The uControllers designate the 4 local DMA channels as follows:
   2517      *   local channel  0     --> TX
   2518      *   local channel  1..3  --> RX
   2519      *
   2520      * Each uController application needs to use a different
   2521      * RX DMA channel to listen on.
   2522      */
   2523 #ifdef BCM_CMICX_SUPPORT
   2524     if (soc_feature(unit, soc_feature_cmicx)) {
   2525         max_rx_channels = BCM_CMICX_RX_CHANNELS;
   2526     }
   2527 #endif /* BCM_CMICX_SUPPORT */
   2528 #ifdef BCM_CMICM_SUPPORT
   2529     if (soc_feature(unit, soc_feature_cmicm)) {
   2530         max_rx_channels = BCM_RX_CHANNELS;
   2531     }
   2532 #endif /* BCM_CMICM_SUPPORT */
   2533     chan_id = (max_rx_channels * (SOC_ARM_CMC(unit, bfd_info->uc_num))) +
   2534                bfd_info->rx_channel;
   2535     for (i = max_cosq; i >= min_cosq; i--) {
   2536         rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id);
   2537         if (BCM_SUCCESS(rv)) {
   2538             bfd_info->cpu_cosq = i;  /* COSQ found */
   2539             break;
   2540         }
   2541     }
   2542     if (i < min_cosq) {
   2543         LOG_ERROR(BSL_LS_BCM_COMMON,
   2544                   (BSL_META_U(unit,
   2545                               "ERROR: No BFD COS Queue available from uC%d\n"),
   2546                    bfd_info->uc_num));
   2547         return BCM_E_RESOURCE;    /* Could not find an available COSQ */
   2548     }
   2549 
   2550 #if defined(BCM_TOMAHAWK_SUPPORT)
   2551     if(!(SOC_IS_TOMAHAWKX(unit) ||
   2552          SOC_IS_TRIDENT3X(unit))) {
   2553 #endif
   2554     /*
   2555      * Direct BFD packets to designated RX CPU COS Queue
   2556      *
   2557      * Reasons:
   2558      *   - bcmRxReasonBfdSlowpath
   2559      *         BFD session lookup hit (good packet)
   2560      *   - bcmRxReasonBfd / bcmRxReasonBfdUnknownVersion
   2561      *         BFD error - Unknown ACH Version or Channel Type
   2562      * NOTE:
   2563      *     BFD RX reasons need to be mapped using different indexes
   2564      *     due to HW restriction.
   2565      *
   2566      *     The user input 'cpu_qid' (bcm_bfd_endpoint_t) could be
   2567      *     used to select different CPU COS queue. Currently,
   2568      *     all priorities are mapped into the same CPU COS Queue.
   2569      */
   2570 
   2571     /* Find available entries in CPU COS queue map table */
   2572     slowpath_index   = -1;   /* COSQ map index for good packets */
   2573     ach_err_index    = -1;   /* COSQ map index for unknown ACH error */
   2574     unknown_version_index = -1;
   2575     BCM_IF_ERROR_RETURN
   2576         (bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size));
   2577     
   2578     for (index = 0; index < cosq_map_size; index++) {
   2579         rv = bcm_esw_rx_cosq_mapping_get(unit, index,
   2580                                          &reasons, &reasons_mask,
   2581                                          &int_prio, &int_prio_mask,
   2582                                          &packet_type, &packet_type_mask,
   2583                                          &cosq);
   2584         if (rv == BCM_E_NOT_FOUND) {
   2585             /* Find available indexes for BFD reason codes */
   2586             rv = BCM_E_NONE;
   2587             if (slowpath_index == -1) {
   2588                 slowpath_index = index;
   2589             } else if(ach_err_index == -1){
   2590                 ach_err_index = index;
   2591             } else {
   2592                 unknown_version_index = index;
   2593                 break;
   2594             }
   2595         }
   2596         if (BCM_FAILURE(rv)) {
   2597             return rv;
   2598         }
   2599     }
   2600     if ((slowpath_index == -1) || (ach_err_index == -1) || (
   2601         unknown_version_index == -1)) {
   2602         return BCM_E_RESOURCE;
   2603     }
   2604 
   2605     /*
   2606      * Map RX reason code to RX CPU COS Queue
   2607      */
   2608     BCM_IF_ERROR_RETURN
   2609         (bcm_esw_rx_cosq_mapping_reasons_get(unit, &reasons_all));
   2610 
   2611     /* BFD Slowpath - Lookup hit */
   2612     BCM_RX_REASON_CLEAR_ALL(reasons);
   2613     BCM_RX_REASON_SET(reasons, bcmRxReasonBfdSlowpath);  /* BFD hit, good */
   2614     BCM_IF_ERROR_RETURN
   2615         (bcm_esw_rx_cosq_mapping_set(unit, slowpath_index,
   2616                                      reasons, reasons,
   2617                                      0, 0, /* Any priority */
   2618                                      0, 0, /* Any packet type */
   2619                                      bfd_info->cpu_cosq));
   2620     bfd_info->cosq_spath_index = slowpath_index;
   2621 
   2622     /* BFD Error */
   2623     BCM_RX_REASON_CLEAR_ALL(reasons);
   2624     BCM_RX_REASON_SET(reasons, bcmRxReasonBfd);
   2625     /*
   2626      * ACH Unknown Version or Channel Type
   2627      * Check if reason code is valid, if so, add to BFD error
   2628      */
   2629     if (BCM_RX_REASON_GET(reasons_all, bcmRxReasonBfdUnknownVersion)) {
   2630         BCM_RX_REASON_SET(reasons, bcmRxReasonBfdUnknownVersion);
   2631     }
   2632     BCM_IF_ERROR_RETURN
   2633         (bcm_esw_rx_cosq_mapping_set(unit, ach_err_index,
   2634                                      reasons, reasons,
   2635                                      0, 0, /* Any priority */
   2636                                      0, 0, /* Any packet type */
   2637                                      bfd_info->cpu_cosq));
   2638     bfd_info->cosq_ach_err_index = ach_err_index;
   2639 
   2640     /* Cosq mapping for Rxreason : bcmRxReasonBfdUnknownVersion */
   2641     if(BCM_RX_REASON_GET(reasons_all, bcmRxReasonBfdUnknownVersion)) {
   2642         BCM_RX_REASON_CLEAR_ALL(reasons);
   2643         BCM_RX_REASON_SET(reasons, bcmRxReasonBfdUnknownVersion);
   2644         BCM_IF_ERROR_RETURN
   2645             (bcm_esw_rx_cosq_mapping_set(unit, unknown_version_index,
   2646                                          reasons, reasons,
   2647                                          0, 0, /* Any priority */
   2648                                          0, 0, /* Any packet type */
   2649                                          bfd_info->cpu_cosq));
   2650         bfd_info->cosq_unknown_version_index = unknown_version_index;
   2651     }
   2652 #if defined(BCM_TOMAHAWK_SUPPORT)
   2653     }
   2654 #endif
   2655     return rv;
   2656 }
   2657 
   2658 /*
   2659  * Functions:
   2660  *      bcmi_xgs5_bfd_<header/label>_pack
   2661  * Purpose:
   2662  *      The following set of _pack() functions packs in
   2663  *      network byte order a given header/label.
   2664  * Parameters:
   2665  *      buffer          - (OUT) Buffer where to pack header/label.
   2666  *      <header/label>  - (IN) Header/label to pack.
   2667  * Returns:
   2668  *      Pointer to next position in buffer.
   2669  * Notes:
   2670  */
   2671 STATIC uint8 *
   2672 bcmi_xgs5_bfd_udp_header_pack(uint8 *buffer, bfd_udp_header_t *udp)
   2673 {
   2674     BFD_ENCAP_PACK_U16(buffer, udp->src);
   2675     BFD_ENCAP_PACK_U16(buffer, udp->dst);
   2676     BFD_ENCAP_PACK_U16(buffer, udp->length);
   2677     BFD_ENCAP_PACK_U16(buffer, udp->sum);
   2678 
   2679     return buffer;
   2680 }
   2681 
   2682 STATIC uint8 *
   2683 bcmi_xgs5_bfd_ipv4_header_pack(uint8 *buffer, bfd_ipv4_header_t *ip)
   2684 {
   2685     uint32  tmp;
   2686 
   2687     tmp = ((ip->version & 0xf) << 28) | ((ip->h_length & 0xf) << 24) |
   2688         ((ip->dscp & 0x3f) << 18) | ((ip->ecn & 0x3)<< 16) | (ip->length);
   2689     BFD_ENCAP_PACK_U32(buffer, tmp);
   2690 
   2691     tmp = (ip->id << 16) | ((ip->flags & 0x7) << 13) | (ip->f_offset & 0x1fff);
   2692     BFD_ENCAP_PACK_U32(buffer, tmp);
   2693 
   2694     tmp = (ip->ttl << 24) | (ip->protocol << 16) | ip->sum;
   2695     BFD_ENCAP_PACK_U32(buffer, tmp);
   2696 
   2697     BFD_ENCAP_PACK_U32(buffer, ip->src);
   2698     BFD_ENCAP_PACK_U32(buffer, ip->dst);
   2699 
   2700     return buffer;
   2701 }
   2702 
   2703 STATIC uint8 *
   2704 bcmi_xgs5_bfd_ipv6_header_pack(uint8 *buffer, bfd_ipv6_header_t *ip)
   2705 {
   2706     uint32  tmp;
   2707     int     i;
   2708 
   2709     tmp = ((ip->version & 0xf) << 28) | (ip->t_class << 20) |
   2710         (ip->f_label & 0xfffff);
   2711     BFD_ENCAP_PACK_U32(buffer, tmp);
   2712 
   2713     tmp = (ip->p_length << 16 ) | (ip->next_header << 8) | ip->hop_limit;
   2714     BFD_ENCAP_PACK_U32(buffer, tmp);
   2715 
   2716     for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
   2717         BFD_ENCAP_PACK_U8(buffer, ip->src[i]);
   2718     }
   2719 
   2720     for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
   2721         BFD_ENCAP_PACK_U8(buffer, ip->dst[i]);
   2722     }
   2723 
   2724     return buffer;
   2725 }
   2726 
   2727 STATIC uint8 *
   2728 bcmi_xgs5_bfd_gre_header_pack(uint8 *buffer, bfd_gre_header_t *gre)
   2729 {
   2730     uint32  tmp;
   2731 
   2732     tmp = ((gre->checksum & 0x1) << 31) | ((gre->routing & 0x1) << 30) |
   2733         ((gre->key & 0x1) << 29) | ((gre->sequence_num & 0x1) << 28) | 
   2734         ((gre->strict_src_route & 0x1) << 27) |
   2735         ((gre->recursion_control & 0x7) << 24) | ((gre->flags & 0x1f) << 19) |
   2736         ((gre->version & 0x7) << 16) | (gre->protocol & 0xffff);
   2737 
   2738     BFD_ENCAP_PACK_U32(buffer, tmp);
   2739 
   2740     return buffer;
   2741 }
   2742 
   2743 STATIC uint8 *
   2744 bcmi_xgs5_bfd_ach_header_pack(uint8 *buffer, bfd_ach_header_t *ach)
   2745 {
   2746     uint32  tmp;
   2747 
   2748     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
   2749         (ach->reserved << 16) | ach->channel_type;
   2750 
   2751     BFD_ENCAP_PACK_U32(buffer, tmp);
   2752 
   2753     return buffer;
   2754 }
   2755 
   2756 STATIC uint8 *
   2757 bcmi_xgs5_bfd_mpls_label_pack(uint8 *buffer, bfd_mpls_label_t *mpls)
   2758 {
   2759     uint32  tmp;
   2760 
   2761     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
   2762         ((mpls->s & 0x1) << 8) | mpls->ttl;
   2763     BFD_ENCAP_PACK_U32(buffer, tmp);
   2764 
   2765     return buffer;
   2766 }
   2767 
   2768 STATIC uint8 *
   2769 bcmi_xgs5_bfd_l2_header_pack(uint8 *buffer, bfd_l2_header_t *l2)
   2770 {
   2771     uint32  tmp;
   2772     int     i;
   2773 
   2774     for (i = 0; i < BFD_MAC_ADDR_LENGTH; i++) {
   2775         BFD_ENCAP_PACK_U8(buffer, l2->dst_mac[i]);
   2776     }
   2777 
   2778     for (i = 0; i < BFD_MAC_ADDR_LENGTH; i++) {
   2779         BFD_ENCAP_PACK_U8(buffer, l2->src_mac[i]);
   2780     }
   2781 
   2782     /*
   2783      * VLAN Tag
   2784      *
   2785      * A TPID value of 0 indicates this is an untagged frame.
   2786      */
   2787     if (l2->outer_vlan_tag.tpid != 0) {
   2788         /* Add VLAN tag */
   2789         tmp = (l2->outer_vlan_tag.tpid << 16) |
   2790             ((l2->outer_vlan_tag.tci.prio & 0x7) << 13) |
   2791             ((l2->outer_vlan_tag.tci.cfi & 0x1) << 12) |
   2792             (l2->outer_vlan_tag.tci.vid & 0xfff);
   2793         BFD_ENCAP_PACK_U32(buffer, tmp);
   2794     }
   2795 
   2796     /* Packet inner vlan tag */
   2797 
   2798     if (l2->inner_vlan_tag.tpid != 0) {
   2799         /* Add VLAN tag */
   2800         tmp = (l2->inner_vlan_tag.tpid << 16) |
   2801             ((l2->inner_vlan_tag.tci.prio & 0x7) << 13) |
   2802             ((l2->inner_vlan_tag.tci.cfi & 0x1) << 12) |
   2803             (l2->inner_vlan_tag.tci.vid & 0xfff);
   2804         BFD_ENCAP_PACK_U32(buffer, tmp);
   2805     }
   2806 
   2807     BFD_ENCAP_PACK_U16(buffer, l2->etype);
   2808 
   2809     return buffer;
   2810 }
   2811 
   2812 STATIC uint8 *
   2813 bcmi_xgs5_bfd_hg_header_pack(uint8 *buffer, int unit,
   2814                              bfd_endpoint_config_t *endpoint_config,
   2815                              bfd_l2_header_t *l2)
   2816 {
   2817     soc_higig_hdr_t *hg = (soc_higig_hdr_t *)buffer;
   2818     int hg_size;
   2819     int src_mod;
   2820     int src_port;
   2821     int dst_mod;
   2822     int dst_port;
   2823     uint32 vlan_val;
   2824     uint32 prio_val;
   2825     uint32 pfm;
   2826 
   2827     hg_size = sizeof(*hg);
   2828 
   2829     if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &src_mod))) {
   2830         return NULL;
   2831     }
   2832     src_port = endpoint_config->tx_port;
   2833     dst_mod  = endpoint_config->modid;
   2834     dst_port = endpoint_config->port;
   2835     vlan_val = l2->outer_vlan_tag.tci.vid;
   2836     pfm      = SOC_DEFAULT_DMA_PFM_GET(unit);
   2837     prio_val = endpoint_config->info.int_pri;
   2838 
   2839     sal_memset(hg, 0, hg_size);
   2840     soc_higig_field_set(unit, hg, HG_start, SOC_HIGIG_START);
   2841     soc_higig_field_set(unit, hg, HG_hgi, SOC_HIGIG_HGI);
   2842     soc_higig_field_set(unit, hg, HG_opcode, SOC_HIGIG_OP_UC);
   2843     soc_higig_field_set(unit, hg, HG_hdr_format, SOC_HIGIG_HDR_DEFAULT);
   2844     soc_higig_field_set(unit, hg, HG_vlan_tag, vlan_val);
   2845     soc_higig_field_set(unit, hg, HG_dst_mod, dst_mod);
   2846     soc_higig_field_set(unit, hg, HG_dst_port, dst_port);
   2847     soc_higig_field_set(unit, hg, HG_src_mod, src_mod);
   2848     soc_higig_field_set(unit, hg, HG_src_port, src_port);
   2849     soc_higig_field_set(unit, hg, HG_pfm, pfm);
   2850     soc_higig_field_set(unit, hg, HG_cos, prio_val);
   2851 
   2852     if (l2->inner_vlan_tag.tpid != 0) {
   2853         soc_higig_field_set(unit, hg, HG_ingress_tagged, 1);
   2854     }   
   2855 
   2856     buffer += hg_size;
   2857 
   2858     return buffer;
   2859 }
   2860 
   2861 STATIC uint8 *
   2862 bcmi_xgs5_bfd_hg2_header_pack(uint8 *buffer, int unit,
   2863                               bfd_endpoint_config_t *endpoint_config,
   2864                               bfd_l2_header_t *l2)
   2865 {
   2866     soc_higig2_hdr_t *hg = (soc_higig2_hdr_t *)buffer;
   2867     int hg_size;
   2868     int src_mod;
   2869     int src_port;
   2870     int dst_mod;
   2871     int dst_port;
   2872     uint32 vlan_val;
   2873     uint32 prio_val;
   2874     uint32 pfm;
   2875     uint32 ppd;
   2876 
   2877     hg_size = sizeof(*hg);
   2878 
   2879     if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &src_mod))) {
   2880         return NULL;
   2881     }
   2882     src_port = endpoint_config->tx_port;
   2883     dst_mod  = endpoint_config->modid;
   2884     dst_port = endpoint_config->port;
   2885     vlan_val = l2->outer_vlan_tag.tci.vid;
   2886     pfm      = SOC_DEFAULT_DMA_PFM_GET(unit);
   2887     prio_val = endpoint_config->info.int_pri;
   2888     ppd      = 0;
   2889 
   2890     sal_memset(hg, 0, hg_size);
   2891     soc_higig2_field_set(unit, hg, HG_start, SOC_HIGIG2_START);
   2892     soc_higig2_field_set(unit, hg, HG_ppd_type, ppd);
   2893     soc_higig2_field_set(unit, hg, HG_opcode, SOC_HIGIG_OP_UC);
   2894     soc_higig2_field_set(unit, hg, HG_vlan_tag, vlan_val);
   2895     soc_higig2_field_set(unit, hg, HG_dst_mod, dst_mod);
   2896     soc_higig2_field_set(unit, hg, HG_dst_port, dst_port);
   2897     soc_higig2_field_set(unit, hg, HG_src_mod, src_mod);
   2898     soc_higig2_field_set(unit, hg, HG_src_port, src_port);
   2899     soc_higig2_field_set(unit, hg, HG_pfm, pfm);
   2900     soc_higig2_field_set(unit, hg, HG_tc, prio_val);
   2901 
   2902     if (l2->inner_vlan_tag.tpid != 0) {
   2903         soc_higig2_field_set(unit, hg, HG_ingress_tagged, 1);
   2904     }   
   2905 
   2906     buffer += hg_size;
   2907 
   2908     return buffer;
   2909 }
   2910 
   2911 /*
   2912  * Function:
   2913  *      bcmi_xgs5_bfd_udp_checksum_set
   2914  * Purpose:
   2915  *      Set the UDP initial checksum (excludes checksum for the data).
   2916  *
   2917  *      The checksum includes the IP pseudo-header and UDP header.
   2918  *      It does not include the checksum for the data (BFD packet).
   2919  *      The data checksum will be added to UDP initial checksum in
   2920  *      the uC side each time a packet is sent, since data payload may vary.
   2921  * Parameters:
   2922  *      v6              - (IN) Set if IP is IPv6.
   2923  *      ipv4            - (IN) IPv4 header.
   2924  *      ipv6            - (IN) IPv6 header.
   2925  *      udp             - (IN/OUT) UDP header checksum to update.
   2926  * Returns:
   2927  *      None
   2928  */
   2929 STATIC void
   2930 bcmi_xgs5_bfd_udp_checksum_set(int v6,
   2931                                bfd_ipv4_header_t *ipv4,
   2932                                bfd_ipv6_header_t *ipv6,
   2933                                bfd_udp_header_t *udp)
   2934 {
   2935     uint8  buffer[SHR_BFD_UDP_HEADER_LENGTH + (BCM_IP6_ADDRLEN*2) + 8];
   2936     uint8  *cur_ptr = buffer;
   2937     int    i, length;
   2938 
   2939     /* Build IP Pseudo-Header */
   2940     if (v6) {
   2941         /* IPv6 Pseudo-Header
   2942          *     Source address
   2943          *     Destination address
   2944          *     UDP length  (32-bit)
   2945          *     Zeroes(24 bit)
   2946          *     Next Header (lower 8 bits of 32-bit)
   2947          */
   2948         for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
   2949             BFD_ENCAP_PACK_U8(cur_ptr, ipv6->src[i]);
   2950         }
   2951         for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
   2952             BFD_ENCAP_PACK_U8(cur_ptr, ipv6->dst[i]);
   2953         }
   2954         /* UDP length though is actually only 16 bits,
   2955          * is 32 bits in the IPv6 pseudo header format.
   2956          * So adding first 16 bits with 0.
   2957          */
   2958         BFD_ENCAP_PACK_U16(cur_ptr, 0);
   2959         BFD_ENCAP_PACK_U16(cur_ptr, udp->length);
   2960         /* Zeroes */
   2961         BFD_ENCAP_PACK_U16(cur_ptr, 0);
   2962         BFD_ENCAP_PACK_U8(cur_ptr,  0);
   2963         /* last 8 bits of the 32 bit protocol field. */
   2964         BFD_ENCAP_PACK_U8(cur_ptr, ipv6->next_header);
   2965     } else {
   2966         /* IPv4 Pseudo-Header
   2967          *     Source address
   2968          *     Destination address
   2969          *     Protocol    (8 bits)
   2970          *     UDP length  (16-bit)
   2971          */
   2972         BFD_ENCAP_PACK_U32(cur_ptr, ipv4->src);
   2973         BFD_ENCAP_PACK_U32(cur_ptr, ipv4->dst);
   2974         /* 
   2975          * Added 0 before protcol value to compute checksum
   2976          * accurately 
   2977          */ 
   2978         BFD_ENCAP_PACK_U8(cur_ptr, 0);
   2979         BFD_ENCAP_PACK_U8(cur_ptr, ipv4->protocol);
   2980         BFD_ENCAP_PACK_U16(cur_ptr, udp->length);
   2981     }
   2982 
   2983     /* Add UDP header */
   2984     cur_ptr = bcmi_xgs5_bfd_udp_header_pack(cur_ptr, udp);
   2985 
   2986     /* Calculate initial UDP checksum */
   2987     length = cur_ptr - buffer;
   2988     udp->sum = _shr_ip_chksum(length, buffer);
   2989 }
   2990 
   2991 /*
   2992  * Functions:
   2993  *      bcmi_xgs5_bfd_<header/label>_get
   2994  * Purpose:
   2995  *      The following set of _get() functions builds a given header/label.
   2996  * Parameters:
   2997  *      unit            - (IN) Unit number.
   2998  *      endpoint_config - (IN) Pointer to BFD endpoint structure.
   2999  *      packet_flags    - (IN) Flags for building packet.
   3000  *      <... other IN args ...>
   3001  *      <header/label>  - (OUT) Returns header/label.
   3002  * Returns:
   3003  *      BCM_E_XXX
   3004  * Notes:
   3005  */
   3006 STATIC int
   3007 bcmi_xgs5_bfd_udp_header_get(int unit, bcm_bfd_endpoint_info_t *endpoint_info,
   3008                              uint32 packet_flags, bfd_udp_header_t *udp)
   3009 {
   3010     bfd_info_t *bfd_info = BFD_INFO(unit);
   3011     int auth_length;
   3012     int bfd_length;
   3013 
   3014     /* Calculate BFD packet length */
   3015     /* Authentication (optional) */
   3016     switch (endpoint_info->auth) {
   3017     case _SHR_BFD_AUTH_TYPE_SIMPLE_PASSWORD:
   3018         auth_length = SHR_BFD_AUTH_SP_HEADER_START_LENGTH +
   3019             bfd_info->auth_sp[endpoint_info->auth_index].length;
   3020         break;
   3021     case _SHR_BFD_AUTH_TYPE_KEYED_SHA1:
   3022     case _SHR_BFD_AUTH_TYPE_METICULOUS_KEYED_SHA1:
   3023         auth_length = SHR_BFD_AUTH_SHA1_LENGTH;
   3024         break;
   3025     default:
   3026         auth_length = 0;
   3027         break;
   3028     }
   3029     bfd_length = SHR_BFD_CONTROL_HEADER_LENGTH + auth_length;
   3030 
   3031     /* Set UDP */
   3032     sal_memset(udp, 0, sizeof(*udp));
   3033     udp->src = endpoint_info->udp_src_port;
   3034     udp->dst = ((packet_flags  & BFD_ENCAP_PKT_UDP_MICRO_BFD) ? SHR_MICRO_BFD_DEST_PORT :
   3035          ((packet_flags & BFD_ENCAP_PKT_UDP__MULTI_HOP) ?
   3036          SHR_BFD_UDP_MULTI_HOP_DEST_PORT : SHR_BFD_UDP_SINGLE_HOP_DEST_PORT));
   3037     udp->length = SHR_BFD_UDP_HEADER_LENGTH + bfd_length;
   3038     udp->sum = 0;    /* Calculated later */
   3039 
   3040     return BCM_E_NONE;
   3041 }
   3042 
   3043 STATIC int
   3044 bcmi_xgs5_bfd_ipv4_header_get(int data_length, uint8 protocol,
   3045                               uint8 tos, uint8 ttl,
   3046                               bcm_ip_t src_ip_addr, bcm_ip_t dst_ip_addr,
   3047                               bfd_ipv4_header_t *ip)
   3048 {
   3049     uint8 buffer[SHR_BFD_IPV4_HEADER_LENGTH];
   3050 
   3051     sal_memset(ip, 0, sizeof(*ip));
   3052 
   3053     ip->version  = SHR_BFD_IPV4_VERSION;
   3054     ip->h_length = SHR_BFD_IPV4_HEADER_LENGTH_WORDS;
   3055     ip->dscp     = tos;
   3056     ip->ecn      = 0;
   3057     ip->length   = SHR_BFD_IPV4_HEADER_LENGTH + data_length;
   3058     ip->id       = 0;
   3059     ip->flags    = 0;
   3060     ip->f_offset = 0;
   3061     ip->ttl      = ttl;
   3062     ip->protocol = protocol;
   3063     ip->sum      = 0;
   3064     ip->src      = src_ip_addr;
   3065     ip->dst      = dst_ip_addr;
   3066 
   3067     /* Calculate IP header checksum */
   3068     bcmi_xgs5_bfd_ipv4_header_pack(buffer, ip);
   3069     ip->sum = _shr_ip_chksum(SHR_BFD_IPV4_HEADER_LENGTH, buffer);
   3070 
   3071     return BCM_E_NONE;
   3072 }
   3073 
   3074 STATIC int
   3075 bcmi_xgs5_bfd_ipv6_header_get(int data_length, uint8 protocol,
   3076                               uint8 tos, uint8 ttl,
   3077                               bcm_ip6_t src_ip_addr, bcm_ip6_t dst_ip_addr,
   3078                               bfd_ipv6_header_t *ip)
   3079 {
   3080     sal_memset(ip, 0, sizeof(*ip));
   3081 
   3082     ip->version     = SHR_BFD_IPV6_VERSION;
   3083     ip->t_class     = tos << 2;
   3084     ip->f_label     = 0;  
   3085     ip->p_length    = data_length;
   3086     ip->next_header = protocol;
   3087     ip->hop_limit   = ttl;
   3088     sal_memcpy(ip->src, src_ip_addr, BCM_IP6_ADDRLEN);
   3089     sal_memcpy(ip->dst, dst_ip_addr, BCM_IP6_ADDRLEN);
   3090 
   3091     return BCM_E_NONE;
   3092 }
   3093 
   3094 STATIC int
   3095 bcmi_xgs5_bfd_ip_headers_get(bcm_bfd_endpoint_info_t *endpoint_info,
   3096                              uint32 packet_flags,
   3097                              int udp_length,
   3098                              uint16 *etype,
   3099                              bfd_ipv4_header_t *ipv4, bfd_ipv6_header_t *ipv6,
   3100                              bfd_ipv4_header_t *inner_ipv4,
   3101                              bfd_ipv6_header_t *inner_ipv6)
   3102 {
   3103     int ip_protocol;
   3104     int ip_length;
   3105 
   3106     if (!(packet_flags & BFD_ENCAP_PKT_IP)) {
   3107         return BCM_E_PARAM;
   3108     }
   3109 
   3110     /* Inner IP Header (IP-in-IP/GRE) */
   3111     if (packet_flags & BFD_ENCAP_PKT_INNER_IP) {
   3112 
   3113         if (packet_flags & BFD_ENCAP_PKT_INNER_IP__V6) {
   3114             ip_protocol = SHR_BFD_IP_PROTOCOL_IPV6_ENCAP;
   3115             ip_length   = udp_length + SHR_BFD_IPV6_HEADER_LENGTH;
   3116             BCM_IF_ERROR_RETURN
   3117                 (bcmi_xgs5_bfd_ipv6_header_get
   3118                  (udp_length,
   3119                   SHR_BFD_IP_PROTOCOL_UDP,
   3120                   endpoint_info->inner_ip_tos,
   3121                   endpoint_info->inner_ip_ttl,
   3122                   endpoint_info->inner_src_ip6_addr,
   3123                   endpoint_info->inner_dst_ip6_addr,
   3124                   inner_ipv6));
   3125         } else {
   3126             ip_protocol = SHR_BFD_IP_PROTOCOL_IPV4_ENCAP;
   3127             ip_length   = udp_length + SHR_BFD_IPV4_HEADER_LENGTH;
   3128             BCM_IF_ERROR_RETURN
   3129                 (bcmi_xgs5_bfd_ipv4_header_get
   3130                  (udp_length,
   3131                   SHR_BFD_IP_PROTOCOL_UDP,
   3132                   endpoint_info->inner_ip_tos,
   3133                   endpoint_info->inner_ip_ttl,
   3134                   endpoint_info->inner_src_ip_addr,
   3135                   endpoint_info->inner_dst_ip_addr,
   3136                   inner_ipv4));
   3137         }
   3138     } else {
   3139         ip_protocol = SHR_BFD_IP_PROTOCOL_UDP;
   3140         ip_length   = udp_length;
   3141     }
   3142 
   3143     /* If GRE is present, GRE the protocol that follows the outer IP header */
   3144     if (packet_flags & BFD_ENCAP_PKT_GRE) {
   3145         ip_protocol = SHR_BFD_IP_PROTOCOL_GRE;
   3146         ip_length   = udp_length + SHR_BFD_GRE_HEADER_LENGTH;
   3147         if (packet_flags & BFD_ENCAP_PKT_INNER_IP__V6) {
   3148             ip_length += SHR_BFD_IPV6_HEADER_LENGTH;
   3149         } else {
   3150             ip_length += SHR_BFD_IPV4_HEADER_LENGTH;
   3151         }
   3152     }
   3153 
   3154     /* Outer IP Header */
   3155     if (packet_flags & BFD_ENCAP_PKT_IP__V6) {
   3156         *etype = SHR_BFD_L2_ETYPE_IPV6;
   3157         BCM_IF_ERROR_RETURN
   3158             (bcmi_xgs5_bfd_ipv6_header_get(ip_length,
   3159                                            ip_protocol,
   3160                                            endpoint_info->ip_tos,
   3161                                            endpoint_info->ip_ttl,
   3162                                            endpoint_info->src_ip6_addr,
   3163                                            endpoint_info->dst_ip6_addr,
   3164                                            ipv6));
   3165     } else {
   3166         *etype = SHR_BFD_L2_ETYPE_IPV4;
   3167         BCM_IF_ERROR_RETURN
   3168             (bcmi_xgs5_bfd_ipv4_header_get(ip_length,
   3169                                            ip_protocol,
   3170                                            endpoint_info->ip_tos,
   3171                                            endpoint_info->ip_ttl,
   3172                                            endpoint_info->src_ip_addr,
   3173                                            endpoint_info->dst_ip_addr,
   3174                                            ipv4));
   3175     }
   3176 
   3177     return BCM_E_NONE;
   3178 }
   3179 
   3180 STATIC int
   3181 bcmi_xgs5_bfd_gre_header_get(uint32 packet_flags, bfd_gre_header_t *gre)
   3182 {
   3183     sal_memset(gre, 0, sizeof(*gre));
   3184 
   3185     gre->checksum          = 0;
   3186     gre->routing           = 0;
   3187     gre->key               = 0;
   3188     gre->sequence_num      = 0;
   3189     gre->strict_src_route  = 0;
   3190     gre->recursion_control = 0;
   3191     gre->flags             = 0;
   3192     gre->version           = 0;
   3193     if (packet_flags & BFD_ENCAP_PKT_INNER_IP__V6) {
   3194         gre->protocol = SHR_BFD_L2_ETYPE_IPV6;
   3195     } else {
   3196         gre->protocol = SHR_BFD_L2_ETYPE_IPV4;
   3197     }
   3198 
   3199     return BCM_E_NONE;
   3200 }
   3201 
   3202 STATIC int
   3203 bcmi_xgs5_bfd_ach_header_get(uint32 packet_flags, bfd_ach_header_t *ach)
   3204 {
   3205     sal_memset(ach, 0, sizeof(*ach));
   3206 
   3207     ach->f_nibble = SHR_BFD_ACH_FIRST_NIBBLE;
   3208     ach->version  = SHR_BFD_ACH_VERSION;
   3209     ach->reserved = 0;
   3210 
   3211     if (packet_flags & BFD_ENCAP_PKT_G_ACH__IP) {    /* UDP/IP */
   3212         if (packet_flags & BFD_ENCAP_PKT_IP__V6) {
   3213             ach->channel_type = SHR_BFD_ACH_CHANNEL_TYPE_IPV6;
   3214         } else {
   3215             ach->channel_type = SHR_BFD_ACH_CHANNEL_TYPE_IPV4;
   3216         }
   3217 
   3218     } else if (packet_flags & BFD_ENCAP_PKT_G_ACH__CC) { /* MPLS-TP CC only */
   3219         ach->channel_type = SHR_BFD_ACH_CHANNEL_TYPE_MPLS_TP_CC;
   3220 
   3221     } else if (packet_flags & BFD_ENCAP_PKT_G_ACH__CC_CV) { /* MPLS-TP CC/CV */
   3222         /*
   3223          * CC/CV is done by interleaving CC and CV PDUs.
   3224          * Set CC channel type as a start.
   3225          * BFD engine (uKernel) will set appropriate channel types.
   3226          * One CV PDU is inserted every second.
   3227          */
   3228         ach->channel_type = SHR_BFD_ACH_CHANNEL_TYPE_MPLS_TP_CC;
   3229 
   3230     } else {    /* Raw */
   3231         ach->channel_type = SHR_BFD_ACH_CHANNEL_TYPE_RAW;
   3232     }
   3233 
   3234     return BCM_E_NONE;
   3235 }
   3236 
   3237 STATIC int
   3238 bcmi_xgs5_bfd_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl,
   3239                              bfd_mpls_label_t *mpls)
   3240 {
   3241     sal_memset(mpls, 0, sizeof(*mpls));
   3242 
   3243     mpls->label = label;
   3244     mpls->exp   = exp;
   3245     mpls->s     = s;
   3246     mpls->ttl   = ttl;
   3247 
   3248     return BCM_E_NONE;
   3249 }
   3250 
   3251 STATIC int
   3252 bcmi_xgs5_bfd_mpls_gal_label_get(bfd_mpls_label_t *mpls,
   3253                                  bcm_bfd_endpoint_info_t *endpoint_info)
   3254 {
   3255     uint8 exp = 0;
   3256     uint8 ttl = 0;
   3257     uint8 user_specified_exp = 0;
   3258     uint8 user_specified_ttl = 0;
   3259     uint32 user_gal_label = 0;
   3260     uint8 *gal_label_info = (uint8 *)&user_gal_label;
   3261 
   3262 #ifdef LE_HOST
   3263     user_gal_label =  _shr_swap32(endpoint_info->gal_label);
   3264 #else
   3265     user_gal_label = endpoint_info->gal_label;
   3266 #endif
   3267 
   3268     /* Decode 32bit gal label,  parse the exp, ttl value and ignore gal label field */
   3269     user_specified_exp = (gal_label_info[2] >> 1) & 0x7;
   3270     user_specified_ttl = gal_label_info[3];
   3271 
   3272     exp = user_specified_exp?user_specified_exp:0;
   3273     ttl = user_specified_ttl?user_specified_ttl:1;
   3274 
   3275     /* Always gal_exp holds 3 bit value, range 0 to 7 */
   3276     return bcmi_xgs5_bfd_mpls_label_get(SHR_BFD_MPLS_GAL_LABEL,
   3277                                         exp, 1, ttl, mpls);
   3278 }
   3279 
   3280 STATIC int
   3281 bcmi_xgs5_bfd_mpls_router_alert_label_get(bfd_mpls_label_t *mpls)
   3282 {
   3283     return bcmi_xgs5_bfd_mpls_label_get(SHR_BFD_MPLS_ROUTER_ALERT_LABEL,
   3284                                         0, 0, 1, mpls);
   3285 }
   3286 
   3287 STATIC int
   3288 bcmi_xgs5_bfd_mpls_labels_get(int unit, bcm_bfd_endpoint_info_t *endpoint_info,
   3289                               uint32 packet_flags,
   3290                               int max_count, bfd_mpls_label_t *mpls,
   3291                               int *mpls_count)
   3292 {
   3293     int count = 0;
   3294     bcm_l3_egress_t l3_egress;
   3295     bcm_mpls_port_t mpls_port;
   3296     bcm_mpls_egress_label_t label_array[BFD_MPLS_MAX_LABELS];
   3297     int label_count;
   3298     int i;
   3299 
   3300     /* Get MPLS Tunnel Label(s) */
   3301     bcm_l3_egress_t_init(&l3_egress);
   3302     if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, endpoint_info->egress_if,
   3303                                           &l3_egress))) {
   3304         return BCM_E_PARAM;
   3305     }
   3306 
   3307     /* Look for a tunnel associated with this interface */
   3308     if (BCM_SUCCESS
   3309         (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf,
   3310                                            BFD_MPLS_MAX_LABELS,
   3311                                            label_array, &label_count))) {
   3312         for (i = 0; (i < label_count) && (count < max_count); i++) {
   3313              if (label_array[i].label) {
   3314                  bcmi_xgs5_bfd_mpls_label_get(label_array[i].label,
   3315                                               label_array[i].exp,
   3316                                               0,
   3317                                               label_array[i].ttl,
   3318                                               &mpls[count++]);
   3319              }
   3320         }
   3321     } else {
   3322         LOG_ERROR(BSL_LS_BCM_BFD,
   3323                   (BSL_META_U(unit,
   3324                               "MPLS tunnel initiator information get failed\n")));
   3325         return BCM_E_PARAM;
   3326     }
   3327 
   3328     /* MPLS Router Alert */
   3329     if (packet_flags & BFD_ENCAP_PKT_MPLS_ROUTER_ALERT) {
   3330         bcmi_xgs5_bfd_mpls_router_alert_label_get(&mpls[count++]);
   3331     }
   3332 
   3333     /* Get L2 VPN PW VC label */
   3334     if (BCM_GPORT_IS_MPLS_PORT(endpoint_info->gport)) {
   3335         /* Get mpls port and label info */
   3336         bcm_mpls_port_t_init(&mpls_port);
   3337         mpls_port.mpls_port_id = endpoint_info->gport;
   3338         if (BCM_FAILURE
   3339             (bcm_esw_mpls_port_get(unit, endpoint_info->vpn,
   3340                                    &mpls_port))) {
   3341             return BCM_E_PARAM;
   3342         } else {
   3343             if (endpoint_info->type == bcmBFDTunnelTypePweTtl) {
   3344                 mpls_port.egress_label.ttl = 0x1;
   3345             }
   3346 
   3347             bcmi_xgs5_bfd_mpls_label_get(mpls_port.egress_label.label,
   3348                                          mpls_port.egress_label.exp,
   3349                                          0,
   3350                                          mpls_port.egress_label.ttl,
   3351                                          &mpls[count++]);
   3352         }
   3353     }
   3354 
   3355     /* Set Bottom of Stack if there is no GAL label */
   3356     if (!(packet_flags & BFD_ENCAP_PKT_GAL)) {
   3357         mpls[count-1].s = 1;
   3358     }
   3359 
   3360     *mpls_count = count;
   3361 
   3362     return BCM_E_NONE;
   3363 
   3364 }
   3365 
   3366 STATIC int
   3367 bcmi_xgs5_bfd_l2_header_get(int unit, bcm_bfd_endpoint_info_t *endpoint_info,
   3368                             uint32 packet_flags, bcm_port_t port,
   3369                             uint16 etype, bfd_l2_header_t *l2)
   3370 {
   3371     uint16 tpid;
   3372     bcm_l3_egress_t l3_egress;
   3373     bcm_l3_intf_t l3_intf;
   3374     int tpid_select;
   3375     bcm_vlan_control_vlan_t vc;
   3376     bcm_pbmp_t pbmp, ubmp;
   3377 
   3378     sal_memset(l2, 0, sizeof(*l2));
   3379 
   3380     /* Get L3 interfaces */
   3381     bcm_l3_egress_t_init(&l3_egress);
   3382     bcm_l3_intf_t_init(&l3_intf);
   3383 
   3384     if (BCM_FAILURE
   3385         (bcm_esw_l3_egress_get(unit, endpoint_info->egress_if, &l3_egress))) {
   3386         return BCM_E_PARAM;
   3387     }
   3388 
   3389     l3_intf.l3a_intf_id = l3_egress.intf;
   3390     if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) {
   3391         return BCM_E_PARAM;
   3392     }
   3393 
   3394     /* Get TPID */
   3395     if (BCM_FAILURE
   3396         (bcm_esw_vlan_control_port_get(unit, port, bcmVlanPortOuterTpidSelect,
   3397             &tpid_select))) {
   3398         return BCM_E_INTERNAL; 
   3399     }     
   3400     
   3401     if (tpid_select == BCM_PORT_OUTER_TPID) { 
   3402     if (BCM_FAILURE(bcm_esw_port_tpid_get(unit, port, &tpid))) {
   3403         return BCM_E_INTERNAL;
   3404     }
   3405     } else {
   3406         if (BCM_FAILURE
   3407             (bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc))) {
   3408             return BCM_E_INTERNAL;
   3409         }
   3410         tpid = vc.outer_tpid; 
   3411     }
   3412 
   3413     /* Destination and Source MAC */
   3414     sal_memcpy(l2->dst_mac, l3_egress.mac_addr, BFD_MAC_ADDR_LENGTH);
   3415     sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, BFD_MAC_ADDR_LENGTH);
   3416 
   3417     /*
   3418      * VLAN Tag
   3419      */
   3420     l2->outer_vlan_tag.tpid     = tpid;
   3421     l2->outer_vlan_tag.tci.vid  = l3_intf.l3a_vid;
   3422     l2->outer_vlan_tag.tci.prio = endpoint_info->vlan_pri;
   3423     l2->outer_vlan_tag.tci.cfi  = 0;
   3424 
   3425     BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit,
   3426                                               l2->outer_vlan_tag.tci.vid,
   3427                                               &pbmp,
   3428                                               &ubmp));
   3429 
   3430     if ((endpoint_info->flags & BCM_BFD_ENDPOINT_USE_PKT_VLAN_ID) &&
   3431         (endpoint_info->type == bcmBFDTunnelTypeUdp)) {
   3432         /*
   3433          * Check the outer vlan id status, being set in BFD Tx pkt
   3434          * Whether it's set by pkt_vlan_id or default l3 interface
   3435          */
   3436         l2->outer_vlan_tag.tci.vid  = endpoint_info->pkt_vlan_id;
   3437     } else if (BCM_PBMP_MEMBER(ubmp, port)) {
   3438         /* Set to 0 to indicate untagged */
   3439         l2->outer_vlan_tag.tpid = 0;
   3440     }
   3441 
   3442     if (l3_intf.l3a_inner_vlan != 0) {
   3443         if (BCM_FAILURE(bcm_esw_port_inner_tpid_get(unit, port, &tpid))) {
   3444             return BCM_E_INTERNAL;
   3445         }
   3446         l2->inner_vlan_tag.tpid     = tpid;
   3447         l2->inner_vlan_tag.tci.prio = endpoint_info->inner_vlan_pri;
   3448         l2->inner_vlan_tag.tci.cfi  = 0;
   3449         l2->inner_vlan_tag.tci.vid  = l3_intf.l3a_inner_vlan;
   3450     } else {
   3451         l2->inner_vlan_tag.tpid = 0;  /* Set to 0 to indicate untagged */
   3452     }
   3453 
   3454     /* Ether Type */
   3455     l2->etype = etype;
   3456 
   3457     return BCM_E_NONE;
   3458 }
   3459 
   3460 /*
   3461  * Function:
   3462  *      bcmi_xgs5_bfd_encap_build_pack
   3463  * Purpose:
   3464  *      Builds and packs the BFD packet encapsulation for a given
   3465  *      BFD tunnel type.
   3466  * Parameters:
   3467  *      unit            - (IN) Unit number.
   3468  *      endpoint_config - (IN/OUT) Pointer to BFD endpoint structure.
   3469  *      packet_flags    - (IN) Flags for building packet.
   3470  *      buffer          - (OUT) Buffer returning BFD encapsulation.
   3471  * Returns:
   3472  *      BCM_E_XXX
   3473  * Notes:
   3474  *      The returning BFD encapsulation includes only all the
   3475  *      encapsulation headers/labels and does not include
   3476  *      the BFD control packet.
   3477  */
   3478 STATIC int
   3479 bcmi_xgs5_bfd_encap_build_pack(int unit,
   3480                                bfd_endpoint_config_t *endpoint_config,
   3481                                uint32 packet_flags,
   3482                                uint8 *buffer)
   3483 {
   3484     bcm_bfd_endpoint_info_t *endpoint_info = &endpoint_config->info;
   3485     uint8          *cur_ptr = buffer;
   3486     bcm_port_t     tx_port;  /* Local port to TX packet */
   3487     uint16         etype = 0;
   3488     bfd_udp_header_t  udp;
   3489     bfd_ipv4_header_t ipv4, inner_ipv4;
   3490     bfd_ipv6_header_t ipv6, inner_ipv6;
   3491     bfd_gre_header_t  gre;
   3492     int            v6 = 0;
   3493     bfd_ach_header_t  ach;
   3494     bfd_mpls_label_t  mpls_gal;
   3495     bfd_mpls_label_t  mpls_labels[BFD_MPLS_MAX_LABELS];
   3496     int            mpls_count = 0;
   3497     int            i;
   3498     bfd_l2_header_t   l2;
   3499     int            ip_offset = 0;
   3500 
   3501     sal_memset(&udp, 0, sizeof(udp));
   3502     sal_memset(&ipv4, 0, sizeof(ipv4));
   3503     sal_memset(&inner_ipv4, 0, sizeof(inner_ipv4));
   3504     sal_memset(&ipv6, 0, sizeof(ipv6));
   3505     sal_memset(&inner_ipv6, 0, sizeof(inner_ipv6));
   3506 
   3507     tx_port = endpoint_config->tx_port;
   3508 
   3509     /*
   3510      * Get necessary headers/labels information.
   3511      *
   3512      * Following order is important since some headers/labels
   3513      * may depend on previous header/label information.
   3514      */
   3515     if (packet_flags & BFD_ENCAP_PKT_UDP) {
   3516         BCM_IF_ERROR_RETURN
   3517             (bcmi_xgs5_bfd_udp_header_get(unit, endpoint_info,
   3518                                           packet_flags, &udp));
   3519     }
   3520 
   3521     if (packet_flags & BFD_ENCAP_PKT_IP) {
   3522         BCM_IF_ERROR_RETURN
   3523             (bcmi_xgs5_bfd_ip_headers_get(endpoint_info,
   3524                                           packet_flags, udp.length,
   3525                                           &etype,
   3526                                           &ipv4, &ipv6,
   3527                                           &inner_ipv4, &inner_ipv6));
   3528     }
   3529 
   3530     /* Set UDP checksum with corresponding IP header information */
   3531     if (packet_flags & BFD_ENCAP_PKT_UDP) {
   3532         v6 = 0;
   3533         if (packet_flags & BFD_ENCAP_PKT_INNER_IP) {
   3534             if (packet_flags & BFD_ENCAP_PKT_INNER_IP__V6) {
   3535                 v6 = 1;
   3536             }
   3537             bcmi_xgs5_bfd_udp_checksum_set(v6, &inner_ipv4, &inner_ipv6, &udp);
   3538         } else {
   3539             if (packet_flags & BFD_ENCAP_PKT_IP__V6) {
   3540                 v6 = 1;
   3541             }
   3542             bcmi_xgs5_bfd_udp_checksum_set(v6, &ipv4, &ipv6, &udp);
   3543         }
   3544     }
   3545 
   3546     if (packet_flags & BFD_ENCAP_PKT_GRE) {
   3547         BCM_IF_ERROR_RETURN
   3548             (bcmi_xgs5_bfd_gre_header_get(packet_flags, &gre));
   3549     }
   3550 
   3551     if (packet_flags & BFD_ENCAP_PKT_G_ACH) {
   3552         BCM_IF_ERROR_RETURN
   3553             (bcmi_xgs5_bfd_ach_header_get(packet_flags, &ach));
   3554     }
   3555 
   3556     if (packet_flags & BFD_ENCAP_PKT_GAL) {
   3557         BCM_IF_ERROR_RETURN
   3558             (bcmi_xgs5_bfd_mpls_gal_label_get(&mpls_gal, endpoint_info));
   3559     }
   3560 
   3561     if (packet_flags & BFD_ENCAP_PKT_MPLS) {
   3562         etype = SHR_BFD_L2_ETYPE_MPLS_UCAST;
   3563         BCM_IF_ERROR_RETURN
   3564             (bcmi_xgs5_bfd_mpls_labels_get(unit, endpoint_info,
   3565                                            packet_flags,
   3566                                            BFD_MPLS_MAX_LABELS,
   3567                                            mpls_labels, &mpls_count));
   3568 
   3569         /* User explicitly set the MPLS egress label exp and ttl values */
   3570         if (endpoint_info->egress_label.exp != 0xFF) {
   3571             if (endpoint_info->egress_label.exp <= 0x07) {
   3572                 mpls_labels[0].exp = endpoint_info->egress_label.exp; 
   3573             } else { 
   3574                 return BCM_E_PARAM;
   3575             }
   3576         }
   3577         if (endpoint_info->egress_label.ttl != 0) {
   3578            mpls_labels[0].ttl = endpoint_info->egress_label.ttl; 
   3579         }
   3580     }
   3581 
   3582     /* Always build L2 Header */
   3583     BCM_IF_ERROR_RETURN
   3584         (bcmi_xgs5_bfd_l2_header_get(unit, endpoint_info, packet_flags,
   3585                                      tx_port, etype, &l2));
   3586 
   3587     /*
   3588      * Pack header/labels into given buffer (network packet format).
   3589      *
   3590      * Following packing order must be followed to correctly
   3591      * build the packet encapsulation.
   3592      */
   3593     cur_ptr = buffer;
   3594 
   3595     /* HG Header */
   3596     if (packet_flags & BFD_ENCAP_PKT_HG) {
   3597         cur_ptr = bcmi_xgs5_bfd_hg_header_pack(cur_ptr, unit,
   3598                                                endpoint_config, &l2);
   3599     } else if (packet_flags & BFD_ENCAP_PKT_HG2) {
   3600         cur_ptr = bcmi_xgs5_bfd_hg2_header_pack(cur_ptr, unit,
   3601                                                 endpoint_config, &l2);
   3602     }
   3603     if (cur_ptr == NULL) {
   3604         return BCM_E_INTERNAL;
   3605     }
   3606 
   3607     /* L2 Header is always present */
   3608     cur_ptr = bcmi_xgs5_bfd_l2_header_pack(cur_ptr, &l2);
   3609 
   3610     if (packet_flags & BFD_ENCAP_PKT_MPLS) {
   3611         for (i = 0; i < mpls_count; i++) {
   3612             cur_ptr = bcmi_xgs5_bfd_mpls_label_pack(cur_ptr, &mpls_labels[i]);
   3613         }
   3614     }
   3615 
   3616     /* Remaining packet headers */
   3617     if (packet_flags & BFD_ENCAP_PKT_GAL) {
   3618         cur_ptr = bcmi_xgs5_bfd_mpls_label_pack(cur_ptr, &mpls_gal);
   3619     }
   3620     if (packet_flags & BFD_ENCAP_PKT_G_ACH) {
   3621         cur_ptr = bcmi_xgs5_bfd_ach_header_pack(cur_ptr, &ach);
   3622     }
   3623     if (packet_flags & BFD_ENCAP_PKT_GRE) {
   3624     }
   3625     if (packet_flags & BFD_ENCAP_PKT_IP) {
   3626         /*
   3627          * IP offset for Lookup Key
   3628          * For IP-in-IP, this is the outer IP header
   3629          */
   3630         ip_offset = cur_ptr - buffer;
   3631 
   3632         if (packet_flags & BFD_ENCAP_PKT_IP__V6) {
   3633             cur_ptr = bcmi_xgs5_bfd_ipv6_header_pack(cur_ptr, &ipv6);
   3634         } else {
   3635             cur_ptr = bcmi_xgs5_bfd_ipv4_header_pack(cur_ptr, &ipv4);
   3636         }
   3637     }
   3638     if (packet_flags & BFD_ENCAP_PKT_GRE) {
   3639         cur_ptr = bcmi_xgs5_bfd_gre_header_pack(cur_ptr, &gre);
   3640     }
   3641     if (packet_flags & BFD_ENCAP_PKT_INNER_IP) {
   3642         if (packet_flags & BFD_ENCAP_PKT_INNER_IP__V6) {
   3643             cur_ptr = bcmi_xgs5_bfd_ipv6_header_pack(cur_ptr, &inner_ipv6);
   3644         } else {
   3645             cur_ptr = bcmi_xgs5_bfd_ipv4_header_pack(cur_ptr, &inner_ipv4);
   3646         }
   3647     }
   3648     if (packet_flags & BFD_ENCAP_PKT_UDP) {
   3649         cur_ptr = bcmi_xgs5_bfd_udp_header_pack(cur_ptr, &udp);
   3650     }
   3651 
   3652 
   3653     /* Set BFD encapsulation length */
   3654     endpoint_config->encap_length = cur_ptr - buffer;
   3655 
   3656     /*
   3657      * Set Lookup Key for initial BFD packets
   3658      * Offset is relative to the start of a given encapsulation data.
   3659      *
   3660      * Lookup Key:
   3661      *   UDP/IP  : IPSA of RX packet       = IPDA on BFD Session
   3662      *   IP-in-IP: Outer IPSA of RX packet = Outer IPDA on BFD Session
   3663      *   MPLS    : MPLS BOS of RX packet   = 'label' on BFD endpoint struct
   3664      *             - If GAL label (BOS) is present, then use MPLS label above.
   3665      *             - 'mpls_label' on BFD endpoint is the incomming inner MPLS
   3666      *               label.
   3667      */
   3668     endpoint_config->lkey_etype  = etype;
   3669     endpoint_config->lkey_offset = 0;
   3670     endpoint_config->lkey_length = 0;
   3671 
   3672     if (etype == SHR_BFD_L2_ETYPE_IPV4) {
   3673         endpoint_config->lkey_offset = ip_offset +
   3674             SHR_BFD_IPV4_HEADER_DA_OFFSET;
   3675         endpoint_config->lkey_length = SHR_BFD_IPV4_HEADER_SA_LENGTH;
   3676 
   3677     } else if (etype ==  SHR_BFD_L2_ETYPE_IPV6) {
   3678         endpoint_config->lkey_offset = ip_offset +
   3679             SHR_BFD_IPV6_HEADER_DA_OFFSET;
   3680         endpoint_config->lkey_length = SHR_BFD_IPV6_HEADER_SA_LENGTH;
   3681 
   3682     } else if (etype == SHR_BFD_L2_ETYPE_MPLS_UCAST) {
   3683         /*
   3684          * The lookup key is the incomming inner MPLS label,
   3685          * which is specified when the BFD endpoint is create.
   3686          *
   3687          * The lookup key data is located in the 'mpls_label'
   3688          * field of the message, rather than in the encap data
   3689          * packet buffer.
   3690          */
   3691 
   3692 
   3693 
   3694         /*
   3695          * If tunnel type to is PHP, update the eth type as IPv6/ipv4
   3696          * instead of MPLS_UCAST,
   3697          * lkey offset as ip address instead of mpls label and lkey length
   3698          * in ukernel session creation hash table update to perform hash lookup
   3699          */
   3700         if (endpoint_info->type == bcmBFDTunnelTypeMplsPhp) {
   3701             if (v6) {
   3702                 endpoint_config->lkey_etype  = SHR_BFD_L2_ETYPE_IPV6;
   3703                 endpoint_config->lkey_offset = ip_offset +
   3704                                                SHR_BFD_IPV6_HEADER_DA_OFFSET;
   3705                 endpoint_config->lkey_length = SHR_BFD_IPV6_HEADER_SA_LENGTH;
   3706             } else {
   3707                 endpoint_config->lkey_etype  = SHR_BFD_L2_ETYPE_IPV4;
   3708                 endpoint_config->lkey_offset = ip_offset +
   3709                                            SHR_BFD_IPV4_HEADER_DA_OFFSET;
   3710                 endpoint_config->lkey_length = SHR_BFD_IPV4_HEADER_SA_LENGTH;
   3711             }
   3712         } else {
   3713             endpoint_config->lkey_offset = 0;
   3714             endpoint_config->lkey_length = SHR_BFD_MPLS_LABEL_LABEL_LENGTH;
   3715         }
   3716     }
   3717 
   3718     return BCM_E_NONE;
   3719 }
   3720 
   3721 /*
   3722  * Function:
   3723  *      bcmi_xgs5_bfd_encap_data_dump
   3724  * Purpose:
   3725  *      Dumps buffer contents.
   3726  * Parameters:
   3727  *      buffer  - (IN) Buffer to dump data.
   3728  *      length  - (IN) Length of buffer.
   3729  * Returns:
   3730  *      None
   3731  */
   3732 void
   3733 bcmi_xgs5_bfd_encap_data_dump(uint8 *buffer, int length)
   3734 {
   3735     int i;
   3736 
   3737     LOG_CLI((BSL_META("\nBFD encapsulation (length=%d):\n"), length));
   3738 
   3739     for (i = 0; i < length; i++) {
   3740         if ((i % 10) == 0) {
   3741             LOG_CLI((BSL_META("\n")));
   3742         }
   3743         LOG_CLI((BSL_META(" 0x%02x"), buffer[i]));
   3744     }
   3745 
   3746     LOG_CLI((BSL_META("\n")));
   3747     return;
   3748 }
   3749 
   3750 /*
   3751  * Function:
   3752  *      bcmi_xgs5_bfd_ip_validate_1
   3753  * Purpose:
   3754  *      Performs the following IP address check and IP TTL configuration:
   3755  *      - IP Source Address is routable
   3756  *      - IP Destination Addresss is routable
   3757  *      - Sets IP TTL=255  for 1-hop
   3758  * Parameters:
   3759  *      endpoint_info - (IN/OUT) Pointer to BFD endpoint info structure.
   3760  *      packet_flags  - (IN) Packet flags.
   3761  * Returns:
   3762  *      BCM_E_XXX
   3763  */
   3764 int
   3765 bcmi_xgs5_bfd_ip_validate_1(bcm_bfd_endpoint_info_t *endpoint_info,
   3766                             uint32 packet_flags)
   3767 {
   3768 
   3769     /* IP-SA and IP-DA Routable */
   3770     if (packet_flags & BFD_ENCAP_PKT_IP__V6) {
   3771         if (BCM_IP6_MULTICAST(endpoint_info->src_ip6_addr)) {
   3772             return BCM_E_PARAM;
   3773         }
   3774         if (IPV6_LOOPBACK(endpoint_info->dst_ip6_addr)) {
   3775             return BCM_E_PARAM;
   3776         }
   3777     } else {
   3778         if (BCM_IP4_MULTICAST(endpoint_info->src_ip_addr)) {
   3779             return BCM_E_PARAM;
   3780         }
   3781         if (IPV4_LOOPBACK(endpoint_info->dst_ip_addr)) {
   3782             return BCM_E_PARAM;
   3783         }
   3784     }
   3785 
   3786     if (!(packet_flags & BFD_ENCAP_PKT_UDP__MULTI_HOP)) {
   3787         if (endpoint_info->ip_ttl == 0) {
   3788             endpoint_info->ip_ttl = 255;
   3789         } else if (endpoint_info->ip_ttl != 255) {    /* 1-hop */
   3790             return BCM_E_PARAM;
   3791         }
   3792     }
   3793 
   3794     return BCM_E_NONE;
   3795 }
   3796 
   3797 /*
   3798  * Function:
   3799  *      bcmi_xgs5_bfd_ip_validate_2
   3800  * Purpose:
   3801  *      Performs the following IP address check and IP TTL configuration:
   3802  *      - IP Source Address is routable
   3803  *      - IP Destination Addresss is loopback or routable address
   3804  *      - Sets IP TTL=1  for 1-hop when IP DA is loopback,
   3805  *        or   IP TTL=255 for 1-hop when IP DA is a routable address         
   3806  * Parameters:
   3807  *      endpoint_info - (IN/OUT) Pointer to BFD endpoint info structure.
   3808  *      packet_flags  - (IN) Packet flags.
   3809  * Returns:
   3810  *      BCM_E_XXX
   3811  */
   3812 int
   3813 bcmi_xgs5_bfd_ip_validate_2(bcm_bfd_endpoint_info_t *endpoint_info,
   3814                             uint32 packet_flags)
   3815 {
   3816     int ip_ttl = 0;
   3817     bcm_ip_t dst_ip_addr;
   3818     bcm_ip6_t src_ip6_addr, dst_ip6_addr;
   3819     int v6 = 0;
   3820 
   3821     if (packet_flags & BFD_ENCAP_PKT_INNER_IP) {
   3822         if (packet_flags & BFD_ENCAP_PKT_INNER_IP__V6) {
   3823             v6 = 1;
   3824         }
   3825         dst_ip_addr  = endpoint_info->inner_dst_ip_addr;
   3826         sal_memcpy(src_ip6_addr, endpoint_info->inner_src_ip6_addr,
   3827                    BCM_IP6_ADDRLEN);
   3828         sal_memcpy(dst_ip6_addr, endpoint_info->inner_dst_ip6_addr,
   3829                    BCM_IP6_ADDRLEN);
   3830     } else {
   3831         if (packet_flags & BFD_ENCAP_PKT_IP__V6) {
   3832             v6 = 1;
   3833         }
   3834         dst_ip_addr  = endpoint_info->dst_ip_addr;
   3835         sal_memcpy(src_ip6_addr, endpoint_info->src_ip6_addr,
   3836                    BCM_IP6_ADDRLEN);
   3837         sal_memcpy(dst_ip6_addr, endpoint_info->dst_ip6_addr,
   3838                    BCM_IP6_ADDRLEN);
   3839     }
   3840 
   3841     /* IP-DA:
   3842      *     Loopback: 127/8 or 0:0:0:0:0:FFFF:127/104, then ttl=1
   3843      *     Routable: then ttl=255
   3844      */
   3845     if (v6) {
   3846         if (IPV6_LOOPBACK(dst_ip6_addr)) {
   3847             ip_ttl = 1;
   3848         } else {
   3849             ip_ttl = 255;
   3850         }
   3851     } else {
   3852         if (IPV4_LOOPBACK(dst_ip_addr)) {
   3853             ip_ttl = 1;
   3854         } else {
   3855             ip_ttl = 255;
   3856         }
   3857     }
   3858 
   3859     if (!(packet_flags & BFD_ENCAP_PKT_UDP__MULTI_HOP)) {
   3860         /* 1-hop */
   3861         if (packet_flags & BFD_ENCAP_PKT_INNER_IP) {
   3862             if ((endpoint_info->flags & BCM_BFD_ENDPOINT_ENCAP_SET) &&
   3863                 (endpoint_info->inner_ip_ttl != ip_ttl)) {
   3864                  return BCM_E_PARAM;
   3865             } else {
   3866                 endpoint_info->inner_ip_ttl = ip_ttl;
   3867             }
   3868         } else {
   3869             if ((endpoint_info->flags & BCM_BFD_ENDPOINT_ENCAP_SET) &&
   3870                 (endpoint_info->ip_ttl != ip_ttl)) {
   3871                  return BCM_E_PARAM;
   3872             } else {
   3873                 endpoint_info->ip_ttl = ip_ttl;
   3874             }
   3875         }
   3876     }
   3877 
   3878     return BCM_E_NONE;
   3879 }
   3880 
   3881 
   3882 /*
   3883  * Function:
   3884  *      bcmi_xgs5_bfd_encap_create
   3885  * Purpose:
   3886  *      Creates a BFD packet encapsulation.
   3887  * Parameters:
   3888  *      unit            - (IN) Unit number.
   3889  *      endpoint_config - (IN/OUT) Pointer to BFD endpoint structure.
   3890  *      encap_data      - (OUT) Buffer returning BFD encapsulation.
   3891  * Returns:
   3892  *      BCM_E_XXX
   3893  * Notes:
   3894  *      The returning BFD encapsulation buffer includes all the
   3895  *      corresponding headers/labels EXCEPT for the BFD control packet.
   3896  */
   3897 STATIC int
   3898 bcmi_xgs5_bfd_encap_create(int unit,
   3899                            bfd_endpoint_config_t *endpoint_config,
   3900                            uint8 *encap_data)
   3901 {
   3902     bcm_bfd_endpoint_info_t *endpoint_info;
   3903     uint32 packet_flags;
   3904     uint32 ip_flag;
   3905     bcm_port_t tx_port;  /* Local port to TX packet */
   3906     bcm_pbmp_t st_pbmp;
   3907     bcm_pbmp_t tx_pbmp;
   3908 
   3909     endpoint_info = &endpoint_config->info;
   3910     tx_port       = endpoint_config->tx_port;
   3911 
   3912     /* Check for incompatible flags */
   3913     if ((endpoint_info->flags & BCM_BFD_ENDPOINT_PWE_RAW) &&
   3914         (endpoint_info->flags & BCM_BFD_ENDPOINT_IPV6)) {
   3915         return BCM_E_PARAM;
   3916     }
   3917 
   3918     packet_flags = 0;
   3919     ip_flag      = 0;
   3920 
   3921     /* Set IPv4 or IPv6 flag */
   3922     if (endpoint_info->flags & BCM_BFD_ENDPOINT_IPV6) {
   3923         ip_flag |= BFD_ENCAP_PKT_IP__V6;
   3924     }
   3925 
   3926     /* 1-hop or Multi-hop */
   3927     if (endpoint_info->flags & BCM_BFD_ENDPOINT_MULTIHOP) {
   3928         packet_flags |= BFD_ENCAP_PKT_UDP__MULTI_HOP;
   3929     }
   3930 
   3931     /*
   3932      * Get BFD encapsulation packet format flags
   3933      *
   3934      * Also, perform the following for each BFD tunnel type:
   3935      * - Check for valid parameter values
   3936      * - Set specific values required by the BFD tunnel definition 
   3937      *   (e.g. such as ttl=1,...)
   3938      */
   3939     switch (endpoint_info->type) {
   3940     case bcmBFDTunnelTypeUdp:
   3941         packet_flags |= 
   3942             (BFD_ENCAP_PKT_IP | ip_flag |
   3943              BFD_ENCAP_PKT_UDP);
   3944         if (endpoint_config->is_micro_bfd) {
   3945             packet_flags |= BFD_ENCAP_PKT_UDP_MICRO_BFD;
   3946         }
   3947         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   3948 
   3949         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   3950                                                         packet_flags));
   3951         break;
   3952 
   3953     case bcmBFDTunnelTypeIp4in4:
   3954         packet_flags |= 
   3955             (BFD_ENCAP_PKT_IP |
   3956              BFD_ENCAP_PKT_INNER_IP |
   3957              BFD_ENCAP_PKT_UDP);
   3958 
   3959         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   3960 
   3961         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   3962                                                         packet_flags));
   3963         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   3964                                                         packet_flags));
   3965         break;
   3966 
   3967 
   3968     case bcmBFDTunnelTypeIp6in4:
   3969         packet_flags |= 
   3970             (BFD_ENCAP_PKT_IP |
   3971              BFD_ENCAP_PKT_INNER_IP | BFD_ENCAP_PKT_INNER_IP__V6 |
   3972              BFD_ENCAP_PKT_UDP);
   3973 
   3974         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   3975 
   3976         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   3977                                                         packet_flags));
   3978         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   3979                                                         packet_flags));
   3980         break;
   3981 
   3982     case bcmBFDTunnelTypeIp4in6:
   3983         packet_flags |= 
   3984             (BFD_ENCAP_PKT_IP | BFD_ENCAP_PKT_IP__V6 |
   3985              BFD_ENCAP_PKT_INNER_IP |
   3986              BFD_ENCAP_PKT_UDP);
   3987 
   3988         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   3989 
   3990         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   3991                                                         packet_flags));
   3992         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   3993                                                         packet_flags));
   3994         break;
   3995 
   3996     case bcmBFDTunnelTypeIp6in6:
   3997         packet_flags |= 
   3998             (BFD_ENCAP_PKT_IP | BFD_ENCAP_PKT_IP__V6 |
   3999              BFD_ENCAP_PKT_INNER_IP | BFD_ENCAP_PKT_INNER_IP__V6 |
   4000              BFD_ENCAP_PKT_UDP);
   4001 
   4002         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4003 
   4004         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   4005                                                         packet_flags));
   4006         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4007                                                         packet_flags));
   4008         break;
   4009 
   4010     case bcmBFDTunnelTypeGre4In4:
   4011         /*
   4012          * bcmBFDTunnelTypeGRE is an old enum, which is now equivalent
   4013          * to the new GRE IPv4-in-IPv4 tunnel type bcmBFDTunnelTypeGre4In4.
   4014          */
   4015         packet_flags |=
   4016             (BFD_ENCAP_PKT_GRE |
   4017              BFD_ENCAP_PKT_IP |
   4018              BFD_ENCAP_PKT_INNER_IP |
   4019              BFD_ENCAP_PKT_UDP);
   4020 
   4021         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4022 
   4023         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   4024                                                         packet_flags));
   4025         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4026                                                         packet_flags));
   4027         break;
   4028 
   4029     case bcmBFDTunnelTypeGre6In4:
   4030         packet_flags |=
   4031             (BFD_ENCAP_PKT_GRE |
   4032              BFD_ENCAP_PKT_IP |
   4033              BFD_ENCAP_PKT_INNER_IP | BFD_ENCAP_PKT_INNER_IP__V6 |
   4034              BFD_ENCAP_PKT_UDP);
   4035 
   4036         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4037 
   4038         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   4039                                                         packet_flags));
   4040         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4041                                                         packet_flags));
   4042         break;
   4043 
   4044     case bcmBFDTunnelTypeGre4In6:
   4045         packet_flags |=
   4046             (BFD_ENCAP_PKT_GRE |
   4047              BFD_ENCAP_PKT_IP | BFD_ENCAP_PKT_IP__V6 |
   4048              BFD_ENCAP_PKT_INNER_IP |
   4049              BFD_ENCAP_PKT_UDP);
   4050 
   4051         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4052 
   4053         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   4054                                                         packet_flags));
   4055         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4056                                                         packet_flags));
   4057         break;
   4058 
   4059     case bcmBFDTunnelTypeGre6In6:
   4060 
   4061         packet_flags |=
   4062             (BFD_ENCAP_PKT_GRE |
   4063              BFD_ENCAP_PKT_IP | BFD_ENCAP_PKT_IP__V6 |
   4064              BFD_ENCAP_PKT_INNER_IP | BFD_ENCAP_PKT_INNER_IP__V6 |
   4065              BFD_ENCAP_PKT_UDP);
   4066 
   4067         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4068 
   4069         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_1(endpoint_info,
   4070                                                         packet_flags));
   4071         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4072                                                         packet_flags));
   4073         break;
   4074 
   4075     case bcmBFDTunnelTypeMpls:
   4076     case bcmBFDTunnelTypeMplsPhp:
   4077         packet_flags |=
   4078             (BFD_ENCAP_PKT_MPLS |
   4079              BFD_ENCAP_PKT_IP | ip_flag |
   4080              BFD_ENCAP_PKT_UDP);
   4081 
   4082         ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4083 
   4084         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4085                                                         packet_flags));
   4086 
   4087 
   4088         break;
   4089 
   4090     case bcmBFDTunnelTypeMplsTpCc:
   4091         packet_flags |= (BFD_ENCAP_PKT_MPLS | BFD_ENCAP_PKT_G_ACH);
   4092 
   4093         if (!(endpoint_info->flags & BCM_BFD_ENDPOINT_PWE_RAW)) {
   4094             packet_flags |= BFD_ENCAP_PKT_G_ACH__CC;
   4095         }
   4096 
   4097         if (endpoint_config->is_l3_vpn) {
   4098             packet_flags |= BFD_ENCAP_PKT_GAL;
   4099         }
   4100 
   4101         break;
   4102 
   4103     case bcmBFDTunnelTypeMplsTpCcCv:
   4104         packet_flags |= (BFD_ENCAP_PKT_MPLS | BFD_ENCAP_PKT_G_ACH);
   4105 
   4106         if (!(endpoint_info->flags & BCM_BFD_ENDPOINT_PWE_RAW)) {
   4107             packet_flags |= BFD_ENCAP_PKT_G_ACH__CC_CV;
   4108         }
   4109 
   4110         if (endpoint_config->is_l3_vpn) {
   4111             packet_flags |= BFD_ENCAP_PKT_GAL;
   4112         }
   4113 
   4114         if ((endpoint_info->mep_id_length <= 0) ||
   4115             (endpoint_info->mep_id_length >
   4116              _SHR_BFD_ENDPOINT_MAX_MEP_ID_LENGTH)) {
   4117             return BCM_E_PARAM;
   4118         }
   4119         break;
   4120 
   4121     case bcmBFDTunnelTypePweControlWord:
   4122         packet_flags |=
   4123             (BFD_ENCAP_PKT_MPLS |
   4124              BFD_ENCAP_PKT_G_ACH);
   4125 
   4126         /* Check for incompatible flags */
   4127         if ((endpoint_info->flags & BCM_BFD_ENDPOINT_DEMAND) ||
   4128             (endpoint_info->flags & BCM_BFD_ENDPOINT_PASSIVE)) {
   4129             return BCM_E_PARAM;
   4130         }
   4131 
   4132         /* PW required */
   4133         if (!BCM_GPORT_IS_MPLS_PORT(endpoint_info->gport)) {
   4134             return BCM_E_PARAM;
   4135         }
   4136 
   4137         /* Raw mode or UDP/IP */
   4138         if (!(endpoint_info->flags & BCM_BFD_ENDPOINT_PWE_RAW)) {
   4139             /* UDP/IP */
   4140             ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4141             packet_flags |= BFD_ENCAP_PKT_G_ACH__IP;
   4142             packet_flags |=
   4143                 (BFD_ENCAP_PKT_IP | ip_flag |
   4144                  BFD_ENCAP_PKT_UDP);
   4145 
   4146             BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4147                                                             packet_flags));
   4148         }
   4149         break;
   4150 
   4151     case bcmBFDTunnelTypePweRouterAlert:
   4152         packet_flags |= BFD_ENCAP_PKT_MPLS_ROUTER_ALERT;
   4153         /* Fall through */
   4154     case bcmBFDTunnelTypePweTtl:
   4155         packet_flags |=
   4156             BFD_ENCAP_PKT_MPLS;
   4157 
   4158         /* Check for incompatible flags */
   4159         if ((endpoint_info->flags & BCM_BFD_ENDPOINT_DEMAND) ||
   4160             (endpoint_info->flags & BCM_BFD_ENDPOINT_PASSIVE)) {
   4161             return BCM_E_PARAM;
   4162         }
   4163 
   4164         /* PW required */
   4165         if (!BCM_GPORT_IS_MPLS_PORT(endpoint_info->gport)) {
   4166             return BCM_E_PARAM;
   4167         }
   4168 
   4169         /*
   4170          * If ACH is present, UDP/IP and RAW can be used
   4171          * Otherwise, only UDP/IP can be set
   4172          */
   4173         if (endpoint_info->flags & BCM_BFD_ENDPOINT_PWE_ACH) {
   4174             packet_flags |= BFD_ENCAP_PKT_G_ACH;
   4175             /* Raw or UDP/IP */
   4176             if (!(endpoint_info->flags & BCM_BFD_ENDPOINT_PWE_RAW)) {
   4177                 packet_flags |= BFD_ENCAP_PKT_G_ACH__IP;
   4178             }
   4179         } else {
   4180             if (endpoint_info->flags & BCM_BFD_ENDPOINT_PWE_RAW) {
   4181                 return BCM_E_PARAM;
   4182             }
   4183             packet_flags |= BFD_ENCAP_PKT_G_ACH__IP;
   4184         }
   4185         
   4186         if (packet_flags & BFD_ENCAP_PKT_G_ACH__IP) {
   4187            /* UDP/IP */
   4188             ENCAP_UDP_SRCPORT_VALIDATE(endpoint_info->udp_src_port);
   4189             packet_flags |= BFD_ENCAP_PKT_G_ACH__IP;
   4190             packet_flags |=
   4191                 (BFD_ENCAP_PKT_IP | ip_flag |
   4192                  BFD_ENCAP_PKT_UDP);
   4193 
   4194             BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_ip_validate_2(endpoint_info,
   4195                                                             packet_flags));
   4196         }
   4197         break;
   4198 
   4199     default:
   4200         return BCM_E_PARAM;
   4201     }
   4202 
   4203     /* Check if HG Header is needed (TX port is HG) */
   4204     SOC_PBMP_PORT_SET(tx_pbmp, tx_port);
   4205     SOC_PBMP_ASSIGN(st_pbmp, PBMP_ST_ALL(unit));
   4206     BCM_API_XLATE_PORT_PBMP_P2A(unit, &st_pbmp);
   4207     SOC_PBMP_AND(st_pbmp, tx_pbmp);
   4208     if (SOC_PBMP_NOT_NULL(st_pbmp)) {
   4209         if (IS_HG2_ENABLED_PORT(unit, tx_port)) {
   4210             packet_flags |= BFD_ENCAP_PKT_HG2;
   4211         } else {
   4212             packet_flags |= BFD_ENCAP_PKT_HG;
   4213         }
   4214     }
   4215 
   4216     /* Build header/labels and pack in buffer */
   4217     BCM_IF_ERROR_RETURN
   4218         (bcmi_xgs5_bfd_encap_build_pack(unit,
   4219                                         endpoint_config,
   4220                                         packet_flags,
   4221                                         encap_data));
   4222 
   4223     /*
   4224      * Set encap type.  Used to indicate uC for special
   4225      * handling on certain encapsulation types:
   4226      * - UDP checksum update is required
   4227      * - packet is MPLS-TP CC only
   4228      * - packet is MPLS-TP CC/CV
   4229      */
   4230     if (packet_flags & BFD_ENCAP_PKT_UDP) {
   4231         if (packet_flags & BFD_ENCAP_PKT_IP__V6) {
   4232             endpoint_config->encap_type = SHR_BFD_ENCAP_TYPE_V6UDP;
   4233         } else {
   4234             endpoint_config->encap_type = SHR_BFD_ENCAP_TYPE_V4UDP;
   4235         }
   4236     } else if (packet_flags & BFD_ENCAP_PKT_G_ACH__CC) {
   4237         endpoint_config->encap_type = SHR_BFD_ENCAP_TYPE_MPLS_TP_CC;
   4238     } else if (packet_flags & BFD_ENCAP_PKT_G_ACH__CC_CV) {
   4239         endpoint_config->encap_type = SHR_BFD_ENCAP_TYPE_MPLS_TP_CC_CV;
   4240     } else {
   4241         endpoint_config->encap_type = SHR_BFD_ENCAP_TYPE_RAW;
   4242     }                    
   4243 
   4244 #ifdef BFD_DEBUG_DUMP
   4245     bcmi_xgs5_bfd_encap_data_dump(encap_data, endpoint_config->encap_length);
   4246 #endif
   4247 
   4248     return BCM_E_NONE;
   4249 }
   4250     
   4251 /*
   4252  * Function:
   4253  *      bcmi_xgs5_bfd_session_hw_set
   4254  * Purpose:
   4255  *      Sets BFD Session in HW device.
   4256  * Parameters:
   4257  *      unit            - (IN) Unit number.
   4258  *      endpoint_config - (IN) Pointer to BFD endpoint structure.
   4259  * Returns:
   4260  *      BCM_E_XXX
   4261  * Notes:
   4262  */
   4263 STATIC int
   4264 bcmi_xgs5_bfd_session_hw_set(int unit,
   4265                              bfd_endpoint_config_t *endpoint_config)
   4266 {
   4267     int rv = BCM_E_NONE;
   4268     bcm_bfd_endpoint_info_t *endpoint_info;
   4269     uint32 mpls = 1;
   4270     bfd_info_t *bfd_info = BFD_INFO(unit);
   4271 
   4272     endpoint_info  = &endpoint_config->info;
   4273 
   4274     switch(endpoint_info->type) {
   4275     case bcmBFDTunnelTypeUdp:
   4276 #if defined(BCM_TOMAHAWK_SUPPORT)
   4277     if(!(SOC_IS_TOMAHAWKX(unit) ||
   4278          SOC_IS_TRIDENT3X(unit))) {
   4279 #endif
   4280         if (!(bfd_info->use_sess_id_as_discr)) {
   4281             /* Set L2_ENTRY entry, Your Discriminator lookup */
   4282             BCM_IF_ERROR_RETURN
   4283                 (bcmi_xgs5_bfd_l2x_entry_set(unit, endpoint_config, 0));
   4284         }
   4285 
   4286 #if defined(BCM_TOMAHAWK_SUPPORT)
   4287     }
   4288 #endif
   4289         /* L3 entry */
   4290         L3_LOCK(unit);
   4291         rv = bcmi_xgs5_bfd_l3_entry_set(unit, endpoint_info);
   4292         L3_UNLOCK(unit);
   4293 
   4294         break;
   4295 
   4296     case bcmBFDTunnelTypeIp4in4:
   4297     case bcmBFDTunnelTypeIp6in4:
   4298     case bcmBFDTunnelTypeIp4in6:
   4299     case bcmBFDTunnelTypeIp6in6:
   4300     case bcmBFDTunnelTypeGre4In4:
   4301     case bcmBFDTunnelTypeGre6In4:
   4302     case bcmBFDTunnelTypeGre4In6:
   4303     case bcmBFDTunnelTypeGre6In6:
   4304 #if defined(BCM_TOMAHAWK_SUPPORT)
   4305     if(!(SOC_IS_TOMAHAWKX(unit) ||
   4306          SOC_IS_TRIDENT3X(unit))) {
   4307 #endif
   4308         if (!(bfd_info->use_sess_id_as_discr)) {
   4309             /* Set L2_ENTRY entry, Your Discriminator lookup */
   4310             BCM_IF_ERROR_RETURN
   4311                 (bcmi_xgs5_bfd_l2x_entry_set(unit, endpoint_config, 0));
   4312         }
   4313 #if defined(BCM_TOMAHAWK_SUPPORT)
   4314     }
   4315 #endif
   4316         /* L3_TUNNEL */
   4317         BCM_IF_ERROR_RETURN
   4318             (bcmi_xgs5_bfd_l3_tunnel_entry_set(unit, endpoint_info));
   4319 
   4320         break;
   4321 
   4322     case bcmBFDTunnelTypeMpls:
   4323     case bcmBFDTunnelTypeMplsPhp:
   4324     case bcmBFDTunnelTypeMplsTpCc:
   4325     case bcmBFDTunnelTypeMplsTpCcCv:
   4326     case bcmBFDTunnelTypePweControlWord:
   4327     case bcmBFDTunnelTypePweRouterAlert:
   4328     case bcmBFDTunnelTypePweTtl:
   4329 #if defined(BCM_MPLS_SUPPORT)
   4330         if ((BCM_ESW_BFD_DRV(unit) == NULL) ||
   4331             (BFD_HW_CALL(unit)->mpls_lock == NULL) ||
   4332             (BFD_HW_CALL(unit)->mpls_unlock == NULL)) {
   4333             return BCM_E_UNAVAIL;
   4334         }
   4335         if (endpoint_info->flags & BCM_BFD_ENDPOINT_KEY_TYPE_USE_YOUR_DISC) {
   4336             mpls = 0;
   4337         }
   4338 
   4339 #if defined(BCM_TOMAHAWK_SUPPORT)
   4340     if(!(SOC_IS_TOMAHAWKX(unit) ||
   4341          SOC_IS_TRIDENT3X(unit))) {
   4342 #endif
   4343         if (endpoint_info->type == bcmBFDTunnelTypeMplsPhp) {
   4344             if (!(bfd_info->use_sess_id_as_discr)) {
   4345                 /* Set L2_ENTRY entry, Your Discriminator lookup */
   4346                 BCM_IF_ERROR_RETURN
   4347                     (bcmi_xgs5_bfd_l2x_entry_set(unit, endpoint_config, 0));
   4348             }
   4349         } else {
   4350             if (!(bfd_info->use_sess_id_as_discr)) {
   4351                 /* Set L2_ENTRY entry, MPLS lookup */
   4352                 BCM_IF_ERROR_RETURN
   4353                     (bcmi_xgs5_bfd_l2x_entry_set(unit, endpoint_config, mpls));
   4354             }
   4355         }
   4356 #if defined(BCM_TOMAHAWK_SUPPORT)
   4357     }
   4358 #endif
   4359         /* MPLS entry */
   4360         BCM_IF_ERROR_RETURN(BFD_HW_CALL(unit)->mpls_lock(unit));
   4361         rv = bcmi_xgs5_bfd_mpls_entry_set(unit, endpoint_config);
   4362         BFD_HW_CALL(unit)->mpls_unlock(unit);
   4363 
   4364         if (BCM_FAILURE(rv)) {
   4365        /* Clear the L2 entry */
   4366 #if defined(BCM_TOMAHAWK_SUPPORT)
   4367             if(!(SOC_IS_TOMAHAWKX(unit) ||
   4368                  SOC_IS_TRIDENT3X(unit))) {
   4369 #endif
   4370                 if (endpoint_info->type == bcmBFDTunnelTypeMplsPhp) {
   4371                     if (!(bfd_info->use_sess_id_as_discr)) {
   4372                         /* clear L2_ENTRY entry, Your Discriminator lookup */
   4373                         BCM_IF_ERROR_RETURN
   4374                              (bcmi_xgs5_bfd_l2_entry_clear(unit, 0,
   4375                                        endpoint_info->label,
   4376                                        endpoint_info->local_discr));
   4377                     }
   4378                 } else {
   4379                     if (!(bfd_info->use_sess_id_as_discr)) {
   4380                         /* clear L2_ENTRY entry, MPLS lookup */
   4381                         BCM_IF_ERROR_RETURN
   4382                             (bcmi_xgs5_bfd_l2_entry_clear(unit, mpls,
   4383                                       endpoint_info->label,
   4384                                       endpoint_info->local_discr));
   4385                     }
   4386                 }
   4387 #if defined(BCM_TOMAHAWK_SUPPORT)
   4388             }
   4389 #endif
   4390         }
   4391 
   4392 #else
   4393         return BCM_E_UNAVAIL;
   4394 #endif /* BCM_MPLS_SUPPORT */
   4395         break;
   4396 
   4397     default:
   4398         rv = BCM_E_UNAVAIL;
   4399         break;
   4400     }
   4401 
   4402     return rv;
   4403 }
   4404 
   4405 /*
   4406  * Function:
   4407  *      bcmi_xgs5_bfd_mpls_entry_status
   4408  */
   4409 STATIC int
   4410 bcmi_xgs5_bfd_mpls_entry_status(int unit,
   4411                                  bfd_endpoint_config_t *endpoint_config)
   4412 {
   4413 #if defined(BCM_MPLS_SUPPORT)
   4414     bcm_bfd_endpoint_info_t *endpoint_info;
   4415     mpls_entry_entry_t mpls_entry;
   4416     mpls_entry_entry_t mpls_key;
   4417 #if defined(BCM_TRIUMPH3_SUPPORT)
   4418     mpls_entry_extd_entry_t mpls_extd_entry;
   4419     mpls_entry_extd_entry_t mpls_extd_key;
   4420 #endif
   4421     int mpls_index = 0;
   4422     bcm_module_t mod_out;
   4423     bcm_port_t port_out;
   4424     int rv;
   4425     endpoint_info  = &endpoint_config->info;
   4426 
   4427     sal_memset(&mpls_key, 0, sizeof(mpls_key));
   4428 
   4429     /* Add key_type_value 16 for Tr3*/
   4430     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   4431                         BFD_HW_MPLS(unit)->key_type,
   4432                         BFD_HW_MPLS(unit)->key_type_value);
   4433 
   4434     soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   4435                         BFD_HW_MPLS(unit)->mpls_label, endpoint_info->label);
   4436 
   4437 #if defined(INCLUDE_L3)
   4438     if (bcm_tr_mpls_port_independent_range(unit, endpoint_info->label,
   4439                                            BCM_GPORT_INVALID) != BCM_E_NONE) {
   4440         rv = bcmi_xgs5_bfd_mpls_port_resolve(unit, endpoint_info,
   4441                                              &mod_out , &port_out);
   4442         BCM_IF_ERROR_RETURN(rv);
   4443 
   4444         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   4445             BFD_HW_MPLS(unit)->mod_id, mod_out);
   4446         soc_mem_field32_set(unit, BFD_HW_MPLS_MEM(unit), &mpls_key,
   4447             BFD_HW_MPLS(unit)->port_num, port_out);
   4448     }
   4449 #endif
   4450  /* coverity[overrun-buffer-val : FALSE]    */
   4451 #if defined(BCM_TRIUMPH3_SUPPORT)
   4452     if (SOC_IS_TRIUMPH3(unit)) {
   4453         /* First Search for key_type 16 */
   4454         rv = soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   4455                             MEM_BLOCK_ANY, &mpls_index,
   4456                             &mpls_key, &mpls_entry, 0);
   4457 
   4458         /* If key_type 16 not found, Search for key_type 17 in MPLS_ENTRY_EXTDm */
   4459         if (rv == BCM_E_NOT_FOUND) {
   4460             sal_memset(&mpls_extd_key, 0, sizeof(mpls_extd_key));
   4461             /* Add key_type_value 17 for Tr3 with conversion */
   4462             BCM_IF_ERROR_RETURN(_bcm_tr3_mpls_entry_convert_to_extd_entry_key(unit,
   4463                                 &mpls_key, &mpls_extd_key));
   4464 
   4465             SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRY_EXTDm,
   4466                                                MEM_BLOCK_ANY, &mpls_index,
   4467                                                &mpls_extd_key, &mpls_extd_entry, 0));
   4468         }
   4469 } else
   4470 #endif
   4471 {
   4472     SOC_IF_ERROR_RETURN(soc_mem_search(unit, BFD_HW_MPLS_MEM(unit),
   4473                                        MEM_BLOCK_ANY, &mpls_index,
   4474                                        &mpls_key, &mpls_entry, 0));
   4475 }
   4476     return BCM_E_NONE;
   4477 #else
   4478     return BCM_E_UNAVAIL;
   4479 #endif /* BCM_MPLS_SUPPORT */
   4480 }
   4481 
   4482 /*
   4483  * Function:
   4484  *     bcmi_xgs5_bfd_mpls_l3_table_status
   4485  * Purpose:
   4486  *      Sets BFD Session in HW device.
   4487  * Parameters:
   4488  *      unit            - (IN) Unit number.
   4489  *      endpoint_config - (IN) Pointer to BFD endpoint structure.
   4490  * Returns:
   4491  *      BCM_E_XXX
   4492  * Notes:
   4493  */
   4494 STATIC int
   4495 bcmi_xgs5_bfd_mpls_l3_table_status(int unit,
   4496                              bfd_endpoint_config_t *endpoint_config)
   4497 {
   4498     int rv = BCM_E_NONE;
   4499     bcm_bfd_endpoint_info_t *endpoint_info;
   4500 
   4501     endpoint_info  = &endpoint_config->info;
   4502 
   4503     switch(endpoint_info->type) {
   4504     case bcmBFDTunnelTypeUdp:
   4505         /* L3 entry */
   4506         rv = bcmi_xgs5_bfd_l3_entry_status(unit, endpoint_info);
   4507 
   4508         break;
   4509 
   4510     case bcmBFDTunnelTypeIp4in4:
   4511     case bcmBFDTunnelTypeIp6in4:
   4512     case bcmBFDTunnelTypeIp4in6:
   4513     case bcmBFDTunnelTypeIp6in6:
   4514     case bcmBFDTunnelTypeGre4In4:
   4515     case bcmBFDTunnelTypeGre6In4:
   4516     case bcmBFDTunnelTypeGre4In6:
   4517     case bcmBFDTunnelTypeGre6In6:
   4518         /* L3_TUNNEL */
   4519         BCM_IF_ERROR_RETURN
   4520             (bcmi_xgs5_bfd_l3_tunnel_entry_status(unit, endpoint_info));
   4521 
   4522         break;
   4523 
   4524     case bcmBFDTunnelTypeMpls:
   4525     case bcmBFDTunnelTypeMplsPhp:
   4526     case bcmBFDTunnelTypeMplsTpCc:
   4527     case bcmBFDTunnelTypeMplsTpCcCv:
   4528     case bcmBFDTunnelTypePweControlWord:
   4529     case bcmBFDTunnelTypePweRouterAlert:
   4530     case bcmBFDTunnelTypePweTtl:
   4531 #if defined(BCM_MPLS_SUPPORT)
   4532         /* MPLS entry */
   4533         rv = bcmi_xgs5_bfd_mpls_entry_status(unit, endpoint_config);
   4534 
   4535 #else
   4536         return BCM_E_UNAVAIL;
   4537 #endif /* BCM_MPLS_SUPPORT */
   4538         break;
   4539 
   4540     default:
   4541         rv = BCM_E_UNAVAIL;
   4542         break;
   4543     }
   4544 
   4545     return rv;
   4546 }
   4547 
   4548 
   4549 /*
   4550  * Function:
   4551  *      bcmi_xgs5_bfd_session_hw_delete
   4552  * Purpose:
   4553  *      Delete BFD Session in HW device.
   4554  * Parameters:
   4555  *      unit            - (IN) Unit number.
   4556  *      endpoint_config - (IN) Pointer to BFD endpoint structure.
   4557  * Returns:
   4558  *      BCM_E_XXX
   4559  * Notes:
   4560  */
   4561 STATIC int
   4562 bcmi_xgs5_bfd_session_hw_delete(int unit,
   4563                                 bfd_endpoint_config_t *endpoint_config)
   4564 {
   4565     int rv = BCM_E_NONE;
   4566     bcm_bfd_endpoint_info_t *endpoint_info;
   4567     int index, ref_count = 0;
   4568     bfd_info_t *bfd_info = BFD_INFO(unit);
   4569     uint32 mpls = 1;
   4570 
   4571     endpoint_info  = &endpoint_config->info;
   4572 
   4573     switch(endpoint_config->info.type) {
   4574     case bcmBFDTunnelTypeUdp:
   4575         for (index = 0; index < bfd_info->endpoint_count; index++) {
   4576             if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   4577                 endpoint_config = BFD_ENDPOINT_CONFIG(unit, index);
   4578                 /* Check for IPv4 */
   4579                 if (endpoint_config->encap_type == SHR_BFD_ENCAP_TYPE_V4UDP){
   4580                     if (endpoint_config->info.src_ip_addr == endpoint_info->src_ip_addr) {
   4581                         ref_count++;
   4582                     }
   4583                 }
   4584                 /* Check for IPv6 */
   4585                 else if (endpoint_config->encap_type == SHR_BFD_ENCAP_TYPE_V6UDP) {
   4586                     if (BCM_IP6_ADDR_EQ (endpoint_config->info.src_ip6_addr, endpoint_info->src_ip6_addr)) {
   4587                         ref_count++;
   4588                     }
   4589                 }
   4590             }
   4591         }
   4592         /* Don't delete the l3 entry till last BFD session is destroyed */ 
   4593         if (ref_count <= 1) {
   4594             /* L3 entry */
   4595             L3_LOCK(unit);
   4596             (void) bcmi_xgs5_bfd_l3_entry_clear(unit, endpoint_info);
   4597             L3_UNLOCK(unit);
   4598         }
   4599 
   4600 #if defined(BCM_TOMAHAWK_SUPPORT)
   4601     if(!(SOC_IS_TOMAHAWKX(unit) ||
   4602          SOC_IS_TRIDENT3X(unit))) {
   4603 #endif
   4604         if (!(bfd_info->use_sess_id_as_discr)) {
   4605             /* L2_ENTRY */
   4606             rv = bcmi_xgs5_bfd_l2_entry_clear(unit, 0,
   4607                     endpoint_info->label,
   4608                     endpoint_info->local_discr);
   4609         }
   4610 #if defined(BCM_TOMAHAWK_SUPPORT)
   4611     }
   4612 #endif
   4613         break;
   4614 
   4615     case bcmBFDTunnelTypeIp4in4:
   4616     case bcmBFDTunnelTypeIp6in4:
   4617     case bcmBFDTunnelTypeIp4in6:
   4618     case bcmBFDTunnelTypeIp6in6:
   4619     case bcmBFDTunnelTypeGre4In4:
   4620     case bcmBFDTunnelTypeGre6In4:
   4621     case bcmBFDTunnelTypeGre4In6:
   4622     case bcmBFDTunnelTypeGre6In6:
   4623         /* L3_TUNNEL */
   4624         BCM_IF_ERROR_RETURN
   4625             (bcmi_xgs5_bfd_l3_tunnel_entry_clear(unit, endpoint_info));
   4626 
   4627 #if defined(BCM_TOMAHAWK_SUPPORT)
   4628     if(!(SOC_IS_TOMAHAWKX(unit) ||
   4629          SOC_IS_TRIDENT3X(unit))) {
   4630 #endif
   4631         if (!(bfd_info->use_sess_id_as_discr)) {
   4632             /* L2_ENTRY */
   4633             rv = bcmi_xgs5_bfd_l2_entry_clear(unit, 0,
   4634                     endpoint_info->label,
   4635                     endpoint_info->local_discr);
   4636         }
   4637 #if defined(BCM_TOMAHAWK_SUPPORT)
   4638     }
   4639 #endif
   4640         break;
   4641 
   4642     case bcmBFDTunnelTypeMpls:
   4643     case bcmBFDTunnelTypeMplsPhp:
   4644     case bcmBFDTunnelTypeMplsTpCc:
   4645     case bcmBFDTunnelTypeMplsTpCcCv:
   4646     case bcmBFDTunnelTypePweControlWord:
   4647     case bcmBFDTunnelTypePweRouterAlert:
   4648     case bcmBFDTunnelTypePweTtl:
   4649 #if defined(BCM_MPLS_SUPPORT)
   4650         if ((BCM_ESW_BFD_DRV(unit) == NULL) ||
   4651             (BFD_HW_CALL(unit)->mpls_lock == NULL) ||
   4652             (BFD_HW_CALL(unit)->mpls_unlock == NULL)) {
   4653             return BCM_E_UNAVAIL;
   4654         }
   4655 
   4656         if (endpoint_info->flags & BCM_BFD_ENDPOINT_KEY_TYPE_USE_YOUR_DISC) {
   4657             mpls = 0;
   4658         }
   4659 
   4660         /* MPLS entry */
   4661         BCM_IF_ERROR_RETURN(BFD_HW_CALL(unit)->mpls_lock(unit));
   4662         rv = bcmi_xgs5_bfd_mpls_entry_clear(unit, endpoint_config);
   4663         BFD_HW_CALL(unit)->mpls_unlock(unit);
   4664         BCM_IF_ERROR_RETURN(rv);
   4665 
   4666 #if defined(BCM_TOMAHAWK_SUPPORT)
   4667     if(!(SOC_IS_TOMAHAWKX(unit) ||
   4668          SOC_IS_TRIDENT3X(unit))) {
   4669 #endif
   4670         if (endpoint_info->type == bcmBFDTunnelTypeMplsPhp) {
   4671             for (index = 0; index < bfd_info->endpoint_count; index++) {
   4672                  if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   4673                      endpoint_config = BFD_ENDPOINT_CONFIG(unit, index);
   4674                      /* Check for IPv4 */
   4675                      if (endpoint_config->lkey_etype == SHR_BFD_L2_ETYPE_IPV4){
   4676                           if (endpoint_config->info.src_ip_addr == endpoint_info->src_ip_addr) {
   4677                               ref_count++;
   4678                           }
   4679                          /* Check for IPv6 */
   4680                      } else if (endpoint_config->lkey_etype == SHR_BFD_L2_ETYPE_IPV6) {
   4681                          if (BCM_IP6_ADDR_EQ (endpoint_config->info.src_ip6_addr, endpoint_info->src_ip6_addr)) {
   4682                              ref_count++;
   4683                           }
   4684                      }
   4685                  }
   4686             }
   4687            /* Don't delete the l3 entry till last BFD session is destroyed */
   4688            if (ref_count <= 1) {
   4689                /* L3 entry */
   4690                L3_LOCK(unit);
   4691                (void) bcmi_xgs5_bfd_l3_entry_clear(unit, endpoint_info);
   4692                L3_UNLOCK(unit);
   4693            }
   4694 
   4695            if (!(bfd_info->use_sess_id_as_discr)) {
   4696                 /* L2_ENTRY */
   4697                 rv = bcmi_xgs5_bfd_l2_entry_clear(unit, 0,
   4698                                endpoint_info->label,
   4699                                endpoint_info->local_discr);
   4700            }
   4701         } else {
   4702             if (!(bfd_info->use_sess_id_as_discr)) {
   4703                 /* L2_ENTRY */
   4704                 rv = bcmi_xgs5_bfd_l2_entry_clear(unit, mpls,
   4705                               endpoint_info->label,
   4706                               endpoint_info->local_discr);
   4707             }
   4708         }
   4709 #if defined(BCM_TOMAHAWK_SUPPORT)
   4710     }
   4711 #endif
   4712 
   4713 #else
   4714         return BCM_E_UNAVAIL;
   4715 #endif /* BCM_MPLS_SUPPORT */
   4716         break;
   4717 
   4718     default:
   4719         break;
   4720     }
   4721 
   4722     return rv;
   4723 }
   4724 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   4725 
   4726 
   4727 #ifdef BCM_WARM_BOOT_SUPPORT
   4728 int bcmi_xgs5_bfd_version_exchange(int unit)
   4729 {
   4730 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   4731     uint8 *buffer_reply, *buffer_req, *buffer_ptr;
   4732     uint16 buffer_len, reply_len;
   4733     bfd_sdk_version_exchange_msg_t sdk_msg,uc_msg;
   4734     bfd_info_t *bfd_info = BFD_INFO(unit);
   4735     int rv = BCM_E_NONE;
   4736 
   4737     BFD_FEATURE_INIT_CHECK(unit);
   4738 
   4739     /* Pack control message data into DMA */
   4740     sdk_msg.version = BFD_SDK_VERSION;
   4741 
   4742     buffer_req      = bfd_info->dma_buffer;
   4743     buffer_ptr      = bfd_sdk_version_exchange_msg_pack(buffer_req, &sdk_msg);
   4744     buffer_len      = buffer_ptr - buffer_req;
   4745 
   4746     /* Send Message to exchange version value*/
   4747     rv = bcmi_xgs5_bfd_msg_send_receive(unit, MOS_MSG_SUBCLASS_BFD_VERSION_EXCHANGE,
   4748                                         buffer_len, 0,
   4749                                         MOS_MSG_SUBCLASS_BFD_VER_EXCHANGE_REPLY,
   4750                                         &reply_len, bfd_uc_msg_timeout_usecs);
   4751     if (rv == BCM_E_UNAVAIL) {
   4752         bfd_firmware_version = BFD_UC_MIN_VERSION;
   4753         return BCM_E_NONE;
   4754     } else if (rv < 0) {
   4755         return rv;
   4756     }
   4757 
   4758     sal_memset(&uc_msg, 0, sizeof(uc_msg));
   4759     buffer_reply = bfd_info->dma_buffer;
   4760     buffer_ptr   = bfd_sdk_version_exchange_msg_unpack(buffer_reply, &uc_msg);
   4761     buffer_len   = buffer_ptr - buffer_reply;
   4762 
   4763     if (reply_len != buffer_len) {
   4764         return BCM_E_INTERNAL;
   4765     }
   4766 
   4767     bfd_firmware_version = uc_msg.version;
   4768     return BCM_E_NONE;
   4769 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   4770     return BCM_E_UNAVAIL;
   4771 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   4772 }
   4773 #endif
   4774 
   4775 /*
   4776  * Function:
   4777  *      bcmi_xgs5_bfd_match_id
   4778  * Purpose:
   4779  *      Initialize the Match ID for BFD packet processing.
   4780  * Parameters:
   4781  *      unit - (IN) Unit number.
   4782  * Returns:
   4783  *      BCM_E_XXX
   4784  * Notes:
   4785  */
   4786 #if defined(BCM_TRIDENT3_SUPPORT)
   4787 STATIC int
   4788 bcmi_xgs5_bfd_match_id(int unit, bfd_info_t *bfd_info)
   4789 {
   4790     int rv = BCM_E_NONE;
   4791     bfd_sdk_msg_match_id_map_t match_id_field = {0};
   4792     uint8 *buffer, *buffer_ptr;
   4793     uint16 buffer_len, reply_len;
   4794     soc_cancun_ceh_field_info_t  ceh_info;
   4795     uint16   zone_width[5];
   4796 
   4797     /* Zone Match ID Width as defined by CANCUN */
   4798     /*
   4799      *
   4800      * --------------------------------------------------------------------------------------------------------------------------
   4801      * | <---   49 - 39   --->  | <---   38 - 28   ---> | <---   27 - 17   ---> | <---   16 - 06   ---> | <---   05 - 00   ---> |
   4802      * | <--- Z4_MATCH_ID --->  | <--- Z3_MATCH_ID ---> | <--- Z2_MATCH_ID ---> | <--- Z1_MATCH_ID ---> | <--- Z0_MATCH_ID ---> |
   4803      * --------------------------------------------------------------------------------------------------------------------------
   4804  */
   4805     rv = soc_cancun_ceh_obj_field_get(unit, "MATCH_ID", "Z0_MATCH_ID", &ceh_info);
   4806     if (rv != SOC_E_NONE){
   4807         return BCM_E_INTERNAL;
   4808     }
   4809 
   4810     /* Convert BFD uController error code to BCM */
   4811     zone_width[0] = ceh_info.width;
   4812     rv = soc_cancun_ceh_obj_field_get(unit, "MATCH_ID", "Z1_MATCH_ID", &ceh_info);
   4813     if (rv != SOC_E_NONE){
   4814         return BCM_E_INTERNAL;
   4815     }
   4816 
   4817     zone_width[1] = ceh_info.width;
   4818     rv = soc_cancun_ceh_obj_field_get(unit, "MATCH_ID", "Z2_MATCH_ID", &ceh_info);
   4819     if (rv != SOC_E_NONE){
   4820         return BCM_E_INTERNAL;
   4821     }
   4822 
   4823     zone_width[2] = ceh_info.width;
   4824     rv = soc_cancun_ceh_obj_field_get(unit, "MATCH_ID", "Z3_MATCH_ID", &ceh_info);
   4825     if (rv != SOC_E_NONE){
   4826         return BCM_E_INTERNAL;
   4827     }
   4828 
   4829     zone_width[3] = ceh_info.width;
   4830     rv = soc_cancun_ceh_obj_field_get(unit, "MATCH_ID", "Z4_MATCH_ID", &ceh_info);
   4831     if (rv != SOC_E_NONE){
   4832         return BCM_E_INTERNAL;
   4833     }
   4834 
   4835     zone_width[4] = ceh_info.width;
   4836 
   4837     match_id_field.match_id_length = (zone_width[0] + zone_width[1] +
   4838                                        zone_width[2] + zone_width[3] +
   4839                                        zone_width[4]);
   4840 
   4841     /* Zone 1 L2 details */
   4842     /*
   4843      *
   4844      * ------------------------------------------------------------------------------------------
   4845      * |  10    |   9   |   8   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
   4846      * |        |       |       |       |       |       |       | ITAG  |       |       |       |
   4847      * |        |       |       |       |       |       |<--OTAG_ITAG-->|       |       |       |
   4848      * ------------------------------------------------------------------------------------------
   4849  */
   4850     /* Single TAG value = 1 offset = 3 width = 2 */
   4851     rv = soc_cancun_ceh_obj_field_get(unit, "Z1_MATCH_ID", "SINGLE_OTAG", &ceh_info);
   4852     if (rv != SOC_E_NONE){
   4853         return BCM_E_INTERNAL;
   4854     }
   4855 
   4856     match_id_field.match_id_fields[SHR_BFD_UC_SINGLE_TAG].offset =
   4857                                          (ceh_info.offset + zone_width[0]);
   4858     match_id_field.match_id_fields[SHR_BFD_UC_SINGLE_TAG].width = ceh_info.width;
   4859     match_id_field.match_id_fields[SHR_BFD_UC_SINGLE_TAG].value = ceh_info.value;
   4860     match_id_field.match_id_types += 1;
   4861 
   4862     /* Double TAG value = 3  offset = 3 width = 2 */
   4863     rv = soc_cancun_ceh_obj_field_get(unit, "Z1_MATCH_ID", "OTAG_ITAG", &ceh_info);
   4864     if (rv != SOC_E_NONE){
   4865         return BCM_E_INTERNAL;
   4866     }
   4867 
   4868     match_id_field.match_id_fields[SHR_BFD_UC_DOUBLE_TAG].offset = (ceh_info.offset + zone_width[0]);
   4869     match_id_field.match_id_fields[SHR_BFD_UC_DOUBLE_TAG].width = ceh_info.width;
   4870     match_id_field.match_id_fields[SHR_BFD_UC_DOUBLE_TAG].value = ceh_info.value;
   4871     match_id_field.match_id_types += 1;
   4872 
   4873     /* Zone 2 OUTER L3/MPLS/UDP/BFD details */
   4874     /*
   4875      *
   4876      * ------------------------------------------------------------------------------------------
   4877      * |  10    |   9   |   8   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
   4878      * |        |       |       |  MPLS | <---    MPLS     ---> |       |  MPLS |  IPV4 |  IPV6 |
   4879      * |        |       |       |   CW  | <---  NUM LABELS ---> | <--- GRE ---> |       |       |
   4880      * |        |       |       |       |       |       |  BFD  |       |       |       |       |
   4881      * ------------------------------------------------------------------------------------------
   4882  */
   4883     /* Outer IPV4 value = 2  offset = 0 width = 2 */
   4884     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "IPV4", &ceh_info);
   4885     if (rv != SOC_E_NONE){
   4886         return BCM_E_INTERNAL;
   4887     }
   4888 
   4889     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_IPV4].offset = (ceh_info.offset + zone_width[0] +
   4890                                                 zone_width[1]);
   4891     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_IPV4].width = ceh_info.width;
   4892     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_IPV4].value = ceh_info.value;
   4893     match_id_field.match_id_types += 1;
   4894 
   4895     /* Outer IPV6 value = 1  offset = 0 width = 2 */
   4896     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "IPV6", &ceh_info);
   4897     if (rv != SOC_E_NONE){
   4898         return BCM_E_INTERNAL;
   4899     }
   4900 
   4901     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_IPV6].offset = (ceh_info.offset + zone_width[0] +
   4902                                                 zone_width[1]);
   4903     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_IPV6].width = ceh_info.width;
   4904     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_IPV6].value = ceh_info.value;
   4905     match_id_field.match_id_types += 1;
   4906 
   4907     /* Outer GRE value = 3  offset = 2 width = 5 */
   4908     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "GRE", &ceh_info);
   4909     if (rv != SOC_E_NONE){
   4910         return BCM_E_INTERNAL;
   4911     }
   4912 
   4913     match_id_field.match_id_fields[SHR_BFD_UC_GRE].offset = (ceh_info.offset + zone_width[0] +
   4914                                                 zone_width[1]);
   4915     match_id_field.match_id_fields[SHR_BFD_UC_GRE].width = ceh_info.width;
   4916     match_id_field.match_id_fields[SHR_BFD_UC_GRE].value = ceh_info.value;
   4917     match_id_field.match_id_types += 1;
   4918 
   4919     /* Outer IPINGRE value = 12  offset = 2 width = 5 */
   4920     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "IPINGRE", &ceh_info);
   4921     if (rv != SOC_E_NONE){
   4922         return BCM_E_INTERNAL;
   4923     }
   4924 
   4925     match_id_field.match_id_fields[SHR_BFD_UC_IPINGRE].offset = (ceh_info.offset + zone_width[0] +
   4926                                                 zone_width[1]);
   4927     match_id_field.match_id_fields[SHR_BFD_UC_IPINGRE].width = ceh_info.width;
   4928     match_id_field.match_id_fields[SHR_BFD_UC_IPINGRE].value = ceh_info.value;
   4929     match_id_field.match_id_types += 1;
   4930 
   4931     /* Outer IPINIP value = 11  offset = 2 width = 5 */
   4932     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "IPINIP", &ceh_info);
   4933     if (rv != SOC_E_NONE){
   4934         return BCM_E_INTERNAL;
   4935     }
   4936 
   4937     match_id_field.match_id_fields[SHR_BFD_UC_IPINIP].offset = (ceh_info.offset + zone_width[0] +
   4938                                                 zone_width[1]);
   4939     match_id_field.match_id_fields[SHR_BFD_UC_IPINIP].width = ceh_info.width;
   4940     match_id_field.match_id_fields[SHR_BFD_UC_IPINIP].value = ceh_info.value;
   4941     match_id_field.match_id_types += 1;
   4942 
   4943     /* Outer IP UDP value = 17 offset = 2 width = 5 */
   4944     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "UDP", &ceh_info);
   4945     if (rv != SOC_E_NONE){
   4946         return BCM_E_INTERNAL;
   4947     }
   4948 
   4949     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_UDP].offset = (ceh_info.offset + zone_width[0] +
   4950                                                 zone_width[1]);
   4951     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_UDP].width = ceh_info.width;
   4952     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_UDP].value = ceh_info.value;
   4953     match_id_field.match_id_types += 1;
   4954 
   4955     /* Outer IP UDP BFD value = 4 offset = 2 width = 5 */
   4956     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "BFD", &ceh_info);
   4957     if (rv != SOC_E_NONE){
   4958         return BCM_E_INTERNAL;
   4959     }
   4960 
   4961     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_BFD].offset = (ceh_info.offset + zone_width[0] +
   4962                                                 zone_width[1]);
   4963     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_BFD].width = ceh_info.width;
   4964     match_id_field.match_id_fields[SHR_BFD_UC_OUTER_BFD].value = ceh_info.value;
   4965     match_id_field.match_id_types += 1;
   4966 
   4967     /* Zone 4 OUTER L3/MPLS/UDP/BFD details */
   4968     /*
   4969      *
   4970      * ------------------------------------------------------------------------------------------
   4971      * |  10    |   9   |   8   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
   4972      * |        |       |       |  MPLS | <---    MPLS     ---> |       |  MPLS |  IPV4 |  IPV6 |
   4973      * |        |       |       |   CW  | <---  NUM LABELS ---> |       |       |       |       |
   4974      * |        |       |       |       |       |       |  BFD  |       |       |       |       |
   4975      * ------------------------------------------------------------------------------------------
   4976  */
   4977     /* Inner IPV4 value = 2  offset = 0 width = 2 */
   4978     rv = soc_cancun_ceh_obj_field_get(unit, "Z4_MATCH_ID", "IPV4", &ceh_info);
   4979     if (rv != SOC_E_NONE){
   4980         return BCM_E_INTERNAL;
   4981     }
   4982 
   4983     match_id_field.match_id_fields[SHR_BFD_UC_IPV4_IN].offset = (ceh_info.offset + zone_width[0] +
   4984                                                 zone_width[1] + zone_width[2] + zone_width[3]);
   4985     match_id_field.match_id_fields[SHR_BFD_UC_IPV4_IN].width = ceh_info.width;
   4986     match_id_field.match_id_fields[SHR_BFD_UC_IPV4_IN].value = ceh_info.value;
   4987     match_id_field.match_id_types += 1;
   4988 
   4989     /* Inner IPV6 value = 1  offset = 0 width = 2 */
   4990     rv = soc_cancun_ceh_obj_field_get(unit, "Z4_MATCH_ID", "IPV6", &ceh_info);
   4991     if (rv != SOC_E_NONE){
   4992         return BCM_E_INTERNAL;
   4993     }
   4994 
   4995     match_id_field.match_id_fields[SHR_BFD_UC_IPV6_IN].offset = (ceh_info.offset + zone_width[0] +
   4996                                                 zone_width[1] + zone_width[2] + zone_width[3]);
   4997     match_id_field.match_id_fields[SHR_BFD_UC_IPV6_IN].width = ceh_info.width;
   4998     match_id_field.match_id_fields[SHR_BFD_UC_IPV6_IN].value = ceh_info.value;
   4999     match_id_field.match_id_types += 1;
   5000 
   5001     /* Outer GRE value = 3  offset = 2 width = 5 */
   5002     rv = soc_cancun_ceh_obj_field_get(unit, "Z4_MATCH_ID", "GRE", &ceh_info);
   5003     if (rv != SOC_E_NONE){
   5004         return BCM_E_INTERNAL;
   5005     }
   5006 
   5007     match_id_field.match_id_fields[SHR_BFD_UC_GRE_IN].offset = (ceh_info.offset + zone_width[0] +
   5008                                                 zone_width[1] + zone_width[2] + zone_width[3]);
   5009     match_id_field.match_id_fields[SHR_BFD_UC_GRE_IN].width = ceh_info.width;
   5010     match_id_field.match_id_fields[SHR_BFD_UC_GRE_IN].value = ceh_info.value;
   5011     match_id_field.match_id_types += 1;
   5012 
   5013     /* Inner IP UDP value = 17 offset = 2 width = 5 */
   5014     rv = soc_cancun_ceh_obj_field_get(unit, "Z4_MATCH_ID", "UDP", &ceh_info);
   5015     if (rv != SOC_E_NONE){
   5016         return BCM_E_INTERNAL;
   5017     }
   5018 
   5019     match_id_field.match_id_fields[SHR_BFD_UC_INNER_UDP].offset = (ceh_info.offset + zone_width[0] +
   5020                                                 zone_width[1] + zone_width[2] + zone_width[3]);
   5021     match_id_field.match_id_fields[SHR_BFD_UC_INNER_UDP].width = ceh_info.width;
   5022     match_id_field.match_id_fields[SHR_BFD_UC_INNER_UDP].value = ceh_info.value;
   5023     match_id_field.match_id_types += 1;
   5024 
   5025     /* Inner IP UDP BFD value = 4 offset = 2 width = 5 */
   5026     rv = soc_cancun_ceh_obj_field_get(unit, "Z4_MATCH_ID", "BFD", &ceh_info);
   5027     if (rv != SOC_E_NONE){
   5028         return BCM_E_INTERNAL;
   5029     }
   5030 
   5031     match_id_field.match_id_fields[SHR_BFD_UC_INNER_BFD].offset = (ceh_info.offset + zone_width[0] +
   5032                                                  zone_width[1] + zone_width[2] + zone_width[3]);
   5033     match_id_field.match_id_fields[SHR_BFD_UC_INNER_BFD].width = ceh_info.width;
   5034     match_id_field.match_id_fields[SHR_BFD_UC_INNER_BFD].value = ceh_info.value;
   5035     match_id_field.match_id_types += 1;
   5036 
   5037     /* MPLS value = 4 offset = 0 width = 4 */
   5038     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "MPLS", &ceh_info);
   5039     if (rv != SOC_E_NONE){
   5040         return BCM_E_INTERNAL;
   5041     }
   5042 
   5043     match_id_field.match_id_fields[SHR_BFD_UC_MPLS].offset = (ceh_info.offset + zone_width[0] +
   5044                                                  zone_width[1]);
   5045     match_id_field.match_id_fields[SHR_BFD_UC_MPLS].width = ceh_info.width;
   5046     match_id_field.match_id_fields[SHR_BFD_UC_MPLS].value = ceh_info.value;
   5047     match_id_field.match_id_types += 1;
   5048 
   5049     /* Number of label can be obtained (((value - 4) / 16) + 1)
   5050      * MSB bit represent CW
   5051      * MPLS LABEL DETIALS
   5052      */
   5053     rv = soc_cancun_ceh_obj_field_get(unit, "Z2_MATCH_ID", "MPLS_1_LABEL_WITH_CW", &ceh_info);
   5054     if (rv != SOC_E_NONE){
   5055         return BCM_E_INTERNAL;
   5056     }
   5057 
   5058     match_id_field.match_id_fields[SHR_BFD_UC_MPLS_LABEL].offset = (ceh_info.offset + zone_width[0] +
   5059                                                  zone_width[1]);
   5060     match_id_field.match_id_fields[SHR_BFD_UC_MPLS_LABEL].width = ceh_info.width;
   5061     match_id_field.match_id_fields[SHR_BFD_UC_MPLS_LABEL].value = ceh_info.value;
   5062     match_id_field.match_id_types += 1;
   5063 
   5064     if(match_id_field.match_id_types >= MAX_MATCH_ID_FIELDS) {
   5065         LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   5066                   "BFD match id array over flow.\n")));
   5067         return BCM_E_INTERNAL;
   5068     }
   5069 
   5070     buffer     = bfd_info->dma_buffer;
   5071     buffer_ptr = bfd_sdk_msg_match_id_map_pack(buffer, &match_id_field);
   5072     buffer_len = buffer_ptr - buffer;
   5073 
   5074      rv = bcmi_xgs5_bfd_msg_send_receive(unit,
   5075                                          MOS_MSG_SUBCLASS_BFD_MATCH_ID,
   5076                                          buffer_len, 0,
   5077                                          MOS_MSG_SUBCLASS_BFD_MATCH_ID_REPLY,
   5078                                          &reply_len, bfd_uc_msg_timeout_usecs);
   5079     if ((rv != BCM_E_UNAVAIL) &&
   5080         (BCM_FAILURE(rv) || (reply_len != 0))) {
   5081         return BCM_E_INTERNAL;
   5082     }
   5083     return rv;
   5084 }
   5085 #endif
   5086 
   5087 /*
   5088  * Function:
   5089  *      bcmi_xgs5_bfd_init
   5090  * Purpose:
   5091  *      Initialize the BFD subsystem
   5092  * Parameters:
   5093  *      unit - (IN) Unit number.
   5094  * Returns:
   5095  *      BCM_E_NONE Operation completed successfully
   5096  *      BCM_E_MEMORY Unable to allocate memory for internal control structures
   5097  *      BCM_E_INTERNAL Failed to initialize
   5098  *      BCM_E_CONFIG   Configuration error 
   5099  *      BCM_E_UNAVAIL  Not supported 
   5100  * Notes:
   5101  *      BFD initialization will return BCM_E_NONE for the following
   5102  *      error conditions (i.e. feature not supported):
   5103  *      - uKernel is not loaded
   5104  *      - BFD application is not found in any of the uC uKernel
   5105  */
   5106 int
   5107 bcmi_xgs5_bfd_init(int unit,
   5108                    bcm_esw_bfd_drv_t *drv,
   5109                    bcm_xgs5_bfd_hw_defs_t *hw_defs)
   5110 {
   5111 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   5112     int rv = BCM_E_NONE;
   5113     bfd_info_t *bfd_info;
   5114     int num_sessions;
   5115     int num_auth_sha1, num_auth_sp;
   5116     int cpu_cosq;
   5117     bfd_sdk_msg_ctrl_init_t msg_init;
   5118     uint8 *buffer, *buffer_ptr;
   5119     uint16 buffer_len, reply_len;
   5120     int uc;
   5121     int priority;
   5122     uint32 bfd_encap_memory_size = 0;
   5123     uint8  session_down_on_create = 0;
   5124     int    status;
   5125     bfd_sdk_msg_ctrl_trace_log_enable_t msg_trace;
   5126 
   5127     FEATURE_CHECK(unit);
   5128 
   5129     PARAM_NULL_CHECK(drv);
   5130     PARAM_NULL_CHECK(hw_defs);
   5131 
   5132     if (SAL_BOOT_QUICKTURN) {
   5133         bfd_uc_msg_timeout_usecs = BFD_UC_MSG_TIMEOUT_USECS_QUICKTURN;
   5134     } else {
   5135         bfd_uc_msg_timeout_usecs = BFD_UC_MSG_TIMEOUT_USECS;
   5136     }
   5137 
   5138     /*
   5139      * Initialize uController side
   5140      */
   5141 
   5142     /*
   5143      * Start BFD application in BTE (Broadcom Task Engine) uController,
   5144      * if not already running (warm boot).
   5145      * Determine which uController is running BFD  by choosing the first
   5146      * uC that returns successfully.
   5147      */
   5148     for (uc = 0; uc < CMICM_NUM_UCS; uc++) {
   5149         rv = soc_uc_status(unit, uc, &status);
   5150         if ((rv == SOC_E_NONE) && (status != 0)) {
   5151             rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BFD,
   5152                                        bfd_uc_msg_timeout_usecs,
   5153                                        BFD_SDK_VERSION,
   5154                                        BFD_UC_MIN_VERSION,
   5155                                        NULL, NULL);
   5156             if (SOC_E_NONE == rv) {
   5157                 /* BFD started successfully */
   5158                 break;
   5159             }
   5160         }
   5161     }
   5162 
   5163     if (uc >= CMICM_NUM_UCS) {
   5164         /* Could not find or start BFD appl */
   5165         LOG_WARN(BSL_LS_BCM_BFD,
   5166                  (BSL_META_U(unit,
   5167                              "uKernel BFD application not available\n")));
   5168         return BCM_E_NONE;
   5169     }
   5170 
   5171     /* Detach if already initialized */
   5172     if (BFD_INIT(unit)) {
   5173         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_detach(unit));
   5174     }
   5175 
   5176     /* Install Tables */
   5177     BCM_ESW_BFD_DRV(unit) = drv;
   5178     BFD_HW(unit)          = hw_defs;
   5179 
   5180     /* Get SOC properties */
   5181     num_sessions = soc_property_get(unit, spn_BFD_NUM_SESSIONS, 256);
   5182 
   5183     /*BFD Endpoint with ID 0 is not supported in TRIDENT3*/
   5184     if (SOC_IS_TRIDENT3X(unit)) {
   5185         num_sessions = num_sessions + 1;
   5186     }
   5187     if (num_sessions > BFD_MAX_NUM_ENDPOINTS) {
   5188         return BCM_E_CONFIG;
   5189     }
   5190     num_auth_sha1 = soc_property_get(unit, spn_BFD_SHA1_KEYS, 0);
   5191     num_auth_sp   = soc_property_get(unit, spn_BFD_SIMPLE_PASSWORD_KEYS, 0);
   5192     cpu_cosq      = soc_property_get(unit, spn_BFD_COSQ, BFD_COSQ_INVALID);
   5193     bfd_encap_memory_size =
   5194                     soc_property_get(unit, spn_BFD_ENCAP_MEMORY_SIZE, 0);
   5195     if (bfd_encap_memory_size > SHR_BFD_MAX_ENCAP_LENGTH) {
   5196         LOG_ERROR(BSL_LS_BCM_BFD,
   5197                  (BSL_META_U(unit,
   5198                              "BFD encap memory size greater than max\n")));
   5199         return BCM_E_CONFIG;
   5200     }
   5201     session_down_on_create = soc_property_get(unit, 
   5202                                     spn_BFD_SESSION_DOWN_EVENT_ON_CREATE, 0);
   5203 
   5204     /*
   5205      * Initialize HOST side
   5206      */
   5207     rv = bcmi_xgs5_bfd_alloc_resource(unit, num_sessions,
   5208                                       num_auth_sha1, num_auth_sp);
   5209     if (BCM_FAILURE(rv)) {
   5210         bcmi_xgs5_bfd_free_resource(unit);
   5211         return rv;
   5212     }
   5213 
   5214     bfd_info                     = BFD_INFO(unit);
   5215     bfd_info->unit               = unit;
   5216     bfd_info->uc_num             = uc;
   5217     bfd_info->endpoint_count     = num_sessions;
   5218     bfd_info->num_auth_sha1_keys = num_auth_sha1;
   5219     bfd_info->num_auth_sp_keys   = num_auth_sp;
   5220     bfd_info->cpu_cosq           = cpu_cosq;
   5221     bfd_info->cosq_spath_index   = -1;
   5222     bfd_info->cosq_ach_err_index = -1;
   5223     bfd_info->cosq_unknown_version_index = -1;
   5224     bfd_info->bfd_feature_enable = hw_defs->bfd_feature_enable;
   5225 
   5226     /* RX DMA channel (0..3) local to the uC */
   5227     bfd_info->rx_channel = BCM_XGS5_BFD_RX_CHANNEL;
   5228 
   5229     bfd_info->use_sess_id_as_discr   = soc_property_get(unit,
   5230                                     spn_BFD_USE_ENDPOINT_ID_AS_DISCRIMINATOR, 0);
   5231     bfd_info->static_remote_discr = soc_property_get(unit, spn_BFD_REMOTE_DISCRIMINATOR, 0);
   5232     bfd_info->bfd_cpi_bit = soc_property_get(unit, spn_BFD_CONTROL_PLANE_INDEPENDENCE, 1);
   5233 
   5234 #ifdef BCM_WARM_BOOT_SUPPORT
   5235     if (!SOC_WARM_BOOT(unit)) {
   5236 #endif
   5237 
   5238     /* Set control message data */
   5239     sal_memset(&msg_init, 0, sizeof(msg_init));
   5240     msg_init.num_sessions       = bfd_info->endpoint_count;
   5241     msg_init.encap_size         = bfd_encap_memory_size;
   5242     msg_init.num_auth_sha1_keys = bfd_info->num_auth_sha1_keys;
   5243     msg_init.num_auth_sp_keys   = bfd_info->num_auth_sp_keys;
   5244     msg_init.rx_channel         = bfd_info->rx_channel;
   5245     if (BFD_UC_FEATURE_CHECK(BFD_FEATURE_INIT_CONFIG_FLAGS)) {
   5246         msg_init.config_flags  |= 
   5247             (session_down_on_create?BFD_CONFIG_SESSION_DOWN_EVENT_ON_CREATE:0);
   5248         msg_init.config_flags  |= 
   5249             ((bfd_info->use_sess_id_as_discr)?BFD_CONFIG_SESSION_ID_AS_DISCR:0);
   5250         msg_init.config_flags  |=
   5251             ((bfd_info->static_remote_discr)?BFD_CONFIG_STATIC_REMOTE_DISCR:0);
   5252         msg_init.config_flags  |=
   5253             ((bfd_info->bfd_cpi_bit)?BFD_CONFIG_CONTROL_PLANE_BIT:0);
   5254     }
   5255     
   5256     /* Pack control message data into DMA buffer */
   5257     buffer     = bfd_info->dma_buffer;
   5258     buffer_ptr = bfd_sdk_msg_ctrl_init_pack(buffer, &msg_init);
   5259     buffer_len = buffer_ptr - buffer;
   5260 
   5261     /* Send BFD Init message to uC */
   5262     rv = bcmi_xgs5_bfd_msg_send_receive(unit,
   5263                                         MOS_MSG_SUBCLASS_BFD_INIT,
   5264                                         buffer_len, 0,
   5265                                         MOS_MSG_SUBCLASS_BFD_INIT_REPLY,
   5266                                         &reply_len, bfd_uc_msg_timeout_usecs);
   5267 
   5268     if (BCM_FAILURE(rv) || (reply_len != 0)) {
   5269         bcmi_xgs5_bfd_free_resource(unit);
   5270         if (BCM_SUCCESS(rv)) {
   5271             rv = BCM_E_INTERNAL;
   5272         }
   5273         return rv;
   5274     }
   5275 
   5276     bfd_info->trace_addr = 0;
   5277     if (BFD_UC_FEATURE_CHECK(BFD_FEATURE_DBG_TRACE)) {
   5278         BCM_IF_ERROR_RETURN(
   5279            bcmi_xgs5_bfd_msg_send_receive(unit,
   5280                                           MOS_MSG_SUBCLASS_BFD_TRACE_LOG_ENABLE,
   5281                                           BFD_TRACE_LOG_MAX_SIZE, 0,
   5282                                           MOS_MSG_SUBCLASS_BFD_TRACE_LOG_ENABLE_REPLY,
   5283                                           &reply_len,
   5284                                           bfd_uc_msg_timeout_usecs));
   5285 
   5286         sal_memset(&msg_trace, 0, sizeof(msg_trace));
   5287         buffer     = bfd_info->dma_buffer;
   5288         buffer_ptr = bfd_sdk_msg_ctrl_trace_log_enable_unpack(buffer, &msg_trace);
   5289         buffer_len = buffer_ptr - buffer;
   5290 
   5291         if (reply_len != buffer_len) {
   5292             return BCM_E_INTERNAL;
   5293         }
   5294         bfd_info->trace_addr = msg_trace.addr_lo;
   5295     }
   5296 
   5297 
   5298 #if defined(BCM_TOMAHAWK_SUPPORT)
   5299     if (SOC_IS_TOMAHAWKX(unit) ||
   5300         SOC_IS_TRIDENT3X(unit)) {
   5301         int max_num_port = SOC_INFO(unit).port.max ,min_num_port = SOC_INFO(unit).port.min;
   5302         int i = 0;
   5303         bfd_sdk_msg_port_txqueue_map_t queue_map = {0};
   5304         uint8 *buffer, *buffer_ptr;
   5305         uint16 buffer_len, reply_len;
   5306 
   5307         queue_map.max_num_port = max_num_port;
   5308         for(i = min_num_port; i <= max_num_port; i++) {
   5309             queue_map.tx_queue[i] = SOC_INFO(unit).port_uc_cosq_base[i];
   5310         }
   5311 
   5312         buffer     = bfd_info->dma_buffer;
   5313         buffer_ptr = bfd_sdk_msg_port_txqueue_map_pack(buffer, &queue_map);
   5314         buffer_len = buffer_ptr - buffer;
   5315 
   5316          rv = bcmi_xgs5_bfd_msg_send_receive(unit,
   5317                                              MOS_MSG_SUBCLASS_BFD_PORT_TX_QNUM,
   5318                                              buffer_len, 0,
   5319                                              MOS_MSG_SUBCLASS_BFD_PORT_TX_QNUM_REPLY,
   5320                                              &reply_len, bfd_uc_msg_timeout_usecs);
   5321         if ((rv != BCM_E_UNAVAIL)
   5322             && (BCM_FAILURE(rv) || (reply_len != 0))) {
   5323             bcmi_xgs5_bfd_free_resource(unit);
   5324             return BCM_E_INTERNAL;
   5325         }
   5326     }
   5327 #endif
   5328 
   5329 #if defined(BCM_TRIDENT3_SUPPORT)
   5330     if(SOC_IS_TRIDENT3X(unit)) {
   5331         rv = bcmi_xgs5_bfd_match_id(unit, bfd_info);
   5332         if (BCM_FAILURE(rv)) {
   5333             bcmi_xgs5_bfd_free_resource(unit);
   5334             return rv;
   5335         }
   5336     }
   5337 #endif
   5338     /*
   5339      * Initialize HW
   5340      */
   5341     rv = bcmi_xgs5_bfd_hw_init(unit);
   5342     if (BCM_FAILURE(rv)) {
   5343         BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_detach(unit));
   5344         return rv;
   5345     }
   5346 #ifdef BCM_WARM_BOOT_SUPPORT
   5347    } 
   5348 #endif
   5349 
   5350     /*
   5351      * Initialize Event handler
   5352      */
   5353     /* Start event thread handler */
   5354     priority = soc_property_get(unit, spn_BFD_THREAD_PRI, BCM_ESW_BFD_THREAD_PRI_DFLT);
   5355     if (bfd_info->event_thread_id == NULL) {
   5356         if ((bfd_info->event_thread_id =
   5357             sal_thread_create("bcmBFD", SAL_THREAD_STKSZ,
   5358                               priority,
   5359                               (void (*)(void*))bcmi_xgs5_bfd_callback_thread,
   5360                               INT_TO_PTR(unit))) == SAL_THREAD_ERROR) {
   5361             if (SAL_BOOT_QUICKTURN) {
   5362                 /* If emulation, then wait */
   5363                 sal_usleep(1000000);
   5364             }
   5365 
   5366             if (bfd_info->event_thread_id == NULL) {
   5367                 BCM_IF_ERROR_RETURN(bcmi_xgs5_bfd_detach(unit));
   5368                 return BCM_E_MEMORY;
   5369             }
   5370         }
   5371     }
   5372 
   5373     /* Module has been initialized */
   5374     bfd_info->initialized = 1;
   5375 
   5376 #if defined(BCM_WARM_BOOT_SUPPORT)
   5377     bfd_info->wb_current_version = BCM_BFD_WB_DEFAULT_VERSION;
   5378     bfd_info->wb_next_version = BCM_BFD_WB_DEFAULT_VERSION;
   5379 
   5380     if(!SOC_WARM_BOOT(unit)) {
   5381         bcmi_xgs5_bfd_scache_alloc(unit);
   5382     }
   5383     if (SOC_WARM_BOOT(unit)) {
   5384         rv = bcmi_xgs5_bfd_reinit(unit);
   5385         if (BCM_FAILURE(rv)) {
   5386             bcmi_xgs5_bfd_free_resource(unit);
   5387             return (rv);
   5388         }
   5389         rv = bcmi_xgs5_bfd_version_exchange(unit);
   5390         if (BCM_FAILURE(rv)) {
   5391             bcmi_xgs5_bfd_free_resource(unit);
   5392             return rv;
   5393         }
   5394 
   5395     }
   5396 #endif
   5397 
   5398     return BCM_E_NONE;
   5399 
   5400 #else  /* BCM_CMICX_SUPPORT || BCM_CMICX_SUPPORT */
   5401     return BCM_E_UNAVAIL;
   5402 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   5403 }
   5404 
   5405 /*
   5406  * Function:
   5407  *      bcmi_xgs5_bfd_detach
   5408  * Purpose:
   5409  *      Shut down the BFD subsystem
   5410  * Parameters:
   5411  *      unit - (IN) Unit number.
   5412  * Returns:
   5413  *      BCM_E_NONE Operation completed successfully
   5414  * Notes:
   5415  *      In progress...
   5416  */
   5417 int
   5418 bcmi_xgs5_bfd_detach(int unit)
   5419 {
   5420 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   5421     int rv;
   5422     bfd_info_t *bfd_info = BFD_INFO(unit);
   5423     bfd_endpoint_config_t *endpoint_config;
   5424     uint16 reply_len;
   5425     int index;
   5426     sal_usecs_t timeout = 0;
   5427     int status;
   5428 
   5429     FEATURE_CHECK(unit);
   5430 
   5431     if (!BFD_INIT(unit)) {
   5432         return BCM_E_NONE;
   5433     }
   5434 
   5435     /* Delete BFD Sessions in HW device */
   5436     for (index = 0; index < bfd_info->endpoint_count; index++) {
   5437         if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   5438             endpoint_config = BFD_ENDPOINT_CONFIG(unit, index);
   5439 
   5440             bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config);
   5441 
   5442             SHR_BITCLR(bfd_info->endpoints_in_use,
   5443                        endpoint_config->endpoint_index);
   5444             endpoint_config->endpoint_index = -1;
   5445             endpoint_config->is_l3_vpn = 0;
   5446             endpoint_config->is_micro_bfd = 0;
   5447             endpoint_config->local_echo = 0;
   5448         }
   5449     }
   5450 
   5451     /* Event Handler thread exit signal */
   5452     timeout = sal_time_usecs() + 5000000;
   5453     while (NULL !=  bfd_info->event_thread_id) {
   5454         soc_cmic_uc_msg_receive_cancel(unit, bfd_info->uc_num,
   5455                                        MOS_MSG_CLASS_BFD_EVENT);
   5456 
   5457         if (sal_time_usecs() < timeout) {
   5458             /*give some time to already running bfd callback thread
   5459              * to schedule and exit */
   5460             sal_usleep(10000);
   5461         } else {
   5462             /*timeout*/
   5463             LOG_ERROR(BSL_LS_BCM_OAM,
   5464                       (BSL_META_U(unit,
   5465                                   "BFD event thread did not exit.\n")));
   5466             return BCM_E_INTERNAL;
   5467         }
   5468     }
   5469 
   5470 
   5471     if (!SOC_WARM_BOOT(unit)) {
   5472         /*
   5473          * Send BFD Uninit message to uC
   5474          * Ignore error since that may indicate uKernel was reloaded.
   5475          */
   5476         SOC_IF_ERROR_RETURN(soc_uc_status(unit, bfd_info->uc_num, &status));
   5477         if (status) {
   5478             rv = bcmi_xgs5_bfd_msg_send_receive(unit,
   5479                                                 MOS_MSG_SUBCLASS_BFD_UNINIT,
   5480                                                 0, 0,
   5481                                                 MOS_MSG_SUBCLASS_BFD_UNINIT_REPLY,
   5482                                                 &reply_len, 5000000);
   5483             if (BCM_SUCCESS(rv) && (reply_len != 0)) {
   5484                 return BCM_E_INTERNAL;
   5485             }
   5486         }
   5487 #if defined(BCM_TOMAHAWK_SUPPORT)
   5488         if(!(SOC_IS_TOMAHAWKX(unit) ||
   5489              SOC_IS_TRIDENT3X(unit))) {
   5490 #endif
   5491          /* Delete CPU COS queue mapping entries for BFD packets */
   5492          if (bfd_info->cosq_spath_index >= 0) {
   5493              (void) bcm_esw_rx_cosq_mapping_delete(unit,
   5494                                                    bfd_info->cosq_spath_index);
   5495              bfd_info->cosq_spath_index = -1;
   5496          }
   5497          if (bfd_info->cosq_ach_err_index >= 0) {
   5498              (void) bcm_esw_rx_cosq_mapping_delete(unit,
   5499                                                   bfd_info->cosq_ach_err_index);
   5500              bfd_info->cosq_ach_err_index = -1;
   5501          }
   5502          if (bfd_info->cosq_unknown_version_index >= 0) {
   5503              (void) bcm_esw_rx_cosq_mapping_delete(unit,
   5504                                                    bfd_info->cosq_unknown_version_index);
   5505              bfd_info->cosq_unknown_version_index = -1;
   5506          }
   5507 
   5508          /* Delete entry for special Session-ID for Unknown Remote Discriminator */
   5509          (void) bcmi_xgs5_bfd_l2_entry_clear(unit,
   5510                                              0, 0,
   5511                                              SHR_BFD_DISCR_UNKNOWN_YOUR_DISCR);
   5512 
   5513 #if defined(BCM_TOMAHAWK_SUPPORT)
   5514       }
   5515 #endif
   5516     }
   5517 
   5518     /* Free resources */
   5519     bcmi_xgs5_bfd_event_unregister_all(unit);
   5520     bcmi_xgs5_bfd_free_resource(unit);
   5521     bcm_xgs5_bfd_info[unit] = NULL;
   5522 
   5523     /* Uninstall Tables */
   5524     BCM_ESW_BFD_DRV(unit) = NULL;
   5525     BFD_HW(unit)          = NULL;
   5526 
   5527     return BCM_E_NONE;
   5528 
   5529 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   5530     return BCM_E_UNAVAIL;
   5531 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   5532 }
   5533 
   5534 /*
   5535  * Function:
   5536  *     _bcm_sb2_oam_endpoint_gport_resolve
   5537  * Purpose:
   5538  *     Resolve an endpoint GPORT value to SGLP and DGLP value.
   5539  * Parameters:
   5540  *     unit       - (IN) BCM device number
   5541  *     is_tx      - (IN) TX/RX port
   5542  *     endpoint_info  - (IN/OUT) Pointer to endpoint information.
   5543  *     module_id    - (IN/OUT) Pointer to module ID of port.
   5544  *     port_id    - (IN/OUT) Pointer to port number of port.
   5545  *     trunk_id    - (IN/OUT) Pointer to Trunk ID. 
   5546  *     local_id    - (IN/OUT) Pointer to local ID of port. 
   5547  *     is_trunk_bfd    - (IN/OUT) Is BFD over Trunk. 
   5548  *     is_micro_bfd    - (IN/OUT) Is Micro BFD session. 
   5549  * Retruns:
   5550  *     BCM_E_XXX
   5551  */
   5552 STATIC int
   5553 bcmi_xgs5_bfd_endpoint_gport_resolve(int unit,
   5554                                 uint8 is_tx,
   5555                                 bcm_bfd_endpoint_info_t *endpoint_info,
   5556                                 bcm_module_t *module_id,
   5557                                 bcm_port_t   *port_id,
   5558                                 bcm_trunk_t *trunk_id,
   5559                                 int *local_id,
   5560                                 uint8 *is_trunk_bfd,
   5561                                 uint8 *is_micro_bfd)
   5562 
   5563 {
   5564 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   5565     bcm_trunk_member_t *member_array = NULL; /* Trunk member array. */
   5566     int                member_count = 0;     /* Trunk Member count. */
   5567     int                rv = SOC_E_NONE;      /* Return status.      */
   5568     int                idx = 0 , link = 0;
   5569     bcm_l3_egress_t    l3_egress;
   5570     bcm_trunk_member_t   member_array_max[BCM_SWITCH_TRUNK_MAX_PORTCNT];
   5571  
   5572     sal_memset(&l3_egress, 0, sizeof(l3_egress));
   5573 
   5574     if(!is_tx) {
   5575         BCM_IF_ERROR_RETURN
   5576             (_bcm_esw_gport_resolve(unit, endpoint_info->gport, module_id,
   5577                                     port_id, trunk_id, local_id));
   5578     } else {
   5579         BCM_IF_ERROR_RETURN
   5580             (_bcm_esw_gport_resolve(unit, endpoint_info->tx_gport, module_id,
   5581                                     port_id, trunk_id, local_id));
   5582     }
   5583 
   5584 
   5585     if (BCM_GPORT_IS_TRUNK(endpoint_info->gport)) {
   5586         if (BCM_TRUNK_INVALID == *trunk_id)  {
   5587             /* Has to be a valid Trunk. */
   5588             return (BCM_E_PARAM);
   5589         }
   5590 
   5591         /* Get count of ports in this trunk. */
   5592         BCM_IF_ERROR_RETURN
   5593             (bcm_esw_trunk_get(unit, *trunk_id, NULL, BCM_SWITCH_TRUNK_MAX_PORTCNT, 
   5594                                member_array_max, &member_count));
   5595         if (0 == member_count) {
   5596             /* No members have been added to the trunk group yet */
   5597             LOG_ERROR(BSL_LS_BCM_BFD,
   5598                       (BSL_META_U(unit,
   5599                                 "\n No members have been added to trunk yet \n")));
   5600             return (BCM_E_PARAM);
   5601         }
   5602         member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count, "Trunk info");
   5603         if (NULL == member_array) {
   5604             return (BCM_E_MEMORY);
   5605         }
   5606         /* Get Trunk Info for the Trunk ID. */
   5607         rv = _bcm_esw_trunk_active_member_get(unit, *trunk_id, NULL, member_count,
   5608                                 member_array, &member_count);
   5609         if (BCM_FAILURE(rv)) {
   5610             sal_free(member_array);
   5611             return rv;
   5612         }
   5613         for(idx = 0;idx < member_count; idx++) {
   5614             /* Get the Modid and Port value using Trunk Index value. */
   5615             rv = _bcm_esw_gport_resolve
   5616                     (unit, member_array[idx].gport,
   5617                     module_id, port_id, trunk_id, local_id);
   5618             if (BCM_FAILURE(rv)) {
   5619                 sal_free(member_array);
   5620             }
   5621 
   5622             rv = bcm_esw_port_link_status_get(unit, *port_id, &link);
   5623             if (BCM_FAILURE(rv)) {
   5624                 sal_free(member_array);
   5625             }
   5626             if (link == BCM_PORT_LINK_STATUS_UP) {
   5627                 break;
   5628             }
   5629         }
   5630         /*Only when there are active members in trunk then
   5631           below condition should be set */
   5632         if((!is_tx) && member_count) {
   5633             *is_trunk_bfd = 1;
   5634         }
   5635         if(!(*is_trunk_bfd)) {
   5636             LOG_ERROR(BSL_LS_BCM_BFD,
   5637                       (BSL_META_U(unit,
   5638                                   "\n Could not get valid port for tx from trunk \n")));
   5639             sal_free(member_array);
   5640             return (BCM_E_PORT);
   5641         }
   5642         sal_free(member_array);
   5643     } else if (!is_tx) {
   5644         BCM_IF_ERROR_RETURN
   5645             (bcm_esw_l3_egress_get(unit, endpoint_info->egress_if,
   5646                                    &l3_egress));
   5647         /* Use the Modid, Port value and determine if the port
   5648          * belongs to a Trunk. */
   5649         if (BCM_TRUNK_INVALID == *trunk_id) {
   5650             rv = bcm_esw_trunk_find(unit, *module_id, *port_id, trunk_id);
   5651         }
   5652 
   5653         if ((BCM_SUCCESS(rv)) || *trunk_id != BCM_TRUNK_INVALID) {
   5654             /* If Dest MAC is dedicated multicast MAC address 01-00-5E-90-00-01
   5655              * and treat it as micro BFD */
   5656             if ((!is_tx) && MICRO_BFD_DST_MAC(l3_egress.mac_addr)){
   5657                 *is_micro_bfd = 1;
   5658             }
   5659         } else if(MICRO_BFD_DST_MAC(l3_egress.mac_addr)){
   5660                 LOG_ERROR(BSL_LS_BCM_BFD,
   5661                          (BSL_META_U(unit,
   5662                                      "\n Dedicated MAC 01-00-5E-90-00-01 must not be used for regular BFD session\n")));
   5663         }
   5664     }
   5665     return (BCM_E_NONE);
   5666 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   5667     return BCM_E_UNAVAIL;
   5668 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   5669 }
   5670 
   5671 /*
   5672  * Function:
   5673  *      bcmi_xgs5_bfd_endpoint_create
   5674  * Purpose:
   5675  *      Create or update an BFD endpoint object
   5676  * Parameters:
   5677  *      unit          - (IN) Unit number.
   5678  *      endpoint_info - (IN/OUT) Pointer to an BFD endpoint structure.
   5679  * Returns:
   5680  *      BCM_E_NONE      Operation completed successfully
   5681  *      BCM_E_PARAM     Invalid parameter specified
   5682  *      BCM_E_NOT_FOUND Attempt to update an endpoint which does not exist
   5683  *      BCM_E_EXISTS    Attempt to create an endpoint with a specified ID
   5684  *                      which is already in use
   5685  *      BCM_E_FULL      No free endpoints available.
   5686  *
   5687  * Notes:
   5688  */
   5689 int
   5690 bcmi_xgs5_bfd_endpoint_create(int unit,
   5691                               bcm_bfd_endpoint_info_t *endpoint_info)
   5692 {
   5693 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   5694     bfd_info_t *bfd_info = BFD_INFO(unit);
   5695     bfd_endpoint_config_t *endpoint_config;
   5696     int update;
   5697     int endpoint_index;
   5698     bcm_module_t module_id;
   5699     bcm_port_t port_id;
   5700     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
   5701     int local_id;
   5702     bcm_port_t tx_port = 0;
   5703     int is_local;
   5704     bcm_l3_egress_t l3_egress;
   5705     bfd_sdk_msg_ctrl_sess_set_t msg_sess;
   5706     uint8 *buffer, *buffer_ptr;
   5707     uint16 buffer_len, reply_len;
   5708     int encap = 0, rv = BCM_E_NONE, rv_old = BCM_E_NONE;
   5709     uint32 session_flags = 0;
   5710     bfd_mpls_label_t mpls_label;
   5711     uint8 is_micro_bfd = 0;
   5712     uint8 local_echo = 0;
   5713     uint8 l2_update = 0;
   5714     /* To reset it to old values in error cases. */
   5715     bfd_endpoint_config_t old_endpoint_config;
   5716     uint8 is_trunk_bfd = 0;
   5717     uint8 bfd_session_hw_update = 0;
   5718     bcm_cos_queue_t tx_cos =0; 
   5719 
   5720     BFD_FEATURE_INIT_CHECK(unit);
   5721 
   5722     sal_memset(&old_endpoint_config, 0, sizeof(old_endpoint_config));
   5723 
   5724     PARAM_NULL_CHECK(endpoint_info);
   5725 
   5726 #ifdef  BCM_TOMAHAWK3_SUPPORT
   5727     if(SOC_IS_TOMAHAWK3(unit)) {
   5728         if((endpoint_info->type == bcmBFDTunnelTypePweControlWord) ||
   5729             (endpoint_info->type == bcmBFDTunnelTypePweRouterAlert) ||
   5730             (endpoint_info->type ==  bcmBFDTunnelTypePweTtl)) {
   5731             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   5732                 "Encap type not supported on TH3\n")));
   5733             return BCM_E_UNAVAIL;
   5734         }
   5735     }
   5736 #endif
   5737     /* Check Authentication key index */
   5738     if (endpoint_info->auth == bcmBFDAuthTypeNone) {
   5739         /* Nothing to check */
   5740     } else if (endpoint_info->auth == bcmBFDAuthTypeSimplePassword) {
   5741         AUTH_SP_INDEX_CHECK(unit, endpoint_info->auth_index);
   5742     } else if ((endpoint_info->auth == bcmBFDAuthTypeKeyedSHA1) ||
   5743                (endpoint_info->auth == bcmBFDAuthTypeMeticulousKeyedSHA1)) {
   5744         AUTH_SHA1_INDEX_CHECK(unit, endpoint_info->auth_index);
   5745     } else {
   5746         /*
   5747          * Not supported:
   5748          * bcmBFDAuthTypeKeyedMD5 and bcmBFDAuthTypeMeticulousKeyedMD5
   5749          */
   5750         return BCM_E_PARAM;
   5751     }
   5752 
   5753     if (endpoint_info->flags & BCM_BFD_ENDPOINT_USE_PKT_VLAN_ID) {
   5754         /* Validate the packet vlan id */
   5755         if (endpoint_info->pkt_vlan_id == 0) {
   5756             LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit,
   5757                       "BFD: vlan id zero is invalid config\n")));
   5758             return BCM_E_PARAM;
   5759         }
   5760         VLAN_CHK_ID(unit, endpoint_info->pkt_vlan_id);
   5761     }
   5762 
   5763     /* A unique local discriminator should be nonzero */
   5764     if (!endpoint_info->local_discr) {
   5765         LOG_ERROR(BSL_LS_BCM_BFD,
   5766                   (BSL_META_U(unit,
   5767                               "BFD local discriminator cannot be zero\n")));
   5768         return BCM_E_PARAM;
   5769     }
   5770 
   5771     /*
   5772      * If user configured static remote discr,
   5773      * remote discriminator should be nonzero
   5774      */
   5775     if (bfd_info->static_remote_discr &&
   5776         !endpoint_info->remote_discr) {
   5777         LOG_ERROR(BSL_LS_BCM_BFD,
   5778                   (BSL_META_U(unit,
   5779                               "BFD static remote discriminator cannot be zero\n")));
   5780         return BCM_E_PARAM;
   5781     }
   5782 
   5783     /* Local detection multiplier should be set to Default value, if configured value is 0 */
   5784     if (!endpoint_info->local_detect_mult) {
   5785         endpoint_info->local_detect_mult = BFD_DEFAULT_DETECT_MULTIPLIER;
   5786         LOG_VERBOSE(BSL_LS_BCM_BFD,
   5787                     (BSL_META_U(unit,
   5788                                 "\n BFD Detect Multiplier Set to Default Value %d\n"), 
   5789                                 endpoint_info->local_detect_mult));
   5790     }
   5791 
   5792     /* Resolve RX module and port */
   5793     sal_memset(&l3_egress, 0, sizeof(l3_egress));
   5794     if (BCM_GPORT_INVALID != endpoint_info->gport) {
   5795         BCM_IF_ERROR_RETURN
   5796         (bcmi_xgs5_bfd_endpoint_gport_resolve(unit, 0, endpoint_info, &module_id,
   5797             &port_id, &trunk_id, &local_id, &is_trunk_bfd, &is_micro_bfd));
   5798     } else if (BCM_SUCCESS
   5799               (bcm_esw_l3_egress_get(unit, endpoint_info->egress_if,
   5800                                      &l3_egress))) {
   5801         module_id = l3_egress.module;
   5802         port_id = l3_egress.port;
   5803     } else {
   5804         return BCM_E_PARAM;
   5805     }
   5806 
   5807     if (is_trunk_bfd){
   5808         session_flags |= SHR_BFD_SESS_SET_F_TRUNK;
   5809     }
   5810 
   5811     if (is_micro_bfd){
   5812         session_flags |= SHR_BFD_SESS_SET_F_MICRO_BFD;
   5813     }
   5814 
   5815     if(endpoint_info->type == bcmBFDTunnelTypeMplsPhp) {
   5816         session_flags |= SHR_BFD_SESS_SET_F_MPLS_PHP;
   5817     }
   5818 
   5819     if (BCM_GPORT_INVALID == endpoint_info->tx_gport) {
   5820         /* Get local port used for TX BFD packet */
   5821         BCM_IF_ERROR_RETURN
   5822             (_bcm_esw_modid_is_local(unit, module_id, &is_local));
   5823         if (is_local) {    /* Ethernet port */
   5824             tx_port = port_id;
   5825         } else {           /* HG port */
   5826             BCM_IF_ERROR_RETURN
   5827                 (bcm_esw_stk_modport_get(unit, module_id, &tx_port));
   5828         }
   5829     }
   5830     
   5831     /*
   5832      * Check that configuration contains valid cos queue for the tx port
   5833      */
   5834     if (!BCM_COSQ_QUEUE_VALID(unit, endpoint_info->int_pri)) {
   5835         LOG_ERROR(BSL_LS_BCM_BFD,
   5836                   (BSL_META_U(unit,
   5837                               "Invalid int_pri value (%d) for tx_port %d\n"),
   5838                               endpoint_info->int_pri, tx_port));
   5839         return BCM_E_PARAM;
   5840     }
   5841 
   5842     /* Enable the BFD echo mode */
   5843     local_echo = (endpoint_info->flags & BCM_BFD_ECHO) ? 1 : 0;
   5844 
   5845     /* BFD Echo mode should be enabled with IPv4/IPv6 Enacap only*/
   5846     if (local_echo && (endpoint_info->type != bcmBFDTunnelTypeUdp)) {
   5847         LOG_ERROR(BSL_LS_BCM_BFD, (BSL_META_U(unit,
   5848                         "ECHO mode is supported on BFD over IPV4 and IPV6 tunnel only\n")));
   5849         return BCM_E_UNAVAIL;
   5850     }
   5851 
   5852     if (local_echo && !BFD_UC_FEATURE_CHECK(BFD_FEATURE_ECHO_MODE)) {
   5853         LOG_ERROR(BSL_LS_BCM_BFD, (BSL_META_U(unit,
   5854                         "BFD Echo Mode is not supported in uKernel\n")));
   5855         return BCM_E_UNAVAIL;
   5856     }
   5857 
   5858     /*
   5859      * User should Configure the BFD echo feature
   5860      * in Soc Properties as well
   5861      */
   5862     if (local_echo && !(bfd_info->bfd_feature_enable & BFD_ECHO_FEATURE_ENABLE)) {
   5863         LOG_ERROR(BSL_LS_BCM_BFD,
   5864                 (BSL_META_U(unit,
   5865                             "BFD Echo is not Configured in Soc Properties\n")));
   5866         return BCM_E_UNAVAIL;
   5867     }
   5868 
   5869 
   5870     /* Create or Update */
   5871     update = (endpoint_info->flags & BCM_BFD_ENDPOINT_UPDATE) ? 1 : 0;
   5872     session_flags |= ((update) ? 0 : SHR_BFD_SESS_SET_F_CREATE);
   5873 
   5874     if (endpoint_info->flags & BCM_BFD_ENDPOINT_WITH_ID) {
   5875         if ((SOC_IS_TRIDENT3X(unit)) && (endpoint_info->id == 0)) {
   5876             LOG_ERROR(BSL_LS_BCM_BFD,
   5877                       (BSL_META_U(unit,
   5878                                  "BFD Endpoint with ID 0 is not supported\n")));
   5879             return BCM_E_PARAM;
   5880         }
   5881         endpoint_index = endpoint_info->id;
   5882 
   5883         ENDPOINT_INDEX_CHECK(unit, endpoint_index);
   5884 
   5885         /*
   5886          * Update requires endpoint ID to exist
   5887          * Create requires endpoint ID not to exist
   5888          */
   5889         if (update &&
   5890             (!SHR_BITGET(bfd_info->endpoints_in_use, endpoint_index))) {
   5891             return BCM_E_NOT_FOUND;
   5892         } else if (!update &&
   5893                    (SHR_BITGET(bfd_info->endpoints_in_use, endpoint_index))) {
   5894             return BCM_E_EXISTS;
   5895         }
   5896 
   5897     } else {    /* No ID */
   5898 
   5899         if (update) {    /* Update specified with no ID */
   5900             return BCM_E_PARAM;
   5901         }
   5902 
   5903         /* Allocate endpoint */
   5904         endpoint_index =
   5905             bcmi_xgs5_bfd_find_free_endpoint(unit, bfd_info->endpoints_in_use,
   5906                                              bfd_info->endpoint_count);
   5907         if (endpoint_index < 0) {
   5908             return BCM_E_FULL;
   5909         }
   5910 
   5911         endpoint_info->id = endpoint_index;
   5912     }
   5913 
   5914     /* Get Endpoint config entry */
   5915     endpoint_config = BFD_ENDPOINT_CONFIG(unit, endpoint_index);
   5916 
   5917     /* Endpoint tunnel type cannot change */
   5918     if (update && (endpoint_config->info.type != endpoint_info->type)) {
   5919         return BCM_E_PARAM;
   5920     }
   5921 
   5922     /* Update the encap data */
   5923     if (endpoint_info->flags & BCM_BFD_ENDPOINT_ENCAP_SET) {
   5924         encap = 1;
   5925     }
   5926 
   5927     /* IP/MPLS values can't change without encap flag */
   5928     if (update && !encap) {
   5929         if (endpoint_config->info.dst_ip_addr != endpoint_info->dst_ip_addr) {
   5930             return BCM_E_PARAM;
   5931         }
   5932         if (sal_memcmp(endpoint_config->info.dst_ip6_addr, endpoint_info->dst_ip6_addr,
   5933                       BCM_IP6_ADDRLEN) != 0) {
   5934             return BCM_E_PARAM;
   5935         }
   5936         if (endpoint_config->info.src_ip_addr != endpoint_info->src_ip_addr) {
   5937             return BCM_E_PARAM;
   5938         }
   5939         if (sal_memcmp(endpoint_config->info.src_ip6_addr, endpoint_info->src_ip6_addr,
   5940                       BCM_IP6_ADDRLEN) != 0) {
   5941             return BCM_E_PARAM;
   5942         }
   5943         if (endpoint_config->info.ip_tos != endpoint_info->ip_tos) {
   5944             return BCM_E_PARAM;
   5945         }
   5946         if (endpoint_config->info.ip_ttl != endpoint_info->ip_ttl) {
   5947             return BCM_E_PARAM;
   5948         }
   5949         if (endpoint_config->info.inner_dst_ip_addr != endpoint_info->inner_dst_ip_addr) {
   5950             return BCM_E_PARAM;
   5951         }
   5952         if (sal_memcmp(endpoint_config->info.inner_dst_ip6_addr, endpoint_info->inner_dst_ip6_addr,
   5953                       BCM_IP6_ADDRLEN) != 0) {
   5954             return BCM_E_PARAM;
   5955         }
   5956         if (endpoint_config->info.inner_src_ip_addr != endpoint_info->inner_src_ip_addr) {
   5957             return BCM_E_PARAM;
   5958         }
   5959         if (sal_memcmp(endpoint_config->info.inner_src_ip6_addr, endpoint_info->inner_src_ip6_addr,
   5960                       BCM_IP6_ADDRLEN) != 0) {
   5961             return BCM_E_PARAM;
   5962         }
   5963         if (endpoint_config->info.inner_ip_tos != endpoint_info->inner_ip_tos) {
   5964             return BCM_E_PARAM;
   5965         }
   5966         if (endpoint_config->info.inner_ip_ttl != endpoint_info->inner_ip_ttl) {
   5967             return BCM_E_PARAM;
   5968         }
   5969         if (endpoint_config->info.udp_src_port != endpoint_info->udp_src_port) {
   5970             return BCM_E_PARAM;
   5971         }
   5972         if (endpoint_config->info.label != endpoint_info->label) {
   5973             return BCM_E_PARAM;
   5974         }
   5975     }
   5976 
   5977     /*
   5978      * Compare new and old BFD parameters for Update
   5979      */
   5980     if (update) {
   5981         if (endpoint_config->info.local_discr !=
   5982             endpoint_info->local_discr) {
   5983             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_DISC;
   5984         }
   5985         if (endpoint_config->info.remote_discr !=
   5986             endpoint_info->remote_discr) {
   5987             session_flags |= SHR_BFD_SESS_SET_F_REMOTE_DISC;
   5988         }
   5989         if (endpoint_config->info.local_min_tx !=
   5990             endpoint_info->local_min_tx) {
   5991             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_MIN_TX;
   5992         }
   5993         if (endpoint_config->info.local_min_rx !=
   5994             endpoint_info->local_min_rx) {
   5995             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_MIN_RX;
   5996         }
   5997         if (endpoint_config->info.local_min_echo !=
   5998             endpoint_info->local_min_echo) {
   5999             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_MIN_ECHO_RX;
   6000         }
   6001         if (endpoint_config->info.local_diag !=
   6002             endpoint_info->local_diag) {
   6003             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_DIAG;
   6004         }
   6005         if ((endpoint_config->info.flags & BCM_BFD_ENDPOINT_DEMAND)
   6006             != (endpoint_info->flags & BCM_BFD_ENDPOINT_DEMAND)) {
   6007             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_DEMAND;
   6008         }
   6009         if (endpoint_config->info.local_detect_mult !=
   6010             endpoint_info->local_detect_mult) {
   6011             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_DETECT_MULT;
   6012         }
   6013         if (endpoint_info->flags & BCM_BFD_ENDPOINT_ENCAP_SET) {
   6014             session_flags |= SHR_BFD_SESS_SET_F_ENCAP;
   6015         }
   6016         if (endpoint_info->flags & BCM_BFD_ENDPOINT_SHA1_SEQUENCE_INCR) {
   6017             session_flags |= SHR_BFD_SESS_SET_F_SHA1_XMT_SEQ_INCR;
   6018         }
   6019         if (endpoint_config->info.auth !=
   6020             endpoint_info->auth) {
   6021             session_flags |= SHR_BFD_SESS_SET_F_AUTH_TYPE;
   6022         }
   6023         if (endpoint_config->local_echo != local_echo) {
   6024             session_flags |= SHR_BFD_SESS_SET_F_LOCAL_ECHO;
   6025         }
   6026          if (endpoint_config->info.mep_id_length !=
   6027             endpoint_info->mep_id_length) {
   6028             session_flags |= SHR_BFD_SESS_SET_F_MEP_ID_LENGTH;
   6029             session_flags |= SHR_BFD_SESS_SET_F_MEP_ID;
   6030         }
   6031         if (sal_memcmp(endpoint_config->info.mep_id, endpoint_info->mep_id,
   6032                       endpoint_config->info.mep_id_length) != 0) {
   6033             session_flags |= SHR_BFD_SESS_SET_F_MEP_ID;
   6034         }
   6035         if (endpoint_config->info.remote_mep_id_length !=
   6036             endpoint_info->remote_mep_id_length) {
   6037             session_flags |= SHR_BFD_SESS_SET_F_REMOTE_MEP_ID_LENGTH;
   6038             session_flags |= SHR_BFD_SESS_SET_F_REMOTE_MEP_ID;
   6039         }
   6040         if (sal_memcmp(endpoint_config->info.remote_mep_id, endpoint_info->remote_mep_id,
   6041                        endpoint_config->info.remote_mep_id_length) != 0) {
   6042             session_flags |= SHR_BFD_SESS_SET_F_REMOTE_MEP_ID;
   6043         }
   6044 
   6045         /* Update require l2 params */
   6046         if ((endpoint_config->info.gport != endpoint_info->gport) ||
   6047             (endpoint_config->info.tx_gport != endpoint_info->tx_gport) ||
   6048             (endpoint_config->info.int_pri != endpoint_info->int_pri) ||
   6049             (endpoint_config->info.cpu_qid != endpoint_info->cpu_qid )) {
   6050              l2_update = 1;
   6051         }
   6052     }
   6053 
   6054     /* Make a copy of the endpoint config so that it can be reverted to old one
   6055      * in error scenarios.
   6056      */
   6057     sal_memcpy(&old_endpoint_config, endpoint_config, sizeof(bfd_endpoint_config_t));
   6058     /* Set Endpoint config entry */
   6059     endpoint_config->endpoint_index = endpoint_index;
   6060     endpoint_config->modid          = module_id;
   6061     endpoint_config->port           = port_id;
   6062     endpoint_config->tx_port        = tx_port;
   6063     endpoint_config->info           = *endpoint_info;
   6064     endpoint_config->local_echo     = local_echo;
   6065     endpoint_config->is_micro_bfd = is_micro_bfd;
   6066 
   6067     /* Set BFD Session in HW */
   6068     if (!update) {
   6069         rv = bcmi_xgs5_bfd_session_hw_set(unit, endpoint_config);
   6070         if (BCM_FAILURE(rv)) {
   6071             /* Copy the old config back to endpoint config. */
   6072             sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6073             return rv;
   6074         }
   6075         encap = 1;
   6076     } else {
   6077         /* Re-program the Hardware with local discr during update */
   6078         if ((session_flags & SHR_BFD_SESS_SET_F_LOCAL_DISC) || l2_update || encap) {
   6079 
   6080             bfd_session_hw_update = 1;
   6081              /* Check the mpls/ipv4/ipv6 status in l3 table, if encap flag set */
   6082             if (encap) {
   6083                 rv = bcmi_xgs5_bfd_mpls_l3_table_status(unit, endpoint_config);
   6084                 if (BCM_FAILURE(rv)) {
   6085                     /* Copy the old config back to endpoint config. */
   6086                     sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6087                     return BCM_E_PARAM;
   6088                 }
   6089             }
   6090 
   6091             /* Clear the previous hardware entry, before updating local discr */
   6092             BCM_IF_ERROR_RETURN
   6093             (bcmi_xgs5_bfd_session_hw_delete(unit, &old_endpoint_config));
   6094 
   6095             rv = bcmi_xgs5_bfd_session_hw_set(unit, endpoint_config);
   6096             if (BCM_FAILURE(rv)) {
   6097                 /* Copy the old config back to endpoint config. */
   6098                 sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6099 
   6100                 /* hw_set with old config, if hw_set with new config fails */
   6101                 rv_old = bcmi_xgs5_bfd_session_hw_set(unit, endpoint_config);
   6102                 if (BCM_FAILURE(rv_old)) {
   6103                     return rv_old;
   6104                 }
   6105                 return rv;
   6106             }
   6107         }
   6108     }
   6109 
   6110     /* Resolve TX module and port */
   6111     if (BCM_GPORT_INVALID != endpoint_info->tx_gport) {
   6112         rv = bcmi_xgs5_bfd_endpoint_gport_resolve(unit, 1, endpoint_info, &module_id,
   6113                  &port_id, &trunk_id, &local_id, &is_trunk_bfd, &is_micro_bfd);
   6114         if (BCM_FAILURE(rv)) {
   6115             BCM_IF_ERROR_RETURN
   6116             (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6117 
   6118             if (bfd_session_hw_update) {
   6119                 /* Copy the old config back to endpoint config. */
   6120                 sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6121                 rv_old = bcmi_xgs5_bfd_session_hw_set(unit, endpoint_config);
   6122                 if (BCM_FAILURE(rv_old)) {
   6123                     return rv_old;
   6124                 }
   6125             }
   6126             return rv;
   6127         }
   6128             
   6129         /* Get local port used for TX BFD packet */
   6130         rv = _bcm_esw_modid_is_local(unit, module_id, &is_local);
   6131         if (BCM_FAILURE(rv)) {
   6132             BCM_IF_ERROR_RETURN
   6133             (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6134 
   6135             if (bfd_session_hw_update) {
   6136                 /* Copy the old config back to endpoint config. */
   6137                 sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6138                 rv_old = bcmi_xgs5_bfd_session_hw_set(unit, endpoint_config);
   6139                 if (BCM_FAILURE(rv_old)) {
   6140                     return rv_old;
   6141                 }
   6142             }
   6143             return rv;
   6144         }
   6145         if (is_local) {    /* Ethernet port */
   6146             tx_port = port_id;
   6147         } else {           /* HG port */
   6148             rv = bcm_esw_stk_modport_get(unit, module_id, &tx_port);
   6149             if (BCM_FAILURE(rv)) {
   6150                 BCM_IF_ERROR_RETURN
   6151                 (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6152 
   6153                 if (bfd_session_hw_update) {
   6154                     /* Copy the old config back to endpoint config. */
   6155                     sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6156                     rv_old = bcmi_xgs5_bfd_session_hw_set(unit, endpoint_config);
   6157                     if (BCM_FAILURE(rv_old)) {
   6158                         return rv_old;
   6159                     }
   6160                 }
   6161                 return rv;
   6162             }
   6163         }
   6164     }
   6165 
   6166     /* Set Endpoint config entry */
   6167     endpoint_config->endpoint_index = endpoint_index;
   6168     endpoint_config->modid          = module_id;
   6169     endpoint_config->port           = port_id;
   6170     endpoint_config->tx_port        = tx_port;
   6171     endpoint_config->info           = *endpoint_info;
   6172     endpoint_config->local_echo     = local_echo;
   6173 
   6174     /* Set control message data */
   6175     sal_memset(&msg_sess, 0, sizeof(msg_sess));
   6176 
   6177     /*
   6178      * Set the BFD encapsulation data
   6179      *
   6180      * The function bcmi_xgs5_bfd_encap_create() is called first
   6181      * since this sets some fields in 'endpoint_config' which are
   6182      * used in the message.
   6183      */
   6184     if (encap) {
   6185         rv = bcmi_xgs5_bfd_encap_create(unit, endpoint_config,
   6186                                         msg_sess.encap_data);
   6187         if (BCM_FAILURE(rv)) {
   6188             /* Clear the hardware entry, if encap fails */
   6189             BCM_IF_ERROR_RETURN
   6190                 (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6191 
   6192             endpoint_config->endpoint_index = -1;
   6193 
   6194             /* Copy the old config back to endpoint config. */
   6195             sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6196             
   6197             if (bfd_session_hw_update) {
   6198                 rv_old = bcmi_xgs5_bfd_session_hw_set(unit, endpoint_config);
   6199                 if (BCM_FAILURE(rv_old)) {
   6200                     return rv_old;
   6201                 }
   6202             }
   6203             return rv;
   6204         }
   6205     }
   6206     msg_sess.sess_id = endpoint_config->endpoint_index;
   6207     msg_sess.flags   = session_flags;
   6208     msg_sess.passive =
   6209         (endpoint_info->flags & BCM_BFD_ENDPOINT_PASSIVE) ? 1 : 0;
   6210     msg_sess.local_demand =
   6211         (endpoint_info->flags & BCM_BFD_ENDPOINT_DEMAND) ? 1 : 0;
   6212     msg_sess.local_echo           = local_echo;
   6213     msg_sess.local_diag           = endpoint_info->local_diag;
   6214     msg_sess.local_detect_mult    = endpoint_info->local_detect_mult;
   6215     msg_sess.local_discriminator  = endpoint_info->local_discr;
   6216     msg_sess.remote_discriminator = endpoint_info->remote_discr;
   6217     msg_sess.local_min_tx         = endpoint_info->local_min_tx;
   6218     msg_sess.local_min_rx         = endpoint_info->local_min_rx;
   6219     msg_sess.local_min_echo_rx    = endpoint_info->local_min_echo;
   6220     msg_sess.auth_type            = endpoint_info->auth;
   6221     msg_sess.auth_key             = endpoint_info->auth_index;
   6222     msg_sess.xmt_auth_seq         = endpoint_info->tx_auth_seq;
   6223 
   6224     if (BFD_UC_FEATURE_CHECK(BFD_FEATURE_RX_PKT_VLAN_ID)) {
   6225         msg_sess.rx_pkt_vlan_id = endpoint_info->rx_pkt_vlan_id;
   6226     }
   6227 
   6228     if (endpoint_info->mep_id_length >
   6229             BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH) {
   6230         if (bfd_session_hw_update) {
   6231             BCM_IF_ERROR_RETURN
   6232             (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6233 
   6234             rv_old = bcmi_xgs5_bfd_session_hw_set(unit, &old_endpoint_config);
   6235             if (BCM_FAILURE(rv_old)) {
   6236                 return rv_old;
   6237             }
   6238         }
   6239         /* Copy the old config back to endpoint config. */
   6240         sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6241         return BCM_E_PARAM;
   6242     }
   6243 
   6244     if (endpoint_info->mep_id_length) {
   6245         msg_sess.mep_id_length = endpoint_info->mep_id_length;
   6246         sal_memcpy(msg_sess.mep_id, endpoint_info->mep_id,
   6247                    endpoint_info->mep_id_length);
   6248     }
   6249 
   6250     if (BFD_UC_FEATURE_CHECK(BFD_FEATURE_REMOTE_MEP_ID)) {
   6251         if (endpoint_info->remote_mep_id_length >
   6252             BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH) {
   6253             if (bfd_session_hw_update) {
   6254                 BCM_IF_ERROR_RETURN
   6255                 (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6256 
   6257                 rv_old = bcmi_xgs5_bfd_session_hw_set(unit, &old_endpoint_config);
   6258                 if (BCM_FAILURE(rv_old)) {
   6259                   return rv_old;
   6260                 }
   6261             }
   6262 
   6263             /* Copy the old config back to endpoint config. */
   6264             sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6265             return BCM_E_PARAM;
   6266         }
   6267 
   6268         if (endpoint_info->remote_mep_id_length) {
   6269             msg_sess.remote_mep_id_length = endpoint_info->remote_mep_id_length;
   6270             sal_memcpy(msg_sess.remote_mep_id, endpoint_info->remote_mep_id,
   6271                        endpoint_info->remote_mep_id_length);
   6272         }
   6273     }
   6274 
   6275     if (encap) {
   6276         msg_sess.encap_type   = endpoint_config->encap_type;
   6277         msg_sess.encap_length = endpoint_config->encap_length;
   6278         msg_sess.lkey_etype   = endpoint_config->lkey_etype;
   6279         msg_sess.lkey_offset  = endpoint_config->lkey_offset;
   6280         msg_sess.lkey_length  = endpoint_config->lkey_length;
   6281     }
   6282     /* MPLS label needs to be in packet frame format (label field only) */
   6283     bcmi_xgs5_bfd_mpls_label_get(endpoint_info->label, 0, 0, 0,
   6284                                  &mpls_label);
   6285     bcmi_xgs5_bfd_mpls_label_pack(msg_sess.mpls_label, &mpls_label);
   6286 
   6287     msg_sess.tx_port = endpoint_config->tx_port;
   6288     msg_sess.tx_pri  = 0;
   6289     msg_sess.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[msg_sess.tx_port] +
   6290         endpoint_info->int_pri;
   6291 
   6292     BCM_IF_ERROR_RETURN
   6293     (bcm_esw_cosq_port_mapping_get(unit, msg_sess.tx_port,
   6294                                    endpoint_info->int_pri, &tx_cos));
   6295     msg_sess.tx_cos = tx_cos;
   6296 
   6297 #ifdef BCM_TRIDENT2_SUPPORT
   6298     if (SOC_IS_TD2_TT2(unit)) {
   6299         msg_sess.tx_qnum = soc_td2_logical_qnum_hw_qnum(unit, msg_sess.tx_port,
   6300                                                         msg_sess.tx_qnum, 1);
   6301     }
   6302 #endif
   6303 
   6304     /* Pack control message data into DMA buffer */
   6305     buffer     = bfd_info->dma_buffer;
   6306     buffer_ptr = bfd_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess);
   6307     buffer_len = buffer_ptr - buffer;
   6308 
   6309     /* Send BFD Session Set message to uC */
   6310     rv = bcmi_xgs5_bfd_msg_send_receive(unit,
   6311             MOS_MSG_SUBCLASS_BFD_SESS_SET,
   6312             buffer_len, 0,
   6313             MOS_MSG_SUBCLASS_BFD_SESS_SET_REPLY,
   6314             &reply_len, bfd_uc_msg_timeout_usecs);
   6315     if (BCM_FAILURE(rv)) {
   6316         if (bfd_session_hw_update) {
   6317             BCM_IF_ERROR_RETURN
   6318             (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6319 
   6320             rv_old = bcmi_xgs5_bfd_session_hw_set(unit, &old_endpoint_config);
   6321             if (BCM_FAILURE(rv_old)) {
   6322                 return rv_old;
   6323             }
   6324         }
   6325 
   6326         /* Copy the old config back to endpoint config. */
   6327         sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6328         return rv;
   6329     }
   6330     if (reply_len != 0) {
   6331         if (bfd_session_hw_update) {
   6332             BCM_IF_ERROR_RETURN
   6333             (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6334 
   6335             rv_old = bcmi_xgs5_bfd_session_hw_set(unit, &old_endpoint_config);
   6336             if (BCM_FAILURE(rv_old)) {
   6337                 return rv_old;
   6338             }
   6339         }
   6340         /* Copy the old config back to endpoint config. */
   6341         sal_memcpy(endpoint_config, &old_endpoint_config, sizeof(bfd_endpoint_config_t));
   6342         return BCM_E_INTERNAL;
   6343     }
   6344 
   6345 
   6346     /* Mark endpoint in use */
   6347     SHR_BITSET(bfd_info->endpoints_in_use, endpoint_config->endpoint_index);
   6348 
   6349     return BCM_E_NONE;
   6350 
   6351 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6352     return BCM_E_UNAVAIL;
   6353 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6354 }
   6355 
   6356 /*
   6357  * Function:
   6358  *      bcmi_xgs5_bfd_endpoint_get
   6359  * Purpose:
   6360  *      Get an BFD endpoint object
   6361  * Parameters:
   6362  *      unit          - (IN) Unit number.
   6363  *      endpoint      - (IN) The ID of the endpoint object to get.
   6364  *      endpoint_info - (OUT) Pointer to an BFD endpoint structure
   6365  *                            to receive the data.
   6366  * Returns:
   6367  *      BCM_E_NONE      Operation completed successfully
   6368  *      BCM_E_NOT_FOUND Endpoint does not exist
   6369  *      BCM_E_PARAM     Invalid parameter specified
   6370  *      BCM_E_INTERNAL  Failed to read endpoint information
   6371  * Notes:
   6372  */
   6373 int
   6374 bcmi_xgs5_bfd_endpoint_get(int unit,
   6375                            bcm_bfd_endpoint_t endpoint,
   6376                            bcm_bfd_endpoint_info_t *endpoint_info)
   6377 {
   6378 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6379     bfd_info_t *bfd_info = BFD_INFO(unit);
   6380     bfd_endpoint_config_t *endpoint_config;
   6381     bfd_sdk_msg_ctrl_sess_get_t msg_sess;
   6382     uint8 *buffer, *buffer_ptr;
   6383     uint16 buffer_len, reply_len;
   6384 
   6385     BFD_FEATURE_INIT_CHECK(unit);
   6386 
   6387     PARAM_NULL_CHECK(endpoint_info);
   6388 
   6389     ENDPOINT_INDEX_CHECK(unit, endpoint);
   6390 
   6391     if (!SHR_BITGET(bfd_info->endpoints_in_use, endpoint)) {
   6392         return BCM_E_NOT_FOUND;
   6393     }
   6394 
   6395     endpoint_config = BFD_ENDPOINT_CONFIG(unit, endpoint);
   6396     sal_memcpy(endpoint_info, &endpoint_config->info,
   6397                sizeof(*endpoint_info));
   6398 
   6399     /* Send BFD Session Get message to uC */
   6400     BCM_IF_ERROR_RETURN
   6401         (bcmi_xgs5_bfd_msg_send_receive(unit,
   6402                                         MOS_MSG_SUBCLASS_BFD_SESS_GET,
   6403                                         endpoint, 0,
   6404                                         MOS_MSG_SUBCLASS_BFD_SESS_GET_REPLY,
   6405                                         &reply_len, bfd_uc_msg_timeout_usecs));
   6406 
   6407     /* Unpack control message data from DMA buffer */
   6408     sal_memset(&msg_sess, 0, sizeof(msg_sess));
   6409     buffer     = bfd_info->dma_buffer;
   6410     buffer_ptr = bfd_sdk_msg_ctrl_sess_get_unpack(buffer, &msg_sess);
   6411     buffer_len = buffer_ptr - buffer;
   6412 
   6413     if (reply_len != buffer_len) {
   6414         return BCM_E_INTERNAL;
   6415     }
   6416     
   6417     endpoint_info->local_state        = msg_sess.local_sess_state;
   6418     endpoint_info->local_discr        = msg_sess.local_discriminator;
   6419     endpoint_info->local_diag         = msg_sess.local_diag;
   6420     endpoint_info->local_min_tx       = msg_sess.local_min_tx;
   6421     endpoint_info->local_min_rx       = msg_sess.local_min_rx;
   6422     endpoint_info->local_min_echo     = msg_sess.local_min_echo_rx;
   6423     endpoint_info->local_detect_mult  = msg_sess.local_detect_mult;
   6424     endpoint_info->tx_auth_seq        = msg_sess.xmt_auth_seq;
   6425     endpoint_info->rx_auth_seq        = msg_sess.rcv_auth_seq;
   6426     endpoint_info->remote_state       = msg_sess.remote_sess_state;
   6427     endpoint_info->remote_discr       = msg_sess.remote_discriminator;
   6428     endpoint_info->remote_diag        = msg_sess.remote_diag;
   6429     endpoint_info->remote_min_tx      = msg_sess.remote_min_tx;
   6430     endpoint_info->remote_min_rx      = msg_sess.remote_min_rx;
   6431     endpoint_info->remote_min_echo    = msg_sess.remote_min_echo_rx;
   6432     endpoint_info->remote_detect_mult = msg_sess.remote_detect_mult;
   6433 
   6434     endpoint_info->remote_flags = 0;
   6435     if (msg_sess.local_demand) {
   6436         endpoint_info->flags |= BCM_BFD_ENDPOINT_DEMAND;
   6437     }
   6438     if (msg_sess.passive) {
   6439         endpoint_info->flags |= BCM_BFD_ENDPOINT_PASSIVE;
   6440     }
   6441     if (msg_sess.remote_demand) {
   6442         endpoint_info->remote_flags |= BCM_BFD_ENDPOINT_REMOTE_DEMAND;
   6443     }
   6444 
   6445    /* Get echo mode status from ukernel */
   6446    if (msg_sess.local_echo) {
   6447        endpoint_info->flags |= BCM_BFD_ECHO;
   6448    }
   6449 
   6450    if (BFD_UC_FEATURE_CHECK(BFD_FEATURE_POLL_BIT)) {
   6451        endpoint_info->local_flags = 0;
   6452        if (msg_sess.poll) {
   6453            endpoint_info->local_flags |= BCM_BFD_ENDPOINT_LOCAL_FLAGS_P;
   6454        }
   6455    }
   6456 
   6457    if (BFD_UC_FEATURE_CHECK(BFD_FEATURE_REMOTE_MEP_ID)) {
   6458        endpoint_info->mis_conn_mep_id_length = msg_sess.mis_conn_mep_id_length;
   6459        if ((msg_sess.mis_conn_mep_id_length > 0) &&
   6460            (msg_sess.mis_conn_mep_id_length < sizeof(endpoint_info->mis_conn_mep_id))) {
   6461             sal_memcpy(endpoint_info->mis_conn_mep_id, msg_sess.mis_conn_mep_id,
   6462                        msg_sess.mis_conn_mep_id_length);
   6463        }
   6464     }
   6465 
   6466     if(BFD_UC_FEATURE_CHECK(BFD_FEATURE_RX_PKT_VLAN_ID)) {
   6467         endpoint_info->rx_pkt_vlan_id = msg_sess.rx_pkt_vlan_id;
   6468     }
   6469 
   6470     return BCM_E_NONE;
   6471 
   6472 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6473     return BCM_E_UNAVAIL;
   6474 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6475 }
   6476 
   6477 /*
   6478  * Function:
   6479  *      bcmi_xgs5_bfd_tx_start
   6480  * Purpose:
   6481  *      Start all BFD endpoint TX BFD PDUs.
   6482  * Parameters:
   6483  *      unit - (IN) Unit number.
   6484  * Returns:
   6485  *      BCM_E_NONE     Operation completed successfully
   6486  *      BCM_E_NOT_FOUND Attempt to start TX which does not exist
   6487  *      BCM_E_INTERNAL Unable to release resource /
   6488  *                     Failed to read memory or read or write register
   6489  * Notes:
   6490  */
   6491 int
   6492 bcmi_xgs5_bfd_tx_start(int unit)
   6493 {
   6494 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6495     bfd_info_t *bfd_info = BFD_INFO(unit);
   6496     uint16 reply_len;
   6497     int index;
   6498     int ep_found = 0;
   6499 
   6500     BFD_FEATURE_INIT_CHECK(unit);
   6501 
   6502     for (index = 0; index < bfd_info->endpoint_count; index++) {
   6503         if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   6504            ep_found = 1;
   6505            break;
   6506         }
   6507     }
   6508 
   6509     if (!ep_found) {
   6510         return BCM_E_NOT_FOUND;
   6511     }
   6512 
   6513     /* Send BFD Session Delete All message to uC */
   6514     BCM_IF_ERROR_RETURN
   6515         (bcmi_xgs5_bfd_msg_send_receive
   6516          (unit,
   6517           MOS_MSG_SUBCLASS_BFD_TX_START,
   6518           0, 0,
   6519           MOS_MSG_SUBCLASS_BFD_TX_START_REPLY,
   6520           &reply_len, bfd_uc_msg_timeout_usecs));
   6521 
   6522     if (reply_len != 0) {
   6523         return BCM_E_INTERNAL;
   6524     }
   6525 
   6526     return BCM_E_NONE;
   6527 
   6528 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6529     return BCM_E_UNAVAIL;
   6530 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6531 }
   6532 
   6533 /*
   6534  * Function:
   6535  *      bcmi_xgs5_bfd_tx_stop
   6536  * Purpose:
   6537  *      Stop all BFD endpoint TX BFD PDUs.
   6538  * Parameters:
   6539  *      unit - (IN) Unit number.
   6540  * Returns:
   6541  *      BCM_E_NONE     Operation completed successfully
   6542  *      BCM_E_NOT_FOUND Attempt to stop TX which does not exist
   6543  *      BCM_E_INTERNAL Unable to release resource /
   6544  *                     Failed to read memory or read or write register
   6545  * Notes:
   6546  */
   6547 int
   6548 bcmi_xgs5_bfd_tx_stop(int unit)
   6549 {
   6550 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6551     bfd_info_t *bfd_info = BFD_INFO(unit);
   6552     uint16 reply_len;
   6553     int index;
   6554     int ep_found = 0;
   6555 
   6556     BFD_FEATURE_INIT_CHECK(unit);
   6557 
   6558     for (index = 0; index < bfd_info->endpoint_count; index++) {
   6559         if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   6560             ep_found = 1;
   6561             break;
   6562         }
   6563     }
   6564 
   6565     if (!ep_found) {
   6566         return BCM_E_NOT_FOUND;
   6567     }
   6568 
   6569     /* Send BFD Session Delete All message to uC */
   6570     BCM_IF_ERROR_RETURN
   6571         (bcmi_xgs5_bfd_msg_send_receive
   6572          (unit,
   6573           MOS_MSG_SUBCLASS_BFD_TX_STOP,
   6574           0, 0,
   6575           MOS_MSG_SUBCLASS_BFD_TX_STOP_REPLY,
   6576           &reply_len, bfd_uc_msg_timeout_usecs));
   6577 
   6578     if (reply_len != 0) {
   6579         return BCM_E_INTERNAL;
   6580     }
   6581 
   6582     return BCM_E_NONE;
   6583 
   6584 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6585     return BCM_E_UNAVAIL;
   6586 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6587 }
   6588 
   6589 /*
   6590  * Function:
   6591  *      bcmi_xgs5_bfd_endpoint_destroy
   6592  * Purpose:
   6593  *      Destroy an BFD endpoint object.
   6594  * Parameters:
   6595  *      unit     - (IN) Unit number.
   6596  *      endpoint - (IN) The ID of the BFD endpoint object to destroy.
   6597  * Returns:
   6598  *      BCM_E_NONE      Operation completed successfully
   6599  *      BCM_E_NOT_FOUND Attempt to destroy endpoint which does not exist
   6600  *      BCM_E_INTERNAL  Unable to release resource /
   6601  *                      Failed to read memory or read or write register
   6602  * Notes:
   6603  */
   6604 int
   6605 bcmi_xgs5_bfd_endpoint_destroy(int unit, bcm_bfd_endpoint_t endpoint)
   6606 {
   6607 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6608     bfd_info_t *bfd_info = BFD_INFO(unit);
   6609     bfd_endpoint_config_t *endpoint_config;
   6610     uint16 reply_len;
   6611 
   6612     BFD_FEATURE_INIT_CHECK(unit);
   6613 
   6614     ENDPOINT_INDEX_CHECK(unit, endpoint);
   6615 
   6616     if (!SHR_BITGET(bfd_info->endpoints_in_use, endpoint)) {
   6617         return BCM_E_NOT_FOUND;
   6618     }
   6619 
   6620     endpoint_config = BFD_ENDPOINT_CONFIG(unit, endpoint);
   6621 
   6622     /* Send BFD Session Delete message to uC */
   6623     BCM_IF_ERROR_RETURN
   6624         (bcmi_xgs5_bfd_msg_send_receive(unit,
   6625                                         MOS_MSG_SUBCLASS_BFD_SESS_DELETE,
   6626                                         endpoint_config->endpoint_index, 0,
   6627                                         MOS_MSG_SUBCLASS_BFD_SESS_DELETE_REPLY,
   6628                                         &reply_len, bfd_uc_msg_timeout_usecs));
   6629 
   6630     if (reply_len != 0) {
   6631         return BCM_E_INTERNAL;
   6632     }
   6633 
   6634     /* Delete BFD Session in HW, after BFD session deleted in FW*/
   6635     BCM_IF_ERROR_RETURN
   6636         (bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config));
   6637 
   6638     SHR_BITCLR(bfd_info->endpoints_in_use, endpoint_config->endpoint_index);
   6639     endpoint_config->endpoint_index = -1;
   6640     endpoint_config->is_l3_vpn = 0;
   6641     endpoint_config->is_micro_bfd = 0;
   6642     endpoint_config->local_echo = 0;
   6643 
   6644     return BCM_E_NONE;
   6645 
   6646 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6647     return BCM_E_UNAVAIL;
   6648 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6649 }
   6650 
   6651 /*
   6652  * Function:
   6653  *      bcmi_xgs5_bfd_endpoint_destroy_all
   6654  * Purpose:
   6655  *      Destroy all BFD endpoint objects.
   6656  * Parameters:
   6657  *      unit - (IN) Unit number.
   6658  * Returns:
   6659  *      BCM_E_NONE     Operation completed successfully
   6660  *      BCM_E_INTERNAL Unable to release resource /
   6661  *                     Failed to read memory or read or write register
   6662  * Notes:
   6663  */
   6664 int
   6665 bcmi_xgs5_bfd_endpoint_destroy_all(int unit)
   6666 {
   6667 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6668     bfd_info_t *bfd_info = BFD_INFO(unit);
   6669     bfd_endpoint_config_t *endpoint_config;
   6670     uint16 reply_len;
   6671     int index;
   6672 
   6673     BFD_FEATURE_INIT_CHECK(unit);
   6674 
   6675     for (index = 0; index < bfd_info->endpoint_count; index++) {
   6676         if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   6677             endpoint_config = BFD_ENDPOINT_CONFIG(unit, index);
   6678 
   6679             bcmi_xgs5_bfd_session_hw_delete(unit, endpoint_config);
   6680 
   6681             SHR_BITCLR(bfd_info->endpoints_in_use,
   6682                        endpoint_config->endpoint_index);
   6683             endpoint_config->endpoint_index = -1;
   6684             endpoint_config->is_l3_vpn = 0;
   6685             endpoint_config->is_micro_bfd = 0;
   6686             endpoint_config->local_echo = 0;
   6687         }
   6688     }
   6689 
   6690     /* Send BFD Session Delete All message to uC */
   6691     BCM_IF_ERROR_RETURN
   6692         (bcmi_xgs5_bfd_msg_send_receive
   6693          (unit,
   6694           MOS_MSG_SUBCLASS_BFD_SESS_DELETE_ALL,
   6695           0, 0,
   6696           MOS_MSG_SUBCLASS_BFD_SESS_DELETE_ALL_REPLY,
   6697           &reply_len, bfd_uc_msg_timeout_usecs));
   6698 
   6699     if (reply_len != 0) {
   6700         return BCM_E_INTERNAL;
   6701     }
   6702 
   6703     return BCM_E_NONE;
   6704 
   6705 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6706     return BCM_E_UNAVAIL;
   6707 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6708 }
   6709 
   6710 /*
   6711  * Function:
   6712  *      bcmi_xgs5_bfd_endpoint_poll
   6713  * Purpose:
   6714  *      Poll an BFD endpoint object.  Valid only for endpoint in Demand
   6715  *      Mode and in state bcmBFDStateUp.
   6716  * Parameters:
   6717  *      unit     - (IN) Unit number.
   6718  *      endpoint - (IN) The ID of the BFD endpoint object to poll.
   6719  * Returns:
   6720  *      BCM_E_NONE      Operation completed successfully
   6721  *      BCM_E_NOT_FOUND BFD Session ID not in use
   6722  *      BCM_E_INTERNAL  Unable to read or write resource
   6723  *      BCM_E_PARAM     Session not in Demand Mode/
   6724  *                      Session not in UP state
   6725  * Notes: The poll operation will be initiated.  Poll failure will be
   6726  * signalled via asynchronous callback (aka session failure)
   6727  */
   6728 int
   6729 bcmi_xgs5_bfd_endpoint_poll(int unit, bcm_bfd_endpoint_t endpoint)
   6730 {
   6731 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6732     bfd_info_t *bfd_info = BFD_INFO(unit);
   6733     bfd_endpoint_config_t *endpoint_config;
   6734     uint16 reply_len;
   6735 
   6736     BFD_FEATURE_INIT_CHECK(unit);
   6737 
   6738     ENDPOINT_INDEX_CHECK(unit, endpoint);
   6739 
   6740     if (!SHR_BITGET(bfd_info->endpoints_in_use, endpoint)) {
   6741         return BCM_E_NOT_FOUND;
   6742     }
   6743 
   6744     endpoint_config = BFD_ENDPOINT_CONFIG(unit, endpoint);
   6745 
   6746     /* Check for Demand mode */
   6747     if (!(endpoint_config->info.flags & BCM_BFD_ENDPOINT_DEMAND)) {
   6748         return BCM_E_CONFIG;
   6749     }
   6750 
   6751     /* Issue poll request on session not in the UP state will fail */
   6752 
   6753     /* Send BFD Session Poll message to uC */
   6754     BCM_IF_ERROR_RETURN
   6755         (bcmi_xgs5_bfd_msg_send_receive(unit,
   6756                                         MOS_MSG_SUBCLASS_BFD_SESS_POLL,
   6757                                         endpoint_config->endpoint_index, 0,
   6758                                         MOS_MSG_SUBCLASS_BFD_SESS_POLL_REPLY,
   6759                                         &reply_len, bfd_uc_msg_timeout_usecs));
   6760 
   6761     if (reply_len != 0) {
   6762         return BCM_E_INTERNAL;
   6763     }
   6764 
   6765     return BCM_E_NONE;
   6766 
   6767 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6768     return BCM_E_UNAVAIL;
   6769 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6770 }
   6771 
   6772 /*
   6773  * Function:
   6774  *      bcmi_xgs5_bfd_event_register
   6775  * Purpose:
   6776  *      Register a callback for handling BFD events.
   6777  * Parameters:
   6778  *      unit        - (IN) Unit number.
   6779  *      event_types - (IN) The set of BFD events for which the specified
   6780  *                    callback will be invoked.
   6781  *      cb          - (IN) A pointer to the callback function.
   6782  *      user_data   - (IN) Pointer to user data to pass to the callback.
   6783  * Returns:
   6784  *      BCM_E_NONE Operation completed successfully
   6785  * Notes:
   6786  */
   6787 int
   6788 bcmi_xgs5_bfd_event_register(int unit,
   6789                              bcm_bfd_event_types_t event_types,
   6790                              bcm_bfd_event_cb cb, void *user_data)
   6791 {
   6792 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6793     bfd_info_t *bfd_info = BFD_INFO(unit);
   6794     uint32 result;
   6795     bfd_event_handler_t *event_handler;
   6796     bfd_event_handler_t *previous = NULL;
   6797     bcm_bfd_event_type_t event_type;
   6798 
   6799     BFD_FEATURE_INIT_CHECK(unit);
   6800 
   6801     PARAM_NULL_CHECK(cb);
   6802 
   6803     SHR_BITTEST_RANGE(event_types.w, 0, bcmBFDEventCount, result);
   6804 
   6805     if (result == 0) {
   6806         return BCM_E_PARAM;
   6807     }
   6808 
   6809     for (event_handler = bfd_info->event_handler_list;
   6810          event_handler != NULL;
   6811          event_handler = event_handler->next) {
   6812         if (event_handler->cb == cb) {
   6813             break;
   6814         }
   6815 
   6816         previous = event_handler;
   6817     }
   6818 
   6819     if (event_handler == NULL) {
   6820         /* This handler hasn't been registered yet */
   6821 
   6822         event_handler = sal_alloc(sizeof(*event_handler), "BFD event handler");
   6823 
   6824         if (event_handler == NULL) {
   6825             return BCM_E_MEMORY;
   6826         }
   6827 
   6828         sal_memset(event_handler, 0, sizeof(*event_handler));
   6829 
   6830         event_handler->next = NULL;
   6831         event_handler->cb = cb;
   6832 
   6833         SHR_BITCLR_RANGE(event_handler->event_types.w, 0, bcmBFDEventCount);
   6834 
   6835         if (previous != NULL) {
   6836             previous->next = event_handler;
   6837         } else {
   6838             bfd_info->event_handler_list = event_handler;
   6839         }
   6840     }
   6841 
   6842     for (event_type = 0; event_type < bcmBFDEventCount; ++event_type) {
   6843         if (SHR_BITGET(event_types.w, event_type)) {
   6844             if (!SHR_BITGET(event_handler->event_types.w, event_type)) {
   6845                 /* This handler isn't handling this event yet */
   6846                 SHR_BITSET(event_handler->event_types.w, event_type);
   6847             }
   6848         }
   6849     }
   6850 
   6851     event_handler->user_data = user_data;
   6852 
   6853     /* Update Events mask */
   6854     return bcmi_xgs5_bfd_event_mask_set(unit);
   6855 
   6856 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6857     return BCM_E_UNAVAIL;
   6858 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6859 }
   6860 
   6861 /*
   6862  * Function:
   6863  *      bcmi_xgs5_bfd_event_unregister
   6864  * Purpose:
   6865  *      Unregister a callback for handling BFD events.
   6866  * Parameters:
   6867  *      unit        - (IN) Unit number.
   6868  *      event_types - (IN) The set of BFD events for which the specified
   6869  *                    callback should not be invoked.
   6870  *      cb          - (IN) A pointer to the callback function.
   6871  * Returns:
   6872  *      BCM_E_NONE Operation completed successfully
   6873  * Notes:
   6874  */
   6875 int
   6876 bcmi_xgs5_bfd_event_unregister(int unit,
   6877                                bcm_bfd_event_types_t event_types,
   6878                                bcm_bfd_event_cb cb)
   6879 {
   6880 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6881     bfd_info_t *bfd_info = BFD_INFO(unit);
   6882     uint32 result;
   6883     bfd_event_handler_t *event_handler;
   6884     bfd_event_handler_t *previous = NULL;
   6885     bcm_bfd_event_type_t event_type;
   6886 
   6887     BFD_FEATURE_INIT_CHECK(unit);
   6888 
   6889     PARAM_NULL_CHECK(cb);
   6890 
   6891     SHR_BITTEST_RANGE(event_types.w, 0, bcmBFDEventCount, result);
   6892 
   6893     if (result == 0) {
   6894         return BCM_E_PARAM;
   6895     }
   6896 
   6897     for (event_handler = bfd_info->event_handler_list;
   6898          event_handler != NULL;
   6899          event_handler = event_handler->next) {
   6900         if (event_handler->cb == cb) {
   6901             break;
   6902         }
   6903 
   6904         previous = event_handler;
   6905     }
   6906 
   6907     if (event_handler == NULL) {
   6908         return BCM_E_NOT_FOUND;
   6909     }
   6910 
   6911     for (event_type = 0; event_type < bcmBFDEventCount; ++event_type) {
   6912         if (SHR_BITGET(event_types.w, event_type)) {
   6913             SHR_BITCLR(event_handler->event_types.w, event_type);
   6914         }
   6915     }
   6916 
   6917     SHR_BITTEST_RANGE(event_handler->event_types.w, 0, bcmBFDEventCount,
   6918         result);
   6919 
   6920     if (result == 0) {
   6921         /* No more events for this handler to handle */
   6922         if (previous != NULL) {
   6923             previous->next = event_handler->next;
   6924         } else {
   6925             bfd_info->event_handler_list = event_handler->next;
   6926         }
   6927 
   6928         sal_free(event_handler);
   6929     }
   6930 
   6931     /* Update Events mask */
   6932     return bcmi_xgs5_bfd_event_mask_set(unit);
   6933 
   6934 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6935     return BCM_E_UNAVAIL;
   6936 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   6937 }
   6938 
   6939 /*
   6940  * Function:
   6941  *      bcmi_xgs5_bfd_endpoint_stat_get
   6942  * Purpose:
   6943  *      Get BFD endpoint statistics.
   6944  * Parameters:
   6945  *      unit     - (IN) Unit number.
   6946  *      endpoint - (IN) The ID of the endpoint object to get stats for.
   6947  *      ctr_info - (IN/OUT) Pointer to endpoint count structure to receive
   6948  *                 the data.
   6949  *      clear    - (IN) If set, clear stats after read.
   6950  * Returns:
   6951  *      BCM_E_NONE     Operation completed successfully
   6952  *      BCM_E_PARAM    Null pointer to counter information structure
   6953  *      BCM_E_MEMORY   Unable to allocate memory
   6954  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   6955  *                     Failed to read or write register
   6956  * Notes:
   6957  */
   6958 int
   6959 bcmi_xgs5_bfd_endpoint_stat_get(int unit,
   6960                                 bcm_bfd_endpoint_t endpoint,
   6961                                 bcm_bfd_endpoint_stat_t *ctr_info, uint32 options)
   6962 {
   6963 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   6964     bfd_info_t *bfd_info = BFD_INFO(unit);
   6965     bfd_sdk_msg_ctrl_stat_req_t stat_req;
   6966     bfd_sdk_msg_ctrl_stat_reply_t stat_reply;
   6967     uint8 *buffer_req, *buffer_reply, *buffer_ptr;
   6968     uint16 buffer_len, reply_len;
   6969     uint8 stat_64bit;
   6970 
   6971     BFD_FEATURE_INIT_CHECK(unit);
   6972 
   6973     PARAM_NULL_CHECK(ctr_info);
   6974 
   6975     ENDPOINT_INDEX_CHECK(unit, endpoint);
   6976 
   6977     if (!SHR_BITGET(bfd_info->endpoints_in_use, endpoint)) {
   6978         return BCM_E_NOT_FOUND;
   6979     }
   6980     stat_64bit = options & BCM_BFD_ENDPOINT_STAT_64BIT;
   6981 
   6982     if ((stat_64bit) && !BFD_UC_FEATURE_CHECK(BFD_FEATURE_64BIT_STAT)) {
   6983             LOG_ERROR(BSL_LS_BCM_BFD, (BSL_META_U(unit,
   6984                         "64 bit stat not supported")));
   6985             return BCM_E_UNAVAIL;
   6986     }
   6987 
   6988     /* Set control message data */
   6989     sal_memset(&stat_req, 0, sizeof(stat_req));
   6990     stat_req.sess_id = endpoint;
   6991     stat_req.options = options;
   6992 
   6993     /* Pack control message data into DMA */
   6994     buffer_req = bfd_info->dma_buffer;
   6995     buffer_ptr = bfd_sdk_msg_ctrl_stat_req_pack(buffer_req, &stat_req);
   6996     buffer_len = buffer_ptr - buffer_req;
   6997 
   6998     /* Send BFD Stat Get message to uC */
   6999     BCM_IF_ERROR_RETURN
   7000         (bcmi_xgs5_bfd_msg_send_receive(unit,
   7001                                         MOS_MSG_SUBCLASS_BFD_STAT_GET,
   7002                                         buffer_len, 0,
   7003                                         MOS_MSG_SUBCLASS_BFD_STAT_GET_REPLY,
   7004                                         &reply_len, bfd_uc_msg_timeout_usecs));
   7005 
   7006     /* Unpack control message data from DMA buffer */
   7007     sal_memset(&stat_reply, 0, sizeof(stat_reply));
   7008     buffer_reply = bfd_info->dma_buffer;
   7009     buffer_ptr = bfd_sdk_msg_ctrl_stat_reply_unpack(buffer_reply, &stat_reply, stat_64bit);
   7010     buffer_len = buffer_ptr - buffer_reply;
   7011     if (reply_len != buffer_len) {
   7012         return BCM_E_INTERNAL;
   7013     }
   7014 
   7015     if(stat_64bit) {
   7016         COMPILER_64_SET(ctr_info->packets_in_64, stat_reply.packets_in_hi,
   7017                         stat_reply.packets_in);
   7018         COMPILER_64_SET(ctr_info->packets_out_64, stat_reply.packets_out_hi,
   7019                         stat_reply.packets_out);
   7020         COMPILER_64_SET(ctr_info->packets_drop_64, stat_reply.packets_drop_hi,
   7021                         stat_reply.packets_drop);
   7022         COMPILER_64_SET(ctr_info->packets_auth_drop_64, stat_reply.packets_auth_drop_hi,
   7023                         stat_reply.packets_auth_drop);
   7024     } else {
   7025         ctr_info->packets_in = stat_reply.packets_in;
   7026         ctr_info->packets_out = stat_reply.packets_out;
   7027         ctr_info->packets_drop = stat_reply.packets_drop;
   7028         ctr_info->packets_auth_drop = stat_reply.packets_auth_drop;
   7029     }
   7030 
   7031     COMPILER_64_SET(ctr_info->packets_echo_reply,
   7032                     stat_reply.packets_echo_reply_hi,
   7033                     stat_reply.packets_echo_reply);
   7034 
   7035     return BCM_E_NONE;
   7036 
   7037 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7038     return BCM_E_UNAVAIL;
   7039 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7040 }
   7041 
   7042 /*
   7043  * Function:
   7044  *      bcmi_xgs5_bfd_auth_sha1_set
   7045  * Purpose:
   7046  *      Set SHA1 authentication entry.
   7047  * Parameters:
   7048  *      unit  - (IN) Unit number.
   7049  *      index - (IN) Index of the SHA1 entry to configure.
   7050  *      sha1  - (IN) Pointer to SHA1 info structure.
   7051  * Returns:
   7052  *      BCM_E_NONE     Operation completed successfully
   7053  *      BCM_E_PARAM    Null pointer to SHA1 information structure
   7054  *      BCM_E_MEMORY   Unable to allocate memory
   7055  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   7056  *                     Failed to read or write register
   7057  * Notes:
   7058  */
   7059 int
   7060 bcmi_xgs5_bfd_auth_sha1_set(int unit,
   7061                             int index, bcm_bfd_auth_sha1_t *sha1)
   7062 {
   7063 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   7064     bfd_info_t *bfd_info = BFD_INFO(unit);
   7065     shr_bfd_msg_ctrl_auth_sha1_t msg_auth;
   7066     uint8 *buffer, *buffer_ptr;
   7067     uint16 buffer_len, reply_len;
   7068 
   7069     BFD_FEATURE_INIT_CHECK(unit);
   7070 
   7071     PARAM_NULL_CHECK(sha1);
   7072 
   7073     AUTH_SHA1_INDEX_CHECK(unit, index);
   7074 
   7075     /* Set control message data */
   7076     sal_memset(&msg_auth, 0, sizeof(msg_auth));
   7077     msg_auth.index    = index;
   7078     msg_auth.enable   = sha1->enable;
   7079     msg_auth.sequence = sha1->sequence;
   7080     sal_memcpy(msg_auth.key, sha1->key, _SHR_BFD_AUTH_SHA1_KEY_LENGTH);
   7081 
   7082     /* Pack control message data into DMA buffer */
   7083     buffer     = bfd_info->dma_buffer;
   7084     buffer_ptr = shr_bfd_msg_ctrl_auth_sha1_pack(buffer, &msg_auth);
   7085     buffer_len = buffer_ptr - buffer;
   7086 
   7087     /* Send BFD Auth Sha1 Set message to uC */
   7088     BCM_IF_ERROR_RETURN
   7089         (bcmi_xgs5_bfd_msg_send_receive
   7090          (unit,
   7091           MOS_MSG_SUBCLASS_BFD_AUTH_SHA1_SET,
   7092           buffer_len, 0,
   7093           MOS_MSG_SUBCLASS_BFD_AUTH_SHA1_SET_REPLY,
   7094           &reply_len, bfd_uc_msg_timeout_usecs));
   7095     if (reply_len != 0) {
   7096         return BCM_E_INTERNAL;
   7097     }
   7098 
   7099     bfd_info->auth_sha1[index] = *sha1;
   7100 
   7101     return BCM_E_NONE;
   7102 
   7103 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7104     return BCM_E_UNAVAIL;
   7105 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7106 }
   7107 
   7108 
   7109 /*
   7110  * Function:
   7111  *      bcmi_xgs5_bfd_auth_sha1_get
   7112  * Purpose:
   7113  *      Get SHA1 authentication entry.
   7114  * Parameters:
   7115  *      unit  - (IN) Unit number.
   7116  *      index - (IN) Index of the SHA1 entry to retrieve.
   7117  *      sha1  - (IN/OUT) Pointer to SHA1 info structure to receive the data.
   7118  * Returns:
   7119  *      BCM_E_NONE     Operation completed successfully
   7120  *      BCM_E_PARAM    Null pointer to SHA1 information structure
   7121  *      BCM_E_MEMORY   Unable to allocate memory
   7122  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   7123  *                     Failed to read or write register
   7124  * Notes:
   7125  */
   7126 int
   7127 bcmi_xgs5_bfd_auth_sha1_get(int unit,
   7128                             int index, bcm_bfd_auth_sha1_t *sha1)
   7129 {
   7130 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   7131     bfd_info_t *bfd_info = BFD_INFO(unit);
   7132     shr_bfd_msg_ctrl_auth_sha1_t msg_auth;
   7133     uint8 *buffer, *buffer_ptr;
   7134     uint16 buffer_len, reply_len;
   7135 
   7136     BFD_FEATURE_INIT_CHECK(unit);
   7137 
   7138     PARAM_NULL_CHECK(sha1);
   7139 
   7140     AUTH_SHA1_INDEX_CHECK(unit, index);
   7141 
   7142     /* If warmboot, get authentication data from uController, else use cache */
   7143     if (SOC_WARM_BOOT(unit)) {
   7144 
   7145         /* Send BFD Auth Sha1 Get message to uC */
   7146         BCM_IF_ERROR_RETURN
   7147             (bcmi_xgs5_bfd_msg_send_receive
   7148              (unit,
   7149               MOS_MSG_SUBCLASS_BFD_AUTH_SHA1_GET,
   7150               index, 0,
   7151               MOS_MSG_SUBCLASS_BFD_AUTH_SHA1_GET_REPLY,
   7152               &reply_len, bfd_uc_msg_timeout_usecs));
   7153 
   7154         /* Unpack control message data from DMA buffer */
   7155         sal_memset(&msg_auth, 0, sizeof(msg_auth));
   7156         buffer     = bfd_info->dma_buffer;
   7157         buffer_ptr = shr_bfd_msg_ctrl_auth_sha1_unpack(buffer, &msg_auth);
   7158         buffer_len = buffer_ptr - buffer;
   7159 
   7160         if (reply_len != buffer_len) {
   7161             return BCM_E_INTERNAL;
   7162         }
   7163 
   7164         bfd_info->auth_sha1[index].enable   = msg_auth.enable;
   7165         bfd_info->auth_sha1[index].sequence = msg_auth.sequence;
   7166         sal_memcpy(bfd_info->auth_sha1[index].key, msg_auth.key,
   7167                    _SHR_BFD_AUTH_SHA1_KEY_LENGTH);
   7168 
   7169     }
   7170 
   7171     *sha1 = bfd_info->auth_sha1[index];
   7172 
   7173     return BCM_E_NONE;
   7174 
   7175 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7176     return BCM_E_UNAVAIL;
   7177 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7178 }
   7179 
   7180 /*
   7181  * Function:
   7182  *      bcmi_xgs5_bfd_auth_simple_password_set
   7183  * Purpose:
   7184  *      Set Simple Password authentication entry.
   7185  * Parameters:
   7186  *      unit  - (IN) Unit number.
   7187  *      index - (IN) Index of the Simple Password entry to configure.
   7188  *      sp    - (IN) Pointer to Simple Password info structure.
   7189  * Returns:
   7190  *      BCM_E_NONE     Operation completed successfully
   7191  *      BCM_E_PARAM    Null pointer to SHA1 information structure
   7192  *      BCM_E_MEMORY   Unable to allocate memory
   7193  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   7194  *                     Failed to read or write register
   7195  * Notes:
   7196  */
   7197 int
   7198 bcmi_xgs5_bfd_auth_simple_password_set(int unit,
   7199                                        int index,
   7200                                        bcm_bfd_auth_simple_password_t *sp)
   7201 {
   7202 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   7203     bfd_info_t *bfd_info = BFD_INFO(unit);
   7204     shr_bfd_msg_ctrl_auth_sp_t msg_auth;
   7205     uint8 *buffer, *buffer_ptr;
   7206     uint16 buffer_len, reply_len;
   7207 
   7208     BFD_FEATURE_INIT_CHECK(unit);
   7209 
   7210     PARAM_NULL_CHECK(sp);
   7211 
   7212     AUTH_SP_INDEX_CHECK(unit, index);
   7213 
   7214     /* Password length MUST be from 1 to 16 bytes */
   7215     if ((sp->length == 0) ||
   7216         ( sp->length > _SHR_BFD_AUTH_SIMPLE_PASSWORD_KEY_LENGTH)) {
   7217         LOG_ERROR(BSL_LS_BCM_COMMON,
   7218                   (BSL_META_U(unit,
   7219                               "BFD simple password length must be from 1 to 16 bytes\n")));
   7220         return BCM_E_PARAM;
   7221     }
   7222 
   7223     /* Set control message data */
   7224     sal_memset(&msg_auth, 0, sizeof(msg_auth));
   7225     msg_auth.index  = index;
   7226     msg_auth.length = sp->length;
   7227     sal_memcpy(msg_auth.password, sp->password,
   7228                _SHR_BFD_AUTH_SIMPLE_PASSWORD_KEY_LENGTH);
   7229 
   7230     /* Pack control message data into DMA buffer */
   7231     buffer     = bfd_info->dma_buffer;
   7232     buffer_ptr = shr_bfd_msg_ctrl_auth_sp_pack(buffer, &msg_auth);
   7233     buffer_len = buffer_ptr - buffer;
   7234 
   7235     /* Send BFD Auth SimplePassword Set message to uC */
   7236     BCM_IF_ERROR_RETURN
   7237         (bcmi_xgs5_bfd_msg_send_receive(unit,
   7238                                         MOS_MSG_SUBCLASS_BFD_AUTH_SP_SET,
   7239                                         buffer_len, 0,
   7240                                         MOS_MSG_SUBCLASS_BFD_AUTH_SP_SET_REPLY,
   7241                                         &reply_len, bfd_uc_msg_timeout_usecs));
   7242 
   7243     if (reply_len != 0) {
   7244         return BCM_E_INTERNAL;
   7245     }
   7246 
   7247     bfd_info->auth_sp[index] = *sp;
   7248 
   7249     return BCM_E_NONE;
   7250 
   7251 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7252     return BCM_E_UNAVAIL;
   7253 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7254 }
   7255 
   7256 /*
   7257  * Function:
   7258  *      bcmi_xgs5_bfd_auth_simple_password_get
   7259  * Purpose:
   7260  *      Get Simple Password authentication entry.
   7261  * Parameters:
   7262  *      unit  - (IN) Unit number.
   7263  *      index - (IN) Index of the Simple Password entry to retrieve.
   7264  *      sp    - (IN/OUT) Pointer to Simple Password info structure to
   7265  *              receive the data.
   7266  * Returns:
   7267  *      BCM_E_NONE     Operation completed successfully
   7268  *      BCM_E_PARAM    Null pointer to SHA1 information structure
   7269  *      BCM_E_MEMORY   Unable to allocate memory
   7270  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   7271  *                     Failed to read or write register
   7272  * Notes:
   7273  */
   7274 int
   7275 bcmi_xgs5_bfd_auth_simple_password_get(int unit,
   7276                                        int index,
   7277                                        bcm_bfd_auth_simple_password_t *sp)
   7278 {
   7279 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   7280     bfd_info_t *bfd_info = BFD_INFO(unit);
   7281     shr_bfd_msg_ctrl_auth_sp_t msg_auth;
   7282     uint8 *buffer, *buffer_ptr;
   7283     uint16 buffer_len, reply_len;
   7284 
   7285     BFD_FEATURE_INIT_CHECK(unit);
   7286 
   7287     PARAM_NULL_CHECK(sp);
   7288 
   7289     AUTH_SP_INDEX_CHECK(unit, index);
   7290 
   7291     /* If warmboot, get authentication data from uController, else use cache */
   7292     if (SOC_WARM_BOOT(unit)) {
   7293 
   7294         /* Send BFD Auth SimplePassword Get message to uC */
   7295         BCM_IF_ERROR_RETURN
   7296             (bcmi_xgs5_bfd_msg_send_receive
   7297              (unit,
   7298               MOS_MSG_SUBCLASS_BFD_AUTH_SP_GET,
   7299               index, 0,
   7300               MOS_MSG_SUBCLASS_BFD_AUTH_SP_GET_REPLY,
   7301               &reply_len, bfd_uc_msg_timeout_usecs));
   7302 
   7303         /* Unpack control message data from DMA buffer */
   7304         sal_memset(&msg_auth, 0, sizeof(msg_auth));
   7305         buffer     = bfd_info->dma_buffer;
   7306         buffer_ptr = shr_bfd_msg_ctrl_auth_sp_unpack(buffer, &msg_auth);
   7307         buffer_len = buffer_ptr - buffer;
   7308 
   7309         if (reply_len != buffer_len) {
   7310             return BCM_E_INTERNAL;
   7311         }
   7312 
   7313         bfd_info->auth_sp[index].length = msg_auth.length;
   7314         sal_memcpy(bfd_info->auth_sp[index].password, msg_auth.password,
   7315                    _SHR_BFD_AUTH_SIMPLE_PASSWORD_KEY_LENGTH);
   7316     }
   7317 
   7318     *sp = bfd_info->auth_sp[index];
   7319 
   7320     return BCM_E_NONE;
   7321 
   7322 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7323     return BCM_E_UNAVAIL;
   7324 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7325 }
   7326 
   7327 /*
   7328  * Function:
   7329  *     bcmi_xgs5_bfd_status_multi_get
   7330  * Purpose:
   7331  *      Function to retrieve all required Session status of valid BFD end points
   7332  *      in a single call.
   7333  * Parameters:
   7334  *      unit                (IN) BCM device number
   7335  *      max_endpoints       (IN) Number of max endpoint for the protocol
   7336  *      status_arr          (OUT) Pointer to BFD status of all endpoints
   7337  *      endpoint_count      (OUT) Pointer to Number of valid BFD endpoints,
   7338  *                                filled by get API.
   7339  *
   7340  * Returns:
   7341  *      BCM_E_NONE     Operation completed successfully
   7342  *      BCM_E_PARAM    Null pointer to SHA1 information structure
   7343  *      BCM_E_MEMORY   Unable to allocate memory
   7344  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   7345  *                     Failed to read or write register
   7346  */
   7347 int
   7348 bcmi_xgs5_bfd_status_multi_get(
   7349            int unit,
   7350            int max_endpoints,
   7351            bcm_bfd_status_t *status_arr,
   7352            int *count)
   7353 {
   7354 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   7355     bfd_info_t *bfd_info = BFD_INFO(unit);
   7356     bfd_endpoint_config_t *endpoint_config;
   7357     bcm_bfd_status_t *status_temp = status_arr;
   7358     uint8 *buffer;
   7359     uint16 reply_len;
   7360     uint32 status_bitmap;
   7361     int ep_count = 0;
   7362     int index, buffer_len;
   7363 
   7364     BFD_FEATURE_INIT_CHECK(unit);
   7365 
   7366     /* Get no of active bfd sessions only, if max_endpoints 0 */
   7367     if (!max_endpoints) {
   7368         for(index = 0; index < bfd_info->endpoint_count; index++) {
   7369             /* If endpoint not in use, ignore and continue for next session_id). */
   7370             if (!SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   7371                 continue;
   7372             }
   7373             ep_count++;
   7374         }
   7375         *count = ep_count;
   7376         return BCM_E_NONE;
   7377     }
   7378 
   7379     sal_memset(status_arr, 0, ((sizeof(bcm_bfd_status_t))*max_endpoints));
   7380 
   7381     buffer_len = bfd_info->endpoint_count * sizeof(uint32);
   7382     buffer = soc_cm_salloc(unit, buffer_len, "BFD multi stat get buffer");
   7383     if (!buffer) {
   7384         return BCM_E_MEMORY;
   7385     }
   7386 
   7387     sal_memset(buffer, 0, buffer_len);
   7388 
   7389     /* Send BFD Status Get message to uC */
   7390     BCM_IF_ERROR_RETURN
   7391         (bcmi_xgs5_bfd_msg_status_receive
   7392                                       (unit,
   7393                                        MOS_MSG_SUBCLASS_BFD_STATUS_MULTI_GET,
   7394                                        0, 0,
   7395                                        MOS_MSG_SUBCLASS_BFD_STATUS_MULTI_GET_REPLY,
   7396                                        &reply_len, bfd_uc_msg_timeout_usecs, buffer,
   7397                                        buffer_len));
   7398 
   7399     /* Unpack control message data from DMA buffer */
   7400     if (reply_len != buffer_len) {
   7401        return BCM_E_INTERNAL;
   7402     }
   7403 
   7404     for(index = 0; index < bfd_info->endpoint_count; index++) {
   7405 
   7406         /* If endpoint not in use, ignore and continue for next session_id). */
   7407         if (!SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   7408              continue;
   7409         }
   7410 
   7411         endpoint_config = BFD_ENDPOINT_CONFIG(unit, index);
   7412 
   7413         _SHR_UNPACK_U32(buffer, status_bitmap);
   7414 
   7415         status_temp->endpoint_id = endpoint_config->info.id;
   7416 
   7417         /* Update local state status */
   7418         if (status_bitmap & BFD_BTE_EVENT_LOCAL_ADMIN_DOWN) {
   7419             status_temp->session_status |= BCM_BFD_STATUS_LOCAL_ADMIN_DOWN;
   7420         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DOWN) {
   7421             status_temp->session_status |= BCM_BFD_STATUS_LOCAL_DOWN;
   7422         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_INIT) {
   7423             status_temp->session_status |= BCM_BFD_STATUS_LOCAL_INIT;
   7424         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_UP) {
   7425             status_temp->session_status |= BCM_BFD_STATUS_LOCAL_UP;
   7426         }
   7427 
   7428         /* Update remote state status */
   7429         if (status_bitmap & BFD_BTE_EVENT_REMOTE_ADMIN_DOWN) {
   7430             status_temp->session_status |= BCM_BFD_STATUS_REMOTE_ADMIN_DOWN;
   7431         } else if (status_bitmap & BFD_BTE_EVENT_REMOTE_DOWN) {
   7432             status_temp->session_status |= BCM_BFD_STATUS_REMOTE_DOWN;
   7433         } else if (status_bitmap & BFD_BTE_EVENT_REMOTE_INIT) {
   7434             status_temp->session_status |= BCM_BFD_STATUS_REMOTE_INIT;
   7435         } else if (status_bitmap & BFD_BTE_EVENT_REMOTE_UP) {
   7436             status_temp->session_status |= BCM_BFD_STATUS_REMOTE_UP;
   7437         }
   7438 
   7439         /* Update diag status */
   7440         if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_NONE) {
   7441             status_temp->session_status |=
   7442                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_NONE;
   7443         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_CTRL_DETECT_TIME_EXPIRED) {
   7444             status_temp->session_status |=
   7445                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_CTRL_DETECT_TIME_EXPIRED;
   7446         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_ECHO_FAILED) {
   7447             status_temp->session_status |=
   7448                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_ECHO_FAILED;
   7449         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_NEIGHBOR_SIGNALED_SESSION_DOWN) {
   7450             status_temp->session_status |=
   7451                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_NEIGHBOR_SIGNALED_SESSION_DOWN;
   7452         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_FORWARDING_PLANE_RESET) {
   7453             status_temp->session_status |=
   7454                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_FORWARDING_PLANE_RESET;
   7455         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_PATH_DOWN) {
   7456             status_temp->session_status |=
   7457                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_PATH_DOWN;
   7458         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_CONCATENATED_PATH_DOWN) {
   7459             status_temp->session_status |=
   7460                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_CONCATENATED_PATH_DOWN;
   7461         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_ADMIN_DOWN) {
   7462             status_temp->session_status |=
   7463                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_ADMIN_DOWN;
   7464         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_REVERSE_CONCATENATED_PATH_DOWN) {
   7465             status_temp->session_status |=
   7466                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_REVERSE_CONCATENATED_PATH_DOWN;
   7467         } else if (status_bitmap & BFD_BTE_EVENT_LOCAL_DIAG_CODE_MIS_CONNECTIVITY_DEFECT) {
   7468             status_temp->session_status |=
   7469                 BCM_BFD_STATUS_LOCAL_DIAG_CODE_MIS_CONNECTIVITY_DEFECT;
   7470         }
   7471 
   7472         ep_count++;
   7473         status_temp++;
   7474     }
   7475 
   7476     *count = ep_count;
   7477 
   7478     if (buffer != NULL) {
   7479         soc_cm_sfree(unit, buffer);
   7480     }
   7481 
   7482     return BCM_E_NONE;
   7483 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7484     return BCM_E_UNAVAIL;
   7485 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7486 }
   7487 
   7488 /*
   7489  * Function:
   7490  *      bcmi_xgs5_bfd_discard_stat_set
   7491  * Purpose:
   7492  *      Reset the BFD discard statistics
   7493  * Parameters:
   7494  *      unit  - (IN) Unit number.
   7495  *      discarded_info - (OUT) Pointer to discard info
   7496  * Returns:
   7497  *      BCM_E_NONE     Operation completed successfully
   7498  *      BCM_E_PARAM    Null pointer to discarded_info structure
   7499  *      BCM_E_MEMORY   Unable to allocate memory
   7500  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   7501  *                     Failed to read or write register
   7502  */
   7503 int
   7504 bcmi_xgs5_bfd_discard_stat_set(int unit,
   7505                                bcm_bfd_discard_stat_t *discarded_info)
   7506 {
   7507 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   7508     bfd_info_t *bfd_info = BFD_INFO(unit);
   7509     uint16 reply_len;
   7510     int index;
   7511     int ep_found = 0;
   7512 
   7513     BFD_FEATURE_INIT_CHECK(unit);
   7514 
   7515     for (index = 0; index < bfd_info->endpoint_count; index++) {
   7516          if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   7517              ep_found = 1;
   7518              break;
   7519          }
   7520     }
   7521 
   7522     if (!ep_found) {
   7523         return BCM_E_NOT_FOUND;
   7524     }
   7525 
   7526     /* Send BFD reset discard stat message to uC */
   7527     BCM_IF_ERROR_RETURN
   7528         (bcmi_xgs5_bfd_msg_send_receive(unit,
   7529                                         MOS_MSG_SUBCLASS_BFD_DISCARD_STAT_SET,
   7530                                         0, 0,
   7531                                         MOS_MSG_SUBCLASS_BFD_DISCARD_STAT_SET_REPLY,
   7532                                         &reply_len, bfd_uc_msg_timeout_usecs));
   7533     if (reply_len != 0) {
   7534         return BCM_E_INTERNAL;
   7535     }
   7536 
   7537     return BCM_E_NONE;
   7538 
   7539 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7540     return BCM_E_UNAVAIL;
   7541 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7542 }
   7543 
   7544 /*
   7545  * Function:
   7546  *      bcmi_xgs5_bfd_discard_stat_get
   7547  * Purpose:
   7548  *      Get the BFD discard statistics
   7549  * Parameters:
   7550  *      unit  - (IN) Unit number.
   7551  *      discarded_info - (OUT) Pointer to discard info
   7552  * Returns:
   7553  *      BCM_E_NONE     Operation completed successfully
   7554  *      BCM_E_PARAM    Null pointer to discarded_info structure
   7555  *      BCM_E_MEMORY   Unable to allocate memory
   7556  *      BCM_E_INTERNAL Unable to obtain/release resource lock /
   7557  *                     Failed to read or write register
   7558  */
   7559 int
   7560 bcmi_xgs5_bfd_discard_stat_get(int unit,
   7561                                bcm_bfd_discard_stat_t *discarded_info)
   7562 {
   7563 #if defined(BCM_CMICM_SUPPORT) ||  defined(BCM_CMICX_SUPPORT)
   7564     bfd_info_t *bfd_info = BFD_INFO(unit);
   7565     bfd_sdk_msg_ctrl_discard_stat_get_t msg_discard_stat;
   7566     uint8 *buffer, *buffer_ptr;
   7567     uint16 buffer_len, reply_len;
   7568     int index;
   7569     int ep_found = 0;
   7570 
   7571     BFD_FEATURE_INIT_CHECK(unit);
   7572 
   7573     for (index = 0; index < bfd_info->endpoint_count; index++) {
   7574          if (SHR_BITGET(bfd_info->endpoints_in_use, index)) {
   7575              ep_found = 1;
   7576              break;
   7577          }
   7578     }
   7579 
   7580     if (!ep_found) {
   7581         return BCM_E_NOT_FOUND;
   7582     }
   7583 
   7584     /* Send BFD Discard Get message to uC */
   7585     BCM_IF_ERROR_RETURN
   7586         (bcmi_xgs5_bfd_msg_send_receive(unit,
   7587                                         MOS_MSG_SUBCLASS_BFD_DISCARD_STAT_GET,
   7588                                         0, 0,
   7589                                         MOS_MSG_SUBCLASS_BFD_DISCARD_STAT_GET_REPLY,
   7590                                         &reply_len, bfd_uc_msg_timeout_usecs));
   7591 
   7592     /* Unpack control message data from DMA buffer */
   7593     sal_memset(&msg_discard_stat, 0, sizeof(msg_discard_stat));
   7594     buffer     = bfd_info->dma_buffer;
   7595     buffer_ptr = bfd_sdk_msg_ctrl_discard_stat_get_unpack(buffer, &msg_discard_stat);
   7596     buffer_len = buffer_ptr - buffer;
   7597 
   7598     if (reply_len != buffer_len) {
   7599          return BCM_E_INTERNAL;
   7600     }
   7601 
   7602     discarded_info->bfd_ver_err = msg_discard_stat.bfd_ver_err;
   7603     discarded_info->bfd_len_err = msg_discard_stat.bfd_len_err;
   7604     discarded_info->bfd_detect_mult = msg_discard_stat.bfd_detect_mult;
   7605     discarded_info->bfd_my_disc = msg_discard_stat.bfd_my_disc;
   7606     discarded_info->bfd_p_f_bit = msg_discard_stat.bfd_p_f_bit;
   7607     discarded_info->bfd_m_bit = msg_discard_stat.bfd_m_bit;
   7608     discarded_info->bfd_auth_type_mismatch = msg_discard_stat.bfd_auth_type_mismatch;
   7609     discarded_info->bfd_auth_simple_err = msg_discard_stat.bfd_auth_simple_err;
   7610     discarded_info->bfd_auth_m_sha1_err = msg_discard_stat.bfd_auth_m_sha1_err;
   7611     discarded_info->bfd_sess_mismatch = msg_discard_stat.bfd_sess_mismatch;
   7612 
   7613     return BCM_E_NONE;
   7614 
   7615 #else  /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7616     return BCM_E_UNAVAIL;
   7617 #endif /* BCM_CMICM_SUPPORT || BCM_CMICX_SUPPORT */
   7618 }
   7619 
   7620 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   7621 /*
   7622  * Function:
   7623  *      bcmi_xgs5_bfd_sw_dump
   7624  * Purpose:
   7625  *      Displays BFD information maintained by software.
   7626  * Parameters:
   7627  *      unit  - (IN) Unit number.
   7628  * Returns:
   7629  *      None
   7630  */
   7631 void
   7632 bcmi_xgs5_bfd_sw_dump(int unit)
   7633 {
   7634     bfd_info_t *bfd_info = BFD_INFO(unit);
   7635     bfd_endpoint_config_t *endpoint_config;
   7636     int endpoint_idx;
   7637     SHR_BITDCL word;
   7638 
   7639     if (!BFD_INIT(unit)) {
   7640         return;
   7641     }
   7642 
   7643     LOG_CLI((BSL_META_U(unit,
   7644                         "\nSW Information BFD - Unit %d\n"), unit));
   7645 
   7646     LOG_CLI((BSL_META_U(unit,
   7647                         "\n endpoints_in_use \n")));
   7648     for (word = 0; word < _SHR_BITDCLSIZE
   7649              (bfd_info->endpoint_count); word++) {
   7650         LOG_CLI((BSL_META_U(unit,
   7651                             " word %d value %x "), word,
   7652                  bfd_info->endpoints_in_use[word]));
   7653     }
   7654 
   7655     LOG_CLI((BSL_META_U(unit,
   7656                         "\n Endpoint Information \n")));
   7657     for (endpoint_idx = 0; endpoint_idx < bfd_info->endpoint_count;
   7658          endpoint_idx++) {
   7659         if (!SHR_BITGET(bfd_info->endpoints_in_use, endpoint_idx)) {
   7660             continue;
   7661         }
   7662         endpoint_config = BFD_ENDPOINT_CONFIG(unit, endpoint_idx);
   7663         LOG_CLI((BSL_META_U(unit,
   7664                             "\n Endpoint index %d\n"), endpoint_idx));
   7665         LOG_CLI((BSL_META_U(unit,
   7666                             "\t Type %x\n"), endpoint_config->info.type));
   7667         LOG_CLI((BSL_META_U(unit,
   7668                             "\t VRF id %x\n"), endpoint_config->info.vrf_id));
   7669     }
   7670 
   7671     return;
   7672 }
   7673 #endif  /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   7674 
   7675 #ifdef BCM_WARM_BOOT_SUPPORT
   7676 
   7677 
   7678 /*
   7679  * Function:
   7680  *       _bcmi_bfd_wb_downgrade_config_set
   7681  * Purpose:
   7682  *     BFD warmboot configuration set
   7683  * Parameters:
   7684  *     unit - (IN) BCM device number
   7685  *     warmboot_ver - WarmBoot Version for SDK
   7686  * Returns:
   7687  *     BCM_E_XXX
   7688  */
   7689 
   7690 int
   7691 _bcmi_bfd_wb_downgrade_config_set(int unit, uint32 warmboot_ver)
   7692 {
   7693     int pos=0;
   7694     bfd_info_t *bfd_info;
   7695 
   7696     BFD_FEATURE_INIT_CHECK(unit);
   7697     bfd_info = BFD_INFO(unit);
   7698 
   7699     for (pos = 0; pos < COUNTOF(_bfd_sdk_warmboot_version); pos++) {
   7700         if (_bfd_sdk_warmboot_version[pos][0] == warmboot_ver) {
   7701             if (bfd_info->wb_current_version != _bfd_sdk_warmboot_version[pos][1]) {
   7702                 bfd_info->wb_next_version = _bfd_sdk_warmboot_version[pos][1];
   7703                 break;
   7704             } else {
   7705                 return BCM_E_NONE;
   7706             }
   7707         } else if ((pos > 0) &&
   7708                 (_bfd_sdk_warmboot_version[pos][0] > warmboot_ver) &&
   7709                 (_bfd_sdk_warmboot_version[pos - 1][0] < warmboot_ver)) {
   7710                  /* _bfd_sdk_warmboot_version database will be updated only when a
   7711                   * WB change is present in a version. So this database structure will not have
   7712                   * all the version number. When a requested version number is in between 2
   7713                   *  valid versions, use the previous version number. */
   7714                 pos--;
   7715                 if (bfd_info->wb_current_version != _bfd_sdk_warmboot_version[pos][1]) {
   7716                     bfd_info->wb_next_version = _bfd_sdk_warmboot_version[pos][1];
   7717                 } else {
   7718                     return BCM_E_NONE;
   7719                 }
   7720         }
   7721     }
   7722 
   7723     if (pos == COUNTOF(_bfd_sdk_warmboot_version)) {
   7724             LOG_ERROR(BSL_LS_BCM_COMMON,
   7725                       (BSL_META_U(unit,
   7726                        "Version invalid for Warmboot Upgrade / Downgrade\n")));
   7727             return BCM_E_PARAM;
   7728     }
   7729 
   7730     LOG_VERBOSE(BSL_LS_BCM_BFD,
   7731                 (BSL_META_U(unit, "BFD(unit %d) Next WB version [0x%x]\n"),
   7732                 unit, bfd_info->wb_next_version));
   7733 
   7734     return BCM_E_NONE;
   7735 }
   7736 
   7737 /*
   7738  * Function:
   7739  *       bcmi_xgs5_bfd_scache_alloc
   7740  * Purpose:
   7741  *     Allocate scache memory for OAM module
   7742  * Parameters:
   7743  *     unit - (IN) BCM device number
   7744  * Returns:
   7745  *     BCM_E_UNIT    - Invalid BCM unit number.
   7746  *     BCM_E_UNAVAIL - OAM not support on this device.
   7747  *     BCM_E_MEMORY  - Allocation failure
   7748  *     CM_E_XXX     - Error code from bcm_XX_oam_init()
   7749  *     BCM_E_NONE    - Success
   7750  */
   7751 STATIC int
   7752 bcmi_xgs5_bfd_scache_alloc(int unit)
   7753 {
   7754     bfd_info_t *bfd_info;
   7755     soc_scache_handle_t scache_handle;
   7756     uint8 *bfd_scache;
   7757     int alloc_size = 0;
   7758 
   7759     bfd_info = BFD_INFO(unit);
   7760 
   7761     /* Calculate the size to store BFD num session count */
   7762     alloc_size += sizeof(int);
   7763 
   7764     /* Calculate the size to store BFD  end point bit usage  usage */
   7765     alloc_size += SHR_BITALLOCSIZE(bfd_info->endpoint_count);
   7766 
   7767     /* Calculate the size of Packet vlan id */
   7768     alloc_size += (sizeof(bcm_vlan_t) * bfd_info->endpoint_count);
   7769 
   7770     /* Calculate the size of tunnel type */
   7771     alloc_size += (sizeof(bcm_bfd_tunnel_type_t) * bfd_info->endpoint_count);
   7772 
   7773     /* Calculate the size of gport */
   7774     alloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   7775 
   7776     /* Calculate the size of tx gport */
   7777     alloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   7778 
   7779     /* Calculate the size of remote gport */
   7780     alloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   7781 
   7782     /* Calculate the size of bfd period */
   7783     alloc_size += (sizeof(int) * bfd_info->endpoint_count);
   7784 
   7785     /* Calculate the size of vpn */
   7786     alloc_size += (sizeof(bcm_vpn_t) * bfd_info->endpoint_count);
   7787 
   7788     /* Calculate the size of vlan_pri */
   7789     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7790 
   7791     /* Calculate the size of inner_vlan_pri */
   7792     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7793 
   7794     /* Calculate the size of vrf_id */
   7795     alloc_size += (sizeof(bcm_vrf_t) * bfd_info->endpoint_count);
   7796 
   7797     /* Calculate the size of dst_ip_addr */
   7798     alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   7799 
   7800     /* Calculate the size of dst_ip6_addr */
   7801     alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   7802 
   7803     /* Calculate the size of src_ip_addr */
   7804     alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   7805 
   7806     /* Calculate the size of src_ip6_addr */
   7807     alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   7808 
   7809     /* Calculate the size of ip_tos */
   7810     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7811 
   7812     /* Calculate the size of ip_ttl */
   7813     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7814 
   7815     /* Calculate the size of inner_dst_ip_addr */
   7816     alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   7817 
   7818     /* Calculate the size of inner_dst_ip6_addr */
   7819     alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   7820 
   7821     /* Calculate the size of inner_src_ip_addr */
   7822     alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   7823 
   7824     /* Calculate the size of inner_src_ip6_addr */
   7825     alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   7826 
   7827     /* Calculate the size of inner_ip_tos */
   7828     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7829 
   7830     /* Calculate the size of inner_ip_ttl */
   7831     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7832 
   7833     /* Calculate the size of udp_src_port */
   7834     alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   7835 
   7836     /* Calculate the size of mpls label */
   7837     alloc_size += (sizeof(bcm_mpls_label_t) * bfd_info->endpoint_count);
   7838 
   7839     if(bfd_info->wb_current_version <= BCM_BFD_WB_VERSION_1_2) {
   7840         alloc_size += (VERSION_1_2_EGRESS_LABEL_SIZE * bfd_info->endpoint_count);
   7841     } else {
   7842         /* Calculate the size of egress_label.exp */
   7843         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7844 
   7845         /* Calculate the size of egress_label.ttl */
   7846         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7847 
   7848     }
   7849 
   7850     /* Calculate the size of egress interface */
   7851     alloc_size += (sizeof(bcm_if_t) * bfd_info->endpoint_count);
   7852 
   7853     /* Calculate the size of mep_id_length */
   7854     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7855 
   7856     /* Calculate the size of mep_id */
   7857     alloc_size += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH * bfd_info->endpoint_count);
   7858 
   7859     /* Calculate the size of int_pri */
   7860     alloc_size += (sizeof(bcm_cos_t) * bfd_info->endpoint_count);
   7861 
   7862     /* Calculate the size of cpu_qid */
   7863     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7864 
   7865     /* Calculate the size of auth type */
   7866     alloc_size += (sizeof(bcm_bfd_auth_type_t) * bfd_info->endpoint_count);
   7867 
   7868     /* Calculate the size of auth_index */
   7869     alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   7870 
   7871     /* Calculate the size of sampling_ratio */
   7872     alloc_size += (sizeof(int) * bfd_info->endpoint_count);
   7873 
   7874     /* Calculate the size of loc_clear_threshold */
   7875     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7876 
   7877     /* Calculate the size of ip_subnet_length */
   7878     alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   7879 
   7880     /* Calculate the size of remote_mep_id_length */
   7881     alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7882 
   7883     /* Calculate the size of remote_mep_id */
   7884     alloc_size += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH * bfd_info->endpoint_count);
   7885 
   7886     /* Calculate the size of bfd_detection_time */
   7887     alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   7888 
   7889     if(bfd_info->wb_current_version >= BCM_BFD_WB_VERSION_1_4) {
   7890         /* Calculate the size of flags */
   7891         alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   7892     }
   7893 
   7894     if(bfd_info->wb_next_version >= BCM_BFD_WB_VERSION_1_5) {
   7895        /* Calculate the size of gal label */
   7896        alloc_size += (sizeof(bcm_mpls_label_t) * bfd_info->endpoint_count);
   7897     }
   7898 
   7899     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_BFD, 0);
   7900     BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1,
   7901                         alloc_size, &bfd_scache, BCM_BFD_WB_DEFAULT_VERSION, NULL));
   7902     return BCM_E_NONE;
   7903 }
   7904 
   7905 /*
   7906  * Function:
   7907  *      bcmi_xgs5_bfd_sync
   7908  * Purpose:
   7909  *       
   7910  * Parameters:
   7911  *      unit - (IN) Unit number.
   7912  * result =s:
   7913  *      BCM_E_XXX
   7914  * Notes:
   7915  */
   7916 int
   7917 bcmi_xgs5_bfd_sync(int unit)
   7918 {
   7919     int         rv = BCM_E_NONE;
   7920     int         alloc_size = 0;
   7921     int         stable_size;
   7922     bfd_info_t  *bfd_info;
   7923     uint8       *bfd_scache;
   7924     int         idx = 0;
   7925     int         ep_not_use = 0;
   7926     soc_scache_handle_t scache_handle;
   7927     bfd_endpoint_config_t *endpoint_config = NULL;
   7928 
   7929     BFD_INIT_CHECK(unit); 
   7930     /* Get The BFD module storage size. */
   7931     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   7932 
   7933     /* In case  WARM BOOT level 2 store is not configured return from here. */
   7934     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) {
   7935     /* Get The BFD module storage size. */
   7936         return BCM_E_NONE;
   7937     }
   7938     do {
   7939         /* BFD info structure for the given unit. */
   7940         bfd_info = BFD_INFO(unit);
   7941 
   7942         /* Calculate the size to store BFD num session count */
   7943         alloc_size += sizeof(int);
   7944 
   7945         /* Calculate the size to store BFD  end point bit usage  usage */
   7946         alloc_size += SHR_BITALLOCSIZE(bfd_info->endpoint_count);
   7947 
   7948         /* Calculate the size of Packet vlan id */
   7949         alloc_size += (sizeof(bcm_vlan_t) * bfd_info->endpoint_count);
   7950 
   7951         /* Calculate the size of tunnel type */
   7952         alloc_size += (sizeof(bcm_bfd_tunnel_type_t) * bfd_info->endpoint_count);
   7953 
   7954         /* Calculate the size of gport */
   7955         alloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   7956 
   7957         /* Calculate the size of tx gport */
   7958         alloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   7959 
   7960         /* Calculate the size of remote gport */
   7961         alloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   7962 
   7963         /* Calculate the size of bfd period */
   7964         alloc_size += (sizeof(int) * bfd_info->endpoint_count);
   7965 
   7966         /* Calculate the size of vpn */
   7967         alloc_size += (sizeof(bcm_vpn_t) * bfd_info->endpoint_count);
   7968 
   7969         /* Calculate the size of vlan_pri */
   7970         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7971 
   7972         /* Calculate the size of inner_vlan_pri */
   7973         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7974 
   7975         /* Calculate the size of vrf_id */
   7976         alloc_size += (sizeof(bcm_vrf_t) * bfd_info->endpoint_count);
   7977 
   7978         /* Calculate the size of dst_ip_addr */
   7979         alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   7980 
   7981         /* Calculate the size of dst_ip6_addr */
   7982         alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   7983 
   7984         /* Calculate the size of src_ip_addr */
   7985         alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   7986 
   7987         /* Calculate the size of src_ip6_addr */
   7988         alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   7989 
   7990         /* Calculate the size of ip_tos */
   7991         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7992 
   7993         /* Calculate the size of ip_ttl */
   7994         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   7995 
   7996         /* Calculate the size of inner_dst_ip_addr */
   7997         alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   7998 
   7999         /* Calculate the size of inner_dst_ip6_addr */
   8000         alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   8001 
   8002         /* Calculate the size of inner_src_ip_addr */
   8003         alloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   8004 
   8005         /* Calculate the size of inner_src_ip6_addr */
   8006         alloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   8007 
   8008         /* Calculate the size of inner_ip_tos */
   8009         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8010 
   8011         /* Calculate the size of inner_ip_ttl */
   8012         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8013 
   8014         /* Calculate the size of udp_src_port */
   8015         alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8016 
   8017         /* Calculate the size of mpls label */
   8018         alloc_size += (sizeof(bcm_mpls_label_t) * bfd_info->endpoint_count);
   8019 
   8020         if(bfd_info->wb_next_version <= BCM_BFD_WB_VERSION_1_2) {
   8021             alloc_size += (VERSION_1_2_EGRESS_LABEL_SIZE * bfd_info->endpoint_count);
   8022         } else {
   8023             /* Calculate the size of egress_label.exp */
   8024             alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8025 
   8026             /* Calculate the size of egress_label.ttl */
   8027             alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8028         }
   8029 
   8030         /* Calculate the size of egress interface */
   8031         alloc_size += (sizeof(bcm_if_t) * bfd_info->endpoint_count);
   8032 
   8033         /* Calculate the size of mep_id_length */
   8034         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8035 
   8036         /* Calculate the size of mep_id */
   8037         alloc_size += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH * bfd_info->endpoint_count);
   8038 
   8039         /* Calculate the size of int_pri */
   8040         alloc_size += (sizeof(bcm_cos_t) * bfd_info->endpoint_count);
   8041 
   8042         /* Calculate the size of cpu_qid */
   8043         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8044 
   8045         /* Calculate the size of auth type */
   8046         alloc_size += (sizeof(bcm_bfd_auth_type_t) * bfd_info->endpoint_count);
   8047 
   8048         /* Calculate the size of auth_index */
   8049         alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8050 
   8051         /* Calculate the size of sampling_ratio */
   8052         alloc_size += (sizeof(int) * bfd_info->endpoint_count);
   8053 
   8054         /* Calculate the size of loc_clear_threshold */
   8055         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8056 
   8057         /* Calculate the size of ip_subnet_length */
   8058         alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8059 
   8060         /* Calculate the size of remote_mep_id_length */
   8061         alloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8062 
   8063         /* Calculate the size of remote_mep_id */
   8064         alloc_size += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH * bfd_info->endpoint_count);
   8065 
   8066         /* Calculate the size of bfd_detection_time */
   8067         alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8068 
   8069          if(bfd_info->wb_next_version >= BCM_BFD_WB_VERSION_1_4) {
   8070             /* Calculate the size of flags */
   8071             alloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8072         }
   8073 
   8074         if(bfd_info->wb_next_version >= BCM_BFD_WB_VERSION_1_5) {
   8075            /* Calculate the size of gal label */
   8076            alloc_size += (sizeof(bcm_mpls_label_t) * bfd_info->endpoint_count);
   8077         }
   8078 
   8079         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_BFD, 0);
   8080 
   8081         rv = _bcm_esw_scache_ptr_get(unit,
   8082                                     scache_handle,
   8083                                      0,
   8084                                     alloc_size,
   8085                                     &bfd_scache,
   8086                                     BCM_BFD_WB_DEFAULT_VERSION,
   8087                                     NULL
   8088                                     );
   8089         if ((!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) ||
   8090             (bfd_info->wb_current_version != bfd_info->wb_next_version)) {
   8091             rv = _bcm_esw_scache_ptr_get(unit,
   8092                                         scache_handle,
   8093                                         1,
   8094                                         alloc_size,
   8095                                          &bfd_scache,
   8096                                         BCM_BFD_WB_DEFAULT_VERSION,
   8097                                          NULL
   8098                                         );
   8099             if (BCM_FAILURE(rv) || (NULL == bfd_scache)) {
   8100                 LOG_CLI((BSL_META("\nBFD Scache alloc failed (rv= %d)\n"), rv));
   8101                 break;  
   8102             }
   8103         } else if (BCM_FAILURE(rv)) {
   8104             LOG_CLI((BSL_META("\nBFD Scache ptr get failed (rv= %d)\n"), rv));
   8105             break;
   8106         }
   8107         /* Store the  BFD num sessions  */
   8108         sal_memcpy(bfd_scache, &bfd_info->endpoint_count, sizeof(int));
   8109         bfd_scache += sizeof(int);
   8110 
   8111         /* Store the BFD  end point bit usage  usage */
   8112         for (idx = 0; idx < _SHR_BITDCLSIZE (bfd_info->endpoint_count); idx++) {
   8113             sal_memcpy(bfd_scache, &bfd_info->endpoints_in_use[idx], sizeof(SHR_BITDCL));
   8114             bfd_scache += sizeof(SHR_BITDCL);
   8115         }
   8116 
   8117         /* Store a each endpoint info */
   8118         for (idx = 0; idx < bfd_info->endpoint_count; idx++) {
   8119              if (!SHR_BITGET(bfd_info->endpoints_in_use, idx)) {
   8120                 continue;
   8121              }
   8122 
   8123              endpoint_config = BFD_ENDPOINT_CONFIG(unit, idx);
   8124              if (endpoint_config->info.flags & BCM_BFD_ENDPOINT_USE_PKT_VLAN_ID) {
   8125                  sal_memcpy(bfd_scache, &endpoint_config->info.pkt_vlan_id, sizeof(bcm_vlan_t));
   8126              } else {
   8127                  sal_memset(bfd_scache, 0, sizeof(bcm_vlan_t));
   8128              }
   8129              bfd_scache += sizeof(bcm_vlan_t);
   8130 
   8131              sal_memcpy(bfd_scache, &endpoint_config->info.type, sizeof(bcm_bfd_tunnel_type_t));
   8132              bfd_scache += sizeof(bcm_bfd_tunnel_type_t);
   8133 
   8134              sal_memcpy(bfd_scache, &endpoint_config->info.gport, sizeof(bcm_gport_t));
   8135              bfd_scache += sizeof(bcm_gport_t);
   8136 
   8137              sal_memcpy(bfd_scache, &endpoint_config->info.tx_gport, sizeof(bcm_gport_t));
   8138              bfd_scache += sizeof(bcm_gport_t);
   8139 
   8140              sal_memcpy(bfd_scache, &endpoint_config->info.remote_gport, sizeof(bcm_gport_t));
   8141              bfd_scache += sizeof(bcm_gport_t);
   8142 
   8143              sal_memcpy(bfd_scache, &endpoint_config->info.bfd_period, sizeof(int));
   8144              bfd_scache += sizeof(int);
   8145 
   8146              sal_memcpy(bfd_scache, &endpoint_config->info.vpn, sizeof(bcm_vpn_t));
   8147              bfd_scache += sizeof(bcm_vpn_t);
   8148 
   8149              sal_memcpy(bfd_scache, &endpoint_config->info.vlan_pri, sizeof(uint8));
   8150              bfd_scache += sizeof(uint8);
   8151 
   8152              sal_memcpy(bfd_scache, &endpoint_config->info.inner_vlan_pri, sizeof(uint8));
   8153              bfd_scache += sizeof(uint8);
   8154 
   8155              sal_memcpy(bfd_scache, &endpoint_config->info.vrf_id, sizeof(bcm_vrf_t));
   8156              bfd_scache += sizeof(bcm_vrf_t);
   8157 
   8158              sal_memcpy(bfd_scache, &endpoint_config->info.dst_ip_addr, sizeof(bcm_ip_t));
   8159              bfd_scache += sizeof(bcm_ip_t);
   8160 
   8161              sal_memcpy(bfd_scache, &endpoint_config->info.dst_ip6_addr, sizeof(bcm_ip6_t));
   8162              bfd_scache += sizeof(bcm_ip6_t);
   8163 
   8164              sal_memcpy(bfd_scache, &endpoint_config->info.src_ip_addr, sizeof(bcm_ip_t));
   8165              bfd_scache += sizeof(bcm_ip_t);
   8166 
   8167              sal_memcpy(bfd_scache, &endpoint_config->info.src_ip6_addr, sizeof(bcm_ip6_t));
   8168              bfd_scache += sizeof(bcm_ip6_t);
   8169 
   8170              sal_memcpy(bfd_scache, &endpoint_config->info.ip_tos, sizeof(uint8));
   8171              bfd_scache += sizeof(uint8);
   8172 
   8173              sal_memcpy(bfd_scache, &endpoint_config->info.ip_ttl, sizeof(uint8));
   8174              bfd_scache += sizeof(uint8);
   8175 
   8176              sal_memcpy(bfd_scache, &endpoint_config->info.inner_dst_ip_addr, sizeof(bcm_ip_t));
   8177              bfd_scache += sizeof(bcm_ip_t);
   8178 
   8179              sal_memcpy(bfd_scache, &endpoint_config->info.inner_dst_ip6_addr, sizeof(bcm_ip6_t));
   8180              bfd_scache += sizeof(bcm_ip6_t);
   8181 
   8182              sal_memcpy(bfd_scache, &endpoint_config->info.inner_src_ip_addr, sizeof(bcm_ip_t));
   8183              bfd_scache += sizeof(bcm_ip_t);
   8184 
   8185              sal_memcpy(bfd_scache, &endpoint_config->info.inner_src_ip6_addr, sizeof(bcm_ip6_t));
   8186              bfd_scache += sizeof(bcm_ip6_t);
   8187 
   8188              sal_memcpy(bfd_scache, &endpoint_config->info.inner_ip_tos, sizeof(uint8));
   8189              bfd_scache += sizeof(uint8);
   8190 
   8191              sal_memcpy(bfd_scache, &endpoint_config->info.inner_ip_ttl, sizeof(uint8));
   8192              bfd_scache += sizeof(uint8);
   8193 
   8194              sal_memcpy(bfd_scache, &endpoint_config->info.udp_src_port, sizeof(uint32));
   8195              bfd_scache += sizeof(uint32);
   8196 
   8197              sal_memcpy(bfd_scache, &endpoint_config->info.label, sizeof(bcm_mpls_label_t));
   8198              bfd_scache += sizeof(bcm_mpls_label_t);
   8199 
   8200              if(bfd_info->wb_next_version <= BCM_BFD_WB_VERSION_1_2) {
   8201                 sal_memcpy(bfd_scache, &endpoint_config->info.egress_label, VERSION_1_2_EGRESS_LABEL_SIZE);
   8202                 bfd_scache += VERSION_1_2_EGRESS_LABEL_SIZE;
   8203              } else {
   8204                 sal_memcpy(bfd_scache, &endpoint_config->info.egress_label.exp, sizeof(uint8));
   8205                 bfd_scache += sizeof(uint8);
   8206 
   8207                 sal_memcpy(bfd_scache, &endpoint_config->info.egress_label.ttl, sizeof(uint8));
   8208                 bfd_scache += sizeof(uint8);
   8209              }
   8210 
   8211              sal_memcpy(bfd_scache, &endpoint_config->info.egress_if, sizeof(bcm_if_t));
   8212              bfd_scache += sizeof(bcm_if_t);
   8213 
   8214              sal_memcpy(bfd_scache, &endpoint_config->info.mep_id_length, sizeof(uint8));
   8215              bfd_scache += sizeof(uint8);
   8216 
   8217              sal_memcpy(bfd_scache, &endpoint_config->info.mep_id, endpoint_config->info.mep_id_length);
   8218              bfd_scache += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH);
   8219 
   8220              sal_memcpy(bfd_scache, &endpoint_config->info.int_pri, sizeof(bcm_cos_t));
   8221              bfd_scache += sizeof(bcm_cos_t);
   8222 
   8223              sal_memcpy(bfd_scache, &endpoint_config->info.cpu_qid, sizeof(uint8));
   8224              bfd_scache += sizeof(uint8);
   8225 
   8226              sal_memcpy(bfd_scache, &endpoint_config->info.auth, sizeof(bcm_bfd_auth_type_t));
   8227              bfd_scache += sizeof(bcm_bfd_auth_type_t);
   8228 
   8229              sal_memcpy(bfd_scache, &endpoint_config->info.auth_index, sizeof(uint32));
   8230              bfd_scache += sizeof(uint32);
   8231 
   8232              sal_memcpy(bfd_scache, &endpoint_config->info.sampling_ratio, sizeof(int));
   8233              bfd_scache += sizeof(int);
   8234 
   8235              sal_memcpy(bfd_scache, &endpoint_config->info.loc_clear_threshold, sizeof(uint8));
   8236              bfd_scache += sizeof(uint8);
   8237 
   8238              sal_memcpy(bfd_scache, &endpoint_config->info.ip_subnet_length, sizeof(uint32));
   8239              bfd_scache += sizeof(uint32);
   8240 
   8241              sal_memcpy(bfd_scache, &endpoint_config->info.remote_mep_id_length, sizeof(uint8));
   8242              bfd_scache += sizeof(uint8);
   8243 
   8244              sal_memcpy(bfd_scache, &endpoint_config->info.remote_mep_id, endpoint_config->info.remote_mep_id_length);
   8245              bfd_scache += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH);
   8246 
   8247              sal_memcpy(bfd_scache, &endpoint_config->info.bfd_detection_time, sizeof(uint32));
   8248              bfd_scache += sizeof(uint32);
   8249 
   8250              if(bfd_info->wb_next_version >= BCM_BFD_WB_VERSION_1_4) {
   8251                 sal_memcpy(bfd_scache, &endpoint_config->info.flags, sizeof(uint32));
   8252                 bfd_scache += sizeof(uint32);
   8253              }
   8254 
   8255              if (bfd_info->wb_next_version >= BCM_BFD_WB_VERSION_1_5) {
   8256                  sal_memcpy(bfd_scache, &endpoint_config->info.gal_label, sizeof(bcm_mpls_label_t));
   8257                  bfd_scache += sizeof(bcm_mpls_label_t);
   8258              }
   8259 
   8260              ep_not_use++;
   8261         }
   8262         for (idx = ep_not_use; idx < bfd_info->endpoint_count; idx++) {
   8263              bfd_scache += sizeof(bcm_vlan_t);
   8264              bfd_scache += sizeof(bcm_bfd_tunnel_type_t);
   8265              bfd_scache += sizeof(bcm_gport_t);
   8266              bfd_scache += sizeof(bcm_gport_t);
   8267              bfd_scache += sizeof(bcm_gport_t);
   8268              bfd_scache += sizeof(int);
   8269              bfd_scache += sizeof(bcm_vpn_t);
   8270              bfd_scache += sizeof(uint8);
   8271              bfd_scache += sizeof(uint8);
   8272              bfd_scache += sizeof(bcm_vrf_t);
   8273              bfd_scache += sizeof(bcm_ip_t);
   8274              bfd_scache += sizeof(bcm_ip6_t);
   8275              bfd_scache += sizeof(bcm_ip_t);
   8276              bfd_scache += sizeof(bcm_ip6_t);
   8277              bfd_scache += sizeof(uint8);
   8278              bfd_scache += sizeof(uint8);
   8279              bfd_scache += sizeof(bcm_ip_t);
   8280              bfd_scache += sizeof(bcm_ip6_t);
   8281              bfd_scache += sizeof(bcm_ip_t);
   8282              bfd_scache += sizeof(bcm_ip6_t);
   8283              bfd_scache += sizeof(uint8);
   8284              bfd_scache += sizeof(uint8);
   8285              bfd_scache += sizeof(uint32);
   8286              bfd_scache += sizeof(bcm_mpls_label_t);
   8287              if(bfd_info->wb_next_version <= BCM_BFD_WB_VERSION_1_2) {
   8288                 bfd_scache += VERSION_1_2_EGRESS_LABEL_SIZE;
   8289              } else {
   8290                 bfd_scache += sizeof(uint8); /*egress_label.exp */
   8291                 bfd_scache += sizeof(uint8); /*egress_label.ttl */
   8292              }
   8293              bfd_scache += sizeof(bcm_if_t);
   8294              bfd_scache += sizeof(uint8);
   8295              bfd_scache += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH);
   8296              bfd_scache += sizeof(bcm_cos_t);
   8297              bfd_scache += sizeof(uint8);
   8298              bfd_scache += sizeof(bcm_bfd_auth_type_t);
   8299              bfd_scache += sizeof(uint32);
   8300              bfd_scache += sizeof(int);
   8301              bfd_scache += sizeof(uint8);
   8302              bfd_scache += sizeof(uint32);
   8303              bfd_scache += sizeof(uint8);
   8304              bfd_scache += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH);
   8305              bfd_scache += sizeof(uint32);
   8306              if(bfd_info->wb_next_version >= BCM_BFD_WB_VERSION_1_4) {
   8307                 bfd_scache += sizeof(uint32); /* flags */
   8308              }
   8309              if(bfd_info->wb_next_version >= BCM_BFD_WB_VERSION_1_5) {
   8310                 bfd_scache += sizeof(bcm_mpls_label_t); /* gal label */
   8311              }
   8312         }
   8313     }while(0);
   8314 
   8315     return rv;
   8316 }
   8317 
   8318 /*
   8319  * Function:
   8320  *     bcmi_xgs5_bfd_recover
   8321  * Purpose:
   8322  *     Recover BFD group configuration.
   8323  * Parameters:
   8324  *     unit        - (IN) BCM device number
   8325  *     stable_size - (IN) BFD module Level2 storage size.
   8326  *     oam_scache  - (IN) Pointer to BFD scache address pointer.
   8327  *     recovered_ver - (IN) Warmboot recovery version.
   8328  * Returns:
   8329  *     BCM_E_XXX
   8330  */
   8331 STATIC int
   8332 bcmi_xgs5_bfd_recover(int unit, int stable_size, uint8 **bfd_scache, uint16 recovered_ver)
   8333 {
   8334     int         rv = BCM_E_UNAVAIL;
   8335     bfd_info_t  *bfd_info;
   8336     bfd_endpoint_config_t *endpoint_config;
   8337     int         idx = 0;
   8338     bcm_vlan_t  pkt_vlan_id = 0;
   8339     int         is_local;
   8340     bcm_l3_egress_t l3_egress;
   8341     bfd_sdk_msg_ctrl_sess_set_t msg_sess;
   8342     bcm_trunk_t trunk_id = BCM_TRUNK_INVALID;
   8343     int         local_id = 0;
   8344     uint8       is_trunk_bfd = 0;
   8345 
   8346     /* BFD info structure for the given unit. */
   8347     bfd_info = BFD_INFO(unit);
   8348 
   8349     /* Recover the  size to store BFD  end point config */
   8350     for (idx = 0; idx < bfd_info->endpoint_count; idx++) {
   8351          if (!SHR_BITGET(bfd_info->endpoints_in_use, idx)) {
   8352                 continue;
   8353          }
   8354 
   8355         /* Recover the packet vlan id */
   8356         if (recovered_ver >= BCM_BFD_WB_VERSION_1_1) {
   8357             sal_memcpy(&pkt_vlan_id, *bfd_scache, sizeof(bcm_vlan_t));
   8358             *bfd_scache += sizeof(bcm_vlan_t);
   8359         }
   8360 
   8361         endpoint_config = BFD_ENDPOINT_CONFIG(unit, idx);
   8362 
   8363         if (endpoint_config) {
   8364             bcm_bfd_endpoint_info_t_init(&endpoint_config->info);
   8365             if (pkt_vlan_id) {
   8366                 endpoint_config->info.pkt_vlan_id = pkt_vlan_id;
   8367             }
   8368             endpoint_config->info.id = idx;
   8369             endpoint_config->endpoint_index = idx;
   8370 
   8371             /* Recover a each endpoint info */
   8372             if (recovered_ver >= BCM_BFD_WB_VERSION_1_2) {
   8373                 sal_memcpy(&endpoint_config->info.type, *bfd_scache, sizeof(bcm_bfd_tunnel_type_t));
   8374                 *bfd_scache += sizeof(bcm_bfd_tunnel_type_t);
   8375 
   8376                 sal_memcpy(&endpoint_config->info.gport, *bfd_scache, sizeof(bcm_gport_t));
   8377                 *bfd_scache += sizeof(bcm_gport_t);
   8378 
   8379                 sal_memcpy(&endpoint_config->info.tx_gport, *bfd_scache, sizeof(bcm_gport_t));
   8380                 *bfd_scache += sizeof(bcm_gport_t);
   8381 
   8382                 sal_memcpy(&endpoint_config->info.remote_gport, *bfd_scache, sizeof(bcm_gport_t));
   8383                 *bfd_scache += sizeof(bcm_gport_t);
   8384 
   8385                 sal_memcpy(&endpoint_config->info.bfd_period, *bfd_scache, sizeof(int));
   8386                 *bfd_scache += sizeof(int);
   8387 
   8388                 sal_memcpy(&endpoint_config->info.vpn, *bfd_scache, sizeof(bcm_vpn_t));
   8389                 *bfd_scache += sizeof(bcm_vpn_t);
   8390 
   8391                 sal_memcpy(&endpoint_config->info.vlan_pri, *bfd_scache, sizeof(uint8));
   8392                 *bfd_scache += sizeof(uint8);
   8393 
   8394                 sal_memcpy(&endpoint_config->info.inner_vlan_pri, *bfd_scache, sizeof(uint8));
   8395                 *bfd_scache += sizeof(uint8);
   8396 
   8397                 sal_memcpy(&endpoint_config->info.vrf_id, *bfd_scache, sizeof(bcm_vrf_t));
   8398                 *bfd_scache += sizeof(bcm_vrf_t);
   8399 
   8400                 sal_memcpy(&endpoint_config->info.dst_ip_addr, *bfd_scache, sizeof(bcm_ip_t));
   8401                 *bfd_scache += sizeof(bcm_ip_t);
   8402 
   8403                 sal_memcpy(&endpoint_config->info.dst_ip6_addr, *bfd_scache, sizeof(bcm_ip6_t));
   8404                 *bfd_scache += sizeof(bcm_ip6_t);
   8405 
   8406                 sal_memcpy(&endpoint_config->info.src_ip_addr, *bfd_scache, sizeof(bcm_ip_t));
   8407                 *bfd_scache += sizeof(bcm_ip_t);
   8408 
   8409                 sal_memcpy(&endpoint_config->info.src_ip6_addr, *bfd_scache, sizeof(bcm_ip6_t));
   8410                 *bfd_scache += sizeof(bcm_ip6_t);
   8411 
   8412                 sal_memcpy(&endpoint_config->info.ip_tos, *bfd_scache, sizeof(uint8));
   8413                 *bfd_scache += sizeof(uint8);
   8414 
   8415                 sal_memcpy(&endpoint_config->info.ip_ttl, *bfd_scache, sizeof(uint8));
   8416                 *bfd_scache += sizeof(uint8);
   8417 
   8418                 sal_memcpy(&endpoint_config->info.inner_dst_ip_addr, *bfd_scache, sizeof(bcm_ip_t));
   8419                 *bfd_scache += sizeof(bcm_ip_t);
   8420 
   8421                 sal_memcpy(&endpoint_config->info.inner_dst_ip6_addr, *bfd_scache, sizeof(bcm_ip6_t));
   8422                 *bfd_scache += sizeof(bcm_ip6_t);
   8423 
   8424                 sal_memcpy(&endpoint_config->info.inner_src_ip_addr, *bfd_scache, sizeof(bcm_ip_t));
   8425                 *bfd_scache += sizeof(bcm_ip_t);
   8426 
   8427                 sal_memcpy(&endpoint_config->info.inner_src_ip6_addr, *bfd_scache, sizeof(bcm_ip6_t));
   8428                 *bfd_scache += sizeof(bcm_ip6_t);
   8429 
   8430                 sal_memcpy(&endpoint_config->info.inner_ip_tos, *bfd_scache, sizeof(uint8));
   8431                 *bfd_scache += sizeof(uint8);
   8432 
   8433                 sal_memcpy(&endpoint_config->info.inner_ip_ttl, *bfd_scache, sizeof(uint8));
   8434                 *bfd_scache += sizeof(uint8);
   8435 
   8436                 sal_memcpy(&endpoint_config->info.udp_src_port, *bfd_scache, sizeof(uint32));
   8437                 *bfd_scache += sizeof(uint32);
   8438 
   8439                 sal_memcpy(&endpoint_config->info.label, *bfd_scache, sizeof(bcm_mpls_label_t));
   8440                 *bfd_scache += sizeof(bcm_mpls_label_t);
   8441 
   8442                 if (recovered_ver == BCM_BFD_WB_VERSION_1_2) {
   8443                     /* Special case. Version 1.2 stored egress_label_t as a full structure.
   8444                      * and a new field was added in the egress_label_t later. So copying
   8445                      * for the size of egress_label_t structure will cause 
   8446                      * problem in recovery. So recover for older size.  The recovered value
   8447                      * will align itself to the new structure, since the new fields are 
   8448                      * added only at the last and we really dont need them for BFD purposes.
   8449                      */
   8450                     sal_memcpy(&endpoint_config->info.egress_label, *bfd_scache, VERSION_1_2_EGRESS_LABEL_SIZE);
   8451                     *bfd_scache += VERSION_1_2_EGRESS_LABEL_SIZE;
   8452                 } else {
   8453                     sal_memcpy(&endpoint_config->info.egress_label.exp, *bfd_scache, sizeof(uint8));
   8454                     *bfd_scache += sizeof(uint8);
   8455                     sal_memcpy(&endpoint_config->info.egress_label.ttl, *bfd_scache, sizeof(uint8));
   8456                     *bfd_scache += sizeof(uint8);
   8457                 }
   8458 
   8459                 sal_memcpy(&endpoint_config->info.egress_if, *bfd_scache, sizeof(bcm_if_t));
   8460                 *bfd_scache += sizeof(bcm_if_t);
   8461 
   8462                 sal_memcpy(&endpoint_config->info.mep_id_length, *bfd_scache, sizeof(uint8));
   8463                 *bfd_scache += sizeof(uint8);
   8464 
   8465                 sal_memcpy(&endpoint_config->info.mep_id, *bfd_scache, endpoint_config->info.mep_id_length);
   8466                 *bfd_scache += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH);
   8467 
   8468                 sal_memcpy(&endpoint_config->info.int_pri, *bfd_scache, sizeof(bcm_cos_t));
   8469                 *bfd_scache += sizeof(bcm_cos_t);
   8470 
   8471                 sal_memcpy(&endpoint_config->info.cpu_qid, *bfd_scache, sizeof(uint8));
   8472                 *bfd_scache += sizeof(uint8);
   8473 
   8474                 sal_memcpy(&endpoint_config->info.auth, *bfd_scache, sizeof(bcm_bfd_auth_type_t));
   8475                 *bfd_scache += sizeof(bcm_bfd_auth_type_t);
   8476 
   8477                 sal_memcpy(&endpoint_config->info.auth_index, *bfd_scache, sizeof(uint32));
   8478                 *bfd_scache += sizeof(uint32);
   8479 
   8480                 sal_memcpy(&endpoint_config->info.sampling_ratio, *bfd_scache, sizeof(int));
   8481                 *bfd_scache += sizeof(int);
   8482 
   8483                 sal_memcpy(&endpoint_config->info.loc_clear_threshold, *bfd_scache, sizeof(uint8));
   8484                 *bfd_scache += sizeof(uint8);
   8485 
   8486                 sal_memcpy(&endpoint_config->info.ip_subnet_length, *bfd_scache, sizeof(uint32));
   8487                 *bfd_scache += sizeof(uint32);
   8488 
   8489                 sal_memcpy(&endpoint_config->info.remote_mep_id_length, *bfd_scache, sizeof(uint8));
   8490                 *bfd_scache += sizeof(uint8);
   8491 
   8492                 sal_memcpy(&endpoint_config->info.remote_mep_id, *bfd_scache, endpoint_config->info.remote_mep_id_length);
   8493                 *bfd_scache += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH);
   8494 
   8495                 sal_memcpy(&endpoint_config->info.bfd_detection_time, *bfd_scache, sizeof(uint32));
   8496                 *bfd_scache += sizeof(uint32);
   8497             }
   8498 
   8499             /* recover flags */
   8500             if (recovered_ver == BCM_BFD_WB_VERSION_1_2) {
   8501                 endpoint_config->info.flags |= BCM_BFD_ENDPOINT_WITH_ID;
   8502             } else if (recovered_ver >= BCM_BFD_WB_VERSION_1_4) {
   8503                 sal_memcpy(&endpoint_config->info.flags, *bfd_scache, sizeof(uint32));
   8504                 *bfd_scache += sizeof(uint32);
   8505             }
   8506 
   8507             if (recovered_ver >= BCM_BFD_WB_VERSION_1_5) {
   8508                 sal_memcpy(&endpoint_config->info.gal_label, *bfd_scache, sizeof(bcm_mpls_label_t));
   8509                 *bfd_scache += sizeof(bcm_mpls_label_t);
   8510             }
   8511 
   8512             rv = bcmi_xgs5_bfd_endpoint_get(unit, idx, &endpoint_config->info);
   8513             if (BCM_FAILURE(rv)) {
   8514                 LOG_CLI((BSL_META("\nBFD endpoint(%d) get failed (rv= %d)\n"), 
   8515                             idx, rv));
   8516             }
   8517 
   8518             /* Recover endpoint config params */
   8519             sal_memset(&msg_sess, 0, sizeof(msg_sess));
   8520             sal_memset(&l3_egress, 0, sizeof(l3_egress));
   8521             if (BCM_GPORT_INVALID != endpoint_config->info.gport) {
   8522                 BCM_IF_ERROR_RETURN
   8523                 (bcmi_xgs5_bfd_endpoint_gport_resolve(unit, 0, &endpoint_config->info, &endpoint_config->modid,
   8524                  &endpoint_config->port, &trunk_id, &local_id, &is_trunk_bfd, &endpoint_config->is_micro_bfd));
   8525             } else if (BCM_SUCCESS
   8526                        (bcm_esw_l3_egress_get(unit, endpoint_config->info.egress_if,
   8527                                               &l3_egress))) {
   8528                 endpoint_config->modid = l3_egress.module;
   8529                 endpoint_config->port = l3_egress.port;
   8530             } else {
   8531                 return BCM_E_PARAM;
   8532             }
   8533 
   8534             if (BCM_GPORT_INVALID == endpoint_config->info.tx_gport) {
   8535                 /* Get local port used for TX BFD packet */
   8536                 BCM_IF_ERROR_RETURN
   8537                          (_bcm_esw_modid_is_local(unit, endpoint_config->modid, &is_local));
   8538                 if (is_local) {    /* Ethernet port */
   8539                     endpoint_config->tx_port = endpoint_config->port;
   8540                 } else {           /* HG port */
   8541                     BCM_IF_ERROR_RETURN
   8542                           (bcm_esw_stk_modport_get(unit, endpoint_config->modid, &endpoint_config->tx_port));
   8543                 }
   8544                 /* Resolve TX module and port */
   8545             } else {
   8546                 BCM_IF_ERROR_RETURN
   8547                 (bcmi_xgs5_bfd_endpoint_gport_resolve(unit, 1, &endpoint_config->info, &endpoint_config->modid,
   8548                  &endpoint_config->port, &trunk_id,  &local_id, &is_trunk_bfd, &endpoint_config->is_micro_bfd));
   8549                 /* Get local port used for TX BFD packet */
   8550                 BCM_IF_ERROR_RETURN
   8551                 (_bcm_esw_modid_is_local(unit,  endpoint_config->modid, &is_local));
   8552                 if (is_local) {    /* Ethernet port */
   8553                     endpoint_config->tx_port = endpoint_config->port;
   8554                 } else {           /* HG port */
   8555                     BCM_IF_ERROR_RETURN
   8556                     (bcm_esw_stk_modport_get(unit, endpoint_config->modid, &endpoint_config->tx_port));
   8557                 }
   8558             }
   8559 
   8560             if ((endpoint_config->info.type == bcmBFDTunnelTypeMplsTpCc) ||
   8561                 (endpoint_config->info.type == bcmBFDTunnelTypeMplsTpCcCv)) {
   8562                 rv = bcmi_xgs5_bfd_mpls_is_l3_vpn_get(unit, endpoint_config);
   8563                 if (BCM_FAILURE(rv)) {
   8564                     LOG_CLI((BSL_META("\nBFD is l3 vpn (%d) get failed (rv= %d)\n"),
   8565                              idx, rv));
   8566                     return rv;
   8567                 }
   8568             }
   8569 
   8570             rv = bcmi_xgs5_bfd_encap_create(unit, endpoint_config,
   8571                                         msg_sess.encap_data);
   8572             if (BCM_FAILURE(rv)) {
   8573                 LOG_CLI((BSL_META("\nBFD encap param (%d) get failed (rv= %d)\n"),
   8574                              idx, rv));
   8575                 return rv;
   8576             }
   8577 
   8578             if (endpoint_config->info.flags & BCM_BFD_ECHO) {
   8579                 endpoint_config->local_echo = 1;
   8580             }
   8581         }
   8582     }
   8583 
   8584     /* Recover the simple Passwords used for endpoints  */
   8585     for (idx = 0; idx < bfd_info->num_auth_sp_keys; idx++) {
   8586         rv = bcmi_xgs5_bfd_auth_simple_password_get(unit, idx, 
   8587                                                     &bfd_info->auth_sp[idx]); 
   8588         if (BCM_FAILURE(rv)) {
   8589             LOG_CLI((BSL_META("\n bfd sp auth(key=%d) get failed (rv=%d)\n"),
   8590                     idx, rv));
   8591         }
   8592     }
   8593 
   8594     /* Recover the sha1 auth keyd for endpoints */
   8595     for (idx = 0; idx < bfd_info->num_auth_sha1_keys; idx++) {
   8596         rv = bcmi_xgs5_bfd_auth_sha1_get(unit, idx, 
   8597                                          &bfd_info->auth_sha1[idx]); 
   8598         if (BCM_FAILURE(rv)) {
   8599             LOG_CLI((BSL_META("\n bfd sha1 (key=%d) get failed (rv=%d)\n"),
   8600                     idx, rv));
   8601         }
   8602     }
   8603     return rv;
   8604 }
   8605 
   8606 /*
   8607  * Function:
   8608  *     bcmi_xgs5_bfd_reinit
   8609  * Purpose:
   8610  *     Reconstruct BFD module software state.
   8611  * Parameters:
   8612  *     unit - (IN) BCM device number
   8613  * Retruns:
   8614  *     BCM_E_XXX
   8615  */
   8616 STATIC int
   8617 bcmi_xgs5_bfd_reinit(int unit)
   8618 {
   8619     int         rv = BCM_E_NONE;
   8620     int         stable_size;
   8621     bfd_info_t  *bfd_info;
   8622     uint8       *bfd_scache;
   8623     int         idx = 0;
   8624     soc_scache_handle_t scache_handle;
   8625     uint16      recovered_ver = 0;
   8626     int         realloc_size = 0;
   8627 
   8628     /* BFD info structure for the given unit. */
   8629      bfd_info = BFD_INFO(unit);
   8630 
   8631     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   8632 
   8633     /* In case  WARM BOOT level 2 store is not configured return from here. */
   8634     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) {
   8635 
   8636         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_BFD, 0);
   8637         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0,
   8638                                      &bfd_scache, BCM_BFD_WB_DEFAULT_VERSION,
   8639                                      &recovered_ver);
   8640         if (BCM_FAILURE(rv)) {
   8641             LOG_CLI((BSL_META("\nBFD bfd reinit failed (rv= %d)\n"), rv));
   8642             return rv;
   8643         }
   8644 
   8645         /* Recover BFD endpoint count  */
   8646         sal_memcpy(&bfd_info->endpoint_count, bfd_scache, sizeof(int));
   8647         bfd_scache += sizeof(int);
   8648 
   8649         /* Recover the BFD  end point bit usage  usage */
   8650         for (idx = 0; idx < _SHR_BITDCLSIZE (bfd_info->endpoint_count); idx++) {
   8651             sal_memcpy(&bfd_info->endpoints_in_use[idx], bfd_scache, sizeof(SHR_BITDCL));
   8652             bfd_scache += sizeof(SHR_BITDCL);
   8653         }
   8654 
   8655         bcmi_xgs5_bfd_recover(unit, stable_size, &bfd_scache, recovered_ver);
   8656 
   8657         /* In BCM_BFD_WB_VERSION_1_1 onwards we allocate memory for storing pkt_vlan_id
   8658            also, as such while upgrading from any version lower than
   8659            BCM_BFD_WB_VERSION_1_1 we must add the differential.
   8660          */
   8661         if (recovered_ver < BCM_BFD_WB_VERSION_1_1) {
   8662             realloc_size += (sizeof(bcm_vlan_t) * bfd_info->endpoint_count);
   8663         }
   8664         if (recovered_ver < BCM_BFD_WB_VERSION_1_2) {
   8665             realloc_size += (sizeof(bcm_bfd_tunnel_type_t) * bfd_info->endpoint_count);
   8666             realloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   8667             realloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   8668             realloc_size += (sizeof(bcm_gport_t) * bfd_info->endpoint_count);
   8669             realloc_size += (sizeof(int) * bfd_info->endpoint_count);
   8670             realloc_size += (sizeof(bcm_vpn_t) * bfd_info->endpoint_count);
   8671             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8672             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8673             realloc_size += (sizeof(bcm_vrf_t) * bfd_info->endpoint_count);
   8674             realloc_size += (sizeof(bcm_ip_t)  * bfd_info->endpoint_count);
   8675             realloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   8676             realloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   8677             realloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   8678             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8679             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8680             realloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   8681             realloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   8682             realloc_size += (sizeof(bcm_ip_t) * bfd_info->endpoint_count);
   8683             realloc_size += (sizeof(bcm_ip6_t) * bfd_info->endpoint_count);
   8684             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8685             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8686             realloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8687             realloc_size += (sizeof(bcm_mpls_label_t) * bfd_info->endpoint_count);
   8688             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count); /* egress_label.exp */
   8689             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count); /* egress_label.ttl */
   8690             realloc_size += (sizeof(bcm_if_t) * bfd_info->endpoint_count);
   8691             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8692             realloc_size += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH * bfd_info->endpoint_count);
   8693             realloc_size += (sizeof(bcm_cos_t) * bfd_info->endpoint_count);
   8694             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8695             realloc_size += (sizeof(bcm_bfd_auth_type_t) * bfd_info->endpoint_count);
   8696             realloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8697             realloc_size += (sizeof(int) * bfd_info->endpoint_count);
   8698             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8699             realloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8700             realloc_size += (sizeof(uint8) * bfd_info->endpoint_count);
   8701             realloc_size += (sizeof(uint8) * BCM_BFD_ENDPOINT_MAX_MEP_ID_LENGTH * bfd_info->endpoint_count);
   8702             realloc_size += (sizeof(uint32) * bfd_info->endpoint_count);
   8703         }
   8704         if (recovered_ver < BCM_BFD_WB_VERSION_1_4) {
   8705             realloc_size += (sizeof(uint32) * bfd_info->endpoint_count); /* flags */
   8706         }
   8707         if (recovered_ver < BCM_BFD_WB_VERSION_1_5) {
   8708             realloc_size += (sizeof(bcm_mpls_label_t) * bfd_info->endpoint_count); /* gal label */
   8709         }
   8710 
   8711         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_BFD, 0);
   8712         rv = soc_scache_realloc(unit, scache_handle, realloc_size);
   8713         if (BCM_FAILURE(rv)) {
   8714             LOG_CLI((BSL_META("\nBFD scache realloc failed (rv= %d)\n"), rv));
   8715             return rv;
   8716         }
   8717     }
   8718     return BCM_E_NONE;
   8719 }
   8720 
   8721 #endif  /* BCM_WARM_BOOT_SUPPORT */
   8722 
   8723 /*
   8724  * Function:
   8725  *      bcm_petra_bfd_uc_dump_trace
   8726  * Purpose:
   8727  *      Dump the BFD stack trace
   8728  * Parameters:
   8729  *      unit  - (IN) Unit number.
   8730  * Returns:
   8731  *      None
   8732  * Notes:
   8733  */
   8734 void bcmi_xgs5_bfd_dump_trace(int unit)
   8735 {
   8736 #ifdef BCM_CMICM_SUPPORT
   8737     bfd_info_t          *bfd_info = BFD_INFO(unit);
   8738     uint16               trace[BFD_TRACE_LOG_MAX_SIZE + SHR_BFD_TRACE_LOG_METADATA_SIZE];
   8739     char                *filename[] = SHR_BFD_FILENAMES;
   8740     uint32               w32;
   8741     uint8                file;
   8742     uint16               line;
   8743     uint32               pcie_addr, uc_addr;
   8744     int                  idx, cur_idx;
   8745 
   8746     if ((bfd_info == NULL) || (bfd_info->trace_addr == 0)) {
   8747         LOG_ERROR(BSL_LS_BCM_BFD,
   8748                   (BSL_META_U(unit,
   8749                               "Trace not enabled \n")));
   8750         return;
   8751     }
   8752 
   8753     sal_memset(trace, 0,
   8754                sizeof(uint16) * (BFD_TRACE_LOG_MAX_SIZE +
   8755                                  SHR_BFD_TRACE_LOG_METADATA_SIZE));
   8756 
   8757     /* We read 32 bits and each entry is 16 bit */
   8758     for (idx = 0;
   8759          idx < (BFD_TRACE_LOG_MAX_SIZE + SHR_BFD_TRACE_LOG_METADATA_SIZE);
   8760          idx += (sizeof(uint32) / sizeof(uint16))) {
   8761 
   8762         uc_addr   = bfd_info->trace_addr + (idx * sizeof(uint16));
   8763         pcie_addr = soc_uc_addr_to_pcie(unit, bfd_info->uc_num, uc_addr);
   8764         w32       = soc_uc_mem_read(unit, pcie_addr);
   8765 
   8766         trace[idx]     = w32 & 0xFFFF;
   8767         trace[idx + 1] = (w32 >> 16) & 0xFFFF;
   8768     }
   8769 
   8770     idx = cur_idx = SHR_BFD_TRACE_LOG_CUR_IDX(trace);
   8771     do {
   8772         file = trace[idx] >> 12;
   8773         line = trace[idx] & 0xFFF;
   8774 
   8775         if (file >= SHR_BFD_FILENAME_MAX) {
   8776             LOG_ERROR(BSL_LS_BCM_BFD,
   8777                       (BSL_META_U(unit,
   8778                                   "Trace dump failed \n")));
   8779             break;
   8780         }
   8781 
   8782         if (line != 0) {
   8783             LOG_CLI((BSL_META("%s : %4u \n"), filename[file], line));
   8784         }
   8785 
   8786         idx = SHR_BFD_TRACE_LOG_IDX_DECR(trace, idx);
   8787     } while(idx != cur_idx);
   8788 #endif /* BCM_CMICM_SUPPORT */
   8789 }
   8790 
   8791 #else /* INCLUDE_BFD */
   8792 int bcm_xgs5_bfd_not_empty;
   8793 #endif  /* INCLUDE_BFD */
   8794