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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        l2.c
      8  * Purpose:     Trident L2 function implementations
      9  */
     10 #include <soc/defs.h>
     11 	 
     12 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
     13 	 
     14 #include <assert.h>
     15 	 
     16 #include <sal/core/libc.h>
     17 	 
     18 #include <soc/mem.h>
     19 #include <soc/debug.h>
     20 #include <soc/cm.h>
     21 #include <soc/drv.h>
     22 #include <soc/register.h>
     23 #include <soc/memory.h>
     24 #include <soc/hash.h>
     25 #include <soc/l2x.h>
     26 #include <soc/triumph.h>
     27 #include <soc/trident2.h>
     28 #include <bcm/l2.h>
     29 #include <bcm/error.h>
     30 #include <bcm_int/esw/l2.h>
     31 #include <bcm_int/common/multicast.h>
     32 #include <bcm_int/esw/trill.h>
     33 #include <bcm_int/esw/trident.h>
     34 #include <bcm_int/esw/triumph.h>
     35 
     36 typedef uint32 L2_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS];
     37 
     38 #if defined(INCLUDE_L3)
     39 /*
     40  * Purpose:
     41  *      Add TRILL Multicast entry
     42  * Parameters:
     43  *      unit            - Device unit number
     44  *      key             - defines entry type
     45  *      vid             - Customer Vlan ID
     46  *      mac             - Customer MAC
     47  *      trill_tree_id   - specify Multicast Tree ID
     48  *      group           - Multicast group
     49  * Returns:
     50  *      BCM_E_NONE - Success.
     51  *      BCM_E_XXX
     52  */
     53 int 
     54 bcm_td2_trill_l2_multicast_entry_add(int unit, uint32 flags, int key, 
     55                                     bcm_vlan_t vid, bcm_mac_t mac, 
     56                                     uint8 trill_tree_id, bcm_multicast_t group)
     57 {
     58     L2_ENTRY_T  l2_entry, l2_lookup;
     59     soc_mem_t mem; 
     60     soc_field_t field_key;
     61     int rv=BCM_E_NONE;
     62     int mc_index=0,l2_index=0;
     63     vlan_tab_entry_t  vt;
     64 
     65     sal_memset(&l2_entry, 0, sizeof (l2_entry));
     66     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
     67 
     68     mem = L2Xm;
     69 
     70     if (_BCM_MULTICAST_IS_SET(group)) {
     71 
     72         mc_index = _BCM_MULTICAST_ID_GET(group);
     73 
     74         switch (key) {
     75         case TR_L2_HASH_KEY_TYPE_BRIDGE:
     76             field_key = TD2_L2_HASH_KEY_TYPE_BRIDGE;      
     77             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
     78                                  KEY_TYPEf, field_key);
     79             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
     80                                     VALIDf, 1);
     81             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
     82                                  L2__DEST_TYPEf, 0);
     83             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
     84                                  L2__L2MC_PTRf, mc_index);
     85             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
     86                                  L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1);
     87             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
     88                                  L2__VLAN_IDf, vid);
     89             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
     90                                   L2__MAC_ADDRf, mac);
     91             break;
     92 
     93         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
     94                 field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS;
     95                 if (flags & BCM_TRILL_MULTICAST_STATIC) { 
     96                     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
     97                                   L2__STATIC_BITf, 0x1);
     98                 }
     99                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    100                                     KEY_TYPEf, field_key);
    101                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    102                                     L2__VLAN_IDf, vid);
    103                 soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
    104                                      L2__MAC_ADDRf, mac);
    105                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    106                                     L2__DEST_TYPEf, 0x3);
    107                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    108                                     L2__L3MC_PTRf, mc_index);
    109                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    110                                     VALIDf, 1);
    111             break;
    112 
    113         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    114                 field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT;
    115                 if (flags & BCM_TRILL_MULTICAST_STATIC) { 
    116                     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    117                                   TRILL_NONUC_NETWORK_SHORT__STATIC_BITf, 0x1);
    118                 } else {
    119                     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    120                                   TRILL_NONUC_NETWORK_SHORT__STATIC_BITf, 0x0);
    121                 }           
    122             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    123                                  KEY_TYPEf, field_key);
    124             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, VALIDf, 1);
    125             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    126                                  TRILL_NONUC_NETWORK_SHORT__TREE_IDf, trill_tree_id);
    127             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    128                                  TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf, mc_index);
    129             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    130                                  TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid);
    131 
    132             BCM_IF_ERROR_RETURN(soc_mem_read(unit, VLAN_TABm, 
    133                                   MEM_BLOCK_ANY, vid, &vt));
    134 
    135             if (soc_mem_field32_get(unit, VLAN_TABm, &vt, 
    136                     TRILL_ACCESS_RECEIVERS_PRESENTf)) {
    137                   soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    138                                  TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 1);
    139             }
    140 
    141             break;
    142 
    143         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    144                 field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG;
    145                 if (flags & BCM_TRILL_MULTICAST_STATIC) { 
    146                     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    147                                   TRILL_NONUC_NETWORK_LONG__STATIC_BITf, 0x1);
    148                 }           
    149             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    150                                  KEY_TYPEf, field_key);
    151             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, VALIDf, 1);
    152             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    153                                  TRILL_NONUC_NETWORK_LONG__TREE_IDf, trill_tree_id);
    154             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    155                                  TRILL_NONUC_NETWORK_LONG__TRILL_ACCESS_RECEIVERS_PRESENTf, 1);
    156             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    157                                  TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf, mc_index);
    158             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    159                                  TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid);
    160             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
    161                                   TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac);
    162             break;
    163 
    164         default:
    165             break;
    166         }
    167     }
    168 
    169 
    170     /* See if the entry already exists */
    171     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index,
    172                         (void *)&l2_entry, (void *)&l2_lookup, 0);
    173 
    174     if (rv == SOC_E_NONE) {
    175         if (key == TR_L2_HASH_KEY_TYPE_BRIDGE) {
    176             soc_mem_field32_set(unit, mem, (uint32*)&l2_lookup,
    177                                  L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1);
    178             rv = soc_mem_write(unit, mem,
    179                                MEM_BLOCK_ALL, l2_index,
    180                                &l2_lookup);
    181         }
    182     } else if ((rv < 0) && (rv != SOC_E_NOT_FOUND)) {
    183         return rv;
    184     } else {
    185         /* Add Entry */
    186         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry);
    187         if ((rv == SOC_E_FULL) &&
    188             ((key == TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) ||
    189             (key == TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG)) &&
    190             (flags & BCM_TRILL_MULTICAST_REPLACE_DYNAMIC)) {
    191             /*
    192              *  If the table is FULL,
    193              *  replace the existing entry for TRILL_NW_SHORT and TRILL_NW_LONG.
    194              */
    195             l2x_entry_t l2x_entry;
    196             sal_memcpy((void *)&l2x_entry,
    197                        (void *)&l2_entry, sizeof(l2x_entry_t));
    198             rv = _bcm_l2_hash_dynamic_replace(unit, &l2x_entry);
    199         }
    200     }
    201     return rv;
    202 }
    203 
    204 
    205 /*
    206  * Purpose:
    207  *      Update TRILL Multicast entry
    208  * Parameters:
    209  *      unit            - Device unit number
    210  *      key             - defines entry type
    211  *      vid             - Customer Vlan ID
    212  *      mac             - Customer MAC
    213  *      trill_tree_id   - specify Multicast Tree ID
    214  *      group           - Trill Multicast group
    215  * Returns:
    216  *      BCM_E_NONE - Success.
    217  *      BCM_E_XXX
    218  */
    219 int 
    220 bcm_td2_trill_l2_multicast_entry_update(int unit, int key, 
    221                                     bcm_vlan_t vid, bcm_mac_t mac, 
    222                                     uint8 trill_tree_id, bcm_multicast_t group)
    223 {
    224     L2_ENTRY_T  l2_entry, l2_lookup;
    225     soc_mem_t mem; 
    226     soc_field_t field_key;
    227     int rv=BCM_E_NONE;
    228     int l2_index=0;
    229 
    230     sal_memset(&l2_entry, 0, sizeof (l2_entry));
    231     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
    232 
    233     mem = L2Xm;
    234 
    235     if (_BCM_MULTICAST_IS_TRILL(group)) {
    236 
    237         switch (key) {
    238         case TR_L2_HASH_KEY_TYPE_BRIDGE:
    239             field_key = TD2_L2_HASH_KEY_TYPE_BRIDGE;
    240             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    241                                  KEY_TYPEf, field_key);
    242             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    243                                     VALIDf, 1);
    244             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    245                                  L2__VLAN_IDf, vid);
    246             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
    247                                   L2__MAC_ADDRf, mac);
    248             break;
    249 
    250         }
    251     }
    252 
    253     /* See if the entry already exists */
    254     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index,
    255                         (void *)&l2_entry, (void *)&l2_lookup, 0);
    256     if (rv == SOC_E_NONE) {
    257         if (key == TR_L2_HASH_KEY_TYPE_BRIDGE) {
    258             soc_mem_field32_set(unit, mem, (uint32*)&l2_lookup,
    259                                  L2__TRILL_NETWORK_RECEIVERS_PRESENTf, 1);
    260             rv = soc_mem_write(unit, mem,
    261                                MEM_BLOCK_ALL, l2_index,
    262                                &l2_lookup);
    263         }
    264     } else {
    265         /* Entry must exist */
    266         return rv;
    267     }
    268     return rv;
    269 }
    270 
    271 /*
    272  * Purpose:
    273  *      Delete TRILL Multicast entry
    274  * Parameters:
    275  *      unit            - Device unit number
    276  *      key             - defines entry type
    277  *      vid             - Customer Vlan ID
    278  *      mac             - Customer MAC
    279  *      trill_tree_id   - specify Multicast Tree ID
    280  * Returns:
    281  *      BCM_E_NONE - Success.
    282  *      BCM_E_XXX
    283  */
    284 int 
    285 bcm_td2_trill_l2_multicast_entry_delete(int unit, int key, bcm_vlan_t vid, 
    286                                        bcm_mac_t mac, uint8 trill_tree_id)
    287 {
    288     L2_ENTRY_T  l2_entry, l2_lookup;
    289     soc_mem_t mem; 
    290     soc_field_t field_key;
    291     int rv=BCM_E_NONE;
    292     int l2_index=0;
    293 
    294     sal_memset(&l2_entry, 0, sizeof (l2_entry));
    295     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
    296 
    297     mem = L2Xm;
    298 
    299     switch (key) {
    300         case TR_L2_HASH_KEY_TYPE_BRIDGE:
    301             field_key = TD2_L2_HASH_KEY_TYPE_BRIDGE;
    302             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    303                                 KEY_TYPEf, field_key);
    304             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    305                                 L2__VLAN_IDf, vid);
    306             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
    307                                  L2__MAC_ADDRf, mac);
    308             break;
    309 
    310         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
    311             field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS;
    312             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    313                                 KEY_TYPEf, field_key);
    314             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    315                                 L2__VLAN_IDf, vid);
    316             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
    317                                  L2__MAC_ADDRf, mac);           
    318             break;
    319 
    320         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    321             field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT;
    322             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    323                                 KEY_TYPEf, field_key);
    324             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    325                                 TRILL_NONUC_NETWORK_SHORT__TREE_IDf,
    326                                 trill_tree_id);
    327             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    328                                 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid);
    329             break;
    330 
    331         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    332             field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG;            
    333             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    334                                 KEY_TYPEf, field_key);
    335             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    336                                  TRILL_NONUC_NETWORK_LONG__TREE_IDf,
    337                                 trill_tree_id);
    338             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    339                                 TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid);
    340             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
    341                                  TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac);
    342             break;
    343                         
    344         default:
    345             break;
    346     }
    347 
    348     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 
    349                         (void *)&l2_entry, (void *)&l2_lookup, 0);
    350                  
    351     if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) {
    352         return rv;
    353     } 
    354 
    355     rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry);
    356     return rv;
    357 }
    358 
    359 
    360 /*
    361  * Description:
    362  *      Delete all TRILL tree-sepecific Multicast entries
    363  * Parameters:
    364  *     unit             - device number
    365  *     tree_id          - Trill Tree ID
    366  * Return:
    367  *     BCM_E_XXX
    368  */
    369 int
    370 bcm_td2_trill_l2_multicast_entry_delete_all (int unit, uint8 tree_id)
    371 {
    372     int           ix, key_type, chnk_end;
    373     int           chunksize, chunk, chunk_max, mem_idx_max;
    374     L2_ENTRY_T   *l2e, *l2ep;
    375     soc_control_t *soc = SOC_CONTROL(unit);
    376     soc_mem_t     mem;
    377     int           rv = BCM_E_NONE;
    378     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    379                                  L2_MEM_CHUNKS_DEFAULT);
    380 
    381     mem = L2Xm;
    382 
    383     l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk");
    384     if (l2e == NULL) {
    385         return BCM_E_MEMORY;
    386     }
    387     mem_idx_max = soc_mem_index_max(unit, mem);
    388     soc_mem_lock(unit, mem);
    389     for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max;
    390          chunk += chunksize) {
    391         
    392         chunk_max = chunk + chunksize - 1;
    393         if (chunk_max > mem_idx_max) {
    394             chunk_max = mem_idx_max;
    395         }
    396 
    397         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    398                                 chunk, chunk_max, l2e);
    399         if (rv < 0) {
    400             break;
    401         }
    402         chnk_end = (chunk_max - chunk);
    403         for (ix = 0; ix <= chnk_end; ix++) {
    404             l2ep = soc_mem_table_idx_to_pointer(unit, mem,
    405                                                  L2_ENTRY_T *, l2e, ix);
    406             if (!soc_mem_field32_get(unit, mem, l2ep, VALIDf)) {
    407                 continue;
    408             }
    409             if (soc_mem_field32_get(unit, mem, l2ep, PENDINGf)) {
    410                 continue;
    411             }
    412             
    413             /* Match the Key Type to TRILL */
    414             key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf);
    415                 if (key_type != TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS) {
    416                     if (key_type != TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) {
    417                         if (key_type != TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG) {
    418                             continue;
    419                         }
    420                     }
    421                 }
    422             
    423 
    424             if ((tree_id != soc_mem_field32_get (unit, mem, l2ep,
    425                                                   TRILL_NONUC_NETWORK_LONG__TREE_IDf)) &&
    426                 (tree_id != soc_mem_field32_get(unit, mem, l2ep,
    427                                                  TRILL_NONUC_NETWORK_SHORT__TREE_IDf))){
    428                 continue;
    429             }
    430             
    431             if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
    432                 rv = BCM_E_RESOURCE;
    433                 break;
    434             }
    435             if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) ||
    436                 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep,
    437                                            (chunk + ix), 0)) < 0)) {
    438                 SOC_L2_DEL_SYNC_UNLOCK(soc);
    439                 break;
    440             }
    441             SOC_L2_DEL_SYNC_UNLOCK(soc);
    442         }
    443         if (rv < 0) {
    444             break;
    445         }
    446     }
    447     soc_mem_unlock(unit, mem);
    448     soc_cm_sfree(unit, l2e);
    449 
    450     return rv;
    451 }
    452 
    453 /*
    454  * Purpose:
    455  *      Get TRILL Multicast entry
    456  * Parameters:
    457  *      unit            - Device unit number
    458  *      key             - defines entry type
    459  *      vid             - Customer Vlan ID
    460  *      mac             - Customer MAC
    461  *      trill_tree_id   - specify Multicast Tree ID
    462  *      group           - (OUT) Multicast group
    463  * Returns:
    464  *      BCM_E_NONE - Success.
    465  *      BCM_E_XXX
    466  */
    467 int 
    468 bcm_td2_trill_l2_multicast_entry_get(int unit, int key, bcm_vlan_t vid, 
    469                                        bcm_mac_t mac, uint8 trill_tree_id, bcm_multicast_t *group)
    470 {
    471     L2_ENTRY_T  l2_entry;
    472     soc_mem_t mem; 
    473     soc_field_t field_key;
    474     int rv=BCM_E_NONE;
    475     int l2_index=0;
    476 
    477     sal_memset(&l2_entry, 0, sizeof (l2_entry));
    478 
    479     mem = L2Xm;
    480 
    481     switch (key) {
    482         case TR_L2_HASH_KEY_TYPE_BRIDGE:
    483             field_key = TD2_L2_HASH_KEY_TYPE_BRIDGE;
    484             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    485                                 KEY_TYPEf, field_key);
    486             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    487                                 L2__VLAN_IDf, vid);
    488             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
    489                                  L2__MAC_ADDRf, mac);
    490             break;
    491 
    492         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
    493             field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS;
    494             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    495                                 KEY_TYPEf, field_key);
    496             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    497                                 L2__VLAN_IDf, vid);
    498             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry,
    499                                  L2__MAC_ADDRf, mac);
    500             break;
    501 
    502         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    503             field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT;
    504             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    505                                 KEY_TYPEf, field_key);
    506             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    507                                 TRILL_NONUC_NETWORK_SHORT__TREE_IDf,
    508                                 trill_tree_id);
    509             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    510                                 TRILL_NONUC_NETWORK_SHORT__VLAN_IDf, vid);
    511             break;
    512 
    513         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    514             field_key = TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG;
    515             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    516                                 KEY_TYPEf, field_key);
    517             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    518                                  TRILL_NONUC_NETWORK_LONG__TREE_IDf,
    519                                 trill_tree_id);
    520             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry, 
    521                                 TRILL_NONUC_NETWORK_LONG__VLAN_IDf, vid);
    522             soc_mem_mac_addr_set(unit, mem, (uint32 *)&l2_entry, 
    523                                  TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac);
    524             break;
    525                         
    526         default:
    527             break;
    528     }
    529 
    530     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index, 
    531                         (void *)&l2_entry, (void *)&l2_entry, 0);
    532                  
    533     if (BCM_FAILURE(rv)) {
    534         return rv;
    535     } 
    536 
    537     switch (key) {
    538         case TR_L2_HASH_KEY_TYPE_BRIDGE:
    539                 _BCM_MULTICAST_GROUP_SET(*group, 
    540                                   _BCM_MULTICAST_TYPE_L2,  
    541                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
    542                                     L2__L2MC_PTRf));
    543                 break;
    544 
    545         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
    546             if (SOC_IS_TRIUMPH3(unit)) {
    547                 _BCM_MULTICAST_GROUP_SET(*group, 
    548                                   _BCM_MULTICAST_TYPE_TRILL,  
    549                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
    550                                     L2__L2MC_PTRf));
    551                 break;
    552             }  else if (SOC_IS_TRIDENT2X(unit)) {
    553                 _BCM_MULTICAST_GROUP_SET(*group, 
    554                                   _BCM_MULTICAST_TYPE_TRILL,  
    555                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
    556                                     L2__L3MC_PTRf));
    557                 break;
    558             } else {
    559                 _BCM_MULTICAST_GROUP_SET(*group, 
    560                                   _BCM_MULTICAST_TYPE_TRILL,  
    561                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
    562                                     TRILL_NONUC_ACCESS__L3MC_PTRf));
    563                 break;
    564             }
    565 
    566         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    567                 _BCM_MULTICAST_GROUP_SET(*group, 
    568                                   _BCM_MULTICAST_TYPE_TRILL,  
    569                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
    570                                     TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf));
    571                 break;
    572 
    573         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    574                 _BCM_MULTICAST_GROUP_SET(*group, 
    575                                   _BCM_MULTICAST_TYPE_TRILL,  
    576                                   soc_mem_field32_get (unit, mem, (uint32 *)&l2_entry,
    577                                     TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf));
    578                 break;
    579         default:
    580             break;
    581     }
    582     return rv;
    583 }
    584 
    585 
    586 /*
    587  * Description:
    588  *      Traverse  TRILL Long and Short Multicast entries
    589  * Parameters:
    590  *     unit             - device number
    591  *     trav_st        - Traverse structure with all the data.
    592  * Return:
    593  *     BCM_E_XXX
    594  */
    595 int
    596 bcm_td2_trill_l2_network_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st)
    597 {
    598    /* Indexes to iterate over memories, chunks and entries */
    599     int        chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
    600     int        buf_size, chunksize, chnk_end;
    601     /* Buffer to store chunk of L2 table we currently work on */
    602     uint32     *l2_trill_tbl_chnk;
    603     L2_ENTRY_T *l2_entry;
    604     int        rv = BCM_E_NONE;
    605     soc_mem_t  mem;
    606     int        key_type=-1;
    607     uint16     tree_id = 0;
    608     bcm_trill_multicast_entry_t trill_mc;
    609 
    610 
    611     mem = L2Xm;
    612     
    613     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
    614 
    615     if (!soc_mem_index_count(unit, mem)) {
    616         return BCM_E_NONE;
    617     }
    618 
    619     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    620                                  L2_MEM_CHUNKS_DEFAULT);
    621 
    622     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
    623     l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill network multicast traverse");
    624     if (NULL == l2_trill_tbl_chnk) {
    625         return BCM_E_MEMORY;
    626     }
    627 
    628     mem_idx_max = soc_mem_index_max(unit, mem);
    629     for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 
    630          chnk_idx += chunksize) {
    631         sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size);
    632 
    633         chnk_idx_max = 
    634             ((chnk_idx + chunksize) < mem_idx_max) ? 
    635             (chnk_idx + chunksize - 1) : mem_idx_max;
    636 
    637         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    638                                 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk);
    639         if (SOC_FAILURE(rv)) {
    640             break;
    641         }
    642         chnk_end = (chnk_idx_max - chnk_idx);
    643         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
    644             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 
    645                                              l2_trill_tbl_chnk, ent_idx);
    646 
    647             if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) {
    648                 continue;
    649             }
    650 
    651             key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf);
    652           
    653             /* Match the Key Type to TRILL */
    654             if (key_type != TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG) {
    655                 if (key_type != TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) {
    656                     continue;
    657                 }
    658             }
    659 
    660             switch (key_type) {
    661 
    662                 case  TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    663                                 tree_id = soc_mem_field32_get(unit, mem, l2_entry,
    664                                                  TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
    665                                 /* Check for Valid Tree_Id */
    666                                 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
    667                                    continue;
    668                                 }
    669                                 (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name);
    670                                 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
    671                                                   _BCM_MULTICAST_TYPE_TRILL,  
    672                                                   soc_mem_field32_get (unit, mem, l2_entry,
    673                                                     TRILL_NONUC_NETWORK_SHORT__L3MC_INDEXf));
    674                                 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry,
    675                                                   TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
    676                                 break;
    677 
    678                 case  TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    679                                 tree_id = soc_mem_field32_get (unit, mem, l2_entry,
    680                                                   TRILL_NONUC_NETWORK_LONG__TREE_IDf);
    681                                 /* Check for Valid Tree_Id */
    682                                 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
    683                                     continue;
    684                                 }
    685                                 (void) bcm_td_trill_root_name_get (unit, tree_id, &trill_mc.root_name);
    686                                 _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
    687                                                   _BCM_MULTICAST_TYPE_TRILL,  
    688                                                   soc_mem_field32_get (unit, mem, l2_entry,
    689                                                     TRILL_NONUC_NETWORK_LONG__L3MC_INDEXf));
    690                                 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry,
    691                                                   TRILL_NONUC_NETWORK_LONG__VLAN_IDf);
    692                                 soc_mem_mac_addr_get(unit, mem, l2_entry,
    693                                                    TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, trill_mc.c_dmac);
    694                                 break;
    695 
    696             }
    697             trill_mc.flags = BCM_TRILL_MULTICAST_STATIC;
    698             rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data);
    699             if (BCM_FAILURE(rv)) {
    700                 break;
    701             }
    702         }
    703         if (BCM_FAILURE(rv)) {
    704             break;
    705         }
    706     }
    707     soc_cm_sfree(unit, l2_trill_tbl_chnk);
    708     return rv;        
    709 }
    710 
    711 /*
    712  * Description:
    713  *      Traverse  TRILL Access to Network Multicast entries
    714  * Parameters:
    715  *     unit             - device number
    716  *     trav_st        - Traverse structure with all the data.
    717  * Return:
    718  *     BCM_E_XXX
    719  */
    720 int
    721 bcm_td2_trill_l2_access_multicast_entry_traverse (int unit, _bcm_td_trill_multicast_entry_traverse_t *trav_st)
    722 {
    723    /* Indexes to iterate over memories, chunks and entries */
    724     int        chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
    725     int        buf_size, chunksize, chnk_end;
    726     /* Buffer to store chunk of L2 table we currently work on */
    727     uint32     *l2_trill_tbl_chnk;
    728     L2_ENTRY_T *l2_entry;
    729     int        rv = BCM_E_NONE;
    730     soc_mem_t  mem;
    731     int        key_type=-1;
    732     bcm_trill_multicast_entry_t  trill_mc;
    733 
    734     mem = L2Xm;
    735 
    736     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
    737 
    738     if (!soc_mem_index_count(unit, mem)) {
    739         return BCM_E_NONE;
    740     }
    741 
    742     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    743                                  L2_MEM_CHUNKS_DEFAULT);
    744 
    745     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
    746     l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill access multicast traverse");
    747     if (NULL == l2_trill_tbl_chnk) {
    748         return BCM_E_MEMORY;
    749     }
    750 
    751     mem_idx_max = soc_mem_index_max(unit, mem);
    752     for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 
    753          chnk_idx += chunksize) {
    754         sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size);
    755 
    756         chnk_idx_max = 
    757             ((chnk_idx + chunksize) < mem_idx_max) ? 
    758             (chnk_idx + chunksize - 1) : mem_idx_max;
    759 
    760         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    761                                 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk);
    762         if (SOC_FAILURE(rv)) {
    763             break;
    764         }
    765         chnk_end = (chnk_idx_max - chnk_idx);
    766         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
    767             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 
    768                                              l2_trill_tbl_chnk, ent_idx);
    769 
    770                 if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) {
    771                     continue;
    772                 }
    773                 key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf);
    774                 if (key_type != TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS) {
    775                     continue;
    776                 } else {
    777                     _BCM_MULTICAST_GROUP_SET(trill_mc.group, 
    778                                       _BCM_MULTICAST_TYPE_TRILL,  
    779                                       soc_mem_field32_get(unit, mem, l2_entry,
    780                                          L2__L3MC_PTRf));
    781                     trill_mc.c_vlan = soc_mem_field32_get(unit, mem, l2_entry,
    782                                          L2__VLAN_IDf);
    783                     soc_mem_mac_addr_get(unit, mem, l2_entry,
    784                                          L2__MAC_ADDRf, trill_mc.c_dmac);
    785                 }
    786            
    787             trill_mc.flags = BCM_TRILL_MULTICAST_ACCESS_TO_NETWORK | BCM_TRILL_MULTICAST_STATIC;
    788             rv = bcm_td_multicast_trill_rootname_get(unit, trill_mc.group, &trill_mc.root_name);
    789             if (BCM_FAILURE(rv)) {
    790                  continue;
    791             }
    792 
    793             rv = trav_st->user_cb(unit, &trill_mc, trav_st->user_data);
    794             if (BCM_FAILURE(rv)) {
    795                 break;
    796             }
    797         }
    798         if (BCM_FAILURE(rv)) {
    799             break;
    800         }
    801     }
    802     soc_cm_sfree(unit, l2_trill_tbl_chnk);
    803     return rv;        
    804 }
    805 
    806 /*
    807  * Description:
    808  *      Modify  TRILL short Multicast entries
    809  * Parameters:
    810  *     unit             - device number
    811  *     trav_st        - Traverse structure with all the data.
    812  * Return:
    813  *     BCM_E_XXX
    814  */
    815 int
    816 bcm_td2_trill_vlan_multicast_entry_modify (int unit, bcm_vlan_t vlan, int set_bit)
    817 {
    818    /* Indexes to iterate over memories, chunks and entries */
    819     int        chnk_idx, ent_idx, chnk_idx_max, mem_idx_max;
    820     int        buf_size, chunksize, chnk_end;
    821     /* Buffer to store chunk of L2 table we currently work on */
    822     uint32     *l2_trill_tbl_chnk;
    823     L2_ENTRY_T *l2_entry;
    824     int        rv = BCM_E_NONE;
    825     soc_mem_t  mem;
    826     int        key_type=-1;
    827     uint16     tree_id = 0;
    828     bcm_trill_multicast_entry_t trill_mc;
    829     int count=0;
    830 
    831     mem = L2Xm;
    832     
    833     sal_memset (&trill_mc, 0, sizeof (bcm_trill_multicast_entry_t));
    834 
    835     if (!soc_mem_index_count(unit, mem)) {
    836         return BCM_E_NONE;
    837     }
    838 
    839     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    840                                  L2_MEM_CHUNKS_DEFAULT);
    841 
    842     buf_size = 4 * SOC_MAX_MEM_FIELD_WORDS * chunksize;
    843     l2_trill_tbl_chnk = soc_cm_salloc(unit, buf_size, "trill network multicast traverse");
    844     if (NULL == l2_trill_tbl_chnk) {
    845         return BCM_E_MEMORY;
    846     }
    847 
    848     mem_idx_max = soc_mem_index_max(unit, mem);
    849     for (chnk_idx = soc_mem_index_min(unit, mem); chnk_idx <= mem_idx_max; 
    850          chnk_idx += chunksize) {
    851         sal_memset((void *)l2_trill_tbl_chnk, 0, buf_size);
    852 
    853         chnk_idx_max = 
    854             ((chnk_idx + chunksize) < mem_idx_max) ? 
    855             (chnk_idx + chunksize - 1) : mem_idx_max;
    856 
    857         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    858                                 chnk_idx, chnk_idx_max, l2_trill_tbl_chnk);
    859         if (SOC_FAILURE(rv)) {
    860             break;
    861         }
    862         chnk_end = (chnk_idx_max - chnk_idx);
    863         for (ent_idx = 0 ; ent_idx <= chnk_end; ent_idx ++) {
    864             l2_entry = soc_mem_table_idx_to_pointer(unit, mem, L2_ENTRY_T *, 
    865                                              l2_trill_tbl_chnk, ent_idx);
    866 
    867             if (!soc_mem_field32_get(unit, mem, l2_entry, VALIDf)) {
    868                 continue;
    869             }
    870 
    871             key_type = soc_mem_field32_get(unit, mem, l2_entry, KEY_TYPEf);
    872           
    873             /* Match the Key Type to TRILL */
    874             if (key_type != TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT) {
    875                continue;
    876             } else {
    877                 tree_id = soc_mem_field32_get(unit, mem, l2_entry,
    878                                  TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
    879                 /* Check for Valid Tree_Id */
    880                 if (tree_id >= BCM_MAX_NUM_TRILL_TREES ) {
    881                    continue;
    882                 }
    883                 trill_mc.c_vlan = soc_mem_field32_get (unit, mem, l2_entry,
    884                                   TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
    885                 if (vlan ==  trill_mc.c_vlan) {
    886                    if (set_bit) {
    887                        soc_mem_field32_set(unit, mem, (uint32 *)l2_entry, 
    888                              TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 0x1);
    889                    } else {
    890                        soc_mem_field32_set(unit, mem, (uint32 *)l2_entry, 
    891                              TRILL_NONUC_NETWORK_SHORT__TRILL_ACCESS_RECEIVERS_PRESENTf, 0x0);
    892                    }
    893                    count ++;
    894                 }
    895             }
    896         }
    897         if (count > 0) {
    898             rv = soc_mem_write_range(unit, SOURCE_VPm,
    899                                      MEM_BLOCK_ANY, chnk_idx,
    900                                      chnk_idx_max, l2_trill_tbl_chnk);
    901         } 
    902     }
    903     soc_cm_sfree(unit, l2_trill_tbl_chnk);
    904     return rv;        
    905 }
    906 
    907 #endif /* INCLUDE_L3 */
    908 
    909 #endif /* BCM_TRIDENT2_SUPORT */
    910