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 (70454B)


      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 Triumph3 Trill API
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 
     14 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
     15 #include <soc/drv.h>
     16 #include <soc/mem.h>
     17 #include <soc/util.h>
     18 #include <soc/hash.h>
     19 #include <soc/debug.h>
     20 #include <bcm/types.h>
     21 #include <bcm/error.h>
     22 #include <soc/ism_hash.h>
     23 
     24 #include <bcm/types.h>
     25 #include <bcm/l3.h>
     26 #include <bcm/multicast.h>
     27 #include <bcm/trill.h>
     28 
     29 #include <bcm_int/esw/mbcm.h>
     30 #include <bcm_int/esw_dispatch.h>
     31 #include <bcm_int/esw/virtual.h>
     32 #include <bcm_int/esw/firebolt.h>
     33 #include <bcm_int/esw/trident.h>
     34 #include <bcm_int/esw/triumph.h>
     35 #include <bcm_int/esw/triumph2.h>
     36 #include <bcm_int/esw/triumph3.h>
     37 #include <bcm_int/esw/trill.h>
     38 #include <bcm_int/common/multicast.h>
     39 #include <bcm_int/esw/multicast.h>
     40 
     41 typedef uint32 L2_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS];
     42 
     43 /*
     44  * Function:
     45  *		_bcm_tr3_trill_transit_entry_key_set
     46  * Purpose:
     47  *		Set TRILL Transit forwarding entry key
     48  * Parameters:
     49  *		IN :  Unit
     50  *  IN :  trill_port
     51  *  IN : next_hop / ecmp group index
     52  *  IN : MPLS entry pointer
     53  * Returns:
     54  *		BCM_E_XXX
     55  */
     56 
     57 
     58 STATIC void
     59 _bcm_tr3_trill_transit_entry_key_set(int unit, bcm_trill_port_t *trill_port,
     60                 int nh_ecmp_index, mpls_entry_extd_entry_t *tr_ent, int clean_flag)
     61 {
     62 
     63     if (clean_flag) {
     64          sal_memset(tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
     65     }
     66 
     67     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     68                                          KEY_TYPE_0f, 26);
     69     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     70                                          KEY_TYPE_1f, 26);
     71     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     72                                          TRILL__RBRIDGE_NICKNAMEf, trill_port->name);
     73     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     74                                          TRILL__CLASS_IDf, trill_port->if_class);
     75     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     76                                          TRILL__DECAP_TRILL_TUNNELf, 0x0);
     77     if (trill_port->flags & _BCM_TRILL_PORT_MULTIPATH) {
     78          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     79                                          TRILL__ECMPf, 0x1);
     80          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     81                                          TRILL__ECMP_PTRf, nh_ecmp_index);
     82     } else {
     83          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     84                                          TRILL__ECMPf, 0x0);
     85          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     86                                          TRILL__NEXT_HOP_INDEXf, nh_ecmp_index);
     87     }
     88     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__UCAST_DST_DISCARDf)) { 
     89         if ((trill_port->flags & BCM_TRILL_PORT_DROP) ||
     90             !(trill_port->flags & BCM_TRILL_PORT_NETWORK)) {
     91               soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     92                                          TRILL__UCAST_DST_DISCARDf, 0x1);
     93         } else if (trill_port->flags & BCM_TRILL_PORT_NETWORK) {
     94               soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
     95                                          TRILL__UCAST_DST_DISCARDf, 0x0);
     96         }
     97     }
     98     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__DST_COPY_TO_CPUf) && 
     99         (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) {
    100          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    101                                          TRILL__DST_COPY_TO_CPUf, 0x1);
    102     }
    103     /* Multicast-traffic discard setting */
    104     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__MCAST_DST_DISCARDf)) {
    105         if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) {
    106             soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    107                                      TRILL__MCAST_DST_DISCARDf, 0x0);
    108         } else {
    109             soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    110                                      TRILL__MCAST_DST_DISCARDf, 0x1);
    111         }
    112     }
    113 
    114     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    115                                          VALID_0f, 0x1);
    116     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    117                                          VALID_1f, 0x1);
    118 }
    119 
    120 
    121 /*
    122  * Function:
    123  *      _bcm_tr3_trill_transit_entry_set
    124  * Purpose:
    125  *     Set TRILL Transit forwarding entry
    126  * Parameters:
    127  *      IN :  Unit
    128  *      IN :  trill_port
    129  *      IN : next_hop / ecmp group index
    130  * Returns:
    131  *      BCM_E_XXX
    132  */
    133 
    134 int
    135 _bcm_tr3_trill_transit_entry_set(int unit, bcm_trill_port_t *trill_port,
    136                                          int nh_ecmp_index)
    137 {
    138     int rv = BCM_E_NONE;
    139     int index=0;
    140     mpls_entry_extd_entry_t  key_ent;
    141     mpls_entry_extd_entry_t  return_ent;
    142 
    143     _bcm_tr3_trill_transit_entry_key_set(unit, trill_port, 
    144                         nh_ecmp_index, &key_ent, 1);
    145 
    146     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    147                         &key_ent, &return_ent, 0);
    148     if (rv == SOC_E_NONE) {
    149          (void) _bcm_tr3_trill_transit_entry_key_set(unit, trill_port, 
    150                                   nh_ecmp_index, &return_ent, 0);
    151          rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm,
    152                                   MEM_BLOCK_ALL, index,
    153                                   &return_ent);
    154     } else if (rv != SOC_E_NOT_FOUND) {
    155         return rv;
    156     } else {
    157          rv = soc_mem_insert(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, &key_ent);
    158     }
    159     return rv;
    160 }
    161 
    162 /*
    163  * Function:
    164  *		_bcm_tr3_trill_transit_entry_reset
    165  * Purpose:
    166  *		Reset TRILL Transit forwarding entry
    167  * Parameters:
    168  *		IN :  Unit
    169  *  IN :  vp
    170  *  IN : next_hop / ecmp group index
    171  *  IN : ecmp flag
    172  * Returns:
    173  *		BCM_E_XXX
    174  */
    175 
    176 int
    177 _bcm_tr3_trill_transit_entry_reset(int unit, int vp, int nh_ecmp_idx, int ecmp)
    178 {
    179     int rv = BCM_E_UNAVAIL;
    180     int index=0;
    181     bcm_trill_name_t rb_name;      /* Destination RBridge Nickname. */
    182     int if_class=0;               /* Interface class ID. */
    183     mpls_entry_extd_entry_t  tr_ent;
    184     egr_dvp_attribute_entry_t  egr_dvp_attribute;
    185     source_vp_entry_t svp;
    186 
    187     sal_memset(&tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    188  
    189     BCM_IF_ERROR_RETURN(
    190          soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
    191                                          MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
    192 
    193     rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
    194                                          EGRESS_RBRIDGE_NICKNAMEf);
    195 
    196     BCM_IF_ERROR_RETURN(
    197          soc_mem_read(unit, SOURCE_VPm,
    198                                          MEM_BLOCK_ALL, vp, &svp));
    199 
    200     if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf);
    201 
    202 
    203     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    204                                       KEY_TYPE_0f, 26);
    205     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    206                                          KEY_TYPE_1f, 26);
    207     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    208                                       TRILL__RBRIDGE_NICKNAMEf, rb_name);
    209     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    210                                       TRILL__CLASS_IDf, if_class);
    211     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    212                                       TRILL__DECAP_TRILL_TUNNELf, 0x0);
    213     if (ecmp) {
    214       soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    215                                       TRILL__ECMPf, 0x1);
    216       soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    217                                       TRILL__ECMP_PTRf, nh_ecmp_idx);
    218     } else {
    219       soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    220                                       TRILL__NEXT_HOP_INDEXf, nh_ecmp_idx);
    221     }
    222     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    223                                       VALID_0f, 0x1);
    224     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    225                                          VALID_1f, 0x1);
    226     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    227                      &tr_ent, &tr_ent, 0);
    228     if (rv < 0) {
    229          return rv;
    230     }
    231     /* Delete the entry from HW */
    232     rv = soc_mem_delete(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, &tr_ent);
    233     return rv;
    234 }
    235 
    236 /*
    237  * Function:
    238  *		_bcm_tr3_trill_learn_entry_key_set
    239  * Purpose:
    240  *		Set TRILL learn entry key
    241  * Parameters:
    242  *		IN :  Unit
    243  *  IN :  trill_port
    244  *  IN :  VP
    245  *  IN : MPLS entry pointer
    246  * Returns:
    247  *		BCM_E_XXX
    248  */
    249 
    250 STATIC void
    251  _bcm_tr3_trill_learn_entry_key_set(int unit, bcm_trill_port_t *trill_port,
    252                                           int vp, mpls_entry_extd_entry_t   *tr_ent, int clean_flag)
    253  {
    254     uint8 trill_tree_id=0;
    255 
    256     if (clean_flag) {
    257          sal_memset(tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    258     }
    259 
    260     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    261                                          KEY_TYPE_0f, 26);
    262     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    263                                          KEY_TYPE_1f, 26);
    264     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    265                                          TRILL__RBRIDGE_NICKNAMEf, trill_port->name);
    266     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    267                                          TRILL__CLASS_IDf, trill_port->if_class);
    268     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    269                                          TRILL__VIRTUAL_PORTf, vp);
    270     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    271                                          TRILL__PHB_FROM_OUTER_L2_HEADERf, 0x1);
    272     if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) {
    273          (void) bcm_td_trill_tree_profile_get (unit, trill_port->name, &trill_tree_id);
    274          if (trill_tree_id < BCM_MAX_NUM_TRILL_TREES) {
    275               soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    276                                          TRILL__TREE_IDf, trill_tree_id);
    277          }
    278     }
    279     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__SRC_DISCARDf) && 
    280         (trill_port->flags & BCM_TRILL_PORT_DROP)) {
    281          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    282                                          TRILL__SRC_DISCARDf, 0x1);
    283     }
    284     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__SRC_COPY_TO_CPUf) && 
    285         (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) {
    286          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    287                                          TRILL__SRC_COPY_TO_CPUf, 0x1);
    288     }
    289     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    290                                          VALID_0f, 0x1);
    291     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    292                                          VALID_1f, 0x1);
    293  }
    294 
    295 /*
    296  * Function:
    297  *		_bcm_tr3_trill_learn_entry_set
    298  * Purpose:
    299  *		Set TRILL  Learn Entry 
    300  * Parameters:
    301  *		IN :  Unit
    302  *  IN :  trill_port
    303  *  IN : vp
    304  * Returns:
    305  *		BCM_E_XXX
    306  */
    307 
    308 int
    309 _bcm_tr3_trill_learn_entry_set(int unit, bcm_trill_port_t *trill_port, int vp)
    310 {
    311     mpls_entry_extd_entry_t  key_ent;
    312     mpls_entry_extd_entry_t  return_ent;
    313     int rv = BCM_E_UNAVAIL;
    314     int index=0;
    315 
    316     _bcm_tr3_trill_learn_entry_key_set(unit, trill_port, vp, &key_ent, 1);
    317 
    318     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    319                         &key_ent, &return_ent, 0);
    320 
    321     if (rv == SOC_E_NONE) {
    322          (void) _bcm_tr3_trill_learn_entry_key_set(unit, trill_port, vp, &return_ent, 0);
    323          rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm,
    324                                            MEM_BLOCK_ALL, index,
    325                                            &return_ent);
    326     } else if (rv != SOC_E_NOT_FOUND) {
    327         return rv;
    328     } else {
    329          rv = soc_mem_insert(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, &key_ent);
    330     }
    331 
    332     return rv;
    333 }
    334 
    335 /*
    336  * Function:
    337  *		_bcm_tr3_trill_learn_entry_reset
    338  * Purpose:
    339  *		Reset TRILL RPF entry
    340  * Parameters:
    341  *		IN :  Unit
    342  *  IN :  vp
    343  * Returns:
    344  *		BCM_E_XXX
    345  */
    346 
    347 int
    348 _bcm_tr3_trill_learn_entry_reset(int unit, int vp)
    349 {
    350     int rv = BCM_E_UNAVAIL;
    351     int index=0;
    352     bcm_trill_name_t rb_name;      /* Destination RBridge Nickname. */
    353     int if_class=0;               /* Interface class ID. */
    354     mpls_entry_extd_entry_t  tr_ent;
    355     egr_dvp_attribute_entry_t  egr_dvp_attribute;
    356     source_vp_entry_t svp;
    357 
    358     sal_memset(&tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    359 
    360     BCM_IF_ERROR_RETURN(
    361          soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
    362                              MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
    363 
    364     rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
    365                              EGRESS_RBRIDGE_NICKNAMEf);
    366 
    367     BCM_IF_ERROR_RETURN(
    368          soc_mem_read(unit, SOURCE_VPm,
    369                              MEM_BLOCK_ALL, vp, &svp));
    370 
    371     if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf);
    372 
    373     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    374                              KEY_TYPE_0f, 26);
    375     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    376                                          KEY_TYPE_1f, 26);
    377     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    378                              TRILL__RBRIDGE_NICKNAMEf, rb_name);
    379     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    380                              TRILL__CLASS_IDf, if_class);
    381     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    382                              TRILL__VIRTUAL_PORTf, vp);
    383     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    384                              TRILL__PHB_FROM_OUTER_L2_HEADERf, 0x1);
    385     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    386                              VALID_0f, 0x1);
    387     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    388                                          VALID_1f, 0x1);
    389 
    390     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    391                              &tr_ent, &tr_ent, 0);
    392     if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
    393          return rv;
    394     }
    395     /* Delete the entry from HW */
    396     rv = soc_mem_delete(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, &tr_ent);
    397     
    398     if ( (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE) ) {
    399        return rv;
    400     } else {
    401        return BCM_E_NONE;
    402     }
    403 }
    404 
    405 
    406 /*
    407  * Function:
    408  *		_bcm_tr3_trill_decap_entry_key_set
    409  * Purpose:
    410  *		Set TRILL Decap entry key
    411  * Parameters:
    412  *		IN :  Unit
    413  *  IN :  trill_port
    414  *  IN :  VP
    415  *  IN : MPLS entry pointer
    416  * Returns:
    417  *		BCM_E_XXX
    418  */
    419 
    420 STATIC void
    421  _bcm_tr3_trill_decap_entry_key_set(int unit, bcm_trill_port_t *trill_port,
    422                                           mpls_entry_extd_entry_t   *tr_ent, int clean_flag)
    423  {
    424     if (clean_flag) {
    425        sal_memset(tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    426     }
    427 
    428     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    429                                          KEY_TYPE_0f, 26);
    430     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    431                                          KEY_TYPE_1f, 26);
    432     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    433                                          TRILL__RBRIDGE_NICKNAMEf, trill_port->name);
    434     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    435                                          TRILL__DECAP_TRILL_TUNNELf, 0x1);
    436     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    437                                          TRILL__CLASS_IDf, trill_port->if_class);
    438     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__UCAST_DST_DISCARDf)) { 
    439        if ((trill_port->flags & BCM_TRILL_PORT_DROP) ||
    440             !(trill_port->flags & BCM_TRILL_PORT_NETWORK)) {
    441               soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    442                                          TRILL__UCAST_DST_DISCARDf, 0x1);
    443        } else if (trill_port->flags & BCM_TRILL_PORT_NETWORK) {
    444               soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    445                                          TRILL__UCAST_DST_DISCARDf, 0x0);
    446         }
    447     }
    448     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__DST_COPY_TO_CPUf) && 
    449         (trill_port->flags & BCM_TRILL_PORT_COPYTOCPU)) {
    450          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    451                                          TRILL__DST_COPY_TO_CPUf, 0x1);
    452     }
    453     /* Multicast-traffic discard setting */
    454     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__MCAST_DST_DISCARDf)) {
    455         if (trill_port->flags & BCM_TRILL_PORT_MULTICAST) {
    456             soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    457                                      TRILL__MCAST_DST_DISCARDf, 0x0);
    458         } else {
    459             soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    460                                      TRILL__MCAST_DST_DISCARDf, 0x1);
    461         }
    462     }
    463 
    464     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    465                                          VALID_0f, 0x1);
    466     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    467                                          VALID_1f, 0x1);
    468  }
    469 
    470 /*
    471  * Function:
    472  *           _bcm_tr3_trill_decap_entry_set
    473  * Purpose:
    474  *           Set TRILL  Decap  Entry 
    475  * Parameters:
    476  *           IN :  Unit
    477  *  IN :  trill_port
    478  * Returns:
    479  *           BCM_E_XXX
    480  */
    481 
    482 int
    483 _bcm_tr3_trill_decap_entry_set(int unit, bcm_trill_port_t *trill_port)
    484 {
    485     mpls_entry_extd_entry_t  tr_ent;
    486     int rv = BCM_E_UNAVAIL;
    487     int index=0;
    488     mpls_entry_extd_entry_t  return_ent;
    489 
    490     _bcm_tr3_trill_decap_entry_key_set(unit, trill_port, &tr_ent, 1);
    491 
    492     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    493                         &tr_ent, &return_ent, 0);
    494 
    495     if (rv == SOC_E_NONE) {
    496          (void) _bcm_tr3_trill_decap_entry_key_set(unit, trill_port, &return_ent, 0);
    497          rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm,
    498                                   MEM_BLOCK_ALL, index,
    499                                   &return_ent);
    500     } else if (rv != SOC_E_NOT_FOUND) {
    501         return rv;
    502     } else {
    503         rv = soc_mem_insert(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, &tr_ent);
    504     }
    505     return rv;
    506 }
    507 
    508 /*
    509  * Function:
    510  *           _bcm_tr3_trill_decap_entry_reset
    511  * Purpose:
    512  *           Reset TRILL Decap entry
    513  * Parameters:
    514  *            IN :  Unit
    515  *  IN :  vp
    516  * Returns:
    517  *            BCM_E_XXX
    518  */
    519 
    520 int
    521 _bcm_tr3_trill_decap_entry_reset(int unit,  int vp)
    522 {
    523     int rv = BCM_E_UNAVAIL;
    524     int index=0;
    525     bcm_trill_name_t rb_name;      /* Destination RBridge Nickname. */
    526     int if_class=0;               /* Interface class ID. */
    527     mpls_entry_extd_entry_t  tr_ent;
    528     egr_dvp_attribute_entry_t  egr_dvp_attribute;
    529     source_vp_entry_t svp;
    530  
    531     sal_memset(&tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    532 
    533     BCM_IF_ERROR_RETURN(
    534          soc_mem_read(unit, EGR_DVP_ATTRIBUTEm,
    535                          MEM_BLOCK_ALL, vp, &egr_dvp_attribute));
    536 
    537     rb_name = soc_mem_field32_get(unit, EGR_DVP_ATTRIBUTEm, &egr_dvp_attribute,
    538                          EGRESS_RBRIDGE_NICKNAMEf);
    539  
    540     BCM_IF_ERROR_RETURN(
    541          soc_mem_read(unit, SOURCE_VPm,
    542                           MEM_BLOCK_ALL, vp, &svp));
    543  
    544     if_class = soc_mem_field32_get(unit, SOURCE_VPm, &svp, CLASS_IDf);
    545  
    546     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    547                           KEY_TYPE_0f, 26);
    548     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    549                                          KEY_TYPE_1f, 26);
    550     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    551                           TRILL__RBRIDGE_NICKNAMEf, rb_name);
    552     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    553                           TRILL__CLASS_IDf, if_class);
    554     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    555                                          TRILL__DECAP_TRILL_TUNNELf, 0x1);
    556     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    557                           VALID_0f, 0x1);
    558     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    559                                          VALID_1f, 0x1);
    560  
    561     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    562                           &tr_ent, &tr_ent, 0);
    563     if (rv < 0) {
    564          return rv;
    565     }
    566 
    567     /* Delete the entry from HW */
    568     rv = soc_mem_delete(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, &tr_ent);
    569     return rv;
    570 
    571 }
    572 
    573 /*
    574  * Function:
    575  *		_bcm_tr3_trill_multicast_transit_entry_key_set
    576  * Purpose:
    577  *		Set TRILL Multicast entry key
    578  * Parameters:
    579  *  IN :  Unit
    580  *  IN :  Trill Root name
    581  *  IN : MPLS entry pointer
    582  * Returns:
    583  *		BCM_E_XXX
    584  */
    585 
    586 STATIC int
    587  _bcm_tr3_trill_multicast_transit_entry_key_set (int unit, bcm_trill_name_t root_name,
    588                                           mpls_entry_extd_entry_t   *tr_ent)
    589 {
    590     uint8  trill_tree_id=0;
    591 
    592     (void) bcm_td_trill_tree_profile_get (unit, root_name, &trill_tree_id);
    593     if (trill_tree_id >= BCM_MAX_NUM_TRILL_TREES) {
    594          return BCM_E_PARAM;
    595     }
    596     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    597                                        TRILL__TREE_IDf, trill_tree_id);
    598     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    599                                        KEY_TYPE_0f, 26);
    600     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    601                                          KEY_TYPE_1f, 26);
    602     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    603                                        TRILL__RBRIDGE_NICKNAMEf, root_name);
    604     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    605                                        VALID_0f, 0x1);
    606     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, tr_ent,
    607                                          VALID_1f, 0x1);
    608     return BCM_E_NONE;
    609 }
    610 
    611 
    612 
    613 /*
    614  * Purpose:
    615  *      Enable TRILL Multicast traffic   
    616  * Parameters:
    617  *      unit     - (IN) Device Number
    618  *      root_name  - (IN) trill Root_RBridge
    619  */
    620 
    621 int
    622 bcm_tr3_trill_multicast_enable(int unit, int flags, bcm_trill_name_t root_name)
    623 {
    624     mpls_entry_extd_entry_t  tr_key, tr_entry;
    625     int rv = BCM_E_UNAVAIL;
    626     int entry_index=0;
    627 
    628     sal_memset(&tr_key, 0, sizeof(mpls_entry_extd_entry_t));
    629     sal_memset(&tr_entry, 0, sizeof(mpls_entry_extd_entry_t));
    630 
    631     (void) _bcm_tr3_trill_multicast_transit_entry_key_set(unit, root_name, &tr_key);
    632 
    633     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &entry_index,
    634                         &tr_key, &tr_entry, 0);
    635 
    636     if (rv == SOC_E_NONE) {
    637          /* Enable Multicast traffic */
    638          if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__MCAST_DST_DISCARDf)) { 
    639               if (flags & BCM_TRILL_PORT_DROP) {
    640                    soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_entry,
    641                                          TRILL__MCAST_DST_DISCARDf, 0x1);
    642               } else {
    643                    soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_entry,
    644                                          TRILL__MCAST_DST_DISCARDf, 0x0);
    645               }
    646          }
    647          rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm,
    648                         MEM_BLOCK_ALL, entry_index, &tr_entry);
    649     } else {
    650         /* Root Entry Must be present */
    651         return rv;
    652     }
    653     return rv;
    654 }
    655 
    656 
    657 /*
    658  * Purpose:
    659  *      Disable TRILL Multicast traffic   
    660  * Parameters:
    661  *      unit     - (IN) Device Number
    662  *      root_name  - (IN) trill Root_RBridge
    663  */
    664 
    665 int
    666 bcm_tr3_trill_multicast_disable(int unit, int flags, bcm_trill_name_t root_name)
    667 {
    668     mpls_entry_extd_entry_t  tr_ent;
    669     int rv = BCM_E_UNAVAIL;
    670     int index=0;
    671 
    672     sal_memset(&tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    673 
    674     (void) _bcm_tr3_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent);
    675 
    676     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    677                              &tr_ent, &tr_ent, 0);
    678     if (rv < 0) {
    679          return rv;
    680     }
    681    
    682     /* Disable Multicast Traffic */
    683     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__MCAST_DST_DISCARDf)) { 
    684          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    685                         TRILL__MCAST_DST_DISCARDf, 0x1);
    686     }
    687     rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm,
    688                    MEM_BLOCK_ALL, index, &tr_ent);
    689     return rv;
    690 }
    691 
    692 /*
    693  * Purpose:
    694  *      Set TRILL Multicast entry for Transit operation
    695  * Parameters:
    696  *      unit     - (IN) Device Number
    697  *      root_name  - (IN) trill Root_RBridge
    698  *      mc_index   - (IN) Multicast index
    699  */
    700 
    701 int
    702 bcm_tr3_trill_multicast_transit_entry_set(int unit, uint32 flags, bcm_trill_name_t root_name, 
    703                                   int mc_index, uint8  trill_tree_id)
    704 {
    705     mpls_entry_extd_entry_t  tr_key, tr_entry;
    706     int rv = BCM_E_UNAVAIL;
    707     int entry_index=0;
    708 
    709     sal_memset(&tr_key, 0, sizeof(mpls_entry_extd_entry_t));
    710     sal_memset(&tr_entry, 0, sizeof(mpls_entry_extd_entry_t));
    711 
    712     (void) _bcm_tr3_trill_multicast_transit_entry_key_set(unit, root_name, &tr_key);
    713 
    714     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &entry_index,
    715                         &tr_key, &tr_entry, 0);
    716     if (rv == SOC_E_NONE) {
    717          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_entry,
    718                         TRILL__L3MC_INDEXf, mc_index);
    719          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_entry,
    720                         TRILL__TREE_IDf, (uint32) trill_tree_id);
    721          /* Enable Multicast traffic */
    722          if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__MCAST_DST_DISCARDf)) { 
    723               if (flags & BCM_TRILL_PORT_DROP) {
    724                    soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_entry,
    725                                          TRILL__MCAST_DST_DISCARDf, 0x1);
    726               } else {
    727                    soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_entry,
    728                                          TRILL__MCAST_DST_DISCARDf, 0x0);
    729               }
    730          }
    731          rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm,
    732                         MEM_BLOCK_ALL, entry_index, &tr_entry);
    733     } else {
    734         /* Root Entry Must be present */
    735         return rv;
    736     }
    737     return rv;
    738 
    739 }
    740 
    741 /*
    742  * Purpose:
    743  *       Reset TRILL Multicast entry for Transit operation
    744  * Parameters:
    745  *      unit     - (IN) Device Number
    746  *      root_name  - (IN) trill Root_RBridge
    747  *      mc_index   - (IN) Multicast index
    748  */
    749 
    750 int
    751 bcm_tr3_trill_multicast_transit_entry_reset(int unit, bcm_trill_name_t root_name)
    752 {
    753     mpls_entry_extd_entry_t  tr_ent;
    754     int rv = BCM_E_UNAVAIL;
    755     int index=0;
    756 
    757     sal_memset(&tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    758 
    759     (void) _bcm_tr3_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent);
    760 
    761     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    762                              &tr_ent, &tr_ent, 0);
    763     if (rv < 0) {
    764          return rv;
    765     }
    766    
    767     /* Remove l3mc_index from HW entry */
    768     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    769                    TRILL__L3MC_INDEXf, 0);
    770     /* Remove Multicast Tree Id */
    771     soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    772                         TRILL__TREE_IDf, (uint32) 0);
    773     /* Disable Multicast Traffic */
    774     if (soc_mem_field_valid(unit, MPLS_ENTRY_EXTDm, TRILL__MCAST_DST_DISCARDf)) { 
    775          soc_mem_field32_set(unit, MPLS_ENTRY_EXTDm, &tr_ent,
    776                         TRILL__MCAST_DST_DISCARDf, 0x1);
    777     }
    778     rv = soc_mem_write(unit, MPLS_ENTRY_EXTDm,
    779                    MEM_BLOCK_ALL, index, &tr_ent);
    780     return rv;
    781 }
    782 
    783 /*
    784  * Purpose:
    785  *       Get TRILL Multicast entry for Transit operation
    786  * Parameters:
    787  *      unit     - (IN) Device Number
    788  *      root_name  - (IN) trill Root_RBridge
    789  *      group   - (OUT) Multicast Group
    790  */
    791 
    792 int
    793 bcm_tr3_trill_multicast_transit_entry_get(int unit, bcm_trill_name_t root_name, bcm_multicast_t *group)
    794 {
    795     mpls_entry_extd_entry_t  tr_ent;
    796     int rv = BCM_E_UNAVAIL;
    797     int index=0;
    798 
    799     sal_memset(&tr_ent, 0, sizeof(mpls_entry_extd_entry_t));
    800 
    801     (void) _bcm_tr3_trill_multicast_transit_entry_key_set(unit, root_name, &tr_ent);
    802 
    803     rv = soc_mem_search(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ANY, &index,
    804                              &tr_ent, &tr_ent, 0);
    805     if (rv < 0) {
    806          return rv;
    807     }
    808     _BCM_MULTICAST_GROUP_SET(*group, 
    809                   _BCM_MULTICAST_TYPE_TRILL,  
    810                   soc_mem_field32_get (unit, MPLS_ENTRY_EXTDm, (uint32 *)&tr_ent,
    811                     TRILL__L3MC_INDEXf));
    812     return rv;
    813 }
    814 
    815 /*
    816  * Purpose:
    817  *       Reset all TRILL Multicast entries for Transit operation
    818  * Parameters:
    819  *      unit     - (IN) Device Number
    820  *      tree_id - (IN) trill Tree ID
    821  *      mc_index   - (IN) Multicast index
    822  */
    823 
    824 int
    825 bcm_tr3_trill_multicast_transit_entry_reset_all (int unit, uint8 tree_id)
    826 {
    827     int rv = BCM_E_UNAVAIL, idx=0, num_entries=0;
    828     mpls_entry_extd_entry_t ment;
    829     bcm_trill_name_t name;
    830 
    831     /* Tree ID and Root name is 1:1 mapping.
    832        Match on Rbridge name to match */
    833     bcm_td_trill_root_name_get(unit, tree_id, &name);
    834 
    835     num_entries = soc_mem_index_count(unit, MPLS_ENTRY_EXTDm);
    836     for (idx = 0; idx < num_entries; idx++) {
    837         rv = READ_MPLS_ENTRY_EXTDm(unit, MEM_BLOCK_ANY, idx, &ment);
    838         if (rv < 0) {
    839             return rv;
    840         }
    841         if (!soc_MPLS_ENTRY_EXTDm_field32_get(unit, &ment, VALID_0f)) {
    842             continue;
    843         }
    844         if (soc_MPLS_ENTRY_EXTDm_field32_get(unit, &ment, KEY_TYPE_0f) != 0x1A) {
    845             continue;
    846         }
    847 
    848         if ((soc_MPLS_ENTRY_EXTDm_field32_get(unit, &ment,
    849                                         TRILL__TREE_IDf) != tree_id) ||
    850            (soc_MPLS_ENTRY_EXTDm_field32_get(unit, &ment,
    851                                         TRILL__RBRIDGE_NICKNAMEf) != name)) {
    852             continue;
    853         }
    854 
    855 
    856         /* Entry found, for a given RBridge Name + Tree ID Key
    857          * there can be only one entry. Hence stop when entry found.
    858          */
    859         break;
    860     }
    861 
    862     /* Set L3MC index to 0, reserved entry with BITMAP = 0 */
    863     soc_MPLS_ENTRY_EXTDm_field32_set(unit, &ment, TRILL__L3MC_INDEXf, 0);
    864 
    865     /* Write to  HW */
    866     BCM_IF_ERROR_RETURN(
    867         soc_mem_write(unit, MPLS_ENTRY_EXTDm, MEM_BLOCK_ALL, idx, &ment));
    868 
    869     return BCM_E_NONE;
    870 }
    871 
    872 /*
    873  * Purpose:
    874  *      Add TRILL Multicast entry
    875  * Parameters:
    876  *      unit            - Device unit number
    877  *      key             - defines entry type
    878  *      vid             - Customer Vlan ID
    879  *      mac             - Customer MAC
    880  *      trill_tree_id   - specify Multicast Tree ID
    881  *      group           - Multicast group
    882  * Returns:
    883  *      BCM_E_NONE - Success.
    884  *      BCM_E_XXX
    885  */
    886 int 
    887 bcm_tr3_trill_l2_multicast_entry_add(int unit, uint32 flags, int key, 
    888                                     bcm_vlan_t vid, bcm_mac_t mac, 
    889                                     uint8 trill_tree_id, bcm_multicast_t group)
    890 {
    891     L2_ENTRY_T  l2_entry, l2_lookup;
    892     soc_mem_t mem; 
    893     soc_field_t field_key;
    894     int rv=BCM_E_NONE;
    895     int mc_index=0,l2_index=0;
    896     vlan_tab_entry_t  vt;
    897 
    898     sal_memset(&l2_entry, 0, sizeof (l2_entry));
    899     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
    900 
    901     mem = L2_ENTRY_1m;
    902 
    903     if (_BCM_MULTICAST_IS_SET(group)) {
    904 
    905         mc_index = _BCM_MULTICAST_ID_GET(group);
    906 
    907         switch (key) {
    908         case TR_L2_HASH_KEY_TYPE_BRIDGE:
    909             field_key = SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE;
    910             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    911                                  KEY_TYPEf, field_key);
    912             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    913                                     VALIDf, 1);
    914             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    915                                  L2__DEST_TYPEf, 0);
    916             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    917                                  L2__L2MC_PTRf, mc_index);
    918             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    919                                  L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1);
    920             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    921                                  L2__VLAN_IDf, vid);
    922             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
    923                                   L2__MAC_ADDRf, mac);
    924             break;
    925 
    926         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
    927                 mem = L2_ENTRY_2m;
    928                 field_key =  SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS;
    929                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    930                                      KEY_TYPE_0f, field_key);
    931                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    932                                      KEY_TYPE_1f, field_key);
    933                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    934                                     VALID_0f, 1);
    935                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    936                                     VALID_1f, 1);
    937                 if (flags & BCM_TRILL_MULTICAST_STATIC) { 
    938                     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    939                                   STATIC_BIT_1f, 0x1);
    940                     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    941                                   STATIC_BIT_0f, 0x1);
    942                 }
    943                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    944                                      L2__DEST_TYPEf, 0x3);
    945                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    946                                      L2__L2MC_PTRf, mc_index);
    947                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    948                                      L2__VLAN_IDf, vid);
    949                 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
    950                                      L2__MAC_ADDRf, mac);
    951             break;
    952 
    953         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    954             field_key =  
    955             SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT;
    956             if (flags & BCM_TRILL_MULTICAST_STATIC) { 
    957                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    958                               STATIC_BITf, 0x1);
    959             }
    960             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    961                                  KEY_TYPEf, field_key);
    962             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, VALIDf, 1);
    963             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    964                                  TRILL_NONUC_NETWORK_SHORT__TREE_IDf, trill_tree_id);
    965             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    966                                  TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf, mc_index);
    967             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    968                                  TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid);
    969             BCM_IF_ERROR_RETURN(soc_mem_read(unit, VLAN_TABm, 
    970                                   MEM_BLOCK_ANY, vid, &vt));
    971 
    972             if (soc_mem_field32_get(unit, VLAN_TABm, &vt, 
    973                     TRILL_ACCESS_RECEIVERS_PRESENTf)) {
    974                   soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    975                                  TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 1);
    976             }
    977 
    978             break;
    979 
    980         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    981             field_key =  
    982             SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG;
    983             if (flags & BCM_TRILL_MULTICAST_STATIC) { 
    984                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    985                               STATIC_BITf, 0x1);
    986             }
    987             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    988                                  KEY_TYPEf, field_key);
    989             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, VALIDf, 1);
    990             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    991                                  TRILL_NONUC_NETWORK_LONG__TREE_IDf, trill_tree_id);
    992             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    993                                  TRILL_NONUC_NETWORK_LONG__TRILL_ACCESS_RECEIVERS_PRESENTf, 1);
    994             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    995                                  TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf, mc_index);
    996             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    997                                  TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid);
    998             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
    999                                   TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac);
   1000             break;
   1001 
   1002         default:
   1003             break;
   1004         }
   1005     }
   1006 
   1007 
   1008     /* See if the entry already exists */
   1009     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index,
   1010                         (void *)&l2_entry, (void *)&l2_lookup, 0);
   1011 
   1012     if (rv == SOC_E_NONE) {
   1013         if (key == TR_L2_HASH_KEY_TYPE_BRIDGE) {
   1014             soc_mem_field32_set(unit, mem, (uint32*)&l2_lookup,
   1015                                  L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1);
   1016             rv = soc_mem_write(unit, mem,
   1017                                MEM_BLOCK_ALL, l2_index,
   1018                                &l2_lookup);
   1019         }
   1020     } else if ((rv < 0) && (rv != SOC_E_NOT_FOUND)) {
   1021         return rv;
   1022     } else {
   1023         /* Add Entry */
   1024         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry);
   1025         if ((rv == SOC_E_FULL) &&
   1026             ((key == TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) ||
   1027             (key == TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG)) &&
   1028             (flags & BCM_TRILL_MULTICAST_REPLACE_DYNAMIC)) {
   1029             /* For TRILL_NW_SHORT and TRILL_NW_LONG, if the table is FULL,
   1030                replace the existing entry */
   1031             _bcm_tr3_l2_entries_t l2_entries;
   1032             sal_memset(&l2_entries, 0, sizeof(l2_entries));
   1033             sal_memcpy((void *)&(l2_entries.l2_entry_1),
   1034                            (void *)&l2_entry,
   1035                            sizeof(l2_entry_1_entry_t));
   1036             l2_entries.entry_flags = _BCM_TR3_L2_SELECT_L2_ENTRY_1;
   1037             rv = _bcm_tr3_l2_hash_dynamic_replace(unit, &l2_entries);
   1038         }
   1039     }
   1040     return rv;
   1041 }
   1042 
   1043 
   1044 /*
   1045  * Purpose:
   1046  *      Update TRILL Multicast entry
   1047  * Parameters:
   1048  *      unit            - Device unit number
   1049  *      key             - defines entry type
   1050  *      vid             - Customer Vlan ID
   1051  *      mac             - Customer MAC
   1052  *      trill_tree_id   - specify Multicast Tree ID
   1053  *      group           - Trill Multicast group
   1054  * Returns:
   1055  *      BCM_E_NONE - Success.
   1056  *      BCM_E_XXX
   1057  */
   1058 int 
   1059 bcm_tr3_trill_l2_multicast_entry_update(int unit, int key, 
   1060                                     bcm_vlan_t vid, bcm_mac_t mac, 
   1061                                     uint8 trill_tree_id, bcm_multicast_t group)
   1062 {
   1063     L2_ENTRY_T  l2_entry, l2_lookup;
   1064     soc_mem_t mem; 
   1065     soc_field_t field_key;
   1066     int rv=BCM_E_NONE;
   1067     int l2_index=0;
   1068 
   1069     sal_memset(&l2_entry, 0, sizeof (l2_entry));
   1070     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
   1071 
   1072     mem = L2_ENTRY_1m;
   1073 
   1074     if (_BCM_MULTICAST_IS_TRILL(group)) {
   1075 
   1076         switch (key) {
   1077         case TR_L2_HASH_KEY_TYPE_BRIDGE:
   1078             field_key = SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE;
   1079             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1080                                  KEY_TYPEf, field_key);
   1081             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1082                                     VALIDf, 1);
   1083             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1084                                  L2__VLAN_IDf, vid);
   1085             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
   1086                                   L2__MAC_ADDRf, mac);
   1087             break;
   1088 
   1089         }
   1090     }
   1091 
   1092     /* See if the entry already exists */
   1093     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index,
   1094                         (void *)&l2_entry, (void *)&l2_lookup, 0);
   1095     if (rv == SOC_E_NONE) {
   1096         if (key == TR_L2_HASH_KEY_TYPE_BRIDGE) {
   1097             soc_mem_field32_set(unit, mem, (uint32*)&l2_lookup,
   1098                                  L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1);
   1099             rv = soc_mem_write(unit, mem,
   1100                                MEM_BLOCK_ALL, l2_index,
   1101                                &l2_lookup);
   1102         }
   1103     } else {
   1104         /* Entry must exist */
   1105         return rv;
   1106     }
   1107     return rv;
   1108 }
   1109 
   1110 /*
   1111  * Purpose:
   1112  *      Delete TRILL Multicast entry
   1113  * Parameters:
   1114  *      unit            - Device unit number
   1115  *      key             - defines entry type
   1116  *      vid             - Customer Vlan ID
   1117  *      mac             - Customer MAC
   1118  *      trill_tree_id   - specify Multicast Tree ID
   1119  * Returns:
   1120  *      BCM_E_NONE - Success.
   1121  *      BCM_E_XXX
   1122  */
   1123 int 
   1124 bcm_tr3_trill_l2_multicast_entry_delete(int unit, int key, bcm_vlan_t vid, 
   1125                                        bcm_mac_t mac, uint8 trill_tree_id)
   1126 {
   1127     L2_ENTRY_T  l2_entry, l2_lookup;
   1128     soc_mem_t mem; 
   1129     soc_field_t field_key;
   1130     int rv=BCM_E_NONE;
   1131     int l2_index=0;
   1132 
   1133     sal_memset(&l2_entry, 0, sizeof (l2_entry));
   1134     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
   1135 
   1136     mem = L2_ENTRY_1m;
   1137 
   1138     switch (key) {
   1139         case TR_L2_HASH_KEY_TYPE_BRIDGE:
   1140             field_key = SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE;
   1141             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1142                                 KEY_TYPEf, field_key);
   1143             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1144                                 L2__VLAN_IDf, vid);
   1145             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
   1146                                  L2__MAC_ADDRf, mac);
   1147             break;
   1148 
   1149         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
   1150             mem = L2_ENTRY_2m;
   1151             field_key =  SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS;
   1152             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1153                                 KEY_TYPE_0f, field_key);
   1154             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1155                                 KEY_TYPE_1f, field_key);
   1156             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1157                                 L2__VLAN_IDf, vid);
   1158             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
   1159                                  L2__MAC_ADDRf, mac);
   1160 
   1161             break;
   1162 
   1163         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
   1164             field_key =  
   1165             SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT;
   1166             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1167                                 KEY_TYPEf, field_key);
   1168             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1169                                 TRILL_NONUC_NETWORK_SHORT__TREE_IDf,
   1170                                 trill_tree_id);
   1171             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1172                                 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid);
   1173             break;
   1174 
   1175         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
   1176             field_key =  
   1177             SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG;
   1178             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1179                                 KEY_TYPEf, field_key);
   1180             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1181                                  TRILL_NONUC_NETWORK_LONG__TREE_IDf,
   1182                                 trill_tree_id);
   1183             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1184                                 TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid);
   1185             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
   1186                                  TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac);
   1187             break;
   1188                         
   1189         default:
   1190             break;
   1191     }
   1192 
   1193     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 
   1194                         (void *)&l2_entry, (void *)&l2_lookup, 0);
   1195                  
   1196     if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) {
   1197         return rv;
   1198     } 
   1199 
   1200     rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry);
   1201     return rv;
   1202 }
   1203 
   1204 /*
   1205  * Description:
   1206  *      Delete all TRILL entries in L2X table
   1207  * Parameters:
   1208  *     unit             - device number
   1209  *     tree_id          - Trill Tree ID
   1210  * Return:
   1211  *     BCM_E_XXX
   1212  */
   1213 int
   1214 bcm_tr3_trill_l2x_entry_delete_all (int unit, soc_mem_t mem, uint8 tree_id)
   1215 {
   1216     int           ix, key_type, chnk_end;
   1217     int           chunksize, chunk, chunk_max, mem_idx_max;
   1218     L2_ENTRY_T   *l2e, *l2ep;
   1219     soc_control_t *soc = SOC_CONTROL(unit);
   1220     int           rv = BCM_E_NONE;
   1221     int           key_match1, key_match2 = -1;
   1222     int           valid_fld, key_fld;
   1223     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   1224                                  L2_MEM_CHUNKS_DEFAULT);
   1225 
   1226     switch(mem) {
   1227         case L2_ENTRY_1m:
   1228             valid_fld  = VALIDf;
   1229             key_fld    = KEY_TYPEf;
   1230             key_match1 = SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT;
   1231             key_match2 = SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG;
   1232             break;
   1233         case L2_ENTRY_2m:
   1234             valid_fld  = VALID_0f;
   1235             key_fld    = KEY_TYPE_0f;
   1236             key_match1 = SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS;
   1237             break;
   1238         default:
   1239             return BCM_E_INTERNAL;
   1240     }
   1241 
   1242 
   1243     l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk");
   1244     if (l2e == NULL) {
   1245         return BCM_E_MEMORY;
   1246     }
   1247     mem_idx_max = soc_mem_index_max(unit, mem);
   1248     soc_mem_lock(unit, mem);
   1249     for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max;
   1250          chunk += chunksize) {
   1251 
   1252         chunk_max = chunk + chunksize - 1;
   1253         if (chunk_max > mem_idx_max) {
   1254             chunk_max = mem_idx_max;
   1255         }
   1256 
   1257         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   1258                                 chunk, chunk_max, l2e);
   1259         if (rv < 0) {
   1260             break;
   1261         }
   1262         chnk_end = (chunk_max - chunk);
   1263         for (ix = 0; ix <= chnk_end; ix++) {
   1264             l2ep = soc_mem_table_idx_to_pointer(unit, mem,
   1265                                                  L2_ENTRY_T *, l2e, ix);
   1266             if (!soc_mem_field32_get(unit, mem, l2ep, valid_fld)) {
   1267                 continue;
   1268             }
   1269 
   1270             /* Match the Key Type to TRILL */
   1271             key_type = soc_mem_field32_get(unit, mem, l2ep, key_fld);
   1272 
   1273             if (key_match2 != -1) {
   1274                 /* Match both LONG and SHORT keys */
   1275                 if ((key_type != key_match2) && (key_type != key_match1)) {
   1276                     continue;
   1277                 }
   1278 
   1279                 /* Match Tree ID */
   1280                 if ((tree_id != soc_mem_field32_get (unit, mem, l2ep,
   1281                                                       TRILL_NONUC_NETWORK_LONG__TREE_IDf)) &&
   1282                     (tree_id != soc_mem_field32_get(unit, mem, l2ep,
   1283                                                      TRILL_NONUC_NETWORK_SHORT__TREE_IDf))){
   1284                     continue;
   1285                 }
   1286 
   1287             } else {
   1288                 if (key_type != key_match1) {
   1289                     continue;
   1290                 }
   1291             }
   1292 
   1293             if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
   1294                 rv = BCM_E_RESOURCE;
   1295                 break;
   1296             }
   1297             if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) ||
   1298                 ((rv = soc_tr3_l2x_sync_delete(unit, mem, (uint32 *) l2ep,
   1299                                            (chunk + ix), 0)) < 0)) {
   1300                 SOC_L2_DEL_SYNC_UNLOCK(soc);
   1301                 break;
   1302             }
   1303             SOC_L2_DEL_SYNC_UNLOCK(soc);
   1304         }
   1305         if (rv < 0) {
   1306             break;
   1307         }
   1308     }
   1309     soc_mem_unlock(unit, mem);
   1310     soc_cm_sfree(unit, l2e);
   1311     return rv;
   1312 }
   1313 
   1314 /*
   1315  * Description:
   1316  *      Delete all TRILL tree-sepecific Multicast entries
   1317  * Parameters:
   1318  *     unit             - device number
   1319  *     tree_id          - Trill Tree ID
   1320  * Return:
   1321  *     BCM_E_XXX
   1322  */
   1323 int
   1324 bcm_tr3_trill_l2_multicast_entry_delete_all (int unit, uint8 tree_id)
   1325 {
   1326     int rv = BCM_E_NONE;
   1327     BCM_IF_ERROR_RETURN(
   1328         bcm_tr3_trill_l2x_entry_delete_all(unit, L2_ENTRY_1m, tree_id));
   1329 
   1330     rv = bcm_tr3_trill_l2x_entry_delete_all(unit, L2_ENTRY_2m, tree_id);
   1331     return rv;
   1332 }
   1333 
   1334 /*
   1335  * Purpose:
   1336  *      Get TRILL Multicast entry
   1337  * Parameters:
   1338  *      unit            - Device unit number
   1339  *      key             - defines entry type
   1340  *      vid             - Customer Vlan ID
   1341  *      mac             - Customer MAC
   1342  *      trill_tree_id   - specify Multicast Tree ID
   1343  *      group           - (OUT) Multicast group
   1344  * Returns:
   1345  *      BCM_E_NONE - Success.
   1346  *      BCM_E_XXX
   1347  */
   1348 int 
   1349 bcm_tr3_trill_l2_multicast_entry_get(int unit, int key, bcm_vlan_t vid, 
   1350                                        bcm_mac_t mac, uint8 trill_tree_id, bcm_multicast_t *group)
   1351 {
   1352     L2_ENTRY_T  l2_entry;
   1353     soc_mem_t mem; 
   1354     soc_field_t field_key;
   1355     int rv=BCM_E_NONE;
   1356     int l2_index=0;
   1357 
   1358     sal_memset(&l2_entry, 0, sizeof (l2_entry));
   1359 
   1360     mem = L2_ENTRY_1m;
   1361 
   1362     switch (key) {
   1363         case TR_L2_HASH_KEY_TYPE_BRIDGE:
   1364             field_key = SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE;
   1365             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1366                                 KEY_TYPEf, field_key);
   1367             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1368                                 L2__VLAN_IDf, vid);
   1369             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
   1370                                  L2__MAC_ADDRf, mac);
   1371             break;
   1372 
   1373         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
   1374                 mem = L2_ENTRY_2m;
   1375                 field_key =  SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS;
   1376                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1377                                     KEY_TYPE_0f, field_key);
   1378                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1379                                     KEY_TYPE_1f, field_key);
   1380                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1381                                     L2__VLAN_IDf, vid);
   1382                 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
   1383                                      L2__MAC_ADDRf, mac);
   1384            break;
   1385 
   1386         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
   1387             field_key =  
   1388             SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT;          
   1389             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1390                                 KEY_TYPEf, field_key);
   1391             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1392                                 TRILL_NONUC_NETWORK_SHORT__TREE_IDf,
   1393                                 trill_tree_id);
   1394             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1395                                 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid);
   1396             break;
   1397 
   1398         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
   1399             field_key =  
   1400             SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG;
   1401             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1402                                 KEY_TYPEf, field_key);
   1403             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1404                                  TRILL_NONUC_NETWORK_LONG__TREE_IDf,
   1405                                 trill_tree_id);
   1406             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
   1407                                 TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid);
   1408             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
   1409                                  TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac);
   1410             break;
   1411                         
   1412         default:
   1413             break;
   1414     }
   1415 
   1416     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 
   1417                         (void *)&l2_entry, (void *)&l2_entry, 0);
   1418                  
   1419     if (BCM_FAILURE(rv)) {
   1420         return rv;
   1421     } 
   1422 
   1423     switch (key) {
   1424         case TR_L2_HASH_KEY_TYPE_BRIDGE:
   1425                 _BCM_MULTICAST_GROUP_SET(*group, 
   1426                                   _BCM_MULTICAST_TYPE_L2,  
   1427                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
   1428                                     L2__L2MC_PTRf));
   1429                 break;
   1430 
   1431         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
   1432             if (SOC_IS_TRIUMPH3(unit)) {
   1433                 _BCM_MULTICAST_GROUP_SET(*group, 
   1434                                   _BCM_MULTICAST_TYPE_TRILL,  
   1435                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
   1436                                     L2__L2MC_PTRf));
   1437                 break;
   1438             }  else if (SOC_IS_TRIDENT2X(unit)) {
   1439                 _BCM_MULTICAST_GROUP_SET(*group, 
   1440                                   _BCM_MULTICAST_TYPE_TRILL,  
   1441                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
   1442                                     L2__L3MC_PTRf));
   1443                 break;
   1444             } else {
   1445                 _BCM_MULTICAST_GROUP_SET(*group, 
   1446                                   _BCM_MULTICAST_TYPE_TRILL,  
   1447                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
   1448                                     TRILL_NONUC_ACCESS__L3MC_PTRf));
   1449                 break;
   1450             }
   1451 
   1452         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
   1453                 _BCM_MULTICAST_GROUP_SET(*group, 
   1454                                   _BCM_MULTICAST_TYPE_TRILL,  
   1455                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
   1456                                     TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf));
   1457                 break;
   1458 
   1459         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
   1460                 _BCM_MULTICAST_GROUP_SET(*group, 
   1461                                   _BCM_MULTICAST_TYPE_TRILL,  
   1462                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
   1463                                     TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf));
   1464                 break;
   1465         default:
   1466             break;
   1467     }
   1468     return rv;
   1469 }
   1470 
   1471 
   1472 /*
   1473  * Description:
   1474  *      Traverse  TRILL Long and Short Multicast entries
   1475  * Parameters:
   1476  *     unit             - device number
   1477  *     trav_st        - Traverse structure with all the data.
   1478  * Return:
   1479  *     BCM_E_XXX
   1480  */
   1481 int
   1482 bcm_tr3_trill_l2_network_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st)
   1483 {
   1484    /* Indexes to iterate over memories, chunks and entries */
   1485     int        chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   1486     int        buf_size, chunksize, chnk_end;
   1487     /* Buffer to store chunk of L2 table we currently work on */
   1488     uint32     *l2_trill_tbl_chnk;
   1489     L2_ENTRY_T *l2_entry;
   1490     int        rv = BCM_E_NONE;
   1491     soc_mem_t  mem;
   1492     int        key_type=-1;
   1493     uint16     tree_id = 0;
   1494     bcm_trill_multicast_entry_t trill_mc;
   1495 
   1496 
   1497     mem = L2_ENTRY_1m;
   1498     
   1499     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
   1500 
   1501     if (!soc_mem_index_count(unit, mem)) {
   1502         return BCM_E_NONE;
   1503     }
   1504 
   1505     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   1506                                  L2_MEM_CHUNKS_DEFAULT);
   1507 
   1508     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   1509     l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill network multicast traverse");
   1510     if (NULL == l2_trill_tbl_chnk) {
   1511         return BCM_E_MEMORY;
   1512     }
   1513 
   1514     mem_idx_max = soc_mem_index_max(unit, mem);
   1515     for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 
   1516          chnk_idx += chunksize) {
   1517         sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size);
   1518 
   1519         chnk_idx_max = 
   1520             ((chnk_idx + chunksize) < mem_idx_max) ? 
   1521             (chnk_idx + chunksize - 1) : mem_idx_max;
   1522 
   1523         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   1524                                 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk);
   1525         if (SOC_FAILURE(rv)) {
   1526             break;
   1527         }
   1528         chnk_end = (chnk_idx_max - chnk_idx);
   1529         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   1530             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 
   1531                                              l2_trill_tbl_chnk, ent_idx);
   1532 
   1533             if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) {
   1534                 continue;
   1535             }
   1536 
   1537             key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf);
   1538           
   1539             /* Match the Key Type to TRILL */
   1540             if (key_type != SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG) {
   1541                 if (key_type != SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT) {
   1542                     continue;
   1543                 }
   1544             }
   1545            
   1546 
   1547             switch (key_type) {
   1548                 case SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT:
   1549                                 tree_id = soc_mem_field32_get(unit, mem, l2_entry,
   1550                                                  TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
   1551                                 /* Check for Valid Tree_Id */
   1552                                 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
   1553                                    continue;
   1554                                 }
   1555                                 (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name);
   1556                                 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
   1557                                                   _BCM_MULTICAST_TYPE_TRILL,  
   1558                                                   soc_mem_field32_get (unit, mem, l2_entry,
   1559                                                     TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf));
   1560                                 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry,
   1561                                                   TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
   1562                                 break;
   1563 
   1564                 case SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG:
   1565                                 tree_id = soc_mem_field32_get (unit, mem, l2_entry,
   1566                                                   TRILL_NONUC_NETWORK_LONG__TREE_IDf);
   1567                                 /* Check for Valid Tree_Id */
   1568                                 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
   1569                                     continue;
   1570                                 }
   1571                                 (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name);
   1572                                 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
   1573                                                   _BCM_MULTICAST_TYPE_TRILL,  
   1574                                                   soc_mem_field32_get (unit, mem, l2_entry,
   1575                                                     TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf));
   1576                                 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry,
   1577                                                   TRILL_NONUC_NETWORK_LONG__VLAN_IDf);
   1578                                 soc_mem_mac_addr_get(unit, mem, l2_entry,
   1579                                                    TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, trill_mc.c_dmac);
   1580                                 break;
   1581 
   1582             }
   1583             trill_mc.flags = BCM_TRILL_MULTICAST_STATIC;
   1584             rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data);
   1585             if (BCM_FAILURE(rv)) {
   1586                 break;
   1587             }
   1588         }
   1589         if (BCM_FAILURE(rv)) {
   1590             break;
   1591         }
   1592     }
   1593     soc_cm_sfree(unit, l2_trill_tbl_chnk);
   1594     return rv;        
   1595 }
   1596 
   1597 /*
   1598  * Description:
   1599  *      Traverse  TRILL Access to Network Multicast entries
   1600  * Parameters:
   1601  *     unit             - device number
   1602  *     trav_st        - Traverse structure with all the data.
   1603  * Return:
   1604  *     BCM_E_XXX
   1605  */
   1606 int
   1607 bcm_tr3_trill_l2_access_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st)
   1608 {
   1609    /* Indexes to iterate over memories, chunks and entries */
   1610     int        chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   1611     int        buf_size, chunksize, chnk_end;
   1612     /* Buffer to store chunk of L2 table we currently work on */
   1613     uint32     *l2_trill_tbl_chnk;
   1614     L2_ENTRY_T *l2_entry;
   1615     int        rv = BCM_E_NONE;
   1616     soc_mem_t  mem;
   1617     int        key_type=-1;
   1618     bcm_trill_multicast_entry_t  trill_mc;
   1619 
   1620     mem = L2_ENTRY_2m;
   1621     
   1622     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
   1623 
   1624     if (!soc_mem_index_count(unit, mem)) {
   1625         return BCM_E_NONE;
   1626     }
   1627 
   1628     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   1629                                  L2_MEM_CHUNKS_DEFAULT);
   1630 
   1631     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   1632     l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill access multicast traverse");
   1633     if (NULL == l2_trill_tbl_chnk) {
   1634         return BCM_E_MEMORY;
   1635     }
   1636 
   1637     mem_idx_max = soc_mem_index_max(unit, mem);
   1638     for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 
   1639          chnk_idx += chunksize) {
   1640         sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size);
   1641 
   1642         chnk_idx_max = 
   1643             ((chnk_idx + chunksize) < mem_idx_max) ? 
   1644             (chnk_idx + chunksize - 1) : mem_idx_max;
   1645 
   1646         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   1647                                 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk);
   1648         if (SOC_FAILURE(rv)) {
   1649             break;
   1650         }
   1651         chnk_end = (chnk_idx_max - chnk_idx);
   1652         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   1653             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 
   1654                                              l2_trill_tbl_chnk, ent_idx);
   1655 
   1656                 if (!soc_mem_field32_get(unit, mem, l2_entry, VALID_0f)) {
   1657                     continue;
   1658                 }
   1659                 key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPE_0f);
   1660                 if (key_type != SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS) {
   1661                     continue;
   1662                 } else {
   1663                     _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
   1664                                       _BCM_MULTICAST_TYPE_TRILL,  
   1665                                       soc_mem_field32_get (unit, mem, l2_entry,
   1666                                       L2__L2MC_PTRf));
   1667                     trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry,
   1668                                       L2__VLAN_IDf);
   1669                     soc_mem_mac_addr_get(unit, mem, l2_entry,
   1670                                       L2__MAC_ADDRf, trill_mc.c_dmac);
   1671                 }
   1672            
   1673             trill_mc.flags = BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK | BCM_TRILL_MULTICAST_STATIC;
   1674             rv = bcm_td_multicast_trill_rootname_get(unit, trill_mc.group, &trill_mc.root_name);
   1675             if (BCM_FAILURE(rv)) {
   1676                  continue;
   1677             }
   1678 
   1679             rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data);
   1680             if (BCM_FAILURE(rv)) {
   1681                 break;
   1682             }
   1683         }
   1684         if (BCM_FAILURE(rv)) {
   1685             break;
   1686         }
   1687     }
   1688     soc_cm_sfree(unit, l2_trill_tbl_chnk);
   1689     return rv;        
   1690 }
   1691 
   1692 
   1693 
   1694 /*
   1695  * Description:
   1696  *      Traverse  TRILL Unpruned Multicast entries
   1697  * Parameters:
   1698  *     unit             - device number
   1699  *     trav_st        - Traverse structure with all the data.
   1700  * Return:
   1701  *     BCM_E_XXX
   1702  */
   1703 int
   1704 bcm_tr3_trill_unpruned_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st)
   1705 {
   1706    /* Indexes to iterate over memories, chunks and entries */
   1707     int             chnk_idx=0, ent_idx=0, chnk_idx_max=0, mem_idx_max=0;
   1708     int             buf_size=0, chunksize=0, chnk_end=0;
   1709     uint32          *unpruned_trill_tbl_chnk;
   1710     mpls_entry_extd_entry_t *ment;
   1711     int             rv = BCM_E_NONE;
   1712     soc_mem_t     mem;
   1713     int    key_type=0;
   1714     uint8   tree_id=0xff;
   1715     bcm_trill_name_t  root_name=0;
   1716     bcm_trill_multicast_entry_t  trill_mc;
   1717 
   1718     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
   1719 
   1720     mem = MPLS_ENTRY_EXTDm;
   1721 
   1722     if (!soc_mem_index_count(unit, mem)) {
   1723         return BCM_E_NONE;
   1724     }
   1725 
   1726     chunksize = 4096;
   1727 
   1728     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   1729     unpruned_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill multicast unpruned traverse");
   1730     if (NULL == unpruned_trill_tbl_chnk) {
   1731         return BCM_E_MEMORY;
   1732     }
   1733 
   1734     mem_idx_max = soc_mem_index_max(unit, mem);
   1735     for (chnk_idx = soc_mem_index_min(unit, mem); 
   1736          chnk_idx <= mem_idx_max; chnk_idx += chunksize) {
   1737         sal_memset((void *)unpruned_trill_tbl_chnk, 0, buf_size);
   1738 
   1739         chnk_idx_max = 
   1740             ((chnk_idx + chunksize) < mem_idx_max) ? 
   1741             (chnk_idx + chunksize - 1) : mem_idx_max;
   1742 
   1743         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   1744                                 chnk_idx, chnk_idx_max, unpruned_trill_tbl_chnk);
   1745         if (SOC_FAILURE(rv)) {
   1746             break;
   1747         }
   1748         chnk_end = (chnk_idx_max - chnk_idx);
   1749         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   1750             ment = soc_mem_table_idx_to_pointer(unit, mem, mpls_entry_extd_entry_t *, 
   1751                                              unpruned_trill_tbl_chnk, ent_idx);
   1752 
   1753             if (!soc_mem_field32_get(unit, mem, ment, VALID_0f)) {
   1754                 continue;
   1755             }
   1756             if (!soc_mem_field32_get(unit, mem, ment, VALID_1f)) {
   1757                 continue;
   1758             }
   1759           
   1760             /* Match the Key Type to TRILL */
   1761             key_type = soc_mem_field32_get(unit, mem, ment, KEY_TYPE_0f);
   1762 
   1763             if (key_type != 0x1A) { /* RBRIDGE_NICKNAME */
   1764                 continue;
   1765             }
   1766             key_type = soc_mem_field32_get(unit, mem, ment, KEY_TYPE_1f);
   1767 
   1768             if (key_type != 0x1A) { /* RBRIDGE_NICKNAME */
   1769                 continue;
   1770             }
   1771 
   1772             /* Skip entries that discard multicast destinations */
   1773             if (soc_mem_field_valid(unit, mem, 
   1774                                     TRILL__MCAST_DST_DISCARDf)) {
   1775                 if (soc_mem_field32_get(unit,
   1776                                         mem, ment, TRILL__MCAST_DST_DISCARDf)) {
   1777                     continue;
   1778                 }
   1779             }
   1780 
   1781 
   1782             /* Check for Valid Tree_Id */
   1783             tree_id = soc_mem_field32_get(unit, mem, ment, TRILL__TREE_IDf);
   1784             if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
   1785                 continue;
   1786             }
   1787             root_name = soc_mem_field32_get(unit, mem, ment, TRILL__RBRIDGE_NICKNAMEf);
   1788             (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name);
   1789             if (root_name != trill_mc.root_name) {
   1790                 continue;
   1791             }
   1792 
   1793             _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
   1794                               _BCM_MULTICAST_TYPE_TRILL,  
   1795                               soc_mem_field32_get (unit, mem, ment,
   1796                                 TRILL__L3MC_INDEXf));
   1797 
   1798             rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data);
   1799             if (BCM_FAILURE(rv)) {
   1800                 break;
   1801             }
   1802         }
   1803         if (BCM_FAILURE(rv)) {
   1804             break;
   1805         }
   1806     }
   1807     soc_cm_sfree(unit, unpruned_trill_tbl_chnk);
   1808     return rv;        
   1809 }
   1810 
   1811 /*
   1812  * Description:
   1813  *      Modify  TRILL short Multicast entries
   1814  * Parameters:
   1815  *     unit             - device number
   1816  *     trav_st        - Traverse structure with all the data.
   1817  * Return:
   1818  *     BCM_E_XXX
   1819  */
   1820 int
   1821 bcm_tr3_trill_vlan_multicast_entry_modify (int unit, bcm_vlan_t vlan, int set_bit)
   1822 {
   1823    /* Indexes to iterate over memories, chunks and entries */
   1824     int        chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
   1825     int        buf_size, chunksize, chnk_end;
   1826     /* Buffer to store chunk of L2 table we currently work on */
   1827     uint32     *l2_trill_tbl_chnk;
   1828     L2_ENTRY_T *l2_entry;
   1829     int        rv = BCM_E_NONE;
   1830     soc_mem_t  mem;
   1831     int        key_type=-1;
   1832     uint16     tree_id = 0;
   1833     bcm_trill_multicast_entry_t trill_mc;
   1834     int count=0;
   1835 
   1836     mem = L2_ENTRY_1m;
   1837     
   1838     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
   1839 
   1840     if (!soc_mem_index_count(unit, mem)) {
   1841         return BCM_E_NONE;
   1842     }
   1843 
   1844     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   1845                                  L2_MEM_CHUNKS_DEFAULT);
   1846 
   1847     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
   1848     l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill network multicast traverse");
   1849     if (NULL == l2_trill_tbl_chnk) {
   1850         return BCM_E_MEMORY;
   1851     }
   1852 
   1853     mem_idx_max = soc_mem_index_max(unit, mem);
   1854     for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 
   1855          chnk_idx += chunksize) {
   1856         sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size);
   1857 
   1858         chnk_idx_max = 
   1859             ((chnk_idx + chunksize) < mem_idx_max) ? 
   1860             (chnk_idx + chunksize - 1) : mem_idx_max;
   1861 
   1862         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   1863                                 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk);
   1864         if (SOC_FAILURE(rv)) {
   1865             break;
   1866         }
   1867         chnk_end = (chnk_idx_max - chnk_idx);
   1868         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
   1869             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 
   1870                                              l2_trill_tbl_chnk, ent_idx);
   1871 
   1872             if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) {
   1873                 continue;
   1874             }
   1875 
   1876             key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf);
   1877           
   1878             /* Match the Key Type to TRILL */
   1879             if (key_type != SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT) {
   1880                continue;
   1881             } else {
   1882                 tree_id = soc_mem_field32_get(unit, mem, l2_entry,
   1883                                  TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
   1884                 /* Check for Valid Tree_Id */
   1885                 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
   1886                    continue;
   1887                 }
   1888                 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry,
   1889                                   TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
   1890                 if (vlan ==  trill_mc.c_vlan) {
   1891                    if (set_bit) {
   1892                        soc_mem_field32_set(unit, mem, (uint32 *)l2_entry, 
   1893                              TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 0x1);
   1894                    } else {
   1895                        soc_mem_field32_set(unit, mem, (uint32 *)l2_entry, 
   1896                              TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 0x0);
   1897                    }
   1898                    count ++;
   1899                 }
   1900             }
   1901         }
   1902         if (count > 0) {
   1903             rv = soc_mem_write_range(unit, SOURCE_VPm,
   1904                                      MEM_BLOCK_ANY, chnk_idx,
   1905                                      chnk_idx_max, l2_trill_tbl_chnk);
   1906         } 
   1907     }
   1908     soc_cm_sfree(unit, l2_trill_tbl_chnk);
   1909     return rv;        
   1910 }
   1911 
   1912 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
   1913