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

l2.c (36355B)


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