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


      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:     Firebolt L2 function implementations
      9  */
     10 
     11 #include <soc/defs.h>
     12 
     13 #ifdef BCM_FIREBOLT_SUPPORT
     14 
     15 #include <assert.h>
     16 
     17 #include <sal/core/libc.h>
     18 #include <shared/bsl.h>
     19 #include <soc/mem.h>
     20 #include <soc/debug.h>
     21 #include <soc/cm.h>
     22 #include <soc/drv.h>
     23 #include <soc/register.h>
     24 #include <soc/memory.h>
     25 #include <soc/hash.h>
     26 #include <soc/l2x.h>
     27 
     28 #include <bcm/l2.h>
     29 #include <bcm/error.h>
     30 
     31 #include <bcm_int/esw/mbcm.h>
     32 #include <bcm_int/esw/firebolt.h>
     33 #include <bcm_int/esw/stack.h>
     34 #include <bcm_int/common/multicast.h>
     35 
     36 #include <bcm_int/esw_dispatch.h>
     37 
     38 typedef struct _bcm_mac_block_info_s {
     39     bcm_pbmp_t mb_pbmp;
     40     int ref_count;
     41 } _bcm_mac_block_info_t;
     42 
     43 static _bcm_mac_block_info_t *_mbi_entries[BCM_MAX_NUM_UNITS];
     44 static int _mbi_num[BCM_MAX_NUM_UNITS];
     45 
     46 /*
     47  * Function:
     48  *      _bcm_fb_l2_from_l2x
     49  * Purpose:
     50  *      Convert a Firebolt L2X entry to a hardware-independent L2 entry
     51  * Parameters:
     52  *      unit - Unit number
     53  *      l2addr - (OUT) Hardware-independent L2 entry
     54  *      l2x_entry - Firebolt L2X entry
     55  */
     56 
     57 int
     58 _bcm_fb_l2_from_l2x(int unit, bcm_l2_addr_t *l2addr,
     59         l2x_entry_t *l2x_entry)
     60 {
     61     int mb_index, rval;
     62 
     63     sal_memset(l2addr, 0, sizeof (*l2addr));
     64 
     65     /* Valid bit is ignored here; entry is assumed valid */
     66 
     67     soc_L2_ENTRY_ONLYm_mac_addr_get(unit, l2x_entry, MAC_ADDRf, l2addr->mac);
     68 
     69     l2addr->vid = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, VLAN_IDf);
     70     l2addr->cos_dst = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, PRIf);
     71     l2addr->cos_src = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, PRIf);
     72 
     73     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, CPUf)) {
     74         l2addr->flags |= BCM_L2_COPY_TO_CPU;
     75     }
     76 
     77     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, DST_DISCARDf)) {
     78         l2addr->flags |= BCM_L2_DISCARD_DST;
     79     }
     80 
     81     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, SRC_DISCARDf)) {
     82         l2addr->flags |= BCM_L2_DISCARD_SRC;
     83     }
     84 
     85     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, SCPf)) {
     86         l2addr->flags |= BCM_L2_COS_SRC_PRI;
     87     }
     88 
     89     if (BCM_MAC_IS_MCAST(l2addr->mac)) {
     90         l2addr->flags |= BCM_L2_MCAST;
     91         l2addr->l2mc_group =
     92             soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, L2MC_PTRf);
     93 
     94         /* Translate l2mc index */
     95         BCM_IF_ERROR_RETURN(
     96             bcm_esw_switch_control_get(unit, bcmSwitchL2McIdxRetType, &rval));
     97         if (rval)  {
     98            _BCM_MULTICAST_GROUP_SET(l2addr->l2mc_group, _BCM_MULTICAST_TYPE_L2,
     99                                                                 l2addr->l2mc_group);
    100         }
    101     } else {
    102         _bcm_gport_dest_t       dest;
    103         int                     isGport, rv;
    104 
    105         _bcm_gport_dest_t_init(&dest);
    106         /* Trunk group */
    107         if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, Tf)) {
    108             int psc = 0;  /* Dummy not used */
    109             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
    110             if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
    111                 l2addr->tgid = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry,
    112                                                               TGIDf);
    113             } else if (soc_mem_field_valid(unit, L2_ENTRY_ONLYm, TGID_LOf)) {
    114                 l2addr->tgid = (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, TGID_LOf)) |
    115                                (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, TGID_HIf)
    116                             << BCM_TGID_TRUNK_LO_BITS(unit));
    117             }
    118             else {
    119                 l2addr->tgid = (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, TGIDf));
    120             }
    121             bcm_esw_trunk_psc_get(unit, l2addr->tgid, &psc);
    122             if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, REMOTE_TRUNKf)) {
    123                 l2addr->flags |= BCM_L2_REMOTE_TRUNK;
    124             }
    125             dest.tgid = l2addr->tgid;
    126             dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
    127         } else {
    128             bcm_module_t    mod_in, mod_out;
    129             bcm_port_t      port_in, port_out;
    130 
    131             if (soc_feature(unit,soc_feature_trunk_group_overlay)) {
    132                 port_in = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry,
    133                                                          PORT_NUMf);
    134             } else {
    135                 port_in = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry,
    136                                                          PORT_TGIDf);
    137             }
    138             mod_in = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, MODULE_IDf);
    139             BCM_IF_ERROR_RETURN
    140                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
    141                                         mod_in, port_in, &mod_out, &port_out));
    142             l2addr->modid = mod_out;
    143             l2addr->port = port_out;
    144 
    145             dest.port = l2addr->port;
    146             dest.modid = l2addr->modid;
    147             dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
    148         }
    149         rv = bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport);
    150 
    151         if (BCM_SUCCESS(rv) && isGport) {
    152             BCM_IF_ERROR_RETURN(
    153                 _bcm_esw_gport_construct(unit, &dest, &(l2addr->port)));
    154         }
    155     }
    156 
    157     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, L3f)) {
    158         l2addr->flags |= BCM_L2_L3LOOKUP;
    159     }
    160 
    161     if (SOC_CONTROL(unit)->l2x_group_enable) {
    162         l2addr->group = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry,
    163                                                        MAC_BLOCK_INDEXf);
    164     } else {
    165         mb_index = soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry,
    166                                                   MAC_BLOCK_INDEXf);
    167         if (mb_index) {
    168             BCM_PBMP_ASSIGN(l2addr->block_bitmap,
    169                             _mbi_entries[unit][mb_index].mb_pbmp);
    170         }
    171         l2addr->group = 0;
    172     }
    173 
    174     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, RPEf)) {
    175         l2addr->flags |= BCM_L2_SETPRI;
    176     }
    177 
    178     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, STATIC_BITf)) {
    179         l2addr->flags |= BCM_L2_STATIC;
    180     }
    181 
    182     if (soc_L2_ENTRY_ONLYm_field32_get(unit, l2x_entry, MIRRORf)) {
    183         l2addr->flags |= BCM_L2_MIRROR;
    184     }
    185 
    186     if (soc_L2Xm_field32_get(unit, l2x_entry, HITSAf)) {
    187         l2addr->flags |= BCM_L2_SRC_HIT;
    188         l2addr->flags |= BCM_L2_HIT;
    189     }
    190 
    191     if (soc_L2Xm_field32_get(unit, l2x_entry, HITDAf)) {
    192         l2addr->flags |= BCM_L2_DES_HIT;
    193         l2addr->flags |= BCM_L2_HIT;
    194     }
    195 
    196     return BCM_E_NONE;
    197 }
    198 
    199 /*
    200  * Function:
    201  *      _bcm_fb_l2_to_l2x
    202  * Purpose:
    203  *      Convert a hardware-independent L2 entry to a Firebolt L2X entry
    204  * Parameters:
    205  *      unit - Unit number
    206  *      l2x_entry - (OUT) Firebolt L2X entry
    207  *      l2addr - Hardware-independent L2 entry
    208  */
    209 
    210 int
    211 _bcm_fb_l2_to_l2x(int unit, l2x_entry_t *l2x_entry, bcm_l2_addr_t *l2addr)
    212 {
    213     VLAN_CHK_ID(unit, l2addr->vid);
    214     VLAN_CHK_PRIO(unit, l2addr->cos_dst);
    215     if (l2addr->flags & BCM_L2_PENDING) {
    216         return BCM_E_PARAM;
    217     }
    218 
    219 
    220     sal_memset(l2x_entry, 0, sizeof (*l2x_entry));
    221 
    222     soc_L2Xm_field32_set(unit, l2x_entry, VALIDf, 1);
    223     soc_L2Xm_mac_addr_set(unit, l2x_entry, MAC_ADDRf, l2addr->mac);
    224     soc_L2Xm_field32_set(unit, l2x_entry, VLAN_IDf, l2addr->vid);
    225     soc_L2Xm_field32_set(unit, l2x_entry, PRIf, l2addr->cos_dst);
    226 
    227     if (l2addr->flags & BCM_L2_COPY_TO_CPU) {
    228         soc_L2Xm_field32_set(unit, l2x_entry, CPUf, 1);
    229     }
    230 
    231     if (l2addr->flags & BCM_L2_DISCARD_DST) {
    232         soc_L2Xm_field32_set(unit, l2x_entry, DST_DISCARDf, 1);
    233     }
    234 
    235     if (l2addr->flags & BCM_L2_DISCARD_SRC) {
    236         soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 1);
    237     }
    238 
    239     if (l2addr->flags & BCM_L2_COS_SRC_PRI) {
    240         soc_L2Xm_field32_set(unit, l2x_entry, SCPf, 1);
    241     }
    242 
    243     if (l2addr->flags & BCM_L2_REMOTE_TRUNK) {
    244         soc_L2Xm_field32_set(unit, l2x_entry, REMOTE_TRUNKf, 1);
    245     }
    246 
    247     if (l2addr->flags & BCM_L2_MCAST) { /* if (BCM_MAC_IS_MCAST(l2addr->mac)) { */
    248         if (_BCM_MULTICAST_IS_SET(l2addr->l2mc_group)) {
    249             if (_BCM_MULTICAST_IS_L2(l2addr->l2mc_group)) {
    250                 soc_L2Xm_field32_set(unit, l2x_entry, L2MC_PTRf, 
    251                                      _BCM_MULTICAST_ID_GET(l2addr->l2mc_group));
    252             } else {
    253                 /* No other multicast types in L2 on these devices */
    254                 return BCM_E_PARAM;
    255             }
    256         } else {
    257             soc_L2Xm_field32_set(unit, l2x_entry, L2MC_PTRf,
    258                                  l2addr->l2mc_group);
    259         }
    260     } else {
    261         bcm_port_t      port = -1;
    262         bcm_trunk_t     tgid = BCM_TRUNK_INVALID;
    263         bcm_module_t    modid = -1;
    264 
    265         if (BCM_GPORT_IS_SET(l2addr->port)) {
    266             _bcm_l2_gport_params_t  g_params;
    267 
    268             if (BCM_GPORT_IS_BLACK_HOLE(l2addr->port)) {
    269                 soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 1);
    270             } else {
    271                 if (!(l2addr->flags & BCM_L2_DISCARD_SRC)) {
    272                     soc_L2Xm_field32_set(unit, l2x_entry, SRC_DISCARDf, 0);
    273                 }
    274                 BCM_IF_ERROR_RETURN(
    275                     _bcm_esw_l2_gport_parse(unit, l2addr, &g_params));
    276 
    277                 switch (g_params.type) {
    278                     case _SHR_GPORT_TYPE_TRUNK: 
    279                         tgid = g_params.param0;
    280                         break;
    281                     case  _SHR_GPORT_TYPE_MODPORT:
    282                         port = g_params.param0;
    283                         modid = g_params.param1;
    284                         break;
    285                     case _SHR_GPORT_TYPE_LOCAL_CPU:
    286                         port = g_params.param0;
    287                         BCM_IF_ERROR_RETURN(
    288                             bcm_esw_stk_my_modid_get(unit, &modid));
    289                         break;
    290                     default:
    291                         return BCM_E_PORT;
    292                 }
    293             }
    294         } else if (l2addr->flags & BCM_L2_TRUNK_MEMBER) {
    295             tgid = l2addr->tgid;
    296 
    297         } else {
    298             BCM_IF_ERROR_RETURN(
    299                 _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
    300                                        l2addr->modid, l2addr->port, 
    301                                        &modid, &port));
    302             /* Check parameters */
    303             if (!SOC_MODID_ADDRESSABLE(unit, modid)) {
    304                 return BCM_E_BADID;
    305             }
    306             if (!SOC_PORT_ADDRESSABLE(unit, port)) {
    307                 return BCM_E_PORT;
    308             }
    309         }
    310 
    311         /* Setting l2x_entry fields according to parameters */
    312         if ( BCM_TRUNK_INVALID != tgid) {
    313             soc_L2Xm_field32_set(unit, l2x_entry, Tf, 1);
    314             if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
    315                 soc_L2Xm_field32_set(unit, l2x_entry, TGIDf, tgid);
    316             } else if (soc_mem_field_valid(unit, L2Xm, TGID_LOf)) {
    317                 soc_L2Xm_field32_set(unit, l2x_entry, TGID_LOf,
    318                                      tgid & BCM_TGID_PORT_TRUNK_MASK(unit));
    319                 soc_L2Xm_field32_set(unit, l2x_entry, TGID_HIf,
    320                                      tgid >> BCM_TGID_TRUNK_LO_BITS(unit));
    321             }
    322             else {
    323                 soc_L2Xm_field32_set(unit, l2x_entry, TGIDf, 
    324                                      (tgid & BCM_TGID_PORT_TRUNK_MASK(unit)));
    325             }
    326             /*
    327              * Note:  RTAG is ignored here.  Use bcm_trunk_psc_set to
    328              * to set for a given trunk.
    329              */
    330         } else if (-1 != port) {
    331             soc_L2Xm_field32_set(unit, l2x_entry, MODULE_IDf, modid);
    332             if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
    333                 soc_L2Xm_field32_set(unit, l2x_entry, PORT_NUMf, port);
    334             } else {
    335                 soc_L2Xm_field32_set(unit, l2x_entry, PORT_TGIDf, port);
    336             }
    337         }
    338     }
    339     if (l2addr->flags & BCM_L2_L3LOOKUP) {
    340         soc_L2Xm_field32_set(unit, l2x_entry, L3f, 1);
    341     }
    342 
    343     if (l2addr->flags & BCM_L2_MIRROR) {
    344         soc_L2Xm_field32_set(unit, l2x_entry, MIRRORf, 1);
    345     }
    346 
    347     if (SOC_CONTROL(unit)->l2x_group_enable) {
    348         soc_L2Xm_field32_set(unit, l2x_entry, MAC_BLOCK_INDEXf, l2addr->group);
    349     } /* else MAC_BLOCK_INDEXf is handled in the add/remove functions below */
    350 
    351     if (l2addr->flags & BCM_L2_SETPRI) {
    352         soc_L2Xm_field32_set(unit, l2x_entry, RPEf, 1);
    353     }
    354 
    355     if (l2addr->flags & BCM_L2_STATIC) {
    356         soc_L2Xm_field32_set(unit, l2x_entry, STATIC_BITf, 1);
    357     }
    358 
    359     if ((l2addr->flags & BCM_L2_SRC_HIT) || 
    360         (l2addr->flags & BCM_L2_HIT)) {
    361         soc_L2Xm_field32_set(unit, l2x_entry, HITSAf, 1);
    362     }
    363 
    364     if ((l2addr->flags & BCM_L2_DES_HIT) ||
    365         (l2addr->flags & BCM_L2_HIT)){
    366         soc_L2Xm_field32_set(unit, l2x_entry, HITDAf, 1);
    367     }
    368 
    369     return BCM_E_NONE;
    370 }
    371 
    372 /*
    373  * Function:
    374  *      _bcm_mac_block_insert
    375  * Purpose:
    376  *      Find or create a MAC_BLOCK table entry matching the given bitmap.
    377  * Parameters:
    378  *      unit - Unit number
    379  *      mb_pbmp - egress port bitmap for source MAC blocking
    380  *      mb_index - (OUT) Index of MAC_BLOCK table with bitmap.
    381  * Returns:
    382  *      BCM_E_NONE              Success
    383  *      BCM_E_INTERNAL          Chip access failure
    384  *      BCM_E_RESOURCE          No more MAC_BLOCK entries available
    385  *      BCM_E_PARAM             Bad bitmap supplied
    386  */
    387 static int
    388 _bcm_mac_block_insert(int unit, bcm_pbmp_t mb_pbmp, int *mb_index)
    389 {
    390     int cur_index = 0;
    391     _bcm_mac_block_info_t *mbi = _mbi_entries[unit];
    392     mac_block_entry_t mbe;
    393     bcm_pbmp_t temp_pbmp;
    394 
    395     /* Check for reasonable pbmp */
    396     BCM_PBMP_ASSIGN(temp_pbmp, mb_pbmp);
    397     BCM_PBMP_AND(temp_pbmp, PBMP_ALL(unit));
    398     if (BCM_PBMP_NEQ(mb_pbmp, temp_pbmp)) {
    399         return BCM_E_PARAM;
    400     }
    401 
    402     for (cur_index = 0; cur_index < _mbi_num[unit]; cur_index++) {
    403         if (BCM_PBMP_EQ(mbi[cur_index].mb_pbmp, mb_pbmp)) {
    404             mbi[cur_index].ref_count++;
    405             *mb_index = cur_index;
    406             return BCM_E_NONE;
    407         }
    408     }
    409 
    410     /* Not in table already, see if any space free */
    411     for (cur_index = 1; cur_index < _mbi_num[unit]; cur_index++) {
    412         if (mbi[cur_index].ref_count == 0) {
    413             /* Attempt insert */
    414             sal_memset(&mbe, 0, sizeof(mac_block_entry_t));
    415             soc_mem_pbmp_field_set(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf,
    416                                    &mb_pbmp);
    417             SOC_IF_ERROR_RETURN(WRITE_MAC_BLOCKm(unit, MEM_BLOCK_ALL,
    418                                                  cur_index, &mbe));
    419             mbi[cur_index].ref_count++;
    420             BCM_PBMP_ASSIGN(mbi[cur_index].mb_pbmp, mb_pbmp);
    421             *mb_index = cur_index;
    422             return BCM_E_NONE;
    423         }
    424     }
    425 
    426     /* Didn't find a free slot, out of table space */
    427     return BCM_E_RESOURCE;
    428 }
    429 
    430 /*
    431  * Function:
    432  *      _bcm_mac_block_delete
    433  * Purpose:
    434  *      Remove reference to MAC_BLOCK table entry matching the given bitmap.
    435  * Parameters:
    436  *      unit - Unit number
    437  *      mb_index - Index of MAC_BLOCK table with bitmap.
    438  */
    439 static void
    440 _bcm_mac_block_delete(int unit, int mb_index)
    441 {
    442     if (_mbi_entries[unit][mb_index].ref_count > 0) {
    443         _mbi_entries[unit][mb_index].ref_count--;
    444     } else if (mb_index) {
    445         
    446         /* Someone reran init without flushing the L2 table */
    447     } /* else mb_index = 0, as expected for learning */
    448 }
    449 
    450 /*
    451  * Function:
    452  *      bcm_fb_l2_addr_add
    453  * Description:
    454  *      Add a MAC address to the Switch Address Resolution Logic (ARL)
    455  *      port with the given VLAN ID and parameters.
    456  * Parameters:
    457  *      unit - StrataSwitch PCI device unit number (driver internal).
    458  *      l2addr - Pointer to bcm_l2_addr_t containing all valid fields
    459  * Returns:
    460  *      BCM_E_NONE              Success
    461  *      BCM_E_INTERNAL          Chip access failure
    462  *      BCM_E_RESOURCE          No MAC_BLOCK entries available
    463  * Notes:
    464  *      Use CMIC_PORT(unit) to associate the entry with the CPU.
    465  *      Use flag of BCM_L2_COPY_TO_CPU to send a copy to the CPU.
    466  *      Use flag of BCM_L2_TRUNK_MEMBER to set trunking (TGID must be
    467  *      passed as well with non-zero trunk group ID)
    468  *      In case the L2X table is full (e.g. bucket full), an attempt
    469  *      will be made to store the entry in the L2_USER_ENTRY table.
    470  */
    471 
    472 int
    473 bcm_fb_l2_addr_add(int unit, bcm_l2_addr_t *l2addr)
    474 {
    475     l2x_entry_t  l2x_entry, l2ent;
    476     int          rv, hash_select, bucket, slot;
    477 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
    478     int          hash_select2, bucket2 = -1;
    479 #endif
    480     l2x_entry_t  l2x_lookup;
    481     int          l2_index, mb_index = 0;
    482     uint8        key[XGS_HASH_KEY_SIZE];
    483     uint32       hash_control;
    484     int          cf_hit, cf_unhit;
    485     bcm_mac_t    mac;
    486 
    487 
    488 	if (l2addr->flags & BCM_L2_TRUNK_MEMBER)
    489 	{
    490 	    BCM_IF_ERROR_RETURN(
    491 	        _bcm_trunk_id_validate(unit, l2addr->tgid));
    492 	}
    493 
    494     BCM_IF_ERROR_RETURN(
    495         _bcm_fb_l2_to_l2x(unit, &l2x_entry, l2addr));
    496 
    497     rv = soc_fb_l2x_lookup(unit, &l2x_entry, &l2x_lookup, &l2_index);
    498     if (rv < 0) {
    499          if (rv != BCM_E_NOT_FOUND) {
    500              return rv;
    501          }
    502     } 
    503 
    504     if (SOC_CONTROL(unit)->l2x_group_enable) {
    505         /* Using MAC_BLOCK_INDEX field for storing the L2 group */
    506         soc_L2Xm_field32_set(unit, &l2x_entry, MAC_BLOCK_INDEXf, 
    507                              l2addr->group);
    508     } else {
    509         if (rv == BCM_E_NONE) {
    510             /* Only here if L2 entry was found */
    511             mb_index = soc_L2Xm_field32_get(unit, &l2x_lookup, MAC_BLOCK_INDEXf);
    512             _bcm_mac_block_delete(unit, mb_index);
    513         }
    514         /* Mac blocking, attempt to associate with bitmap entry */
    515         BCM_IF_ERROR_RETURN(
    516             _bcm_mac_block_insert(unit, l2addr->block_bitmap, &mb_index));
    517 
    518         soc_L2Xm_field32_set(unit, &l2x_entry, MAC_BLOCK_INDEXf, mb_index);
    519     }
    520 
    521     rv = soc_fb_l2x_insert(unit, &l2x_entry);
    522     if ((rv == BCM_E_FULL) && (l2addr->flags & BCM_L2_REPLACE_DYNAMIC)) {
    523         rv = READ_HASH_CONTROLr(unit, &hash_control); 
    524         if (rv < 0 ) {
    525             goto done;
    526         }
    527         hash_select = soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
    528                                      L2_AND_VLAN_MAC_HASH_SELECTf);
    529 
    530         soc_draco_l2x_param_to_key(l2addr->mac, l2addr->vid, key);
    531         bucket = soc_fb_l2_hash(unit, hash_select, key);
    532 
    533 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
    534         if (soc_feature(unit, soc_feature_dual_hash)) {
    535             rv = READ_L2_AUX_HASH_CONTROLr(unit, &hash_control);
    536             if (rv < 0 ) {
    537                 goto done;
    538             }
    539             if (soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr,
    540                                   hash_control, ENABLEf)) {
    541                 hash_select2 = soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr,
    542                                                  hash_control, HASH_SELECTf);
    543             } else {
    544                 hash_select2 = hash_select;
    545             }
    546             bucket2 = soc_fb_l2_hash(unit, hash_select2, key);
    547         }
    548 #endif
    549 
    550         rv = soc_l2x_freeze(unit);
    551         if (rv < 0) {
    552             goto done;
    553         }
    554 
    555         cf_hit = cf_unhit = -1;
    556         for (slot = 0; slot < SOC_L2X_BUCKET_SIZE; slot++) {
    557 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
    558             if ((bucket2 >=0) && (slot == (SOC_L2X_BUCKET_SIZE/2))) {
    559                 bucket = bucket2;
    560             }
    561 #endif
    562             l2_index = bucket * SOC_L2X_BUCKET_SIZE + slot;
    563             rv = soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY, l2_index, &l2ent);
    564             if ((rv < 0)) {
    565                 (void) soc_l2x_thaw(unit);
    566                 goto done;
    567             }
    568 
    569             if (!soc_L2Xm_field32_get(unit, &l2ent, VALIDf)) {
    570                 /* Found invalid entry - stop the search victim found */
    571                 cf_unhit = l2_index; 
    572                 break;
    573             } else {
    574 
    575                  soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, mac);
    576                 /* Skip static entries */
    577                 if ((soc_L2Xm_field32_get(unit, &l2ent, STATIC_BITf)) ||
    578                     (BCM_MAC_IS_MCAST(mac)) ||
    579                     (soc_L2Xm_field32_get(unit, &l2ent, L3f))) {
    580                     continue;
    581                 }
    582                 if (soc_L2Xm_field32_get(unit, &l2ent, HITDAf) || 
    583                     soc_L2Xm_field32_get(unit, &l2ent, HITSAf) ) {
    584                     cf_hit =  l2_index;
    585                 } else {
    586                     /* Found unhit entry - stop search victim found */
    587                     cf_unhit = l2_index;
    588                     break;
    589                 }
    590             }
    591         }
    592 
    593         if (cf_unhit >= 0) {
    594             l2_index = cf_unhit;   /* take last unhit dynamic */
    595         } else if (cf_hit >= 0) {
    596             l2_index = cf_hit;     /* or last hit dynamic */
    597         } else {
    598           rv = BCM_E_FULL;     /* no dynamics to delete */
    599           (void) soc_l2x_thaw(unit);
    600           goto done;
    601         }
    602 
    603         soc_mem_write(unit, L2Xm, MEM_BLOCK_ALL, l2_index, &l2x_entry);
    604         rv = soc_l2x_thaw(unit);
    605     }
    606 
    607 done:
    608     if (rv < 0) {
    609         _bcm_mac_block_delete(unit, mb_index);
    610     }
    611 
    612     return rv;
    613 }
    614 
    615 /*
    616  * Function:
    617  *      bcm_fb_l2_addr_delete
    618  * Description:
    619  *      Delete an L2 address (MAC+VLAN) from the device
    620  * Parameters:
    621  *      unit - device unit
    622  *      mac  - MAC address to delete
    623  *      vid  - VLAN id
    624  * Returns:
    625  *      BCM_E_XXX
    626  */
    627 int
    628 bcm_fb_l2_addr_delete(int unit, bcm_mac_t mac, bcm_vlan_t vid)
    629 {
    630     bcm_l2_addr_t  l2addr;
    631     l2x_entry_t    l2x_entry, l2x_lookup;
    632     int            l2_index, mb_index;
    633     int            rv;
    634     soc_control_t   *soc = SOC_CONTROL(unit);
    635 
    636     bcm_l2_addr_t_init(&l2addr, mac, vid);
    637 
    638     BCM_IF_ERROR_RETURN(
    639         _bcm_fb_l2_to_l2x(unit, &l2x_entry, &l2addr));
    640 
    641     soc_mem_lock(unit, L2Xm);
    642     rv = soc_fb_l2x_lookup(unit, &l2x_entry, &l2x_lookup, &l2_index);
    643     if (BCM_E_NONE != rv) {
    644         soc_mem_unlock(unit, L2Xm);
    645         return rv;
    646     }
    647 
    648     if (!SOC_CONTROL(unit)->l2x_group_enable) {
    649         mb_index = soc_L2Xm_field32_get(unit, &l2x_lookup, MAC_BLOCK_INDEXf);
    650         _bcm_mac_block_delete(unit, mb_index);
    651     }
    652 
    653     if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
    654         soc_mem_unlock(unit, L2Xm);
    655         return BCM_E_RESOURCE;
    656     }
    657     if ((rv = soc_fb_l2x_delete(unit, &l2x_entry)) >= 0) {
    658         rv = soc_l2x_sync_delete(unit, (uint32 *) &l2x_lookup, l2_index, 0);
    659     }
    660     SOC_L2_DEL_SYNC_UNLOCK(soc);
    661     soc_mem_unlock(unit, L2Xm);
    662 
    663     return rv;
    664 }
    665 
    666 /*
    667  * Function:
    668  *      bcm_fb_l2_addr_get
    669  * Description:
    670  *      Given a MAC address and VLAN ID, check if the entry is present
    671  *      in the L2 table, and if so, return all associated information.
    672  * Parameters:
    673  *      unit - Device unit number
    674  *      mac - input MAC address to search
    675  *      vid - input VLAN ID to search
    676  *      l2addr - Pointer to bcm_l2_addr_t structure to receive results
    677  * Returns:
    678  *      BCM_E_NONE              Success (l2addr filled in)
    679  *      BCM_E_PARAM             Illegal parameter (NULL pointer)
    680  *      BCM_E_INTERNAL          Chip access failure
    681  *      BCM_E_NOT_FOUND Address not found (l2addr not filled in)
    682  */
    683 
    684 int
    685 bcm_fb_l2_addr_get(int unit, sal_mac_addr_t mac, bcm_vlan_t vid,
    686                       bcm_l2_addr_t *l2addr)
    687 {
    688     l2x_entry_t l2fb_search, l2fb_entry;
    689     int         index, rv;
    690 
    691     VLAN_CHK_ID(unit, vid);
    692 
    693     /* Set up entry for query */
    694     sal_memset(&l2fb_search, 0, sizeof(l2fb_search));
    695     sal_memset(&l2fb_entry, 0, sizeof(l2fb_entry));
    696     soc_L2Xm_mac_addr_set(unit, &l2fb_search, MAC_ADDRf, mac);
    697     soc_L2Xm_field32_set(unit, &l2fb_search, VLAN_IDf, vid);
    698 
    699     rv = soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, &index,
    700                         &l2fb_search, &l2fb_entry, 0);
    701 
    702     if (rv == SOC_E_NONE) {
    703         BCM_IF_ERROR_RETURN(_bcm_fb_l2_from_l2x(unit, l2addr, &l2fb_entry));
    704         return BCM_E_NONE;
    705     }
    706 
    707     return rv;
    708 }
    709 
    710 /*
    711  * Function:
    712  *      _bcm_fb_l2_reload_mbi
    713  * Description:
    714  *      Load MAC block info from hardware into software data structures.
    715  * Parameters:
    716  *      unit - StrataSwitch unit number.
    717  */
    718 
    719 STATIC int
    720 _bcm_fb_l2_reload_mbi(int unit)
    721 {
    722 #ifdef BCM_WARM_BOOT_SUPPORT
    723     _bcm_mac_block_info_t *mbi = _mbi_entries[unit];
    724     l2x_entry_t         *l2x_entry, *l2x_table;
    725     mac_block_entry_t   mbe;
    726     int                 index, mb_index, l2x_size;
    727 
    728     /*
    729      * Refresh MAC Block information from the hardware tables.
    730      */
    731 
    732     for (mb_index = 0; mb_index < _mbi_num[unit]; mb_index++) {
    733         SOC_IF_ERROR_RETURN
    734             (READ_MAC_BLOCKm(unit, MEM_BLOCK_ANY, mb_index, &mbe));
    735         soc_mem_pbmp_field_get(unit, MAC_BLOCKm, &mbe, MAC_BLOCK_MASKf,
    736                                &mbi[mb_index].mb_pbmp);
    737     }
    738 
    739     if (!SOC_CONTROL(unit)->l2x_group_enable) {
    740         l2x_size = sizeof(l2x_entry_t) * soc_mem_index_count(unit, L2Xm);
    741         l2x_table = soc_cm_salloc(unit, l2x_size, "l2 reload");
    742         if (l2x_table == NULL) {
    743             return BCM_E_MEMORY;
    744         }
    745 
    746         memset((void *)l2x_table, 0, l2x_size);
    747         if (soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY,
    748                                soc_mem_index_min(unit, L2Xm),
    749                                soc_mem_index_max(unit, L2Xm),
    750                                l2x_table) < 0) {
    751             soc_cm_sfree(unit, l2x_table);
    752             return SOC_E_INTERNAL;
    753         }
    754 
    755         for (index = soc_mem_index_min(unit, L2Xm);
    756              index <= soc_mem_index_max(unit, L2Xm); index++) {
    757 
    758              l2x_entry = soc_mem_table_idx_to_pointer(unit, L2Xm,
    759                                                       l2x_entry_t *,
    760                                                       l2x_table, index);
    761              if (!soc_L2Xm_field32_get(unit, l2x_entry, VALIDf)) {
    762                  continue;
    763              }
    764   
    765              mb_index = soc_L2Xm_field32_get(unit, l2x_entry, MAC_BLOCK_INDEXf);
    766              mbi[mb_index].ref_count++;
    767         }
    768         soc_cm_sfree(unit, l2x_table);
    769     } /* Else, MAC Block table is used for L2 group instead, so no reload */
    770 
    771     return BCM_E_NONE;
    772 #else
    773     return BCM_E_UNAVAIL;
    774 #endif /* BCM_WARM_BOOT_SUPPORT */
    775 }
    776 
    777 /*
    778  * Function:
    779  *      bcm_fb_l2_init
    780  * Description:
    781  *      Initialize chip-dependent parts of L2 module
    782  * Parameters:
    783  *      unit - StrataSwitch unit number.
    784  */
    785 
    786 int
    787 bcm_fb_l2_init(int unit)
    788 {
    789     int         was_running = FALSE;
    790     uint32      flags;
    791     sal_usecs_t interval;
    792 
    793     if (soc_l2x_running(unit, &flags, &interval)) { 	 
    794         was_running = TRUE; 	 
    795         BCM_IF_ERROR_RETURN(soc_l2x_stop(unit)); 	 
    796     }
    797 
    798     if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) {
    799         if (!SAL_BOOT_SIMULATION || SAL_BOOT_BCMSIM) {
    800             soc_fb_l2x_delete_all(unit);
    801         }
    802     }
    803 
    804     if (_mbi_entries[unit] != NULL) {
    805         sal_free(_mbi_entries[unit]);
    806         _mbi_entries[unit] = NULL;
    807     }
    808 
    809     _mbi_num[unit] = (SOC_MEM_INFO(unit, MAC_BLOCKm).index_max -
    810                       SOC_MEM_INFO(unit, MAC_BLOCKm).index_min + 1);
    811     _mbi_entries[unit] = sal_alloc(_mbi_num[unit] *
    812                                    sizeof(_bcm_mac_block_info_t),
    813                                    "BCM L2X MAC blocking info");
    814     if (!_mbi_entries[unit]) {
    815         return BCM_E_MEMORY;
    816     }
    817 
    818     sal_memset(_mbi_entries[unit], 0,
    819                _mbi_num[unit] * sizeof(_bcm_mac_block_info_t));
    820 
    821     if (SOC_WARM_BOOT(unit)) {
    822         BCM_IF_ERROR_RETURN(_bcm_fb_l2_reload_mbi(unit));
    823     }
    824 
    825     /* bcm_l2_register clients */
    826     
    827     soc_l2x_register(unit,
    828             _bcm_l2_register_callback,
    829             NULL);
    830 
    831     if (was_running || SAL_BOOT_BCMSIM) {
    832         interval = (SAL_BOOT_BCMSIM)? BCMSIM_L2XMSG_INTERVAL : interval;
    833         soc_l2x_start(unit, flags, interval);
    834     }
    835 
    836     return BCM_E_NONE;
    837 }
    838 
    839 /*
    840  * Function:
    841  *      bcm_fb_l2_term
    842  * Description:
    843  *      Finalize chip-dependent parts of L2 module
    844  * Parameters:
    845  *      unit - StrataSwitch unit number.
    846  */
    847 
    848 int
    849 bcm_fb_l2_term(int unit)
    850 {
    851     if (_mbi_entries[unit] != NULL) {
    852         sal_free(_mbi_entries[unit]);
    853         _mbi_entries[unit] = NULL;
    854     }
    855 
    856     return BCM_E_NONE;
    857 }
    858 
    859 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
    860 int
    861 _bcm_dual_l2_conflict_get(int unit, bcm_l2_addr_t *addr,
    862                           bcm_l2_addr_t *cf_array, int cf_max,
    863                           int *cf_count)
    864 {
    865     l2x_entry_t         l2ent;
    866     uint8               key[XGS_HASH_KEY_SIZE];
    867     int                 hash_select, bucket, bucket_chunk, slot, bank;
    868 
    869     *cf_count = 0;
    870 
    871     for (bank = 0; bank < 2; bank++) {
    872         /* Get L2 hash select */
    873         SOC_IF_ERROR_RETURN
    874             (soc_fb_l2x_entry_bank_hash_sel_get(unit, bank, &hash_select));
    875         soc_draco_l2x_param_to_key(addr->mac, addr->vid, key);
    876         bucket = soc_fb_l2_hash(unit, hash_select, key);
    877 
    878         bucket_chunk = SOC_L2X_BUCKET_SIZE / 2;
    879 
    880         for (slot = bucket_chunk * bank;
    881              (slot < (bucket_chunk * (bank + 1))) && (*cf_count < cf_max);
    882              slot++) {
    883             SOC_IF_ERROR_RETURN
    884                 (soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY,
    885                               bucket * SOC_L2X_BUCKET_SIZE + slot,
    886                               &l2ent));
    887             if (soc_L2Xm_field32_get(unit, &l2ent, VALIDf)) {
    888                 BCM_IF_ERROR_RETURN
    889                     (_bcm_fb_l2_from_l2x(unit, &cf_array[*cf_count], &l2ent));
    890                 *cf_count += 1;
    891             }
    892         }
    893     }
    894 
    895     return BCM_E_NONE;
    896 }
    897 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
    898 
    899 int
    900 bcm_fb_l2_conflict_get(int unit, bcm_l2_addr_t *addr,
    901                           bcm_l2_addr_t *cf_array, int cf_max,
    902                           int *cf_count)
    903 {
    904     l2x_entry_t         l2ent;
    905     uint8               key[XGS_HASH_KEY_SIZE];
    906     int                 hash_select, bucket, slot;
    907     uint32              hash_control;
    908 
    909 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
    910     if (soc_feature(unit, soc_feature_dual_hash)) {
    911         return _bcm_dual_l2_conflict_get(unit, addr, cf_array,
    912                                          cf_max, cf_count);
    913     }
    914 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
    915 
    916     *cf_count = 0;
    917 
    918     /* Get L2 hash select */
    919     SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &hash_control));
    920     hash_select = soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
    921                                  L2_AND_VLAN_MAC_HASH_SELECTf);
    922     soc_draco_l2x_param_to_key(addr->mac, addr->vid, key);
    923     bucket = soc_fb_l2_hash(unit, hash_select, key);
    924 
    925     for (slot = 0;
    926          slot < SOC_L2X_BUCKET_SIZE && *cf_count < cf_max;
    927          slot++) {
    928         SOC_IF_ERROR_RETURN
    929             (soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY,
    930                           bucket * SOC_L2X_BUCKET_SIZE + slot,
    931                           &l2ent));
    932         if (soc_L2Xm_field32_get(unit, &l2ent, VALIDf)) {
    933             BCM_IF_ERROR_RETURN
    934                 (_bcm_fb_l2_from_l2x(unit, &cf_array[*cf_count], &l2ent));
    935             *cf_count += 1;
    936         }
    937     }
    938 
    939     return BCM_E_NONE;
    940 }
    941 
    942 /*
    943  * Function:
    944  *     _bcm_fb_age_reg_config
    945  * Description:
    946  *     Helper function to _bcm_fb_l2_addr_replace_by_XXX functions to 
    947  *     configure PER_PORT_AGE_CONTROL register for Firebolt
    948  * Parameters:
    949  *     unit         device number
    950  *     flags        flags BCM_L2_REPLACE_* 
    951  *     rep_st       structure with information of what to replace 
    952  * Return:
    953  *     BCM_E_XXX
    954  */
    955 STATIC int 
    956 _bcm_fb_age_reg_config(int unit, uint32 flags, _bcm_l2_replace_t *rep_st)
    957 {
    958     uint32          age_val = 0, op, match_mod, match_port;
    959     uint32          sync_op, soc_flags;
    960     soc_control_t   *soc = SOC_CONTROL(unit);
    961     int             rv;
    962 
    963     BCM_IF_ERROR_RETURN(
    964         _bcm_get_op_from_flags(flags, &op, &sync_op));
    965 
    966     if (rep_st->match_dest.trunk != -1) {
    967         match_mod = BCM_TRUNK_TO_MODIDf(unit, rep_st->match_dest.trunk);
    968         match_port = BCM_TRUNK_TO_TGIDf(unit, rep_st->match_dest.trunk);
    969         if (sync_op == SOC_L2X_PORTMOD_DEL) {
    970             sync_op = SOC_L2X_TRUNK_DEL;
    971         }
    972     } else {
    973         match_mod = rep_st->match_dest.module;
    974         match_port = rep_st->match_dest.port;
    975     }
    976 
    977     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &age_val,
    978                       EXCL_STATICf,
    979                       (flags & BCM_L2_REPLACE_MATCH_STATIC) ? 0 : 1);
    980     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &age_val, 
    981                           PPA_MODEf, op);
    982     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &age_val, 
    983                       VLAN_IDf, rep_st->key_vlan);
    984     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &age_val,
    985                       MODULE_IDf, match_mod);
    986     soc_reg_field_set(unit, PER_PORT_AGE_CONTROLr, &age_val,
    987                       TGID_PORTf, match_port);
    988     BCM_IF_ERROR_RETURN(WRITE_PER_PORT_AGE_CONTROLr(unit, age_val));
    989 
    990     /* OK not to lock L2Xm before since it is locked by upper layer */
    991     if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
    992         return BCM_E_RESOURCE;
    993     }
    994     rv = soc_l2x_port_age(unit, PER_PORT_AGE_CONTROLr, INVALIDr);
    995     if (BCM_FAILURE(rv)) {
    996         SOC_L2_DEL_SYNC_UNLOCK(soc);
    997         return rv;
    998     }
    999     if ((flags & BCM_L2_REPLACE_DELETE)) {
   1000         soc_flags = (flags & BCM_L2_REPLACE_MATCH_STATIC) ? SOC_L2X_INC_STATIC : 0;
   1001         if (flags & BCM_L2_REPLACE_NO_CALLBACKS) {
   1002             soc_flags |= SOC_L2X_NO_CALLBACKS;
   1003         }
   1004         rv = _soc_l2x_sync_delete_by(unit, rep_st->match_dest.module,
   1005                                      rep_st->match_dest.port,
   1006                                      rep_st->key_vlan,
   1007                                      rep_st->match_dest.trunk, 0,
   1008                                      soc_flags, sync_op);
   1009     }
   1010     SOC_L2_DEL_SYNC_UNLOCK(soc);
   1011     return rv;
   1012 }
   1013 
   1014 /*
   1015  * Function:
   1016  *     _bcm_fb_repl_reg_config
   1017  * Description:
   1018  *     Helper function to _bcm_fb_l2_addr_replace_by_XXX functions to 
   1019  *     configure PER_PORT_REPL_CONTROL register for Firebolt
   1020  * Parameters:
   1021  *     unit         device number
   1022  *     flags        flags BCM_L2_REPLACE_* 
   1023  *     rep_st       structure with information of what to replace 
   1024  * Return:
   1025  *     BCM_E_XXX
   1026  */
   1027 STATIC int 
   1028 _bcm_fb_repl_reg_config(int unit, _bcm_l2_replace_t *rep_st)
   1029 {
   1030     uint32 repl_val = 0, mod_val, port_val;
   1031 
   1032     if (rep_st->new_dest.trunk != -1) {
   1033         mod_val = BCM_TRUNK_TO_MODIDf(unit, rep_st->new_dest.trunk);
   1034         port_val = BCM_TRUNK_TO_TGIDf(unit, rep_st->new_dest.trunk);
   1035     } else {
   1036         mod_val = rep_st->new_dest.module;
   1037         port_val = rep_st->new_dest.port;
   1038     }
   1039     soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &repl_val,
   1040                       MODULE_IDf, mod_val);
   1041     soc_reg_field_set(unit, PER_PORT_REPL_CONTROLr, &repl_val,
   1042                       PORT_TGIDf, port_val);
   1043     SOC_IF_ERROR_RETURN(WRITE_PER_PORT_REPL_CONTROLr(unit, repl_val));
   1044 
   1045     return BCM_E_NONE;
   1046 }
   1047 
   1048 /*
   1049  * Function:
   1050  *     _bcm_fb_l2_addr_replace_by_vlan
   1051  * Description:
   1052  *     Helper function to _bcm_l2_addr_replace_by_vlan API to replace l2 entries 
   1053  *      by vlan for Firebolt family 
   1054  * Parameters:
   1055  *     unit         device number
   1056  *     flags        flags BCM_L2_REPLACE_* 
   1057  *     rep_st       structure with information of what to replace
   1058  * Return:
   1059  *     BCM_E_XXX
   1060  */
   1061 int 
   1062 _bcm_fb_l2_addr_replace_by_vlan_dest(int unit, uint32 flags, _bcm_l2_replace_t *rep_st)
   1063 {
   1064 
   1065     if (NULL == rep_st) {
   1066         return BCM_E_PARAM;
   1067     }
   1068     if (flags & BCM_L2_REPLACE_MATCH_VLAN) {
   1069         VLAN_CHK_ID(unit, rep_st->key_vlan);
   1070     }
   1071   
   1072     if (0 == (flags & BCM_L2_REPLACE_DELETE)) {
   1073         BCM_IF_ERROR_RETURN(
   1074             _bcm_fb_repl_reg_config(unit, rep_st));
   1075     }
   1076     BCM_IF_ERROR_RETURN(
   1077         _bcm_fb_age_reg_config(unit, flags, rep_st));
   1078 
   1079     return BCM_E_NONE;
   1080 }
   1081 
   1082 #ifndef BCM_SW_STATE_DUMP_DISABLE
   1083 /*
   1084  * Function:
   1085  *     _bcm_fb_l2_sw_dump
   1086  * Purpose:
   1087  *     Displays L2 information maintained by software.
   1088  * Parameters:
   1089  *     unit - Device unit number
   1090  * Returns:
   1091  *     None
   1092  */
   1093 void
   1094 _bcm_fb_l2_sw_dump(int unit)
   1095 {
   1096     _bcm_mac_block_info_t *mbi;
   1097      char                 pfmt[SOC_PBMP_FMT_LEN];
   1098      int                  i;
   1099 
   1100     LOG_CLI((BSL_META_U(unit,
   1101                         "\n")));
   1102     LOG_CLI((BSL_META_U(unit,
   1103                         "  FB L2 MAC Blocking Info -\n")));
   1104     LOG_CLI((BSL_META_U(unit,
   1105                         "      Number : %d\n"), _mbi_num[unit]));
   1106 
   1107     mbi = _mbi_entries[unit];
   1108     LOG_CLI((BSL_META_U(unit,
   1109                         "      Entries (index: pbmp-count) :\n")));
   1110     if (mbi != NULL) {
   1111         for (i = 0; i < _mbi_num[unit]; i++) {
   1112             SOC_PBMP_FMT(mbi[i].mb_pbmp, pfmt);
   1113             LOG_CLI((BSL_META_U(unit,
   1114                                 "          %5d: %s-%d\n"), i, pfmt, mbi[i].ref_count));
   1115         }
   1116     }
   1117 
   1118     LOG_CLI((BSL_META_U(unit,
   1119                         "\n")));
   1120 
   1121     return;
   1122 }
   1123 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   1124 
   1125 #endif  /* BCM_FIREBOLT_SUPPORT */
   1126