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

trill.c (199875B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * ESW Trill API
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #include <sal/core/libc.h>
     15 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/util.h>
     19 #include <soc/hash.h>
     20 #include <soc/debug.h>
     21 #include <bcm/types.h>
     22 #include <bcm/error.h>
     23 
     24 #include <bcm/types.h>
     25 #include <bcm/l3.h>
     26 #if defined(BCM_TRIUMPH3_SUPPORT)
     27 #include <soc/ism_hash.h>
     28 #endif /* BCM_TRIUMPH3_SUPPORT */
     29 #if defined(BCM_TRIDENT2_SUPPORT)
     30 #include <soc/trident2.h>
     31 #endif /* BCM_TRIDENT2_SUPPORT */
     32 #include <bcm/multicast.h>
     33 #include <bcm/trill.h>
     34 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
     35 #include <bcm/trunk.h>
     36 #endif
     37 
     38 #include <bcm_int/esw/mbcm.h>
     39 #include <bcm_int/api_xlate_port.h>
     40 #include <bcm_int/esw_dispatch.h>
     41 #include <bcm_int/esw/virtual.h>
     42 #include <bcm_int/esw/firebolt.h>
     43 #include <bcm_int/esw/trident.h>
     44 #include <bcm_int/esw/triumph.h>
     45 #include <bcm_int/esw/triumph2.h>
     46 #include <bcm_int/esw/triumph3.h>
     47 #include <bcm_int/esw/tomahawk.h>
     48 #include <bcm_int/esw/trill.h>
     49 #include <bcm_int/common/multicast.h>
     50 #include <bcm_int/esw/multicast.h>
     51 #include <bcm_int/esw/trx.h>
     52 
     53 #ifdef BCM_WARM_BOOT_SUPPORT
     54 #include <bcm_int/esw/switch.h>
     55 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     56 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
     57 #endif /* BCM_WARM_BOOT_SUPPORT */
     58 
     59 _bcm_td_trill_bookkeeping_t   *_bcm_td_trill_bk_info[BCM_MAX_NUM_UNITS] = { 0 };
     60 
     61 #define TRILL_INFO(_unit_)   (_bcm_td_trill_bk_info[_unit_])
     62 #define L3_INFO(_unit_)   (&_bcm_l3_bk_info[_unit_])
     63 
     64 #define BCM_TRILL_CHECK_ERROR_RETURN(_op, _u_, _vp)  do { \
     65     int _rv = _op; \
     66     if (_rv < 0) { \
     67          (void) _bcm_vp_free(_u_, _bcmVpTypeTrill, 1, _vp); \
     68          return (_rv); \
     69     } \
     70 } while (0)
     71 
     72 
     73 #define BCM_TRILL_L2MC_CHECK( _u_ , index) \
     74     if ((index < 0) ||\
     75          (index >= soc_mem_index_count(_u_, L2MCm))) { \
     76           return BCM_E_PARAM; \
     77     } \
     78 
     79 #define BCM_TRILL_L3MC_CHECK( _u_ , index) \
     80     if ((index < 0) ||\
     81          (index >= soc_mem_index_count(_u_, L3_IPMCm))) { \
     82          return BCM_E_PARAM; \
     83     } \
     84 
     85 typedef uint32 L3_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS];
     86 
     87 STATIC int _bcm_td_trill_adjacency_set(int unit, int nh_index);
     88 STATIC int _bcm_td_trill_adjacency_reset(int unit, int nh_index);
     89 
     90 /*
     91  * Function:
     92  *      _bcm_trill_check_init
     93  * Purpose:
     94  *      Check if Trill is initialized
     95  * Parameters:
     96  *      unit     - Device Number
     97  * Returns:
     98  *      BCM_E_XXX
     99  */
    100 
    101 
    102 STATIC int 
    103 _bcm_trill_check_init (int unit)
    104 {
    105     _bcm_td_trill_bookkeeping_t *trill_info;
    106 
    107     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
    108          return BCM_E_UNIT;
    109     }
    110 
    111     trill_info = TRILL_INFO(unit);
    112 
    113     if ((trill_info == NULL) || (trill_info->initialized == FALSE)) { 
    114          return BCM_E_INIT;
    115     } else {
    116          return BCM_E_NONE;
    117     }
    118 }
    119 
    120 
    121 
    122 /*
    123  * Function:
    124  *      bcm_trill_lock
    125  * Purpose:
    126  *      Take the Trill Lock Sempahore
    127  * Parameters:
    128  *      unit     - Device Number
    129  * Returns:
    130  *      BCM_E_XXX
    131  */
    132 
    133 
    134  int 
    135  bcm_td_trill_lock (int unit)
    136 {
    137     int rv = BCM_E_NONE;
    138 
    139    rv = _bcm_trill_check_init (unit);
    140    
    141    if ( rv == BCM_E_NONE ) {
    142            sal_mutex_take(TRILL_INFO((unit))->trill_mutex, sal_mutex_FOREVER);
    143    }
    144    return rv; 
    145 }
    146 
    147 
    148 
    149 /*
    150  * Function:
    151  *      bcm_trill_unlock
    152  * Purpose:
    153  *      Release  the Trill Lock Semaphore
    154  * Parameters:
    155  *      unit     - Device Number
    156  * Returns:
    157  *      BCM_E_XXX
    158  */
    159 
    160 
    161 void
    162 bcm_td_trill_unlock(int unit)
    163 {
    164     int rv = BCM_E_NONE;
    165 
    166     rv = _bcm_trill_check_init (unit);
    167     if ( rv == BCM_E_NONE ) {
    168          sal_mutex_give(TRILL_INFO((unit))->trill_mutex);
    169     }
    170 }
    171 
    172 
    173 
    174 /*
    175  * Function:
    176  *      _bcm_td_trill_free_resource
    177  * Purpose:
    178  *      Free all allocated software resources 
    179  * Parameters:
    180  *      unit - SOC unit number
    181  * Returns:
    182  *      Nothing
    183  */
    184 
    185 
    186 STATIC void
    187 _bcm_td_trill_free_resource(int unit)
    188 {
    189     _bcm_td_trill_bookkeeping_t *trill_info;
    190 
    191     trill_info = TRILL_INFO(unit);
    192 
    193     /* If software tables were not allocated we are done. */ 
    194     if (NULL == TRILL_INFO(unit)) {
    195         return;
    196     }
    197 
    198     if (trill_info->rBridge) {
    199         sal_free(trill_info->rBridge);
    200         trill_info->rBridge = NULL;
    201     }
    202 
    203     if (trill_info->multicast_count) {
    204         sal_free(trill_info->multicast_count);
    205         trill_info->multicast_count = NULL;
    206     }
    207 
    208     /* Free module data. */
    209     sal_free(TRILL_INFO(unit));
    210     TRILL_INFO(unit) = NULL;
    211 }
    212 
    213 /*
    214  * Function:
    215  *      bcm_td_trill_tpid_add
    216  * Purpose:
    217  *      Add Tpid for TRILL 
    218  * Parameters:
    219  *      unit - SOC unit number.
    220  *      port - Trill gport
    221  *      tpid -  Tag protocol ID
    222  * Returns:
    223  *      BCM_E_XXX.
    224  */
    225 int
    226 bcm_td_trill_tpid_add(int unit, bcm_gport_t port, int tpid_idx)
    227 {
    228     int rv = BCM_E_NONE;
    229     uint32 ena_f;
    230     ing_trill_payload_parse_control_entry_t tpid_ent;
    231 
    232     sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t));
    233 
    234     BCM_IF_ERROR_RETURN(
    235        soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    236                     MEM_BLOCK_ALL, 0, &tpid_ent));
    237     ena_f = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get
    238                                 (unit, &tpid_ent, TPID_ENABLEf);
    239 
    240     if (!(ena_f & (1 << tpid_idx))) {
    241         ena_f |= 1 << tpid_idx;
    242         soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_set
    243                         (unit, &tpid_ent, TPID_ENABLEf, ena_f);
    244         BCM_IF_ERROR_RETURN(
    245                 soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    246                               MEM_BLOCK_ALL, 0, &tpid_ent));
    247     }
    248     return rv;
    249 }
    250 
    251 
    252 /*
    253  * Function:
    254  *      bcm_td_trill_tpid_set
    255  * Purpose:
    256  *      Set Tpid for TRILL 
    257  * Parameters:
    258  *      unit - SOC unit number.
    259  *      port - Trill gport
    260  *      tpid -  Tag protocol ID
    261  * Returns:
    262  *      BCM_E_XXX.
    263  */
    264 int
    265 bcm_td_trill_tpid_set(int unit, bcm_gport_t port, int tpid_idx)
    266 {
    267     int rv = BCM_E_NONE;
    268     uint32 ena_f;
    269     ing_trill_payload_parse_control_entry_t tpid_ent;
    270 
    271     sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t));
    272 
    273     BCM_IF_ERROR_RETURN(
    274        soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    275                     MEM_BLOCK_ALL, 0, &tpid_ent));
    276     ena_f = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get
    277                                 (unit, &tpid_ent, TPID_ENABLEf);
    278 
    279     if (!(ena_f & (1 << tpid_idx))) {
    280         ena_f = 1 << tpid_idx;
    281         soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_set
    282                         (unit, &tpid_ent, TPID_ENABLEf, ena_f);
    283         BCM_IF_ERROR_RETURN(
    284                 soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    285                               MEM_BLOCK_ALL, 0, &tpid_ent));
    286     }
    287     return rv;
    288 }
    289 
    290 /*
    291  * Function:
    292  *      bcm_td_trill_tpid_get
    293  * Purpose:
    294  *      Get TRILL TPID
    295  * Parameters:
    296  *      unit - SOC unit number
    297  *      port - Trill gport
    298  *      tpid - Tag protocol ID
    299  * Returns:
    300  *      BCM_E_XXX.
    301  */
    302 int
    303 bcm_td_trill_tpid_get(int unit, bcm_gport_t port, int *tpid_index)
    304 {
    305     int rv = BCM_E_NONE;
    306     ing_trill_payload_parse_control_entry_t tpid_ent;
    307 
    308     sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t));
    309     BCM_IF_ERROR_RETURN(
    310        soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    311                     MEM_BLOCK_ALL, 0, &tpid_ent));
    312 
    313     *tpid_index = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get
    314                                     (unit, &tpid_ent, TPID_ENABLEf);
    315     return rv;
    316 }
    317 
    318 /*
    319  * Function:
    320  *      bcm_td_trill_tpid_delete
    321  * Purpose:
    322  *      Delete Tpid for TRILL 
    323  * Parameters:
    324  *      unit - SOC unit number.
    325  *      port - Trill gport
    326  *      tpid -  Tag protocol ID
    327  * Returns:
    328  *      BCM_E_XXX.
    329  */
    330 int
    331 bcm_td_trill_tpid_delete(int unit, bcm_gport_t port, int tpid_idx)
    332 {
    333     int rv = BCM_E_NONE;
    334     uint32 ena_f;
    335     ing_trill_payload_parse_control_entry_t tpid_ent;
    336 
    337     sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t));
    338 
    339     BCM_IF_ERROR_RETURN(
    340        soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    341                     MEM_BLOCK_ALL, 0, &tpid_ent));
    342     ena_f = soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_get
    343                                 (unit, &tpid_ent, TPID_ENABLEf);
    344 
    345     if (ena_f & (1 << tpid_idx)) {
    346         ena_f &= ~(1 << tpid_idx);
    347         soc_ING_TRILL_PAYLOAD_PARSE_CONTROLm_field32_set
    348                         (unit, &tpid_ent, TPID_ENABLEf, ena_f);
    349         BCM_IF_ERROR_RETURN(
    350                 soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    351                               MEM_BLOCK_ALL, 0, &tpid_ent));
    352     }
    353     return rv;
    354 }
    355 
    356 /*
    357  * Function:
    358  *      bcm_td_trill_ethertype_set
    359  * Purpose:
    360  *      Enable TRILL functionality
    361  * Parameters:
    362  *      unit - SOC unit number.
    363  *      etherType -  Non-zero value: enable TRILL support
    364  *                          Zero vlaue: Disable TRILL support
    365  * Returns:
    366  *      BCM_E_XXX.
    367  */
    368 int
    369 bcm_td_trill_ethertype_set(int unit, uint16 etherType)
    370 {
    371     int rv = BCM_E_NONE;
    372     ing_trill_parse_control_entry_t  ing_ent;
    373     egr_trill_parse_control_entry_t egr_ent;
    374     ing_trill_payload_parse_control_entry_t tpid_ent;
    375 
    376     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));	
    377     sal_memset(&egr_ent, 0, sizeof(egr_trill_parse_control_entry_t));
    378     sal_memset(&tpid_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t));
    379 
    380     if (etherType > 0) {
    381 
    382          if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) {
    383              soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent,
    384                                          TRILL_ETHERTYPE_ENABLEf, 0x1);
    385              soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent,
    386                                          TRILL_ETHERTYPEf, etherType);
    387          }
    388 
    389          soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent,
    390                                          TRILL_ETHERTYPE_ENABLEf, 0x1);
    391          soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent,
    392                                          TRILL_ETHERTYPEf, etherType);
    393          if (SOC_MEM_IS_VALID(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm)) {
    394              soc_mem_field32_set(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, &tpid_ent,
    395                                              TPID_ENABLEf, 0x1);
    396          }
    397     }
    398 
    399     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm,
    400                                             MEM_BLOCK_ALL, 0, &ing_ent));
    401     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm,
    402                                             MEM_BLOCK_ALL, 0, &egr_ent));
    403     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    404                                             MEM_BLOCK_ALL, 0, &tpid_ent));
    405     return rv;
    406 }
    407 
    408 /*
    409  * Function:
    410  *      bcm_td_trill_ethertype_get
    411  * Purpose:
    412  *      Get TRILL EtherType
    413  * Parameters:
    414  *      unit - SOC unit number.
    415  *      etherType - return value
    416  * Returns:
    417  *      BCM_E_XXX.
    418  */
    419 int
    420 bcm_td_trill_ethertype_get(int unit, int *etherType)
    421 {
    422     int rv = BCM_E_NONE;
    423     ing_trill_parse_control_entry_t  ing_ent;
    424 
    425     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));
    426 
    427     BCM_IF_ERROR_RETURN(
    428        soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    429                        MEM_BLOCK_ALL, 0, &ing_ent));
    430 
    431     *etherType = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent,
    432                                          TRILL_ETHERTYPEf);
    433     return rv;
    434 }
    435 
    436 /*
    437  * Function:
    438  *      bcm_td_trill_ISIS_ethertype_set
    439  * Purpose:
    440  *      Set TRILL ISIS EtherType
    441  * Parameters:
    442  *      unit - SOC unit number.
    443  *      etherType -  Non-zero value: enable Ethertype
    444  * Returns:
    445  *      BCM_E_XXX.
    446  */
    447 int
    448 bcm_td_trill_ISIS_ethertype_set(int unit, uint16 etherType)
    449 {
    450     int rv = BCM_E_NONE;
    451     int en = 0;
    452     ing_trill_parse_control_entry_t  ing_ent;
    453     egr_trill_parse_control_entry_t egr_ent;    
    454     egr_trill_parse_control_2_entry_t egr2_ent;
    455 
    456     if (!soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    457                              L2_IS_IS_ETHERTYPE_ENABLEf) ||
    458         !soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROLm, 
    459                         TRILL_L2_IS_IS_ETHERTYPE_ENABLEf) ||
    460         !soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROL_2m, 
    461                         TRILL_L2_IS_IS_ETHERTYPE_ENABLEf)) {
    462         return BCM_E_UNAVAIL;
    463     }
    464 
    465     BCM_IF_ERROR_RETURN(
    466          soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    467                   MEM_BLOCK_ALL, 0, &ing_ent));
    468     BCM_IF_ERROR_RETURN(
    469          soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm,
    470                   MEM_BLOCK_ALL, 0, &egr_ent));
    471     BCM_IF_ERROR_RETURN(
    472          soc_mem_read(unit, EGR_TRILL_PARSE_CONTROL_2m,
    473                   MEM_BLOCK_ALL, 0, &egr2_ent));
    474 
    475     /* enable if ethertype > 0 */
    476     en = (etherType > 0) ? 1 : 0;
    477 
    478     soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent,
    479                               L2_IS_IS_ETHERTYPE_ENABLEf, en);
    480     soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent,
    481                               L2_IS_IS_ETHERTYPEf, etherType);
    482     soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent,
    483                               TRILL_L2_IS_IS_ETHERTYPE_ENABLEf, en);
    484     soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent,
    485                               TRILL_L2_IS_IS_ETHERTYPEf, etherType);
    486     soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROL_2m, &egr2_ent,
    487                               TRILL_L2_IS_IS_ETHERTYPE_ENABLEf, en);
    488     soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROL_2m, &egr2_ent,
    489                                TRILL_L2_IS_IS_ETHERTYPEf, etherType);
    490 
    491     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm,
    492                                        MEM_BLOCK_ALL, 0, &ing_ent));
    493     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm,
    494                                        MEM_BLOCK_ALL, 0, &egr_ent));
    495     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROL_2m,
    496                                        MEM_BLOCK_ALL, 0, &egr2_ent));
    497 
    498     return rv;
    499 }
    500 
    501 /*
    502  * Function:
    503  *      bcm_td_trill_ISIS_ethertype_get
    504  * Purpose:
    505  *      Get TRILL ISIS EtherType
    506  * Parameters:
    507  *      unit - SOC unit number.
    508  *      etherType - return value
    509  * Returns:
    510  *      BCM_E_XXX.
    511  */
    512 int
    513 bcm_td_trill_ISIS_ethertype_get(int unit, int *etherType)
    514 {
    515     int rv = BCM_E_NONE;
    516     ing_trill_parse_control_entry_t  ing_ent;
    517 
    518     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));
    519 
    520     BCM_IF_ERROR_RETURN(
    521        soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    522                        MEM_BLOCK_ALL, 0, &ing_ent));
    523 
    524     if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    525                              L2_IS_IS_ETHERTYPEf)) {
    526          *etherType = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, 
    527                                   &ing_ent, L2_IS_IS_ETHERTYPEf);
    528     } else {
    529          *etherType = 0;
    530          rv = BCM_E_UNAVAIL;  /* BCM_E_UNAVAIL if the field is not supported */
    531     }
    532 
    533     return rv;
    534 }
    535 
    536 
    537 /*
    538  * Function:
    539  *      _bcm_td_trill_mac_set
    540  * Description:
    541  *      flag = 0:  Set the lower 24 bits of MAC address field for TRILL specific MAC
    542  *      flag = 1:  Set the higher 24 bits of MAC address field for TRILL specific MAC
    543  * Parameters:
    544  *      unit       - unit number (driver internal).
    545  *      type      - The required switch control type to set upper MAC for
    546  *      mac      - MAC address
    547  * Returns:
    548  *      BCM_E_xxxx
    549  */
    550 
    551 STATIC void
    552 _bcm_td_trill_mac_set(int unit, uint32 mac_field, soc_mem_t mem, 
    553                         void *entry, soc_field_t field, sal_mac_addr_t mac, uint8 flag) 
    554 {
    555     soc_mem_mac_addr_get(unit, mem, entry, 
    556                         field, mac);
    557     if (!flag) {
    558          /* Set the low-order bytes */
    559          mac[3] = (uint8) (mac_field >> 16 & 0xff);
    560          mac[4] = (uint8) (mac_field >> 8 & 0xff);
    561          mac[5] = (uint8) (mac_field & 0xff);
    562     } else {
    563          /* Set the High-order bytes */
    564          mac[0] = (uint8) (mac_field >> 16 & 0xff);
    565          mac[1] = (uint8) (mac_field >> 8 & 0xff);
    566          mac[2] = (uint8) (mac_field & 0xff);
    567     }
    568     soc_mem_mac_addr_set(unit, mem, entry,
    569                         field, mac);
    570 }
    571 
    572 /*
    573  * Function:
    574  *      bcm_td_trill_mac_set
    575  * Description:
    576  *      flag = 0:  Set the lower 24 bits of MAC address field for TRILL specific MAC
    577  *      flag = 1:  Set the higher 24 bits of MAC address field for TRILL specific MAC
    578  * Parameters:
    579  *      unit      - unit number (driver internal).
    580  *      type     - The required switch control type to set upper MAC for
    581  *      mac     - MAC address
    582  * Returns:
    583  *      BCM_E_xxxx
    584  */
    585 
    586 int
    587 bcm_td_trill_mac_set(int unit, 
    588                             bcm_switch_control_t type,
    589                             uint32 mac_field,
    590                             uint8   flag)
    591 {
    592     ing_trill_parse_control_entry_t  ing_ent;
    593     egr_trill_parse_control_entry_t egr_ent;
    594     egr_trill_parse_control_2_entry_t egr2_ent;
    595     ing_trill_payload_parse_control_entry_t ing_payload_ent;
    596     bcm_mac_t   mac;   
    597 
    598     sal_memset(mac, 0, sizeof(bcm_mac_t));    
    599 
    600     BCM_IF_ERROR_RETURN(
    601        soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    602                        MEM_BLOCK_ALL, 0, &ing_ent));
    603     BCM_IF_ERROR_RETURN(
    604        soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm,
    605                        MEM_BLOCK_ALL, 0, &egr_ent));
    606     BCM_IF_ERROR_RETURN(
    607        soc_mem_read(unit, EGR_TRILL_PARSE_CONTROL_2m,
    608                        MEM_BLOCK_ALL, 0, &egr2_ent));
    609     BCM_IF_ERROR_RETURN(
    610        soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    611                        MEM_BLOCK_ALL, 0, &ing_payload_ent));
    612    
    613     switch (type) {
    614          case bcmSwitchTrillISISDestMacOui:         
    615          case bcmSwitchTrillISISDestMacNonOui:
    616               BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    617                                        MEM_BLOCK_ALL, 0, &ing_ent));
    618               _bcm_td_trill_mac_set(unit, mac_field, ING_TRILL_PARSE_CONTROLm, 
    619                                        &ing_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac, flag);
    620               if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    621                              TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 
    622                 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 
    623                                          TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 
    624               } 
    625               BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm,
    626                                        MEM_BLOCK_ALL, 0, &ing_ent));
    627 
    628               BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm,
    629                                        MEM_BLOCK_ALL, 0, &egr_ent));
    630               sal_memset(mac, 0, sizeof(bcm_mac_t));
    631               _bcm_td_trill_mac_set(unit, mac_field, EGR_TRILL_PARSE_CONTROLm, 
    632                                        &egr_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac, flag);
    633               if (soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROLm, 
    634                              TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 
    635                 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 
    636                                          TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 
    637               } 
    638               BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm,
    639                                        MEM_BLOCK_ALL, 0, &egr_ent));
    640 
    641               BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_PARSE_CONTROL_2m,
    642                                        MEM_BLOCK_ALL, 0, &egr2_ent));
    643               sal_memset(mac, 0, sizeof(bcm_mac_t));
    644               _bcm_td_trill_mac_set(unit, mac_field, EGR_TRILL_PARSE_CONTROL_2m, 
    645                                        &egr2_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac, flag);
    646               if (soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROL_2m, 
    647                              TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) {
    648                 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROL_2m, &egr2_ent, 
    649                                          TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 
    650               } 
    651               BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROL_2m,
    652                                        MEM_BLOCK_ALL, 0, &egr2_ent));
    653               break;
    654         
    655         case bcmSwitchTrillBroadcastDestMacOui:
    656         case bcmSwitchTrillBroadcastDestMacNonOui: 
    657               BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    658                                        MEM_BLOCK_ALL, 0, &ing_ent));
    659               _bcm_td_trill_mac_set(unit, mac_field, ING_TRILL_PARSE_CONTROLm, 
    660                                        &ing_ent, TRILL_ALL_RBRIDGES_MAC_ADDRESSf, mac, flag);
    661               if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    662                              TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 
    663                 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 
    664                                          TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 
    665               } 
    666               BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm,
    667                                        MEM_BLOCK_ALL, 0, &ing_ent));
    668 
    669               BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_PARSE_CONTROLm,
    670                                        MEM_BLOCK_ALL, 0, &egr_ent));
    671               sal_memset(mac, 0, sizeof(bcm_mac_t));
    672               _bcm_td_trill_mac_set(unit, mac_field, EGR_TRILL_PARSE_CONTROLm, 
    673                                        &egr_ent, TRILL_ALL_RBRIDGES_MAC_ADDRESSf, mac, flag);
    674               if (soc_mem_field_valid(unit, EGR_TRILL_PARSE_CONTROLm, 
    675                              TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 
    676                 soc_mem_field32_set(unit, EGR_TRILL_PARSE_CONTROLm, &egr_ent, 
    677                                          TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 
    678               } 
    679               BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_PARSE_CONTROLm,
    680                                        MEM_BLOCK_ALL, 0, &egr_ent));
    681 #ifdef BCM_TOMAHAWK_SUPPORT
    682               if (SOC_IS_TOMAHAWKX(unit)) {
    683                   BCM_IF_ERROR_RETURN(bcm_th_ipmc_trill_mac_update(unit,
    684                               mac_field, flag));
    685               } else
    686 #endif /* BCM_TOMAHAWK_SUPPORT */
    687 #ifdef BCM_TRIUMPH3_SUPPORT
    688               if (SOC_IS_TRIUMPH3(unit)) {
    689                   BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_trill_mac_update(unit,
    690                               mac_field, flag));
    691               }
    692 #endif /* BCM_TRIUMPH3_SUPPORT */
    693               break;
    694 
    695         case bcmSwitchTrillEndStationDestMacOui:        
    696         case bcmSwitchTrillEndStationDestMacNonOui:
    697               BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    698                                        MEM_BLOCK_ALL, 0, &ing_payload_ent));
    699               _bcm_td_trill_mac_set(unit, mac_field, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 
    700                                        &ing_payload_ent, TRILL_ALL_ESADI_RBRIDGES_MAC_ADDRESSf, mac, flag);
    701               if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    702                              TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf)) { 
    703                 soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent, 
    704                                          TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESS_ENABLEf, 0x1); 
    705               } 
    706               BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    707                                        MEM_BLOCK_ALL, 0, &ing_payload_ent));
    708               break;
    709 
    710         default:
    711               return BCM_E_PARAM;
    712     }
    713     return BCM_E_NONE;
    714 }
    715 
    716 /*
    717  * Function:
    718  *      _bcm_td_trill_mac_get
    719  * Description:
    720  *      flag = 0:  Get the lower 24 bits of MAC address field for TRILL specific MAC
    721  *      flag = 1:  Get the higher 24 bits of MAC address field for TRILL specific MAC
    722  * Parameters:
    723  *      unit       - unit number (driver internal).
    724  *      type      - The required switch control type to set upper MAC for
    725  *      mac      - MAC address
    726  * Returns:
    727  *      BCM_E_xxxx
    728  */
    729 
    730 STATIC void
    731 _bcm_td_trill_mac_get(int unit, soc_mem_t mem, 
    732                         void *entry, soc_field_t field, uint32 *mac_field, uint8 flag) 
    733 {
    734     bcm_mac_t mac;
    735 
    736     soc_mem_mac_addr_get(unit, mem, entry, 
    737                         field, mac);
    738 
    739     if (flag) {
    740          /* read the high-order bytes from Memory */
    741          *mac_field = ((mac[0] << 16) | (mac[1] << 8)  | (mac[2] << 0));
    742     } else {
    743          /* read the low-order bytes from Memory */
    744          *mac_field = ((mac[3] << 16) | (mac[4] << 8)  | (mac[5] << 0));
    745     }
    746 }
    747 
    748 
    749 /*
    750  * Function:
    751  *      bcm_td_trill_mac_get
    752  * Description:
    753  *      flag = 0:  Get the lower 24 bits of MAC address field for TRILL specific MAC
    754  *      flag = 1:  Get the higher 24 bits of MAC address field for TRILL specific MAC
    755  * Parameters:
    756  *      unit      - unit number (driver internal).
    757  *      type     - The required switch control type to set upper MAC for
    758  *      mac     - MAC address
    759  * Returns:
    760  *      BCM_E_xxxx
    761  */
    762 
    763 int
    764 bcm_td_trill_mac_get(int unit, 
    765                             bcm_switch_control_t type,
    766                             uint32 *mac_field,
    767                             uint8   flag)
    768 {
    769     ing_trill_parse_control_entry_t  ing_ent;
    770     egr_trill_parse_control_entry_t egr_ent;
    771     egr_trill_parse_control_2_entry_t egr2_ent;
    772     ing_trill_payload_parse_control_entry_t ing_payload_ent;
    773 
    774     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));	
    775     sal_memset(&egr_ent, 0, sizeof(egr_trill_parse_control_entry_t));    
    776     sal_memset(&egr2_ent, 0, sizeof(egr_trill_parse_control_2_entry_t));
    777     sal_memset(&ing_payload_ent, 0, sizeof(ing_trill_payload_parse_control_entry_t));
    778 
    779     switch (type) {
    780          case bcmSwitchTrillISISDestMacOui:         
    781          case bcmSwitchTrillISISDestMacNonOui:
    782               BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    783                                        MEM_BLOCK_ALL, 0, &ing_ent));
    784               _bcm_td_trill_mac_get(unit, ING_TRILL_PARSE_CONTROLm, 
    785                                        &ing_ent, TRILL_ALL_IS_IS_RBRIDGES_MAC_ADDRESSf, mac_field, flag);
    786 
    787               break;
    788         
    789         case bcmSwitchTrillBroadcastDestMacOui:         
    790         case bcmSwitchTrillBroadcastDestMacNonOui: 
    791               BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    792                                        MEM_BLOCK_ALL, 0, &ing_ent));
    793               _bcm_td_trill_mac_get(unit, ING_TRILL_PARSE_CONTROLm, 
    794                                        &ing_ent, TRILL_ALL_RBRIDGES_MAC_ADDRESSf, mac_field, flag);
    795 
    796               break;
    797 
    798         case bcmSwitchTrillEndStationDestMacOui:        
    799         case bcmSwitchTrillEndStationDestMacNonOui:
    800               BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm,
    801                                        MEM_BLOCK_ALL, 0, &ing_payload_ent));
    802               _bcm_td_trill_mac_get(unit, ING_TRILL_PAYLOAD_PARSE_CONTROLm, 
    803                                        &ing_payload_ent, TRILL_ALL_ESADI_RBRIDGES_MAC_ADDRESSf, mac_field, flag);
    804               break;
    805 
    806         default:
    807               return BCM_E_PARAM;
    808     }
    809     return BCM_E_NONE;
    810 }
    811 
    812 /*
    813  * Function:
    814  *      bcm_td_trill_MinTtl_set
    815  * Description:
    816  *       Set minimum TTL value for Transit and Egress Rbridge
    817  * Parameters:
    818  *      unit      - unit number (driver internal).
    819  *      min_ttl     - Minimum TTL value
    820  * Returns:
    821  *      BCM_E_xxxx
    822  */
    823 
    824 int
    825 bcm_td_trill_MinTtl_set(int unit, int min_ttl)
    826 {
    827     int rv = BCM_E_NONE;
    828     ing_trill_parse_control_entry_t  ing_ent;
    829 
    830     if (!soc_feature(unit, soc_feature_trill_ttl)) {
    831         return BCM_E_UNAVAIL;
    832     }
    833 
    834     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));
    835 
    836     if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) {              
    837       if ((min_ttl > 0) && (min_ttl < 64)) {
    838          BCM_IF_ERROR_RETURN(
    839               soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    840                        MEM_BLOCK_ALL, 0, &ing_ent));
    841     
    842          if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    843                              MIN_INCOMING_HOPCOUNTf)) {
    844               soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent,
    845                                          MIN_INCOMING_HOPCOUNTf, min_ttl);
    846          }
    847 
    848          BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm,
    849                                             MEM_BLOCK_ALL, 0, &ing_ent));
    850       }
    851     }
    852     return rv;
    853 }
    854 
    855 /*
    856  * Function:
    857  *      bcm_td_trill_MinTtl_get
    858  * Description:
    859  *       Get minimum TTL value for Transit and Egress Rbridge
    860  * Parameters:
    861  *      unit      - unit number (driver internal).
    862  *      min_ttl     - Minimum TTL value
    863  * Returns:
    864  *      BCM_E_xxxx
    865  */
    866 
    867 int
    868 bcm_td_trill_MinTtl_get(int unit, int *min_ttl)
    869 {
    870     int rv = BCM_E_NONE;
    871     ing_trill_parse_control_entry_t  ing_ent;
    872 
    873     if (!soc_feature(unit, soc_feature_trill_ttl)) {
    874         return BCM_E_UNAVAIL;
    875     }
    876 
    877     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));
    878 
    879     if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) {
    880          BCM_IF_ERROR_RETURN(
    881               soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    882                        MEM_BLOCK_ALL, 0, &ing_ent));
    883     
    884          if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    885                              MIN_INCOMING_HOPCOUNTf)) {
    886               *min_ttl = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, 
    887                                             &ing_ent,
    888                                             MIN_INCOMING_HOPCOUNTf);
    889          }
    890     }
    891     return rv;
    892 }
    893 
    894 /*
    895  * Function:
    896  *      bcm_td_trill_TtlCheckEnable_set
    897  * Description:
    898  *       Set enable for Egress RBridge TTL Check 
    899  * Parameters:
    900  *      unit      - unit number (driver internal).
    901  *      enable     - TTL Check Enable
    902  * Returns:
    903  *      BCM_E_xxxx
    904  */
    905 int
    906 bcm_td_trill_TtlCheckEnable_set(int unit, int enable)
    907 {
    908     int rv = BCM_E_NONE;
    909     ing_trill_parse_control_entry_t  ing_ent;
    910 
    911     if (!soc_feature(unit, soc_feature_trill_ttl)) {
    912         return BCM_E_UNAVAIL;
    913     }
    914 
    915     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));
    916 
    917     if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) {              
    918       if ((enable == TRUE) || (enable == FALSE)) {  
    919          BCM_IF_ERROR_RETURN(
    920               soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    921                        MEM_BLOCK_ALL, 0, &ing_ent));
    922     
    923          if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    924                              EGRESS_RBRIDGE_CHECK_HOPCOUNTf)) {
    925               soc_mem_field32_set(unit, ING_TRILL_PARSE_CONTROLm, &ing_ent,
    926                                          EGRESS_RBRIDGE_CHECK_HOPCOUNTf, enable);
    927          }
    928 
    929          BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_TRILL_PARSE_CONTROLm,
    930                                             MEM_BLOCK_ALL, 0, &ing_ent));
    931       }
    932     }
    933     return rv;
    934 
    935 }
    936 
    937 /*
    938  * Function:
    939  *      bcm_td_trill_TtlCheckEnable_get
    940  * Description:
    941  *       Get enable for Egress RBridge TTL Check 
    942  * Parameters:
    943  *      unit      - unit number (driver internal).
    944  *      enable     - TTL Check Enable
    945  * Returns:
    946  *      BCM_E_xxxx
    947  */
    948 int
    949 bcm_td_trill_TtlCheckEnable_get(int unit, int *enable)
    950 {
    951     int rv = BCM_E_NONE;
    952     ing_trill_parse_control_entry_t  ing_ent;
    953 
    954     if (!soc_feature(unit, soc_feature_trill_ttl)) {
    955         return BCM_E_UNAVAIL;
    956     }
    957 
    958     sal_memset(&ing_ent, 0, sizeof(ing_trill_parse_control_entry_t));
    959 
    960     if (SOC_MEM_IS_VALID(unit, ING_TRILL_PARSE_CONTROLm)) {
    961          BCM_IF_ERROR_RETURN(
    962               soc_mem_read(unit, ING_TRILL_PARSE_CONTROLm,
    963                        MEM_BLOCK_ALL, 0, &ing_ent));
    964     
    965          if (soc_mem_field_valid(unit, ING_TRILL_PARSE_CONTROLm, 
    966                              EGRESS_RBRIDGE_CHECK_HOPCOUNTf)) {
    967               *enable = soc_mem_field32_get(unit, ING_TRILL_PARSE_CONTROLm, 
    968                                             &ing_ent,
    969                                             EGRESS_RBRIDGE_CHECK_HOPCOUNTf);
    970          }
    971     }
    972     return rv;
    973 }
    974 
    975 /*
    976  * Function:
    977  *      bcm_td_trill_allocate_bk
    978  * Purpose:
    979  *      Initialize the Trill software module
    980  * Parameters:
    981  *      unit     - Device Number
    982  * Returns:
    983  *      BCM_E_XXX
    984  */
    985 
    986 STATIC int
    987 bcm_td_trill_allocate_bk(int unit)
    988 {
    989     /* Allocate/Init unit software tables. */
    990     if (NULL == TRILL_INFO(unit)) {
    991         BCM_TD_TRILL_ALLOC(TRILL_INFO(unit), sizeof(_bcm_td_trill_bookkeeping_t),
    992                           "trill_bk_module_data");
    993         if (NULL == TRILL_INFO(unit)) {
    994             return (BCM_E_MEMORY);
    995         } else {
    996             TRILL_INFO(unit)->initialized = FALSE;
    997         }
    998     }
    999     return BCM_E_NONE;
   1000 }
   1001 
   1002 #ifdef BCM_WARM_BOOT_SUPPORT
   1003 /* 
   1004  * Function:
   1005  *      bcm_td_trill_sync
   1006  * Purpose:
   1007  *      Store the multicast count Trill book keeping structure 
   1008  *      onto persistent memory.
   1009  * Parameters:
   1010  *      unit    : (IN) Device Unit Number
   1011  * Returns:
   1012  *      BCM_E_XXX
   1013  */
   1014 int
   1015 bcm_td_trill_sync(int unit)
   1016 {
   1017     int rv=BCM_E_NONE, alloc_sz = 0, num_ipmc=0;
   1018     uint8 *trill_state;
   1019     soc_scache_handle_t scache_handle;
   1020     _bcm_td_trill_bookkeeping_t *trill_info;
   1021 
   1022     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1023         return BCM_E_NONE;        
   1024     }
   1025     trill_info = TRILL_INFO(unit);
   1026     num_ipmc = soc_mem_index_count(unit, L3_IPMCm);
   1027 
   1028     alloc_sz = sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc;   
   1029 
   1030     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRILL, 0);
   1031     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1032                                  alloc_sz, &trill_state, 
   1033                                  BCM_WB_DEFAULT_VERSION, NULL);
   1034     if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) {
   1035         return rv;
   1036     }
   1037     
   1038     sal_memcpy(trill_state, trill_info->multicast_count, alloc_sz);
   1039 
   1040     return rv;
   1041 }
   1042 
   1043 /*
   1044  * Function:
   1045  *      _bcm_td_trill_reinit
   1046  * Purpose:
   1047  *      Perform recovery of Trill s/w state during warmboot.
   1048  * Parameters:
   1049  *      unit - Device Number
   1050  * Returns:
   1051  *      BCM_E_XXX
   1052  */
   1053 STATIC int
   1054 _bcm_td_trill_reinit(int unit)
   1055 {
   1056     uint8 *trill_state;
   1057     int alloc_sz=0, stable_size = 0, num_ipmc=0;
   1058     int idx=0, idx_min=0, idx_max=0;
   1059     soc_scache_handle_t scache_handle;
   1060     _bcm_td_trill_bookkeeping_t *trill_info;
   1061     egr_dvp_attribute_entry_t egr_dvp_attribute;
   1062     egr_trill_tree_profile_entry_t  egr_trill_profile;
   1063 
   1064     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   1065 
   1066     if ((stable_size != 0) && (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 
   1067 
   1068         trill_info = TRILL_INFO(unit);
   1069     
   1070         /* Recover rBridge book keeping info */    
   1071         idx_min = soc_mem_index_min(unit, EGR_DVP_ATTRIBUTEm);
   1072         idx_max = soc_mem_index_max(unit, EGR_DVP_ATTRIBUTEm);
   1073 
   1074         for (idx = idx_min; idx <= idx_max; idx++) {
   1075             SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   1076                                     MEM_BLOCK_ANY, idx, &egr_dvp_attribute));
   1077             if (soc_EGR_DVP_ATTRIBUTEm_field32_get(unit,
   1078                          &egr_dvp_attribute, VP_TYPEf) != 0x1) {
   1079                 continue;
   1080             }
   1081             trill_info->rBridge[idx] = soc_EGR_DVP_ATTRIBUTEm_field32_get(unit,
   1082                                   &egr_dvp_attribute, EGRESS_RBRIDGE_NICKNAMEf);
   1083         }
   1084 
   1085         /* Recover rootBridge book keeping info */    
   1086         idx_min = soc_mem_index_min(unit, EGR_TRILL_TREE_PROFILEm);
   1087         idx_max = soc_mem_index_max(unit, EGR_TRILL_TREE_PROFILEm);
   1088 
   1089         for (idx = idx_min; idx <= idx_max; idx++) {
   1090             SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TRILL_TREE_PROFILEm,
   1091                                     MEM_BLOCK_ANY, idx, &egr_trill_profile));
   1092             /* coverity[overrun-local : FALSE] */
   1093             trill_info->rootBridge[idx] =
   1094                            soc_EGR_TRILL_TREE_PROFILEm_field32_get(unit,
   1095                                     &egr_trill_profile, ROOT_RBRIDGE_NICKNAMEf);
   1096         }
   1097 
   1098         /* Recover multicast ref count book keeping info */    
   1099         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRILL, 0);
   1100         num_ipmc = soc_mem_index_count(unit, L3_IPMCm);
   1101 
   1102         alloc_sz = sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc;   
   1103         SOC_IF_ERROR_RETURN
   1104             (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1105                                      alloc_sz, &trill_state, 
   1106                                      BCM_WB_DEFAULT_VERSION, NULL));
   1107 
   1108         sal_memcpy(trill_info->multicast_count, trill_state, alloc_sz);
   1109     }
   1110 
   1111     return BCM_E_NONE;
   1112 }
   1113 #endif /* BCM_WARM_BOOT_SUPPORT */
   1114 
   1115 /*
   1116  * Function:
   1117  *      bcm_td_trill_init
   1118  * Purpose:
   1119  *      Initialize the Trill software module
   1120  * Parameters:
   1121  *      unit     - Device Number
   1122  * Returns:
   1123  *      BCM_E_XXX
   1124  */
   1125 
   1126 
   1127 int
   1128 bcm_td_trill_init(int unit)
   1129 {
   1130     _bcm_td_trill_bookkeeping_t *trill_info;
   1131     int idx=0, num_vp=0, num_ipmc=0;
   1132 #ifdef BCM_WARM_BOOT_SUPPORT
   1133     uint8 *trill_state = 0;
   1134     soc_scache_handle_t scache_handle;
   1135     int  rv = BCM_E_NONE, alloc_sz = 0;
   1136 #endif /* BCM_WARM_BOOT_SUPPORT */
   1137 
   1138     if (!L3_INFO(unit)->l3_initialized) {
   1139         LOG_ERROR(BSL_LS_BCM_TRILL,
   1140                   (BSL_META_U(unit,
   1141                               "L3 module must be initialized prior to TRILL_init\n")));
   1142         return BCM_E_CONFIG;
   1143     }
   1144 
   1145     /* Allocate BK Info */
   1146     BCM_IF_ERROR_RETURN(bcm_td_trill_allocate_bk(unit));
   1147     trill_info = TRILL_INFO(unit);
   1148 
   1149     /*
   1150      * allocate resources
   1151      */
   1152     if (trill_info->initialized) {
   1153         BCM_IF_ERROR_RETURN(bcm_td_trill_cleanup(unit));
   1154         BCM_IF_ERROR_RETURN(bcm_td_trill_allocate_bk(unit));
   1155         trill_info = TRILL_INFO(unit);
   1156     }
   1157 
   1158     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   1159     num_ipmc = soc_mem_index_count(unit, L3_IPMCm);
   1160 
   1161     trill_info->rBridge =
   1162         sal_alloc(sizeof(bcm_trill_name_t) * num_vp, "trill rBridge store");
   1163     if (trill_info->rBridge == NULL) {
   1164         _bcm_td_trill_free_resource(unit);
   1165         return BCM_E_MEMORY;
   1166     }
   1167 
   1168     trill_info->multicast_count =
   1169         sal_alloc(sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc, "trill multicast store");
   1170     if (trill_info->multicast_count == NULL) {
   1171         _bcm_td_trill_free_resource(unit);
   1172         return BCM_E_MEMORY;
   1173     }
   1174 
   1175 
   1176     /* Create Trill protection mutex. */
   1177     trill_info->trill_mutex = sal_mutex_create("trill_mutex");
   1178     if (!trill_info->trill_mutex) {
   1179          _bcm_td_trill_free_resource(unit);
   1180          return BCM_E_MEMORY;
   1181     }
   1182 
   1183     for (idx=0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) {
   1184          trill_info->rootBridge[idx] = 0;
   1185     }
   1186 
   1187     sal_memset(trill_info->rBridge, 0, sizeof(bcm_trill_name_t) * num_vp);
   1188     sal_memset(trill_info->multicast_count, 0, sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc);
   1189 
   1190 #ifdef BCM_WARM_BOOT_SUPPORT
   1191     if (SOC_WARM_BOOT(unit)) {
   1192         if (BCM_FAILURE(_bcm_td_trill_reinit(unit))) {
   1193             _bcm_td_trill_free_resource(unit);
   1194         }
   1195     } else { /* Coldboot */
   1196         alloc_sz = sizeof(_bcm_td_trill_multicast_count_t) * num_ipmc;   
   1197         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRILL, 0);
   1198         if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1199             rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   1200                                          alloc_sz, &trill_state, 
   1201                                          BCM_WB_DEFAULT_VERSION, NULL);
   1202             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1203                 return rv;
   1204             }
   1205         }
   1206     }
   1207 #endif /* BCM_WARM_BOOT_SUPPORT */
   1208 
   1209     /* Mark the state as initialized */
   1210     trill_info->initialized = TRUE;
   1211 
   1212     return BCM_E_NONE;
   1213 }
   1214 
   1215 /*
   1216  * Function:
   1217  *      _bcm_td_trill_hw_clear
   1218  * Purpose:
   1219  *     Perform hw tables clean up for Trill module. 
   1220  * Parameters:
   1221  *      unit     - Device Number
   1222  * Returns:
   1223  *      BCM_E_XXX
   1224  */
   1225  
   1226 STATIC int
   1227 _bcm_td_trill_hw_clear(int unit)
   1228 {
   1229     int rv = BCM_E_NONE, rv_error = BCM_E_NONE;
   1230     bcm_port_t    port;
   1231     bcm_trill_stat_t stat;
   1232 
   1233     if (!SOC_HW_RESET(unit)) {
   1234         PBMP_E_ITER(unit, port) {
   1235             if (SOC_IS_STACK_PORT(unit, port)) {
   1236                 continue;
   1237             }
   1238             for (stat=bcmTrillInPkts; stat < bcmTrillErrorPkts; stat++) {
   1239                 rv = bcm_td_trill_stat_clear(unit, port, stat);
   1240                 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   1241                     rv_error = rv;
   1242                 }
   1243             }
   1244         }
   1245 
   1246         PBMP_HG_ITER(unit, port) {
   1247             if (SOC_IS_STACK_PORT(unit, port)) {
   1248                 continue;
   1249             }
   1250             for (stat=bcmTrillInPkts; stat < bcmTrillErrorPkts; stat++) {
   1251                 rv = bcm_td_trill_stat_clear(unit, port, stat);
   1252                 if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   1253                     rv_error = rv;
   1254                 }
   1255             }
   1256         }
   1257     }
   1258 
   1259     rv = bcm_td_trill_port_delete_all(unit);
   1260     if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   1261         rv_error = rv;
   1262     }
   1263     if (!SOC_HW_RESET(unit)) {
   1264         rv = bcm_td_trill_multicast_source_delete_all(unit);
   1265         if (BCM_FAILURE(rv) && (BCM_E_NONE == rv_error)) {
   1266             rv_error = rv;
   1267         }
   1268     }
   1269 
   1270     return rv_error;
   1271 }
   1272 
   1273 /*
   1274  * Function:
   1275  *      bcm_td_trill_cleanup
   1276  * Purpose:
   1277  *      DeInit  the Trill software module
   1278  * Parameters:
   1279  *      unit     - Device Number
   1280  * Returns:
   1281  *      BCM_E_XXX
   1282  */
   1283 
   1284 int
   1285 bcm_td_trill_cleanup(int unit)
   1286 {
   1287     _bcm_td_trill_bookkeeping_t *trill_info;
   1288     int rv = BCM_E_UNAVAIL;
   1289 
   1290     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   1291          return BCM_E_UNIT;
   1292     }
   1293 
   1294     trill_info = TRILL_INFO(unit);
   1295 
   1296     if (FALSE == trill_info->initialized) {
   1297         return (BCM_E_NONE);
   1298     } 
   1299 
   1300     rv = bcm_td_trill_lock (unit);
   1301     if (BCM_FAILURE(rv)) {
   1302         return rv;
   1303     }
   1304 
   1305     if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 
   1306         rv = _bcm_td_trill_hw_clear(unit);
   1307     }
   1308 
   1309     /* Mark the state as uninitialized */
   1310     trill_info->initialized = FALSE;
   1311 
   1312     sal_mutex_give(trill_info->trill_mutex);
   1313 
   1314     /* Destroy protection mutex. */
   1315     sal_mutex_destroy(trill_info->trill_mutex );
   1316 
   1317     /* Free software resources */
   1318     (void) _bcm_td_trill_free_resource(unit);
   1319 
   1320     return rv;
   1321 }
   1322 
   1323 /*
   1324  * Function:
   1325  *		_bcm_td_trill_tree_profile_set
   1326  * Purpose:
   1327  *		Set TRILL Tree Profile
   1328  * Parameters:
   1329  *   IN :  Unit
   1330  *   IN :  trill_name
   1331  *   IN :  hopcount
   1332  *   OUT: trill_tree_profile_idx
   1333  * Returns:
   1334  *		BCM_E_XXX
   1335  */
   1336 
   1337 int
   1338 _bcm_td_trill_tree_profile_set (int unit, bcm_trill_name_t trill_name, int hopcount, uint8 *trill_tree_profile_idx)
   1339 {
   1340     _bcm_td_trill_bookkeeping_t *trill_info;
   1341     egr_trill_tree_profile_entry_t  egr_trill_profile;
   1342     int rv=BCM_E_UNAVAIL;
   1343     uint8 idx=0;
   1344 
   1345     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   1346          return BCM_E_UNIT;
   1347     }
   1348 
   1349     if ((hopcount < 0) || (hopcount > 63)) {
   1350          return BCM_E_PARAM;
   1351     }
   1352 
   1353     trill_info = TRILL_INFO(unit);
   1354 
   1355     /* Check if root already exists */
   1356     for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) {
   1357         if (trill_info->rootBridge[idx] == trill_name) {
   1358               *trill_tree_profile_idx = idx;
   1359               break;
   1360          }
   1361     }
   1362 
   1363     /* Root does not exist, Check for free entry */
   1364     if (idx == BCM_MAX_NUM_TRILL_TREES) {
   1365         for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) {
   1366             if (trill_info->rootBridge[idx] == 0) {
   1367                   *trill_tree_profile_idx = idx;
   1368                   break;
   1369              }
   1370         }
   1371     }
   1372 
   1373     if (idx == BCM_MAX_NUM_TRILL_TREES) {
   1374          return  BCM_E_RESOURCE;
   1375     }
   1376     trill_info->rootBridge[*trill_tree_profile_idx] = trill_name;
   1377 
   1378     sal_memset(&egr_trill_profile, 0, sizeof(egr_trill_tree_profile_entry_t));	
   1379     soc_mem_field32_set(unit, EGR_TRILL_TREE_PROFILEm, &egr_trill_profile,
   1380                                             ROOT_RBRIDGE_NICKNAMEf, trill_name);
   1381     soc_mem_field32_set(unit, EGR_TRILL_TREE_PROFILEm, &egr_trill_profile,
   1382                                             HOPCOUNTf, hopcount);
   1383     rv = soc_mem_write(unit, EGR_TRILL_TREE_PROFILEm,
   1384                                             MEM_BLOCK_ALL, *trill_tree_profile_idx, &egr_trill_profile);
   1385 
   1386     return rv;
   1387 }
   1388 
   1389 /*
   1390  * Function:
   1391  *		_bcm_td_trill_tree_profile_reset
   1392  * Purpose:
   1393  *		Reset TRILL Tree Profile
   1394  * Parameters:
   1395  *   IN :  Unit
   1396  *   IN :  trill_Rbridge_nickname
   1397  * Returns:
   1398  *		BCM_E_XXX
   1399  */
   1400 
   1401 int
   1402 _bcm_td_trill_tree_profile_reset (int unit, bcm_trill_name_t trill_name)
   1403 {
   1404     _bcm_td_trill_bookkeeping_t *trill_info;
   1405     egr_trill_tree_profile_entry_t  egr_trill_profile;
   1406     uint8 idx=0;
   1407     int rv=BCM_E_UNAVAIL;
   1408 
   1409     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   1410          return BCM_E_UNIT;
   1411     }
   1412 
   1413     trill_info = TRILL_INFO(unit);
   1414 
   1415     for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) {
   1416          if (trill_info->rootBridge[idx] == trill_name) {
   1417               trill_info->rootBridge[idx] = 0;
   1418               sal_memset(&egr_trill_profile, 0, sizeof(egr_trill_tree_profile_entry_t));  
   1419               rv = soc_mem_write(unit, EGR_TRILL_TREE_PROFILEm,
   1420                                                  MEM_BLOCK_ALL, 
   1421                                                  idx, &egr_trill_profile);
   1422               return rv;
   1423          }
   1424     }
   1425     return BCM_E_NONE;
   1426 }
   1427 
   1428 /*
   1429  * Function:
   1430  *		bcm_td_trill_tree_profile_get
   1431  * Purpose:
   1432  *		Get TRILL Tree Profile index from trill_name
   1433  * Parameters:
   1434  *   IN :  Unit
   1435  *   IN :  trill_tree_profile_idx
   1436  * Returns:
   1437  *		BCM_E_XXX
   1438  */
   1439 
   1440 void
   1441 bcm_td_trill_tree_profile_get (int unit, bcm_trill_name_t trill_name, uint8 *trill_tree_profile_idx)
   1442 {
   1443     _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit);
   1444     uint8 idx=0;
   1445 
   1446     for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) {
   1447          if (trill_info->rootBridge[idx] == trill_name) {
   1448               *trill_tree_profile_idx = idx;
   1449               break;
   1450          }
   1451     }
   1452     if (idx == BCM_MAX_NUM_TRILL_TREES) {
   1453          *trill_tree_profile_idx = BCM_MAX_NUM_TRILL_TREES;
   1454     }
   1455 }
   1456 
   1457 
   1458 /*
   1459  * Function:
   1460  *         bcm_td_trill_root_name_get
   1461  * Purpose:
   1462  *		Get TRILL Root name from Tree Profile
   1463  * Parameters:
   1464  *   IN :  Unit
   1465  *   IN :  trill_tree_profile_idx
   1466  *   OUT:  trill_name
   1467  * Returns:
   1468  *		BCM_E_XXX
   1469  */
   1470 
   1471 void
   1472 bcm_td_trill_root_name_get (int unit, uint8 trill_tree_profile_idx, bcm_trill_name_t *trill_name)
   1473 {
   1474     _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit);
   1475 
   1476      *trill_name = trill_info->rootBridge[trill_tree_profile_idx];
   1477 }
   1478 
   1479 /*
   1480  * Function:
   1481  *      _bcm_td_trill_port_resolve
   1482  * Purpose:
   1483  *      Get the modid, port, trunk values for TRILL port
   1484  * Parameters:
   1485  *   IN  :  Unit
   1486  *   IN  :  trill_port_id
   1487  *   IN  :  encap_id
   1488  *  OUT:  module_id
   1489  *  OUT:  port
   1490  *  OUT:  trunk_id
   1491  *  OUT:  vp
   1492  * Returns:
   1493  *      BCM_E_XXX
   1494  */
   1495 int
   1496 _bcm_td_trill_port_resolve(int unit, bcm_gport_t trill_port_id, 
   1497                           bcm_if_t encap_id, bcm_module_t *modid, 
   1498                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id)
   1499 
   1500 {
   1501     int rv = BCM_E_NONE;
   1502     int ecmp=0, nh_index=0, nh_ecmp_index=0, vp=0;
   1503     ing_l3_next_hop_entry_t ing_nh;
   1504     egr_l3_next_hop_entry_t egr_nh;
   1505     ing_dvp_table_entry_t dvp;
   1506     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry. */
   1507     int  idx=0, max_ent_count=0, base_idx=0;
   1508     BCM_IF_ERROR_RETURN(_bcm_trill_check_init (unit));
   1509 
   1510     if (!BCM_GPORT_IS_TRILL_PORT(trill_port_id)) {
   1511         return (BCM_E_BADID);
   1512     }
   1513 
   1514     vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port_id);
   1515     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   1516         return BCM_E_NOT_FOUND;
   1517     }
   1518     BCM_IF_ERROR_RETURN(
   1519          READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   1520     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   1521     if (!ecmp) {
   1522          nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   1523                                        NEXT_HOP_INDEXf);
   1524 
   1525          if (nh_index == 0) { /* Local My RBridge */
   1526             BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, modid));
   1527          } else if (nh_index > 0) {
   1528             BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   1529                                       nh_index, &ing_nh));
   1530 
   1531             if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) {
   1532                  /* Entry type is not  TRILL DVP  */
   1533                  return BCM_E_NOT_FOUND;
   1534             }
   1535             if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   1536                  *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   1537             } else {
   1538                  /* Only add this to replication set if destination is local */
   1539                 *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   1540                 *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   1541             }
   1542          }
   1543     } else {
   1544          /* Select the desired nhop from ECMP group - pointed by encap_id */
   1545          nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   1546 
   1547          BCM_IF_ERROR_RETURN(
   1548              _bcm_xgs3_l3_ecmp_grp_info_get(unit, nh_ecmp_index,
   1549                                             &max_ent_count, &base_idx));
   1550 
   1551         if(encap_id == -1) {
   1552               BCM_IF_ERROR_RETURN(
   1553                    soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 
   1554                         base_idx, hw_buf));
   1555               nh_index = soc_mem_field32_get(unit, L3_ECMPm, 
   1556                    hw_buf, NEXT_HOP_INDEXf);
   1557 
   1558               /* Multipath group should have at least one member.
   1559                * If not then nh_index points to black hole for which
   1560                * index to ING_L3_NEXT_HOPm is not valid.
   1561                */
   1562               if ((max_ent_count > 0) && nh_index) {
   1563                    BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   1564                      MEM_BLOCK_ANY, nh_index, &egr_nh));
   1565                    BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm,
   1566                           MEM_BLOCK_ANY, nh_index, &ing_nh));
   1567 
   1568                    if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh,
   1569                                ENTRY_TYPEf) != 0x2) {
   1570                           /* Entry type is not  TRILL DVP  */
   1571                           return BCM_E_NOT_FOUND;
   1572                    }
   1573                    if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   1574                        *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   1575                    } else {
   1576                        /* Only add this to replication set if destination is local */
   1577                        *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   1578                        *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   1579                   }
   1580               }
   1581         } else {
   1582             for (idx = 0; idx < max_ent_count; idx++) {
   1583               BCM_IF_ERROR_RETURN(
   1584                    soc_mem_read(unit, L3_ECMPm, MEM_BLOCK_ANY, 
   1585                         (base_idx+idx), hw_buf));
   1586               nh_index = soc_mem_field32_get(unit, L3_ECMPm, 
   1587                    hw_buf, NEXT_HOP_INDEXf);
   1588               BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
   1589                    MEM_BLOCK_ANY, nh_index, &egr_nh));
   1590               if (encap_id == soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 
   1591                                                &egr_nh, INTF_NUMf)) {
   1592                  BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   1593                         MEM_BLOCK_ANY, nh_index, &ing_nh));
   1594 
   1595                  if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, 
   1596                              ENTRY_TYPEf) != 0x2) {
   1597                         /* Entry type is not  TRILL DVP  */
   1598                         return BCM_E_NOT_FOUND;
   1599                  }
   1600                  if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   1601                      *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   1602                  } else {
   1603                      /* Only add this to replication set if destination is local */
   1604                      *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   1605                      *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   1606                 }
   1607                 break;
   1608               }
   1609             }
   1610         }
   1611     }
   1612 
   1613     *id = vp;
   1614     return rv;
   1615 }
   1616 
   1617 /*
   1618  * Function:
   1619  *      _bcm_td_trill_port_cnt_update
   1620  * Purpose:
   1621  *      Update port's VP count.
   1622  * Parameters:
   1623  *      unit  - (IN) SOC unit number. 
   1624  *      gport - (IN) GPORT ID.
   1625  *      vp    - (IN) Virtual port number.
   1626  *      incr  - (IN) If TRUE, increment VP count, else decrease VP count.
   1627  * Returns:
   1628  *      BCM_X_XXX
   1629  */
   1630 
   1631 STATIC int
   1632 _bcm_td_trill_port_cnt_update(int unit, bcm_gport_t gport,
   1633         int vp, int incr_decr_flag)
   1634 {
   1635     int mod_out=-1, port_out=-1, tgid_out=-1, vp_out=-1;
   1636     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
   1637     int local_member_count=0;
   1638     int idx=-1;
   1639     int mod_local=-1;
   1640     _bcm_port_info_t *port_info;
   1641     uint32 port_flags;
   1642 
   1643     BCM_IF_ERROR_RETURN
   1644         (_bcm_esw_gport_resolve(unit, gport, &mod_out, &port_out, &tgid_out,
   1645                                 &vp_out));
   1646 
   1647     if (vp_out == -1) {
   1648        return BCM_E_PARAM;
   1649     }
   1650 
   1651     /* Update the physical port's SW state. If associated with a trunk,
   1652      * update each local physical port's SW state.
   1653      */
   1654 
   1655     if (BCM_TRUNK_INVALID != tgid_out) {
   1656 
   1657         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 
   1658                     SOC_MAX_NUM_PORTS, local_member_array, &local_member_count));
   1659 
   1660         for (idx = 0; idx < local_member_count; idx++) {
   1661             _bcm_port_info_access(unit, local_member_array[idx], &port_info);
   1662             if (incr_decr_flag) {
   1663                 port_info->vp_count++;
   1664             } else {
   1665                 port_info->vp_count--;
   1666             }
   1667             BCM_IF_ERROR_RETURN(
   1668                 bcm_esw_port_vlan_member_get(
   1669                     unit, local_member_array[idx], &port_flags));
   1670             BCM_IF_ERROR_RETURN(
   1671                 bcm_esw_port_vlan_member_set(
   1672                     unit, local_member_array[idx], port_flags));
   1673         }
   1674     } else {
   1675         if (-1 == port_out) {
   1676             return BCM_E_NONE;
   1677         }
   1678 
   1679         BCM_IF_ERROR_RETURN
   1680             (_bcm_esw_modid_is_local(unit, mod_out, &mod_local));
   1681         if (mod_local) {
   1682             if (soc_feature(unit, soc_feature_sysport_remap)) { 
   1683                 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 
   1684             }
   1685             _bcm_port_info_access(unit, port_out, &port_info);
   1686             if (incr_decr_flag) {
   1687                 port_info->vp_count++;
   1688             } else {
   1689                 port_info->vp_count--;
   1690             }
   1691             BCM_IF_ERROR_RETURN(
   1692                 bcm_esw_port_vlan_member_get(
   1693                     unit, port_out, &port_flags));
   1694             BCM_IF_ERROR_RETURN(
   1695                 bcm_esw_port_vlan_member_set(
   1696                     unit, port_out, port_flags));
   1697         }
   1698     }
   1699 
   1700     return BCM_E_NONE;
   1701 }
   1702 
   1703 
   1704 /*
   1705  * Function:
   1706  *		_bcm_td_trill_transit_entry_key_set
   1707  * Purpose:
   1708  *		Set TRILL Transit forwarding entry key
   1709  * Parameters:
   1710  *		IN :  Unit
   1711  *  IN :  trill_port
   1712  *  IN : next_hop / ecmp group index
   1713  *  IN : MPLS entry pointer
   1714  * Returns:
   1715  *		BCM_E_XXX
   1716  */
   1717 
   1718 
   1719 STATIC void
   1720 _bcm_td_trill_transit_entry_key_set(int unit, bcm_trill_port_t *trill_port,
   1721                                          int nh_ecmp_index, mpls_entry_entry_t   *tr_ent, int clean_flag)
   1722 {
   1723 
   1724     if (clean_flag) {
   1725          sal_memset(tr_ent, 0, sizeof(mpls_entry_entry_t));
   1726     }
   1727 
   1728     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1729                                          KEY_TYPEf, 0x5);
   1730     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1731                                          TRILL__RBRIDGE_NICKNAMEf, trill_port->name);
   1732     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1733                                          TRILL__CLASS_IDf, trill_port->if_class);
   1734     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1735                                          TRILL__DECAP_TRILL_TUNNELf, 0x0);
   1736     if (trill_port->flags & _BCM_TRILL_PORT_MULTIPATH) {
   1737          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1738                                          TRILL__ECMPf, 0x1);
   1739          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1740                                          TRILL__ECMP_PTRf, nh_ecmp_index);
   1741     } else {
   1742          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1743                                          TRILL__ECMPf, 0x0);
   1744          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1745                                          TRILL__NEXT_HOP_INDEXf, nh_ecmp_index);
   1746     }
   1747     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__UCAST_DST_DISCARDf)) { 
   1748         if ((trill_port->flags & BCM_TRILL_PORT_DROP) ||
   1749             !(trill_port->flags & BCM_TRILL_PORT_NETWORK)) {
   1750               soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1751                                          TRILL__UCAST_DST_DISCARDf, 0x1);
   1752         } else if (trill_port->flags & BCM_TRILL_PORT_NETWORK) {
   1753               soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1754                                          TRILL__UCAST_DST_DISCARDf, 0x0);
   1755         }
   1756     }
   1757     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__DST_COPY_TO_CPUf) && 
   1758         (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) {
   1759          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1760                                          TRILL__DST_COPY_TO_CPUf, 0x1);
   1761     }
   1762     /* Multicast-traffic discard setting */
   1763     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) {
   1764         if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) {
   1765             soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1766                                      TRILL__MCAST_DST_DISCARDf, 0x0);
   1767         } else {
   1768             soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1769                                      TRILL__MCAST_DST_DISCARDf, 0x1);
   1770         }
   1771     }
   1772 
   1773     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1774                                          VALIDf, 0x1);
   1775 }
   1776 
   1777 
   1778 /*
   1779  * Function:
   1780  *      _bcm_td_trill_transit_entry_set
   1781  * Purpose:
   1782  *     Set TRILL Transit forwarding entry
   1783  * Parameters:
   1784  *      IN :  Unit
   1785  *      IN :  trill_port
   1786  *      IN : next_hop / ecmp group index
   1787  * Returns:
   1788  *      BCM_E_XXX
   1789  */
   1790 
   1791 STATIC int
   1792 _bcm_td_trill_transit_entry_set(int unit, bcm_trill_port_t *trill_port,
   1793                                          int nh_ecmp_index)
   1794 {
   1795     int rv = BCM_E_NONE;
   1796     int index=0;
   1797     mpls_entry_entry_t  key_ent;
   1798     mpls_entry_entry_t  return_ent;
   1799 
   1800     _bcm_td_trill_transit_entry_key_set(unit, trill_port, 
   1801                         nh_ecmp_index, &key_ent, 1);
   1802 
   1803     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   1804                         &key_ent, &return_ent, 0);
   1805     if (rv == SOC_E_NONE) {
   1806          (void) _bcm_td_trill_transit_entry_key_set(unit, trill_port, 
   1807                                   nh_ecmp_index, &return_ent, 0);
   1808          rv = soc_mem_write(unit, MPLS_ENTRYm,
   1809                                   MEM_BLOCK_ALL, index,
   1810                                   &return_ent);
   1811     } else if (rv != SOC_E_NOT_FOUND) {
   1812         return rv;
   1813     } else {
   1814          rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &key_ent);
   1815     }
   1816     return rv;
   1817 }
   1818 
   1819 /*
   1820  * Function:
   1821  *		_bcm_td_trill_transit_entry_reset
   1822  * Purpose:
   1823  *		Reset TRILL Transit forwarding entry
   1824  * Parameters:
   1825  *		IN :  Unit
   1826  *  IN :  vp
   1827  *  IN : next_hop / ecmp group index
   1828  *  IN : ecmp flag
   1829  * Returns:
   1830  *		BCM_E_XXX
   1831  */
   1832 
   1833 STATIC int
   1834 _bcm_td_trill_transit_entry_reset(int unit, int vp, int nh_ecmp_idx, int ecmp)
   1835 {
   1836     int rv = BCM_E_UNAVAIL;
   1837     int index=0;
   1838     bcm_trill_name_t rb_name;      /* Destination RBridge Nickname. */
   1839     int if_class;               /* Interface class ID. */
   1840     mpls_entry_entry_t  tr_ent;
   1841     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   1842     source_vp_entry_t svp;
   1843 
   1844     sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t));
   1845  
   1846     BCM_IF_ERROR_RETURN(
   1847          soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   1848                                          MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
   1849 
   1850     rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   1851                                          EGRESS_RBRIDGE_NICKNAMEf);
   1852 
   1853     BCM_IF_ERROR_RETURN(
   1854          soc_mem_read(unit, SOURCE_VPm,
   1855                                          MEM_BLOCK_ALL, vp, &svp));
   1856 
   1857     if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf);
   1858 
   1859 
   1860     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1861                                       KEY_TYPEf, 0x5);
   1862     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1863                                       TRILL__RBRIDGE_NICKNAMEf, rb_name);
   1864     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1865                                       TRILL__CLASS_IDf, if_class);
   1866     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1867                                       TRILL__DECAP_TRILL_TUNNELf, 0x0);
   1868     if (ecmp) {
   1869       soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1870                                       TRILL__ECMPf, 0x1);
   1871       soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1872                                       TRILL__ECMP_PTRf, nh_ecmp_idx);
   1873     } else {
   1874       soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1875                                       TRILL__NEXT_HOP_INDEXf, nh_ecmp_idx);
   1876     }
   1877     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   1878                                       VALIDf, 0x1);
   1879     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   1880                      &tr_ent, &tr_ent, 0);
   1881     if (rv < 0) {
   1882          return rv;
   1883     }
   1884     /* Delete the entry from HW */
   1885     rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent);
   1886     return rv;
   1887 }
   1888 
   1889 /*
   1890  * Function:
   1891  *		_bcm_td_trill_learn_entry_key_set
   1892  * Purpose:
   1893  *		Set TRILL learn entry key
   1894  * Parameters:
   1895  *		IN :  Unit
   1896  *  IN :  trill_port
   1897  *  IN :  VP
   1898  *  IN : MPLS entry pointer
   1899  * Returns:
   1900  *		BCM_E_XXX
   1901  */
   1902 
   1903 STATIC void
   1904  _bcm_td_trill_learn_entry_key_set(int unit, bcm_trill_port_t *trill_port,
   1905                                           int vp, mpls_entry_entry_t   *tr_ent, int clean_flag)
   1906  {
   1907     uint8 trill_tree_id=0;
   1908 
   1909     if (clean_flag) {
   1910          sal_memset(tr_ent, 0, sizeof(mpls_entry_entry_t));
   1911     }
   1912 
   1913     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1914                                          KEY_TYPEf, 0x5);
   1915     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1916                                          TRILL__RBRIDGE_NICKNAMEf, trill_port->name);
   1917     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1918                                          TRILL__CLASS_IDf, trill_port->if_class);
   1919     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1920                                          TRILL__VIRTUAL_PORTf, vp);
   1921     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1922                                          TRILL__PHB_FROM_OUTER_L2_HEADERf, 0x1);
   1923     if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) {
   1924          (void) bcm_td_trill_tree_profile_get (unit, trill_port->name, &trill_tree_id);
   1925           if (trill_tree_id < BCM_MAX_NUM_TRILL_TREES) {
   1926                soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1927                                          TRILL__TREE_IDf, trill_tree_id);
   1928           }
   1929     }
   1930     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__SRC_DISCARDf) && 
   1931         (trill_port->flags & BCM_TRILL_PORT_DROP)) {
   1932          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1933                                          TRILL__SRC_DISCARDf, 0x1);
   1934     }
   1935     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__SRC_COPY_TO_CPUf) && 
   1936         (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) {
   1937          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1938                                          TRILL__SRC_COPY_TO_CPUf, 0x1);
   1939     }
   1940     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   1941                                          VALIDf, 0x1);
   1942  }
   1943 
   1944 /*
   1945  * Function:
   1946  *		_bcm_td_trill_learn_entry_set
   1947  * Purpose:
   1948  *		Set TRILL  Learn Entry 
   1949  * Parameters:
   1950  *		IN :  Unit
   1951  *  IN :  trill_port
   1952  *  IN : vp
   1953  * Returns:
   1954  *		BCM_E_XXX
   1955  */
   1956 
   1957 STATIC int
   1958 _bcm_td_trill_learn_entry_set(int unit, bcm_trill_port_t *trill_port, int vp)
   1959 {
   1960     mpls_entry_entry_t  key_ent;
   1961     mpls_entry_entry_t  return_ent;
   1962     int rv = BCM_E_UNAVAIL;
   1963     int index;
   1964 
   1965     _bcm_td_trill_learn_entry_key_set(unit, trill_port, vp, &key_ent, 1);
   1966 
   1967     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   1968                         &key_ent, &return_ent, 0);
   1969 
   1970     if (rv == SOC_E_NONE) {
   1971          (void) _bcm_td_trill_learn_entry_key_set(unit, trill_port, vp, &return_ent, 0);
   1972          rv = soc_mem_write(unit, MPLS_ENTRYm,
   1973                                            MEM_BLOCK_ALL, index,
   1974                                            &return_ent);
   1975     } else if (rv != SOC_E_NOT_FOUND) {
   1976         return rv;
   1977     } else {
   1978          rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &key_ent);
   1979     }
   1980 
   1981     return rv;
   1982 }
   1983 
   1984 /*
   1985  * Function:
   1986  *		_bcm_td_trill_learn_entry_reset
   1987  * Purpose:
   1988  *		Reset TRILL RPF entry
   1989  * Parameters:
   1990  *		IN :  Unit
   1991  *  IN :  vp
   1992  * Returns:
   1993  *		BCM_E_XXX
   1994  */
   1995 
   1996 STATIC int
   1997 _bcm_td_trill_learn_entry_reset(int unit, int vp)
   1998 {
   1999     int rv = BCM_E_UNAVAIL;
   2000     int index=0;
   2001     bcm_trill_name_t rb_name;      /* Destination RBridge Nickname. */
   2002     int if_class;               /* Interface class ID. */
   2003     mpls_entry_entry_t  tr_ent;
   2004     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   2005     source_vp_entry_t svp;
   2006 
   2007     sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t));
   2008 
   2009     BCM_IF_ERROR_RETURN(
   2010          soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   2011                              MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
   2012 
   2013     rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   2014                              EGRESS_RBRIDGE_NICKNAMEf);
   2015 
   2016     BCM_IF_ERROR_RETURN(
   2017          soc_mem_read(unit, SOURCE_VPm,
   2018                              MEM_BLOCK_ALL, vp, &svp));
   2019 
   2020     if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf);
   2021 
   2022     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2023                              KEY_TYPEf, 0x5);
   2024     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2025                              TRILL__RBRIDGE_NICKNAMEf, rb_name);
   2026     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2027                              TRILL__CLASS_IDf, if_class);
   2028     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2029                              TRILL__VIRTUAL_PORTf, vp);
   2030     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2031                              TRILL__PHB_FROM_OUTER_L2_HEADERf, 0x1);
   2032     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2033                              VALIDf, 0x1);
   2034 
   2035     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   2036                              &tr_ent, &tr_ent, 0);
   2037     if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
   2038          return rv;
   2039     }
   2040     /* Delete the entry from HW */
   2041     rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent);
   2042     
   2043     if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
   2044        return rv;
   2045     } else {
   2046        return BCM_E_NONE;
   2047     }
   2048 }
   2049 
   2050 
   2051 /*
   2052  * Function:
   2053  *		_bcm_td_trill_decap_entry_key_set
   2054  * Purpose:
   2055  *		Set TRILL Decap entry key
   2056  * Parameters:
   2057  *		IN :  Unit
   2058  *  IN :  trill_port
   2059  *  IN :  VP
   2060  *  IN : MPLS entry pointer
   2061  * Returns:
   2062  *		BCM_E_XXX
   2063  */
   2064 
   2065 STATIC void
   2066  _bcm_td_trill_decap_entry_key_set(int unit, bcm_trill_port_t *trill_port,
   2067                                           mpls_entry_entry_t   *tr_ent, int clean_flag)
   2068  {
   2069     if (clean_flag) {
   2070        sal_memset(tr_ent, 0, sizeof(mpls_entry_entry_t));
   2071     }
   2072 
   2073     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2074                                          KEY_TYPEf, 0x5);
   2075     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2076                                          TRILL__RBRIDGE_NICKNAMEf, trill_port->name);
   2077     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2078                                          TRILL__DECAP_TRILL_TUNNELf, 0x1);
   2079     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2080                                          TRILL__CLASS_IDf, trill_port->if_class);
   2081     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__UCAST_DST_DISCARDf)) { 
   2082        if ((trill_port->flags & BCM_TRILL_PORT_DROP) ||
   2083             !(trill_port->flags & BCM_TRILL_PORT_NETWORK)) {
   2084               soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2085                                          TRILL__UCAST_DST_DISCARDf, 0x1);
   2086        } else if (trill_port->flags & BCM_TRILL_PORT_NETWORK) {
   2087               soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2088                                          TRILL__UCAST_DST_DISCARDf, 0x0);
   2089         }
   2090     }
   2091     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__DST_COPY_TO_CPUf) && 
   2092         (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) {
   2093          soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2094                                          TRILL__DST_COPY_TO_CPUf, 0x1);
   2095     }
   2096     /* Multicast-traffic discard setting */
   2097     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) {
   2098         if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) {
   2099             soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2100                                      TRILL__MCAST_DST_DISCARDf, 0x0);
   2101         } else {
   2102             soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2103                                      TRILL__MCAST_DST_DISCARDf, 0x1);
   2104         }
   2105     }
   2106     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   2107                                          VALIDf, 0x1);
   2108  }
   2109 
   2110 /*
   2111  * Function:
   2112  *           _bcm_td_trill_decap_entry_set
   2113  * Purpose:
   2114  *           Set TRILL  Decap  Entry 
   2115  * Parameters:
   2116  *           IN :  Unit
   2117  *  IN :  trill_port
   2118  * Returns:
   2119  *           BCM_E_XXX
   2120  */
   2121 
   2122 STATIC int
   2123 _bcm_td_trill_decap_entry_set(int unit, bcm_trill_port_t *trill_port)
   2124 {
   2125     mpls_entry_entry_t  tr_ent;
   2126     int rv = BCM_E_UNAVAIL;
   2127     int index=0;
   2128     mpls_entry_entry_t  return_ent;
   2129 
   2130     _bcm_td_trill_decap_entry_key_set(unit, trill_port, &tr_ent, 1);
   2131 
   2132     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   2133                         &tr_ent, &return_ent, 0);
   2134     if (rv == SOC_E_NONE) {
   2135          (void) _bcm_td_trill_decap_entry_key_set(unit, trill_port, &return_ent, 0);
   2136          rv = soc_mem_write(unit, MPLS_ENTRYm,
   2137                                   MEM_BLOCK_ALL, index,
   2138                                   &return_ent);
   2139     } else if (rv != SOC_E_NOT_FOUND) {
   2140         return rv;
   2141     } else {
   2142         rv = soc_mem_insert(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent);
   2143     }
   2144     return rv;
   2145 }
   2146 
   2147 /*
   2148  * Function:
   2149  *           _bcm_td_trill_decap_entry_reset
   2150  * Purpose:
   2151  *           Reset TRILL Decap entry
   2152  * Parameters:
   2153  *            IN :  Unit
   2154  *  IN :  vp
   2155  * Returns:
   2156  *            BCM_E_XXX
   2157  */
   2158 
   2159 STATIC int
   2160 _bcm_td_trill_decap_entry_reset(int unit,  int vp)
   2161 {
   2162     int rv = BCM_E_UNAVAIL;
   2163     int index=0;
   2164     bcm_trill_name_t rb_name;      /* Destination RBridge Nickname. */
   2165     int if_class=0;               /* Interface class ID. */
   2166     mpls_entry_entry_t  tr_ent;
   2167     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   2168     source_vp_entry_t svp;
   2169  
   2170     sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t));
   2171 
   2172     BCM_IF_ERROR_RETURN(
   2173          soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   2174                          MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
   2175 
   2176     rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   2177                          EGRESS_RBRIDGE_NICKNAMEf);
   2178  
   2179     BCM_IF_ERROR_RETURN(
   2180          soc_mem_read(unit, SOURCE_VPm,
   2181                           MEM_BLOCK_ALL, vp, &svp));
   2182  
   2183     if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf);
   2184  
   2185     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2186                           KEY_TYPEf, 0x5);
   2187     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2188                           TRILL__RBRIDGE_NICKNAMEf, rb_name);
   2189     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2190                           TRILL__CLASS_IDf, if_class);
   2191     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2192                                          TRILL__DECAP_TRILL_TUNNELf, 0x1);
   2193     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   2194                           VALIDf, 0x1);
   2195  
   2196     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   2197                           &tr_ent, &tr_ent, 0);
   2198     if (rv < 0) {
   2199          return rv;
   2200     }
   2201 
   2202     /* Delete the entry from HW */
   2203     rv = soc_mem_delete(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, &tr_ent);
   2204     return rv;
   2205 
   2206 }
   2207 
   2208 
   2209 /*
   2210  * Function:
   2211  *            _bcm_td_trill_ingress_next_hop_set
   2212  * Purpose:
   2213  *           Set ING_L3_NEXT_HOP Entry 
   2214  * Parameters:
   2215  *           IN :  Unit
   2216  *           IN :  nh_index
   2217  *           IN : drop
   2218  * Returns:
   2219  *           BCM_E_XXX
   2220  */
   2221 
   2222 STATIC int
   2223 _bcm_td_trill_next_hop_set(int unit, int nh_index, uint32 flags)
   2224 {
   2225     int rv=BCM_E_NONE;
   2226     ing_l3_next_hop_entry_t ing_nh;
   2227     bcm_port_t   port=0;
   2228     bcm_module_t modid=0, local_modid=0;
   2229     bcm_trunk_t tgid=0;
   2230     int  num_local_ports=0, idx=0;
   2231     int  old_nh_index=-1;
   2232     bcm_port_t   local_ports[SOC_MAX_NUM_PORTS];
   2233     uint32 replace=0;
   2234     int gport;
   2235     replace = flags & BCM_L3_REPLACE;
   2236 
   2237     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   2238                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
   2239     if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) {
   2240          tgid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2241                                             &ing_nh, TGIDf);
   2242          rv = _bcm_trunk_id_validate(unit, tgid);
   2243          if (BCM_FAILURE(rv)) {
   2244             return BCM_E_PORT;
   2245          }
   2246          BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   2247                 SOC_MAX_NUM_PORTS, local_ports, &num_local_ports));
   2248     } else {
   2249         modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2250                                     &ing_nh, MODULE_IDf);
   2251         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid));
   2252         if (modid != local_modid) {
   2253             /* Ignore EGR_PORT_TO_NHI_MAPPINGs */
   2254             return BCM_E_NONE;
   2255         }
   2256          port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2257                                             &ing_nh, PORT_NUMf);
   2258         local_ports[num_local_ports++] = port;
   2259     }
   2260     if (!(flags & BCM_L3_IPMC)) { /* Only for Unicast Nexthops */
   2261         for (idx = 0; idx < num_local_ports; idx++) {
   2262             BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &modid));
   2263             BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]);
   2264             BCM_IF_ERROR_RETURN(
   2265                 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index));
   2266             if (old_nh_index && !replace) {
   2267                if (old_nh_index != nh_index) {
   2268                     /* Limitation: For TD/TR3, 
   2269                     Trill egress port can be configured with one NHI*/
   2270                     return BCM_E_RESOURCE;    
   2271                 }
   2272             } else {
   2273                 BCM_IF_ERROR_RETURN(
   2274                     _bcm_trx_gport_to_nhi_set(unit, gport, nh_index));
   2275             }
   2276         }
   2277         BCM_IF_ERROR_RETURN(
   2278              _bcm_td_trill_adjacency_set(unit, nh_index));
   2279     }
   2280     return rv;
   2281 }
   2282 
   2283 /*
   2284  * Function:
   2285  *		_bcm_td_trill_ingress_next_hop_reset
   2286  * Purpose:
   2287  *		Reset ING_L3_NEXT_HOP Entry 
   2288  * Parameters:
   2289  *		IN :  Unit
   2290  *           IN :  nh_index
   2291  *           IN : drop
   2292  * Returns:
   2293  *		BCM_E_XXX
   2294  */
   2295 
   2296 STATIC int
   2297 _bcm_td_trill_next_hop_reset(int unit, int nh_index)
   2298 {
   2299     int rv=BCM_E_NONE;
   2300     ing_l3_next_hop_entry_t ing_nh;
   2301     bcm_port_t   port=0;
   2302     bcm_module_t modid=0, local_modid=0;
   2303     bcm_trunk_t tgid=0;
   2304     int  num_local_ports=0, idx=0;
   2305     bcm_port_t   local_ports[SOC_MAX_NUM_PORTS];
   2306     int  old_nh_index=-1;
   2307     int  gport;
   2308     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   2309                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
   2310     if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) {
   2311          tgid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2312                                             &ing_nh, TGIDf);
   2313          rv = _bcm_trunk_id_validate(unit, tgid);
   2314          if (BCM_FAILURE(rv)) {
   2315             return BCM_E_PORT;
   2316          }
   2317          BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid,
   2318                 SOC_MAX_NUM_PORTS, local_ports, &num_local_ports));
   2319     } else {
   2320         modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2321                                     &ing_nh, MODULE_IDf);
   2322         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid));
   2323 
   2324         if (modid != local_modid) {
   2325             /* Ignore reset for non local modid */
   2326             return BCM_E_NONE;
   2327         }
   2328         port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2329                                             &ing_nh, PORT_NUMf);
   2330         local_ports[num_local_ports++] = port;
   2331     }
   2332 
   2333     for (idx = 0; idx < num_local_ports; idx++) {
   2334         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &modid));
   2335         BCM_GPORT_MODPORT_SET(gport, modid, local_ports[idx]);
   2336         BCM_IF_ERROR_RETURN(
   2337             _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index));
   2338         if (old_nh_index == nh_index) {
   2339             BCM_IF_ERROR_RETURN(
   2340                 _bcm_trx_gport_to_nhi_set(unit, gport, 0));
   2341         }
   2342     }
   2343     BCM_IF_ERROR_RETURN(
   2344           _bcm_td_trill_adjacency_reset(unit, nh_index));
   2345     return rv;
   2346 }
   2347 
   2348 /*
   2349  * Function:
   2350  *           bcm_td_trill_egress_set
   2351  * Purpose:
   2352  *           Set TRILL NextHop 
   2353  * Parameters:
   2354  *           IN :  Unit
   2355  *           IN :  nh_index
   2356  *           IN :  flags
   2357  * Returns:
   2358  *           BCM_E_XXX
   2359  */
   2360 
   2361 int
   2362 bcm_td_trill_egress_set(int unit, int nh_index, uint32 flags)
   2363 {
   2364     ing_l3_next_hop_entry_t ing_nh;
   2365     int rv=BCM_E_NONE;
   2366 
   2367     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   2368                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
   2369 
   2370     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2371                                   ENTRY_TYPEf, 0x2); /* L2 DVP */
   2372     if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
   2373         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2374                 &ing_nh, MTU_SIZEf, 0x3fff);
   2375     }
   2376 #if defined(BCM_TRIUMPH3_SUPPORT)
   2377     else if (SOC_IS_TRIUMPH3(unit)) {
   2378         /* Set default ING_L3_NEXT_HOP_ATTRIBUTE_1 MTU_SIZE 
   2379          * Note: Assumption that first entry has MTU size of 0x3fff
   2380          */
   2381         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2382                             &ing_nh, DVP_ATTRIBUTE_1_INDEXf, 0);
   2383     }
   2384 #endif /* BCM_TRIUMPH3_SUPPORT */
   2385     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_L3_NEXT_HOPm,
   2386                                   MEM_BLOCK_ALL, nh_index, &ing_nh));
   2387 
   2388     rv = _bcm_td_trill_next_hop_set(unit, nh_index, flags);
   2389     return rv;
   2390 }
   2391 
   2392 /*
   2393  * Function:
   2394  *           bcm_td_trill_egress_reset
   2395  * Purpose:
   2396  *           Reset TRILL NextHop 
   2397  * Parameters:
   2398  *           IN :  Unit
   2399  *           IN :  nh_index
   2400  *           IN :  flags
   2401  * Returns:
   2402  *           BCM_E_XXX
   2403  */
   2404 
   2405 int
   2406 bcm_td_trill_egress_reset(int unit, int nh_index)
   2407 {
   2408     ing_l3_next_hop_entry_t ing_nh;
   2409     int rv=BCM_E_NONE;
   2410 
   2411     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   2412                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
   2413 
   2414     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2415                                   ENTRY_TYPEf, 0x0); /* L2 DVP */
   2416     if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
   2417         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2418                 &ing_nh, MTU_SIZEf, 0x0);
   2419     }
   2420 #if defined(BCM_TRIUMPH3_SUPPORT)
   2421     else if (SOC_IS_TRIUMPH3(unit)) {
   2422         /* Set default ING_L3_NEXT_HOP_ATTRIBUTE_1 MTU_SIZE 
   2423          * Note: Assumption that first entry has MTU size of 0x3fff
   2424          */
   2425         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2426                             &ing_nh, DVP_ATTRIBUTE_1_INDEXf, 0);
   2427     }
   2428 #endif /* BCM_TRIUMPH3_SUPPORT */
   2429     BCM_IF_ERROR_RETURN(soc_mem_write(unit, ING_L3_NEXT_HOPm,
   2430                                   MEM_BLOCK_ALL, nh_index, &ing_nh));
   2431 
   2432     rv = _bcm_td_trill_next_hop_reset(unit, nh_index);
   2433     return rv;
   2434 }
   2435 
   2436 /*
   2437  * Function:
   2438  *           bcm_td_trill_egress_get
   2439  * Purpose:
   2440  *           Get TRILL Egress NextHop 
   2441  * Parameters:
   2442  *           IN :  Unit
   2443  *           IN :  nh_index
   2444  * Returns:
   2445  *           BCM_E_XXX
   2446  */
   2447 
   2448 int
   2449 bcm_td_trill_egress_get(int unit, bcm_l3_egress_t *egr, int nh_index)
   2450 {
   2451     int int_l3_flag;
   2452     int_l3_flag = BCM_XGS3_L3_ENT_FLAG(BCM_XGS3_L3_TBL_PTR(unit, next_hop),
   2453                                        nh_index);
   2454     if (int_l3_flag == _BCM_L3_TRILL_ONLY) {
   2455         egr->flags |= BCM_L3_TRILL_ONLY;
   2456     }
   2457 
   2458     return BCM_E_NONE;
   2459 }
   2460 
   2461 /*
   2462  * Function:
   2463  *     _bcm_td_trill_egress_name_set
   2464  * Purpose:
   2465  *     Set My RBridge Nickname
   2466  * Parameters:
   2467  *   IN :  Unit
   2468  *   IN :  trill_name
   2469  * Returns:
   2470  *   BCM_E_XXX
   2471  */
   2472 
   2473 STATIC int
   2474 _bcm_td_trill_egress_name_set(int unit, bcm_trill_name_t  trill_name)
   2475 {
   2476     egr_trill_rbridge_nicknames_entry_t  egr_name_entry;
   2477     int idx=0;
   2478     bcm_trill_name_t  temp_name;
   2479 
   2480       for(idx=0; idx < 4; idx++) {
   2481          BCM_IF_ERROR_RETURN(
   2482               soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2483                        MEM_BLOCK_ALL, idx, &egr_name_entry));
   2484 
   2485          temp_name = 
   2486               soc_mem_field32_get(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 
   2487                                          &egr_name_entry,
   2488                                          RBRIDGE_NICKNAMEf);
   2489          /* If name exists, return */
   2490          if (temp_name == trill_name) {
   2491              return BCM_E_NONE;
   2492          }
   2493 
   2494          if (!temp_name) {
   2495               soc_mem_field32_set(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, 
   2496                                          &egr_name_entry,
   2497                                          RBRIDGE_NICKNAMEf, trill_name);
   2498 
   2499               BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2500                                             MEM_BLOCK_ALL, idx, &egr_name_entry));
   2501               return BCM_E_NONE;
   2502          }
   2503       }
   2504       return BCM_E_FULL;
   2505 }
   2506 
   2507 /*
   2508  * Function:
   2509  *     _bcm_td_trill_egress_name_reset
   2510  * Purpose:
   2511  *     Reset My RBridge Nickname
   2512  * Parameters:
   2513  *   IN :  Unit
   2514  *   IN :  trill_name
   2515  * Returns:
   2516  *   BCM_E_XXX
   2517  */
   2518 
   2519 STATIC int
   2520 _bcm_td_trill_egress_name_reset(int unit, bcm_trill_name_t trill_name)
   2521 {
   2522   egr_trill_rbridge_nicknames_entry_t egr_name_entry;
   2523   int idx=0;
   2524   bcm_trill_name_t temp_name;
   2525 
   2526   for(idx=0; idx < 4; idx++) {
   2527       BCM_IF_ERROR_RETURN(
   2528            soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2529                     MEM_BLOCK_ALL, idx, &egr_name_entry));
   2530       temp_name =
   2531             soc_mem_field32_get(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2532                                         &egr_name_entry,
   2533                                         RBRIDGE_NICKNAMEf);
   2534       if (temp_name == trill_name) {
   2535             soc_mem_field32_set(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2536                                        &egr_name_entry,
   2537                                        RBRIDGE_NICKNAMEf, 0x0);
   2538 
   2539             BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2540                                           MEM_BLOCK_ALL, idx, &egr_name_entry));
   2541             return BCM_E_NONE;
   2542       }
   2543   }
   2544   return BCM_E_NOT_FOUND;
   2545 } 
   2546 /*
   2547  * Purpose:
   2548  *       Obtain Trill Nickname index from name
   2549  * Parameters:
   2550  *       unit  - Device Number
   2551  *       source_trill_name  - (IN) Trill Root_RBridge
   2552  */
   2553 
   2554 int
   2555 bcm_td_trill_source_trill_name_idx_get(int unit, 
   2556                                                                    bcm_trill_name_t source_trill_name,
   2557                                                                    int *trill_name_index)
   2558 {
   2559     egr_trill_rbridge_nicknames_entry_t  egr_name_entry;
   2560     int idx=0;
   2561 
   2562       for(idx=0; idx < 4; idx++) {
   2563          BCM_IF_ERROR_RETURN(
   2564               soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2565                        MEM_BLOCK_ALL, idx, &egr_name_entry));
   2566 
   2567          if ( source_trill_name ==  soc_mem_field32_get(unit, 
   2568                                          EGR_TRILL_RBRIDGE_NICKNAMESm,
   2569                                          &egr_name_entry,
   2570                                          RBRIDGE_NICKNAMEf) ) {
   2571               *trill_name_index =  idx;
   2572               return BCM_E_NONE;
   2573          }
   2574     }
   2575     return BCM_E_NOT_FOUND;
   2576 
   2577 }
   2578 
   2579 /*
   2580  * Purpose:
   2581  *       Obtain Trill Nickname from index
   2582  * Parameters:
   2583  *       unit  - Device Number
   2584  *       source_trill_name  - (IN) Trill Root_RBridge
   2585  */
   2586 
   2587 int
   2588 bcm_td_trill_source_trill_idx_name_get(int  unit,
   2589                                        int  trill_name_index,
   2590                                        bcm_trill_name_t  *source_trill_name)
   2591 {
   2592     egr_trill_rbridge_nicknames_entry_t  egr_name_entry;
   2593 
   2594     if (SOC_MEM_IS_VALID(unit, EGR_TRILL_RBRIDGE_NICKNAMESm)) {
   2595         /* TD3TBD */
   2596         BCM_IF_ERROR_RETURN(
   2597                   soc_mem_read(unit, EGR_TRILL_RBRIDGE_NICKNAMESm,
   2598                            MEM_BLOCK_ALL, trill_name_index, &egr_name_entry));
   2599 
   2600         *source_trill_name =  soc_mem_field32_get(unit,
   2601                                              EGR_TRILL_RBRIDGE_NICKNAMESm,
   2602                                              &egr_name_entry,
   2603                                              RBRIDGE_NICKNAMEf);
   2604         return BCM_E_NONE;
   2605     } else {
   2606         return BCM_E_NOT_FOUND;
   2607     }
   2608 }
   2609 
   2610 
   2611 /*
   2612  * Function:
   2613  *     _bcm_td_trill_egress_dvp_set
   2614  * Purpose:
   2615  *     Set Egress DVP tables
   2616  * Parameters:
   2617  *   IN :  Unit
   2618  *   IN :  vp
   2619  *   IN :  trill_port
   2620  * Returns:
   2621  *   BCM_E_XXX
   2622  */
   2623 
   2624 STATIC int
   2625 _bcm_td_trill_egress_dvp_set(int unit, int vp, bcm_trill_port_t *trill_port)
   2626 {
   2627     int rv=BCM_E_UNAVAIL;
   2628     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   2629     
   2630     sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));
   2631     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   2632                                             VP_TYPEf, 0x1);
   2633     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   2634                                             EGRESS_RBRIDGE_NICKNAMEf, trill_port->name);
   2635     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   2636                                             HOPCOUNTf, trill_port->hopcount);
   2637     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   2638                                             MTU_VALUEf, trill_port->mtu);
   2639     soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
   2640                                             MTU_ENABLEf, 0x1);
   2641     rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm,
   2642                                             MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   2643     if (soc_feature(unit,soc_feature_trill_egr_dvp_classid)) {
   2644         egr_dvp_attribute_1_entry_t  egr_dvp_attribute_1;
   2645         sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t));
   2646         soc_mem_field32_set(unit, EGR_DVP_ATTRIBUTE_1m, &egr_dvp_attribute_1,
   2647                                              TRILL__CLASS_IDf, trill_port->if_class);
   2648         rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTE_1m,
   2649                                         MEM_BLOCK_ALL, vp, &egr_dvp_attribute_1);
   2650     }
   2651     return rv;
   2652 
   2653 }
   2654 
   2655 /*
   2656  * Function:
   2657  *		_bcm_td_trill_egress_dvp_reset
   2658  * Purpose:
   2659  *		Set Egress DVP tables
   2660  * Parameters:
   2661  *		IN :  Unit
   2662  *           IN :  nh_index
   2663  *           IN :  trill_port
   2664  * Returns:
   2665  *		BCM_E_XXX
   2666  */
   2667 
   2668 STATIC int
   2669 _bcm_td_trill_egress_dvp_reset(int unit, int vp)
   2670 {
   2671     int rv=BCM_E_UNAVAIL;
   2672     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   2673 
   2674     
   2675     sal_memset(&egr_dvp_attribute, 0, sizeof(egr_dvp_attribute_entry_t));	
   2676     rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTEm,
   2677                                             MEM_BLOCK_ALL, vp, &egr_dvp_attribute);
   2678     if (soc_feature(unit,soc_feature_trill_egr_dvp_classid)) {
   2679         egr_dvp_attribute_1_entry_t  egr_dvp_attribute_1;
   2680         sal_memset(&egr_dvp_attribute_1, 0, sizeof(egr_dvp_attribute_1_entry_t));
   2681         rv = soc_mem_write(unit, EGR_DVP_ATTRIBUTE_1m,
   2682                                             MEM_BLOCK_ALL, vp, &egr_dvp_attribute_1);
   2683     }
   2684     return rv;
   2685 }
   2686 
   2687 /*
   2688  * Purpose:
   2689  *		Set Egress TRILL Header fields
   2690  * Parameters:
   2691  *		IN :  Unit
   2692  *           IN :  trill_name
   2693  * Returns:
   2694  *		BCM_E_XXX
   2695  */
   2696 
   2697 STATIC int
   2698 _bcm_td_trill_header_set(int unit, bcm_trill_name_t  trill_name)
   2699 {
   2700     uint32  reg_val=0;
   2701     int rv = BCM_E_NONE;
   2702 
   2703     soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 
   2704                              &reg_val, RESERVED_FIELDf, 0);
   2705     soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 
   2706                              &reg_val, VERSIONf, 0);
   2707     if (soc_mem_field_valid(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, RBRIDGE_NICKNAMEf)) {
   2708         rv = _bcm_td_trill_egress_name_set(unit, trill_name);
   2709     } else {
   2710         soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 
   2711                              &reg_val, RBRIDGE_NICKNAMEf, trill_name);
   2712         SOC_IF_ERROR_RETURN(
   2713               WRITE_EGR_TRILL_HEADER_ATTRIBUTESr(unit, reg_val));
   2714     }
   2715 
   2716     return rv;
   2717 }
   2718 
   2719 /*
   2720  * Purpose:
   2721  *		Reset Egress TRILL Header fields
   2722  * Parameters:
   2723  *		IN :  Unit
   2724  *           IN :  trill_name
   2725  * Returns:
   2726  *		BCM_E_XXX
   2727  */
   2728 
   2729 STATIC int
   2730 _bcm_td_trill_header_reset(int unit, bcm_trill_name_t  trill_name)
   2731 {
   2732     uint32  reg_val=0;
   2733     int rv = BCM_E_NONE;
   2734 
   2735      if (soc_mem_field_valid(unit, EGR_TRILL_RBRIDGE_NICKNAMESm, RBRIDGE_NICKNAMEf)) {
   2736             rv = _bcm_td_trill_egress_name_reset(unit, trill_name);
   2737      } else {
   2738          if (trill_name == soc_reg_field_get(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 
   2739                          reg_val, RBRIDGE_NICKNAMEf)) {
   2740               soc_reg_field_set(unit, EGR_TRILL_HEADER_ATTRIBUTESr, 
   2741                          &reg_val, RBRIDGE_NICKNAMEf, 0x0);
   2742               SOC_IF_ERROR_RETURN(
   2743                   WRITE_EGR_TRILL_HEADER_ATTRIBUTESr(unit, reg_val));
   2744 
   2745          }
   2746      }
   2747      return rv;
   2748 }
   2749 
   2750 /*
   2751  * Function:
   2752  *		_bcm_td_trill_adjacency_register_set
   2753  * Purpose:
   2754  *		Set Ingress TRILL Adjacency register
   2755  * Parameters:
   2756  *		IN :  Unit
   2757  *   IN :  port
   2758  *   IN :  mac_addr
   2759  *   IN : vid
   2760  * Returns:
   2761  *		BCM_E_XXX
   2762  */
   2763 
   2764 STATIC int
   2765 _bcm_td_trill_adjacency_register_set(int unit, bcm_port_t  port, bcm_mac_t dst_mac_addr, bcm_vlan_t vid)
   2766 {
   2767     uint64 reg_val;  
   2768     uint64 mac_field;
   2769 #if defined(BCM_TOMAHAWK2_SUPPORT)
   2770     ing_trill_adjacency_entry_t adjacency_entry;
   2771 #endif
   2772     COMPILER_64_ZERO(reg_val);
   2773     COMPILER_64_ZERO(mac_field);
   2774 
   2775     SAL_MAC_ADDR_TO_UINT64(dst_mac_addr, mac_field);
   2776 #if defined(BCM_TOMAHAWK2_SUPPORT)
   2777     if (soc_feature(unit, soc_feature_ing_trill_adjacency_is_memory)) {
   2778         SOC_IF_ERROR_RETURN(READ_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ANY,
   2779                             port, &adjacency_entry));
   2780         soc_ING_TRILL_ADJACENCYm_field32_set(unit, &adjacency_entry, 
   2781                                              VLANf, vid);
   2782         soc_mem_mac_addr_set(unit, ING_TRILL_ADJACENCYm, &adjacency_entry, 
   2783                              MAC_ADDRESSf, dst_mac_addr);        
   2784         SOC_IF_ERROR_RETURN(WRITE_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ALL,
   2785                             port, &adjacency_entry));
   2786     } else
   2787 #endif
   2788     {
   2789         soc_reg64_field32_set(unit, ING_TRILL_ADJACENCYr, &reg_val, 
   2790                                       VLANf, vid);
   2791         soc_reg64_field_set(unit, ING_TRILL_ADJACENCYr, &reg_val, 
   2792                                       MAC_ADDRESSf, mac_field);
   2793         SOC_IF_ERROR_RETURN
   2794                   (WRITE_ING_TRILL_ADJACENCYr(unit, port, reg_val));
   2795     }
   2796     return BCM_E_NONE;
   2797 }
   2798 
   2799 /*
   2800  * Function:
   2801  *   _bcm_td_trill_adjacency_register_reset
   2802  * Purpose:
   2803  *   Reset Ingress TRILL Adjacency register
   2804  * Parameters:
   2805  *   IN :  Unit
   2806  *   IN :  port
   2807  * Returns:
   2808  *   BCM_E_XXX
   2809  */
   2810 
   2811 STATIC int
   2812 _bcm_td_trill_adjacency_register_reset(int unit, bcm_port_t  port)
   2813 {
   2814     uint64 reg_val;  
   2815     uint64 mac_field;
   2816     int id=0;
   2817     bcm_mac_t dst_mac_addr;
   2818 #if defined(BCM_TOMAHAWK2_SUPPORT)
   2819         ing_trill_adjacency_entry_t adjacency_entry;
   2820 #endif
   2821     COMPILER_64_ZERO(reg_val);
   2822     COMPILER_64_ZERO(mac_field);
   2823     for (id=0; id<6; id++) {
   2824         dst_mac_addr[id] = 0x0;
   2825     }
   2826 
   2827     SAL_MAC_ADDR_TO_UINT64(dst_mac_addr, mac_field);
   2828 #if defined(BCM_TOMAHAWK2_SUPPORT)
   2829     if (soc_feature(unit, soc_feature_ing_trill_adjacency_is_memory)) {
   2830         SOC_IF_ERROR_RETURN(READ_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ANY,
   2831                             port, &adjacency_entry));
   2832         soc_ING_TRILL_ADJACENCYm_field32_set(unit, &adjacency_entry, 
   2833                                              VLANf, 0x0);
   2834         soc_mem_mac_addr_set(unit, ING_TRILL_ADJACENCYm, &adjacency_entry, 
   2835                              MAC_ADDRESSf, dst_mac_addr);
   2836         SOC_IF_ERROR_RETURN(WRITE_ING_TRILL_ADJACENCYm(unit, MEM_BLOCK_ALL,
   2837                             port, &adjacency_entry));
   2838     } else
   2839 #endif
   2840     {
   2841         soc_reg64_field32_set(unit, ING_TRILL_ADJACENCYr, &reg_val, 
   2842                                       VLANf, 0x0);
   2843         soc_reg64_field_set(unit, ING_TRILL_ADJACENCYr, &reg_val, 
   2844                                       MAC_ADDRESSf, mac_field);
   2845         SOC_IF_ERROR_RETURN
   2846                   (WRITE_ING_TRILL_ADJACENCYr(unit, port, reg_val));
   2847     }
   2848     return BCM_E_NONE;
   2849 }
   2850 
   2851 /*
   2852  * Function:
   2853  *   _bcm_td_trill_adjacency_set
   2854  * Purpose:
   2855  *   Set TRILL Adjacency
   2856  * Parameters:
   2857  *   IN :  Unit
   2858  *   IN :  nh_index
   2859  *   IN :  trill_port
   2860  * Returns:
   2861  *   BCM_E_XXX
   2862  */
   2863 
   2864 STATIC int
   2865 _bcm_td_trill_adjacency_set(int unit, int nh_index)
   2866 {
   2867     int rv=BCM_E_UNAVAIL;
   2868     ing_l3_next_hop_entry_t ing_nh;
   2869     egr_l3_next_hop_entry_t egr_nh;
   2870     egr_l3_intf_entry_t if_entry;
   2871     bcm_if_t  intf_idx;
   2872     bcm_port_t      port=0;
   2873     bcm_module_t modid=0, local_modid=0;
   2874     bcm_mac_t src_mac_addr;
   2875     bcm_mac_t dst_mac_addr;
   2876     bcm_vlan_t vid=0;
   2877     bcm_trunk_t trunk_id=0;
   2878     int  num_local_ports=0, idx=0;
   2879     bcm_port_t   local_ports[SOC_MAX_NUM_PORTS];
   2880     uint32 trunk_id_data = 0;
   2881     uint32 mod_port_data = 0;
   2882     int num_bits_for_port;
   2883 
   2884     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   2885                                   MEM_BLOCK_ANY, nh_index, &ing_nh));
   2886 
   2887     if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) {
   2888         trunk_id = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2889                                                   &ing_nh, TGIDf);
   2890         rv = _bcm_trunk_id_validate(unit, trunk_id);
   2891         if (BCM_FAILURE(rv)) {
   2892             return BCM_E_PORT;
   2893         }
   2894         if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) {
   2895             trunk_id_data = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id);
   2896         }
   2897         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id,
   2898             SOC_MAX_NUM_PORTS, local_ports, &num_local_ports));
   2899     } else { 
   2900         modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2901                                     &ing_nh, MODULE_IDf);
   2902         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid));
   2903 
   2904         if (modid != local_modid) {
   2905             /* Ignore Adjacency set for non local modid */
   2906             return BCM_E_NONE;
   2907         }
   2908         port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   2909                                            &ing_nh, PORT_NUMf);
   2910         local_ports[num_local_ports++] = port;
   2911         if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) {
   2912             num_bits_for_port =
   2913                 _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit));
   2914             mod_port_data = (modid << num_bits_for_port) | port;
   2915         }
   2916     }
   2917 
   2918     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
   2919                                   MEM_BLOCK_ANY, nh_index, &egr_nh));
   2920 
   2921     intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 
   2922                                    &egr_nh, INTF_NUMf);
   2923 
   2924     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 
   2925                                  MEM_BLOCK_ANY, intf_idx, &if_entry));
   2926 
   2927     /* Obtain Source-MAC, Vlan from EGR_L3_INTF */
   2928     soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &if_entry, 
   2929                                              MAC_ADDRESSf, src_mac_addr);
   2930     vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 
   2931                                              &if_entry,  VIDf);
   2932 
   2933     /* Obtain vlan and Destination-MAC from EGR_L3_NEXT_HOP */
   2934     soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   2935                                              MAC_ADDRESSf, dst_mac_addr);
   2936     /* Trunk supported in MY_STATION_TCAM */ 
   2937     if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) {
   2938         /* Configure MY_STATION entry for trunk */
   2939         if (trunk_id_data) {
   2940             BCM_IF_ERROR_RETURN(
   2941                 bcm_td_metro_myStation_add(unit, src_mac_addr, vid, trunk_id_data, 1));
   2942             for (idx = 0; idx < num_local_ports; idx++) { 
   2943                 /* Configure ING_TRILL_ADJACENCY */
   2944                 rv =  _bcm_td_trill_adjacency_register_set(unit, local_ports[idx], dst_mac_addr, vid);
   2945             }
   2946             return rv;
   2947         } else if (mod_port_data) {
   2948             BCM_IF_ERROR_RETURN(
   2949                 bcm_td_metro_myStation_add(unit, src_mac_addr, vid,
   2950                 mod_port_data, 1));
   2951             for (idx = 0; idx < num_local_ports; idx++) {
   2952                  /* Configure ING_TRILL_ADJACENCY */
   2953                  rv = _bcm_td_trill_adjacency_register_set(
   2954                          unit, local_ports[idx], dst_mac_addr, vid);
   2955             }
   2956             return rv;
   2957         }
   2958     } 
   2959     /* Trunk not supported in MY_STATION_TCAM */
   2960     for (idx = 0; idx < num_local_ports; idx++) {
   2961         /* Configure MY_STATION entry */
   2962         BCM_IF_ERROR_RETURN(
   2963              bcm_td_metro_myStation_add(unit, src_mac_addr, vid, local_ports[idx], 1));
   2964         
   2965         /* Configure ING_TRILL_ADJACENCY */
   2966         rv =  _bcm_td_trill_adjacency_register_set(unit, local_ports[idx], dst_mac_addr, vid);
   2967     }
   2968     return rv;
   2969 }
   2970 
   2971 /*
   2972  * Function:
   2973  *		_bcm_td_trill_adjacency_reset
   2974  * Purpose:
   2975  *		Reset TRILL Adjacency
   2976  * Parameters:
   2977  *		IN :  Unit
   2978  *   IN :  nh_index
   2979  * Returns:
   2980  *		BCM_E_XXX
   2981  */
   2982 
   2983 STATIC int
   2984 _bcm_td_trill_adjacency_reset(int unit, int nh_index)
   2985 {
   2986     int rv=BCM_E_UNAVAIL;
   2987     ing_l3_next_hop_entry_t ing_nh;
   2988     egr_l3_next_hop_entry_t egr_nh;
   2989     egr_l3_intf_entry_t if_entry;
   2990     bcm_if_t  intf_idx;
   2991     bcm_port_t      port=0;
   2992     bcm_module_t modid=0, local_modid=0;
   2993     bcm_mac_t src_mac_addr;
   2994     bcm_vlan_t vid=0;
   2995     bcm_trunk_t trunk_id=0;
   2996     int  num_local_ports=0, idx=0;
   2997     bcm_port_t   local_ports[SOC_MAX_NUM_PORTS];
   2998     uint32 trunk_id_data = 0;
   2999     uint32 mod_port_data = 0;
   3000     int num_bits_for_port;
   3001 
   3002     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, 
   3003                                MEM_BLOCK_ANY, nh_index, &ing_nh));
   3004 
   3005     if (soc_mem_field32_get(unit, ING_L3_NEXT_HOPm, &ing_nh, Tf)) {
   3006         trunk_id = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   3007                                                   &ing_nh, TGIDf);
   3008         rv = _bcm_trunk_id_validate(unit, trunk_id);
   3009         if (BCM_FAILURE(rv)) {
   3010             return BCM_E_PORT;
   3011         }
   3012 
   3013         if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) {
   3014             trunk_id_data = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id);
   3015         }
   3016 
   3017         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, trunk_id,
   3018             SOC_MAX_NUM_PORTS, local_ports, &num_local_ports));
   3019     } else { 
   3020         modid = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   3021                                     &ing_nh, MODULE_IDf);
   3022         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get (unit, &local_modid));
   3023 
   3024         if (modid != local_modid) {
   3025             /* Ignore Adjacency reset for non local modid */
   3026             return BCM_E_NONE;
   3027         }
   3028 
   3029         port = soc_mem_field32_get(unit, ING_L3_NEXT_HOPm,
   3030                                            &ing_nh, PORT_NUMf);
   3031         local_ports[num_local_ports++] = port;
   3032         if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) {
   3033             num_bits_for_port =
   3034                 _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit));
   3035             mod_port_data = (modid << num_bits_for_port) | port;
   3036         }
   3037     }
   3038 
   3039     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
   3040                                MEM_BLOCK_ANY, nh_index, &egr_nh));
   3041  
   3042     intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 
   3043                                 &egr_nh, INTF_NUMf);
   3044  
   3045     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 
   3046                                MEM_BLOCK_ANY, intf_idx, &if_entry));
   3047  
   3048     /* Obtain Source-MAC from EGR_L3_INTF */
   3049     soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &if_entry, 
   3050                                           MAC_ADDRESSf, src_mac_addr);
   3051  
   3052     /* Obtain vlan and Destination-MAC from EGR_L3_NEXT_HOP */
   3053     vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 
   3054                                           &if_entry, OVIDf);
   3055     /* Trunk supported in MY_STATION_TCAM */ 
   3056     if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) {
   3057         /* Delete MY_STATION entry for trunk */
   3058         if (trunk_id_data) {
   3059             rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid, trunk_id_data, 1);
   3060             if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) {
   3061                 if (rv != BCM_E_NONE) {
   3062                     return rv;
   3063                 }
   3064             } else {
   3065                 rv = BCM_E_NONE;
   3066             }
   3067             for (idx = 0; idx < num_local_ports; idx++) { 
   3068                 /* reset ING_TRILL_ADJACENCY */
   3069                 rv =  _bcm_td_trill_adjacency_register_reset(unit, local_ports[idx]);
   3070             }
   3071             return rv;
   3072         } else if (mod_port_data) {
   3073             rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid,
   3074                                                mod_port_data, 1);
   3075             if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) {
   3076                 if (rv != BCM_E_NONE) {
   3077                     return rv;
   3078                 }
   3079             } else {
   3080                 rv = BCM_E_NONE;
   3081             }
   3082             for (idx = 0; idx < num_local_ports; idx++) {
   3083                 /* reset ING_TRILL_ADJACENCY */
   3084                 rv = _bcm_td_trill_adjacency_register_reset(unit,
   3085                                                             local_ports[idx]);
   3086             }
   3087             return rv;
   3088         }
   3089     } 
   3090     /* Trunk not supported in MY_STATION_TCAM */ 
   3091     for (idx = 0; idx < num_local_ports; idx++) {
   3092          /* Delete MY_STATION entry */
   3093          rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid, local_ports[idx], 1);
   3094          if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) {
   3095              if (rv != BCM_E_NONE) {
   3096                return rv;
   3097              }
   3098          }
   3099 
   3100          /* Reset ING_TRILL_ADJACENCY */
   3101          rv = _bcm_td_trill_adjacency_register_reset(unit, local_ports[idx]);
   3102     }
   3103     return rv; 
   3104 }
   3105 
   3106 
   3107 /*
   3108  * Function:
   3109  *		_bcm_td_trill_port_validate
   3110  * Purpose:
   3111  *		Validate Trill Port Parameters
   3112  * Parameters:
   3113  *   IN :  trill_port
   3114  * Returns:
   3115  *		BCM_E_XXX
   3116  */
   3117 
   3118 int
   3119 _bcm_td_trill_port_validate(bcm_trill_port_t *trill_port)
   3120 {
   3121 
   3122     if (!trill_port->name) {
   3123          return BCM_E_PARAM;
   3124     }
   3125 
   3126     /* Check for unsupported Flag */
   3127     if (trill_port->flags & (~(BCM_TRILL_PORT_WITH_ID |
   3128                         BCM_TRILL_PORT_DROP |
   3129                         BCM_TRILL_PORT_COUNTED |                        
   3130                         BCM_TRILL_PORT_NETWORK |
   3131                         BCM_TRILL_PORT_REPLACE |
   3132                         BCM_TRILL_PORT_MULTICAST |
   3133                         BCM_TRILL_PORT_LOCAL  ))) {
   3134          return BCM_E_PARAM;
   3135     }
   3136 
   3137     return BCM_E_NONE;
   3138 }
   3139 
   3140  /*
   3141   * Function:
   3142   *     _bcm_td_trill_root_rbridge_check
   3143   * Purpose:
   3144   *     Check if Root RBridge already exists
   3145   * Parameters:
   3146   *     IN : unit
   3147   * Returns:
   3148   *     BCM_E_XXX
   3149   */
   3150 STATIC int
   3151 _bcm_td_trill_root_rbridge_check(int unit, bcm_trill_port_t *trill_port)
   3152 {
   3153     _bcm_td_trill_bookkeeping_t *trill_info;
   3154     int idx=0;
   3155 
   3156     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   3157          return BCM_E_UNIT;
   3158     }
   3159 
   3160     trill_info = TRILL_INFO(unit);
   3161 
   3162     for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) {
   3163          if (trill_info->rootBridge[idx] == trill_port->name) {
   3164               return (BCM_E_EXISTS); 
   3165          }
   3166     }
   3167     /* TRILL DVP to Root RBridge do NOT exist */
   3168     return BCM_E_NONE;
   3169 }
   3170 
   3171  /*
   3172   * Function:
   3173   *     _bcm_td_trill_root_bridge_set
   3174   * Purpose:
   3175   *     Configure Root RBridge
   3176   * Parameters:
   3177   *     IN : unit
   3178   * Returns:
   3179   *     BCM_E_XXX
   3180   */
   3181  
   3182 STATIC int
   3183 _bcm_td_trill_root_bridge_set(int unit, bcm_trill_port_t *trill_port, int vp)
   3184 {
   3185     _bcm_td_trill_bookkeeping_t *trill_info;
   3186     int rv=BCM_E_NONE;
   3187     uint8 trill_tree_profile_idx=0;
   3188 
   3189     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   3190          return BCM_E_UNIT;
   3191     }
   3192 
   3193     trill_info = TRILL_INFO(unit);
   3194 
   3195     /* Verify whether Root Rbridge already exists? */
   3196     rv = _bcm_td_trill_root_rbridge_check(unit, trill_port);
   3197     if (rv == BCM_E_EXISTS) {
   3198         if (!(trill_port->flags & BCM_TRILL_PORT_REPLACE)) {
   3199              (void) _bcm_vp_free(unit, _bcmVpTypeTrill, 1, vp);
   3200              return rv;
   3201         }
   3202     }
   3203 
   3204     /* Set Tree profile */
   3205     rv = _bcm_td_trill_tree_profile_set (unit, trill_port->name, 
   3206     trill_port->multicast_hopcount, &trill_tree_profile_idx);
   3207     if (rv < 0) {
   3208          trill_info->rootBridge[trill_tree_profile_idx] = 0;
   3209          (void) _bcm_vp_free(unit, _bcmVpTypeTrill, 1, vp);
   3210          return rv;
   3211     }
   3212     return rv;
   3213 }
   3214 
   3215  /*
   3216   * Function:
   3217   *     _bcm_td_trill_root_bridge_clear
   3218   * Purpose:
   3219   *     Configure Root RBridge
   3220   * Parameters:
   3221   *     IN : unit
   3222   * Returns:
   3223   *     BCM_E_XXX
   3224   */
   3225  
   3226 STATIC int
   3227 _bcm_td_trill_root_bridge_clear(int unit, bcm_trill_port_t *trill_port)
   3228 {
   3229     int rv=BCM_E_NONE;
   3230 
   3231     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   3232          return BCM_E_UNIT;
   3233     }
   3234 
   3235     /* Verify whether Root Rbridge already exists? */
   3236     rv = _bcm_td_trill_root_rbridge_check(unit, trill_port);
   3237     if (rv == BCM_E_EXISTS) {
   3238         /* Clear Tree profile */
   3239         rv = _bcm_td_trill_tree_profile_reset (unit, trill_port->name);
   3240     }
   3241     return rv;
   3242 }
   3243 
   3244  /*
   3245   * Function:
   3246   *     _bcm_td_trill_rbridge_name_exists
   3247   * Purpose:
   3248   *     Configure Root RBridge
   3249   * Parameters:
   3250   *     IN : unit
   3251   * Returns:
   3252   *     BCM_E_XXX
   3253   */
   3254  
   3255 STATIC int
   3256 _bcm_td_trill_rbridge_name_exists(int unit, bcm_trill_port_t *trill_port)
   3257 {
   3258     _bcm_td_trill_bookkeeping_t *trill_info;
   3259     int idx=0, num_vp=0;
   3260 
   3261     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   3262          return BCM_E_UNIT;
   3263     }
   3264 
   3265     trill_info = TRILL_INFO(unit);
   3266     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3267 
   3268     for (idx = 0; idx < num_vp; idx++) {
   3269          if (trill_info->rBridge[idx] == trill_port->name) {
   3270               return (BCM_E_EXISTS); 
   3271          }
   3272     }
   3273     /* TRILL DVP to given RBridge_name  do NOT exist */
   3274     return BCM_E_NONE;
   3275 }
   3276 
   3277  /*
   3278   * Function:
   3279   *     bcm_td_multicast_trill_rootname_get
   3280   * Purpose:
   3281   *     Get  Root RBridge name
   3282   * Parameters:
   3283   *     IN : unit
   3284   * Returns:
   3285   *     BCM_E_XXX
   3286   */
   3287 
   3288 int
   3289 bcm_td_multicast_trill_rootname_get(int unit, bcm_multicast_t group, bcm_trill_name_t  *root_name)
   3290 {
   3291     _bcm_td_trill_bookkeeping_t *trill_info;
   3292     int l3mc_index=-1;
   3293     uint8  trill_tree_id=0xFF;
   3294     int rv = BCM_E_NONE;
   3295 
   3296     trill_info = TRILL_INFO(unit);
   3297 
   3298     l3mc_index = _BCM_MULTICAST_ID_GET(group);
   3299     rv = bcm_td_multicast_trill_group_get(unit, l3mc_index, &trill_tree_id);
   3300     if (BCM_SUCCESS(rv)) {
   3301        *root_name = trill_info->rootBridge[trill_tree_id];
   3302     }
   3303     return rv;
   3304 }
   3305 
   3306 
   3307 
   3308 /*
   3309  * Purpose:
   3310  *      Activate Trunk Port-membership from 
   3311  *     ING_TRILL_ADJACENY, EGR_PORT_TO_NHI_MAPPING
   3312  * Parameters:
   3313  *     unit  - (IN) Device Number
   3314  *     tgid - (IN)  Trunk Group ID
   3315  *     trunk_member_count - (IN) Count of Trunk members to be deleted
   3316  *     trunk_member_array - (IN) Trunk member ports to be deleted
   3317 */
   3318 
   3319 int
   3320 bcm_td_trill_trunk_member_add (int unit, bcm_trunk_t trunk_id, 
   3321                 int trunk_member_count, bcm_port_t *trunk_member_array) 
   3322 { 
   3323     int idx=0;
   3324     int rv=BCM_E_NONE;
   3325     int  nh_index=0, old_nh_index=-1;
   3326     bcm_l3_egress_t egr; 
   3327     egr_l3_next_hop_entry_t egr_nh;
   3328     egr_l3_intf_entry_t if_entry;
   3329     bcm_if_t  intf_idx;
   3330     bcm_vlan_t vid=0;
   3331     bcm_mac_t dst_mac_addr;
   3332     int gport = 0;
   3333     int modid = 0;
   3334     rv = _bcm_trunk_id_validate(unit, trunk_id);
   3335     if (BCM_FAILURE(rv)) {
   3336         return BCM_E_PORT;
   3337     }
   3338     
   3339     /* Obtain nh_index for trunk_id */
   3340     rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index);
   3341     if (nh_index == 0) {
   3342         return rv;
   3343     }
   3344     bcm_l3_egress_t_init(&egr);
   3345     BCM_IF_ERROR_RETURN(bcm_td_trill_egress_get(unit, &egr, nh_index));
   3346 
   3347     if (egr.flags & BCM_L3_TRILL_ONLY) {
   3348         for (idx = 0; idx < trunk_member_count; idx++) {
   3349             if (soc_mem_field_valid(unit, MY_STATION_TCAMm, SOURCE_FIELDf)) {                         
   3350                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
   3351                                                  MEM_BLOCK_ANY, nh_index, &egr_nh));
   3352                 intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 
   3353                                                &egr_nh, INTF_NUMf);
   3354                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 
   3355                                                  MEM_BLOCK_ANY, intf_idx, &if_entry));
   3356                 /* Obtain Vlan from EGR_L3_INTF */
   3357                 vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 
   3358                                           &if_entry,  VIDf);
   3359                 /* Obtain Destination-MAC from EGR_L3_NEXT_HOP */
   3360                 soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   3361                                      MAC_ADDRESSf, dst_mac_addr);
   3362                 /* Set ING_TRILL_ADJACENCY */
   3363                 BCM_IF_ERROR_RETURN(
   3364                     _bcm_td_trill_adjacency_register_set(unit, trunk_member_array[idx], 
   3365                                                          dst_mac_addr, vid));
   3366             } else {
   3367                 BCM_IF_ERROR_RETURN(
   3368                     _bcm_td_trill_adjacency_set(unit, nh_index));
   3369             }
   3370             BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   3371             BCM_GPORT_MODPORT_SET(gport, modid, trunk_member_array[idx]);
   3372             BCM_IF_ERROR_RETURN(
   3373                 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index));
   3374             if (!old_nh_index) {
   3375                 BCM_IF_ERROR_RETURN(
   3376                     _bcm_trx_gport_to_nhi_set(unit, gport, nh_index));
   3377              }
   3378 
   3379         }
   3380     }
   3381     return rv;
   3382 }
   3383 
   3384 
   3385 /*
   3386  * Purpose:
   3387  *      Clear Trunk Port-membership from 
   3388  *     ING_TRILL_ADJACENY, EGR_PORT_TO_NHI_MAPPING
   3389  * Parameters:
   3390  *     unit  - (IN) Device Number
   3391  *     tgid - (IN)  Trunk Group ID
   3392  *     trunk_member_count - (IN) Count of Trunk members to be deleted
   3393  *     trunk_member_array - (IN) Trunk member ports to be deleted
   3394 */
   3395 
   3396 int
   3397 bcm_td_trill_trunk_member_delete (int unit, bcm_trunk_t trunk_id, 
   3398                 int trunk_member_count, bcm_port_t *trunk_member_array) 
   3399 { 
   3400    int idx=0;
   3401    int rv=BCM_E_NONE;
   3402     int  old_nh_index=0;
   3403     bcm_mac_t src_mac_addr;
   3404     bcm_vlan_t vid=0;
   3405     bcm_l3_egress_t egr;
   3406     egr_l3_next_hop_entry_t egr_nh;
   3407     egr_l3_intf_entry_t if_entry;
   3408     bcm_if_t  intf_idx;
   3409     int nh_index = 0;
   3410     int gport = 0;
   3411     int modid = 0;
   3412 
   3413     rv = _bcm_trunk_id_validate(unit, trunk_id);
   3414     if (BCM_FAILURE(rv)) {
   3415         return BCM_E_PORT;
   3416     }
   3417 
   3418     /* Obtain nh_index for trunk_id  */
   3419     rv = _bcm_xgs3_trunk_nh_store_get(unit, trunk_id, &nh_index);
   3420     if (nh_index == 0) {
   3421         return rv;
   3422     }
   3423     bcm_l3_egress_t_init(&egr);
   3424     BCM_IF_ERROR_RETURN(bcm_td_trill_egress_get(unit, &egr, nh_index));
   3425 
   3426     if (egr.flags & BCM_L3_TRILL_ONLY) {
   3427         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   3428         for (idx = 0; idx < trunk_member_count; idx++) { 
   3429             /* Reset ING_TRILL_ADJACENCY */
   3430             rv = _bcm_td_trill_adjacency_register_reset(unit, trunk_member_array[idx]);
   3431             if (BCM_FAILURE(rv)) {
   3432                 return rv;
   3433             }           
   3434             BCM_GPORT_MODPORT_SET(gport, modid, trunk_member_array[idx]);
   3435             BCM_IF_ERROR_RETURN(
   3436                 _bcm_trx_gport_to_nhi_get(unit, gport, &old_nh_index));  
   3437 
   3438             if (0 != old_nh_index) {
   3439                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, 
   3440                             MEM_BLOCK_ANY, old_nh_index, &egr_nh));
   3441                 intf_idx = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, 
   3442                             &egr_nh, INTF_NUMf);
   3443                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_INTFm, 
   3444                             MEM_BLOCK_ANY, intf_idx, &if_entry));
   3445                 /* Obtain Source-MAC from EGR_L3_INTF */
   3446                 soc_mem_mac_addr_get(unit, EGR_L3_INTFm, &if_entry, 
   3447                         MAC_ADDRESSf, src_mac_addr);
   3448                 /* Obtain vlan and Destination-MAC from EGR_L3_NEXT_HOP */
   3449                 vid = soc_mem_field32_get(unit, EGR_L3_INTFm, 
   3450                         &if_entry, OVIDf);
   3451 
   3452                 /* Delete MY_STATION entry */
   3453                 rv = bcm_td_metro_myStation_delete(unit, src_mac_addr, vid, trunk_member_array[idx], 1);
   3454                 if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FULL)) {
   3455                     if (rv != BCM_E_NONE) {
   3456                        return rv;
   3457                     }
   3458                 }
   3459 
   3460                 rv = _bcm_trx_gport_to_nhi_set(unit, gport, 0);
   3461                 if (BCM_FAILURE(rv)) {
   3462                     return rv;
   3463                 }
   3464             }
   3465         } 
   3466     }
   3467     return rv;
   3468 }
   3469 
   3470 /*
   3471  * Purpose:
   3472  *	 Add Trill port to TRILL Cloud
   3473  * Parameters:
   3474  *	 unit	 - (IN) Device Number
   3475  *	 trill_port - (IN/OUT) trill port information (OUT : trill_port_id)
   3476 */
   3477 int 
   3478 bcm_td_trill_port_add(int unit, bcm_trill_port_t *trill_port)
   3479 {
   3480     _bcm_td_trill_bookkeeping_t *trill_info;
   3481     int rv=BCM_E_NONE;
   3482     int nh_ecmp_index = -1;
   3483     int old_nh_ecmp_index = -1, old_nh_index = -1;
   3484     int ref_count = 0;
   3485     int  vp, num_vp=0;
   3486     source_vp_entry_t svp;
   3487     ing_dvp_table_entry_t dvp;
   3488     uint32 flags=0;
   3489     bcm_if_t intf;
   3490     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
   3491     _bcm_vp_info_t vp_info;
   3492     int bit_num = 0;
   3493     int network_group=0;
   3494 
   3495     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   3496          return BCM_E_UNIT;
   3497     }
   3498 
   3499     /* Validate paramters */
   3500     if ((trill_port->name < 0)     || (trill_port->name > 0xffff)  ||
   3501         (trill_port->mtu < 0)      || (trill_port->mtu > 0x3fff)   ||
   3502         (trill_port->hopcount < 0) || (trill_port->hopcount > 0x3f)) {
   3503         return BCM_E_PARAM;
   3504     }
   3505 
   3506     if (soc_feature(unit, soc_feature_extended_address_class)) {
   3507         if ((trill_port->if_class > SOC_EXT_ADDR_CLASS_MAX(unit)) ||
   3508             (trill_port->if_class < 0)) {
   3509             return (BCM_E_PARAM);
   3510         }
   3511     } else {
   3512         bit_num = soc_mem_field_length(unit, MPLS_ENTRYm, TRILL__CLASS_IDf);
   3513         if ((trill_port->if_class > (( 1 << bit_num ) - 1)) ||
   3514             (trill_port->if_class < 0)) {
   3515             return BCM_E_PARAM;
   3516         }
   3517     }
   3518 
   3519     trill_info = TRILL_INFO(unit);
   3520     BCM_IF_ERROR_RETURN(
   3521                 _bcm_td_trill_port_validate(trill_port));
   3522 
   3523     /* 
   3524      * Extract next-hop index from egress object  OR
   3525      * Extract ecmp group index from multipath egress object. */
   3526 
   3527     if (!(trill_port->flags & BCM_TRILL_PORT_LOCAL)) {
   3528          BCM_IF_ERROR_RETURN(
   3529                 bcm_xgs3_get_nh_from_egress_object(unit,
   3530                            trill_port->egress_if, &flags, 1, &nh_ecmp_index));
   3531         if (nh_ecmp_index == BCM_XGS3_L3_INVALID_INDEX) {
   3532             return BCM_E_PARAM;
   3533         }
   3534     }
   3535 
   3536     if (flags == BCM_L3_MULTIPATH) {
   3537          trill_port->flags |= _BCM_TRILL_PORT_MULTIPATH;
   3538     }
   3539 
   3540     _bcm_vp_info_init(&vp_info);
   3541     vp_info.vp_type = _bcmVpTypeTrill;
   3542     if (trill_port->flags & BCM_TRILL_PORT_NETWORK) {
   3543         vp_info.flags |= _BCM_VP_INFO_NETWORK_PORT;
   3544     } else {
   3545         vp_info.flags &= ~(_BCM_VP_INFO_NETWORK_PORT);
   3546     }
   3547  
   3548     if (trill_port->flags & BCM_TRILL_PORT_REPLACE) {
   3549 
   3550          vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port->trill_port_id);
   3551          if (vp == -1) {
   3552             return BCM_E_PARAM;
   3553          }
   3554          if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   3555               return BCM_E_NOT_FOUND;
   3556          }
   3557          if (trill_info->rBridge[vp] != trill_port->name) {
   3558            return BCM_E_PARAM; 
   3559          }
   3560 
   3561          BCM_IF_ERROR_RETURN(
   3562               READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   3563          BCM_IF_ERROR_RETURN(
   3564               READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   3565 
   3566          /* Decrement port's VP count */
   3567          rv = _bcm_td_trill_port_cnt_update(unit, trill_port->trill_port_id, vp, FALSE);
   3568          if (rv < 0) {
   3569             return rv;
   3570          }
   3571 
   3572          /* Get replaced egress NHI/ECMP index */ 
   3573          if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf)) {
   3574             old_nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   3575          } else {
   3576             old_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   3577          }
   3578     } else if (trill_port->flags & BCM_TRILL_PORT_WITH_ID ) {
   3579     
   3580          if (!BCM_GPORT_IS_TRILL_PORT(trill_port->trill_port_id)) {
   3581               return (BCM_E_BADID);
   3582          }
   3583 
   3584          /* Check if rbridge_name already exists */
   3585          BCM_IF_ERROR_RETURN(_bcm_td_trill_rbridge_name_exists(unit, trill_port));
   3586 
   3587          num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3588          vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port->trill_port_id);
   3589          if (vp >= num_vp) {
   3590               return (BCM_E_BADID);
   3591          }
   3592          rv = _bcm_vp_used_get(unit, vp, _bcmVpTypeTrill);
   3593          if (rv) {
   3594               return (BCM_E_EXISTS);
   3595          }
   3596          BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
   3597          sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   3598    
   3599     } else {
   3600 
   3601          /* Check if rbridge_name already exists */
   3602          BCM_IF_ERROR_RETURN(_bcm_td_trill_rbridge_name_exists(unit, trill_port));
   3603 
   3604          /* allocate a new VP index */
   3605          num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3606          rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm, vp_info, &vp);
   3607          if (rv < 0) {
   3608               return rv;
   3609          }
   3610          sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   3611   
   3612          BCM_IF_ERROR_RETURN(_bcm_vp_used_set(unit, vp, vp_info));
   3613     }
   3614 
   3615     /* Set Virtual Port */
   3616     soc_SOURCE_VPm_field32_set(unit, &svp, CLASS_IDf, 
   3617                                   trill_port->if_class);
   3618     soc_SOURCE_VPm_field32_set(unit, &svp, 
   3619                                   ENTRY_TYPEf, 0x3); /* TRILL VP */
   3620 
   3621     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   3622         network_group = trill_port->network_group_id;
   3623         rv = _bcm_validate_splithorizon_network_group(unit,
   3624                     trill_port->flags & BCM_TRILL_PORT_NETWORK,
   3625                     &network_group);
   3626         BCM_IF_ERROR_RETURN(rv);
   3627         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_GROUPf,
   3628                         network_group);
   3629     } else {
   3630         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0x1);
   3631         network_group=_bcmVpIngDvpPortTypeNetwork;
   3632     }
   3633 
   3634         /* Set the CML */
   3635        BCM_TRILL_CHECK_ERROR_RETURN(
   3636             _bcm_vp_default_cml_mode_get (unit, 
   3637                            &cml_default_enable, &cml_default_new, 
   3638                            &cml_default_move), unit, vp);
   3639 
   3640         if (cml_default_enable) {
   3641             /* Set the CML to default values */
   3642             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml_default_new);
   3643             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml_default_move);
   3644         } else {
   3645             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
   3646             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, 0x8);
   3647             soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, 0x8);
   3648         }
   3649 
   3650     soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, 0x3);
   3651     BCM_TRILL_CHECK_ERROR_RETURN(
   3652                    WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp), unit, vp);
   3653    
   3654     if (trill_port->flags & BCM_TRILL_PORT_LOCAL) { /* My RBridge */
   3655         intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_ecmp_index;
   3656         BCM_IF_ERROR_RETURN(
   3657             _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigSet, vp, 
   3658                                    _bcmVpIngDvpVpTypeTRILL, intf, 
   3659                                    network_group));
   3660 
   3661         BCM_TRILL_CHECK_ERROR_RETURN(
   3662               _bcm_td_trill_egress_dvp_set(unit, vp, trill_port), unit, vp);
   3663         BCM_TRILL_CHECK_ERROR_RETURN(
   3664               _bcm_td_trill_header_set(unit, trill_port->name), unit, vp);
   3665 
   3666          /* ******** TRILL Decap Entry  ******************** */
   3667 #if   defined(BCM_TRIUMPH3_SUPPORT)
   3668         if (SOC_IS_TRIUMPH3(unit)) {
   3669             rv =   _bcm_tr3_trill_decap_entry_set(unit,  trill_port);
   3670         } else
   3671 #endif /* BCM_TRIUMPH3_SUPPORT */
   3672         {
   3673             rv =   _bcm_td_trill_decap_entry_set(unit,  trill_port);
   3674         }
   3675          if (rv < 0) {
   3676               return rv;
   3677          }
   3678          trill_info->rBridge[vp] = trill_port->name;
   3679 
   3680          /* Root RBridge case */
   3681          if (trill_port->flags &  BCM_TRILL_PORT_MULTICAST) {
   3682               /* Add Tree profile */
   3683               rv = _bcm_td_trill_root_bridge_set(unit, trill_port, vp);
   3684          } else if (trill_port->flags &  BCM_TRILL_PORT_REPLACE) {
   3685               /* Update as Regular RBridge  - if Root Rbridge already exists */
   3686               rv = _bcm_td_trill_root_bridge_clear(unit, trill_port);
   3687          }
   3688          if (rv < 0) {
   3689               return rv;
   3690          }
   3691     } else {
   3692 
   3693          /* Root RBridge */
   3694          if (trill_port->flags &  BCM_TRILL_PORT_MULTICAST) {
   3695               /* Add Tree profile */
   3696               rv = _bcm_td_trill_root_bridge_set(unit, trill_port, vp);
   3697          } else if (trill_port->flags &  BCM_TRILL_PORT_REPLACE) {
   3698               /* Update as Regular RBridge  - if Root Rbridge already exists */
   3699               rv = _bcm_td_trill_root_bridge_clear(unit, trill_port);
   3700          }
   3701          if (rv < 0) {
   3702               return rv;
   3703          }
   3704          /* ******** TRILL Access ECMP/Next-Hop  ********** */
   3705          if (trill_port->flags&_BCM_TRILL_PORT_MULTIPATH) {
   3706              intf = BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit) + nh_ecmp_index;
   3707          } else {
   3708              intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_ecmp_index;   
   3709          }
   3710          BCM_IF_ERROR_RETURN(
   3711              _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigSet, vp, 
   3712                                     _bcmVpIngDvpVpTypeTRILL, 
   3713                                     intf, network_group));
   3714 
   3715 
   3716          BCM_TRILL_CHECK_ERROR_RETURN(
   3717               _bcm_td_trill_egress_dvp_set(unit, vp, trill_port), unit, vp);
   3718 
   3719 #if   defined(BCM_TRIUMPH3_SUPPORT)
   3720         if (SOC_IS_TRIUMPH3(unit)) {
   3721          /* ******** TRILL Transit Forwarding Entry  ********** */
   3722             BCM_TRILL_CHECK_ERROR_RETURN(
   3723               _bcm_tr3_trill_transit_entry_set(unit, trill_port, nh_ecmp_index), unit, vp);
   3724 
   3725          /* ******** TRILL Decap Learn Entry  ********** */
   3726             BCM_TRILL_CHECK_ERROR_RETURN(
   3727               _bcm_tr3_trill_learn_entry_set(unit, trill_port, vp), unit, vp);
   3728         } else
   3729 #endif /* BCM_TRIUMPH3_SUPPORT */
   3730         {
   3731          /* ******** TRILL Transit Forwarding Entry  ********** */
   3732             BCM_TRILL_CHECK_ERROR_RETURN(
   3733               _bcm_td_trill_transit_entry_set(unit, trill_port, nh_ecmp_index), unit, vp);
   3734          /* ******** TRILL Decap Learn Entry  ********** */
   3735             BCM_TRILL_CHECK_ERROR_RETURN(
   3736               _bcm_td_trill_learn_entry_set(unit, trill_port, vp), unit, vp);
   3737         }
   3738         trill_info->rBridge[vp] = trill_port->name;
   3739     }
   3740     /* Set TRILL  port ID */
   3741     BCM_GPORT_TRILL_PORT_ID_SET(trill_port->trill_port_id, vp);
   3742     trill_port->encap_id = nh_ecmp_index;
   3743     /* Increment new-port's VP count */
   3744     BCM_IF_ERROR_RETURN(
   3745        _bcm_td_trill_port_cnt_update(unit, trill_port->trill_port_id, vp, TRUE));
   3746 
   3747     if (old_nh_ecmp_index != -1) {
   3748           BCM_IF_ERROR_RETURN(
   3749                bcm_xgs3_get_ref_count_from_nhi(
   3750                     unit, BCM_L3_MULTIPATH, &ref_count, old_nh_ecmp_index));
   3751     }
   3752     if (old_nh_index != -1) {
   3753       BCM_IF_ERROR_RETURN(
   3754                bcm_xgs3_get_ref_count_from_nhi(unit, 0, &ref_count, old_nh_index));
   3755     }
   3756 
   3757     return BCM_E_NONE;
   3758 }
   3759 
   3760  /*
   3761   * Purpose:
   3762   *      Get a trill port 
   3763   * Parameters:
   3764   *      unit    - (IN) Device Number
   3765   *      trill_port - (IN/OUT) Trill port information (IN : trill_port_id)
   3766   */
   3767 
   3768 int 
   3769 bcm_td_trill_port_get(int unit, bcm_trill_port_t *trill_port)
   3770 {
   3771     uint32 vp=0;
   3772     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   3773     source_vp_entry_t svp;
   3774     egr_trill_tree_profile_entry_t  egr_trill_profile;
   3775     ing_dvp_table_entry_t dvp;
   3776     int  nh_ecmp_index=0;
   3777     int ecmp=0;
   3778     int network_port=0;
   3779     uint8  trill_tree_id=0;
   3780     _bcm_vp_info_t vp_info;
   3781 
   3782     vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port->trill_port_id);
   3783     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   3784          return BCM_E_NOT_FOUND;
   3785     }
   3786 
   3787     /* Initialize the structure */
   3788     bcm_trill_port_t_init(trill_port);
   3789     BCM_GPORT_TRILL_PORT_ID_SET(trill_port->trill_port_id, vp);
   3790 
   3791     BCM_IF_ERROR_RETURN(
   3792        soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   3793                        MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
   3794   
   3795     trill_port->name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 
   3796                                             &egr_dvp_attribute, EGRESS_RBRIDGE_NICKNAMEf);
   3797     trill_port->mtu = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 
   3798                                             &egr_dvp_attribute, MTU_VALUEf);
   3799     trill_port->hopcount = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 
   3800                                             &egr_dvp_attribute, HOPCOUNTf);
   3801   
   3802     BCM_IF_ERROR_RETURN(
   3803        soc_mem_read(unit, SOURCE_VPm,
   3804                         MEM_BLOCK_ALL, vp, &svp));
   3805   
   3806     trill_port->if_class = soc_mem_field32_get(unit, SOURCE_VPm, 
   3807                                             &svp, CLASS_IDf);
   3808 
   3809     BCM_IF_ERROR_RETURN(
   3810          READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   3811     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   3812     if (ecmp) {
   3813          nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   3814          trill_port->egress_if  =  nh_ecmp_index + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
   3815     } else {
   3816          nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   3817          /* Extract next hop index from unipath egress object. */
   3818          if (nh_ecmp_index) {
   3819               trill_port->egress_if  =  nh_ecmp_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
   3820          } else {
   3821               trill_port->flags |=  BCM_TRILL_PORT_LOCAL;
   3822          }
   3823     }
   3824 
   3825     BCM_IF_ERROR_RETURN(_bcm_vp_info_get(unit, vp, &vp_info));
   3826     if (vp_info.flags & _BCM_VP_INFO_NETWORK_PORT) {
   3827         network_port = TRUE;
   3828     }
   3829 
   3830     if (network_port) {
   3831          trill_port->flags |=  BCM_TRILL_PORT_NETWORK;
   3832     }
   3833 
   3834     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   3835         trill_port->network_group_id = soc_ING_DVP_TABLEm_field32_get
   3836                                          (unit, &dvp, NETWORK_GROUPf);
   3837     }
   3838     /* Check Tree-ID */
   3839     (void) bcm_td_trill_tree_profile_get (unit, trill_port->name, &trill_tree_id);
   3840     if (trill_tree_id < BCM_MAX_NUM_TRILL_TREES) {
   3841           trill_port->flags |=  BCM_TRILL_PORT_MULTICAST;
   3842           BCM_IF_ERROR_RETURN(
   3843                  soc_mem_read(unit, EGR_TRILL_TREE_PROFILEm,
   3844                         MEM_BLOCK_ALL, trill_tree_id, &egr_trill_profile));
   3845           trill_port->multicast_hopcount = soc_mem_field32_get(unit, EGR_TRILL_TREE_PROFILEm, 
   3846                                             &egr_trill_profile, HOPCOUNTf);
   3847     }
   3848 
   3849     return BCM_E_NONE;
   3850 }
   3851 
   3852 /*
   3853  * Purpose:
   3854  *      Get all trill ports from TRILL Cloud
   3855  * Parameters:
   3856  *      unit     - (IN) Device Number
   3857  *      port_max   - (IN) Maximum number of Trill ports in array
   3858  *      port_array - (OUT) Array of Trill ports
   3859  *      port_count - (OUT) Number of Trill ports returned in array
   3860  *
   3861  * Returns:
   3862  *      BCM_E_XXX
   3863  * Notes: If port_max == 0 and port_array == NULL, actual number of
   3864  *        trill ports in the TRILL cloud will be returned.
   3865  */
   3866 
   3867 int 
   3868 bcm_td_trill_port_get_all(int unit, int port_max, bcm_trill_port_t *port_array, int *port_count )
   3869 {
   3870     int rv = BCM_E_NONE;
   3871     int vp=0;
   3872     uint32 num_vp=0;
   3873     ing_dvp_table_entry_t dvp;
   3874  
   3875     /* Input parameters check. */
   3876     if (port_max < 0) {
   3877         return BCM_E_PARAM;
   3878     }
   3879 
   3880     if ((port_max > 0) && (NULL == port_array)) {
   3881         return BCM_E_PARAM;
   3882     }
   3883 
   3884     if (NULL == port_count) {
   3885         return (BCM_E_PARAM);
   3886     }
   3887 
   3888     *port_count = 0;
   3889 
   3890     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3891     for (vp = 0; vp < num_vp; vp++) {
   3892          if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   3893               continue;
   3894          }
   3895          if (0 == port_max) {
   3896              (*port_count)++;
   3897          } else {
   3898              if (*port_count == port_max) {
   3899                   break;
   3900              }
   3901              BCM_IF_ERROR_RETURN(
   3902                   READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   3903      
   3904              if (0x1 == soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf)){
   3905                   BCM_GPORT_TRILL_PORT_ID_SET(port_array[*port_count].trill_port_id, vp);
   3906                   rv = bcm_td_trill_port_get(unit,
   3907                                         &port_array[*port_count]);
   3908                   if (rv<0) {
   3909                        return rv;
   3910                   }
   3911                   (*port_count)++;
   3912              }
   3913          }
   3914     }
   3915     return rv;
   3916 }
   3917 
   3918 
   3919 /*
   3920  * Purpose:
   3921  *	 Delete Trill port from TRILL Cloud
   3922  * Parameters:
   3923  *	 unit		- (IN) Device Number
   3924  *		trill_port_id - (IN) Trill port ID
   3925  */
   3926 int
   3927 bcm_td_trill_port_delete(int unit, bcm_gport_t trill_port_id)
   3928 {
   3929     _bcm_td_trill_bookkeeping_t *trill_info;
   3930     int vp=0;
   3931     source_vp_entry_t svp;
   3932     ing_dvp_table_entry_t dvp;
   3933     egr_dvp_attribute_entry_t  egr_dvp_attribute;
   3934     int rv=BCM_E_NONE;
   3935     int nh_ecmp_index=-1;
   3936     int ecmp =-1;
   3937     bcm_trill_name_t trill_name;
   3938     uint32  flags=0;
   3939     int  ref_count=0;
   3940     bcm_trill_port_t  trill_port;
   3941 
   3942     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   3943          return BCM_E_UNIT;
   3944     }
   3945 
   3946     trill_info = TRILL_INFO(unit);
   3947     vp = BCM_GPORT_TRILL_PORT_ID_GET(trill_port_id);
   3948     if (vp == -1) {
   3949         return BCM_E_PARAM;
   3950     }
   3951 
   3952     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {
   3953          return BCM_E_NOT_FOUND;
   3954     }
   3955 
   3956     bcm_trill_port_t_init(&trill_port);
   3957     trill_port.trill_port_id = trill_port_id;
   3958     BCM_IF_ERROR_RETURN(
   3959          bcm_td_trill_port_get(unit, &trill_port));
   3960     
   3961     BCM_IF_ERROR_RETURN(
   3962        soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
   3963                        MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
   3964   
   3965     trill_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, 
   3966                                             &egr_dvp_attribute, EGRESS_RBRIDGE_NICKNAMEf);
   3967 
   3968     /* Decrement port's VP count */
   3969     rv = _bcm_td_trill_port_cnt_update(unit, trill_port_id, vp, FALSE);
   3970     if (rv < 0) {
   3971         return rv;
   3972     }
   3973 
   3974 
   3975     BCM_IF_ERROR_RETURN(
   3976          READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   3977     ecmp = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMPf);
   3978     if (ecmp) {
   3979         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, ECMP_PTRf);
   3980         flags = BCM_L3_MULTIPATH;
   3981         BCM_IF_ERROR_RETURN(
   3982              bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
   3983     } else {
   3984         nh_ecmp_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   3985         if(nh_ecmp_index != 0) {
   3986               BCM_IF_ERROR_RETURN(
   3987                    bcm_xgs3_get_ref_count_from_nhi(unit, flags, &ref_count, nh_ecmp_index));
   3988         }
   3989     }
   3990     if (nh_ecmp_index) {
   3991 #if   defined(BCM_TRIUMPH3_SUPPORT)
   3992         if (SOC_IS_TRIUMPH3(unit)) {
   3993             BCM_IF_ERROR_RETURN(
   3994               _bcm_tr3_trill_transit_entry_reset(unit, vp, nh_ecmp_index, ecmp));
   3995             BCM_IF_ERROR_RETURN(
   3996               _bcm_tr3_trill_learn_entry_reset(unit, vp));
   3997 
   3998         } else
   3999 #endif /* BCM_TRIUMPH3_SUPPORT */
   4000         {
   4001             BCM_IF_ERROR_RETURN(
   4002               _bcm_td_trill_transit_entry_reset(unit, vp, nh_ecmp_index, ecmp));
   4003             BCM_IF_ERROR_RETURN(
   4004               _bcm_td_trill_learn_entry_reset(unit, vp));
   4005         }
   4006          BCM_IF_ERROR_RETURN(
   4007               _bcm_td_trill_egress_dvp_reset(unit, vp));
   4008     } else {
   4009 #if   defined(BCM_TRIUMPH3_SUPPORT)
   4010         if (SOC_IS_TRIUMPH3(unit)) {
   4011             BCM_IF_ERROR_RETURN(
   4012               _bcm_tr3_trill_decap_entry_reset(unit,  vp));
   4013         } else
   4014 #endif /* BCM_TRIUMPH3_SUPPORT */
   4015         {
   4016             BCM_IF_ERROR_RETURN(
   4017               _bcm_td_trill_decap_entry_reset(unit,  vp));
   4018         }
   4019          BCM_IF_ERROR_RETURN(
   4020               _bcm_td_trill_egress_dvp_reset(unit, vp));
   4021     }
   4022     /* Clear the SVP and DVP table entries */
   4023     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   4024     BCM_IF_ERROR_RETURN(
   4025          WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp));
   4026 
   4027     BCM_IF_ERROR_RETURN(
   4028         _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp, 
   4029                                ING_DVP_CONFIG_INVALID_VP_TYPE, 
   4030                                ING_DVP_CONFIG_INVALID_INTF_ID, 
   4031                                ING_DVP_CONFIG_INVALID_PORT_TYPE));
   4032 
   4033     if (trill_port.flags & BCM_TRILL_PORT_LOCAL) {
   4034          BCM_IF_ERROR_RETURN(
   4035              _bcm_td_trill_header_reset(unit, trill_name));
   4036     } 
   4037 
   4038     if (trill_port.flags &  BCM_TRILL_PORT_MULTICAST) {
   4039          BCM_IF_ERROR_RETURN(
   4040               _bcm_td_trill_tree_profile_reset (unit, trill_name));
   4041     }
   4042     /* Free RBridge */
   4043     trill_info->rBridge[vp] = 0;
   4044 
   4045     /* Free the VP */
   4046     (void) _bcm_vp_free(unit, _bcmVpTypeTrill, 1, vp);
   4047 
   4048     return rv;
   4049 }
   4050 
   4051  /*
   4052   * Purpose:
   4053   *	  Delete all Trill ports from TRILL Cloud
   4054   * Parameters:
   4055   *	  unit - Device Number
   4056   */
   4057 
   4058 int 
   4059 bcm_td_trill_port_delete_all(int unit)
   4060 {
   4061     int rv=BCM_E_NONE;
   4062     uint32 vp=0, num_vp=0;
   4063     ing_dvp_table_entry_t dvp;
   4064     bcm_gport_t trill_port_id;
   4065 
   4066     num_vp = soc_mem_index_count(unit, ING_DVP_TABLEm);
   4067     for (vp = 0; vp < num_vp; vp++) {
   4068          /* Check for validity of the VP */
   4069          if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeTrill)) {  
   4070               continue;
   4071          }
   4072          BCM_IF_ERROR_RETURN(
   4073               READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   4074          if ((soc_ING_DVP_TABLEm_field32_get(unit, &dvp, VP_TYPEf) == 0x1)) {
   4075               BCM_GPORT_TRILL_PORT_ID_SET(trill_port_id, vp);
   4076               rv = bcm_td_trill_port_delete(unit, trill_port_id);
   4077               if (rv < 0) {
   4078                    return rv;
   4079               }
   4080          }
   4081     }
   4082     return rv;
   4083 }
   4084 
   4085 /*
   4086  * Function:
   4087  *		_bcm_td_trill_multicast_transit_entry_key_set
   4088  * Purpose:
   4089  *		Set TRILL Multicast entry key
   4090  * Parameters:
   4091  *  IN :  Unit
   4092  *  IN :  Trill Root name
   4093  *  IN : MPLS entry pointer
   4094  * Returns:
   4095  *		BCM_E_XXX
   4096  */
   4097 
   4098 STATIC int
   4099  _bcm_td_trill_multicast_transit_entry_key_set (int unit, bcm_trill_name_t root_name,
   4100                                           mpls_entry_entry_t   *tr_ent)
   4101 {
   4102     uint8  trill_tree_id=0;
   4103 
   4104     (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id);
   4105     if (trill_tree_id == BCM_MAX_NUM_TRILL_TREES) {
   4106          return BCM_E_PARAM;
   4107     }
   4108     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   4109                                        TRILL__TREE_IDf, trill_tree_id);
   4110     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   4111                                        KEY_TYPEf, 0x5);
   4112     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   4113                                        TRILL__RBRIDGE_NICKNAMEf, root_name);
   4114     soc_mem_field32_set(unit, MPLS_ENTRYm, tr_ent,
   4115                                        VALIDf, 0x1);
   4116     return BCM_E_NONE;
   4117 }
   4118 
   4119 /*
   4120  * Purpose:
   4121  *      Set TRILL Multicast entry for Transit operation
   4122  * Parameters:
   4123  *      unit     - (IN) Device Number
   4124  *      root_name  - (IN) trill Root_RBridge
   4125  *      mc_index   - (IN) Multicast index
   4126  */
   4127 
   4128 int
   4129 bcm_td_trill_multicast_transit_entry_set(int unit, int flags,
   4130                    bcm_trill_name_t root_name, int mc_index, uint8  trill_tree_id)
   4131 {
   4132     mpls_entry_entry_t  tr_key, tr_entry;
   4133     int rv = BCM_E_UNAVAIL;
   4134     int entry_index=0;
   4135 
   4136     sal_memset(&tr_key, 0, sizeof(mpls_entry_entry_t));
   4137     sal_memset(&tr_entry, 0, sizeof(mpls_entry_entry_t));
   4138 
   4139     (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_key);
   4140 
   4141     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &entry_index,
   4142                         &tr_key, &tr_entry, 0);
   4143     if (rv == SOC_E_NONE) {
   4144          soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry,
   4145                         TRILL__L3MC_INDEXf, mc_index);
   4146          soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry,
   4147                         TRILL__TREE_IDf, (uint32) trill_tree_id);
   4148          /* Enable Multicast traffic */
   4149          if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 
   4150               if (flags & BCM_TRILL_PORT_DROP) {
   4151                    soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry,
   4152                                          TRILL__MCAST_DST_DISCARDf, 0x1);
   4153               } else {
   4154                    soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry,
   4155                                          TRILL__MCAST_DST_DISCARDf, 0x0);
   4156               }
   4157          }
   4158          rv = soc_mem_write(unit, MPLS_ENTRYm,
   4159                         MEM_BLOCK_ALL, entry_index, &tr_entry);
   4160     } else {
   4161         /* Root Entry Must be present */
   4162         return rv;
   4163     }
   4164     return rv;
   4165 
   4166 }
   4167 
   4168 
   4169 /*
   4170  * Purpose:
   4171  *      Enable TRILL Multicast traffic   
   4172  * Parameters:
   4173  *      unit     - (IN) Device Number
   4174  *      root_name  - (IN) trill Root_RBridge
   4175  */
   4176 
   4177 int
   4178 bcm_td_trill_multicast_enable(int unit, int flags, bcm_trill_name_t root_name)
   4179 {
   4180     mpls_entry_entry_t  tr_key, tr_entry;
   4181     int rv = BCM_E_UNAVAIL;
   4182     int entry_index=0;
   4183 
   4184     sal_memset(&tr_key, 0, sizeof(mpls_entry_entry_t));
   4185     sal_memset(&tr_entry, 0, sizeof(mpls_entry_entry_t));
   4186 
   4187     (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_key);
   4188 
   4189     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &entry_index,
   4190                         &tr_key, &tr_entry, 0);
   4191     if (rv == SOC_E_NONE) {
   4192          /* Enable Multicast traffic */
   4193          if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 
   4194               if (flags & BCM_TRILL_PORT_DROP) {
   4195                    soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry,
   4196                                          TRILL__MCAST_DST_DISCARDf, 0x1);
   4197               } else {
   4198                    soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_entry,
   4199                                          TRILL__MCAST_DST_DISCARDf, 0x0);
   4200               }
   4201          }
   4202          rv = soc_mem_write(unit, MPLS_ENTRYm,
   4203                         MEM_BLOCK_ALL, entry_index, &tr_entry);
   4204     } else {
   4205         /* Root Entry Must be present */
   4206         return rv;
   4207     }
   4208     return rv;
   4209 }
   4210 
   4211 
   4212 /*
   4213  * Purpose:
   4214  *      Disable TRILL Multicast traffic   
   4215  * Parameters:
   4216  *      unit     - (IN) Device Number
   4217  *      root_name  - (IN) trill Root_RBridge
   4218  */
   4219 
   4220 int
   4221 bcm_td_trill_multicast_disable(int unit, int flags, bcm_trill_name_t root_name)
   4222 {
   4223     mpls_entry_entry_t  tr_ent;
   4224     int rv = BCM_E_UNAVAIL;
   4225     int index=0;
   4226 
   4227     sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t));
   4228 
   4229     (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent);
   4230 
   4231     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   4232                              &tr_ent, &tr_ent, 0);
   4233     if (rv < 0) {
   4234          return rv;
   4235     }
   4236    
   4237     /* Disable Multicast Traffic */
   4238     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 
   4239          soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   4240                         TRILL__MCAST_DST_DISCARDf, 0x1);
   4241     }
   4242     rv = soc_mem_write(unit, MPLS_ENTRYm,
   4243                    MEM_BLOCK_ALL, index, &tr_ent);
   4244 
   4245     return rv;
   4246 }
   4247 
   4248 /*
   4249  * Purpose:
   4250  *       Reset TRILL Multicast entry for Transit operation
   4251  * Parameters:
   4252  *      unit     - (IN) Device Number
   4253  *      root_name  - (IN) trill Root_RBridge
   4254  *      mc_index   - (IN) Multicast index
   4255  */
   4256 
   4257 int
   4258 bcm_td_trill_multicast_transit_entry_reset(int unit, bcm_trill_name_t root_name)
   4259 {
   4260     mpls_entry_entry_t  tr_ent;
   4261     int rv = BCM_E_UNAVAIL;
   4262     int index=0;
   4263 
   4264     sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t));
   4265 
   4266     (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent);
   4267 
   4268     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   4269                              &tr_ent, &tr_ent, 0);
   4270     if (rv < 0) {
   4271          return rv;
   4272     }
   4273    
   4274     /* Remove l3mc_index from HW entry */
   4275     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   4276                    TRILL__L3MC_INDEXf, 0);
   4277     /* Remove Multicast Tree Id */
   4278     soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   4279                         TRILL__TREE_IDf, (uint32) 0);
   4280     /* Disable Multicast Traffic */
   4281     if (soc_mem_field_valid(unit, MPLS_ENTRYm, TRILL__MCAST_DST_DISCARDf)) { 
   4282          soc_mem_field32_set(unit, MPLS_ENTRYm, &tr_ent,
   4283                         TRILL__MCAST_DST_DISCARDf, 0x1);
   4284     }
   4285     rv = soc_mem_write(unit, MPLS_ENTRYm,
   4286                    MEM_BLOCK_ALL, index, &tr_ent);
   4287 
   4288     return rv;
   4289 }
   4290 
   4291 /*
   4292  * Purpose:
   4293  *       Get TRILL Multicast entry for Transit operation
   4294  * Parameters:
   4295  *      unit     - (IN) Device Number
   4296  *      root_name  - (IN) trill Root_RBridge
   4297  *      group   - (OUT) Multicast Group
   4298  */
   4299 
   4300 int
   4301 bcm_td_trill_multicast_transit_entry_get(int unit, bcm_trill_name_t root_name, bcm_multicast_t *group)
   4302 {
   4303     mpls_entry_entry_t  tr_ent;
   4304     int rv = BCM_E_UNAVAIL;
   4305     int index=0;
   4306 
   4307     sal_memset(&tr_ent, 0, sizeof(mpls_entry_entry_t));
   4308 
   4309     (void) _bcm_td_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent);
   4310 
   4311     rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &index,
   4312                              &tr_ent, &tr_ent, 0);
   4313     if (rv < 0) {
   4314          return rv;
   4315     }
   4316    
   4317     _BCM_MULTICAST_GROUP_SET(*group, 
   4318                       _BCM_MULTICAST_TYPE_TRILL,  
   4319                       soc_mem_field32_get (unit, MPLS_ENTRYm, (uint32 *)&tr_ent,
   4320                         TRILL__L3MC_INDEXf));
   4321     return rv;
   4322 }
   4323 
   4324 /*
   4325  * Purpose:
   4326  *       Reset all TRILL Multicast entries for Transit operation
   4327  * Parameters:
   4328  *      unit     - (IN) Device Number
   4329  *      tree_id - (IN) trill Tree ID
   4330  *      mc_index   - (IN) Multicast index
   4331  */
   4332 
   4333 int
   4334 bcm_td_trill_multicast_transit_entry_reset_all (int unit, uint8 tree_id)
   4335 {
   4336     int idx=0, num_entries=0;
   4337     int rv = BCM_E_UNAVAIL;
   4338     mpls_entry_entry_t ment;
   4339     int name;
   4340 
   4341     _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit);
   4342     /* Tree ID and Root name is 1:1 mapping.
   4343        Match on Rbridge name to match */
   4344     name = trill_info->rootBridge[tree_id];
   4345 
   4346     num_entries = soc_mem_index_count(unit, MPLS_ENTRYm);
   4347     for (idx = 0; idx < num_entries; idx++) {
   4348         rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, idx, &ment);
   4349         if (rv < 0) {
   4350             return rv;
   4351         }
   4352         if (!soc_MPLS_ENTRYm_field32_get(unit, &ment, VALIDf)) {
   4353             continue;
   4354         }
   4355         if (soc_MPLS_ENTRYm_field32_get(unit, &ment, KEY_TYPEf) != 0x5) {
   4356             continue;
   4357         }
   4358 
   4359         if ((soc_MPLS_ENTRYm_field32_get(unit, &ment,
   4360                                         TRILL__TREE_IDf) != tree_id) ||
   4361            (soc_MPLS_ENTRYm_field32_get(unit, &ment,
   4362                                         TRILL__RBRIDGE_NICKNAMEf) != name)) {
   4363             continue;
   4364         }
   4365 
   4366         /* Entry found, for a given RBridge Name + Tree ID Key
   4367          * there can be only one entry. Hence stop when entry found.
   4368          */
   4369         break;
   4370     }
   4371 
   4372     /* Set L3MC index to 0, reserved entry with BITMAP = 0 */
   4373     soc_MPLS_ENTRYm_field32_set(unit, &ment, TRILL__L3MC_INDEXf, 0);
   4374 
   4375     /* Write to  HW */
   4376     BCM_IF_ERROR_RETURN(
   4377         soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ALL, idx, &ment));
   4378 
   4379     return BCM_E_NONE;
   4380 }
   4381 
   4382 /*
   4383  * Purpose:
   4384  *       Add TRILL multicast entry
   4385  *       root_name = 0: Add Access -> Network entry
   4386  *       root_name > 0: Add Network -> Access entry
   4387  * Parameters:
   4388  *           unit   - Device Number
   4389  *           flags
   4390  *           root_name  - (IN) trill Root_RBridge
   4391  *           vid- (IN) Customer VLAN
   4392  *           c_dmac	- (IN) Customer D-MAC
   4393  *           group  - (IN) Multicast Group ID
   4394  */
   4395 
   4396 int
   4397 bcm_td_trill_multicast_add( int unit, uint32 flags,
   4398                                                      bcm_trill_name_t  root_name, 
   4399                                                      bcm_vlan_t vid, 
   4400                                                      bcm_mac_t c_dmac, 
   4401                                                      bcm_multicast_t group)
   4402 {
   4403     int l3mc_index=0;
   4404     int rv = BCM_E_UNAVAIL;
   4405     uint8  trill_tree_id=0;
   4406     bcm_mac_t mac_zero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 
   4407 
   4408     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   4409          return BCM_E_UNIT;
   4410     }
   4411 
   4412     /* Check Vlan range */
   4413     if (vid >= BCM_VLAN_INVALID) {
   4414          return BCM_E_PARAM;
   4415     }
   4416 
   4417     /* Check DA */
   4418     if (c_dmac == NULL) {
   4419          return BCM_E_PARAM;
   4420     }
   4421 
   4422     /* Check Tree-ID */
   4423     (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id);
   4424     if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) {
   4425          return BCM_E_PARAM;
   4426     }
   4427 
   4428     flags |= BCM_TRILL_MULTICAST_STATIC;
   4429 
   4430     if (flags & BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK) {
   4431 
   4432        l3mc_index = _BCM_MULTICAST_ID_GET(group);
   4433        BCM_TRILL_L3MC_CHECK (unit, l3mc_index);
   4434         if (vid != BCM_VLAN_NONE){
   4435              /* TRILL_Network Domain entry */
   4436              BCM_IF_ERROR_RETURN(
   4437                         _bcm_esw_trill_multicast_entry_add(unit, flags,
   4438                                                TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS, 
   4439                                                vid, c_dmac, trill_tree_id, group));
   4440 
   4441               /* Access-domain Entry - Update */
   4442              BCM_IF_ERROR_RETURN(
   4443                         _bcm_esw_trill_multicast_entry_update(unit, TR_L2_HASH_KEY_TYPE_BRIDGE, 
   4444                                                vid, c_dmac, trill_tree_id, group));
   4445          }
   4446 
   4447         /* Set EGR_IPMC.trill_tree_id */
   4448         rv = bcm_td_multicast_trill_group_update(unit, l3mc_index, trill_tree_id);
   4449     } else {
   4450 
   4451         /* TRILL-Network Domain - Unpruned entry */
   4452         if ((vid == BCM_VLAN_NONE) && (!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t)))) {
   4453 
   4454               l3mc_index = _BCM_MULTICAST_ID_GET(group);
   4455               BCM_TRILL_L3MC_CHECK (unit, l3mc_index);
   4456 
   4457               rv = _bcm_esw_trill_multicast_transit_entry_set(unit, flags,
   4458                                                      root_name, l3mc_index, trill_tree_id);
   4459 
   4460         } else if ((!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t))) && (vid != BCM_VLAN_NONE)) {
   4461 
   4462               l3mc_index = _BCM_MULTICAST_ID_GET(group);
   4463               BCM_TRILL_L3MC_CHECK (unit, l3mc_index);
   4464 
   4465               rv = _bcm_esw_trill_multicast_enable(unit, flags, root_name);
   4466               BCM_IF_ERROR_RETURN (rv);
   4467 
   4468               /* TRILL-Network Domain - Pruned entry - Short */
   4469               rv = _bcm_esw_trill_multicast_entry_add(unit, flags,
   4470                                                  TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT, 
   4471                                                  vid, c_dmac, trill_tree_id, group);
   4472         } else if (vid != BCM_VLAN_NONE) {
   4473 
   4474               l3mc_index = _BCM_MULTICAST_ID_GET(group);
   4475               BCM_TRILL_L3MC_CHECK (unit, l3mc_index);
   4476 
   4477               rv = _bcm_esw_trill_multicast_enable(unit, flags, root_name);
   4478               BCM_IF_ERROR_RETURN (rv);
   4479 
   4480               /* TRILL-Network Domain - Pruned entry - Long */
   4481               rv = _bcm_esw_trill_multicast_entry_add(unit, flags,
   4482                                                  TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG,
   4483                                                  vid, c_dmac, trill_tree_id, group);
   4484         }
   4485     }
   4486     return rv;
   4487 }
   4488 
   4489 /*
   4490  * Purpose:
   4491  *      Delete TRILL multicast entry
   4492  * Parameters:
   4493  *           unit   - Device Number
   4494  *           flags
   4495  *           root_name  - (IN) trill Root_RBridge
   4496  *           vid- (IN) Customer VLAN
   4497  *           c_dmac	  (IN) Customer D-MAC
   4498  *           access_domain_group  - (IN) Multicast Group ID
   4499  *           trill_domain_group  - (IN) Multicast Group ID
   4500  */
   4501 
   4502 int
   4503 bcm_td_trill_multicast_delete(int unit, uint32 flags,
   4504                                                          bcm_trill_name_t root_name,
   4505                                                          bcm_vlan_t vid,
   4506                                                          bcm_mac_t c_dmac)
   4507 {
   4508     int rv = BCM_E_NONE;
   4509     uint8  trill_tree_id=0;
   4510     bcm_mac_t mac_zero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 
   4511 
   4512     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   4513          return BCM_E_UNIT;
   4514     }
   4515 
   4516     /* Check Vlan range */
   4517     if (vid >= BCM_VLAN_INVALID) {
   4518          return BCM_E_PARAM;
   4519     }
   4520 
   4521     /* Check DA */
   4522     if (c_dmac == NULL) {
   4523          return BCM_E_PARAM;
   4524     }
   4525 
   4526     /* Check Tree-ID */
   4527     (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id);
   4528     if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) {
   4529          return BCM_E_PARAM;
   4530     }
   4531 
   4532     if (flags & BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK) {
   4533 
   4534          if (vid != BCM_VLAN_NONE){
   4535              /* TRILL_Network Domain entry */
   4536              rv = _bcm_esw_trill_multicast_entry_delete(unit, 
   4537                                             TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS, 
   4538                                             vid, c_dmac, trill_tree_id);
   4539          }
   4540     } else {
   4541          /* TRILL-Network Domain - Unpruned entry */
   4542          if ((vid == BCM_VLAN_NONE) &&  (!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t)))) {       
   4543                 rv = _bcm_esw_trill_multicast_transit_entry_reset(unit, 
   4544                                        root_name);
   4545          } else if ((!sal_memcmp(c_dmac, mac_zero, sizeof(bcm_mac_t))) && (vid != BCM_VLAN_NONE)) {
   4546               BCM_IF_ERROR_RETURN (rv);
   4547               /* TRILL-Network Domain - Pruned entry - Short */
   4548               rv = _bcm_esw_trill_multicast_entry_delete(unit, 
   4549                                                  TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT, 
   4550                                                  vid, c_dmac, trill_tree_id);
   4551          } else if (vid != BCM_VLAN_NONE) {
   4552               BCM_IF_ERROR_RETURN (rv);
   4553               /* TRILL-Network Domain - Pruned entry - Long */
   4554               rv = _bcm_esw_trill_multicast_entry_delete(unit, 
   4555                                                  TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG,
   4556                                                  vid, c_dmac, trill_tree_id);
   4557          }  
   4558     }
   4559     return rv;
   4560 }
   4561 
   4562 /*
   4563  * Purpose:
   4564  *      Delete all TRILL multicast entries
   4565  * Parameters:
   4566  *		unit   - Device Number
   4567  */
   4568 
   4569 int
   4570 bcm_td_trill_multicast_delete_all(int unit, bcm_trill_name_t  root_name)
   4571 {
   4572     int rv=BCM_E_UNAVAIL;
   4573     uint8  trill_tree_id=0;
   4574 
   4575    (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id);
   4576     if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) {
   4577          return BCM_E_PARAM;
   4578     }
   4579 
   4580     BCM_IF_ERROR_RETURN(
   4581          _bcm_esw_trill_multicast_transit_entry_reset_all (unit, trill_tree_id));
   4582 
   4583    rv = _bcm_esw_trill_multicast_entry_delete_all(unit, trill_tree_id);
   4584 
   4585    return rv;
   4586 }
   4587 
   4588 /*
   4589  * Purpose:
   4590  *      Get TRILL multicast entry
   4591  * Parameters:
   4592  *           unit   - Device Number
   4593  *    trill_mc_entry - Trill Multicast Entry
   4594  */
   4595 
   4596 int
   4597 bcm_td_trill_multicast_entry_get( int unit, 
   4598     bcm_trill_multicast_entry_t *trill_mc_entry)
   4599 {
   4600     _bcm_td_trill_bookkeeping_t *trill_info;
   4601     int rv = BCM_E_NONE;
   4602     uint8  trill_tree_id=0;
   4603     bcm_mac_t mac_zero = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 
   4604     int l3mc_index=0;
   4605 
   4606     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   4607          return BCM_E_UNIT;
   4608     }
   4609     trill_info = TRILL_INFO(unit);
   4610 
   4611     /* Check Vlan range */
   4612     if (trill_mc_entry->c_vlan >= BCM_VLAN_INVALID) {
   4613          return BCM_E_PARAM;
   4614     }
   4615 
   4616     /* Check DA */
   4617     /* coverity[array_null] */
   4618     if (trill_mc_entry->c_dmac == NULL) {
   4619          return BCM_E_PARAM;
   4620     }
   4621 
   4622     trill_mc_entry->flags  |= BCM_TRILL_MULTICAST_STATIC;
   4623 
   4624     if (trill_mc_entry->flags & BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK) {
   4625 
   4626         if (trill_mc_entry->c_vlan != BCM_VLAN_NONE){
   4627              rv = _bcm_esw_trill_multicast_entry_get(unit, TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS, 
   4628                               trill_mc_entry->c_vlan, trill_mc_entry->c_dmac, 
   4629                               trill_tree_id, &trill_mc_entry->group);
   4630             l3mc_index = _BCM_MULTICAST_ID_GET(trill_mc_entry->group);
   4631             BCM_TRILL_L3MC_CHECK (unit, l3mc_index);
   4632             rv = bcm_td_multicast_trill_group_get(unit, l3mc_index, &trill_tree_id);
   4633             trill_mc_entry->root_name = trill_info->rootBridge[trill_tree_id];
   4634         } else if (trill_mc_entry->c_vlan == BCM_VLAN_NONE) {
   4635             /* Get EGR_IPMC.trill_tree_id */
   4636             l3mc_index = _BCM_MULTICAST_ID_GET(trill_mc_entry->group);
   4637             BCM_TRILL_L3MC_CHECK (unit, l3mc_index);
   4638             rv = bcm_td_multicast_trill_group_get(unit, l3mc_index, &trill_tree_id);
   4639             trill_mc_entry->root_name = trill_info->rootBridge[trill_tree_id];
   4640         }
   4641     } else {
   4642          /* Check Tree-ID */
   4643          (void) bcm_td_trill_tree_profile_get (unit, trill_mc_entry->root_name, &trill_tree_id);
   4644          if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) {
   4645                return BCM_E_PARAM;
   4646          }
   4647 
   4648          if ((trill_mc_entry->c_vlan == BCM_VLAN_NONE) &&  
   4649                      (!sal_memcmp(trill_mc_entry->c_dmac, mac_zero, sizeof(bcm_mac_t)))) {   
   4650                      rv = _bcm_esw_trill_multicast_transit_entry_get(unit, 
   4651                               trill_mc_entry->root_name, &trill_mc_entry->group);
   4652          } else if ((!sal_memcmp(trill_mc_entry->c_dmac, mac_zero, sizeof(bcm_mac_t))) && 
   4653                   (trill_mc_entry->c_vlan != BCM_VLAN_NONE)) {
   4654               /* TRILL-Network Domain - Unpruned entry */
   4655               rv = _bcm_esw_trill_multicast_entry_get(unit, TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT, 
   4656                               trill_mc_entry->c_vlan, trill_mc_entry->c_dmac, 
   4657                               trill_tree_id, &trill_mc_entry->group);
   4658          } else if (trill_mc_entry->c_vlan != BCM_VLAN_NONE) {
   4659               /* TRILL-Network Domain - Pruned entry - Long */
   4660               rv = _bcm_esw_trill_multicast_entry_get(unit, TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG, 
   4661                               trill_mc_entry->c_vlan, trill_mc_entry->c_dmac, 
   4662                               trill_tree_id, &trill_mc_entry->group);
   4663          }
   4664     }
   4665     return rv;
   4666 }
   4667 
   4668 /*
   4669  * Purpose:
   4670  *      Verify Trill Multicast group
   4671  * Parameters:
   4672  *      unit         - (IN) Unit number.
   4673  *      l3mc_group        - (IN) Multicast Group
   4674  * Returns:
   4675  *      BCM_E_XXX
   4676  * Notes:
   4677  */
   4678 int
   4679 bcm_td_trill_multicast_check(int unit, bcm_multicast_t l3mc_group)
   4680 {
   4681     _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit);
   4682     int rv=BCM_E_UNAVAIL;
   4683     int l3mc_index=0;
   4684 
   4685     if (_BCM_MULTICAST_IS_TRILL(l3mc_group)) {
   4686           l3mc_index = _BCM_MULTICAST_ID_GET(l3mc_group);
   4687           if (trill_info->multicast_count[l3mc_index].network_port_count) {
   4688               BCM_TRILL_L3MC_CHECK (unit, l3mc_index);  
   4689               return BCM_E_NONE;
   4690           }
   4691     }
   4692     return rv;
   4693 }
   4694 
   4695 
   4696 
   4697 /*
   4698  * Description:
   4699  *      Traverse  TRILL Unpruned Multicast entries
   4700  * Parameters:
   4701  *     unit             - device number
   4702  *     trav_st        - Traverse structure with all the data.
   4703  * Return:
   4704  *     BCM_E_XXX
   4705  */
   4706 int
   4707 bcm_td_trill_unpruned_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st)
   4708 {
   4709    /* Indexes to iterate over memories, chunks and entries */
   4710     int             chnk_idx=0, ent_idx=0, chnk_idx_max=0, mem_idx_max=0;
   4711     int             buf_size=0, chunksize=0, chnk_end=0;
   4712     uint32          *unpruned_trill_tbl_chnk;
   4713     mpls_entry_entry_t *ment;
   4714     int             rv = BCM_E_NONE;
   4715     soc_mem_t     mem;
   4716     int    key_type=0;
   4717     uint8   tree_id=0xff;
   4718     bcm_trill_name_t  root_name=0;
   4719     bcm_trill_multicast_entry_t  trill_mc;
   4720 
   4721     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
   4722 
   4723     mem = MPLS_ENTRYm;
   4724 
   4725     if (!soc_mem_index_count(unit, mem)) {
   4726         return BCM_E_NONE;
   4727     }
   4728 
   4729     chunksize = 4096;
   4730 
   4731     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   4732     unpruned_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill multicast unpruned traverse");
   4733     if (NULL == unpruned_trill_tbl_chnk) {
   4734         return BCM_E_MEMORY;
   4735     }
   4736 
   4737     mem_idx_max = soc_mem_index_max(unit, mem);
   4738     for (chnk_idx = soc_mem_index_min(unit, mem); 
   4739          chnk_idx <= mem_idx_max; chnk_idx += chunksize) {
   4740         sal_memset((void *)unpruned_trill_tbl_chnk, 0, buf_size);
   4741 
   4742         chnk_idx_max = 
   4743             ((chnk_idx + chunksize) < mem_idx_max) ? 
   4744             (chnk_idx + chunksize - 1) : mem_idx_max;
   4745 
   4746         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   4747                                 chnk_idx, chnk_idx_max, unpruned_trill_tbl_chnk);
   4748         if (SOC_FAILURE(rv)) {
   4749             break;
   4750         }
   4751         chnk_end = (chnk_idx_max - chnk_idx);
   4752         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   4753             ment = soc_mem_table_idx_to_pointer(unit, mem, mpls_entry_entry_t *, 
   4754                                              unpruned_trill_tbl_chnk, ent_idx);
   4755 
   4756             if (!soc_mem_field32_get(unit, mem, ment, VALIDf)) {
   4757                 continue;
   4758             }
   4759           
   4760             /* Match the Key Type to TRILL */
   4761             key_type = soc_mem_field32_get(unit, mem, ment, KEY_TYPEf);
   4762 
   4763             if (key_type != 0x5) { /* RBRIDGE_NICKNAME */
   4764                 continue;
   4765             }
   4766 
   4767             /* Skip entries that discard multicast destinations */
   4768             if (soc_mem_field_valid(unit, MPLS_ENTRYm, 
   4769                                     TRILL__MCAST_DST_DISCARDf)) {
   4770                 if (soc_mem_field32_get(unit,
   4771                                         mem, ment, TRILL__MCAST_DST_DISCARDf)) {
   4772                     continue;
   4773                 }
   4774             }
   4775 
   4776 
   4777             /* Check for Valid Tree_Id */
   4778             tree_id = soc_mem_field32_get(unit, mem, ment, TRILL__TREE_IDf);
   4779             if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
   4780                 continue;
   4781             }
   4782             root_name = soc_mem_field32_get(unit, mem, ment, TRILL__RBRIDGE_NICKNAMEf);
   4783             (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name);
   4784             if (root_name != trill_mc.root_name) {
   4785                 continue;
   4786             }
   4787 
   4788             _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
   4789                               _BCM_MULTICAST_TYPE_TRILL,  
   4790                               soc_mem_field32_get (unit, mem, ment,
   4791                                 TRILL__L3MC_INDEXf));
   4792 
   4793             rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data);
   4794             if (BCM_FAILURE(rv)) {
   4795                 break;
   4796             }
   4797         }
   4798         if (BCM_FAILURE(rv)) {
   4799             break;
   4800         }
   4801     }
   4802     soc_cm_sfree(unit, unpruned_trill_tbl_chnk);
   4803     return rv;        
   4804 }
   4805 
   4806 /*
   4807  * Description:
   4808  *      Traverse  TRILL Access Default Multicast entries
   4809  * Parameters:
   4810  *     unit             - device number
   4811  *     trav_st        - Traverse structure with all the data.
   4812  * Return:
   4813  *     BCM_E_XXX
   4814  */
   4815 int
   4816 bcm_td_trill_access_default_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st)
   4817 {
   4818    /* Indexes to iterate over memories, chunks and entries */
   4819     int             chnk_idx=0, ent_idx=0, chnk_idx_max=0, mem_idx_max=0;
   4820     int             buf_size=0, chunksize=0, chnk_end=0;
   4821     uint32          *access_trill_vlan_chnk;
   4822     vlan_tab_entry_t   *vlant;
   4823     int             rv = BCM_E_NONE;
   4824     soc_mem_t     mem;
   4825     int    bc_f=0, uuc_f=0, umc_f=0;
   4826     bcm_trill_multicast_entry_t  trill_mc;
   4827 
   4828     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
   4829 
   4830     mem = VLAN_TABm;
   4831 
   4832     if (!soc_mem_index_count(unit, mem)) {
   4833         return BCM_E_NONE;
   4834     }
   4835 
   4836     chunksize = 1024;
   4837 
   4838     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   4839     access_trill_vlan_chnk = soc_cm_salloc(unit, buf_size, "trill access default multicast traverse");
   4840     if (NULL == access_trill_vlan_chnk) {
   4841         return BCM_E_MEMORY;
   4842     }
   4843 
   4844     mem_idx_max = soc_mem_index_max(unit, mem);
   4845     for (chnk_idx = soc_mem_index_min(unit, mem); 
   4846          chnk_idx <= mem_idx_max; chnk_idx += chunksize) {
   4847         sal_memset((void *)access_trill_vlan_chnk, 0, buf_size);
   4848 
   4849         chnk_idx_max = 
   4850             ((chnk_idx + chunksize) < mem_idx_max) ? 
   4851             (chnk_idx + chunksize - 1) : mem_idx_max;
   4852 
   4853         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   4854                                 chnk_idx, chnk_idx_max, access_trill_vlan_chnk);
   4855         if (SOC_FAILURE(rv)) {
   4856             break;
   4857         }
   4858         chnk_end = (chnk_idx_max - chnk_idx);
   4859         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   4860             vlant = soc_mem_table_idx_to_pointer(unit, mem, vlan_tab_entry_t *, 
   4861                                              access_trill_vlan_chnk, ent_idx);
   4862 
   4863             if (!soc_mem_field32_get(unit, mem, vlant, VALIDf)) {
   4864                 continue;
   4865             }
   4866           
   4867            if (SOC_MEM_FIELD_VALID(unit, mem, 
   4868                 BC_TRILL_NETWORK_RECEIVERS_PRESENTf)) {
   4869                      bc_f = soc_mem_field32_get(unit, mem, vlant,
   4870                                BC_TRILL_NETWORK_RECEIVERS_PRESENTf);
   4871            }
   4872            if (SOC_MEM_FIELD_VALID(unit, mem, 
   4873                 UMC_TRILL_NETWORK_RECEIVERS_PRESENTf)) {
   4874                      umc_f = soc_mem_field32_get(unit, VLAN_TABm, vlant,
   4875                                UMC_TRILL_NETWORK_RECEIVERS_PRESENTf);
   4876            }
   4877            if (SOC_MEM_FIELD_VALID(unit, mem, 
   4878                 UUC_TRILL_NETWORK_RECEIVERS_PRESENTf)) {
   4879                      uuc_f = soc_mem_field32_get(unit, mem, vlant,
   4880                                UUC_TRILL_NETWORK_RECEIVERS_PRESENTf);
   4881            }
   4882 
   4883             if ((!bc_f) && (!uuc_f) && (!umc_f) ) {
   4884                 continue;
   4885             }
   4886 
   4887             _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
   4888                               _BCM_MULTICAST_TYPE_TRILL,  
   4889                               soc_mem_field32_get (unit, mem, vlant,
   4890                                 TRILL_DOMAIN_NONUC_REPL_INDEXf));
   4891 
   4892             trill_mc.flags = BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK;
   4893             rv = bcm_td_multicast_trill_rootname_get(unit, trill_mc.group, &trill_mc.root_name);
   4894             if (BCM_FAILURE(rv)) {
   4895                  continue;
   4896             }
   4897             rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data);
   4898             if (BCM_FAILURE(rv)) {
   4899                 break;
   4900             }
   4901         }
   4902         if (BCM_FAILURE(rv)) {
   4903             break;
   4904         }
   4905     }
   4906     soc_cm_sfree(unit, access_trill_vlan_chnk);
   4907     return rv;        
   4908 
   4909 }
   4910 
   4911 /*
   4912  * Purpose:
   4913  *      Traverse all valid TRILL Multicast entries and call the
   4914  * 	 supplied callback routine.
   4915  * Parameters:
   4916  *     unit   - Device Number
   4917  *     cb  - User callback function, called once per Trill Multicast entry.
   4918  *     user_data - cookie
   4919  */
   4920 
   4921 int
   4922 bcm_td_trill_multicast_traverse(int unit, bcm_trill_multicast_entry_traverse_cb  cb,
   4923                                                         void *user_data)
   4924 {
   4925     _bcm_td_trill_multicast_entry_traverse_t  trav_st;
   4926     int rv = BCM_E_NONE;
   4927 
   4928     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   4929          return BCM_E_UNIT;
   4930     }
   4931      /* If no callback provided, we are done.  */ 
   4932      if (NULL == cb) { 
   4933           return BCM_E_NONE; 
   4934      } 
   4935 
   4936     sal_memset(&trav_st, 0, sizeof(_bcm_td_trill_multicast_entry_traverse_t));
   4937     
   4938     trav_st.user_cb = cb;
   4939     trav_st.user_data = user_data;
   4940 
   4941     /* Traverse Unpruned Trill Multicast entry */
   4942     rv = _bcm_esw_trill_unpruned_entry_traverse(unit, &trav_st);
   4943     if (BCM_SUCCESS(rv)) {
   4944        /* Traverse Pruned Trill Network Multicast entry */
   4945        rv = _bcm_esw_trill_network_multicast_entry_traverse(unit, &trav_st);
   4946        if (BCM_SUCCESS(rv)) {
   4947            /* Traverse Trill Access Multicast entry */
   4948            rv = _bcm_esw_trill_access_multicast_entry_traverse(unit, &trav_st);
   4949            if (BCM_SUCCESS(rv)) {
   4950                /* Traverse Trill default Multicast entry */
   4951                rv = bcm_td_trill_access_default_multicast_entry_traverse(unit, &trav_st);
   4952            }
   4953        }
   4954     }
   4955     return rv;
   4956 }
   4957 
   4958 
   4959 /*
   4960  * Purpose:
   4961  *      Add C-VLAN multicast_idx when enabled for TRILL
   4962  * Parameters:
   4963  *      unit         - (IN) Unit number.
   4964  *      vlan         - (IN) C-VLAN
   4965  *      vtab         - (IN/OUT) Vlan Table entry
   4966  * Returns:
   4967  *      BCM_E_XXX
   4968  * Notes:
   4969  */
   4970 int
   4971 bcm_td_trill_vlan_multicast_group_add(int unit, bcm_vlan_t vlan, vlan_tab_entry_t   *vtab)
   4972 {
   4973     bcm_pbmp_t vlan_pbmp, vlan_ubmp, pbmp, l3_pbmp;
   4974     soc_field_t group_type[3] = {BC_IDXf, UMC_IDXf, UUC_IDXf};
   4975     int i=0, mc_idx=0;
   4976     int rv = BCM_E_NONE;
   4977     bcm_multicast_t mc_grp;
   4978 
   4979     /* Enable VP switching on the VLAN */
   4980     if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
   4981        if (!soc_mem_field32_get(unit, VLAN_TABm, vtab, 
   4982                                      TRILL_ACCESS_RECEIVERS_PRESENTf)) {
   4983             soc_mem_field32_set(unit, VLAN_TABm, vtab, 
   4984                        TRILL_ACCESS_RECEIVERS_PRESENTf, 1);
   4985 
   4986             rv = bcm_td_l2_trill_vlan_multicast_entry_modify (unit, vlan, 0x1);
   4987             if (rv < 0) {
   4988                 return rv;
   4989             } 
   4990 
   4991             if (SHR_BITGET(vlan_info[unit].vp_mode, vlan)) {
   4992                 return rv;
   4993             }
   4994 
   4995             soc_mem_field32_set(unit, VLAN_TABm, vtab, VIRTUAL_PORT_ENf, 1);
   4996             
   4997             /* Also need to copy the physical port members to the L2_BITMAP of
   4998              * the IPMC entry for each group once we've gone virtual */
   4999             rv = mbcm_driver[unit]->mbcm_vlan_port_get
   5000                 (unit, vlan, &vlan_pbmp, &vlan_ubmp, NULL);
   5001                                                    
   5002             if (rv < 0) {
   5003                 return rv;
   5004             }
   5005 
   5006             /* Deal with each group */
   5007             for (i = 0; i < 3; i++) {
   5008                 BCM_PBMP_CLEAR(l3_pbmp);
   5009                 mc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, vtab, group_type[i]);
   5010                 if (BCM_FAILURE(_bcm_tr_multicast_ipmc_group_type_get(unit,
   5011                                                         mc_idx, &mc_grp))) {
   5012                     continue;
   5013                 }
   5014                 if ((mc_idx >= 0) && 
   5015                     (mc_idx < soc_mem_index_count(unit, L3_IPMCm))) {
   5016                     rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &pbmp, 
   5017                                                  &l3_pbmp);
   5018                     if (rv < 0) {
   5019                         return rv;
   5020                     }
   5021                     rv = _bcm_esw_multicast_ipmc_write(unit, mc_idx, vlan_pbmp, 
   5022                                                   l3_pbmp, TRUE);
   5023                     if (rv < 0) {
   5024                         return rv;
   5025                     }
   5026                 }
   5027             }
   5028         }
   5029     }
   5030     return rv;
   5031 }
   5032 
   5033 /*
   5034  * Purpose:
   5035  *      Delete C-VLAN multicast_idx when enabled for TRILL
   5036  * Parameters:
   5037  *      unit         - (IN) Unit number.
   5038  *      vlan         - (IN) C-VLAN
   5039  *      vtab         - (IN/OUT) Vlan Table entry
   5040  * Returns:
   5041  *      BCM_E_XXX
   5042  * Notes:
   5043  */
   5044 int
   5045 bcm_td_trill_vlan_multicast_group_delete(int unit, bcm_vlan_t vlan, vlan_tab_entry_t *vtab)
   5046 {
   5047     bcm_pbmp_t vlan_pbmp, pbmp, l3_pbmp;
   5048     soc_field_t group_type[3] = {BC_IDXf, UMC_IDXf, UUC_IDXf};
   5049     int i=0, mc_idx=0;
   5050     int rv = BCM_E_NONE;
   5051     bcm_multicast_t mc_grp;
   5052 
   5053     /* Enable VP switching on the VLAN */
   5054     if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
   5055         if (soc_mem_field32_get(unit, VLAN_TABm, vtab, 
   5056                             TRILL_ACCESS_RECEIVERS_PRESENTf)) {
   5057             soc_mem_field32_set(unit, VLAN_TABm, vtab, 
   5058                             TRILL_ACCESS_RECEIVERS_PRESENTf, 0);
   5059 
   5060             rv = bcm_td_l2_trill_vlan_multicast_entry_modify(unit, vlan, 0x0);
   5061             if (rv < 0) {
   5062                 return rv;
   5063             }
   5064 
   5065             if (SHR_BITGET(vlan_info[unit].vp_mode, vlan)) {
   5066                 return rv;
   5067             }   
   5068 
   5069             soc_mem_field32_set(unit, VLAN_TABm, vtab, VIRTUAL_PORT_ENf, 0);
   5070 
   5071             /* Deal with each group */
   5072             for (i = 0; i < 3; i++) {
   5073                 BCM_PBMP_CLEAR(pbmp);
   5074                 mc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, vtab, group_type[i]);
   5075                 if (BCM_FAILURE(_bcm_tr_multicast_ipmc_group_type_get(unit,
   5076                                                             mc_idx, &mc_grp))) {
   5077                     continue;
   5078                 }
   5079 
   5080                 if ((mc_idx >= 0) && (mc_idx < soc_mem_index_count(unit, L3_IPMCm))) {
   5081                     rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &vlan_pbmp, 
   5082                                                  &l3_pbmp);
   5083                     if (rv < 0) {
   5084                        return rv;
   5085                     }
   5086                     rv = _bcm_esw_multicast_ipmc_write(unit, mc_idx, pbmp, 
   5087                                                l3_pbmp, TRUE);
   5088                     if (rv < 0) {
   5089                        return rv;
   5090                     }
   5091                 }
   5092             }
   5093         }
   5094     }
   5095     return rv;
   5096 
   5097 }
   5098 /*
   5099  * Purpose:
   5100  *      Add TRILL Gports to L2MC
   5101  * Parameters:
   5102  *      unit         - (IN) Unit number.
   5103  *      port         - (IN) Gport.
   5104  *      mc_index        - (IN) Multicast Index
   5105  * Returns:
   5106  *      BCM_E_XXX
   5107  * Notes:
   5108  */
   5109 int
   5110 bcm_td_trill_egress_add(int unit, bcm_multicast_t l3mc_group)
   5111 {
   5112     _bcm_td_trill_bookkeeping_t *trill_info;
   5113     int rv = BCM_E_NONE;
   5114     int l3mc_index=0;
   5115     
   5116     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   5117          return BCM_E_UNIT;
   5118     }
   5119 
   5120     trill_info = TRILL_INFO(unit);
   5121     l3mc_index = _BCM_MULTICAST_ID_GET(l3mc_group);
   5122 
   5123     if (trill_info->multicast_count[l3mc_index].network_port_count == 0) {
   5124         trill_info->multicast_count[l3mc_index].l3mc_group = l3mc_group;
   5125         trill_info->multicast_count[l3mc_index].network_port_count++;
   5126     } else if (trill_info->multicast_count[l3mc_index].network_port_count > 0) {
   5127         trill_info->multicast_count[l3mc_index].network_port_count++;
   5128     }
   5129     return rv;
   5130 }
   5131 
   5132 /*
   5133  * Purpose:
   5134  *      Delete TRILL Gports from L2MC
   5135  * Parameters:
   5136  *      unit         - (IN) Unit number.
   5137  *      port         - (IN) Gport.
   5138  *      mc_index        - (IN) Multicast Index
   5139  * Returns:
   5140  *      BCM_E_XXX
   5141  * Notes:
   5142  */
   5143 int
   5144 bcm_td_trill_egress_delete(int unit, bcm_multicast_t l3mc_group)
   5145 {
   5146     _bcm_td_trill_bookkeeping_t *trill_info;
   5147     int rv = BCM_E_NONE;
   5148     int l3mc_index=0;
   5149 
   5150     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   5151          return BCM_E_UNIT;
   5152     }
   5153 
   5154     trill_info = TRILL_INFO(unit);
   5155 
   5156     l3mc_index = _BCM_MULTICAST_ID_GET(l3mc_group);
   5157     l3mc_group = trill_info->multicast_count[l3mc_index].l3mc_group;
   5158     trill_info->multicast_count[l3mc_index].network_port_count--;
   5159 
   5160     return rv;
   5161 }
   5162 
   5163 /*
   5164  * Function:
   5165  *      _bcm_td_trill_multicast_source_entry_key_set
   5166  * Purpose:
   5167  *      Set TRILL Multicast RPF entry key
   5168  * Parameters:
   5169  *  IN :  Unit
   5170  *  IN :  root_name
   5171  *  IN :  source_name
   5172  *  IN :  gport to desired-neighbor
   5173  *  IN :  entry pointer
   5174  * Returns:
   5175  *       BCM_E_XXX
   5176  */
   5177 
   5178 STATIC int
   5179  _bcm_td_trill_multicast_source_entry_key_set(int unit, 
   5180                                          bcm_trill_name_t root_name, bcm_trill_name_t source_name, 
   5181                                          bcm_gport_t gport,  bcm_if_t encap_intf, L3_ENTRY_T *l3_key)
   5182  {
   5183     int rv = BCM_E_NONE;
   5184     uint8  trill_tree_id=0;
   5185     bcm_module_t  local_modid=-1;
   5186     bcm_port_t    local_port=-1;
   5187     bcm_trunk_t  local_tgid=BCM_TRUNK_INVALID;
   5188     int local_id=-1;
   5189     soc_mem_t mem;
   5190 
   5191     (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id);
   5192     if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) {
   5193          return BCM_E_PARAM;
   5194     }
   5195     rv = _bcm_esw_gport_resolve(unit, gport, &local_modid,
   5196                                        &local_port, &local_tgid, &local_id);
   5197     if (rv < 0) {
   5198          return SOC_E_UNAVAIL;
   5199     }
   5200 
   5201 #if defined(BCM_TRIUMPH3_SUPPORT)
   5202     if (SOC_IS_TRIUMPH3(unit)) {
   5203         mem = L3_ENTRY_1m;
   5204         soc_mem_field32_set(unit, mem, l3_key, KEY_TYPEf,
   5205                             SOC_MEM_KEY_L3_ENTRY_1_TRILL_TRILL);
   5206     } else 
   5207 #endif /* BCM_TRIUMPH3_SUPPORT */
   5208 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
   5209     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) {
   5210         mem = L3_ENTRY_IPV4_UNICASTm;
   5211         soc_mem_field32_set(unit, mem, l3_key, KEY_TYPEf,
   5212                             TD2_L3_HASH_KEY_TYPE_TRILL);
   5213     } else 
   5214 #endif /* BCM_TRIDENT2_SUPPORT */ 
   5215    {
   5216         mem = L3_ENTRY_IPV4_UNICASTm;
   5217         soc_mem_field32_set(unit, mem, l3_key, KEY_TYPEf,
   5218                             TR_L3_HASH_KEY_TYPE_TRILL);
   5219 
   5220     }
   5221 
   5222     soc_mem_field32_set(unit, mem, l3_key, 
   5223                    TRILL__INGRESS_RBRIDGE_NICKNAMEf, source_name);
   5224     soc_mem_field32_set(unit, mem, l3_key, 
   5225                    TRILL__TREE_IDf, trill_tree_id);
   5226     if (BCM_TRUNK_INVALID != local_tgid) {
   5227          soc_mem_field32_set(unit, mem, l3_key, 
   5228                    TRILL__EXPECTED_TGIDf, local_tgid);
   5229          soc_mem_field32_set(unit, mem, l3_key, 
   5230                    TRILL__EXPECTED_Tf, 0x1);
   5231     } else {
   5232          soc_mem_field32_set(unit, mem, l3_key, 
   5233                    TRILL__EXPECTED_MODULE_IDf, local_modid);
   5234          soc_mem_field32_set(unit, mem, l3_key, 
   5235                    TRILL__EXPECTED_PORT_NUMf, local_port);
   5236     }
   5237 
   5238     soc_mem_field32_set(unit, mem, l3_key, VALIDf, 1);
   5239     return rv;
   5240  }
   5241 
   5242 /*
   5243  * Purpose:
   5244  *       Add TRILL multicast RPF  entry
   5245  * Parameters:
   5246  *      unit  - Device Number
   5247  *      root_name  - (IN) Trill Root_RBridge
   5248  *      source_name - (IN) Source Rbridge
   5249  *      port - (IN) Ingress port
   5250  */
   5251 
   5252 int
   5253 bcm_td_trill_multicast_source_add( int unit,
   5254                                                                      bcm_trill_name_t root_name, 
   5255                                                                      bcm_trill_name_t source_name, 
   5256                                                                      bcm_gport_t gport,
   5257                                                                      bcm_if_t   encap_intf)
   5258 {
   5259     L3_ENTRY_T l3_key, l3_entry;
   5260     int rv = BCM_E_NONE;
   5261     int l3_entry_index=0;
   5262     soc_mem_t mem;
   5263 
   5264     sal_memset(&l3_key, 0, sizeof(L3_ENTRY_T));
   5265     sal_memset(&l3_entry, 0, sizeof(L3_ENTRY_T));
   5266 
   5267     if (SOC_IS_TRIUMPH3(unit)) {
   5268         mem = L3_ENTRY_1m;
   5269     } else {
   5270         mem = L3_ENTRY_IPV4_UNICASTm;
   5271     }
   5272 
   5273      /* Check for Gport type - Mod Port or TRUNK Port */
   5274      if ( (SOC_GPORT_IS_TRUNK(gport)) ||
   5275            (SOC_GPORT_IS_LOCAL(gport)) || 
   5276            (SOC_GPORT_IS_DEVPORT(gport)) || 
   5277            (SOC_GPORT_IS_MODPORT(gport))) {
   5278          BCM_IF_ERROR_RETURN(
   5279               _bcm_td_trill_multicast_source_entry_key_set(unit, root_name, 
   5280                         source_name, gport, encap_intf, &l3_key));
   5281     } else {
   5282             return BCM_E_PARAM;
   5283     }
   5284 
   5285 
   5286     rv = soc_mem_search(unit, mem, 
   5287                         MEM_BLOCK_ANY, &l3_entry_index,
   5288                         &l3_key, &l3_entry, 0);
   5289     if (rv == SOC_E_NONE) {
   5290          rv = soc_mem_write(unit, mem,
   5291                         MEM_BLOCK_ALL, l3_entry_index, &l3_key);
   5292     } else if (rv != SOC_E_NOT_FOUND) {
   5293         return rv;
   5294     } else {
   5295          rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &l3_key);
   5296     }
   5297     return rv;
   5298 }
   5299 
   5300 /*
   5301  * Purpose:
   5302  *       Delete TRILL multicast RPF  entry
   5303  * Parameters:
   5304  *             unit  - Device Number
   5305  *             root_name  - (IN) Trill Root_RBridge
   5306  *             source_name - (IN) Source Rbridge
   5307  *             port - (IN) Ingress port
   5308  */
   5309 
   5310 int
   5311 bcm_td_trill_multicast_source_delete( int unit,
   5312                                                                          bcm_trill_name_t root_name, 
   5313                                                                          bcm_trill_name_t source_name, 
   5314                                                                          bcm_gport_t gport,
   5315                                                                          bcm_if_t  encap_intf)
   5316 {
   5317     L3_ENTRY_T l3_entry;
   5318     int rv = BCM_E_UNAVAIL;
   5319     int l3_entry_index=0;
   5320     soc_mem_t mem;
   5321 
   5322     if (SOC_IS_TRIUMPH3(unit)) {
   5323         mem = L3_ENTRY_1m;
   5324     } else {
   5325         mem = L3_ENTRY_IPV4_UNICASTm;
   5326     }
   5327 
   5328     sal_memset(&l3_entry, 0, sizeof(L3_ENTRY_T));
   5329     if ( (SOC_GPORT_IS_TRUNK(gport)) ||
   5330            (SOC_GPORT_IS_LOCAL(gport)) || 
   5331            (SOC_GPORT_IS_DEVPORT(gport)) || 
   5332            (SOC_GPORT_IS_MODPORT(gport))) {
   5333          (void) _bcm_td_trill_multicast_source_entry_key_set(unit, root_name, 
   5334                         source_name, gport, encap_intf, &l3_entry);
   5335     } else {
   5336             return BCM_E_PARAM;
   5337     }
   5338 
   5339     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l3_entry_index,
   5340                              &l3_entry, &l3_entry, 0);
   5341     if (rv < 0) {
   5342          return rv;
   5343     }
   5344    
   5345     /* Delete the entry from HW */
   5346     rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, &l3_entry);
   5347     
   5348     if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
   5349        return rv;
   5350     } else {
   5351        return BCM_E_NONE;
   5352     }
   5353 }
   5354 
   5355 /*
   5356  * Purpose:
   5357  *       Get TRILL multicast RPF  entry
   5358  * Parameters:
   5359  *             unit - Device Number
   5360  *             root_name  - (IN) Trill Root_RBridge
   5361  *             source_name - (IN) Source Rbridge
   5362  *             port  - (OUT) Ingress port
   5363  */
   5364 
   5365 int
   5366 bcm_td_trill_multicast_source_get( int unit,
   5367                                                                     bcm_trill_name_t root_name, 
   5368                                                                     bcm_trill_name_t source_name, 
   5369                                                                     bcm_gport_t *gport)
   5370 {
   5371     L3_ENTRY_T l3_key, l3_entry;
   5372     int l3_entry_index=0;
   5373     uint8  trill_tree_id=0;
   5374     bcm_module_t  module_id=0, mod_out=0;
   5375     bcm_port_t    port_num=0, port_out=0;
   5376     bcm_trunk_t  tgid=0;
   5377     soc_mem_t mem;
   5378 
   5379     sal_memset(&l3_key, 0, sizeof(L3_ENTRY_T));
   5380 
   5381     if (SOC_IS_TRIUMPH3(unit)) {
   5382         mem = L3_ENTRY_1m;
   5383     } else {
   5384         mem = L3_ENTRY_IPV4_UNICASTm;
   5385     }
   5386  
   5387     (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id);
   5388     if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) {
   5389          return BCM_E_PARAM;
   5390     }
   5391 
   5392     soc_mem_field32_set(unit, mem, &l3_key, TRILL__INGRESS_RBRIDGE_NICKNAMEf, source_name);
   5393 
   5394     soc_mem_field32_set(unit, mem, &l3_key, TRILL__TREE_IDf, trill_tree_id);
   5395 
   5396 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
   5397     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) {
   5398         soc_mem_field32_set(unit, mem, &l3_key, KEY_TYPEf,
   5399                                  TD2_L3_HASH_KEY_TYPE_TRILL);
   5400     } else 
   5401 #endif /* BCM_TRIDENT2_SUPPORT */
   5402     {
   5403         soc_mem_field32_set(unit, mem, &l3_key, KEY_TYPEf,
   5404                                  TR_L3_HASH_KEY_TYPE_TRILL);
   5405     }
   5406 
   5407     BCM_IF_ERROR_RETURN (
   5408     soc_mem_search(unit, mem, MEM_BLOCK_ANY,
   5409                              &l3_entry_index, &l3_key, &l3_entry, 0));
   5410 
   5411     if (soc_mem_field32_get(unit, mem, &l3_entry, TRILL__EXPECTED_Tf)) {
   5412          tgid = soc_mem_field32_get(unit, mem,
   5413                              &l3_entry, TRILL__EXPECTED_TGIDf);
   5414          SOC_GPORT_TRUNK_SET(*gport, tgid);
   5415     } else {
   5416          module_id = soc_mem_field32_get(unit, mem,
   5417                              &l3_entry, TRILL__EXPECTED_MODULE_IDf);
   5418          port_num = soc_mem_field32_get(unit, mem,
   5419                              &l3_entry, TRILL__EXPECTED_PORT_NUMf);
   5420          BCM_IF_ERROR_RETURN (
   5421                    _bcm_gport_modport_hw2api_map(unit, module_id,
   5422                                                                           port_num, &mod_out,
   5423                                                                           &port_out));
   5424          SOC_GPORT_MODPORT_SET(*gport, mod_out, port_out);
   5425     }
   5426     return BCM_E_NONE;
   5427 }
   5428 
   5429 /* Purpose:
   5430 *	   Traverse all valid TRILL Multicast RPF entries and call the
   5431 *	supplied callback routine.
   5432 * Parameters:
   5433 *	   unit   - Device Number
   5434 *	   cb		 - User callback function, called once per Trill Multicast entry.
   5435 *	   user_data - cookie
   5436 */
   5437 
   5438 int
   5439 bcm_td_trill_multicast_source_traverse(int unit, bcm_trill_multicast_source_traverse_cb cb,
   5440                                        void *user_data)
   5441 {
   5442     uint32 *l3_entry_p;
   5443     uint8  tree_id=0;
   5444     bcm_module_t  module_id=0, mod_out=0;
   5445     bcm_port_t    port_num=0, port_out=0;
   5446     bcm_trunk_t  tgid=0;
   5447     bcm_gport_t gport=0;
   5448     soc_mem_t mem;
   5449     uint32 trill_key_type=0xff;
   5450     bcm_trill_name_t root_name=0;
   5451     bcm_trill_name_t source_name=0;
   5452 
   5453     int table_ent_size=0;         /* Table entry size. */
   5454     int table_size=0;             /* Number of entries in the table. */
   5455     int idx_max=0;                /* Maximum iteration index.        */
   5456     int idx_min=0;                /* Minimum iteration index.        */
   5457     int idx=0;                    /* Iterator index.                 */
   5458     char *l3_tbl_ptr = NULL;    /* Table dma pointer.              */
   5459     int rv = BCM_E_NONE;        /* Operation return value.         */
   5460     _bcm_td_trill_bookkeeping_t *trill_info;
   5461 
   5462     trill_info = TRILL_INFO(unit);
   5463 
   5464     /* If no callback provided, we are done.  */
   5465     if (NULL == cb) {
   5466         return (BCM_E_NONE);
   5467     }
   5468 
   5469     if (SOC_IS_TRIUMPH3(unit)) {
   5470         mem = L3_ENTRY_1m;
   5471     } else {
   5472         mem = L3_ENTRY_IPV4_UNICASTm;
   5473     }
   5474 
   5475     /* Get table boundaries. */
   5476     idx_max = soc_mem_index_max(unit, mem);
   5477     idx_min =  soc_mem_index_min(unit, mem);
   5478 
   5479     /* Get single entry size. */
   5480     table_ent_size = BCM_XGS3_L3_ENT_SZ(unit, v4);
   5481 
   5482     soc_mem_lock(unit, mem);
   5483     /* Dma the table - to speed up operation. */
   5484     rv = bcm_xgs3_l3_tbl_dma(unit, mem, table_ent_size, 
   5485                               "trill_rpf_tbl", &l3_tbl_ptr, &table_size);
   5486     soc_mem_unlock(unit, mem);
   5487 
   5488     if (BCM_FAILURE(rv)) {
   5489         if(l3_tbl_ptr) {
   5490             soc_cm_sfree(unit, l3_tbl_ptr);
   5491         }
   5492         return rv; 
   5493     }
   5494 
   5495     /* Iterate over all the entries - show matching ones. */
   5496     for (idx = idx_min; idx <= idx_max; idx++) {
   5497         l3_entry_p =
   5498             soc_mem_table_idx_to_pointer(unit, mem,
   5499                                          uint32 *,
   5500                                          l3_tbl_ptr, idx);
   5501 
   5502         /* Check if this is an TRILL RPF entry */
   5503 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
   5504         if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) {
   5505             trill_key_type = TD2_L3_HASH_KEY_TYPE_TRILL;
   5506         } else 
   5507 #endif /* BCM_TRIDENT2_SUPPORT */
   5508         {
   5509             trill_key_type = TR_L3_HASH_KEY_TYPE_TRILL;
   5510         }
   5511         if (soc_mem_field32_get(unit, mem, l3_entry_p, KEY_TYPEf) != trill_key_type) {
   5512             continue;
   5513         }
   5514 
   5515         tree_id = soc_mem_field32_get(unit, mem, l3_entry_p, TRILL__TREE_IDf);
   5516         if (!(tree_id < BCM_MAX_NUM_TRILL_TREES)) {
   5517             /* Not a vaild Root tree: entry shouldn't exist */
   5518             continue;
   5519         }
   5520 
   5521         root_name = trill_info->rootBridge[tree_id];
   5522         source_name = soc_mem_field32_get(unit, mem, l3_entry_p, 
   5523                                           TRILL__INGRESS_RBRIDGE_NICKNAMEf);
   5524 
   5525         if (soc_mem_field32_get(unit, mem, l3_entry_p, TRILL__EXPECTED_Tf)) {
   5526              tgid = soc_mem_field32_get(unit, mem,
   5527                                  l3_entry_p, TRILL__EXPECTED_TGIDf);
   5528              SOC_GPORT_TRUNK_SET(gport, tgid);
   5529         } else {
   5530              module_id = soc_mem_field32_get(unit, mem,
   5531                                  l3_entry_p, TRILL__EXPECTED_MODULE_IDf);
   5532              port_num = soc_mem_field32_get(unit, mem,
   5533                                  l3_entry_p, TRILL__EXPECTED_PORT_NUMf);
   5534              rv = _bcm_gport_modport_hw2api_map(unit, module_id, port_num, &mod_out,
   5535                                                 &port_out);
   5536              if (BCM_FAILURE(rv)) {
   5537                  break;
   5538              }
   5539              SOC_GPORT_MODPORT_SET(gport, mod_out, port_out);
   5540         }
   5541 
   5542         rv = (*cb) (unit, root_name, source_name, gport, user_data);
   5543 #ifdef BCM_CB_ABORT_ON_ERR
   5544         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   5545             break;
   5546         }
   5547 #endif
   5548     }
   5549 
   5550     if(l3_tbl_ptr) {
   5551         soc_cm_sfree(unit, l3_tbl_ptr);
   5552     }
   5553 
   5554     /* Reset last read status. */
   5555     if (BCM_E_NOT_FOUND == rv) {
   5556         rv = BCM_E_NONE;
   5557     }
   5558 
   5559     return (rv);
   5560 }
   5561 
   5562 /*
   5563  * Function:
   5564  *      bcm_td_trill_multicast_source_delete_all
   5565  * Purpose:
   5566  *      Delete all RFP entries in L3 Table
   5567  * Parameters:
   5568  *      unit     - Device Number
   5569  * Returns:
   5570  *      BCM_E_XXX
   5571  */
   5572 int
   5573 bcm_td_trill_multicast_source_delete_all(int unit)
   5574 {
   5575     uint32 *l3_entry_p;
   5576     soc_mem_t mem;
   5577     uint32 trill_key_type=0xff;   /* L3 Table KEY_TYPE */
   5578 
   5579     int table_ent_size=0;         /* Table entry size. */
   5580     int table_size=0;             /* Number of entries in the table. */
   5581     int idx_max=0;                /* Maximum iteration index.        */
   5582     int idx_min=0;                /* Minimum iteration index.        */
   5583     int idx=0;                    /* Iterator index.                 */
   5584     char *l3_tbl_ptr = NULL;      /* Table dma pointer.              */
   5585     int rv = BCM_E_NONE;          /* Operation return value.         */
   5586 
   5587 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
   5588     if (SOC_IS_TRIDENT2X(unit)|| SOC_IS_TOMAHAWKX(unit)) {
   5589         mem = L3_ENTRY_IPV4_UNICASTm;
   5590         trill_key_type = TD2_L3_HASH_KEY_TYPE_TRILL;
   5591     } else
   5592 #endif /* BCM_TRIDENT2_SUPPORT */
   5593 #if defined(BCM_TRIDENT3_SUPPORT)
   5594     if (SOC_IS_TRIDENT3X(unit)) {
   5595         mem = L3_ENTRY_ONLY_SINGLEm;
   5596         trill_key_type = TD2_L3_HASH_KEY_TYPE_TRILL;
   5597     } else
   5598 #endif /* BCM_TRIDENT3_SUPPORT */
   5599 #if defined(BCM_TRIUMPH3_SUPPORT)
   5600     if (SOC_IS_TRIUMPH3(unit)) {
   5601         mem = L3_ENTRY_1m;
   5602         trill_key_type = SOC_MEM_KEY_L3_ENTRY_1_TRILL_TRILL;
   5603     } else
   5604 #endif /* BCM_TRIUMPH3_SUPPORT */
   5605     {
   5606         mem = L3_ENTRY_IPV4_UNICASTm;
   5607         trill_key_type = TR_L3_HASH_KEY_TYPE_TRILL;
   5608     }
   5609 
   5610     /* Get table boundaries. */
   5611     idx_max = soc_mem_index_max(unit, mem);
   5612     idx_min =  soc_mem_index_min(unit, mem);
   5613 
   5614     /* Get single entry size. */
   5615     table_ent_size = BCM_XGS3_L3_ENT_SZ(unit, v4);
   5616 
   5617     soc_mem_lock(unit, mem);
   5618     /* Dma the table - to speed up operation. */
   5619     rv = bcm_xgs3_l3_tbl_dma(unit, mem, table_ent_size,
   5620                               "trill_rpf_tbl", &l3_tbl_ptr, &table_size);
   5621 
   5622     if (BCM_FAILURE(rv)) {
   5623         if(l3_tbl_ptr) {
   5624             soc_cm_sfree(unit, l3_tbl_ptr);
   5625         }
   5626 
   5627         soc_mem_unlock(unit, mem);
   5628         return rv;
   5629     }
   5630 
   5631     /* Iterate over all the entries - show matching ones. */
   5632     for (idx = idx_min; idx <= idx_max; idx++) {
   5633         l3_entry_p =
   5634             soc_mem_table_idx_to_pointer(unit, mem,
   5635                                          uint32 *,
   5636                                          l3_tbl_ptr, idx);
   5637 
   5638 
   5639         /* Skip entry if its not a Trill RFP entry */
   5640         if (soc_mem_field32_get(unit, mem, l3_entry_p, KEY_TYPEf) != trill_key_type) {
   5641             continue;
   5642         }
   5643 
   5644         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l3_entry_p);
   5645         if (BCM_FAILURE(rv)) {
   5646             break;
   5647         }
   5648     }
   5649 
   5650     /* Free resources */
   5651     if(l3_tbl_ptr) {
   5652         soc_cm_sfree(unit, l3_tbl_ptr);
   5653     }
   5654 
   5655     soc_mem_unlock(unit, mem);
   5656     return (rv);
   5657 }
   5658 
   5659 
   5660 /*
   5661  * Function:
   5662  *      bcm_tr_trill_stat_get
   5663  * Purpose:
   5664  *      Get TRILL Stats
   5665  * Parameters:
   5666  *      unit   - (IN) SOC unit #
   5667  *      port   - (IN) Physical port
   5668  *      stat   - (IN)  specify the Stat type
   5669  *      val    - (OUT) 64-bit Stats value
   5670  * Returns:
   5671  *      BCM_E_XXX
   5672  */     
   5673 
   5674 int
   5675 bcm_td_trill_stat_get(int unit, bcm_port_t port,
   5676                            bcm_trill_stat_t stat, uint64 *val)
   5677 {
   5678     int rv=BCM_E_NONE;
   5679     uint32 reg_val=0;
   5680     uint32  val_low=0;
   5681     trill_drop_stats_entry_t  drop;
   5682     bcm_port_t    local_port=-1;
   5683     int local_id=-1;
   5684 
   5685     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   5686          return BCM_E_UNIT;
   5687     }
   5688 
   5689     if (BCM_GPORT_IS_SET(port)) {
   5690          if ( (SOC_GPORT_IS_LOCAL(port)) || 
   5691                (SOC_GPORT_IS_DEVPORT(port)) || 
   5692                (SOC_GPORT_IS_MODPORT(port))) {
   5693                    BCM_IF_ERROR_RETURN
   5694                       (bcm_esw_port_local_get(unit, port, &local_port));
   5695          } else if (SOC_GPORT_IS_TRILL_PORT(port)) {
   5696               /* Flex stats not supported for TRILL port */
   5697               return BCM_E_UNAVAIL;
   5698          } else {
   5699               return BCM_E_PARAM;
   5700          }
   5701    } else if (SOC_GPORT_INVALID == port) {
   5702          local_id = 0;
   5703    } else {
   5704         local_port = port;
   5705    }
   5706 
   5707     COMPILER_64_ZERO(*val);
   5708 
   5709     switch (stat) {
   5710 
   5711          case bcmTrillInPkts:
   5712            if (local_port != -1) {
   5713                if (SOC_REG_IS_VALID(unit, ING_TRILL_RX_PKTSr)) {
   5714                    SOC_IF_ERROR_RETURN
   5715                        (READ_ING_TRILL_RX_PKTSr(unit, local_port, &reg_val));
   5716                    val_low = 
   5717                        soc_reg_field_get(unit, ING_TRILL_RX_PKTSr, 
   5718                                          reg_val, COUNTf);
   5719                    COMPILER_64_SET(*val, 0, val_low);
   5720                } else {
   5721                    uint64 rval64;
   5722 
   5723                    SOC_IF_ERROR_RETURN
   5724                        (READ_ING_TRILL_RX_PKTS_64r(unit, local_port, &rval64));
   5725                    *val = soc_reg64_field_get(unit, ING_TRILL_RX_PKTS_64r,
   5726                                               rval64, COUNTf);       
   5727                }
   5728            } else {
   5729               return BCM_E_UNAVAIL;
   5730            }
   5731            break;
   5732 
   5733          case bcmTrillOutPkts:
   5734            if (local_port != -1) {
   5735                if (SOC_REG_IS_VALID(unit, EGR_TRILL_TX_PKTSr)) {
   5736                    SOC_IF_ERROR_RETURN
   5737                        (READ_EGR_TRILL_TX_PKTSr(unit, local_port, &reg_val));
   5738                    val_low =
   5739                        soc_reg_field_get(unit, EGR_TRILL_TX_PKTSr, 
   5740                                          reg_val, COUNTf);
   5741                    COMPILER_64_SET(*val, 0, val_low);
   5742                } else {
   5743                    uint64 rval64;
   5744 
   5745                    SOC_IF_ERROR_RETURN
   5746                        (READ_EGR_TRILL_TX_PKTS_64r(unit, local_port, &rval64));
   5747                    *val = soc_reg64_field_get(unit, EGR_TRILL_TX_PKTS_64r,
   5748                                               rval64, COUNTf);       
   5749                }
   5750            } else {
   5751               return BCM_E_UNAVAIL;
   5752            }
   5753            break;
   5754 
   5755          case bcmTrillErrorPkts:
   5756            if (local_id == 0) {
   5757               BCM_IF_ERROR_RETURN(
   5758                    soc_mem_read(unit, TRILL_DROP_STATSm,
   5759                         MEM_BLOCK_ALL, local_id, &drop));
   5760               soc_mem_field64_get(unit, TRILL_DROP_STATSm, 
   5761                                   &drop, TRILL_ERROR_DROPSf, val);    
   5762            } else {
   5763               return BCM_E_UNAVAIL;
   5764            }
   5765            break;
   5766 
   5767          case bcmTrillNameMissPkts:             
   5768            if (local_id == 0) {
   5769               BCM_IF_ERROR_RETURN(
   5770                    soc_mem_read(unit, TRILL_DROP_STATSm,
   5771                         MEM_BLOCK_ALL, local_id, &drop));             
   5772               soc_mem_field64_get(unit, TRILL_DROP_STATSm, &drop, 
   5773                                   TRILL_RBRIDGE_LOOKUP_MISS_DROPSf, val);             
   5774            } else {
   5775               return BCM_E_UNAVAIL;
   5776            }
   5777            break;
   5778 
   5779          case bcmTrillRpfFailPkts:
   5780            if (local_id == 0) {
   5781               BCM_IF_ERROR_RETURN(
   5782                    soc_mem_read(unit, TRILL_DROP_STATSm,
   5783                         MEM_BLOCK_ALL, local_id, &drop));
   5784               soc_mem_field64_get(unit, TRILL_DROP_STATSm, &drop, 
   5785                                   TRILL_RPF_CHECK_FAIL_DROPSf, val);             
   5786            } else {
   5787               return BCM_E_UNAVAIL;
   5788            }
   5789            break;
   5790 
   5791          case bcmTrillTtlFailPkts:            
   5792            if (local_id == 0) {
   5793               BCM_IF_ERROR_RETURN(
   5794                    soc_mem_read(unit, TRILL_DROP_STATSm,
   5795                         MEM_BLOCK_ALL, local_id, &drop));
   5796               soc_mem_field64_get(unit, TRILL_DROP_STATSm, &drop, 
   5797                                   TRILL_HOPCOUNT_CHECK_FAIL_DROPSf, val);               
   5798            } else {
   5799               return BCM_E_UNAVAIL;
   5800            }
   5801            break;
   5802 
   5803          default:
   5804                    break;
   5805 
   5806     }
   5807 
   5808     return rv;
   5809 }
   5810 
   5811 int
   5812 bcm_td_trill_stat_get32(int unit, bcm_port_t port,
   5813                              bcm_trill_stat_t stat, uint32 *val)
   5814 {
   5815     int rv=BCM_E_NONE;
   5816     uint64 val64;
   5817 
   5818     rv = bcm_td_trill_stat_get(unit, port, stat, &val64);
   5819     if (rv == BCM_E_NONE) {
   5820         *val = COMPILER_64_LO(val64);
   5821     }
   5822     return rv;
   5823 }
   5824 
   5825 /*
   5826  * Function:
   5827  *      bcm_td_trill_stat_clear
   5828  * Purpose:
   5829  *      Clear TRILL Stats
   5830  * Parameters:
   5831  *      unit   - (IN) SOC unit #
   5832  *      port   - (IN) Physcial port
   5833  *      stat   - (IN)  specify the Stat type
   5834  * Returns:
   5835  *      BCM_E_XXX
   5836  */     
   5837 
   5838 int
   5839 bcm_td_trill_stat_clear(int unit, bcm_port_t port,
   5840                              bcm_trill_stat_t stat)
   5841 {
   5842     int rv=BCM_E_NONE;
   5843     uint32 reg_val=0;
   5844     trill_drop_stats_entry_t  drop;
   5845     bcm_port_t    local_port=-1;
   5846     int local_id=-1;
   5847 
   5848     if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
   5849          return BCM_E_UNIT;
   5850     }
   5851 
   5852     if (BCM_GPORT_IS_SET(port)) {
   5853          if ( (SOC_GPORT_IS_LOCAL(port)) || 
   5854                (SOC_GPORT_IS_DEVPORT(port)) || 
   5855                (SOC_GPORT_IS_MODPORT(port))) {
   5856                    BCM_IF_ERROR_RETURN
   5857                       (bcm_esw_port_local_get(unit, port, &local_port));
   5858          } else if (SOC_GPORT_IS_TRILL_PORT(port)) {
   5859               /* Flex stats not supported for TRILL port */
   5860               return BCM_E_UNAVAIL;
   5861          } else {
   5862               return BCM_E_PARAM;
   5863          }
   5864    } else if (SOC_GPORT_INVALID == port) {
   5865          local_id = 0;
   5866 
   5867          /* Global stats , initialize and read entry */
   5868          sal_memset(&drop, 0, sizeof(trill_drop_stats_entry_t));
   5869          BCM_IF_ERROR_RETURN(
   5870              soc_mem_read(unit, TRILL_DROP_STATSm, MEM_BLOCK_ALL, 
   5871                   0, &drop));
   5872    } else {
   5873         local_port = port;
   5874    }
   5875 
   5876     switch (stat) {
   5877 
   5878          case bcmTrillInPkts:
   5879 
   5880            if (local_port != -1) {
   5881                if (SOC_REG_IS_VALID(unit, ING_TRILL_RX_PKTSr)) {
   5882                    soc_reg_field_set(unit, ING_TRILL_RX_PKTSr, 
   5883                                                    &reg_val, COUNTf, 0);
   5884                    SOC_IF_ERROR_RETURN
   5885                      (WRITE_ING_TRILL_RX_PKTSr(unit, local_port, reg_val));
   5886                } else {
   5887                    uint64 cntval;
   5888                    uint64 rval64;      /* Current 64 bit register data.  */
   5889 
   5890                    COMPILER_64_ZERO(cntval);
   5891                    COMPILER_64_ZERO(rval64);
   5892 
   5893                    soc_reg64_field_set(unit, ING_TRILL_RX_PKTS_64r, 
   5894                                              &rval64, COUNTf, cntval);
   5895                    SOC_IF_ERROR_RETURN
   5896                      (WRITE_ING_TRILL_RX_PKTS_64r(unit, local_port, rval64));
   5897                }
   5898            } else {
   5899               return BCM_E_UNAVAIL;
   5900            }
   5901            break;
   5902 
   5903          case bcmTrillOutPkts:
   5904 
   5905            if (local_port != -1) {
   5906                if (SOC_REG_IS_VALID(unit, EGR_TRILL_TX_PKTSr)) {
   5907                    soc_reg_field_set(unit, EGR_TRILL_TX_PKTSr, 
   5908                                                    &reg_val, COUNTf, 0);
   5909                    SOC_IF_ERROR_RETURN
   5910                        (WRITE_EGR_TRILL_TX_PKTSr(unit, local_port, reg_val));
   5911                } else {
   5912                    uint64 cntval;
   5913                    uint64 rval64;      /* Current 64 bit register data.  */
   5914 
   5915                    COMPILER_64_ZERO(cntval);
   5916                    COMPILER_64_ZERO(rval64);
   5917 
   5918                    soc_reg64_field_set(unit, EGR_TRILL_TX_PKTS_64r, 
   5919                                              &rval64, COUNTf, cntval);
   5920                    SOC_IF_ERROR_RETURN
   5921                      (WRITE_EGR_TRILL_TX_PKTS_64r(unit, local_port, rval64));
   5922                }
   5923            } else {
   5924               return BCM_E_UNAVAIL;
   5925            }
   5926            break;
   5927 
   5928          case bcmTrillErrorPkts:
   5929 
   5930             if (local_id == 0) {
   5931                 uint64 mem_val;
   5932                 COMPILER_64_ZERO(mem_val);
   5933                 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop,
   5934                                     TRILL_ERROR_DROPSf, mem_val);
   5935 
   5936                 BCM_IF_ERROR_RETURN
   5937                     (soc_mem_write(unit, TRILL_DROP_STATSm,
   5938                                    MEM_BLOCK_ALL, local_id, &drop));
   5939             } else {
   5940                 return BCM_E_UNAVAIL;
   5941             }
   5942             break;
   5943 
   5944          case bcmTrillNameMissPkts:
   5945               
   5946             if (local_id == 0) {  
   5947                 uint64 mem_val;
   5948                 COMPILER_64_ZERO(mem_val);
   5949                 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop,
   5950                                     TRILL_RBRIDGE_LOOKUP_MISS_DROPSf, mem_val);
   5951                 BCM_IF_ERROR_RETURN
   5952                     (soc_mem_write(unit, TRILL_DROP_STATSm,
   5953                                    MEM_BLOCK_ALL, local_id, &drop));
   5954             } else {
   5955               return BCM_E_UNAVAIL;
   5956             }
   5957             break;
   5958 
   5959          case bcmTrillRpfFailPkts:
   5960               
   5961             if (local_id == 0) {
   5962                 uint64 mem_val;
   5963                 COMPILER_64_ZERO(mem_val);
   5964                 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop,
   5965                                     TRILL_RPF_CHECK_FAIL_DROPSf, mem_val);                
   5966                 BCM_IF_ERROR_RETURN
   5967                     (soc_mem_write(unit, TRILL_DROP_STATSm,
   5968                                    MEM_BLOCK_ALL, local_id, &drop));
   5969             } else {
   5970                 return BCM_E_UNAVAIL;
   5971             }
   5972             break;
   5973 
   5974          case bcmTrillTtlFailPkts:
   5975               
   5976             if (local_id == 0) {
   5977                 uint64 mem_val;
   5978                 COMPILER_64_ZERO(mem_val);
   5979                 soc_mem_field64_set(unit, TRILL_DROP_STATSm, &drop,
   5980                                     TRILL_HOPCOUNT_CHECK_FAIL_DROPSf, mem_val);
   5981                 BCM_IF_ERROR_RETURN
   5982                     (soc_mem_write(unit, TRILL_DROP_STATSm,
   5983                                    MEM_BLOCK_ALL, local_id, &drop));
   5984             } else {
   5985                 return BCM_E_UNAVAIL;
   5986             }
   5987             break;
   5988 
   5989          default:
   5990                    break;
   5991 
   5992     }
   5993 
   5994     return rv;
   5995 }
   5996 
   5997 #ifndef BCM_SW_STATE_DUMP_DISABLE
   5998 /*
   5999  * Function:
   6000  *     _bcm_td_trill_sw_dump
   6001  * Purpose:
   6002  *     Displays Trill State information maintained by software.
   6003  * Parameters:
   6004  *     unit - Device unit number
   6005  * Returns:
   6006  *     None
   6007  */
   6008 void
   6009 _bcm_td_trill_sw_dump(int unit)
   6010 {
   6011     int idx=0, num_vp=0, num_ipmc=0;
   6012     _bcm_td_trill_bookkeeping_t *trill_info = TRILL_INFO(unit);
   6013     
   6014     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   6015     num_ipmc = soc_mem_index_count(unit, L3_IPMCm);
   6016 
   6017     LOG_CLI((BSL_META_U(unit,
   6018                         "\nRoot Bridges:\n")));
   6019     for (idx = 0; idx < BCM_MAX_NUM_TRILL_TREES; idx++) {
   6020         LOG_CLI((BSL_META_U(unit,
   6021                             "%d "), trill_info->rootBridge[idx]));
   6022     }
   6023     
   6024     LOG_CLI((BSL_META_U(unit,
   6025                         "\n\nrBridges:\n")));
   6026     for (idx = 0; idx < num_vp; idx++) {
   6027         if (trill_info->rBridge[idx] != 0) {
   6028             LOG_CLI((BSL_META_U(unit,
   6029                                 "Index:%d rBridge nickname:%d\n"), idx,
   6030                      trill_info->rBridge[idx]));
   6031         }
   6032     }
   6033 
   6034     LOG_CLI((BSL_META_U(unit,
   6035                         "\n\nMulticast use count:\n")));
   6036     for (idx = 0; idx < num_ipmc; idx++) {
   6037         if (trill_info->multicast_count[idx].network_port_count != 0) {
   6038             LOG_CLI((BSL_META_U(unit,
   6039                                 "    Multicast group %d use count:%d\n"),
   6040                      trill_info->multicast_count[idx].l3mc_group,
   6041                      trill_info->multicast_count[idx].network_port_count));
   6042         }
   6043     }
   6044     
   6045     return;
   6046 }
   6047 
   6048 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   6049 
   6050 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
   6051