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

extender.c (236626B)


      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:    extender.c
      8  * Purpose: Implements Port Extension APIs for Triumph3.
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 
     14 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
     15 
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/hash.h>
     19 #include <soc/l2x.h>
     20 #if defined(BCM_TRIDENT3_SUPPORT)
     21 #include <soc/trident3.h>
     22 #endif
     23 #include <shared/bsl.h>
     24 #include <bcm/error.h>
     25 #include <bcm_int/esw/switch.h>
     26 
     27 #include <bcm_int/esw_dispatch.h>
     28 #include <bcm_int/api_xlate_port.h>
     29 #include <bcm_int/common/multicast.h>
     30 #include <bcm_int/esw/stack.h>
     31 #include <bcm_int/esw/virtual.h>
     32 #include <bcm_int/esw/port.h>
     33 #include <bcm_int/esw/trx.h>
     34 #include <bcm_int/esw/triumph2.h>
     35 #include <bcm_int/esw/triumph3.h>
     36 #include <bcm_int/esw/qos.h>
     37 #include <bcm_int/esw/failover.h>
     38 #include <bcm_int/esw/trident2.h>
     39 #include <bcm_int/esw/tomahawk.h>
     40 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     41 #include <bcm_int/esw/trident2plus.h>
     42 #include <bcm_int/esw/xgs5.h>
     43 #endif /* BCM_TRIDENT2PLUS_SUPPORT*/
     44 #if defined(BCM_SABER2_SUPPORT)
     45 #include <soc/saber2.h>
     46 #endif /* BCM_SABER2_SUPPORT */
     47 
     48 #define  TD_EXTENDER_PORT_HASH_BKT_SIZE          32
     49 /*
     50  * Extender EGR_L3_NEXT_HOP View
     51  */
     52 #define _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW    0x2
     53 #define _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW     0x7
     54 
     55 /*
     56  * Extender EGR_L3_NEXT_HOP VNTAG ACTIONS
     57  */
     58 enum _BCM_EXTENDEREGR_NEXT_HOP_VNTAG_ACTIONS {
     59     ETAG_NOOP            = 0,
     60     VNTAG_ADD_OR_REPLACE = 1,
     61     ETAG_ADD_OR_REPLACE  = 2,
     62     ETAG_DELETE          = 3,
     63     VNTAG_ACTIONS_COUNT
     64 };
     65 
     66 /*
     67  * Software book keeping for Port Extension information
     68  */
     69 typedef struct _bcm_tr3_extender_egress_s {
     70     uint32 flags;
     71     bcm_gport_t port;
     72     uint16 extended_port_vid;
     73     bcm_vlan_t match_vlan;
     74     bcm_extender_pcp_de_select_t pcp_de_select;
     75     int qos_map_id;
     76     uint8 pcp;
     77     uint8 de;
     78     int service_qos_map_id;
     79     uint16 service_tpid;
     80     bcm_vlan_t service_vlan;
     81     uint8 service_pri;
     82     uint8 service_cfi;
     83     int next_hop_index;
     84     bcm_if_t intf;
     85     uint32 multicast_flags;
     86     struct _bcm_tr3_extender_egress_s *next; /* Pointer to next Extender egress
     87                                                 object */
     88 } _bcm_tr3_extender_egress_t;
     89 
     90 typedef struct _bcm_tr3_extender_nh_info_s {
     91     bcm_port_t port;
     92     int nh_ref_cnt;
     93     struct _bcm_tr3_extender_nh_info_s *next;
     94 } _bcm_tr3_extender_nh_info_t;
     95 
     96 typedef struct _bcm_tr3_extender_port_info_s {
     97     uint32 flags;
     98     bcm_gport_t port;
     99     uint16 extended_port_vid;
    100     bcm_extender_pcp_de_select_t pcp_de_select;
    101     int qos_map_id;
    102     uint8 pcp;
    103     uint8 de;
    104     bcm_vlan_t match_vlan;
    105     _bcm_tr3_extender_egress_t *egress_list; /* Linked list of Extender egress
    106                                                objects */
    107     _bcm_tr3_extender_nh_info_t *mc_nh_info;
    108                                /* nh info for multicast egress objects. */
    109 } _bcm_tr3_extender_port_info_t;
    110 
    111 /* Structure to facilitate passing of SD-tag parameters */
    112 typedef struct _bcm_tr3_extender_sd_tag_s {
    113     uint32 flags;
    114     uint16 service_tpid;
    115     bcm_vlan_t service_vlan;
    116     uint8 service_pri;
    117     uint8 service_cfi;
    118     int service_qos_map_id;
    119 } _bcm_tr3_extender_sd_tag_t;
    120 
    121 typedef struct _bcm_tr3_extender_bookkeeping_s {
    122     _bcm_tr3_extender_port_info_t *port_info; /* VP state */
    123     int invalid_next_hop_index;
    124 } _bcm_tr3_extender_bookkeeping_t;
    125 
    126 static _bcm_tr3_extender_bookkeeping_t _bcm_tr3_extender_bk_info[BCM_MAX_NUM_UNITS];
    127 
    128 #define EXTENDER_INFO(unit) (&_bcm_tr3_extender_bk_info[unit])
    129 #define EXTENDER_PORT_INFO(unit, vp) (&EXTENDER_INFO(unit)->port_info[vp])
    130 #define EXTENDER_PORT_HASH_BKT(unit, vp, idx) \
    131             (&(EXTENDER_PORT_INFO(unit, vp)->egress_list[idx]))
    132 #define EXTENDER_PORT_MC_NH_INFO(unit, vp) (EXTENDER_PORT_INFO(unit, vp)->mc_nh_info)
    133 
    134 STATIC int
    135 _bcm_tr3_extender_egress_pbmp_add(int unit, int vp, bcm_pbmp_t pbmp);
    136 
    137 STATIC int
    138 _bcm_tr3_extender_egress_hash_calc(int unit, void *hash_key, uint16 *hash);
    139 
    140 /*
    141  * Function:
    142  *      _bcm_tr3_extender_port_cnt_update
    143  * Purpose:
    144  *      Update port's VP count.
    145  * Parameters:
    146  *      unit  - (IN) SOC unit number. 
    147  *      gport - (IN) GPORT ID.
    148  *      vp    - (IN) Virtual port number.
    149  *      incr  - (IN) If TRUE, increment VP count, else decrease VP count.
    150  * Returns:
    151  *      BCM_X_XXX
    152  */
    153 STATIC int
    154 _bcm_tr3_extender_port_cnt_update(int unit, bcm_gport_t gport,
    155         int vp, int incr)
    156 {
    157     int mod_out, port_out, tgid_out, id_out;
    158     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
    159     int local_member_count;
    160     int idx;
    161     int mod_local;
    162     _bcm_port_info_t *port_info;
    163     uint32 port_flags;
    164 
    165     BCM_IF_ERROR_RETURN
    166         (_bcm_esw_gport_resolve(unit, gport, &mod_out, 
    167                                 &port_out, &tgid_out, &id_out));
    168     if (-1 != id_out) {
    169         return BCM_E_PARAM;
    170     }
    171 
    172     /* Update the physical port's SW state. If associated with a trunk,
    173      * update each local physical port's SW state.
    174      */
    175 
    176     if (BCM_TRUNK_INVALID != tgid_out) {
    177 
    178         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out, 
    179                     SOC_MAX_NUM_PORTS, local_member_array, &local_member_count));
    180 
    181         for (idx = 0; idx < local_member_count; idx++) {
    182             _bcm_port_info_access(unit, local_member_array[idx], &port_info);
    183             if (incr) {
    184                 port_info->vp_count++;
    185             } else {
    186                 port_info->vp_count--;
    187             }
    188             BCM_IF_ERROR_RETURN(
    189                 bcm_esw_port_vlan_member_get(
    190                     unit, local_member_array[idx], &port_flags));
    191             BCM_IF_ERROR_RETURN(
    192                 bcm_esw_port_vlan_member_set(
    193                     unit, local_member_array[idx], port_flags));
    194         }
    195     } else {
    196         BCM_IF_ERROR_RETURN
    197             (_bcm_esw_modid_is_local(unit, mod_out, &mod_local));
    198         if (mod_local) {
    199             if (soc_feature(unit, soc_feature_sysport_remap)) { 
    200                 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 
    201             }
    202             _bcm_port_info_access(unit, port_out, &port_info);
    203             if (incr) {
    204                 port_info->vp_count++;
    205             } else {
    206                 port_info->vp_count--;
    207             }
    208             BCM_IF_ERROR_RETURN(
    209                 bcm_esw_port_vlan_member_get(
    210                     unit, port_out, &port_flags));
    211             BCM_IF_ERROR_RETURN(
    212                 bcm_esw_port_vlan_member_set(
    213                     unit, port_out, port_flags));
    214         }
    215     }
    216 
    217     return BCM_E_NONE;
    218 }
    219 
    220 #ifdef BCM_WARM_BOOT_SUPPORT
    221 
    222 #define BCM_WB_VERSION_1_0     SOC_SCACHE_VERSION(1,0)
    223 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0
    224 
    225 /*
    226  * Function:
    227  *      _bcm_tr3_extender_egress_hash_recover
    228  * Purpose:
    229  *      Recover the vp based hash table according to hardware information.
    230  * Parameters:
    231  *      unit - (IN) SOC unit Number
    232  *      vp   - (IN) Virtual port number.
    233  *      node - (IN) extender egress hardware information.
    234  * Returns:
    235  *      BCM_E_XXX
    236  */
    237 STATIC int
    238 _bcm_tr3_extender_egress_hash_recover(
    239     int unit, int vp, _bcm_tr3_extender_egress_t *node)
    240 {
    241     int bkt_idx, alloc_size;
    242     uint16 hash_val;
    243     bcm_extender_egress_t extender_egress;
    244     _bcm_tr3_extender_egress_t *temp_ptr = NULL;
    245 
    246     bcm_extender_egress_t_init(&extender_egress);
    247     extender_egress.flags                = node->flags;
    248     extender_egress.port                 = node->port;
    249     extender_egress.intf                 = node->intf;
    250     extender_egress.service_tpid         = node->service_tpid;
    251     extender_egress.service_vlan         = node->service_vlan;
    252     extender_egress.service_pri          = node->service_pri;
    253     extender_egress.service_cfi          = node->service_cfi;
    254     extender_egress.service_qos_map_id   = node->service_qos_map_id;
    255     extender_egress.extended_port_vid    = node->extended_port_vid;
    256     extender_egress.pcp                  = node->pcp;
    257     extender_egress.de                   = node->de;
    258     BCM_IF_ERROR_RETURN(
    259         _bcm_tr3_extender_egress_hash_calc(unit, (void *)&extender_egress,
    260                                           &hash_val));
    261     bkt_idx  = hash_val % TD_EXTENDER_PORT_HASH_BKT_SIZE;
    262     if ((EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL)) {
    263         alloc_size = sizeof(_bcm_tr3_extender_egress_t) *
    264                      TD_EXTENDER_PORT_HASH_BKT_SIZE;
    265         temp_ptr = sal_alloc(alloc_size, "EXTENDER egress object");
    266         if (NULL == temp_ptr) {
    267             return BCM_E_MEMORY;
    268         }
    269         sal_memset(temp_ptr, 0, alloc_size);
    270         EXTENDER_PORT_INFO(unit, vp)->egress_list = temp_ptr;
    271     }
    272     node->next = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next;
    273     EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next = node;
    274 
    275     return BCM_E_NONE;
    276 }
    277 
    278 /*
    279  * Function:
    280  *      bcm_tr3_extender_required_scache_size_get
    281  * Purpose:
    282  *      Get required Extender module scache size for Level 2 Warm Boot
    283  * Parameters:
    284  *      unit - StrataSwitch unit number.
    285  *      size - (OUT) Required scache size.
    286  * Returns:
    287  *      BCM_E_XXX
    288  */
    289 int
    290 bcm_tr3_extender_required_scache_size_get(int unit, uint32 *size)
    291 {
    292     int num_vp;
    293     int num_nh;
    294     int num_ports;
    295 
    296     *size = 0;
    297     /* Add size required to store the bitmap of Extender VPs that
    298      * were created without match criteria.
    299      */
    300     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    301     *size += SHR_BITALLOCSIZE(num_vp);
    302 
    303     /* Add size required to store the bitmap of next hops that
    304      * are associated with Extender egress objects.
    305      */
    306     num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
    307     *size += SHR_BITALLOCSIZE(num_nh);
    308 
    309     /* Add size required to store an array of physical port bitmaps.
    310      * The size of the array equals to the number of next hops.
    311      * A next hop entry may be shared by multiple Extender egress objects that
    312      * have identical attributes except for the physical port. Hence,
    313      * the physical port of each Extender egress object cannot be recovered
    314      * from hardware and needs to be stored in the next hop's physical
    315      * port bitmap.
    316      */
    317     num_ports = soc_mem_field_length(unit, L3_IPMCm, L3_BITMAPf);
    318     *size += (SHR_BITALLOCSIZE(num_ports) * num_nh);
    319 
    320     /* Add size required to store match_vlan. There can be at most
    321      * one match_vlan per Extender virtual port.
    322      */
    323     *size += (sizeof(bcm_vlan_t) * num_vp);
    324 
    325     /* Add size required to store the bitmap of next hops which
    326      * are associated with BCM_EXTENDER_EGRESS_MULTICAST.
    327      */
    328     *size += SHR_BITALLOCSIZE(num_nh);
    329 
    330     return BCM_E_NONE;
    331 }
    332 
    333 /*
    334  * Function:
    335  *      bcm_tr3_extender_sync
    336  * Purpose:
    337  *      Record persistent info into the scache.
    338  * Parameters:
    339  *      unit - StrataSwitch unit #
    340  *      scache_ptr - (IN/OUT) Scache pointer
    341  * Returns:
    342  *      BCM_E_xxx
    343  */
    344 
    345 int
    346 _bcm_tr3_extender_sync(int unit, uint8 **scache_ptr)
    347 {
    348     int rv = BCM_E_NONE;
    349     int num_vp, num_nh, num_ports;
    350     SHR_BITDCL *match_none_vp_bitmap = NULL;
    351     SHR_BITDCL *nh_bitmap = NULL;
    352     SHR_BITDCL *mc_nh_bitmap = NULL;
    353     SHR_BITDCL **pbmp_ptr_array = NULL;
    354     bcm_vlan_t *match_vlan_array = NULL;
    355     int i;
    356     _bcm_tr3_extender_egress_t *curr_ptr;
    357     int nh_index;
    358     bcm_module_t mod_out;
    359     bcm_port_t port_out;
    360     bcm_trunk_t tgid_out;
    361     int id_out;
    362     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
    363     int local_member_count;
    364     int mod_local;
    365     int bkt_idx, bkt_size;
    366     int vp_mc = 0;
    367 #if defined(BCM_SABER2_SUPPORT)
    368     uint32 source_vp_sb2_5626x = 0xFED5ABC7;
    369 #endif /* BCM_SABER2_SUPPORT */
    370 
    371     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    372     num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
    373     num_ports = soc_mem_field_length(unit, L3_IPMCm, L3_BITMAPf);
    374 
    375     /* Allocate a bitmap of Extender VPs that were created without match criteria */
    376     match_none_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp),
    377             "Bitmap of Extender VPs without match criteria");
    378     if (NULL == match_none_vp_bitmap) {
    379         rv = BCM_E_MEMORY;
    380         goto cleanup;
    381     }
    382     sal_memset(match_none_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
    383 
    384     /* Allocate a bitmap of next hops associated with Extender egress objects */
    385     nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of NHs");
    386     if (NULL == nh_bitmap) {
    387         rv = BCM_E_MEMORY;
    388         goto cleanup;
    389     }
    390     sal_memset(nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh));
    391 
    392     /* Allocate an array of pointers to port bitmaps */
    393     pbmp_ptr_array = sal_alloc(sizeof(SHR_BITDCL *) * num_nh,
    394             "Array of pointers to pbmp");
    395     if (NULL == pbmp_ptr_array) {
    396         rv = BCM_E_MEMORY;
    397         goto cleanup;
    398     }
    399     sal_memset(pbmp_ptr_array, 0, sizeof(SHR_BITDCL *) * num_nh);
    400 
    401     /* Allocate an array of match_vlan */
    402     match_vlan_array = sal_alloc(sizeof(bcm_vlan_t) * num_vp,
    403             "Array of match_vlan");
    404     if (NULL == match_vlan_array) {
    405         rv = BCM_E_MEMORY;
    406         goto cleanup;
    407     }
    408     sal_memset(match_vlan_array, 0, sizeof(bcm_vlan_t) * num_vp);
    409 
    410     /* Allocate a bitmap of next hops associated with multicast Extender egress objects */
    411     mc_nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of multicast NHs");
    412     if (NULL == mc_nh_bitmap) {
    413         rv = BCM_E_MEMORY;
    414         goto cleanup;
    415     }
    416     sal_memset(mc_nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh));
    417 
    418     /* Traverse Extender VPs */
    419     for (i = 0; i < num_vp; i++) {
    420         if (EXTENDER_PORT_INFO(unit, i)->flags & BCM_EXTENDER_PORT_MATCH_NONE) {
    421             SHR_BITSET(match_none_vp_bitmap, i);
    422             /* Traverse this Extender VP's list of Extender egress objects */
    423             vp_mc = 0;
    424             if (EXTENDER_PORT_MC_NH_INFO(unit, i) != NULL) {
    425                 /* The shared vp associates with mulicast egress objects. */
    426                 if (EXTENDER_PORT_INFO(unit, i)->egress_list == NULL) {
    427                     rv = BCM_E_INTERNAL;
    428                     goto cleanup;
    429                 }
    430                 vp_mc = 1;
    431             }
    432             bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1;
    433             for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) {
    434                 if (vp_mc) {
    435                     curr_ptr = EXTENDER_PORT_HASH_BKT(unit, i, bkt_idx)->next;
    436                 } else {
    437                     curr_ptr = EXTENDER_PORT_INFO(unit, i)->egress_list;
    438                 }
    439 
    440                 while (NULL != curr_ptr) {
    441                     if (curr_ptr->match_vlan) {
    442                         /* Match_vlan can be nonzero only for unicast Extender egress
    443                          * objects, and there can be at most one unicast Extender
    444                          * egress object in the Extender port's egress_list. These
    445                          * constraints are enforced by bcm_tr3_extender_egress_add.
    446                          */
    447                         match_vlan_array[i] = curr_ptr->match_vlan;
    448                     }
    449 
    450                     nh_index = curr_ptr->next_hop_index;
    451                     SHR_BITSET(nh_bitmap, nh_index);
    452 
    453                     if (curr_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
    454                         SHR_BITSET(mc_nh_bitmap, nh_index);
    455                     }
    456 
    457                     /* If not already done, allocate a port bitmap for this
    458                      * next hop index.
    459                      */
    460                     if (NULL == pbmp_ptr_array[nh_index]) {
    461                         pbmp_ptr_array[nh_index] =
    462                                 sal_alloc(SHR_BITALLOCSIZE(num_ports), "NH pbmp");
    463                         sal_memset(pbmp_ptr_array[nh_index], 0,
    464                                 SHR_BITALLOCSIZE(num_ports));
    465                     }
    466 
    467                     /* Set the bit in the port bitmap corresponding to the
    468                      * physical port this Extender egress object resides on.
    469                      */
    470                     rv = _bcm_esw_gport_resolve(unit, curr_ptr->port,
    471                             &mod_out, &port_out, &tgid_out, &id_out);
    472                     if (BCM_FAILURE(rv)) {
    473                         goto cleanup;
    474                     }
    475                     if (BCM_TRUNK_INVALID != tgid_out) {
    476                         rv = _bcm_esw_trunk_local_members_get(unit,
    477                                     tgid_out, SOC_MAX_NUM_PORTS, local_member_array,
    478                                     &local_member_count);
    479                         if (BCM_FAILURE(rv)) {
    480                             goto cleanup;
    481                         }
    482                         /* Only one member needs to be added for warm boot recovery
    483                          * of the trunk group ID.
    484                          */
    485                         if (local_member_count > 0) {
    486                             SHR_BITSET(pbmp_ptr_array[nh_index], local_member_array[0]);
    487                         }
    488                     } else {
    489                         rv = _bcm_esw_modid_is_local(unit, mod_out, &mod_local);
    490                         if (BCM_FAILURE(rv)) {
    491                             goto cleanup;
    492                         }
    493                         if (mod_local) {
    494                             SHR_BITSET(pbmp_ptr_array[nh_index], port_out);
    495                         } else {
    496                             rv = BCM_E_INTERNAL;
    497                             goto cleanup;
    498                         }
    499                     }
    500 
    501                     /* Advance to next egress object */
    502                     curr_ptr = curr_ptr->next;
    503                 }
    504             }
    505         } else { /* BCM_EXTENDER_PORT_MATCH_NONE is not set */
    506             if (EXTENDER_PORT_INFO(unit, i)->match_vlan) {
    507                 match_vlan_array[i] = EXTENDER_PORT_INFO(unit, i)->match_vlan;
    508             }
    509         }
    510     }
    511 
    512     /* Maximum virtual port supported on saber2 5626x devices are 4K
    513      * This fix is related to scaling down of vpn from 8K to 4K
    514      */
    515 #if defined(BCM_SABER2_SUPPORT)
    516     if (soc_sb2_5626x_devtype(unit)) {
    517         sal_memcpy(*scache_ptr, &source_vp_sb2_5626x, sizeof(source_vp_sb2_5626x));
    518         *scache_ptr += sizeof(source_vp_sb2_5626x);
    519     }
    520 #endif /* BCM_SABER2_SUPPORT */
    521 
    522     /* Store in scache the bitmap of Extender VPs that were created without
    523      * match criteria.
    524      */
    525     sal_memcpy(*scache_ptr, match_none_vp_bitmap, SHR_BITALLOCSIZE(num_vp));
    526     *scache_ptr += SHR_BITALLOCSIZE(num_vp);
    527 
    528     /* Store in scache the bitmap of next hops associated with
    529      * Extender egress objects.
    530      */
    531     sal_memcpy(*scache_ptr, nh_bitmap, SHR_BITALLOCSIZE(num_nh));
    532     *scache_ptr += SHR_BITALLOCSIZE(num_nh);
    533 
    534     /* Store in scache the physical port bitmap of the next hops
    535      * associated with Extender egress objects.
    536      */
    537     for (i = 0; i < num_nh; i++) {
    538         if (SHR_BITGET(nh_bitmap, i)) {
    539             sal_memcpy(*scache_ptr, pbmp_ptr_array[i],
    540                     SHR_BITALLOCSIZE(num_ports));
    541             *scache_ptr += SHR_BITALLOCSIZE(num_ports);
    542         }
    543     }
    544 
    545     /* Store in scache the array of match_vlan */
    546     sal_memcpy(*scache_ptr, match_vlan_array, sizeof(bcm_vlan_t) * num_vp);
    547     *scache_ptr += (sizeof(bcm_vlan_t) * num_vp);
    548 
    549     /*
    550      * Store in scache the bitmap of next hops which are associated
    551      * with BCM_EXTENDER_EGRESS_MULTICAST.
    552      */
    553     sal_memcpy(*scache_ptr, mc_nh_bitmap, SHR_BITALLOCSIZE(num_nh));
    554     *scache_ptr += SHR_BITALLOCSIZE(num_nh);
    555 
    556 cleanup:
    557     if (NULL != match_none_vp_bitmap) {
    558         sal_free(match_none_vp_bitmap);
    559     }
    560     if (NULL != nh_bitmap) {
    561         sal_free(nh_bitmap);
    562     }
    563     if (NULL != pbmp_ptr_array) {
    564         for (i = 0; i < num_nh; i++) {
    565             if (NULL != pbmp_ptr_array[i]) {
    566                 /* pbmp_ptr_array[i] is not null when nh_bitmap[bit i] is set */
    567                 sal_free(pbmp_ptr_array[i]);
    568             }
    569         }
    570         sal_free(pbmp_ptr_array);
    571     }
    572     if (NULL != match_vlan_array) {
    573         sal_free(match_vlan_array);
    574     }
    575     if (NULL != mc_nh_bitmap) {
    576         sal_free(mc_nh_bitmap);
    577     }
    578 
    579     return rv;
    580 }
    581 
    582 /*
    583  * Function:
    584  *      _bcm_tr3_extender_sd_tag_recover
    585  * Purpose:
    586  *      Recover SD-tag fields from a egress next hop entry.
    587  * Parameters:
    588  *      unit - Device Number
    589  *      egr_nh - Egress next hop entry
    590  *      sd_tag - (OUT) SD-tag fields
    591  * Returns:
    592  *      BCM_E_XXX
    593  */
    594 
    595 STATIC int
    596 _bcm_tr3_extender_sd_tag_recover(int unit, egr_l3_next_hop_entry_t *egr_nh,
    597         _bcm_tr3_extender_sd_tag_t *sd_tag)
    598 {
    599     int sd_tag_action_if_not_present;
    600     int sd_tag_add;
    601     int sd_tag_action_if_present;
    602     int sd_tag_replace_vlan;
    603     int sd_tag_replace_pri;
    604     int sd_tag_replace_tpid;
    605     int sd_tag_delete;
    606     int tpid_index;
    607     int pri_select;
    608     int mapping_ptr;
    609     int qos_map_type;
    610 
    611     sal_memset(sd_tag, 0, sizeof(_bcm_tr3_extender_sd_tag_t));
    612 
    613     /* GET SD-tag action if packet doesn't have a SD-tag */
    614     sd_tag_action_if_not_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    615             egr_nh, SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
    616     if (1 == sd_tag_action_if_not_present) {
    617         sd_tag_add = TRUE;
    618     } else {
    619         sd_tag_add = FALSE;
    620     }
    621 
    622     /* GET SD-tag action if packet already has a SD-tag */
    623     sd_tag_action_if_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    624             egr_nh, SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
    625     sd_tag_replace_vlan = FALSE;
    626     sd_tag_replace_pri = FALSE;
    627     sd_tag_replace_tpid = FALSE;
    628     sd_tag_delete = FALSE;
    629     switch (sd_tag_action_if_present) {
    630         case 1: /* REPLACE_VID_TPID */
    631             sd_tag_replace_vlan = TRUE;
    632             sd_tag_replace_tpid = TRUE;
    633             break;
    634         case 2: /* REPLACE_VID_ONLY */
    635             sd_tag_replace_vlan = TRUE;
    636             break;
    637         case 3: /* DELETE SD-TAG */
    638             sd_tag_delete = TRUE;
    639             break;
    640         case 4: /* REPLACE_VID_PRI_TPID */
    641             sd_tag_replace_vlan = TRUE;
    642             sd_tag_replace_pri = TRUE;
    643             sd_tag_replace_tpid = TRUE;
    644             break;
    645         case 5: /* REPLACE_VID_PRI_ONLY */
    646             sd_tag_replace_vlan = TRUE;
    647             sd_tag_replace_pri = TRUE;
    648             break;
    649         case 6: /* REPLACE_PRI_ONLY */
    650             sd_tag_replace_pri = TRUE;
    651             break;
    652         case 7: /* REPLACE_TPID_ONLY */
    653             sd_tag_replace_tpid = TRUE;
    654             break;
    655         default:
    656             break;
    657     }
    658 
    659     /* Recover BCM_EXTENDER_EGRESS_SERVICE_xxx flags */
    660     if (sd_tag_add) {
    661         sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_VLAN_ADD;
    662     }
    663     if (sd_tag_delete) {
    664         sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_VLAN_DELETE;
    665     }
    666     if (sd_tag_replace_vlan) {
    667         sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_VLAN_REPLACE;
    668     }
    669     if (sd_tag_replace_pri) {
    670         sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_PRI_REPLACE;
    671     }
    672     if (sd_tag_replace_tpid) {
    673         sd_tag->flags |= BCM_EXTENDER_EGRESS_SERVICE_TPID_REPLACE;
    674     }
    675 
    676     /* Recover SD-tag TPID */
    677     if (sd_tag_add || sd_tag_replace_tpid) {
    678         tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    679                 egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
    680         BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_tab_ref_count_add(unit,
    681                     tpid_index, 1));
    682         BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_get(unit,
    683                     &sd_tag->service_tpid, tpid_index));
    684     }
    685 
    686     /* Recover SD-tag VLAN ID */
    687     if (sd_tag_add || sd_tag_replace_vlan) {
    688         sd_tag->service_vlan = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    689                 egr_nh, SD_TAG__SD_TAG_VIDf);
    690     }
    691 
    692     /* Recover SD-tag Priority, CFI, and Qos Map ID */
    693     pri_select = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    694             egr_nh, SD_TAG__SD_TAG_DOT1P_PRI_SELECTf);
    695     if (pri_select) {
    696         mapping_ptr = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    697                 egr_nh, SD_TAG__SD_TAG_DOT1P_MAPPING_PTRf);
    698         qos_map_type = 2; /* _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS */
    699         BCM_IF_ERROR_RETURN(_bcm_tr2_qos_idx2id(unit, mapping_ptr,
    700                     qos_map_type, &sd_tag->service_qos_map_id));
    701     } else {
    702         sd_tag->service_pri = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    703                 egr_nh, SD_TAG__NEW_PRIf);
    704         sd_tag->service_cfi = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    705                 egr_nh, SD_TAG__NEW_CFIf);
    706     }
    707 
    708     return BCM_E_NONE;
    709 }
    710 
    711 /*
    712  * Function:
    713  *      _bcm_tr3_extender_reinit
    714  * Purpose:
    715  *      Warm boot recovery for the Extender module
    716  * Parameters:
    717  *      unit - Device Number
    718  * Returns:
    719  *      BCM_E_XXX
    720  */
    721 STATIC int 
    722 _bcm_tr3_extender_reinit(int unit)
    723 {
    724     int rv = BCM_E_NONE;
    725     int num_vp, num_nh, num_ports;
    726     SHR_BITDCL *match_none_vp_bitmap = NULL;
    727     SHR_BITDCL *extender_vp_bitmap = NULL;
    728     SHR_BITDCL *nh_bitmap = NULL;
    729     SHR_BITDCL *mc_nh_bitmap = NULL;
    730     SHR_BITDCL **pbmp_ptr_array = NULL;
    731     bcm_vlan_t *match_vlan_array = NULL;
    732     soc_scache_handle_t scache_handle;
    733     uint8 *scache_ptr;
    734     uint16 recovered_ver;
    735     int stable_size;
    736     uint32 additional_scache_size = 0;
    737     uint8 *ing_nh_buf = NULL;
    738     ing_l3_next_hop_entry_t *ing_nh_entry;
    739     uint8 *egr_nh_buf = NULL;
    740     egr_l3_next_hop_entry_t *egr_nh_entry;
    741     int i, index_min, index_max;
    742     uint32 entry_type = 0, vp = 0, trunk_bit = 0, vntag_action = 0;
    743     int lower_th, higher_th;
    744 #ifdef BCM_TRIDENT2_SUPPORT
    745     int etag_dot1p_mapping_ptr, map_id;
    746 #endif
    747     uint32 pcp_de_select_mode = 0;
    748     _bcm_tr3_extender_sd_tag_t extender_sd_tag;
    749     bcm_trunk_t tgid = 0;
    750     bcm_module_t modid = 0, mod_out = 0;
    751     bcm_port_t port_num = 0, port_out = 0;
    752     int num_valid_ports;
    753     int j;
    754     _bcm_tr3_extender_egress_t *curr_ptr = NULL;
    755     bcm_gport_t gport;
    756     uint8 *svp_buf = NULL;
    757     source_vp_entry_t *svp_entry;
    758     int tpid_enable;
    759     int  vp_mc, mc_flags;
    760     bcm_pbmp_t pbmp;
    761     _bcm_vp_info_t vp_info;
    762     int  old_num_vp = 0;
    763 #if defined(BCM_SABER2_SUPPORT)
    764     uint32 source_vp_sb2_5626x = 0;
    765 #endif /* BCM_SABER2_SUPPORT */
    766     soc_field_t    entry_type_field;
    767     uint32 dv, dt = SOC_MEM_FIF_DEST_INVALID;
    768 
    769     _bcm_vp_info_init(&vp_info);
    770     vp_info.vp_type = _bcmVpTypeExtender;
    771 
    772     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    773     num_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
    774     num_ports = soc_mem_field_length(unit, L3_IPMCm, L3_BITMAPf);
    775 
    776     /* Allocate a bitmap of Extender VPs that were created without match criteria */
    777     match_none_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp),
    778             "Bitmap of Extender VPs without match criteria");
    779     if (NULL == match_none_vp_bitmap) {
    780         rv = BCM_E_MEMORY;
    781         goto cleanup;
    782     }
    783     sal_memset(match_none_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
    784 
    785     /* Allocate a bitmap of Extender VPs */
    786     extender_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "Bitmap of Extender VPs");
    787     if (NULL == extender_vp_bitmap) {
    788         rv = BCM_E_MEMORY;
    789         goto cleanup;
    790     }
    791     sal_memset(extender_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
    792 
    793     /* Allocate a bitmap of next hops associated with Extender egress objects */
    794     nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of NHs");
    795     if (NULL == nh_bitmap) {
    796         rv = BCM_E_MEMORY;
    797         goto cleanup;
    798     }
    799     sal_memset(nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh));
    800 
    801     /* Allocate an array of pointers to port bitmaps */
    802     pbmp_ptr_array = sal_alloc(sizeof(SHR_BITDCL *) * num_nh,
    803             "Array of pointers to pbmp");
    804     if (NULL == pbmp_ptr_array) {
    805         rv = BCM_E_MEMORY;
    806         goto cleanup;
    807     }
    808     sal_memset(pbmp_ptr_array, 0, sizeof(SHR_BITDCL *) * num_nh);
    809 
    810     /* Allocate an array of match_vlan */
    811     match_vlan_array = sal_alloc(sizeof(bcm_vlan_t) * num_vp,
    812             "Array of match_vlan");
    813     if (NULL == match_vlan_array) {
    814         rv = BCM_E_MEMORY;
    815         goto cleanup;
    816     }
    817     sal_memset(match_vlan_array, 0, sizeof(bcm_vlan_t) * num_vp);
    818 
    819     /* Allocate a bitmap of next hops associated with multicast Extender egress objects */
    820     mc_nh_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_nh), "Bitmap of multicast NHs");
    821     if (NULL == mc_nh_bitmap) {
    822         rv = BCM_E_MEMORY;
    823         goto cleanup;
    824     }
    825     sal_memset(mc_nh_bitmap, 0, SHR_BITALLOCSIZE(num_nh));
    826 
    827     rv = soc_stable_size_get(unit, &stable_size);
    828     if (SOC_FAILURE(rv)) {
    829         goto cleanup;
    830     }
    831 
    832     /* Read scache */
    833     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_EXTENDER, 0);
    834     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    835             0, &scache_ptr, BCM_WB_DEFAULT_VERSION, &recovered_ver);
    836 
    837     if (BCM_E_NOT_FOUND == rv) {
    838         if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
    839             rv = BCM_E_NONE;
    840         } else {
    841             /* Get scache size required for default version */
    842             rv = bcm_tr3_extender_required_scache_size_get(unit,
    843                      &additional_scache_size);
    844             if (BCM_FAILURE(rv)) {
    845                 goto cleanup;
    846             }
    847 
    848             /* Upgrading from SDK release that does not have warmboot state */
    849             rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    850                     additional_scache_size, &scache_ptr,
    851                     BCM_WB_DEFAULT_VERSION, NULL);
    852             if (BCM_FAILURE(rv)) {
    853                 goto cleanup;
    854             }
    855         }
    856 
    857     } else if (BCM_FAILURE(rv)) {
    858         goto cleanup;
    859     } else {
    860         /* Maximum virtual port supported on saber2 5626x devices are 4K
    861          * This fix is related to scaling down of vpn from 8K to 4K
    862          */
    863 #if defined(BCM_SABER2_SUPPORT)
    864         if (soc_sb2_5626x_devtype(unit)) {
    865             sal_memcpy(&source_vp_sb2_5626x, scache_ptr,
    866                     sizeof(source_vp_sb2_5626x));
    867             if (source_vp_sb2_5626x == 0xFED5ABC7) {
    868                 scache_ptr += sizeof(source_vp_sb2_5626x);
    869             } else {
    870                 old_num_vp = 1;
    871             }
    872         }
    873 #endif /* BCM_SABER2_SUPPORT */
    874         /* Recover the bitmap of Extender VPs that were created without
    875          * match criteria.
    876          */
    877         sal_memcpy(match_none_vp_bitmap, scache_ptr, SHR_BITALLOCSIZE(num_vp));
    878         if (old_num_vp) {
    879             scache_ptr += SHR_BITALLOCSIZE(num_vp * 2);
    880         } else {
    881             scache_ptr += SHR_BITALLOCSIZE(num_vp);
    882         }
    883 
    884         /* Recover the bitmap of next hops associated with
    885          * Extender egress objects.
    886          */
    887         sal_memcpy(nh_bitmap, scache_ptr, SHR_BITALLOCSIZE(num_nh));
    888         scache_ptr += SHR_BITALLOCSIZE(num_nh);
    889 
    890         /* Recover the physical port bitmap of the next hops associated
    891          * with Extender egress objects.
    892          */
    893         for (i = 0; i < num_nh; i++) {
    894             if (SHR_BITGET(nh_bitmap, i)) {
    895                 pbmp_ptr_array[i] = sal_alloc(SHR_BITALLOCSIZE(num_ports),
    896                         "NH pbmp");
    897                 sal_memcpy(pbmp_ptr_array[i], scache_ptr,
    898                         SHR_BITALLOCSIZE(num_ports));
    899                 scache_ptr += SHR_BITALLOCSIZE(num_ports);
    900             }
    901         }
    902 
    903         sal_memcpy(match_vlan_array, scache_ptr, sizeof(bcm_vlan_t) * num_vp);
    904         if (old_num_vp) {
    905             scache_ptr += (sizeof(bcm_vlan_t) * num_vp * 2);
    906         } else {
    907             scache_ptr += (sizeof(bcm_vlan_t) * num_vp);
    908         }
    909 
    910         /* Recover the bitmap of next hops associated with
    911          * multicast Extender egress objects.
    912          */
    913         sal_memcpy(mc_nh_bitmap, scache_ptr, SHR_BITALLOCSIZE(num_nh));
    914         scache_ptr += SHR_BITALLOCSIZE(num_nh);
    915 
    916         if (additional_scache_size > 0) {
    917             rv = soc_scache_realloc(unit, scache_handle,additional_scache_size);
    918             if(BCM_FAILURE(rv)) {
    919                goto cleanup;
    920             }
    921         }
    922     }
    923 
    924      /* Recover the BCM_EXTENDER_PORT_MATCH_NONE from match_none_vp_bitmap */
    925     for (i = 0; i < num_vp; i++) {
    926         if (SHR_BITGET(match_none_vp_bitmap, i)) {
    927             EXTENDER_PORT_INFO(unit, i)->flags |= BCM_EXTENDER_PORT_MATCH_NONE;
    928         }
    929     }
    930 
    931     /* Copy match_none_vp_bitmap to extender_vp_bitmap */
    932     sal_memcpy(extender_vp_bitmap, match_none_vp_bitmap, SHR_BITALLOCSIZE(num_vp));
    933 
    934     /* Recover EXTENDER ports and EXTENDER egress objects from next hop tables */
    935     ing_nh_buf = soc_cm_salloc(unit,
    936             SOC_MEM_TABLE_BYTES(unit, ING_L3_NEXT_HOPm), "Ing Next Hop buffer");
    937     if (NULL == ing_nh_buf) {
    938         rv = BCM_E_MEMORY;
    939         goto cleanup;
    940     }
    941     index_min = soc_mem_index_min(unit, ING_L3_NEXT_HOPm);
    942     index_max = soc_mem_index_max(unit, ING_L3_NEXT_HOPm);
    943     rv = soc_mem_read_range(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
    944             index_min, index_max, ing_nh_buf);
    945     if (SOC_FAILURE(rv)) {
    946         goto cleanup;
    947     }
    948 
    949     egr_nh_buf = soc_cm_salloc(unit,
    950             SOC_MEM_TABLE_BYTES(unit, EGR_L3_NEXT_HOPm), "Egr Next Hop buffer");
    951     if (NULL == egr_nh_buf) {
    952         rv = BCM_E_MEMORY;
    953         goto cleanup;
    954     }
    955     index_min = soc_mem_index_min(unit, EGR_L3_NEXT_HOPm);
    956     index_max = soc_mem_index_max(unit, EGR_L3_NEXT_HOPm);
    957     rv = soc_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
    958             index_min, index_max, egr_nh_buf);
    959     if (SOC_FAILURE(rv)) {
    960         goto cleanup;
    961     }
    962 
    963     /* Get multicast E-VID range */
    964     rv = bcm_esw_switch_control_get(unit,
    965             bcmSwitchExtenderMulticastLowerThreshold, &lower_th);
    966     if (SOC_FAILURE(rv)) {
    967         goto cleanup;
    968     }
    969     rv = bcm_esw_switch_control_get(unit,
    970             bcmSwitchExtenderMulticastHigherThreshold, &higher_th);
    971     if (SOC_FAILURE(rv)) {
    972         goto cleanup;
    973     }
    974 
    975     /* Check entry type */
    976     if (SOC_IS_TRIDENT3X(unit)) {
    977         entry_type_field = DATA_TYPEf;
    978     } else {
    979         entry_type_field = ENTRY_TYPEf;
    980     }
    981 
    982     for (i = index_min; i <= index_max; i++) {
    983         egr_nh_entry = soc_mem_table_idx_to_pointer(unit, EGR_L3_NEXT_HOPm,
    984                 egr_l3_next_hop_entry_t *, egr_nh_buf, i);
    985 
    986         /* Check entry type */
    987         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
    988                 entry_type_field);
    989 
    990         if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) {
    991             /* Check that VN-tag action is ADD */
    992             vntag_action = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
    993                     SD_TAG__VNTAG_ACTIONSf);
    994             if ((ETAG_ADD_OR_REPLACE!= vntag_action) && (ETAG_NOOP != vntag_action)) {
    995                 continue;
    996             }
    997 
    998             /* Check pcp_de_select mode */
    999             pcp_de_select_mode = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1000                     SD_TAG__ETAG_PCP_DE_SOURCEf);
   1001             if ((BCM_EXTENDER_PCP_DE_SELECT_DEFAULT != pcp_de_select_mode)
   1002                 && (BCM_EXTENDER_PCP_DE_SELECT_PHB != pcp_de_select_mode)) {
   1003                 continue;
   1004             }
   1005 
   1006         } else if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW) {
   1007             if (!soc_feature(unit, soc_feature_virtual_port_routing)) {
   1008                 continue;
   1009             }
   1010 
   1011             /* Check that VN-tag action is ADD */
   1012             vntag_action = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1013                     L3MC__VNTAG_ACTIONSf);
   1014             if ((ETAG_ADD_OR_REPLACE != vntag_action) && (ETAG_NOOP != vntag_action)) {
   1015                 continue;
   1016             }
   1017 
   1018             /* Check pcp_de_select mode */
   1019             pcp_de_select_mode = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1020                     L3MC__ETAG_PCP_DE_SOURCEf);
   1021             if ((BCM_EXTENDER_PCP_DE_SELECT_DEFAULT != pcp_de_select_mode)
   1022                 && (BCM_EXTENDER_PCP_DE_SELECT_PHB != pcp_de_select_mode)) {
   1023                 continue;
   1024             }
   1025         } else {
   1026             /* Not Extender virtual port entry type */
   1027             continue;
   1028         }
   1029 
   1030         if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) {
   1031             /* Recover VP */
   1032             vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1033                     SD_TAG__DVPf);
   1034         } else if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW) {
   1035             /* L3MC*/
   1036             vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1037                     L3MC__DVPf);
   1038         }
   1039 
   1040         if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1041             rv = _bcm_vp_used_set(unit, vp, vp_info);
   1042             if (BCM_FAILURE(rv)) {
   1043                 goto cleanup;
   1044             }
   1045         } else {
   1046             if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   1047                 /* VP bitmap is recovered by virtual_init */
   1048                 continue;
   1049             }
   1050         }
   1051 
   1052         /* Add VP to EXTENDER VP bitmap */
   1053         SHR_BITSET(extender_vp_bitmap, vp);
   1054 
   1055         if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   1056             if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) {
   1057                 /* Recover ETAG PCP and DE info */
   1058                 if (BCM_EXTENDER_PCP_DE_SELECT_DEFAULT == pcp_de_select_mode) {
   1059                     EXTENDER_PORT_INFO(unit, vp)->pcp_de_select =
   1060                             BCM_EXTENDER_PCP_DE_SELECT_DEFAULT;
   1061                     EXTENDER_PORT_INFO(unit, vp)->pcp = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1062                             egr_nh_entry, SD_TAG__ETAG_PCPf);
   1063                     EXTENDER_PORT_INFO(unit, vp)->de = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1064                             egr_nh_entry, SD_TAG__ETAG_DEf);
   1065                 } else if (BCM_EXTENDER_PCP_DE_SELECT_PHB == pcp_de_select_mode) {
   1066                     EXTENDER_PORT_INFO(unit, vp)->pcp_de_select =
   1067                         BCM_EXTENDER_PCP_DE_SELECT_PHB;
   1068 #ifdef BCM_TRIDENT2_SUPPORT
   1069                     /* Get ETAG priority mapping profile pointer */
   1070                     etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1071                             egr_nh_entry, SD_TAG__ETAG_DOT1P_MAPPING_PTRf);
   1072 #ifdef BCM_TOMAHAWK_SUPPORT
   1073                     if (SOC_IS_TOMAHAWKX(unit)) {
   1074                          rv = bcm_th_qos_egr_etag_profile2id(unit, etag_dot1p_mapping_ptr,
   1075                                                              &map_id);
   1076                     } else
   1077 #endif
   1078                     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIDENT3X(unit)) {
   1079                         rv = bcm_td2_qos_egr_etag_profile2id(unit, etag_dot1p_mapping_ptr,
   1080                                                              &map_id);
   1081                     } else {
   1082                         rv = BCM_E_BADID;
   1083                     }
   1084                     if (rv == BCM_E_NONE) {
   1085                         EXTENDER_PORT_INFO(unit, vp)->qos_map_id = map_id;
   1086                     }
   1087 #endif
   1088                 }
   1089 
   1090                 /* Recover ETAG VID */
   1091                 EXTENDER_PORT_INFO(unit, vp)->extended_port_vid =
   1092                         soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1093                         SD_TAG__VNTAG_DST_VIFf);
   1094 
   1095                 /* Recover multicast flag */
   1096                 if ((EXTENDER_PORT_INFO(unit, vp)->extended_port_vid >= lower_th) &&
   1097                     (EXTENDER_PORT_INFO(unit, vp)->extended_port_vid <= higher_th)) {
   1098                     EXTENDER_PORT_INFO(unit, vp)->flags |= BCM_EXTENDER_PORT_MULTICAST;
   1099                 }
   1100 
   1101                 /* Recover transparent flag */
   1102                 if (vntag_action == ETAG_NOOP) {
   1103                     EXTENDER_PORT_INFO(unit, vp)->flags |=
   1104                             BCM_EXTENDER_PORT_EGRESS_TRANSPARENT;
   1105                 }
   1106 
   1107                 /* Recover physical trunk or port from ingress next hop table */
   1108                 ing_nh_entry = soc_mem_table_idx_to_pointer(unit,
   1109                         ING_L3_NEXT_HOPm, ing_l3_next_hop_entry_t *, ing_nh_buf, i);
   1110                 if (soc_feature(unit, soc_feature_generic_dest)) {
   1111                     dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, ing_nh_entry,
   1112                                                   DESTINATIONf, &dt);
   1113                     if (dt == SOC_MEM_FIF_DEST_LAG) {
   1114                         tgid = dv;
   1115                         trunk_bit = 1;
   1116                     } else {
   1117                         trunk_bit = 0;
   1118                         port_num = dv & SOC_MEM_FIF_DGPP_PORT_MASK;
   1119                         modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   1120                                     SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   1121                     }
   1122                 } else {
   1123                     trunk_bit = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry, Tf);
   1124                     if (trunk_bit) {
   1125                         tgid = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry,
   1126                                                                 TGIDf);
   1127                     } else {
   1128                         modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry,
   1129                                                                  MODULE_IDf);
   1130                         port_num = soc_ING_L3_NEXT_HOPm_field32_get(unit, ing_nh_entry,
   1131                                                                     PORT_NUMf);
   1132                     }
   1133                 }
   1134 
   1135                 if (trunk_bit) {
   1136                     BCM_GPORT_TRUNK_SET(EXTENDER_PORT_INFO(unit, vp)->port, tgid);
   1137                 } else {
   1138                     rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   1139                                             modid, port_num, &mod_out, &port_out);
   1140                     if (BCM_FAILURE(rv)) {
   1141                         goto cleanup;
   1142                     }
   1143                     BCM_GPORT_MODPORT_SET(EXTENDER_PORT_INFO(unit, vp)->port,
   1144                             mod_out, port_out);
   1145                 }
   1146 
   1147                 /* The match_vlan can be recovered from either match_vlan_array
   1148                  * or EGR_L3_NEXT_HOP.SD_TAG_VID field. The latter approach
   1149                  * is taken since older SDKs stored match_vlan in EGR_L3_NEXT_HOP
   1150                  * entry, not in scache.
   1151                  */
   1152                 EXTENDER_PORT_INFO(unit, vp)->match_vlan =
   1153                         soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1154                         SD_TAG__SD_TAG_VIDf);
   1155 
   1156                 if (stable_size == 0) {
   1157                     /* In the Port module, a port's VP count is not recovered in
   1158                      * level 1 Warm Boot.
   1159                      */
   1160                     rv = _bcm_tr3_extender_port_cnt_update(unit,
   1161                             EXTENDER_PORT_INFO(unit, vp)->port, vp, TRUE);
   1162                     if (BCM_FAILURE(rv)) {
   1163                         goto cleanup;
   1164                     }
   1165                 }
   1166             }
   1167         } else { /* The Extender port was created without match criteria */
   1168             vp_mc = 0;
   1169             BCM_PBMP_CLEAR(pbmp);
   1170             if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) {
   1171                 rv = _bcm_tr3_extender_sd_tag_recover(unit, egr_nh_entry, &extender_sd_tag);
   1172                 if (BCM_FAILURE(rv)) {
   1173                     goto cleanup;
   1174                 }
   1175 
   1176                 num_valid_ports = 0;
   1177                 for (j = 0; j < num_ports; j++) {
   1178                     if ((pbmp_ptr_array[i] != NULL) ?
   1179                         (SHR_BITGET(pbmp_ptr_array[i], j)) : 0) {
   1180                         /* Insert a new Extender egress object into VP's egress list */
   1181                         curr_ptr = sal_alloc(sizeof(_bcm_tr3_extender_egress_t),
   1182                                 "Extender egress object");
   1183                         if (NULL == curr_ptr) {
   1184                             rv = BCM_E_MEMORY;
   1185                             goto cleanup;
   1186                         }
   1187                         sal_memset(curr_ptr, 0, sizeof(_bcm_tr3_extender_egress_t));
   1188 
   1189                         curr_ptr->extended_port_vid =
   1190                                 soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1191                                 SD_TAG__VNTAG_DST_VIFf);
   1192 
   1193                         /* Recover multicast flag */
   1194                         if (curr_ptr->extended_port_vid >= lower_th &&
   1195                             curr_ptr->extended_port_vid <= higher_th) {
   1196                             curr_ptr->flags |= BCM_EXTENDER_EGRESS_MULTICAST;
   1197                         }
   1198 
   1199                         if (BCM_EXTENDER_PCP_DE_SELECT_DEFAULT == pcp_de_select_mode) {
   1200                             curr_ptr->pcp_de_select =
   1201                                     BCM_EXTENDER_PCP_DE_SELECT_DEFAULT;
   1202                             curr_ptr->pcp = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1203                                     egr_nh_entry, SD_TAG__ETAG_PCPf);
   1204                             curr_ptr->de = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1205                                                 egr_nh_entry, SD_TAG__ETAG_DEf);
   1206                         } else if (BCM_EXTENDER_PCP_DE_SELECT_PHB == pcp_de_select_mode) {
   1207                             curr_ptr->pcp_de_select = BCM_EXTENDER_PCP_DE_SELECT_PHB;
   1208 #ifdef BCM_TRIDENT2_SUPPORT
   1209                             /* Get ETAG priority mapping profile pointer */
   1210                             etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1211                                     egr_nh_entry, SD_TAG__ETAG_DOT1P_MAPPING_PTRf);
   1212                             rv = bcm_td2_qos_egr_etag_profile2id(unit,
   1213                                     etag_dot1p_mapping_ptr, &map_id);
   1214                             if (rv == BCM_E_NONE) {
   1215                                 curr_ptr->qos_map_id = map_id;
   1216                             }
   1217 #endif
   1218                         }
   1219                         rv = bcm_esw_port_gport_get(unit, j, &gport);
   1220                         if (BCM_FAILURE(rv)) {
   1221                             sal_free(curr_ptr);
   1222                             goto cleanup;
   1223                         }
   1224                         rv = bcm_esw_trunk_find(unit, BCM_MODID_INVALID, gport, &tgid);
   1225                         if (BCM_SUCCESS(rv)) {
   1226                             BCM_GPORT_TRUNK_SET(curr_ptr->port, tgid);
   1227                         } else if (rv == BCM_E_NOT_FOUND) {
   1228                             rv = BCM_E_NONE;
   1229                             curr_ptr->port = gport;
   1230                         } else {
   1231                             sal_free(curr_ptr);
   1232                             goto cleanup;
   1233                         }
   1234 
   1235                         curr_ptr->match_vlan = match_vlan_array[vp];
   1236                         curr_ptr->flags |= extender_sd_tag.flags;
   1237                         curr_ptr->service_tpid = extender_sd_tag.service_tpid;
   1238                         curr_ptr->service_vlan = extender_sd_tag.service_vlan;
   1239                         curr_ptr->service_pri = extender_sd_tag.service_pri;
   1240                         curr_ptr->service_cfi = extender_sd_tag.service_cfi;
   1241                         curr_ptr->service_qos_map_id = extender_sd_tag.service_qos_map_id;
   1242                         curr_ptr->next_hop_index = i;
   1243                         curr_ptr->next = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   1244                         if (curr_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   1245                             vp_mc = 1;
   1246                             rv = _bcm_tr3_extender_egress_hash_recover(unit, vp, curr_ptr);
   1247                             if (BCM_FAILURE(rv)) {
   1248                                 sal_free(curr_ptr);
   1249                                 goto cleanup;
   1250                             }
   1251                             BCM_PBMP_PORT_ADD(pbmp, j);
   1252                         } else {
   1253                             EXTENDER_PORT_INFO(unit, vp)->egress_list = curr_ptr;
   1254                         }
   1255 
   1256                         /* Increment the number of ports in port bitmap */
   1257                         num_valid_ports++;
   1258                     }
   1259                 }
   1260 
   1261                 /* During warm boot, L3 module had already incremented reference
   1262                  * count for non-null next hop entries. Hence, the next hop's
   1263                  * reference count should be incremented further by num_valid_ports
   1264                  * minus one.
   1265                  */
   1266                 for (j = 0; j < num_valid_ports - 1; j++) {
   1267                     _bcm_xgs3_nh_ref_cnt_incr(unit, i);
   1268                 }
   1269             } else if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_L3MC_VIEW) {
   1270                 num_valid_ports = 0;
   1271                 vp_mc = 1;
   1272                 for (j = 0; j < num_ports; j++) {
   1273                     if ((pbmp_ptr_array[i] != NULL) ?
   1274                         (!SHR_BITGET(pbmp_ptr_array[i], j)) : 1) {
   1275                         continue;
   1276                     }
   1277                     /* Insert a new Extender egress object into VP's egress list */
   1278                     curr_ptr = sal_alloc(sizeof(_bcm_tr3_extender_egress_t),
   1279                             "Extender egress object");
   1280                     if (NULL == curr_ptr) {
   1281                         rv = BCM_E_MEMORY;
   1282                         goto cleanup;
   1283                     }
   1284                     sal_memset(curr_ptr, 0, sizeof(_bcm_tr3_extender_egress_t));
   1285 
   1286                     /*entry_type == 7, L3MC */
   1287                     curr_ptr->flags |= BCM_EXTENDER_EGRESS_L3;
   1288 
   1289                     if (BCM_EXTENDER_PCP_DE_SELECT_DEFAULT == pcp_de_select_mode) {
   1290                         curr_ptr->pcp_de_select = BCM_EXTENDER_PCP_DE_SELECT_DEFAULT;
   1291                         curr_ptr->pcp = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1292                                 egr_nh_entry, L3MC__ETAG_PCPf);
   1293                         curr_ptr->de = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1294                                     egr_nh_entry, L3MC__ETAG_DEf);
   1295                     } else if (BCM_EXTENDER_PCP_DE_SELECT_PHB == pcp_de_select_mode) {
   1296                         curr_ptr->pcp_de_select = BCM_EXTENDER_PCP_DE_SELECT_PHB;
   1297 #ifdef BCM_TRIDENT2_SUPPORT
   1298                         /* Get ETAG priority mapping profile pointer */
   1299                         etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1300                                 egr_nh_entry, L3MC__ETAG_DOT1P_MAPPING_PTRf);
   1301                         rv = bcm_td2_qos_egr_etag_profile2id(unit,
   1302                                 etag_dot1p_mapping_ptr, &map_id);
   1303                         if (rv == BCM_E_NONE) {
   1304                             curr_ptr->qos_map_id = map_id;
   1305                         }
   1306 #endif
   1307                     }
   1308                     rv = bcm_esw_port_gport_get(unit, j, &gport);
   1309                     if (BCM_FAILURE(rv)) {
   1310                         sal_free(curr_ptr);
   1311                         goto cleanup;
   1312                     }
   1313                     rv = bcm_esw_trunk_find(unit, BCM_MODID_INVALID, gport, &tgid);
   1314                     if (BCM_SUCCESS(rv)) {
   1315                         BCM_GPORT_TRUNK_SET(curr_ptr->port, tgid);
   1316                     } else if (rv == BCM_E_NOT_FOUND) {
   1317                         rv = BCM_E_NONE;
   1318                         curr_ptr->port = gport;
   1319                     } else {
   1320                         sal_free(curr_ptr);
   1321                         goto cleanup;
   1322                     }
   1323                     curr_ptr->extended_port_vid = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1324                         L3MC__VNTAG_DST_VIFf);
   1325                     /* Recover multicast flag */
   1326                     if (curr_ptr->extended_port_vid >= lower_th &&
   1327                         curr_ptr->extended_port_vid <= higher_th) {
   1328                         curr_ptr->flags |= BCM_EXTENDER_EGRESS_MULTICAST;
   1329                     }
   1330                     curr_ptr->next_hop_index = i;
   1331                     curr_ptr->intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1332                         L3MC__INTF_NUMf);
   1333 
   1334                     mc_flags = 0;
   1335                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1336                         L3MC__L2_MC_DA_DISABLEf)) {
   1337                         mc_flags |= BCM_L3_MULTICAST_L2_DEST_PRESERVE;
   1338                     }
   1339                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1340                         L3MC__L2_MC_SA_DISABLEf)) {
   1341                         mc_flags |= BCM_L3_MULTICAST_L2_SRC_PRESERVE;
   1342                     }
   1343                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1344                         L3MC__L2_MC_VLAN_DISABLEf)) {
   1345                         mc_flags |= BCM_L3_MULTICAST_L2_VLAN_PRESERVE;
   1346                     }
   1347                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1348                         L3MC__L3_MC_TTL_DISABLEf)) {
   1349                         mc_flags |= BCM_L3_MULTICAST_TTL_PRESERVE;
   1350                     }
   1351                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1352                         L3MC__L3_MC_DA_DISABLEf)) {
   1353                         mc_flags |= BCM_L3_MULTICAST_DEST_PRESERVE;
   1354                     }
   1355                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1356                         L3MC__L3_MC_SA_DISABLEf)) {
   1357                         mc_flags |= BCM_L3_MULTICAST_SRC_PRESERVE;
   1358                     }
   1359                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1360                         L3MC__L3_MC_VLAN_DISABLEf)) {
   1361                         mc_flags |= BCM_L3_MULTICAST_VLAN_PRESERVE;
   1362                     }
   1363                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1364                         L3MC__L3_DROPf)) {
   1365                         mc_flags |= BCM_L3_MULTICAST_L3_DROP;
   1366                     }
   1367                     if(soc_EGR_L3_NEXT_HOPm_field32_get(unit, egr_nh_entry,
   1368                         L3MC__L2_DROPf)) {
   1369                         mc_flags |= BCM_L3_MULTICAST_L2_DROP;
   1370                     }
   1371                     curr_ptr->multicast_flags |= mc_flags;
   1372                     rv = _bcm_tr3_extender_egress_hash_recover(
   1373                              unit, vp, curr_ptr);
   1374                     if (BCM_FAILURE(rv)) {
   1375                         sal_free(curr_ptr);
   1376                         goto cleanup;
   1377                     }
   1378                     /* Increment the number of ports in port bitmap */
   1379                     num_valid_ports++;
   1380                     BCM_PBMP_PORT_ADD(pbmp, j);
   1381                 }
   1382 
   1383                 /* During warm boot, L3 module had already incremented reference
   1384                  * count for non-null next hop entries. Hence, the next hop's
   1385                  * reference count should be incremented further by num_valid_ports
   1386                  * minus one.
   1387                  */
   1388                 for (j = 0; j < num_valid_ports - 1; j++) {
   1389                     _bcm_xgs3_nh_ref_cnt_incr(unit, i);
   1390                 }
   1391             }
   1392 
   1393             if (vp_mc) {
   1394                 rv = _bcm_tr3_extender_egress_pbmp_add(unit, vp, pbmp);
   1395                 if (BCM_FAILURE(rv)) {
   1396                     sal_free(curr_ptr);
   1397                     goto cleanup;
   1398                 }
   1399             }
   1400         }
   1401     }
   1402 
   1403     /* Recover SD-tag TPID reference count from SOURCE_VP table */
   1404     if (entry_type == _BCM_EXTENDER_EGR_NEXT_HOP_SDTAG_VIEW) {
   1405         svp_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, SOURCE_VPm),
   1406                 "SOURCE_VP buffer");
   1407         if (NULL == svp_buf) {
   1408             rv = BCM_E_MEMORY;
   1409             goto cleanup;
   1410         }
   1411         index_min = soc_mem_index_min(unit, SOURCE_VPm);
   1412         index_max = soc_mem_index_max(unit, SOURCE_VPm);
   1413         rv = soc_mem_read_range(unit, SOURCE_VPm, MEM_BLOCK_ANY,
   1414                 index_min, index_max, svp_buf);
   1415         if (SOC_FAILURE(rv)) {
   1416             goto cleanup;
   1417         }
   1418         for (i = index_min; i <= index_max; i++) {
   1419             svp_entry = soc_mem_table_idx_to_pointer
   1420                 (unit, SOURCE_VPm, source_vp_entry_t *, svp_buf, i);
   1421             tpid_enable = soc_SOURCE_VPm_field32_get(unit, svp_entry, TPID_ENABLEf);
   1422             if (tpid_enable) {
   1423                 for (j = 0; j < soc_mem_field_length(unit, SOURCE_VPm, TPID_ENABLEf);
   1424                         j++) {
   1425                     if (tpid_enable & (1 << j)) {
   1426                         rv = _bcm_fb2_outer_tpid_tab_ref_count_add(unit, j, 1);
   1427                         if (SOC_FAILURE(rv)) {
   1428                             goto cleanup;
   1429                         }
   1430                     }
   1431                 }
   1432             }
   1433         }
   1434     }
   1435 
   1436 cleanup:
   1437     if (match_none_vp_bitmap) {
   1438         sal_free(match_none_vp_bitmap);
   1439     }
   1440     if (extender_vp_bitmap) {
   1441         sal_free(extender_vp_bitmap);
   1442     }
   1443     if (nh_bitmap) {
   1444         sal_free(nh_bitmap);
   1445     }
   1446     if (mc_nh_bitmap) {
   1447         sal_free(mc_nh_bitmap);
   1448     }
   1449     if (pbmp_ptr_array) {
   1450         for (i = 0; i < num_nh; i++) {
   1451             if (pbmp_ptr_array[i]) {
   1452                 sal_free(pbmp_ptr_array[i]);
   1453             }
   1454         }
   1455         sal_free(pbmp_ptr_array);
   1456     }
   1457     if (match_vlan_array) {
   1458         sal_free(match_vlan_array);
   1459     }
   1460     if (ing_nh_buf) {
   1461         soc_cm_sfree(unit, ing_nh_buf);
   1462     }
   1463     if (egr_nh_buf) {
   1464         soc_cm_sfree(unit, egr_nh_buf);
   1465     }
   1466     if (svp_buf) {
   1467         soc_cm_sfree(unit, svp_buf);
   1468     }
   1469 
   1470     return rv;
   1471 }
   1472 #endif /* BCM_WARM_BOOT_SUPPORT */
   1473 
   1474 /*
   1475  * Function:
   1476  *      _bcm_tr3_extender_free_resources
   1477  * Purpose:
   1478  *      Free all allocated tables and memory
   1479  * Parameters:
   1480  *      unit - SOC unit number
   1481  * Returns:
   1482  *      Nothing
   1483  */
   1484 STATIC void
   1485 _bcm_tr3_extender_free_resources(int unit)
   1486 {
   1487     if (EXTENDER_INFO(unit)->port_info) {
   1488         sal_free(EXTENDER_INFO(unit)->port_info);
   1489         EXTENDER_INFO(unit)->port_info = NULL;
   1490     }
   1491 }
   1492 
   1493 /*
   1494  * Function:
   1495  *      bcm_tr3_extender_init
   1496  * Purpose:
   1497  *      Initialize the Extender module.
   1498  * Parameters:
   1499  *      unit - SOC unit number.
   1500  * Returns:
   1501  *      BCM_E_XXX
   1502  */
   1503 int
   1504 bcm_tr3_extender_init(int unit)
   1505 {
   1506     int num_vp;
   1507     int rv = BCM_E_NONE;
   1508 
   1509     sal_memset(EXTENDER_INFO(unit), 0,
   1510             sizeof(_bcm_tr3_extender_bookkeeping_t));
   1511 
   1512     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   1513     if (NULL == EXTENDER_INFO(unit)->port_info) {
   1514         EXTENDER_INFO(unit)->port_info = sal_alloc
   1515             (sizeof(_bcm_tr3_extender_port_info_t) * num_vp,
   1516              "extender_port_info");
   1517         if (NULL == EXTENDER_INFO(unit)->port_info) {
   1518             _bcm_tr3_extender_free_resources(unit);
   1519             return BCM_E_MEMORY;
   1520         }
   1521     }
   1522     sal_memset(EXTENDER_INFO(unit)->port_info, 0,
   1523             sizeof(_bcm_tr3_extender_port_info_t) * num_vp);
   1524     /* When creating a EXTENDER virtual port without any match criteria,
   1525      * the ING_DVP_TABLE.NEXT_HOP_INDEX is configured with an invalid
   1526      * next hop index, which is assigned to be the black hole next hop index.
   1527      */
   1528     EXTENDER_INFO(unit)->invalid_next_hop_index = BCM_XGS3_L3_BLACK_HOLE_NH_IDX(unit);
   1529 
   1530 #ifdef BCM_WARM_BOOT_SUPPORT
   1531     if (SOC_WARM_BOOT(unit)) {
   1532         /* Warm Boot recovery */
   1533         rv = _bcm_tr3_extender_reinit(unit);
   1534         if (BCM_FAILURE(rv)) {
   1535             _bcm_tr3_extender_free_resources(unit);
   1536         }
   1537     } else
   1538 #endif /* BCM_WARM_BOOT_SUPPORT */
   1539     {
   1540         /* Initialize ETAG VID multicast range */
   1541         BCM_IF_ERROR_RETURN(bcm_esw_switch_control_set(unit,
   1542                     bcmSwitchExtenderMulticastLowerThreshold, 0x1000));
   1543         BCM_IF_ERROR_RETURN(bcm_esw_switch_control_set(unit,
   1544                     bcmSwitchExtenderMulticastHigherThreshold, 0x3fff));
   1545     }
   1546 
   1547 #ifdef BCM_TRIDENT3_SUPPORT
   1548     if (SOC_IS_TRIDENT3X(unit)) {
   1549         soc_td3_rx_etype_pe[unit] = 0;
   1550     }
   1551 #endif
   1552 
   1553     return rv;
   1554 }
   1555 
   1556 /*
   1557  * Function:
   1558  *      bcm_tr3_extender_cleanup
   1559  * Purpose:
   1560  *      Detach the Extender module.
   1561  * Parameters:
   1562  *      unit - SOC unit number.
   1563  * Returns:
   1564  *      BCM_E_XXX
   1565  */
   1566 int
   1567 bcm_tr3_extender_cleanup(int unit)
   1568 {
   1569     _bcm_tr3_extender_free_resources(unit);
   1570 
   1571 #ifdef BCM_TRIDENT3_SUPPORT
   1572     if (SOC_IS_TRIDENT3X(unit)) {
   1573         soc_td3_rx_etype_pe[unit] = 0;
   1574     }
   1575 #endif
   1576 
   1577     return BCM_E_NONE;
   1578 }
   1579 
   1580 /*
   1581  * Function:
   1582  *      _bcm_tr3_extender_failover_add
   1583  * Purpose:
   1584  *      Setup a failover extender port id.
   1585  * Parameters:
   1586  *      unit       - (IN) SOC unit number. 
   1587  *      extender_port  - (IN) Pointer to Extender port structure. 
   1588  *      vp         - (IN) Virtual port number.
   1589  * Returns:
   1590  *      BCM_X_XXX
   1591  */
   1592 STATIC int
   1593 _bcm_tr3_extender_failover_add(int unit, bcm_extender_port_t *extender_port, int vp)
   1594 {
   1595     int rv = BCM_E_NONE;
   1596     ing_dvp_table_entry_t dvp_entry;
   1597     int nh_index, failover_vp = -1, failover_nh_index = 0;
   1598     uint32 protection_flags = 0;
   1599     bcm_extender_port_t *ep = extender_port;
   1600 
   1601     if (_BCM_MULTICAST_IS_SET(ep->failover_mc_group)) {
   1602         protection_flags |= _BCM_FAILOVER_1_PLUS_PROTECTION;
   1603     } else {
   1604         /* Get egress next-hop index from Failover EXTENDER gport */
   1605         failover_vp = 
   1606             BCM_GPORT_EXTENDER_PORT_ID_GET(ep->failover_port_id);
   1607         if (failover_vp != -1) {
   1608             BCM_IF_ERROR_RETURN(
   1609                 READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, failover_vp,
   1610                                     &dvp_entry));
   1611             failover_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
   1612                                                                NEXT_HOP_INDEXf);
   1613         }
   1614     }
   1615 
   1616     BCM_IF_ERROR_RETURN(
   1617         READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   1618     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 
   1619                                               NEXT_HOP_INDEXf);
   1620     /* Set the failover to a given extender port */
   1621     rv = _bcm_esw_failover_prot_nhi_create(unit, protection_flags, 
   1622                                            nh_index, failover_nh_index, 
   1623                                            ep->failover_mc_group,
   1624                                            ep->failover_id);
   1625     BCM_IF_ERROR_RETURN(rv);
   1626 
   1627     return BCM_E_NONE;
   1628 }
   1629 
   1630 /*
   1631  * Function:
   1632  *      _bcm_tr3_extender_failover_delete
   1633  * Purpose:
   1634  *      Delete a failover extender port id.
   1635  * Parameters:
   1636  *      unit       - (IN) SOC unit number. 
   1637  *      gport - (IN) Extender GPORT ID.
   1638  * Returns:
   1639  *      BCM_X_XXX
   1640  */
   1641 STATIC int
   1642 _bcm_tr3_extender_failover_delete(int unit, bcm_gport_t gport)
   1643 {
   1644     int rv = BCM_E_NONE;
   1645     int nh_index;
   1646     uint32 vp;
   1647     ing_dvp_table_entry_t dvp_entry;
   1648 
   1649     /* Get egress next-hop index from EXTENDER gport */
   1650     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   1651 
   1652     BCM_IF_ERROR_RETURN(
   1653         READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   1654     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, 
   1655                                               NEXT_HOP_INDEXf);
   1656     /* Cleanup the failover from a given extender port */
   1657     rv = _bcm_esw_failover_prot_nhi_cleanup(unit, nh_index);
   1658     if ((rv != BCM_E_NOT_FOUND) && (rv != BCM_E_NONE)) {
   1659         return rv;
   1660     }
   1661 
   1662     return BCM_E_NONE;
   1663 }
   1664 
   1665 /*
   1666  * Function:
   1667  *      _bcm_tr3_extender_failover_get
   1668  * Purpose:
   1669  *      Setup a failover extender port id.
   1670  * Parameters:
   1671  *      unit          - (IN) SOC unit number. 
   1672  *      extender_port - (IN) extender port Id. 
   1673  *      failover_port - (OUT) failover extender port Id. 
   1674  *      failover_id   - (OUT) failover object index.. 
   1675  *      failover_mc_group - (OUT) failover multicast group id. 
   1676  * Returns:
   1677  *      BCM_X_XXX
   1678  */
   1679 STATIC int
   1680 _bcm_tr3_extender_failover_get(int unit, bcm_gport_t extender_port, 
   1681                                bcm_gport_t *failover_port, 
   1682                                bcm_failover_t *failover_id,
   1683                                bcm_multicast_t *failover_mc_group)
   1684 {
   1685     int failover_vp;
   1686     uint32 vp;
   1687     int nh_index, prot_nh_index = -1, multicast_group = 0;
   1688     bcm_failover_t fo_id;
   1689     ing_dvp_table_entry_t dvp_entry;
   1690     egr_l3_next_hop_entry_t egr_nh;
   1691 
   1692     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port);
   1693 
   1694     BCM_IF_ERROR_RETURN
   1695         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   1696     /* Get the next hop index */
   1697     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
   1698                                               NEXT_HOP_INDEXf);
   1699     /* Get the protecting information of this next hop index */
   1700     BCM_IF_ERROR_RETURN
   1701         (_bcm_esw_failover_prot_nhi_get(unit, nh_index, &fo_id,
   1702                                         &prot_nh_index, &multicast_group));
   1703     if (fo_id > 0) {
   1704         if (_BCM_MULTICAST_IS_SET(multicast_group)) {
   1705             if (failover_mc_group) {
   1706                 *failover_mc_group = multicast_group;
   1707             }
   1708         } else {
   1709             if (failover_port) {
   1710                 /* Read the existing egress next_hop entry */
   1711                 BCM_IF_ERROR_RETURN
   1712                     (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   1713                                   prot_nh_index, &egr_nh));
   1714                 /* retrieve the failover virtual port from egress next hop entry */
   1715                 failover_vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   1716                                                                SD_TAG__DVPf);
   1717                 /* failover port should also be a extender port */
   1718                 if (!_bcm_vp_used_get(unit, failover_vp, _bcmVpTypeExtender)) {
   1719                     return BCM_E_PARAM;
   1720                 }
   1721                 BCM_GPORT_EXTENDER_PORT_ID_SET(*failover_port, failover_vp);
   1722             }
   1723         }
   1724         if (failover_id) {
   1725             *failover_id = fo_id;
   1726         }
   1727 
   1728         return BCM_E_NONE;
   1729     }
   1730 
   1731     return BCM_E_NOT_FOUND;
   1732 }
   1733 
   1734 /*
   1735  * Function:
   1736  *      _bcm_tr3_extender_nh_info_set
   1737  * Purpose:
   1738  *      Get a next hop index and configure next hop tables.
   1739  * Parameters:
   1740  *      unit       - (IN) SOC unit number.
   1741  *      extender_port  - (IN) Pointer to Extender port structure.
   1742  *      vp         - (IN) Virtual port number.
   1743  *      drop       - (IN) Drop indication.
   1744  *      nh_index   - (IN/OUT) Next hop index.
   1745  * Returns:
   1746  *      BCM_X_XXX
   1747  */
   1748 STATIC int
   1749 _bcm_tr3_extender_nh_info_set(int unit, bcm_extender_port_t *extender_port,
   1750         _bcm_tr3_extender_sd_tag_t *sd_tag, int vp, int drop, int *nh_index)
   1751 {
   1752     int rv;
   1753     uint32 nh_flags;
   1754     bcm_l3_egress_t nh_info;
   1755     egr_l3_next_hop_entry_t egr_nh;
   1756     uint8 egr_nh_entry_type;
   1757     int etag_dot1p_mapping_ptr;
   1758     bcm_module_t mod_out;
   1759     bcm_port_t port_out;
   1760     bcm_trunk_t trunk_id;
   1761     int id;
   1762     int ing_nh_port;
   1763     int ing_nh_module;
   1764     int ing_nh_trunk;
   1765     ing_l3_next_hop_entry_t ing_nh;
   1766     initial_ing_l3_next_hop_entry_t initial_ing_nh;
   1767     int sd_tag_add = 0;
   1768     int sd_tag_delete = 0;
   1769     int sd_tag_replace_vlan = 0;
   1770     int sd_tag_replace_pri = 0;
   1771     int sd_tag_replace_tpid = 0;
   1772     int tpid_index;
   1773     int mapping_ptr;
   1774     soc_field_t ent_type_f = ENTRY_TYPEf;
   1775     if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   1776         ent_type_f = DATA_TYPEf;
   1777     }
   1778 
   1779     /* Get a next hop index */
   1780 
   1781     if (extender_port->flags & BCM_EXTENDER_PORT_REPLACE) {
   1782         if ((*nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) ||
   1783                 (*nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm)))  {
   1784             return BCM_E_PARAM;
   1785         }
   1786     } else {
   1787         /*
   1788          * Allocate a next-hop entry. By calling bcm_xgs3_nh_add()
   1789          * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is
   1790          * allocated but nothing is written to hardware. The "nh_info"
   1791          * in this case is not used, so just set to all zeros.
   1792          */
   1793         bcm_l3_egress_t_init(&nh_info);
   1794 
   1795         nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
   1796         rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, nh_index);
   1797         BCM_IF_ERROR_RETURN(rv);
   1798     }
   1799 
   1800     /* Write EGR_L3_NEXT_HOP entry */
   1801 
   1802     if (extender_port->flags & BCM_EXTENDER_PORT_REPLACE) {
   1803         /* Read the existing egress next_hop entry */
   1804         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   1805                 *nh_index, &egr_nh);
   1806         BCM_IF_ERROR_RETURN(rv);
   1807 
   1808         /* Be sure that the existing entry is programmed to SD-tag */
   1809         egr_nh_entry_type = 
   1810             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ent_type_f);
   1811         if (egr_nh_entry_type != 0x2) { /* != SD-tag */
   1812             return BCM_E_PARAM;
   1813         }
   1814 
   1815         /* Get ETAG priority mapping profile pointer */
   1816         etag_dot1p_mapping_ptr = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   1817                 &egr_nh, SD_TAG__ETAG_DOT1P_MAPPING_PTRf);
   1818     } else {
   1819         egr_nh_entry_type = 0x2; /* SD-tag */
   1820         etag_dot1p_mapping_ptr = 0;
   1821 #ifdef BCM_TOMAHAWK_SUPPORT
   1822         if (SOC_IS_TOMAHAWKX(unit)) {
   1823             bcm_th_qos_egr_etag_id2profile(unit, extender_port->qos_map_id,
   1824                                            &etag_dot1p_mapping_ptr);
   1825         }
   1826 #endif
   1827 #ifdef BCM_TRIDENT2_SUPPORT
   1828         if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIDENT3X(unit)){
   1829             bcm_td2_qos_egr_etag_id2profile(unit, extender_port->qos_map_id,
   1830                                             &etag_dot1p_mapping_ptr);
   1831         }
   1832 #endif
   1833     }
   1834 
   1835     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   1836     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1837             ent_type_f, egr_nh_entry_type);
   1838     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1839             SD_TAG__DVPf, vp);
   1840     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1841             SD_TAG__HG_HDR_SELf, 1);
   1842     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1843             SD_TAG__VNTAG_DST_VIFf, extender_port->extended_port_vid);
   1844     if (extender_port->pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_DEFAULT) {
   1845         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1846                 SD_TAG__ETAG_PCP_DE_SOURCEf, 2);
   1847         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1848                 SD_TAG__ETAG_PCPf, extender_port->pcp);
   1849         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1850                 SD_TAG__ETAG_DEf, extender_port->de);
   1851     } else if (extender_port->pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_PHB) {
   1852         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1853                 SD_TAG__ETAG_PCP_DE_SOURCEf, 3);
   1854         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1855                 SD_TAG__ETAG_DOT1P_MAPPING_PTRf, etag_dot1p_mapping_ptr);
   1856     } else {
   1857         return BCM_E_PARAM;
   1858     }
   1859     /* For the transparent port, do not modify the ETAG. */
   1860     if ((extender_port->flags & BCM_EXTENDER_PORT_EGRESS_TRANSPARENT) == 0) {
   1861         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
   1862                             SD_TAG__VNTAG_ACTIONSf, 2);
   1863     }
   1864 
   1865     if (NULL != sd_tag) {
   1866         sd_tag_add = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_VLAN_ADD;
   1867         sd_tag_delete = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_VLAN_DELETE;
   1868         sd_tag_replace_vlan = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_VLAN_REPLACE;
   1869         sd_tag_replace_pri = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_PRI_REPLACE;
   1870         sd_tag_replace_tpid = sd_tag->flags & BCM_EXTENDER_EGRESS_SERVICE_TPID_REPLACE;
   1871 
   1872         /* Set SD-tag action for packets without an SD-tag */
   1873         if (sd_tag_add) {
   1874             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1875                     SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf, 1);
   1876         }
   1877 
   1878         /* Set SD-tag action for packets with an SD-tag */
   1879         if (sd_tag_delete) {
   1880             if (sd_tag_replace_vlan || sd_tag_replace_pri || sd_tag_replace_tpid) {
   1881                 return BCM_E_PARAM;
   1882             }
   1883             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1884                     SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 3); /* DELETE SD-TAG */
   1885         } else {
   1886             if (!sd_tag_replace_vlan && !sd_tag_replace_pri && !sd_tag_replace_tpid) {
   1887                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1888                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 0); /* NOOP */
   1889             } else if (sd_tag_replace_vlan && !sd_tag_replace_pri && sd_tag_replace_tpid) {
   1890                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1891                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 1); /* REPLACE_VID_TPID */
   1892             } else if (sd_tag_replace_vlan && !sd_tag_replace_pri && !sd_tag_replace_tpid) {
   1893                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1894                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 2); /* REPLACE_VID_ONLY */
   1895             } else if (sd_tag_replace_vlan && sd_tag_replace_pri && sd_tag_replace_tpid) {
   1896                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1897                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 4); /* REPLACE_VID_PRI_TPID */
   1898             } else if (sd_tag_replace_vlan && sd_tag_replace_pri && !sd_tag_replace_tpid) {
   1899                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1900                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 5); /* REPLACE_VID_PRI_ONLY */
   1901             } else if (!sd_tag_replace_vlan && sd_tag_replace_pri && !sd_tag_replace_tpid) {
   1902                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1903                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 6); /* REPLACE_PRI_ONLY */
   1904             } else if (!sd_tag_replace_vlan && !sd_tag_replace_pri && sd_tag_replace_tpid) {
   1905                 if (SOC_IS_TRIDENT(unit)) {
   1906                     /* REPLACE_TPID_ONLY action is not available on Trident.
   1907                                    * It's available on Triumph3 and Trident2.
   1908                                    */
   1909                     return BCM_E_PARAM;
   1910                 }
   1911                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1912                         SD_TAG__SD_TAG_ACTION_IF_PRESENTf, 7); /* REPLACE_TPID_ONLY */
   1913             } else {
   1914                 return BCM_E_PARAM;
   1915             }
   1916         }
   1917 
   1918         /* Set SD-tag TPID */
   1919         if (sd_tag->service_tpid) {
   1920             if (sd_tag_add || sd_tag_replace_tpid) {
   1921                 BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit,
   1922                             sd_tag->service_tpid, &tpid_index));
   1923                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1924                         SD_TAG__SD_TAG_TPID_INDEXf, tpid_index);
   1925             } else {
   1926                 return BCM_E_PARAM;
   1927             }
   1928         } else {
   1929             if (sd_tag_add || sd_tag_replace_tpid) {
   1930                 return BCM_E_PARAM;
   1931             }
   1932         }
   1933 
   1934         /* Set SD-tag VLAN ID */
   1935         if (sd_tag->service_vlan) {
   1936             if (sd_tag_add || sd_tag_replace_vlan) {
   1937                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1938                         SD_TAG__SD_TAG_VIDf, sd_tag->service_vlan);
   1939             } else {
   1940                 return BCM_E_PARAM;
   1941             }
   1942         } else {
   1943             if (sd_tag_add || sd_tag_replace_vlan) {
   1944                 return BCM_E_PARAM;
   1945             }
   1946         }
   1947 
   1948         /* Set SD-tag Priority */
   1949         if (sd_tag->service_qos_map_id) {
   1950             if (sd_tag_add || sd_tag_replace_pri) {
   1951                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1952                         SD_TAG__SD_TAG_DOT1P_PRI_SELECTf, 1);
   1953                 BCM_IF_ERROR_RETURN(_bcm_tr2_qos_id2idx(unit,
   1954                             sd_tag->service_qos_map_id, &mapping_ptr));
   1955                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1956                         SD_TAG__SD_TAG_DOT1P_MAPPING_PTRf, mapping_ptr);
   1957             } else {
   1958                 return BCM_E_PARAM;
   1959             }
   1960         } else {
   1961             if (sd_tag_add || sd_tag_replace_pri) {
   1962                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1963                         SD_TAG__SD_TAG_DOT1P_PRI_SELECTf, 0);
   1964                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1965                         SD_TAG__NEW_PRIf, sd_tag->service_pri);
   1966                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1967                         SD_TAG__NEW_CFIf, sd_tag->service_cfi);
   1968             }
   1969         }
   1970     }
   1971 
   1972     /* The field SD_TAG_VID is not used for Port Extension.
   1973      * Store match_vlan here for warm boot recovery.
   1974      */
   1975     if (extender_port->match_vlan >= BCM_VLAN_INVALID) {
   1976         return BCM_E_PARAM;
   1977     }
   1978 
   1979     if (NULL == sd_tag) {
   1980         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1981                 SD_TAG__SD_TAG_VIDf, extender_port->match_vlan);
   1982     } else {
   1983         /* Indicate this egress object is on shared VP */
   1984         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   1985                  SD_TAG__RSVD_DVPf, 1);
   1986     }
   1987     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   1988             MEM_BLOCK_ALL, *nh_index, &egr_nh);
   1989     if (rv < 0) {
   1990     goto cleanup;
   1991     }
   1992 
   1993     /* Resolve gport */
   1994 
   1995     rv = _bcm_esw_gport_resolve(unit, extender_port->port, &mod_out, &port_out, &trunk_id, &id);
   1996     if (rv < 0) {
   1997         goto cleanup;
   1998     }
   1999 
   2000     ing_nh_port = -1;
   2001     ing_nh_module = -1;
   2002     ing_nh_trunk = -1;
   2003 
   2004     if (BCM_GPORT_IS_TRUNK(extender_port->port)) {
   2005         ing_nh_module = -1;
   2006         ing_nh_port = -1;
   2007         ing_nh_trunk = trunk_id;
   2008     } else {
   2009         ing_nh_module = mod_out;
   2010         ing_nh_port = port_out;
   2011         ing_nh_trunk = -1;
   2012     }
   2013 
   2014     /* Write ING_L3_NEXT_HOP entry */
   2015 
   2016     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
   2017 
   2018     if (ing_nh_trunk == -1) {
   2019         if (soc_feature(unit, soc_feature_generic_dest)) {
   2020             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2021                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   2022                 ing_nh_module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_port);
   2023         } else {
   2024             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2025                     &ing_nh, PORT_NUMf, ing_nh_port);
   2026             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2027                     &ing_nh, MODULE_IDf, ing_nh_module);
   2028         }
   2029     } else {
   2030         if (soc_feature(unit, soc_feature_generic_dest)) {
   2031             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2032                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_trunk);
   2033         } else {
   2034             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2035                     &ing_nh, Tf, 1);
   2036             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2037                     &ing_nh, TGIDf, ing_nh_trunk);
   2038         }
   2039     }
   2040 
   2041     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop);
   2042     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
   2043             &ing_nh, ENTRY_TYPEf, 0x2); /* L2 DVP */
   2044 
   2045     if (soc_mem_field_valid(unit, ING_L3_NEXT_HOPm, DVP_ATTRIBUTE_1_INDEXf)) {
   2046         uint32 mtu_profile_index;
   2047 
   2048         rv = _bcm_tr3_mtu_profile_index_get(unit, 0x3fff, &mtu_profile_index);
   2049         if (rv < 0) {
   2050             goto cleanup;
   2051         }
   2052         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2053                 DVP_ATTRIBUTE_1_INDEXf, mtu_profile_index);
   2054     } else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
   2055         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2056                 MTU_SIZEf, 0x3fff);
   2057     }
   2058 
   2059     rv = soc_mem_write (unit, ING_L3_NEXT_HOPm,
   2060             MEM_BLOCK_ALL, *nh_index, &ing_nh);
   2061     if (rv < 0) {
   2062         goto cleanup;
   2063     }
   2064 
   2065     /* Write INITIAL_ING_L3_NEXT_HOP entry */
   2066 
   2067     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
   2068     if (ing_nh_trunk == -1) {
   2069         if (soc_feature(unit, soc_feature_generic_dest)) {
   2070             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2071                 &initial_ing_nh, DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
   2072                 ing_nh_module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS | ing_nh_port);
   2073         } else {
   2074             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2075                     &initial_ing_nh, PORT_NUMf, ing_nh_port);
   2076             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2077                     &initial_ing_nh, MODULE_IDf, ing_nh_module);
   2078         }
   2079     } else {
   2080         if (soc_feature(unit, soc_feature_generic_dest)) {
   2081             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2082                 &initial_ing_nh, DESTINATIONf, SOC_MEM_FIF_DEST_LAG,
   2083                 ing_nh_trunk);
   2084         } else {
   2085             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2086                     &initial_ing_nh, Tf, 1);
   2087             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2088                     &initial_ing_nh, TGIDf, ing_nh_trunk);
   2089         }
   2090     }
   2091     rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
   2092             MEM_BLOCK_ALL, *nh_index, &initial_ing_nh);
   2093     if (rv < 0) {
   2094         goto cleanup;
   2095     }
   2096 
   2097     return rv;
   2098 
   2099 cleanup:
   2100     if (!(extender_port->flags & BCM_EXTENDER_PORT_REPLACE)) {
   2101         (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index);
   2102     }
   2103     return rv;
   2104 }
   2105 
   2106 /*
   2107  * Function:
   2108  *      _bcm_tr3_extender_nh_info_delete
   2109  * Purpose:
   2110  *      Free next hop index and clear next hop tables.
   2111  * Parameters:
   2112  *      unit     - (IN) SOC unit number. 
   2113  *      nh_index - (IN) Next hop index. 
   2114  * Returns:
   2115  *      BCM_X_XXX
   2116  */
   2117 STATIC int
   2118 _bcm_tr3_extender_nh_info_delete(int unit, int nh_index)
   2119 {
   2120     egr_l3_next_hop_entry_t egr_nh;
   2121     ing_l3_next_hop_entry_t ing_nh;
   2122     initial_ing_l3_next_hop_entry_t initial_ing_nh;
   2123     int ref_count;
   2124     int sd_tag_action_if_not_present;
   2125     int sd_tag_action_if_present;
   2126     int sd_tag_add;
   2127     int sd_tag_replace_tpid;
   2128     int tpid_index;
   2129     uint32 entry_type = 0;
   2130     soc_field_t etfld;
   2131 
   2132     /* Read egress next hop entry before it's potentially deleted by
   2133      * bcm_xgs3_nh_del.
   2134      */
   2135     BCM_IF_ERROR_RETURN
   2136         (READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &egr_nh));
   2137     /* Check next hop's reference count. If the count is zero,
   2138      * the egress next hop entry was cleared by bcm_xgs3_nh_del.
   2139      * In this case, the EGR_L3_NEXT_HOP.SD_TAG_TPID_INDEX's
   2140      * reference count needs to be decremented.
   2141      */
   2142     BCM_IF_ERROR_RETURN(bcm_xgs3_nh_ref_count_get(unit, nh_index, &ref_count));
   2143     /* Check entry type */
   2144     etfld = SOC_IS_TRIDENT3X(unit) ? DATA_TYPEf : ENTRY_TYPEf;
   2145     entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, etfld);
   2146 
   2147     if (ref_count == 0 && entry_type == 2) {
   2148         sd_tag_action_if_not_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   2149                 &egr_nh, SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   2150         if (1 == sd_tag_action_if_not_present) {
   2151             sd_tag_add = TRUE;
   2152         } else {
   2153             sd_tag_add = FALSE;
   2154         }
   2155 
   2156         sd_tag_action_if_present = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   2157                 &egr_nh, SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   2158         if ((1 == sd_tag_action_if_present) ||
   2159                 (4 == sd_tag_action_if_present) ||
   2160                 (7 == sd_tag_action_if_present)) {
   2161             sd_tag_replace_tpid = TRUE;
   2162         } else {
   2163             sd_tag_replace_tpid = FALSE;
   2164         }
   2165 
   2166         if (sd_tag_add || sd_tag_replace_tpid) {
   2167             tpid_index = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   2168                     &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
   2169             BCM_IF_ERROR_RETURN
   2170                 (_bcm_fb2_outer_tpid_entry_delete(unit, tpid_index));
   2171         }
   2172     }
   2173 
   2174     /* Clear EGR_L3_NEXT_HOP entry */
   2175     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   2176     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   2177                                    MEM_BLOCK_ALL, nh_index, &egr_nh));
   2178 
   2179     /* Clear ING_L3_NEXT_HOP entry */
   2180     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
   2181     BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm,
   2182                                    MEM_BLOCK_ALL, nh_index, &ing_nh));
   2183 
   2184     /* Clear INITIAL_ING_L3_NEXT_HOP entry */
   2185     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
   2186     BCM_IF_ERROR_RETURN(soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
   2187                                    MEM_BLOCK_ALL, nh_index, &initial_ing_nh));
   2188 
   2189     /* Free the next-hop index. */
   2190     BCM_IF_ERROR_RETURN
   2191         (bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index));
   2192 
   2193     return BCM_E_NONE;
   2194 }
   2195 
   2196 /*
   2197  * Function:
   2198  *      _bcm_tr3_extender_port_nh_info_set
   2199  * Purpose:
   2200  *      Get a next hop index and configure next hop tables.
   2201  * Parameters:
   2202  *      unit       - (IN) SOC unit number.
   2203  *      port              - (IN) Physical GPORT ID.
   2204  *      extender_port_vid - (IN) extender port VID in ETAG.
   2205  *      pcp -             - (IN) PCP field in  ETAG.
   2206  *      de -              - (IN) DE field in  ETAG.
   2207  *      pcp_de_select     - (IN) Selection of PCP and DE fields for egress ETAG.
   2208  *      qos_map_id-         (IN) Qos map id for egress etag mapping profile.
   2209  *      sd_tag           - (IN) SD-tag attributes.
   2210  *      vp         - (IN) Virtual port number.
   2211  *      nh_index   - (IN/OUT) Next hop index.
   2212  * Returns:
   2213  *      BCM_X_XXX
   2214  */
   2215 STATIC int
   2216 _bcm_tr3_extender_port_nh_info_set(int unit,
   2217         bcm_gport_t port, uint16 extended_port_vid,
   2218         bcm_vlan_t match_vlan, uint8 pcp, uint8 de,
   2219         uint32 pcp_de_select, int qos_map_id,
   2220         _bcm_tr3_extender_sd_tag_t *sd_tag,
   2221         int vp, int *nh_index)
   2222 {
   2223     int drop;
   2224     bcm_extender_port_t  extender_port;
   2225 
   2226     bcm_extender_port_t_init(&extender_port);
   2227     extender_port.flags = EXTENDER_PORT_INFO(unit, vp)->flags;
   2228     extender_port.port = port;
   2229     extender_port.match_vlan = match_vlan;
   2230     extender_port.extended_port_vid = extended_port_vid;
   2231     extender_port.pcp = pcp;
   2232     extender_port.de = de;
   2233     extender_port.pcp_de_select = pcp_de_select;
   2234     extender_port.qos_map_id = qos_map_id;
   2235     drop = (extender_port.flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0;
   2236 
   2237     return _bcm_tr3_extender_nh_info_set(unit, &extender_port, sd_tag, vp, drop, nh_index);
   2238 }
   2239 
   2240 /*
   2241  * Function:
   2242  *      _bcm_tr3_extender_l3mc_nh_info_set
   2243  * Purpose:
   2244  *      Configure next hop tables for L3MC.
   2245  * Parameters:
   2246  *      unit             - (IN) SOC unit number.
   2247  *      nh_index      - (IN) Next hop index.
   2248  *      flags                    - (IN) EXTENDER multicast flag.
   2249  *      multicast_flags      - (IN) EXTENDER multicast flag.
   2250  *      port             - (IN) Physical GPORT ID.
   2251  *      extended_port_vid - (IN) extender port VID in Etag.
   2252  *      pcp_de_select      - (IN) Selection of PCP and DE fields for egress ETAG.
   2253  *      qos_map_id-       - (IN) Qos map id for egress etag mapping profile.
   2254  *      pcp -                  - (IN) PCP field in  ETAG.
   2255  *      de -                    - (IN) DE field in  ETAG.
   2256  *      vp               - (IN) Virtual port number.
   2257  * Returns:
   2258  *      BCM_X_XXX
   2259  */
   2260 STATIC int
   2261 _bcm_tr3_extender_l3mc_nh_info_set(int unit, int nh_index, uint32 flags,
   2262         uint32 multicast_flags, bcm_gport_t port, bcm_if_t intf,
   2263         uint16 extended_port_vid, int qos_map_id,
   2264         uint32 pcp_de_select, uint8 pcp, uint8 de, int vp)
   2265 {
   2266     egr_l3_next_hop_entry_t egr_nh;
   2267     bcm_module_t mod_out;
   2268     bcm_port_t port_out;
   2269     bcm_trunk_t trunk_id;
   2270     int id;
   2271     int ing_nh_port;
   2272     int ing_nh_module;
   2273     int ing_nh_trunk;
   2274     ing_l3_next_hop_entry_t ing_nh;
   2275     initial_ing_l3_next_hop_entry_t initial_ing_nh;
   2276     int i;
   2277     int flag_set;
   2278     int etag_dot1p_mapping_ptr;
   2279     int drop;
   2280     soc_mem_t mem = EGR_L3_NEXT_HOPm;
   2281 
   2282     uint32 flag_array[] = {
   2283         BCM_L3_MULTICAST_L2_DEST_PRESERVE,
   2284         BCM_L3_MULTICAST_L2_SRC_PRESERVE,
   2285         BCM_L3_MULTICAST_L2_VLAN_PRESERVE,
   2286         BCM_L3_MULTICAST_TTL_PRESERVE,
   2287         BCM_L3_MULTICAST_DEST_PRESERVE,
   2288         BCM_L3_MULTICAST_SRC_PRESERVE,
   2289         BCM_L3_MULTICAST_VLAN_PRESERVE,
   2290         BCM_L3_MULTICAST_L3_DROP,
   2291         BCM_L3_MULTICAST_L2_DROP
   2292     };
   2293     soc_field_t field_array[] = {
   2294         L3MC__L2_MC_DA_DISABLEf,
   2295         L3MC__L2_MC_SA_DISABLEf,
   2296         L3MC__L2_MC_VLAN_DISABLEf,
   2297         L3MC__L3_MC_TTL_DISABLEf,
   2298         L3MC__L3_MC_DA_DISABLEf,
   2299         L3MC__L3_MC_SA_DISABLEf,
   2300         L3MC__L3_MC_VLAN_DISABLEf,
   2301         L3MC__L3_DROPf,
   2302         L3MC__L2_DROPf
   2303     };
   2304 
   2305     if ((nh_index > soc_mem_index_max(unit, mem)) ||
   2306             (nh_index < soc_mem_index_min(unit, mem))) {
   2307         return BCM_E_PARAM;
   2308     }
   2309 
   2310     etag_dot1p_mapping_ptr = 0;
   2311 #ifdef BCM_TOMAHAWK_SUPPORT
   2312     if (SOC_IS_TOMAHAWKX(unit)) {
   2313         bcm_th_qos_egr_etag_id2profile(unit, qos_map_id,
   2314                                        &etag_dot1p_mapping_ptr);
   2315     }
   2316 #endif
   2317 #ifdef BCM_TRIDENT2_SUPPORT
   2318     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TRIDENT3X(unit)){
   2319         bcm_td2_qos_egr_etag_id2profile(unit, qos_map_id,
   2320                                         &etag_dot1p_mapping_ptr);
   2321     }
   2322 #endif
   2323 
   2324     /*SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   2325             MEM_BLOCK_ANY, nh_index, &egr_nh));*/
   2326     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   2327 
   2328     soc_mem_field32_set(unit, mem, &egr_nh, ENTRY_TYPEf, 7); /* L3MC view */
   2329     soc_mem_field32_set(unit, mem, &egr_nh, L3MC__INTF_NUMf, intf);
   2330 
   2331     for (i = 0; i < COUNTOF(flag_array); i++) {
   2332         if (multicast_flags & flag_array[i]) {
   2333             flag_set = 1;
   2334         } else {
   2335             flag_set = 0;
   2336         }
   2337         if (soc_mem_field_valid(unit, mem, field_array[i])) {
   2338             soc_mem_field32_set(unit, mem, &egr_nh, field_array[i], flag_set);
   2339         } else {
   2340             if (flag_set) {
   2341                 return BCM_E_PARAM;
   2342             }
   2343         }
   2344     }
   2345     /* Set up EGR_L3_NEXT_HOP entry */
   2346     /*soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   2347             L3MC__L3MC_USE_CONFIGURED_MACf, 0);*/
   2348 
   2349 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2350     if (soc_feature(unit, soc_feature_egr_l3_next_hop_next_ptr)) {
   2351         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__NEXT_PTR_TYPEf, 1);
   2352     } else
   2353 #endif
   2354     {
   2355         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__DVP_VALIDf, 1);
   2356     }
   2357     soc_mem_field32_set(unit, mem, &egr_nh,
   2358             L3MC__VNTAG_DST_VIFf, extended_port_vid);
   2359     /* PPD2 header */
   2360     soc_mem_field32_set(unit, mem, &egr_nh, L3MC__HG_HDR_SELf, 1);
   2361 
   2362     /* For the transparent port, do not modify the ETAG. */
   2363     if ((flags & BCM_EXTENDER_PORT_EGRESS_TRANSPARENT) == 0) {
   2364         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__VNTAG_ACTIONSf, 2);
   2365     }
   2366 
   2367     if (pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_DEFAULT) {
   2368         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_PCP_DE_SOURCEf, 2);
   2369         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_PCPf, pcp);
   2370         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_DEf, de);
   2371     } else if (pcp_de_select == BCM_EXTENDER_PCP_DE_SELECT_PHB) {
   2372         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__ETAG_PCP_DE_SOURCEf, 3);
   2373         soc_mem_field32_set(unit, mem, &egr_nh,
   2374                 L3MC__ETAG_DOT1P_MAPPING_PTRf, etag_dot1p_mapping_ptr);
   2375     } else {
   2376         return BCM_E_PARAM;
   2377     }
   2378 
   2379     /* Indicate this egress object is on shared VP */
   2380     if (SOC_IS_TRIDENT3X(unit)) {
   2381         int fld_len = soc_mem_field_length(unit, mem, L3MC__RESERVED_1f);
   2382         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__NEXT_PTRf, vp);
   2383         if (fld_len > 0) {
   2384             soc_mem_field32_set(unit, mem, &egr_nh,
   2385                                 L3MC__RESERVED_1f, 1 << (fld_len - 1));
   2386         }
   2387     } else {
   2388         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__RSVD_DVPf, 1);
   2389         soc_mem_field32_set(unit, mem, &egr_nh, L3MC__DVPf, vp);
   2390     }
   2391 
   2392     /* Resolve gport */
   2393     BCM_IF_ERROR_RETURN(
   2394         _bcm_esw_gport_resolve(unit, port, &mod_out, &port_out,
   2395                                &trunk_id, &id));
   2396 
   2397 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2398     if (soc_mem_field_valid(unit, mem, L3MC__HG_MC_DST_PORT_NUMf)) {
   2399         if ((!BCM_GPORT_IS_TRUNK(port)) &&
   2400             (_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out))) {
   2401             soc_mem_field32_set(unit, mem, &egr_nh,
   2402                                 L3MC__HG_MC_DST_PORT_NUMf, port_out);
   2403             soc_mem_field32_set(unit, mem, &egr_nh,
   2404                                 L3MC__HG_MC_DST_MODIDf, mod_out);
   2405         }
   2406     }
   2407 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   2408     /* Write EGR_L3_NEXT_HOP entry */
   2409     SOC_IF_ERROR_RETURN(
   2410         soc_mem_write(unit, mem, MEM_BLOCK_ALL, nh_index, &egr_nh));
   2411 
   2412     ing_nh_port = -1;
   2413     ing_nh_module = -1;
   2414     ing_nh_trunk = -1;
   2415     if (BCM_GPORT_IS_TRUNK(port)) {
   2416         ing_nh_module = -1;
   2417         ing_nh_port = -1;
   2418         ing_nh_trunk = trunk_id;
   2419     } else {
   2420         ing_nh_module = mod_out;
   2421         ing_nh_port = port_out;
   2422         ing_nh_trunk = -1;
   2423     }
   2424 
   2425     /* Write ING_L3_NEXT_HOP entry. It is not necessary and to be removed */
   2426     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
   2427     if (ing_nh_trunk == -1) {
   2428         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2429                 PORT_NUMf, ing_nh_port);
   2430         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2431                 MODULE_IDf, ing_nh_module);
   2432     } else {
   2433         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2434                 Tf, 1);
   2435         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
   2436                 TGIDf, ing_nh_trunk);
   2437     }
   2438 
   2439     drop = (flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0;
   2440     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop);
   2441 
   2442     SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_L3_NEXT_HOPm,
   2443                 MEM_BLOCK_ALL, nh_index, &ing_nh));
   2444 
   2445     /* Write INITIAL_ING_L3_NEXT_HOP entry */
   2446     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
   2447     if (ing_nh_trunk == -1) {
   2448         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2449                 &initial_ing_nh, PORT_NUMf, ing_nh_port);
   2450         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2451                 &initial_ing_nh, MODULE_IDf, ing_nh_module);
   2452     } else {
   2453         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2454                 &initial_ing_nh, Tf, 1);
   2455         soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
   2456                 &initial_ing_nh, TGIDf, ing_nh_trunk);
   2457     }
   2458     SOC_IF_ERROR_RETURN(soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
   2459                 MEM_BLOCK_ALL, nh_index, &initial_ing_nh));
   2460 
   2461     return BCM_E_NONE;
   2462 }
   2463 
   2464 /*
   2465  * Function:
   2466  *      _bcm_tr3_extender_match_key_assemble
   2467  * Purpose:
   2468  *      Constructs a vlan_xlate key for extender match
   2469  *      according to extender port.
   2470  * Parameters:
   2471  *      unit -          (IN) SOC unit number.
   2472  *      extender_port - (IN) Pointer to VLAN virtual port structure.
   2473  *      vent -          (OUT) Pointer to a vlan_xlate entry.
   2474  * Returns:
   2475  *      BCM_X_XXX
   2476  */
   2477 STATIC int
   2478 _bcm_tr3_extender_match_key_assemble(
   2479     int                 unit,
   2480     bcm_extender_port_t *extender_port,
   2481     void  *vent)
   2482 {
   2483     int                   key_type;
   2484     bcm_module_t          mod_out;
   2485     bcm_port_t            port_out;
   2486     bcm_trunk_t           trunk_out;
   2487     int                   tmp_id;
   2488     soc_mem_t             mem = VLAN_XLATEm;
   2489 
   2490     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   2491         mem = VLAN_XLATE_1_DOUBLEm;
   2492         sal_memset(vent, 0, sizeof(vlan_xlate_1_double_entry_t));
   2493     } else {
   2494         sal_memset(vent, 0, sizeof(vlan_xlate_entry_t));
   2495     }
   2496 
   2497     if (soc_feature(unit, soc_feature_base_valid)) {
   2498         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
   2499         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
   2500     } else {
   2501         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
   2502     }
   2503 
   2504     if (extender_port->match_vlan == BCM_VLAN_NONE) {
   2505         BCM_IF_ERROR_RETURN(
   2506             _bcm_esw_vlan_xlate_key_type_value_get(
   2507                 unit, VLXLT_HASH_KEY_TYPE_VIF,&key_type));
   2508     } else {
   2509         if (!BCM_VLAN_VALID(extender_port->match_vlan)) {
   2510             return BCM_E_PARAM;
   2511         }
   2512         BCM_IF_ERROR_RETURN(
   2513             _bcm_esw_vlan_xlate_key_type_value_get(
   2514                 unit, VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type));
   2515         soc_mem_field32_set(unit, mem, vent, VIF__VLANf,
   2516                             extender_port->match_vlan);
   2517     }
   2518     soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type);
   2519     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   2520         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type);
   2521     }
   2522 
   2523     if (extender_port->extended_port_vid >=
   2524             (1 << soc_mem_field_length(unit, mem, VIF__SRC_VIFf))) {
   2525         return BCM_E_PARAM;
   2526     }
   2527     soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf,
   2528                         extender_port->extended_port_vid);
   2529 
   2530 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
   2531     if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) {
   2532         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
   2533     }
   2534 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
   2535     BCM_IF_ERROR_RETURN
   2536         (_bcm_esw_gport_resolve(unit, extender_port->port,
   2537                                 &mod_out, &port_out, &trunk_out, &tmp_id));
   2538     if (BCM_GPORT_IS_TRUNK(extender_port->port)) {
   2539         soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1);
   2540         soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out);
   2541     } else {
   2542         soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out);
   2543         soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out);
   2544     }
   2545 
   2546     return BCM_E_NONE;
   2547 }
   2548 
   2549 /*
   2550  * Function:
   2551  *      bcm_tr3_extender_match_key_get
   2552  * Purpose:
   2553  *      get a vlan_xlate key for extender match according to extender port id.
   2554  * Parameters:
   2555  *      unit -             (IN) SOC unit number.
   2556  *      extender_port_id - (IN) extender gport id.
   2557  *      vent -             (OUT) Pointer to a vlan_xlate entry.
   2558  * Returns:
   2559  *      BCM_X_XXX
   2560  */
   2561 int
   2562 bcm_tr3_extender_match_key_get(
   2563     int                 unit,
   2564     bcm_gport_t         extender_port_id,
   2565     void  *vent)
   2566 {
   2567     bcm_extender_port_t   extender_port;
   2568 
   2569     bcm_extender_port_t_init(&extender_port);
   2570     extender_port.extender_port_id = extender_port_id;
   2571     BCM_IF_ERROR_RETURN(
   2572         bcm_tr3_extender_port_get(unit, &extender_port));
   2573     return _bcm_tr3_extender_match_key_assemble(unit, &extender_port, vent);
   2574 }
   2575 
   2576 /*
   2577  * Function:
   2578  *      _bcm_tr3_extender_match_add
   2579  * Purpose:
   2580  *      Add match criteria for Extender VP.
   2581  * Parameters:
   2582  *      unit - (IN) SOC unit number. 
   2583  *      extender_port - (IN) Pointer to VLAN virtual port structure. 
   2584  *      vp - (IN) Virtual port number.
   2585  * Returns:
   2586  *      BCM_X_XXX
   2587  */
   2588 STATIC int
   2589 _bcm_tr3_extender_match_add(int unit, bcm_extender_port_t *extender_port,
   2590         int vp)
   2591 {
   2592     uint32                vent[SOC_MAX_MEM_FIELD_WORDS];
   2593     uint32                old_vent[SOC_MAX_MEM_FIELD_WORDS];
   2594     int                   key_type;
   2595     bcm_module_t          mod_out;
   2596     bcm_port_t            port_out;
   2597     bcm_trunk_t           trunk_out;
   2598     int                   tmp_id;
   2599     bcm_vlan_action_set_t action;
   2600     uint32                profile_idx;
   2601     int                   rv;
   2602     bcm_trunk_t           trunk_id;
   2603     int                   idx;
   2604     int                   mod_local;
   2605     int                   num_local_ports;
   2606     bcm_port_t            local_ports[SOC_MAX_NUM_PORTS];
   2607     int                   local_member_count;
   2608     bcm_port_t            local_member_array[SOC_MAX_NUM_PORTS];
   2609     int                   port_key_type_vif_vlan, port_key_type_vif;
   2610     int                   port_key_type_a, port_key_type_b;
   2611     int                   use_port_a, use_port_b;
   2612     int                   vt_enable;
   2613     soc_mem_t             mem = VLAN_XLATEm;
   2614 
   2615     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   2616         mem = VLAN_XLATE_1_DOUBLEm;
   2617     }
   2618     sal_memset(vent, 0, sizeof(vent));
   2619 
   2620     if (soc_feature(unit, soc_feature_base_valid)) {
   2621         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
   2622         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
   2623     } else {
   2624         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
   2625     }
   2626 
   2627     if (extender_port->match_vlan == BCM_VLAN_NONE) {
   2628         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   2629                     VLXLT_HASH_KEY_TYPE_VIF, &key_type));
   2630     } else {
   2631         if (!BCM_VLAN_VALID(extender_port->match_vlan)) {
   2632             return BCM_E_PARAM;
   2633         }
   2634         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   2635                     VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type));
   2636         soc_mem_field32_set(unit, mem, vent, VIF__VLANf,
   2637                 extender_port->match_vlan);
   2638     }
   2639     soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type);
   2640     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   2641         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type);
   2642     }
   2643 
   2644     if (extender_port->extended_port_vid >=
   2645             (1 << soc_mem_field_length(unit, mem, VIF__SRC_VIFf))) {
   2646         return BCM_E_PARAM;
   2647     }
   2648     soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf,
   2649             extender_port->extended_port_vid);
   2650 
   2651 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
   2652     if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) {
   2653         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
   2654     }
   2655 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
   2656     BCM_IF_ERROR_RETURN
   2657         (_bcm_esw_gport_resolve(unit, extender_port->port,
   2658                                 &mod_out, &port_out, &trunk_out, &tmp_id));
   2659     if (BCM_GPORT_IS_TRUNK(extender_port->port)) {
   2660         soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1);
   2661         soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out);
   2662     } else {
   2663         soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out);
   2664         soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out);
   2665     }
   2666 
   2667     /* SVP */
   2668     soc_mem_field32_set(unit, mem, vent, VIF__MPLS_ACTIONf,
   2669         ((extender_port->flags & BCM_EXTENDER_PORT_ID_ASSIGN_DISABLE) ? 0x0 : 0x1));
   2670     soc_mem_field32_set(unit, mem, vent, VIF__SOURCE_VPf, vp);
   2671 
   2672     bcm_vlan_action_set_t_init(&action);
   2673     if (BCM_VLAN_VALID(extender_port->match_vlan)) {
   2674         soc_mem_field32_set(unit, mem, vent, VIF__NEW_OVIDf,
   2675                             extender_port->match_vlan);
   2676         action.dt_outer = bcmVlanActionCopy;
   2677         action.dt_inner = bcmVlanActionDelete;
   2678         action.ot_outer = bcmVlanActionReplace;
   2679     } else {
   2680         action.ot_outer_prio = bcmVlanActionReplace;
   2681         action.ut_outer = bcmVlanActionAdd;
   2682     }
   2683     BCM_IF_ERROR_RETURN
   2684         (_bcm_trx_vlan_action_profile_entry_add(unit, &action, &profile_idx));
   2685     soc_mem_field32_set(unit, mem, vent, VIF__TAG_ACTION_PROFILE_PTRf,
   2686             profile_idx);
   2687 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
   2688     if (soc_mem_field_valid(unit, mem, VIF__VLAN_ACTION_VALIDf)) {
   2689         soc_mem_field32_set(unit, mem, vent, VIF__VLAN_ACTION_VALIDf, 1);
   2690     }
   2691 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
   2692 
   2693     rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL,
   2694             vent, old_vent);
   2695     if (rv == SOC_E_EXISTS) {
   2696         /* Delete the old vlan translate profile entry */
   2697         profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   2698                 VIF__TAG_ACTION_PROFILE_PTRf);
   2699         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   2700     }
   2701     BCM_IF_ERROR_RETURN(rv);
   2702 
   2703     num_local_ports = 0;
   2704     if (BCM_GPORT_IS_TRUNK(extender_port->port)) {
   2705         trunk_id = BCM_GPORT_TRUNK_GET(extender_port->port);
   2706         rv = _bcm_trunk_id_validate(unit, trunk_id);
   2707         if (BCM_FAILURE(rv)) {
   2708             return BCM_E_PORT;
   2709         }
   2710         rv = _bcm_esw_trunk_local_members_get(unit, trunk_id,
   2711                 SOC_MAX_NUM_PORTS, local_member_array, &local_member_count);
   2712         if (BCM_FAILURE(rv)) {
   2713             return BCM_E_PORT;
   2714         }
   2715         for (idx = 0; idx < local_member_count; idx++) {
   2716             local_ports[num_local_ports++] = local_member_array[idx];
   2717         }
   2718     } else {
   2719         BCM_IF_ERROR_RETURN
   2720             (_bcm_esw_gport_resolve(unit, extender_port->port, &mod_out, &port_out,
   2721                                     &trunk_id, &tmp_id)); 
   2722         if ((trunk_id != -1) || (tmp_id != -1)) {
   2723             return BCM_E_PARAM;
   2724         }
   2725         BCM_IF_ERROR_RETURN
   2726             (_bcm_esw_modid_is_local(unit, mod_out, &mod_local));
   2727         if (mod_local) {
   2728             local_ports[num_local_ports++] = port_out;
   2729         }
   2730     }
   2731 
   2732     BCM_IF_ERROR_RETURN(_bcm_esw_pt_vtkey_type_value_get(unit,
   2733                 VLXLT_HASH_KEY_TYPE_VIF_VLAN, &port_key_type_vif_vlan));
   2734     BCM_IF_ERROR_RETURN(_bcm_esw_pt_vtkey_type_value_get(unit,
   2735                 VLXLT_HASH_KEY_TYPE_VIF, &port_key_type_vif));
   2736     for (idx = 0; idx < num_local_ports; idx++) {
   2737         BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx],
   2738                     _bcmPortVTKeyTypeFirst, &port_key_type_a));
   2739         BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx],
   2740                     _bcmPortVTKeyPortFirst, &use_port_a));
   2741         BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx],
   2742                     _bcmPortVTKeyTypeSecond, &port_key_type_b));
   2743         BCM_IF_ERROR_RETURN(_bcm_esw_port_config_get(unit, local_ports[idx],
   2744                     _bcmPortVTKeyPortSecond, &use_port_b));
   2745 
   2746         if (BCM_VLAN_VALID(extender_port->match_vlan)) {
   2747             if ((port_key_type_a != port_key_type_vif_vlan) &&
   2748                     (port_key_type_b != port_key_type_vif_vlan)) {
   2749                 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2750                             local_ports[idx], _bcmPortVTKeyTypeFirst,
   2751                             port_key_type_vif_vlan));
   2752                 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2753                             local_ports[idx], _bcmPortVTKeyPortFirst, 1));
   2754                 if (port_key_type_a == port_key_type_vif) {
   2755                     /* The first slot contained VIF key type, which
   2756                      * was just overwritten by VIF_VLAN key type. Hence,
   2757                      * the VIF key type needs to be moved to second slot.
   2758                      */
   2759                     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2760                                 local_ports[idx], _bcmPortVTKeyTypeSecond,
   2761                                 port_key_type_a));
   2762                     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2763                                 local_ports[idx], _bcmPortVTKeyPortSecond,
   2764                                 use_port_a));
   2765                 }
   2766             }
   2767         } else {
   2768             if ((port_key_type_a != port_key_type_vif) &&
   2769                     (port_key_type_b != port_key_type_vif)) {
   2770                 if (port_key_type_a != port_key_type_vif_vlan) {
   2771                     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2772                                 local_ports[idx], _bcmPortVTKeyTypeFirst,
   2773                                 port_key_type_vif));
   2774                     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2775                                 local_ports[idx], _bcmPortVTKeyPortFirst, 1));
   2776                 } else {
   2777                     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2778                                 local_ports[idx], _bcmPortVTKeyTypeSecond,
   2779                                 port_key_type_vif));
   2780                     BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit,
   2781                                 local_ports[idx], _bcmPortVTKeyPortSecond, 1));
   2782                 }
   2783             }
   2784         }
   2785 
   2786         /* Enable ingress VLAN translation */
   2787         BCM_IF_ERROR_RETURN
   2788             (_bcm_esw_port_config_get(unit, local_ports[idx],
   2789                                       _bcmPortVlanTranslate, &vt_enable));
   2790         if (!vt_enable) {
   2791             BCM_IF_ERROR_RETURN
   2792                 (_bcm_esw_port_config_set(unit, local_ports[idx],
   2793                                           _bcmPortVlanTranslate, 1));
   2794         }
   2795 
   2796         if (BCM_VLAN_VALID(extender_port->match_vlan)) {
   2797             /* Enable egress VLAN translation */
   2798 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   2799             if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) {
   2800                 if (soc_feature(unit, soc_feature_egr_all_profile)) {
   2801                     BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_set(unit,
   2802                         local_ports[idx], EGR_VLAN_CONTROL_1m, VT_ENABLEf, 1));
   2803                 } else {
   2804                     SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit,
   2805                         EGR_VLAN_CONTROL_1m, local_ports[idx], VT_ENABLEf, 1));
   2806                 }
   2807             } else
   2808 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   2809             {
   2810                 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit,
   2811                             EGR_VLAN_CONTROL_1r, local_ports[idx], VT_ENABLEf, 1));
   2812             }
   2813         }
   2814     }
   2815 
   2816     return BCM_E_NONE;
   2817 }
   2818 
   2819 /*
   2820  * Function:
   2821  *      _bcm_tr3_extender_match_delete
   2822  * Purpose:
   2823  *      Delete match criteria for Extender VP.
   2824  * Parameters:
   2825  *      unit   - (IN) SOC unit number.
   2826  *      vp     - (IN) Virtual port number.
   2827  *      old_vp - (OUT) Pointer to the old virtual port number of the entry.
   2828  * Returns:
   2829  *      BCM_X_XXX
   2830  */
   2831 STATIC int
   2832 _bcm_tr3_extender_match_delete(int unit, int vp, int *old_vp)
   2833 {
   2834     uint32             vent[SOC_MAX_MEM_FIELD_WORDS];
   2835     uint32             old_vent[SOC_MAX_MEM_FIELD_WORDS];
   2836     int                key_type;
   2837     bcm_module_t       mod_out;
   2838     bcm_port_t         port_out;
   2839     bcm_trunk_t        trunk_out;
   2840     int                tmp_id;
   2841     uint32             profile_idx;
   2842     int                rv;
   2843     soc_mem_t          mem = VLAN_XLATEm;
   2844 
   2845     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   2846         mem = VLAN_XLATE_1_DOUBLEm;
   2847     }
   2848     sal_memset(vent, 0, sizeof(vent));
   2849 
   2850     if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) {
   2851         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   2852                     VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type));
   2853         soc_mem_field32_set(unit, mem, vent, VIF__VLANf,
   2854                 EXTENDER_PORT_INFO(unit, vp)->match_vlan);
   2855     } else {
   2856         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   2857                     VLXLT_HASH_KEY_TYPE_VIF, &key_type));
   2858     }
   2859     soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type);
   2860     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   2861         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type);
   2862     }
   2863 
   2864     soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf,
   2865             EXTENDER_PORT_INFO(unit, vp)->extended_port_vid);
   2866 
   2867 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
   2868     if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) {
   2869         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
   2870     }
   2871 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
   2872     BCM_IF_ERROR_RETURN
   2873         (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port,
   2874                                 &mod_out, &port_out, &trunk_out, &tmp_id));
   2875     if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) {
   2876         soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1);
   2877         soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out);
   2878     } else {
   2879         soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out);
   2880         soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out);
   2881     }
   2882 
   2883     rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL,
   2884                                    vent, old_vent);
   2885     if (rv == SOC_E_NONE) {
   2886         uint32 is_valid = 0;
   2887         if (soc_feature(unit, soc_feature_base_valid)) {
   2888             is_valid =
   2889                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 &&
   2890                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7;
   2891         } else {
   2892             is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf);
   2893         }
   2894         if (is_valid) {
   2895             if (old_vp != NULL) {
   2896                 *old_vp = soc_mem_field32_get(unit, mem, old_vent,
   2897                                               VIF__SOURCE_VPf);
   2898             }
   2899             profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   2900                                               VIF__TAG_ACTION_PROFILE_PTRf);
   2901             /* Delete the old vlan action profile entry */
   2902             rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   2903         }
   2904     }
   2905 
   2906     return rv;
   2907 }
   2908 
   2909 
   2910 /*
   2911  * Function:
   2912  *      _bcm_tr3_extender_port_match_add
   2913  * Purpose:
   2914  *      Add a match to an existing port.
   2915  * Parameters:
   2916  *      unit -             (IN) SOC unit number. 
   2917  *      port -             (IN) port of match criteria.
   2918  *      extended_port_vid -(IN) extended_port_vid of match criteria.
   2919  *      vlan -             (IN) vlan of match criteria.
   2920  *      vp -               (IN) the vp of match destination.
   2921  * Returns:
   2922  *      BCM_X_XXX
   2923  */
   2924 int
   2925 _bcm_tr3_extender_port_match_add(int unit, bcm_gport_t port,
   2926                                  uint16 extended_port_vid,
   2927                                   bcm_vlan_t vlan, int vp)
   2928 {
   2929     bcm_extender_port_t  extender_port;
   2930     
   2931     bcm_extender_port_t_init(&extender_port);
   2932     extender_port.port = port;
   2933     extender_port.match_vlan = vlan;
   2934     extender_port.extended_port_vid = extended_port_vid;
   2935 
   2936     return _bcm_tr3_extender_match_add(unit, &extender_port, vp);    
   2937 }
   2938 
   2939 /*
   2940  * Function:
   2941  *      _bcm_tr3_extender_port_match_delete
   2942  * Purpose:
   2943  *      delete a match from an existing vp.
   2944  * Parameters:
   2945  *      unit -             (IN) SOC unit number. 
   2946  *      port -             (IN) port of match criteria.
   2947  *      extender_port_vid -(IN) extended_port_vid of match criteria.
   2948  *      vlan -             (IN) vlan of match criteria.
   2949  *      vp -               (IN) the vp of match destination.
   2950  * Returns:
   2951  *      BCM_X_XXX
   2952  */
   2953 int
   2954 _bcm_tr3_extender_port_match_delete(int unit, bcm_gport_t port,
   2955                                     uint16 extended_port_vid,
   2956                                     bcm_vlan_t vlan, int vp)
   2957 {
   2958     uint32             vent[SOC_MAX_MEM_FIELD_WORDS];
   2959     uint32             old_vent[SOC_MAX_MEM_FIELD_WORDS];
   2960     int                key_type;
   2961     bcm_module_t       mod_out;
   2962     bcm_port_t         port_out;
   2963     bcm_trunk_t        trunk_out;
   2964     int                tmp_id;
   2965     uint32             profile_idx;
   2966     int                rv;
   2967     int                old_vp;
   2968     int                entry_index;
   2969     soc_mem_t          mem = VLAN_XLATEm;
   2970 
   2971     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   2972         mem = VLAN_XLATE_1_DOUBLEm;
   2973     }
   2974     sal_memset(vent, 0, sizeof(vent));
   2975 
   2976     if (BCM_VLAN_VALID(vlan)) {
   2977         BCM_IF_ERROR_RETURN(
   2978             _bcm_esw_vlan_xlate_key_type_value_get(unit,
   2979                                                    VLXLT_HASH_KEY_TYPE_VIF_VLAN,
   2980                                                    &key_type));
   2981         soc_mem_field32_set(unit, mem, vent, VIF__VLANf, vlan);
   2982     } else {
   2983         BCM_IF_ERROR_RETURN(
   2984             _bcm_esw_vlan_xlate_key_type_value_get(unit,
   2985                                                    VLXLT_HASH_KEY_TYPE_VIF,
   2986                                                    &key_type));
   2987     }
   2988     soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type);
   2989     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   2990         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, key_type);
   2991     }
   2992 
   2993     soc_mem_field32_set(unit, mem, vent, VIF__SRC_VIFf, extended_port_vid);
   2994 
   2995 #if defined( BCM_TRIDENT2_SUPPORT) || defined(BCM_PE_SUPPORT)
   2996     if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) {
   2997         soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
   2998     }
   2999 #endif /* BCM_TRIDENT2_SUPPORT || BCM_PE_SUPPORT */
   3000     BCM_IF_ERROR_RETURN
   3001         (_bcm_esw_gport_resolve(unit, port, &mod_out,
   3002                                 &port_out, &trunk_out, &tmp_id));
   3003     if (BCM_GPORT_IS_TRUNK(port)) {
   3004         soc_mem_field32_set(unit, mem, vent, VIF__Tf, 1);
   3005         soc_mem_field32_set(unit, mem, vent, VIF__TGIDf, trunk_out);
   3006     } else {
   3007         soc_mem_field32_set(unit, mem, vent, VIF__MODULE_IDf, mod_out);
   3008         soc_mem_field32_set(unit, mem, vent, VIF__PORT_NUMf, port_out);
   3009     }
   3010 
   3011     soc_mem_lock(unit, mem);
   3012     rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, &entry_index,
   3013                         vent, old_vent, 0);
   3014     if (SOC_FAILURE(rv)) {
   3015         soc_mem_unlock(unit, mem);
   3016         return rv;
   3017     }
   3018 
   3019     old_vp = soc_mem_field32_get(unit, mem, old_vent, VIF__SOURCE_VPf);
   3020     if (vp != old_vp) {
   3021         soc_mem_unlock(unit, mem);
   3022         return BCM_E_NOT_FOUND;
   3023     }
   3024 
   3025     rv = soc_mem_delete_return_old(unit, mem,
   3026                                    MEM_BLOCK_ALL, vent, old_vent);
   3027     soc_mem_unlock(unit, mem);
   3028     if (rv == SOC_E_NONE) {
   3029         uint32 is_valid = 0;
   3030         if (soc_feature(unit, soc_feature_base_valid)) {
   3031             is_valid =
   3032                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 &&
   3033                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7;
   3034         } else {
   3035             is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf);
   3036         }
   3037         if (is_valid) {
   3038             profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   3039                                               VIF__TAG_ACTION_PROFILE_PTRf);
   3040             /* Delete the old vlan action profile entry */
   3041             rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   3042         }
   3043     }
   3044 
   3045     return rv;
   3046 }
   3047 
   3048 /*
   3049  * Function:
   3050  *      bcm_tr3_extender_port_add
   3051  * Purpose:
   3052  *      Create an Extender port on Controlling Bridge.
   3053  * Parameters:
   3054  *      unit - (IN) SOC unit number. 
   3055  *      extender_port - (IN/OUT) Extender port information
   3056  * Returns:
   3057  *      BCM_X_XXX
   3058  */
   3059 int
   3060 bcm_tr3_extender_port_add(int unit,
   3061                          bcm_extender_port_t *extender_port)
   3062 {
   3063     int mode;
   3064     int vp, old_vp = 0, matched_vp;
   3065     int rv = BCM_E_NONE;
   3066     int num_vp;
   3067     int nh_index = 0;
   3068     bcm_if_t intf;
   3069     ing_dvp_table_entry_t dvp_entry;
   3070     source_vp_entry_t svp_entry;
   3071     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
   3072     int drop;
   3073     _bcm_vp_info_t vp_info;
   3074 
   3075     _bcm_vp_info_init(&vp_info);
   3076     vp_info.vp_type = _bcmVpTypeExtender;
   3077 
   3078     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode));
   3079     if (!mode) {
   3080         LOG_INFO(BSL_LS_BCM_L3,
   3081                  (BSL_META_U(unit,
   3082                              "L3 egress mode must be set first\n")));
   3083         return BCM_E_DISABLED;
   3084     }
   3085 
   3086     if ((!soc_feature(unit, soc_feature_port_extender_vp_sharing)) &&
   3087         (extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   3088         return BCM_E_UNAVAIL;
   3089     }
   3090 
   3091     /* Check for invalid flag combinations */
   3092     if (extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE) {
   3093         if ((extender_port->flags & BCM_EXTENDER_PORT_REPLACE) ||
   3094             (extender_port->flags & BCM_EXTENDER_PORT_MULTICAST)) {
   3095             return BCM_E_PARAM;
   3096         }
   3097     }
   3098 
   3099     if (!(extender_port->flags & BCM_EXTENDER_PORT_REPLACE)) {
   3100         /* Create new Extender VP */
   3101 
   3102         if (extender_port->flags & BCM_EXTENDER_PORT_WITH_ID) {
   3103             if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port->extender_port_id)) {
   3104                 return BCM_E_PARAM;
   3105             }
   3106             vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port->extender_port_id);
   3107             if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) {
   3108                 return BCM_E_PARAM;
   3109             }
   3110             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   3111                 return BCM_E_EXISTS;
   3112             } else {
   3113                 rv = _bcm_vp_used_set(unit, vp, vp_info);
   3114                 if (rv < 0) {
   3115                     return rv;
   3116                 }
   3117             }
   3118         } else {
   3119             /* allocate a new VP index */
   3120             num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   3121             rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm,
   3122                     vp_info, &vp);
   3123             if (rv < 0) {
   3124                 return rv;
   3125             }
   3126         }
   3127 
   3128         if (extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE) {
   3129             /* For a EXTENDER port without any match criteria, an invalid
   3130                       * next hop index will be written to the ING_DVP_TABLE.
   3131                       */
   3132             nh_index = EXTENDER_INFO(unit)->invalid_next_hop_index;
   3133         } else {
   3134             /* Configure next hop tables */
   3135             drop = (extender_port->flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0;
   3136             rv = _bcm_tr3_extender_nh_info_set(unit, extender_port, NULL, vp, drop,
   3137                                               &nh_index);
   3138             if (rv < 0) {
   3139                 goto cleanup;
   3140             }
   3141         }
   3142 
   3143         /* Configure DVP table */
   3144         intf = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   3145         rv = _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigSet, vp,
   3146                                     ING_DVP_CONFIG_INVALID_VP_TYPE, intf,
   3147                                     ING_DVP_CONFIG_INVALID_PORT_TYPE);
   3148         if (rv < 0) {
   3149             goto cleanup;
   3150         }
   3151 
   3152         /* Configure SVP table */
   3153         sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t));
   3154         soc_SOURCE_VPm_field32_set(unit, &svp_entry, ENTRY_TYPEf, 3);
   3155 
   3156         /* Set the CML */
   3157         rv = _bcm_vp_default_cml_mode_get(unit, &cml_default_enable,
   3158                 &cml_default_new, &cml_default_move);
   3159         if (rv < 0) {
   3160             goto cleanup;
   3161         }
   3162         if (cml_default_enable) {
   3163             /* Set the CML to default values */
   3164             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf,
   3165                     cml_default_new);
   3166             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf,
   3167                     cml_default_move);
   3168         } else {
   3169             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
   3170             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf, 0x8);
   3171             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf, 0x8);
   3172         }
   3173 
   3174         /* Set the TPID_SOURCE based on SGLP */
   3175         if (soc_mem_field_valid(unit, SOURCE_VPm, TPID_SOURCEf)) {
   3176             soc_SOURCE_VPm_field32_set(unit, &svp_entry, TPID_SOURCEf, 2);
   3177         }
   3178 
   3179         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry);
   3180         if (rv < 0) {
   3181             goto cleanup;
   3182         }
   3183 
   3184         /* Configure SOURCE_VP_2 table */
   3185 #ifdef BCM_TRIDENT2_SUPPORT
   3186         if (soc_mem_field_valid(unit, SOURCE_VP_2m, PARSE_USING_SGLP_TPIDf)) {
   3187             source_vp_2_entry_t svp_2_entry;
   3188 
   3189             sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
   3190             soc_SOURCE_VP_2m_field32_set(unit, &svp_2_entry, PARSE_USING_SGLP_TPIDf, 1);
   3191             rv = WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry);
   3192             if (rv < 0) {
   3193                 goto cleanup;
   3194             }
   3195         }
   3196 #endif /* BCM_TRIDENT2_SUPPORT */
   3197 
   3198         if (!(extender_port->flags & BCM_EXTENDER_PORT_MULTICAST)
   3199             && (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE))) {
   3200             /* Configure ingress VLAN translation table for unicast VPs */
   3201            rv = _bcm_tr3_extender_match_add(unit, extender_port, vp);
   3202            if (rv < 0) {
   3203                goto cleanup;
   3204            }
   3205        }
   3206 
   3207         /* Configure the failover information */
   3208         if (BCM_SUCCESS(_bcm_esw_failover_extender_check(unit, 
   3209                                                          extender_port))) {
   3210             rv = _bcm_tr3_extender_failover_add(unit, extender_port, vp);
   3211             if (rv < 0) {
   3212                 goto cleanup;
   3213             }
   3214         }
   3215 
   3216         if (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   3217 
   3218             /* Increment port's VP count */
   3219             rv = _bcm_tr3_extender_port_cnt_update(unit, extender_port->port, vp, TRUE);
   3220             if (rv < 0) {
   3221                 goto cleanup;
   3222             }
   3223         }
   3224 
   3225     } else { /* Replace properties of existing Extender VP */
   3226 
   3227         if (!(extender_port->flags & BCM_EXTENDER_PORT_WITH_ID)) {
   3228             return BCM_E_PARAM;
   3229         }
   3230         if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port->extender_port_id)) {
   3231             return BCM_E_PARAM;
   3232         }
   3233         vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port->extender_port_id);
   3234         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   3235             return BCM_E_PARAM;
   3236         }
   3237 
   3238         /* For existing Extender vp, NH entry already exists */
   3239         BCM_IF_ERROR_RETURN
   3240             (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   3241         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
   3242                 NEXT_HOP_INDEXf);
   3243 
   3244         /* Update existing next hop entries */
   3245         drop = (extender_port->flags & BCM_EXTENDER_PORT_DROP) ? 1 : 0;
   3246         BCM_IF_ERROR_RETURN
   3247             (_bcm_tr3_extender_nh_info_set(unit, extender_port, NULL, vp, drop,
   3248                                            &nh_index));
   3249 
   3250         /* Delete old ingress VLAN translation entry,
   3251                * install new ingress VLAN translation entry
   3252                */
   3253         if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MULTICAST)
   3254             && (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE))) {
   3255             BCM_IF_ERROR_RETURN(
   3256                 _bcm_tr3_extender_match_delete(unit, vp, &old_vp));
   3257         }
   3258         if (!(extender_port->flags & BCM_EXTENDER_PORT_MULTICAST)) {
   3259 #ifdef BCM_TRIDENT2_SUPPORT
   3260             /* The extender port id may be one of members of a vplag. */
   3261             if (_bcm_vp_used_get(unit, old_vp, _bcmVpTypeVpLag)) {
   3262                 matched_vp = old_vp;
   3263             } else
   3264 #endif /* BCM_TRIDENT2_SUPPORT */
   3265             {
   3266                 matched_vp = vp;
   3267             }
   3268             BCM_IF_ERROR_RETURN
   3269                 (_bcm_tr3_extender_match_add(unit, extender_port, matched_vp));
   3270         }
   3271 
   3272         /* Configure the failover information */
   3273         if (BCM_SUCCESS(_bcm_esw_failover_extender_check(unit, 
   3274                                                          extender_port))) {
   3275             BCM_IF_ERROR_RETURN
   3276                 (_bcm_tr3_extender_failover_add(unit, extender_port, vp));
   3277         } else {
   3278             /* remove the failover configuration if found*/
   3279             bcm_gport_t gport = extender_port->extender_port_id;
   3280             if (BCM_SUCCESS(_bcm_tr3_extender_failover_get(unit, gport, 
   3281                                                            NULL, NULL, NULL))) {
   3282                 BCM_IF_ERROR_RETURN
   3283                     (_bcm_tr3_extender_failover_delete(unit, gport));
   3284             }
   3285         }
   3286 
   3287         /* Decrement old port's VP count, increment new port's VP count */
   3288         BCM_IF_ERROR_RETURN
   3289             (_bcm_tr3_extender_port_cnt_update(unit,
   3290                 EXTENDER_PORT_INFO(unit, vp)->port, vp, FALSE));
   3291         BCM_IF_ERROR_RETURN
   3292             (_bcm_tr3_extender_port_cnt_update(unit,
   3293                 EXTENDER_PORT_INFO(unit, vp)->port, vp, TRUE));
   3294     }
   3295 
   3296     /* Set Extender VP software state */
   3297     EXTENDER_PORT_INFO(unit, vp)->flags = extender_port->flags;
   3298     EXTENDER_PORT_INFO(unit, vp)->port = extender_port->port;
   3299     EXTENDER_PORT_INFO(unit, vp)->extended_port_vid =
   3300         extender_port->extended_port_vid;
   3301     EXTENDER_PORT_INFO(unit, vp)->pcp_de_select = extender_port->pcp_de_select;
   3302     EXTENDER_PORT_INFO(unit, vp)->qos_map_id = extender_port->qos_map_id;
   3303     EXTENDER_PORT_INFO(unit, vp)->pcp = extender_port->pcp;
   3304     EXTENDER_PORT_INFO(unit, vp)->de = extender_port->de;
   3305     EXTENDER_PORT_INFO(unit, vp)->match_vlan = extender_port->match_vlan;
   3306 
   3307     BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port->extender_port_id, vp);
   3308 
   3309     return rv;
   3310 
   3311 cleanup:
   3312     if (!(extender_port->flags & BCM_EXTENDER_PORT_REPLACE)) {
   3313         (void) _bcm_vp_free(unit, _bcmVpTypeExtender, 1, vp);
   3314 
   3315         if (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   3316             _bcm_tr3_extender_nh_info_delete(unit, nh_index);
   3317         }
   3318 
   3319         (void)_bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp, 
   3320                                      ING_DVP_CONFIG_INVALID_VP_TYPE, 
   3321                                      ING_DVP_CONFIG_INVALID_INTF_ID, 
   3322                                      ING_DVP_CONFIG_INVALID_PORT_TYPE);
   3323 
   3324         sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t));
   3325         (void)WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry);
   3326 
   3327 #ifdef BCM_TRIDENT2_SUPPORT
   3328         if (soc_mem_is_valid(unit, SOURCE_VP_2m)) {
   3329             source_vp_2_entry_t svp_2_entry;
   3330 
   3331             sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
   3332             (void)WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry);
   3333         }
   3334 #endif /* BCM_TRIDENT2_SUPPORT */
   3335 
   3336         if (!(extender_port->flags & BCM_EXTENDER_PORT_MULTICAST)
   3337             && (!(extender_port->flags & BCM_EXTENDER_PORT_MATCH_NONE))) {
   3338             (void) _bcm_tr3_extender_match_delete(unit, vp, NULL);
   3339         }
   3340     }
   3341 
   3342     return rv;
   3343 }
   3344 
   3345 /*
   3346  * Function:
   3347  *      bcm_tr3_extender_port_delete
   3348  * Purpose:
   3349  *      Destroy a Extender virtual port.
   3350  * Parameters:
   3351  *      unit - (IN) SOC unit number. 
   3352  *      gport - (IN) Extender GPORT ID.
   3353  * Returns:
   3354  *      BCM_X_XXX
   3355  */
   3356 int
   3357 bcm_tr3_extender_port_delete(int unit, bcm_gport_t gport)
   3358 {
   3359     int vp;
   3360     source_vp_entry_t svp_entry;
   3361     int nh_index;
   3362     ing_dvp_table_entry_t dvp_entry;
   3363 
   3364     if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   3365         return BCM_E_PARAM;
   3366     }
   3367 
   3368     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   3369     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   3370         return BCM_E_NOT_FOUND;
   3371     }
   3372     if (EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE) {
   3373         if (EXTENDER_PORT_INFO(unit, vp)->egress_list != NULL) {
   3374             /* There are still EXTENDER egress objects attached to this
   3375              * EXTENDER port.
   3376              */
   3377             return BCM_E_BUSY;
   3378         }
   3379     }
   3380     /* Delete failover information if found */
   3381     if (BCM_SUCCESS(_bcm_tr3_extender_failover_get(unit, gport, 
   3382                                                    NULL, NULL, NULL))) {
   3383         BCM_IF_ERROR_RETURN
   3384             (_bcm_tr3_extender_failover_delete(unit, gport));
   3385     }
   3386 
   3387     /* Delete ingress VLAN translation entry */
   3388     if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MULTICAST)
   3389         && (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE))
   3390     ) {
   3391         BCM_IF_ERROR_RETURN
   3392             (_bcm_tr3_extender_match_delete(unit, vp, NULL));
   3393     }
   3394 
   3395     /* Clear SVP entry */
   3396     sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t));
   3397     BCM_IF_ERROR_RETURN
   3398         (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry));
   3399 
   3400     /* Clear SOURCE_VP_2 entry */
   3401 #ifdef BCM_TRIDENT2_SUPPORT
   3402     if (soc_mem_is_valid(unit, SOURCE_VP_2m)) {
   3403         source_vp_2_entry_t svp_2_entry;
   3404 
   3405         sal_memset(&svp_2_entry, 0, sizeof(source_vp_2_entry_t));
   3406         BCM_IF_ERROR_RETURN
   3407             (WRITE_SOURCE_VP_2m(unit, MEM_BLOCK_ALL, vp, &svp_2_entry));
   3408     }
   3409 #endif /* BCM_TRIDENT2_SUPPORT */
   3410 
   3411     /* Clear DVP entry */
   3412     BCM_IF_ERROR_RETURN
   3413         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   3414     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, NEXT_HOP_INDEXf);
   3415     BCM_IF_ERROR_RETURN(
   3416         _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp, 
   3417                                ING_DVP_CONFIG_INVALID_VP_TYPE, 
   3418                                ING_DVP_CONFIG_INVALID_INTF_ID, 
   3419                                ING_DVP_CONFIG_INVALID_PORT_TYPE));
   3420     if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   3421         /* Clear next hop entries and free next hop index */
   3422         BCM_IF_ERROR_RETURN
   3423             (_bcm_tr3_extender_nh_info_delete(unit, nh_index));
   3424 
   3425         /* Decrement port's VP count */
   3426         BCM_IF_ERROR_RETURN
   3427             (_bcm_tr3_extender_port_cnt_update(unit,
   3428                                                EXTENDER_PORT_INFO(unit, vp)->port,
   3429                                                vp, FALSE));
   3430     }
   3431     /* Free VP */
   3432     BCM_IF_ERROR_RETURN
   3433         (_bcm_vp_free(unit, _bcmVpTypeExtender, 1, vp));
   3434 
   3435     /* Clear Extender VP software state */
   3436     sal_memset(EXTENDER_PORT_INFO(unit, vp), 0,
   3437             sizeof(_bcm_tr3_extender_port_info_t));
   3438 
   3439     return BCM_E_NONE;
   3440 }
   3441 
   3442 /*
   3443  * Function:
   3444  *      bcm_tr3_extender_port_delete_all
   3445  * Purpose:
   3446  *      Destroy all Extender virtual ports.
   3447  * Parameters:
   3448  *      unit - (IN) SOC unit number. 
   3449  * Returns:
   3450  *      BCM_X_XXX
   3451  */
   3452 int
   3453 bcm_tr3_extender_port_delete_all(int unit)
   3454 {
   3455     int i;
   3456     bcm_gport_t extender_port_id;
   3457 
   3458     for (i = soc_mem_index_min(unit, SOURCE_VPm);
   3459          i <= soc_mem_index_max(unit, SOURCE_VPm);
   3460          i++) {
   3461         if (_bcm_vp_used_get(unit, i, _bcmVpTypeExtender)) {
   3462             BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port_id, i);
   3463             BCM_IF_ERROR_RETURN
   3464                 (bcm_tr3_extender_port_delete(unit, extender_port_id));
   3465         }
   3466     }
   3467 
   3468     return BCM_E_NONE;
   3469 }
   3470 
   3471 /*
   3472  * Function:
   3473  *      bcm_tr3_extender_port_get
   3474  * Purpose:
   3475  *      Get Extender virtual port info.
   3476  * Parameters:
   3477  *      unit - (IN) SOC unit number. 
   3478  *      extender_port - (IN/OUT) Pointer to Extender virtual port structure. 
   3479  * Returns:
   3480  *      BCM_X_XXX
   3481  */
   3482 int
   3483 bcm_tr3_extender_port_get(int unit, bcm_extender_port_t *extender_port)
   3484 {
   3485     int rv, vp;
   3486 
   3487     if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port->extender_port_id)) {
   3488         return BCM_E_PARAM;
   3489     }
   3490 
   3491     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port->extender_port_id);
   3492     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   3493         return BCM_E_NOT_FOUND;
   3494     }
   3495 
   3496     bcm_extender_port_t_init(extender_port);
   3497     extender_port->flags = EXTENDER_PORT_INFO(unit, vp)->flags;
   3498     BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port->extender_port_id, vp);
   3499     extender_port->port = EXTENDER_PORT_INFO(unit, vp)->port;
   3500     extender_port->extended_port_vid = EXTENDER_PORT_INFO(unit, vp)->
   3501                                        extended_port_vid;
   3502     extender_port->pcp_de_select = EXTENDER_PORT_INFO(unit, vp)->pcp_de_select;
   3503     extender_port->qos_map_id = EXTENDER_PORT_INFO(unit, vp)->qos_map_id;
   3504     extender_port->pcp = EXTENDER_PORT_INFO(unit, vp)->pcp;
   3505     extender_port->de = EXTENDER_PORT_INFO(unit, vp)->de;
   3506     extender_port->match_vlan = EXTENDER_PORT_INFO(unit, vp)->match_vlan;
   3507 
   3508     rv = _bcm_tr3_extender_failover_get(unit, extender_port->extender_port_id,
   3509                                         &extender_port->failover_port_id,
   3510                                         &extender_port->failover_id,
   3511                                         &extender_port->failover_mc_group);
   3512     if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND && rv != BCM_E_UNAVAIL) {
   3513         return rv;
   3514     }
   3515 
   3516     return BCM_E_NONE;
   3517 }
   3518 
   3519 /*
   3520  * Function:
   3521  *      bcm_tr3_extender_port_traverse
   3522  * Purpose:
   3523  *      Traverse all Extender ports and call supplied callback routine.
   3524  * Parameters:
   3525  *      unit      - (IN) Device Number
   3526  *      cb        - (IN) User-provided callback
   3527  *      user_data - (IN/OUT) Cookie
   3528  * Returns:
   3529  *      BCM_E_XXX
   3530  */
   3531 int
   3532 bcm_tr3_extender_port_traverse(int unit, bcm_extender_port_traverse_cb cb, 
   3533                                   void *user_data)
   3534 {
   3535     int i;
   3536     bcm_extender_port_t extender_port;
   3537 
   3538     for (i = soc_mem_index_min(unit, SOURCE_VPm);
   3539          i <= soc_mem_index_max(unit, SOURCE_VPm);
   3540          i++) {
   3541         if (_bcm_vp_used_get(unit, i, _bcmVpTypeExtender)) {
   3542             bcm_extender_port_t_init(&extender_port);
   3543             BCM_GPORT_EXTENDER_PORT_ID_SET(extender_port.extender_port_id, i);
   3544             BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port));
   3545             BCM_IF_ERROR_RETURN(cb(unit, &extender_port, user_data));
   3546         }
   3547     }
   3548 
   3549     return BCM_E_NONE;
   3550 }
   3551 
   3552 /*
   3553  * Function:
   3554  *      _bcm_tr3_extender_port_resolve
   3555  * Purpose:
   3556  *      Get the modid, port, trunk values for a Extender virtual port
   3557  * Parameters:
   3558  *      unit     - (IN) BCM device number
   3559  *      gport    - (IN) Global port identifier
   3560  *      modid    - (OUT) Module ID
   3561  *      port     - (OUT) Port number
   3562  *      trunk_id - (OUT) Trunk ID
   3563  *      id       - (OUT) Virtual port ID
   3564  * Returns:
   3565  *      BCM_E_XXX
   3566  */
   3567 int
   3568 _bcm_tr3_extender_port_resolve(int unit, bcm_gport_t extender_port_id,
   3569                           bcm_module_t *modid, bcm_port_t *port,
   3570                           bcm_trunk_t *trunk_id, int *id)
   3571 
   3572 {
   3573     int rv = BCM_E_NONE, nh_index, vp;
   3574     ing_l3_next_hop_entry_t ing_nh;
   3575     ing_dvp_table_entry_t dvp;
   3576     uint32 dv, dt = SOC_MEM_FIF_DEST_INVALID;
   3577 
   3578     if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port_id)) {
   3579         return (BCM_E_BADID);
   3580     }
   3581 
   3582     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port_id);
   3583     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   3584         return BCM_E_NOT_FOUND;
   3585     }
   3586     BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   3587     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   3588                                               NEXT_HOP_INDEXf);
   3589     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   3590                                       nh_index, &ing_nh));
   3591 
   3592     if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) {
   3593         /* Entry type is not L2 DVP */
   3594         return BCM_E_NOT_FOUND;
   3595     }
   3596 
   3597     if (soc_feature(unit, soc_feature_generic_dest)) {
   3598         dv = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, &ing_nh,
   3599                                       DESTINATIONf, &dt);
   3600         if (dt == SOC_MEM_FIF_DEST_LAG) {
   3601             *trunk_id = dv;
   3602         } else {
   3603             *port = dv & SOC_MEM_FIF_DGPP_PORT_MASK;
   3604             *modid = (dv & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   3605                         SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   3606         }
   3607     } else {
   3608         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   3609             *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   3610         } else {
   3611             *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   3612             *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   3613         }
   3614     }
   3615     *id = vp;
   3616     return rv;
   3617 }
   3618 
   3619 /*
   3620  * Purpose:
   3621  *	Add a downstream forwarding entry
   3622  * Parameters:
   3623  *	unit - (IN) Device Number
   3624  *	forward_entry - (IN) Forwarding entry
   3625  */
   3626 int
   3627 bcm_tr3_extender_forward_add(int unit, bcm_extender_forward_t *forward_entry)
   3628 {
   3629     int rv = BCM_E_NONE;
   3630     bcm_module_t mod_out;
   3631     bcm_port_t port_out;
   3632     bcm_trunk_t tgid_out;
   3633     int id_out;
   3634     l2_entry_1_entry_t l2_entry;
   3635     int lower_th, higher_th;
   3636 
   3637     if (forward_entry->name_space > 0xfff) {
   3638         return BCM_E_PARAM;
   3639     }
   3640 
   3641     BCM_IF_ERROR_RETURN(
   3642         bcm_esw_switch_control_get(unit,
   3643                                    bcmSwitchExtenderMulticastLowerThreshold,
   3644                                    &lower_th));
   3645     BCM_IF_ERROR_RETURN(
   3646         bcm_esw_switch_control_get(unit,
   3647                                    bcmSwitchExtenderMulticastHigherThreshold, 
   3648                                    &higher_th));
   3649 
   3650     if ((forward_entry->extended_port_vid >=
   3651          (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__ETAG_VIDf))) ||
   3652         (forward_entry->class_id >=
   3653          (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__CLASS_IDf)))) {
   3654         return BCM_E_PARAM;
   3655     }
   3656 
   3657     if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) {
   3658          if (forward_entry->extended_port_vid >=
   3659             (1 << soc_mem_field_length(unit, L2_ENTRY_1m,
   3660                                        PE_VID__ETAG_VIDf))) {
   3661             return BCM_E_PARAM;
   3662         }
   3663 
   3664         if ((forward_entry->extended_port_vid >= lower_th) &&
   3665             (forward_entry->extended_port_vid <= higher_th)) {
   3666             return BCM_E_PARAM;
   3667         }
   3668 
   3669         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit,
   3670                     forward_entry->dest_port,
   3671                     &mod_out, &port_out, &tgid_out, &id_out));
   3672         if (-1 != id_out) {
   3673             return BCM_E_PARAM;
   3674         }
   3675 
   3676         sal_memset(&l2_entry, 0, sizeof(l2_entry));
   3677         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VALIDf, 1);
   3678         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
   3679                 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID);
   3680         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf,
   3681                 forward_entry->name_space);
   3682         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf,
   3683                 forward_entry->extended_port_vid);
   3684         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__CLASS_IDf,
   3685                 forward_entry->class_id);
   3686         if (-1 != tgid_out) {
   3687             BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid_out));
   3688             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__DEST_TYPEf,
   3689                     1);
   3690             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__TGIDf,
   3691                     tgid_out);
   3692         } else {
   3693             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__MODULE_IDf,
   3694                     mod_out);
   3695             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__PORT_NUMf,
   3696                     port_out);
   3697         }
   3698         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, STATIC_BITf, 1);
   3699 
   3700     } else { /* Multicast forward entry */
   3701         if ((forward_entry->extended_port_vid < lower_th) ||
   3702                (forward_entry->extended_port_vid > higher_th)) {
   3703             return BCM_E_PARAM;
   3704         }
   3705         if (!_BCM_MULTICAST_IS_L2(forward_entry->dest_multicast)) {
   3706             return BCM_E_PARAM;
   3707         }
   3708 
   3709         sal_memset(&l2_entry, 0, sizeof(l2_entry));
   3710         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VALIDf, 1);
   3711         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
   3712                 SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID);
   3713         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf,
   3714                 forward_entry->name_space);
   3715         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf,
   3716                 forward_entry->extended_port_vid);
   3717         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__CLASS_IDf,
   3718                 forward_entry->class_id);
   3719         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__L2MC_PTRf,
   3720                 _BCM_MULTICAST_ID_GET(forward_entry->dest_multicast));
   3721         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, STATIC_BITf, 1);
   3722     }
   3723 
   3724     if (forward_entry->flags & BCM_EXTENDER_FORWARD_COPY_TO_CPU) {
   3725         if (SOC_MEM_FIELD_VALID(unit, L2_ENTRY_1m, PE_VID__DST_CPUf)) {
   3726             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__DST_CPUf, 1);
   3727         }
   3728     }
   3729 
   3730     soc_mem_lock(unit, L2_ENTRY_1m);
   3731 
   3732     if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_REPLACE)) {
   3733         l2_entry_1_entry_t  l2x_lookup;
   3734         int                 l2_index;
   3735 
   3736         /* See if the entry already exists */
   3737         rv = soc_mem_generic_lookup(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 0,
   3738                                     &l2_entry, &l2x_lookup, &l2_index);
   3739         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   3740             soc_mem_unlock(unit, L2_ENTRY_1m);
   3741             return rv;
   3742         }
   3743         if (BCM_SUCCESS(rv)) {
   3744             soc_mem_unlock(unit, L2_ENTRY_1m);
   3745             return BCM_E_EXISTS;
   3746         }
   3747 
   3748         rv = soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
   3749         if (SOC_FAILURE(rv)) {
   3750             soc_mem_unlock(unit, L2_ENTRY_1m);
   3751             return rv;
   3752         }
   3753     } else { /* Replace existing entry */
   3754         rv = soc_mem_delete(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
   3755         if (SOC_FAILURE(rv)) {
   3756             soc_mem_unlock(unit, L2_ENTRY_1m);
   3757             return rv;
   3758         }
   3759         rv = soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
   3760         if (SOC_FAILURE(rv)) {
   3761             soc_mem_unlock(unit, L2_ENTRY_1m);
   3762             return rv;
   3763         }
   3764     }
   3765 
   3766     soc_mem_unlock(unit, L2_ENTRY_1m);
   3767 
   3768     return rv;
   3769 }
   3770 
   3771 /*
   3772  * Purpose:
   3773  *	Delete a downstream forwarding entry
   3774  * Parameters:
   3775  *      unit - (IN) Device Number
   3776  *      forward_entry - (IN) Forwarding entry
   3777  */
   3778 int
   3779 bcm_tr3_extender_forward_delete(int unit,
   3780         bcm_extender_forward_t *forward_entry)
   3781 {
   3782     int rv = BCM_E_NONE;
   3783     l2_entry_1_entry_t l2_entry;
   3784     int lower_th, higher_th;
   3785 
   3786     if (forward_entry->name_space > 0xfff) {
   3787         return BCM_E_PARAM;
   3788     }
   3789     
   3790     BCM_IF_ERROR_RETURN(
   3791         bcm_esw_switch_control_get(unit,
   3792                                    bcmSwitchExtenderMulticastLowerThreshold,
   3793                                    &lower_th));
   3794     BCM_IF_ERROR_RETURN(
   3795         bcm_esw_switch_control_get(unit,
   3796                                    bcmSwitchExtenderMulticastHigherThreshold, 
   3797                                    &higher_th));
   3798 
   3799     if (forward_entry->extended_port_vid >=
   3800          (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__ETAG_VIDf))) {
   3801         return BCM_E_PARAM;
   3802     }
   3803     
   3804     if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) {
   3805         if ((forward_entry->extended_port_vid >= lower_th) &&
   3806             (forward_entry->extended_port_vid <= higher_th)) {
   3807             return BCM_E_PARAM;
   3808         }
   3809     } else { /* Multicast forward entry */
   3810         if ((forward_entry->extended_port_vid < lower_th) ||
   3811                (forward_entry->extended_port_vid > higher_th)) {
   3812             return BCM_E_PARAM;
   3813         }
   3814     }
   3815 
   3816     sal_memset(&l2_entry, 0, sizeof(l2_entry));
   3817     soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
   3818             SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID);
   3819     soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf,
   3820             forward_entry->name_space);
   3821     soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf,
   3822             forward_entry->extended_port_vid);
   3823     soc_mem_lock(unit, L2_ENTRY_1m);
   3824     rv = soc_mem_delete(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
   3825     soc_mem_unlock(unit, L2_ENTRY_1m);
   3826 
   3827     return rv;
   3828 }
   3829 
   3830 /*
   3831  * Purpose:
   3832  *	Delete all downstream forwarding entries
   3833  * Parameters:
   3834  *	unit - Device Number
   3835  */
   3836 int
   3837 bcm_tr3_extender_forward_delete_all(int unit)
   3838 {
   3839     int rv = BCM_E_NONE;
   3840     int seconds, enabled;
   3841     l2_entry_1_entry_t match_mask;
   3842     l2_entry_1_entry_t match_data;
   3843     l2_bulk_entry_t l2_bulk;
   3844     int match_mask_index, match_data_index;
   3845     uint32 rval;
   3846     int field_len;
   3847 
   3848     SOC_IF_ERROR_RETURN
   3849         (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled));
   3850     if (enabled) {
   3851         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit));
   3852     }
   3853 
   3854     soc_mem_lock(unit, L2_ENTRY_1m);
   3855 
   3856     /* Set match mask and data */
   3857     sal_memset(&match_mask, 0, sizeof(match_mask));
   3858     sal_memset(&match_data, 0, sizeof(match_data));
   3859 
   3860     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, VALIDf, 1);
   3861     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, VALIDf, 1);
   3862 
   3863     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, WIDEf, 1);
   3864     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, WIDEf, 0);
   3865 
   3866     field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf);
   3867     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, KEY_TYPEf,
   3868             (1 << field_len) - 1);
   3869     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, KEY_TYPEf,
   3870             SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID);
   3871 
   3872     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
   3873     sal_memcpy(&l2_bulk, &match_mask, sizeof(match_mask));
   3874     match_mask_index = 1;
   3875     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_mask_index, &l2_bulk);
   3876     if (BCM_SUCCESS(rv)) {
   3877         sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
   3878         sal_memcpy(&l2_bulk, &match_data, sizeof(match_data));
   3879         match_data_index = 0;
   3880         rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_data_index, &l2_bulk);
   3881     }
   3882 
   3883     /* Set bulk control */
   3884     rval = 0;
   3885     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
   3886     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
   3887     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
   3888                       _SOC_TR3_L2_BULK_BURST_MAX);
   3889     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
   3890     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
   3891                       soc_mem_index_count(unit, L2_ENTRY_1m));
   3892     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0);
   3893     if (BCM_SUCCESS(rv)) {
   3894         rv = WRITE_L2_BULK_CONTROLr(unit, rval);
   3895     }
   3896     if (BCM_SUCCESS(rv)) {
   3897         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
   3898     }
   3899 
   3900     soc_mem_unlock(unit, L2_ENTRY_1m);
   3901 
   3902     if(enabled) {
   3903         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds));
   3904     }
   3905 
   3906     return rv;
   3907 }
   3908 
   3909 /*
   3910  * Purpose:
   3911  *      Get a downstream forwarding entry
   3912  * Parameters:
   3913  *      unit - (IN) Device Number
   3914  *      forward_entry - (IN/OUT) Forwarding entry
   3915  */
   3916 int
   3917 bcm_tr3_extender_forward_get(int unit, bcm_extender_forward_t *forward_entry)
   3918 {
   3919     int rv = BCM_E_NONE;
   3920     l2_entry_1_entry_t l2_entry, l2_entry_out;
   3921     int idx;
   3922     _bcm_gport_dest_t dest;
   3923     int l2mc_index;
   3924     int lower_th, higher_th;
   3925 
   3926     if (forward_entry->name_space > 0xfff) {
   3927         return BCM_E_PARAM;
   3928     }
   3929 
   3930     BCM_IF_ERROR_RETURN(
   3931         bcm_esw_switch_control_get(unit,
   3932                                    bcmSwitchExtenderMulticastLowerThreshold,
   3933                                    &lower_th));
   3934     BCM_IF_ERROR_RETURN(
   3935         bcm_esw_switch_control_get(unit,
   3936                                    bcmSwitchExtenderMulticastHigherThreshold, 
   3937                                    &higher_th));
   3938    
   3939     if (forward_entry->extended_port_vid >=
   3940         (1 << soc_mem_field_length(unit, L2_ENTRY_1m, PE_VID__ETAG_VIDf))) {
   3941         return BCM_E_PARAM;
   3942     }
   3943 
   3944     if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) {
   3945         if ((forward_entry->extended_port_vid >= lower_th) &&
   3946             (forward_entry->extended_port_vid <= higher_th)) {
   3947             return BCM_E_PARAM;
   3948         }
   3949     } else { /* Multicast forward entry */
   3950         if ((forward_entry->extended_port_vid < lower_th) ||
   3951                (forward_entry->extended_port_vid > higher_th)) {
   3952             return BCM_E_PARAM;
   3953         }
   3954     }
   3955 
   3956     sal_memset(&l2_entry, 0, sizeof(l2_entry));
   3957     soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
   3958             SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID);
   3959     soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__NAMESPACEf,
   3960             forward_entry->name_space);
   3961     soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, PE_VID__ETAG_VIDf,
   3962             forward_entry->extended_port_vid);
   3963     soc_mem_lock(unit, L2_ENTRY_1m);
   3964     rv = soc_mem_search(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &idx, &l2_entry,
   3965             &l2_entry_out, 0);
   3966     soc_mem_unlock(unit, L2_ENTRY_1m);
   3967 
   3968     if (SOC_SUCCESS(rv)) {
   3969         if (!(forward_entry->flags & BCM_EXTENDER_FORWARD_MULTICAST)) {
   3970             if (soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
   3971                         PE_VID__DEST_TYPEf)) {
   3972                 dest.tgid = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
   3973                         PE_VID__TGIDf);
   3974                 dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   3975             } else {
   3976                 dest.modid = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
   3977                         PE_VID__MODULE_IDf);
   3978                 dest.port = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
   3979                         PE_VID__PORT_NUMf);
   3980                 dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   3981             }
   3982             BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest,
   3983                         &(forward_entry->dest_port)));
   3984         } else {
   3985             l2mc_index = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
   3986                     PE_VID__L2MC_PTRf);
   3987             _BCM_MULTICAST_GROUP_SET(forward_entry->dest_multicast,
   3988                     _BCM_MULTICAST_TYPE_L2, l2mc_index);
   3989         }
   3990         forward_entry->class_id = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
   3991                                                               PE_VID__CLASS_IDf);
   3992     }
   3993 
   3994     return rv;
   3995 }
   3996 
   3997 /*
   3998  * Purpose:
   3999  *      Traverse all valid downstream forwarding entries and call the
   4000  *      supplied callback routine.
   4001  * Parameters:
   4002  *      unit      - Device Number
   4003  *      cb        - User callback function, called once per forwarding entry.
   4004  *      user_data - cookie
   4005  * Returns:
   4006  *      BCM_E_XXX
   4007  */
   4008 int
   4009 bcm_tr3_extender_forward_traverse(int unit,
   4010                              bcm_extender_forward_traverse_cb cb,
   4011                              void *user_data)
   4012 {
   4013     int rv = BCM_E_NONE;
   4014     int chunk_entries, chunk_bytes;
   4015     uint8 *l2_tbl_chunk = NULL;
   4016     int chunk_idx_min, chunk_idx_max;
   4017     int ent_idx;
   4018     l2_entry_1_entry_t *l2_entry;
   4019     bcm_extender_forward_t forward_entry;
   4020     int l2mc_index;
   4021     _bcm_gport_dest_t dest;
   4022     int lower_th, higher_th;
   4023 
   4024     /* Get ETAG VID multicast range */
   4025     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   4026                 bcmSwitchExtenderMulticastLowerThreshold, &lower_th));
   4027     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   4028                 bcmSwitchExtenderMulticastHigherThreshold, &higher_th));
   4029 
   4030     chunk_entries = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   4031                                  L2_MEM_CHUNKS_DEFAULT);
   4032     chunk_bytes = 4 * SOC_MEM_WORDS(unit, L2_ENTRY_1m) * chunk_entries;
   4033     l2_tbl_chunk = soc_cm_salloc(unit, chunk_bytes, "extender forward traverse");
   4034     if (NULL == l2_tbl_chunk) {
   4035         return BCM_E_MEMORY;
   4036     }
   4037     for (chunk_idx_min = soc_mem_index_min(unit, L2_ENTRY_1m); 
   4038          chunk_idx_min <= soc_mem_index_max(unit, L2_ENTRY_1m); 
   4039          chunk_idx_min += chunk_entries) {
   4040 
   4041         /* Read a chunk of L2 table */
   4042         sal_memset(l2_tbl_chunk, 0, chunk_bytes);
   4043         chunk_idx_max = chunk_idx_min + chunk_entries - 1;
   4044         if (chunk_idx_max > soc_mem_index_max(unit, L2_ENTRY_1m)) {
   4045             chunk_idx_max = soc_mem_index_max(unit, L2_ENTRY_1m);
   4046         }
   4047         rv = soc_mem_read_range(unit, L2_ENTRY_1m, MEM_BLOCK_ANY,
   4048                                 chunk_idx_min, chunk_idx_max, l2_tbl_chunk);
   4049         if (SOC_FAILURE(rv)) {
   4050             break;
   4051         }
   4052         for (ent_idx = 0;
   4053              ent_idx <= (chunk_idx_max - chunk_idx_min);
   4054              ent_idx++) {
   4055             l2_entry = soc_mem_table_idx_to_pointer(unit, L2_ENTRY_1m,
   4056                     l2_entry_1_entry_t *, l2_tbl_chunk, ent_idx);
   4057 
   4058             if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, VALIDf) == 0) {
   4059                 continue;
   4060             }
   4061             if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, KEY_TYPEf) != 
   4062                     SOC_MEM_KEY_L2_ENTRY_1_PE_VID_PE_VID) {
   4063                 continue;
   4064             }
   4065 
   4066             /* Get fields of forwarding entry */
   4067             bcm_extender_forward_t_init(&forward_entry);
   4068             forward_entry.name_space = soc_L2_ENTRY_1m_field32_get(unit,
   4069                     l2_entry, PE_VID__NAMESPACEf);
   4070             forward_entry.extended_port_vid = soc_L2_ENTRY_1m_field32_get(unit,
   4071                     l2_entry, PE_VID__ETAG_VIDf);
   4072             forward_entry.class_id = soc_L2_ENTRY_1m_field32_get(unit,
   4073                     l2_entry, PE_VID__CLASS_IDf);
   4074             if ((forward_entry.extended_port_vid >= lower_th) &&
   4075                 (forward_entry.extended_port_vid <= higher_th)) {
   4076                 /* Multicast downstream forwarding entry */
   4077                 forward_entry.flags |= BCM_EXTENDER_FORWARD_MULTICAST;
   4078                 l2mc_index = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
   4079                         PE_VID__L2MC_PTRf);
   4080                 _BCM_MULTICAST_GROUP_SET(forward_entry.dest_multicast,
   4081                         _BCM_MULTICAST_TYPE_L2, l2mc_index);
   4082             } else {
   4083                 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
   4084                             PE_VID__DEST_TYPEf)) {
   4085                     dest.tgid = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
   4086                             PE_VID__TGIDf);
   4087                     dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   4088                 } else {
   4089                     dest.modid = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
   4090                             PE_VID__MODULE_IDf);
   4091                     dest.port = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
   4092                             PE_VID__PORT_NUMf);
   4093                     dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   4094                 }
   4095                 rv = _bcm_esw_gport_construct(unit, &dest,
   4096                         &(forward_entry.dest_port));
   4097                 if (BCM_FAILURE(rv)) {
   4098                     break;
   4099                 }
   4100             }
   4101 
   4102             if (SOC_MEM_FIELD_VALID(unit, L2_ENTRY_1m, PE_VID__DST_CPUf)) {
   4103                 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
   4104                             PE_VID__DST_CPUf)) {
   4105                     forward_entry.flags |= BCM_EXTENDER_FORWARD_COPY_TO_CPU;
   4106                 }
   4107             }
   4108 
   4109             /* Invoke callback */
   4110             rv = cb(unit, &forward_entry, user_data);
   4111             if (BCM_FAILURE(rv)) {
   4112                 break;
   4113             }
   4114         }
   4115         if (BCM_FAILURE(rv)) {
   4116             break;
   4117         }
   4118     }
   4119     soc_cm_sfree(unit, l2_tbl_chunk);
   4120 
   4121     return rv;
   4122 }
   4123 
   4124 /*
   4125  * Function:
   4126  *      bcm_tr3_etag_ethertype_set
   4127  * Purpose:
   4128  *      Set ETAG Ethertype.
   4129  * Parameters:
   4130  *      unit      - (IN) BCM device number
   4131  *      ethertype - (IN) Ethertype
   4132  * Returns:
   4133  *      BCM_E_XXX
   4134  */
   4135 int
   4136 bcm_tr3_etag_ethertype_set(int unit, int ethertype)
   4137 {
   4138 
   4139     if (ethertype < 0 || ethertype > 0xffff) {
   4140         return BCM_E_PARAM;
   4141     }
   4142 
   4143     if (soc_reg_field_valid(unit, PE_ETHERTYPEr, ETHERTYPEf)) {
   4144         BCM_IF_ERROR_RETURN
   4145             (soc_reg_field32_modify(unit, PE_ETHERTYPEr,
   4146                                     REG_PORT_ANY, ETHERTYPEf, ethertype));
   4147         BCM_IF_ERROR_RETURN
   4148             (soc_reg_field32_modify(unit, PE_ETHERTYPEr,
   4149                                     REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0));
   4150     }
   4151 
   4152     if (soc_reg_field_valid(unit, EGR_PE_ETHERTYPEr, ETHERTYPEf)) {
   4153         BCM_IF_ERROR_RETURN
   4154             (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPEr,
   4155                                     REG_PORT_ANY, ETHERTYPEf, ethertype));
   4156         BCM_IF_ERROR_RETURN
   4157             (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPEr,
   4158                                     REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0));
   4159     }
   4160 
   4161     if (soc_reg_field_valid(unit, EGR_PE_ETHERTYPE_2r, ETHERTYPEf)) {
   4162         BCM_IF_ERROR_RETURN
   4163             (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPE_2r,
   4164                                     REG_PORT_ANY, ETHERTYPEf, ethertype));
   4165         BCM_IF_ERROR_RETURN
   4166             (soc_reg_field32_modify(unit, EGR_PE_ETHERTYPE_2r,
   4167                                     REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0));
   4168     }
   4169 
   4170     if (soc_reg_field_valid(unit, IDB_OBM0_PE_ETHERTYPEr, ETHERTYPEf)) {
   4171         BCM_IF_ERROR_RETURN
   4172             (soc_reg_field32_modify(unit, IDB_OBM0_PE_ETHERTYPEr,
   4173                                     REG_PORT_ANY, ETHERTYPEf, ethertype));
   4174         BCM_IF_ERROR_RETURN
   4175             (soc_reg_field32_modify(unit, IDB_OBM0_PE_ETHERTYPEr,
   4176                                     REG_PORT_ANY, ENABLEf, ethertype ? 1 : 0));
   4177     }
   4178 
   4179 #ifdef BCM_TRIDENT3_SUPPORT
   4180     if (SOC_IS_TRIDENT3X(unit)) {
   4181         soc_td3_rx_etype_pe[unit] = ethertype;
   4182     }
   4183 #endif
   4184 
   4185     return BCM_E_NONE;
   4186 }
   4187 
   4188 /*
   4189  * Function:
   4190  *      bcm_tr3_etag_ethertype_get
   4191  * Purpose:
   4192  *      Get ETAG Ethertype.
   4193  * Parameters:
   4194  *      unit      - (IN) BCM device number
   4195  *      ethertype - (OUT) Ethertype
   4196  * Returns:
   4197  *      BCM_E_XXX
   4198  */
   4199 int
   4200 bcm_tr3_etag_ethertype_get(int unit, int *ethertype)
   4201 {
   4202     uint32 rval;
   4203 
   4204     if (ethertype == NULL) {
   4205         return BCM_E_PARAM;
   4206     }
   4207 
   4208     BCM_IF_ERROR_RETURN(READ_PE_ETHERTYPEr(unit, &rval));
   4209     if (soc_reg_field_get(unit, PE_ETHERTYPEr, rval, ENABLEf)) {
   4210         *ethertype = soc_reg_field_get(unit, PE_ETHERTYPEr, rval, ETHERTYPEf);
   4211     } else {
   4212         *ethertype = 0;
   4213     }
   4214 
   4215     return BCM_E_NONE;
   4216 }
   4217 
   4218 /*
   4219  * Function:
   4220  *      bcm_tr3_extender_untagged_add
   4221  * Purpose:
   4222  *      Set Extender VP tagging/untagging status by adding
   4223  *      a (Extender VP, VLAN) egress VLAN translation entry.
   4224  * Parameters:
   4225  *      unit - (IN) SOC unit number. 
   4226  *      vlan - (IN) VLAN ID. 
   4227  *      vp   - (IN) Virtual port number.
   4228  *      flags - (IN) Untagging indication.
   4229  *      egr_vt_added - (OUT) Indicates if (VP, VLAN) added to egress VLAN
   4230  *                           translation table.
   4231  * Returns:
   4232  *      BCM_X_XXX
   4233  */
   4234 int
   4235 bcm_tr3_extender_untagged_add(int unit, bcm_vlan_t vlan, int vp, int flags,
   4236         int *egr_vt_added)
   4237 {
   4238     uint32                  vent[SOC_MAX_MEM_FIELD_WORDS];
   4239     uint32                  old_vent[SOC_MAX_MEM_FIELD_WORDS];
   4240     bcm_vlan_action_set_t   action;
   4241     uint32 profile_idx;
   4242     int rv = BCM_E_NONE;
   4243     soc_mem_t               mem = EGR_VLAN_XLATEm;
   4244     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   4245         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   4246     }
   4247 
   4248     *egr_vt_added = FALSE;
   4249 
   4250     sal_memset(vent, 0, sizeof(vent));
   4251     if (soc_feature(unit, soc_feature_base_valid)) {
   4252         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
   4253         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
   4254     } else {
   4255         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
   4256     }
   4257     if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   4258         soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1);
   4259     } else if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) {
   4260         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, 1);
   4261     }
   4262 
   4263     if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) {
   4264         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1);
   4265     }
   4266     soc_mem_field32_set(unit, mem, vent, DVPf, vp);
   4267     soc_mem_field32_set(unit, mem, vent, OVIDf, vlan);
   4268 
   4269     if (!BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) {
   4270         if (!(flags & BCM_VLAN_PORT_UNTAGGED)) {
   4271             /* No need to insert an egress vlan translation entry
   4272              * to remove the outer tag.
   4273              */
   4274             return BCM_E_NONE;
   4275         }
   4276 
   4277 #ifdef BCM_TRIDENT2_SUPPORT
   4278         if (soc_mem_field_valid(unit, EGR_VP_VLAN_MEMBERSHIPm, UNTAGf)) {
   4279             if (flags & BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP) {
   4280                 /* The UNTAG field of EGR_VP_VLAN_MEMBERSHIP table will
   4281                  * be configured with untagging status. It would be redundant
   4282                  * to insert an egress VLAN translation entry.
   4283                  */
   4284                 return BCM_E_NONE;
   4285             }
   4286         } 
   4287 #endif /* BCM_TRIDENT2_SUPPORT */
   4288 
   4289         bcm_vlan_action_set_t_init(&action);
   4290         action.dt_outer = bcmVlanActionDelete;
   4291         action.ot_outer = bcmVlanActionDelete;
   4292     } else {
   4293         /* Extender port's match_vlan is valid. It needs to be inserted
   4294          * into the packet using an egress vlan translation entry.
   4295          */
   4296         soc_mem_field32_set(unit, mem, vent, NEW_OVIDf,
   4297                 EXTENDER_PORT_INFO(unit, vp)->match_vlan);
   4298         bcm_vlan_action_set_t_init(&action);
   4299         action.dt_outer = bcmVlanActionReplace;
   4300         action.ot_outer = bcmVlanActionReplace;
   4301         if (flags & BCM_VLAN_PORT_UNTAGGED) {
   4302             action.dt_inner = bcmVlanActionNone;
   4303             action.ot_inner = bcmVlanActionNone;
   4304         } else {
   4305             action.dt_inner = bcmVlanActionCopy;
   4306             action.ot_inner = bcmVlanActionCopy;
   4307         }
   4308     }
   4309     BCM_IF_ERROR_RETURN
   4310         (_bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &profile_idx));
   4311     soc_mem_field32_set(unit, mem, vent, TAG_ACTION_PROFILE_PTRf,
   4312             profile_idx);
   4313 
   4314     rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL,
   4315                                    vent, old_vent);
   4316     if (rv == SOC_E_EXISTS) {
   4317         /* Delete the old vlan translate profile entry */
   4318         profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   4319                                           TAG_ACTION_PROFILE_PTRf);
   4320         rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx);
   4321     }
   4322 
   4323     *egr_vt_added = TRUE;
   4324 
   4325     return rv;
   4326 }
   4327 
   4328 /*
   4329  * Function:
   4330  *      bcm_tr3_extender_untagged_delete
   4331  * Purpose:
   4332  *      Delete (Extender VP, VLAN) egress VLAN translation entry.
   4333  * Parameters:
   4334  *      unit - (IN) SOC unit number. 
   4335  *      vlan - (IN) VLAN ID. 
   4336  *      vp   - (IN) Virtual port number.
   4337  * Returns:
   4338  *      BCM_X_XXX
   4339  */
   4340 int
   4341 bcm_tr3_extender_untagged_delete(int unit, bcm_vlan_t vlan, int vp)
   4342 {
   4343     uint32                  vent[SOC_MAX_MEM_FIELD_WORDS];
   4344     uint32                  old_vent[SOC_MAX_MEM_FIELD_WORDS];
   4345     uint32 profile_idx;
   4346     int rv;
   4347     soc_mem_t               mem = EGR_VLAN_XLATEm;
   4348     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   4349         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   4350     }
   4351 
   4352     sal_memset(vent, 0, sizeof(vent));
   4353     if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   4354         soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1);
   4355     } else if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) {
   4356         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, 1);
   4357     }
   4358 
   4359     if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) {
   4360         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1);
   4361     }
   4362     soc_mem_field32_set(unit, mem, vent, DVPf, vp);
   4363     soc_mem_field32_set(unit, mem, vent, OVIDf, vlan);
   4364 
   4365     rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL,
   4366                                    vent, old_vent);
   4367     if (rv == SOC_E_NONE) {
   4368         uint32 is_valid = 0;
   4369         if (soc_feature(unit, soc_feature_base_valid)) {
   4370             is_valid =
   4371                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 &&
   4372                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7;
   4373         } else {
   4374             is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf);
   4375         }
   4376         if (is_valid) {
   4377             /* Delete the old vlan translate profile entry */
   4378             profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   4379                                               TAG_ACTION_PROFILE_PTRf);
   4380             rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx);
   4381         }
   4382     }
   4383 
   4384     return rv;
   4385 }
   4386 
   4387 /*
   4388  * Function:
   4389  *      bcm_tr3_extender_untagged_get
   4390  * Purpose:
   4391  *      Get tagging/untagging status of a Extender virtual port by
   4392  *      reading the (Extender VP, VLAN) egress vlan translation entry.
   4393  * Parameters:
   4394  *      unit - (IN) SOC unit number.
   4395  *      vlan - (IN) VLAN to remove virtual port from.
   4396  *      vp   - (IN) Virtual port number.
   4397  *      flags - (OUT) Untagging status of the Extender virtual port.
   4398  * Returns:
   4399  *      BCM_E_XXX
   4400  */
   4401 int
   4402 bcm_tr3_extender_untagged_get(int unit, bcm_vlan_t vlan, int vp,
   4403                                   int *flags)
   4404 {
   4405     uint32                  vent[SOC_MAX_MEM_FIELD_WORDS];
   4406     uint32                  res_vent[SOC_MAX_MEM_FIELD_WORDS];
   4407     int idx;
   4408     uint32 profile_idx;
   4409     int rv;
   4410     bcm_vlan_action_set_t action;
   4411     soc_mem_t               mem = EGR_VLAN_XLATEm;
   4412     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   4413         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   4414     }
   4415 
   4416     *flags = 0;
   4417 
   4418     sal_memset(vent, 0, sizeof(vent));
   4419     if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   4420         soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1);
   4421     } else if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) {
   4422         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, 1);
   4423     }
   4424 
   4425     if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) {
   4426         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1);
   4427     }
   4428     soc_mem_field32_set(unit, mem, vent, DVPf, vp);
   4429     soc_mem_field32_set(unit, mem, vent, OVIDf, vlan);
   4430 
   4431     rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, &idx, vent, res_vent, 0);
   4432     if (rv == SOC_E_NONE) {
   4433         uint32 is_valid = 0;
   4434         if (soc_feature(unit, soc_feature_base_valid)) {
   4435             is_valid =
   4436                 soc_mem_field32_get(unit, mem, res_vent, BASE_VALID_0f) == 3 &&
   4437                 soc_mem_field32_get(unit, mem, res_vent, BASE_VALID_1f) == 7;
   4438         } else {
   4439             is_valid = soc_mem_field32_get(unit, mem, res_vent, VALIDf);
   4440         }
   4441         if (is_valid) {
   4442             profile_idx = soc_mem_field32_get(unit, mem, res_vent,
   4443                                               TAG_ACTION_PROFILE_PTRf);
   4444             _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, profile_idx);
   4445 
   4446             if (!BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) {
   4447                 if (bcmVlanActionDelete == action.ot_outer) {
   4448                     *flags = BCM_VLAN_PORT_UNTAGGED;
   4449                 }
   4450             } else {
   4451                 if (bcmVlanActionNone == action.ot_inner) {
   4452                     *flags = BCM_VLAN_PORT_UNTAGGED;
   4453                 }
   4454             }
   4455         }
   4456     }
   4457 
   4458     return rv;
   4459 }
   4460 
   4461 /*
   4462  * Function:
   4463  *      bcm_tr3_niv_port_untagged_vlan_set
   4464  * Purpose:
   4465  *      Set the default VLAN ID for an Extender port.
   4466  * Parameters:
   4467  *      unit - StrataSwitch unit number.
   4468  *      port - Extender gport.
   4469  *      vid -  VLAN ID used for packets that ingress without a VLAN tag.
   4470  * Returns:
   4471  *      BCM_E_xxx
   4472  */
   4473 int
   4474 bcm_tr3_extender_port_untagged_vlan_set(int unit, bcm_port_t port,
   4475         bcm_vlan_t vid)
   4476 {
   4477     int                rv = BCM_E_NONE;
   4478     int                vp;
   4479     uint32             key_data[SOC_MAX_MEM_FIELD_WORDS];
   4480     uint32             entry_data[SOC_MAX_MEM_FIELD_WORDS];
   4481     int                key_type;
   4482     bcm_module_t       mod_out;
   4483     bcm_port_t         port_out;
   4484     bcm_trunk_t        trunk_out;
   4485     int                tmp_id;
   4486     int                entry_index;
   4487     soc_mem_t          mem = VLAN_XLATEm;
   4488 
   4489     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   4490         mem = VLAN_XLATE_1_DOUBLEm;
   4491     }
   4492 
   4493     /* Get VP */
   4494     if (BCM_GPORT_IS_EXTENDER_PORT(port)) {
   4495         vp = BCM_GPORT_EXTENDER_PORT_ID_GET(port);
   4496     } else {
   4497         return BCM_E_PORT;
   4498     }
   4499 
   4500     /* Construct lookup key */
   4501     sal_memset(key_data, 0, sizeof(key_data));
   4502 
   4503     if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) {
   4504         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4505                     VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type));
   4506         soc_mem_field32_set(unit, mem, key_data, VIF__VLANf,
   4507                 EXTENDER_PORT_INFO(unit, vp)->match_vlan);
   4508     } else {
   4509         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4510                     VLXLT_HASH_KEY_TYPE_VIF, &key_type));
   4511     }
   4512     soc_mem_field32_set(unit, mem, key_data, KEY_TYPEf, key_type);
   4513     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   4514         soc_mem_field32_set(unit, mem, key_data, DATA_TYPEf, key_type);
   4515     }
   4516 
   4517     soc_mem_field32_set(unit, mem, key_data, VIF__SRC_VIFf,
   4518             EXTENDER_PORT_INFO(unit, vp)->extended_port_vid);
   4519 
   4520     if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) {
   4521         soc_mem_field32_set(unit, mem, key_data, SOURCE_TYPEf, 1);
   4522     }
   4523     BCM_IF_ERROR_RETURN
   4524         (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port,
   4525                                 &mod_out, &port_out, &trunk_out, &tmp_id));
   4526     if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) {
   4527         soc_mem_field32_set(unit, mem, key_data, VIF__Tf, 1);
   4528         soc_mem_field32_set(unit, mem, key_data, VIF__TGIDf, trunk_out);
   4529     } else {
   4530         soc_mem_field32_set(unit, mem, key_data, VIF__MODULE_IDf, mod_out);
   4531         soc_mem_field32_set(unit, mem, key_data, VIF__PORT_NUMf, port_out);
   4532     }
   4533 
   4534     /* Lookup existing entry */
   4535     SOC_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ALL,
   4536                 &entry_index, key_data, entry_data, 0));
   4537 
   4538     /* Replace entry's new VLAN */
   4539     soc_mem_field32_set(unit, mem, entry_data, VIF__NEW_OVIDf, vid);
   4540 
   4541     /* Insert new entry */
   4542     rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, entry_data);
   4543     if (rv == SOC_E_EXISTS) {
   4544         rv = BCM_E_NONE;
   4545     } else {
   4546         return BCM_E_INTERNAL;
   4547     }
   4548 
   4549     return rv;
   4550 }
   4551 
   4552 /*
   4553  * Function:
   4554  *      bcm_tr3_extender_port_untagged_vlan_get
   4555  * Purpose:
   4556  *      Get the default VLAN ID for an Extender port.
   4557  * Parameters:
   4558  *      unit - StrataSwitch unit number.
   4559  *      port - Extender gport.
   4560  *      vid  - (OUT) VLAN ID used for packets that ingress without a VLAN tag.
   4561  * Returns:
   4562  *      BCM_E_xxx
   4563  */
   4564 int
   4565 bcm_tr3_extender_port_untagged_vlan_get(int unit, bcm_port_t port,
   4566         bcm_vlan_t *vid)
   4567 {
   4568     int                rv = BCM_E_NONE;
   4569     int                vp;
   4570     uint32             key_data[SOC_MAX_MEM_FIELD_WORDS];
   4571     uint32             entry_data[SOC_MAX_MEM_FIELD_WORDS];
   4572     int                key_type;
   4573     bcm_module_t       mod_out;
   4574     bcm_port_t         port_out;
   4575     bcm_trunk_t        trunk_out;
   4576     int                tmp_id;
   4577     int                entry_index;
   4578     soc_mem_t          mem = VLAN_XLATEm;
   4579 
   4580     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   4581         mem = VLAN_XLATE_1_DOUBLEm;
   4582     }
   4583 
   4584     /* Get VP */
   4585     if (BCM_GPORT_IS_EXTENDER_PORT(port)) {
   4586         vp = BCM_GPORT_EXTENDER_PORT_ID_GET(port);
   4587     } else {
   4588         return BCM_E_PORT;
   4589     }
   4590 
   4591     /* Construct lookup key */
   4592     sal_memset(key_data, 0, sizeof(key_data));
   4593 
   4594     if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) {
   4595         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4596                     VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type));
   4597         soc_mem_field32_set(unit, mem, key_data, VIF__VLANf,
   4598                 EXTENDER_PORT_INFO(unit, vp)->match_vlan);
   4599     } else {
   4600         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4601                     VLXLT_HASH_KEY_TYPE_VIF, &key_type));
   4602     }
   4603     soc_mem_field32_set(unit, mem, key_data, KEY_TYPEf, key_type);
   4604     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   4605         soc_mem_field32_set(unit, mem, key_data, DATA_TYPEf, key_type);
   4606     }
   4607 
   4608     soc_mem_field32_set(unit, mem, key_data, VIF__SRC_VIFf,
   4609             EXTENDER_PORT_INFO(unit, vp)->extended_port_vid);
   4610 
   4611     if (soc_mem_field_valid(unit, mem, SOURCE_TYPEf)) {
   4612         soc_mem_field32_set(unit, mem, key_data, SOURCE_TYPEf, 1);
   4613     }
   4614     BCM_IF_ERROR_RETURN
   4615         (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port,
   4616                                 &mod_out, &port_out, &trunk_out, &tmp_id));
   4617     if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) {
   4618         soc_mem_field32_set(unit, mem, key_data, VIF__Tf, 1);
   4619         soc_mem_field32_set(unit, mem, key_data, VIF__TGIDf, trunk_out);
   4620     } else {
   4621         soc_mem_field32_set(unit, mem, key_data, VIF__MODULE_IDf, mod_out);
   4622         soc_mem_field32_set(unit, mem, key_data, VIF__PORT_NUMf, port_out);
   4623     }
   4624 
   4625     /* Lookup existing entry */
   4626     SOC_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ALL,
   4627                 &entry_index, key_data, entry_data, 0));
   4628 
   4629     /* Get entry's VLAN */
   4630     *vid = soc_mem_field32_get(unit, mem, entry_data, VIF__NEW_OVIDf);
   4631 
   4632     return rv;
   4633 }
   4634 
   4635 /*
   4636  * Function:
   4637  *      bcm_tr3_extender_port_learn_set
   4638  * Purpose:
   4639  *      Set the CML bits for an extender port id.
   4640  * Parameters:
   4641  *      unit             - (IN) SOC unit number.
   4642  *      extender_port_id - (IN) Extender port id.
   4643  *      flags            - (IN) Logical OR of BCM_PORT_LEARN_xxx flags
   4644  * Returns:
   4645  *      BCM_E_XXX
   4646  */
   4647 int
   4648 bcm_tr3_extender_port_learn_set(int unit, bcm_gport_t extender_port_id,
   4649                                 uint32 flags)
   4650 {
   4651     int               vp = -1;
   4652     int               cml = 0;
   4653     int               rv = BCM_E_NONE;
   4654     int               entry_type;
   4655     source_vp_entry_t svp;
   4656 
   4657     cml = 0;
   4658     if (!(flags & BCM_PORT_LEARN_FWD)) {
   4659        cml |= (1 << 0);
   4660     }
   4661     if (flags & BCM_PORT_LEARN_CPU) {
   4662        cml |= (1 << 1);
   4663     }
   4664     if (flags & BCM_PORT_LEARN_PENDING) {
   4665        cml |= (1 << 2);
   4666     }
   4667     if (flags & BCM_PORT_LEARN_ARL) {
   4668        cml |= (1 << 3);
   4669     }
   4670 
   4671     /* Get the VP index from the gport */
   4672     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port_id);
   4673     if (vp == -1) {
   4674        return BCM_E_PARAM;
   4675     }
   4676 
   4677     MEM_LOCK(unit, SOURCE_VPm);
   4678     /* Be sure the entry is used and is set for Extender */
   4679     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   4680         MEM_UNLOCK(unit, SOURCE_VPm);
   4681         return BCM_E_NOT_FOUND;
   4682     }
   4683     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   4684     if (SOC_FAILURE(rv)) {
   4685         MEM_UNLOCK(unit, SOURCE_VPm);
   4686         return rv;
   4687     }
   4688 
   4689     entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
   4690     if (entry_type != 3) {
   4691         MEM_UNLOCK(unit, SOURCE_VPm);
   4692         return BCM_E_NOT_FOUND;
   4693     }
   4694 
   4695     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml);
   4696     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml);
   4697     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   4698 
   4699     MEM_UNLOCK(unit, SOURCE_VPm);
   4700     return rv;
   4701 }
   4702 
   4703 /*
   4704  * Function:
   4705  *      bcm_tr3_extender_port_learn_get
   4706  * Purpose:
   4707  *      Get the CML bits for an extender port id
   4708  * Parameters:
   4709  *      unit             - (IN) SOC unit number.
   4710  *      extender_port_id - (IN) Extender port id.
   4711  *      flags            - (OUT) Logical OR of BCM_PORT_LEARN_xxx flags
   4712  * Returns:
   4713  *      BCM_E_XXX
   4714  */
   4715 int
   4716 bcm_tr3_extender_port_learn_get(int unit, bcm_gport_t extender_port_id,
   4717                                 uint32 *flags)
   4718 {
   4719     int               vp = -1;
   4720     int               cml = 0;
   4721     int               rv = BCM_E_NONE;
   4722     int               entry_type;
   4723     source_vp_entry_t svp;
   4724 
   4725     /* Get the VP index from the gport */
   4726     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port_id);
   4727     if (vp == -1) {
   4728        return BCM_E_PARAM;
   4729     }
   4730 
   4731     /* Be sure the entry is used and is set for EXTENDER */
   4732     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   4733         return BCM_E_NOT_FOUND;
   4734     }
   4735     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   4736     if (rv < 0) {
   4737         return rv;
   4738     }
   4739 
   4740     entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
   4741     if (entry_type != 3) {
   4742         return BCM_E_NOT_FOUND;
   4743     }
   4744 
   4745     cml = soc_SOURCE_VPm_field32_get(unit, &svp, CML_FLAGS_NEWf);
   4746 
   4747     *flags = 0;
   4748     if (!(cml & (1 << 0))) {
   4749        *flags |= BCM_PORT_LEARN_FWD;
   4750     }
   4751     if (cml & (1 << 1)) {
   4752        *flags |= BCM_PORT_LEARN_CPU;
   4753     }
   4754     if (cml & (1 << 2)) {
   4755        *flags |= BCM_PORT_LEARN_PENDING;
   4756     }
   4757     if (cml & (1 << 3)) {
   4758        *flags |= BCM_PORT_LEARN_ARL;
   4759     }
   4760     return BCM_E_NONE;
   4761 }
   4762 
   4763 #ifdef BCM_TRIDENT2_SUPPORT
   4764 
   4765 /*
   4766  * Function:
   4767  *      _bcm_td2_extender_match_vp_replace
   4768  * Purpose:
   4769  *      Replace VP value in Extender VP's match entry.
   4770  * Parameters:
   4771  *      unit - (IN) SOC unit number. 
   4772  *      vp - (IN) Extender VP whose match entry is being replaced.
   4773  *      new_vp - (IN) New VP value.
   4774  *      old_vp - (OUT) Old VP value.
   4775  * Returns:
   4776  *      BCM_X_XXX
   4777  */
   4778 STATIC int
   4779 _bcm_td2_extender_match_vp_replace(int unit, int vp, int new_vp, int *old_vp)
   4780 {
   4781     int                rv = BCM_E_NONE;
   4782     uint32             key_data[SOC_MAX_MEM_FIELD_WORDS];
   4783     uint32             entry_data[SOC_MAX_MEM_FIELD_WORDS];
   4784     int                key_type;
   4785     bcm_module_t       mod_out;
   4786     bcm_port_t         port_out;
   4787     bcm_trunk_t        trunk_out;
   4788     int                tmp_id;
   4789     int                entry_index;
   4790     soc_mem_t          vx_mem = VLAN_XLATEm;
   4791 
   4792     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   4793         vx_mem = VLAN_XLATE_1_DOUBLEm;
   4794     }
   4795 
   4796     /* Construct lookup key */
   4797     sal_memset(key_data, 0, sizeof(key_data));
   4798 
   4799     if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) {
   4800         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4801                     VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type));
   4802         soc_mem_field32_set(unit, vx_mem, key_data, VIF__VLANf,
   4803                 EXTENDER_PORT_INFO(unit, vp)->match_vlan);
   4804     } else {
   4805         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4806                     VLXLT_HASH_KEY_TYPE_VIF, &key_type));
   4807     }
   4808     soc_mem_field32_set(unit, vx_mem, key_data, KEY_TYPEf, key_type);
   4809     if (SOC_MEM_FIELD_VALID(unit, vx_mem, DATA_TYPEf)) {
   4810         soc_mem_field32_set(unit, vx_mem, key_data, DATA_TYPEf, key_type);
   4811     }
   4812 
   4813     soc_mem_field32_set(unit, vx_mem, key_data, VIF__SRC_VIFf,
   4814             EXTENDER_PORT_INFO(unit, vp)->extended_port_vid);
   4815     if (soc_mem_field_valid(unit, vx_mem, SOURCE_TYPEf)) {
   4816         soc_mem_field32_set(unit, vx_mem, key_data, SOURCE_TYPEf, 1);
   4817     }
   4818     BCM_IF_ERROR_RETURN
   4819         (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port,
   4820                                 &mod_out, &port_out, &trunk_out, &tmp_id));
   4821     if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) {
   4822         soc_mem_field32_set(unit, vx_mem, key_data, VIF__Tf, 1);
   4823         soc_mem_field32_set(unit, vx_mem, key_data, VIF__TGIDf, trunk_out);
   4824     } else {
   4825         soc_mem_field32_set(unit, vx_mem, key_data, VIF__MODULE_IDf, mod_out);
   4826         soc_mem_field32_set(unit, vx_mem, key_data, VIF__PORT_NUMf, port_out);
   4827     }
   4828 
   4829     /* Lookup existing entry */
   4830     SOC_IF_ERROR_RETURN(soc_mem_search(unit, vx_mem, MEM_BLOCK_ALL,
   4831                 &entry_index, key_data, entry_data, 0));
   4832 
   4833     /* Replace entry's VP value */
   4834     *old_vp = soc_mem_field32_get(unit, vx_mem, entry_data, VIF__SOURCE_VPf);
   4835     soc_mem_field32_set(unit, vx_mem, entry_data, VIF__SOURCE_VPf, new_vp);
   4836 
   4837     /* Insert new entry */
   4838     rv = soc_mem_insert(unit, vx_mem, MEM_BLOCK_ALL, entry_data);
   4839     if (rv == SOC_E_EXISTS) {
   4840         rv = BCM_E_NONE;
   4841     } else {
   4842         return BCM_E_INTERNAL;
   4843     }
   4844 
   4845     return rv;
   4846 }
   4847 
   4848 /*
   4849  * Function:
   4850  *      bcm_td2_extender_port_source_vp_lag_set
   4851  * Purpose:
   4852  *      Set source VP LAG for an Extender virtual port.
   4853  * Parameters:
   4854  *      unit - (IN) SOC unit number. 
   4855  *      gport - (IN) Extender virtual port GPORT ID. 
   4856  *      vp_lag_vp - (IN) VP representing the VP LAG. 
   4857  * Returns:
   4858  *      BCM_X_XXX
   4859  */
   4860 int
   4861 bcm_td2_extender_port_source_vp_lag_set(int unit, bcm_gport_t gport,
   4862         int vp_lag_vp)
   4863 {
   4864     int vp, old_vp;
   4865 
   4866     if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4867         return BCM_E_PARAM;
   4868     }
   4869     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   4870     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   4871         return BCM_E_PARAM;
   4872     }
   4873 
   4874     /* Set source VP LAG by replacing the SVP field in Extender VP's
   4875      * match entry with the VP value representing the VP LAG.
   4876      */
   4877     BCM_IF_ERROR_RETURN
   4878         (_bcm_td2_extender_match_vp_replace(unit, vp, vp_lag_vp, &old_vp));
   4879 
   4880     return BCM_E_NONE;
   4881 }
   4882 
   4883 /*
   4884  * Function:
   4885  *      bcm_td2_extender_port_source_vp_lag_clear
   4886  * Purpose:
   4887  *      Clear source VP LAG for an Extender virtual port.
   4888  * Parameters:
   4889  *      unit - (IN) SOC unit number. 
   4890  *      gport - (IN) Extender virtual port GPORT ID. 
   4891  *      vp_lag_vp - (IN) VP representing the VP LAG. 
   4892  * Returns:
   4893  *      BCM_X_XXX
   4894  */
   4895 int
   4896 bcm_td2_extender_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
   4897         int vp_lag_vp)
   4898 {
   4899     int vp, old_vp;
   4900 
   4901     if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4902         return BCM_E_PARAM;
   4903     }
   4904     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   4905     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   4906         return BCM_E_PARAM;
   4907     }
   4908 
   4909     /* Clear source VP LAG by replacing the SVP field in Extender VP's
   4910      * match entry with the VP value.
   4911      */
   4912     BCM_IF_ERROR_RETURN
   4913         (_bcm_td2_extender_match_vp_replace(unit, vp, vp, &old_vp));
   4914 
   4915     /* Check that the old VP value matches the VP value representing
   4916      * the VP LAG or has been restored.
   4917      */
   4918     if ((old_vp != vp_lag_vp) && (old_vp != vp)) {
   4919         return BCM_E_INTERNAL;
   4920     }
   4921 
   4922     return BCM_E_NONE;
   4923 }
   4924 
   4925 /*
   4926  * Function:
   4927  *      bcm_td2_extender_port_source_vp_lag_get
   4928  * Purpose:
   4929  *      Set source VP LAG for an Extender virtual port.
   4930  * Parameters:
   4931  *      unit - (IN) SOC unit number. 
   4932  *      gport - (IN) Extender virtual port GPORT ID. 
   4933  *      vp_lag_vp - (OUT) VP representing the VP LAG. 
   4934  * Returns:
   4935  *      BCM_X_XXX
   4936  */
   4937 int
   4938 bcm_td2_extender_port_source_vp_lag_get(int unit, bcm_gport_t gport,
   4939         int *vp_lag_vp)
   4940 {
   4941     int                vp;
   4942     uint32             key_data[SOC_MAX_MEM_FIELD_WORDS];
   4943     uint32             entry_data[SOC_MAX_MEM_FIELD_WORDS];
   4944     int                key_type;
   4945     bcm_module_t       mod_out;
   4946     bcm_port_t         port_out;
   4947     bcm_trunk_t        trunk_out;
   4948     int                tmp_id;
   4949     int                entry_index;
   4950     soc_mem_t          vx_mem = VLAN_XLATEm;
   4951 
   4952     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   4953         vx_mem = VLAN_XLATE_1_DOUBLEm;
   4954     }
   4955 
   4956     if (!BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4957         return BCM_E_PARAM;
   4958     }
   4959     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   4960     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   4961         return BCM_E_PARAM;
   4962     }
   4963 
   4964     /* Construct match entry lookup key */
   4965     sal_memset(key_data, 0, sizeof(key_data));
   4966 
   4967     if (BCM_VLAN_VALID(EXTENDER_PORT_INFO(unit, vp)->match_vlan)) {
   4968         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4969                     VLXLT_HASH_KEY_TYPE_VIF_VLAN, &key_type));
   4970         soc_mem_field32_set(unit, vx_mem, key_data, VIF__VLANf,
   4971                 EXTENDER_PORT_INFO(unit, vp)->match_vlan);
   4972     } else {
   4973         BCM_IF_ERROR_RETURN(_bcm_esw_vlan_xlate_key_type_value_get(unit,
   4974                     VLXLT_HASH_KEY_TYPE_VIF, &key_type));
   4975     }
   4976     soc_mem_field32_set(unit, vx_mem, key_data, KEY_TYPEf, key_type);
   4977     if (SOC_MEM_FIELD_VALID(unit, vx_mem, DATA_TYPEf)) {
   4978         soc_mem_field32_set(unit, vx_mem, key_data, DATA_TYPEf, key_type);
   4979     }
   4980 
   4981     soc_mem_field32_set(unit, vx_mem, key_data, VIF__SRC_VIFf,
   4982             EXTENDER_PORT_INFO(unit, vp)->extended_port_vid);
   4983     if (soc_mem_field_valid(unit, vx_mem, SOURCE_TYPEf)) {
   4984         soc_mem_field32_set(unit, vx_mem, key_data, SOURCE_TYPEf, 1);
   4985     }
   4986     BCM_IF_ERROR_RETURN
   4987         (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port,
   4988                                 &mod_out, &port_out, &trunk_out, &tmp_id));
   4989     if (BCM_GPORT_IS_TRUNK(EXTENDER_PORT_INFO(unit, vp)->port)) {
   4990         soc_mem_field32_set(unit, vx_mem, key_data, VIF__Tf, 1);
   4991         soc_mem_field32_set(unit, vx_mem, key_data, VIF__TGIDf, trunk_out);
   4992     } else {
   4993         soc_mem_field32_set(unit, vx_mem, key_data, VIF__MODULE_IDf, mod_out);
   4994         soc_mem_field32_set(unit, vx_mem, key_data, VIF__PORT_NUMf, port_out);
   4995     }
   4996 
   4997     /* Lookup existing entry */
   4998     SOC_IF_ERROR_RETURN(soc_mem_search(unit, vx_mem, MEM_BLOCK_ALL,
   4999                 &entry_index, key_data, entry_data, 0));
   5000 
   5001     /* Get VP value representing VP LAG */
   5002     *vp_lag_vp = soc_mem_field32_get(unit, vx_mem, entry_data, VIF__SOURCE_VPf);
   5003     if (!_bcm_vp_used_get(unit, *vp_lag_vp, _bcmVpTypeVpLag)) {
   5004         return BCM_E_INTERNAL;
   5005     }
   5006 
   5007     return BCM_E_NONE;
   5008 }
   5009 
   5010 #endif /* BCM_TRIDENT2_SUPPORT */
   5011 
   5012 /* Function:
   5013  *      _bcm_tr3_extender_local_port_match
   5014  * Purpose:
   5015  *      Determine if two gports represent the same local physical port(s).
   5016  * Parameters:
   5017  *      unit - (IN) SOC unit Number
   5018  *      gport1 - (IN) GPORT ID 1
   5019  *      gport2 - (IN) GPORT ID 2
   5020  *      match  - (OUT) Match indication
   5021  * Returns:
   5022  *      BCM_E_XXX
   5023  */
   5024 STATIC int
   5025 _bcm_tr3_extender_local_port_match(int unit, bcm_gport_t gport1,
   5026         bcm_gport_t gport2, int *match)
   5027 {
   5028     bcm_module_t mod1, mod2;
   5029     bcm_port_t port1, port2;
   5030     bcm_trunk_t tgid1, tgid2;
   5031     int id1, id2;
   5032     int mod_local;
   5033 
   5034     *match = FALSE;
   5035 
   5036     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport1,
   5037                 &mod1, &port1, &tgid1, &id1));
   5038     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport2,
   5039                 &mod2, &port2, &tgid2, &id2));
   5040     if (id1 != -1 || id2 != -1) {
   5041         return BCM_E_PORT;
   5042     }
   5043 
   5044     if (BCM_TRUNK_INVALID != tgid1) {
   5045         if (BCM_TRUNK_INVALID != tgid2) {
   5046             if (tgid1 == tgid2) {
   5047                 *match = TRUE;
   5048             }
   5049         }
   5050     } else {
   5051         BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod1, &mod_local));
   5052         if (!mod_local) {
   5053             return BCM_E_PORT;
   5054         }
   5055         if (BCM_TRUNK_INVALID == tgid2) {
   5056             BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod2, &mod_local));
   5057             if (!mod_local) {
   5058                 return BCM_E_PORT;
   5059             }
   5060             if (mod1 == mod2 && port1 == port2) {
   5061                 *match = TRUE;
   5062             }
   5063         }
   5064     }
   5065 
   5066     return BCM_E_NONE;
   5067 }
   5068 
   5069 /* Function:
   5070  *      _bcm_tr3_extender_egress_match_ex_port
   5071  * Purpose:
   5072  *      Determine if two Extender egress objects' attributes match, except for
   5073  *      port.
   5074  * Parameters:
   5075  *      unit - (IN) SOC unit Number
   5076  *      extender_egress1 - (IN) Extender egress object 1, represented by
   5077  *                                  bcm_extender_egress_t.
   5078  *      extender_egress2 - (IN) Extender egress object 2, represented by
   5079  *                                 _bcm_tr3_extender_egress_t.
   5080  *      match - (OUT) Match indication
   5081  * Returns:
   5082  *      BCM_E_XXX
   5083  */
   5084 STATIC int
   5085 _bcm_tr3_extender_egress_match_ex_port(int unit,
   5086         bcm_extender_egress_t *extender_egress1,
   5087         _bcm_tr3_extender_egress_t *extender_egress2,
   5088         int *match)
   5089 {
   5090     int flags_match, vlan_match = 1, etag_vid_match ;
   5091     int etag_pcp_match = 1, etag_de_match = 1;
   5092     int pcp_de_select_match = 1, l3_intf_match = 1;
   5093     int service_qos_map_id_match = 1, service_tpid_match = 1;
   5094     int service_vlan_match = 1, service_pri_match = 1;
   5095     int service_cfi_match = 1, qos_map_id_match = 1;
   5096 
   5097     flags_match = (extender_egress1->flags == extender_egress2->flags);
   5098     etag_vid_match   = (extender_egress1->extended_port_vid ==
   5099                         extender_egress2->extended_port_vid);
   5100     etag_pcp_match = (extender_egress1->pcp == extender_egress2->pcp);
   5101     etag_de_match = (extender_egress1->de == extender_egress2->de);
   5102     pcp_de_select_match  = (extender_egress1->pcp_de_select  ==
   5103                              extender_egress2->pcp_de_select);
   5104     qos_map_id_match  = (extender_egress1->qos_map_id  ==
   5105                          extender_egress2->qos_map_id);
   5106     if (extender_egress1->flags & BCM_EXTENDER_EGRESS_L3) {
   5107         l3_intf_match = (extender_egress1->intf == extender_egress2->intf);
   5108     } else {
   5109         vlan_match  = (extender_egress1->match_vlan == extender_egress2->match_vlan);
   5110         service_tpid_match = (extender_egress1->service_tpid == extender_egress2->service_tpid);
   5111         service_vlan_match = (extender_egress1->service_vlan == extender_egress2->service_vlan);
   5112         service_pri_match  = (extender_egress1->service_pri  == extender_egress2->service_pri);
   5113         service_cfi_match  = (extender_egress1->service_cfi  == extender_egress2->service_cfi);
   5114         service_qos_map_id_match = (extender_egress1->service_qos_map_id ==
   5115                                    extender_egress2->service_qos_map_id);
   5116     }
   5117 
   5118     if (flags_match && vlan_match && etag_vid_match &&
   5119             etag_pcp_match && etag_de_match &&
   5120             pcp_de_select_match && qos_map_id_match &&
   5121             service_vlan_match && service_tpid_match &&
   5122             service_pri_match && service_cfi_match &&
   5123             service_qos_map_id_match && l3_intf_match) {
   5124         *match = TRUE;
   5125     } else {
   5126         *match = FALSE;
   5127     }
   5128 
   5129     return BCM_E_NONE;
   5130 }
   5131 
   5132 /*
   5133  * Function:
   5134  *      _bcm_tr3_extender_egress_hash_calc
   5135  * Purpose:
   5136  *      Calculate the hash value according to the egress object info.
   5137  * Parameters:
   5138  *      unit     -  (IN) SOC unit number.
   5139  *      hash_key -  (IN) hash key.
   5140  *      hash     -  (OUT) Hash(signature) calculated value.
   5141  * Returns:
   5142  *      BCM_X_XXX
   5143  */
   5144 STATIC int
   5145 _bcm_tr3_extender_egress_hash_calc(int unit, void *hash_key, uint16 *hash)
   5146 {
   5147     uint32 sw_buf[8];
   5148     int size;
   5149     int buf_idx = 0;
   5150     bcm_extender_egress_t *extender_egress;
   5151 
   5152     /* Input parameters check. */
   5153     if ((NULL == hash_key) || (NULL == hash)) {
   5154         return (BCM_E_PARAM);
   5155     }
   5156     size = sizeof(sw_buf);
   5157     sal_memset(sw_buf, 0, size);
   5158     extender_egress = (bcm_extender_egress_t *)hash_key;
   5159 
   5160     /*
   5161      * Copy entry information to a temporary buffer, so we can
   5162      * mask some fields we don't want to include in hash calculation.
   5163      */
   5164     sw_buf[buf_idx++] = extender_egress->flags;
   5165     sw_buf[buf_idx++] = extender_egress->intf;
   5166     sw_buf[buf_idx++] = ((extender_egress->extended_port_vid << 16) |
   5167                           (extender_egress->pcp << 8) | extender_egress->de);
   5168     sw_buf[buf_idx++] = extender_egress->qos_map_id;
   5169     if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_L3)) {
   5170         sw_buf[buf_idx++] = ((extender_egress->service_tpid << 16) |
   5171                               extender_egress->service_vlan);
   5172         sw_buf[buf_idx++] = ((extender_egress->service_pri << 16) |
   5173                               extender_egress->service_cfi);
   5174         sw_buf[buf_idx++] = extender_egress->service_qos_map_id;
   5175     }
   5176 
   5177     size = sizeof(uint32) * buf_idx;
   5178     *hash = _shr_crc16(0, (uint8 *)&sw_buf[0], size);
   5179 
   5180     return BCM_E_NONE;
   5181 }
   5182 
   5183 
   5184 /*
   5185  * Function:
   5186  *      _bcm_tr3_extender_egress_pbmp_get
   5187  * Purpose:
   5188  *      Get the pbmp of the multicast egress objects
   5189  *      attaching to vp in the linked list.
   5190  * Parameters:
   5191  *      unit  - (IN) SOC unit Number
   5192  *      vp    - (IN) Virtual port number.
   5193  *      pbmp  - (OUT) pbmp of the multicast egress objects attaching to vp.
   5194  * Returns:
   5195  *      BCM_E_XXX
   5196  */
   5197 STATIC void
   5198 _bcm_tr3_extender_egress_pbmp_get(int unit, int vp, bcm_pbmp_t *pbmp)
   5199 {
   5200     _bcm_tr3_extender_nh_info_t  *nh_info;
   5201     BCM_PBMP_CLEAR(*pbmp);
   5202 
   5203     nh_info = EXTENDER_PORT_MC_NH_INFO(unit, vp);
   5204     while (nh_info) {
   5205         BCM_PBMP_PORT_ADD(*pbmp, nh_info->port);
   5206         nh_info = nh_info->next;
   5207     }
   5208 
   5209     return;
   5210 }
   5211 
   5212 /*
   5213  * Function:
   5214  *      _bcm_tr3_extender_egress_pbmp_delete
   5215  * Purpose:
   5216  *      delete the pbmp of the multicast egress objects
   5217  *      attaching to vp from the linked list.
   5218  *      decrease the next hop ref_count of the port.
   5219  *      if next hop ref_count of the port is zero,
   5220  *      delete the node of the port from the list.
   5221  * Parameters:
   5222  *      unit - (IN) SOC unit Number
   5223  *      vp   - (IN) Virtual port number.
   5224  *      pbmp - (IN) pbmp of the multicast egress objects attaching to vp.
   5225  * Returns:
   5226  *      BCM_E_XXX
   5227  */
   5228 STATIC void
   5229 _bcm_tr3_extender_egress_pbmp_delete(int unit, int vp, bcm_pbmp_t pbmp)
   5230 {
   5231     _bcm_tr3_extender_nh_info_t      *ni_pre, *ni_cur, *ni_del;
   5232 
   5233     ni_cur  = EXTENDER_PORT_MC_NH_INFO(unit, vp);
   5234     ni_pre  = ni_cur;
   5235     ni_del  = NULL;
   5236     while (ni_cur) {
   5237         if (!BCM_PBMP_MEMBER(pbmp, ni_cur->port)) {
   5238             ni_pre = ni_cur;
   5239             ni_cur = ni_cur->next;
   5240             continue;
   5241         }
   5242 
   5243         /* port match */
   5244         ni_cur->nh_ref_cnt--;
   5245         if (ni_cur->nh_ref_cnt > 0) {
   5246             ni_pre = ni_cur;
   5247             ni_cur = ni_cur->next;
   5248             continue;
   5249         }
   5250 
   5251         /* Next hop refence count is zero. */
   5252         if (ni_cur == EXTENDER_PORT_MC_NH_INFO(unit, vp)) {
   5253             EXTENDER_PORT_MC_NH_INFO(unit, vp) = ni_cur->next;
   5254             ni_del = ni_cur;
   5255             ni_cur = ni_cur->next;
   5256             ni_pre = ni_cur;
   5257         } else {
   5258             ni_del = ni_cur;
   5259             ni_pre->next = ni_cur->next;
   5260             ni_cur = ni_cur->next;
   5261         }
   5262         sal_free(ni_del);
   5263     }
   5264 
   5265     return;
   5266 }
   5267 
   5268 /*
   5269  * Function:
   5270  *      _bcm_tr3_extender_egress_pbmp_add
   5271  * Purpose:
   5272  *      add the pbmp of the multicast egress objects
   5273  *      attaching to vp to the linked list.
   5274  *      decrease the next hop ref_count of the port.
   5275  *      if next hop ref_count of the port is zero,
   5276  *      delete the node of the port from the list.
   5277  * Parameters:
   5278  *      unit  - (IN) SOC unit Number
   5279  *      vp    - (IN) Virtual port number.
   5280  *      pbmp  - (IN) pbmp of the multicast egress objects attaching to vp.
   5281  * Returns:
   5282  *      BCM_E_XXX
   5283  */
   5284 STATIC int
   5285 _bcm_tr3_extender_egress_pbmp_add(int unit, int vp, bcm_pbmp_t pbmp)
   5286 {
   5287     bcm_port_t                      port;
   5288     int                             alloc_size;
   5289     _bcm_tr3_extender_nh_info_t      *nh_info;
   5290     bcm_pbmp_t                      sucess_pbmp;
   5291 
   5292     nh_info = EXTENDER_PORT_MC_NH_INFO(unit, vp);
   5293     while (nh_info) {
   5294         if (BCM_PBMP_MEMBER(pbmp, nh_info->port)) {
   5295             nh_info->nh_ref_cnt++;
   5296             BCM_PBMP_PORT_REMOVE(pbmp, nh_info->port);
   5297         }
   5298         nh_info = nh_info->next;
   5299     }
   5300 
   5301     BCM_PBMP_CLEAR(sucess_pbmp);
   5302     alloc_size = sizeof(_bcm_tr3_extender_nh_info_t);
   5303     BCM_PBMP_ITER(pbmp, port) {
   5304         nh_info = sal_alloc(alloc_size, "EXTENDER Egress Next Hop Info");
   5305         if (NULL == nh_info) {
   5306             _bcm_tr3_extender_egress_pbmp_delete(unit, vp, sucess_pbmp);
   5307             return BCM_E_MEMORY;
   5308         }
   5309         sal_memset(nh_info, 0, alloc_size);
   5310         nh_info->port = port;
   5311         nh_info->nh_ref_cnt = 1;
   5312         nh_info->next = EXTENDER_PORT_MC_NH_INFO(unit, vp);
   5313         EXTENDER_PORT_MC_NH_INFO(unit, vp) = nh_info;
   5314         BCM_PBMP_PORT_ADD(sucess_pbmp, port);
   5315     }
   5316 
   5317     return BCM_E_NONE;
   5318 }
   5319 
   5320 /*
   5321  * Function:
   5322  *      _bcm_tr3_extender_egress_pbmp_clear
   5323  * Purpose:
   5324  *      clear the linked list which maintain the pbmp of
   5325  *      the multicast egress objects attaching to vp.
   5326  * Parameters:
   5327  *      unit  - (IN) SOC unit Number
   5328  *      vp    - (IN) Virtual port number.
   5329  * Returns:
   5330  *      BCM_E_XXX
   5331  */
   5332 STATIC void
   5333 _bcm_tr3_extender_egress_pbmp_clear(int unit, int vp)
   5334 {
   5335     _bcm_tr3_extender_nh_info_t  *cur_node, *next_node;
   5336 
   5337     next_node = NULL;
   5338     cur_node = EXTENDER_PORT_MC_NH_INFO(unit, vp);
   5339     while (cur_node) {
   5340         next_node = cur_node->next;
   5341         sal_free(cur_node);
   5342         cur_node = next_node;
   5343     }
   5344     EXTENDER_PORT_MC_NH_INFO(unit, vp) = NULL;
   5345 
   5346     return;
   5347 }
   5348 
   5349 /* Function:
   5350  *      bcm_tr3_extender_egress_add
   5351  * Purpose:
   5352  *      Add a Extender egress object to a Extender Port
   5353  * Parameters:
   5354  *      unit - (IN) SOC unit Number
   5355  *      extender_port - (IN) Extender Port
   5356  *      extender_egress - (IN/OUT) Extender egress object, the egress_if field is output.
   5357  * Returns:
   5358  *      BCM_E_XXX
   5359  */
   5360 int
   5361 bcm_tr3_extender_egress_add(
   5362     int unit,
   5363     bcm_gport_t extender_port,
   5364     bcm_extender_egress_t *extender_egress)
   5365 {
   5366     int vp;
   5367     int match_ex_port;
   5368     int local_port_match;
   5369     int shared_nh_found;
   5370     bcm_pbmp_t existing_pbmp, new_pbmp, update_pbmp;
   5371     _bcm_tr3_extender_egress_t *curr_ptr = NULL, *temp_ptr = NULL;
   5372     int nh_index;
   5373     bcm_module_t mod_out;
   5374     bcm_port_t port_out;
   5375     bcm_trunk_t tgid_out;
   5376     int id_out;
   5377     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
   5378     int local_member_count;
   5379     int i;
   5380     int mod_local = FALSE;
   5381     bcm_port_t local_port;
   5382     bcm_gport_t gport;
   5383     _bcm_tr3_extender_sd_tag_t extender_sd_tag;
   5384     bcm_if_t intf;
   5385     int      alloc_size;
   5386     uint16   hash_val;
   5387     int      bkt_idx = 0;
   5388 #ifdef BCM_TRIDENT2_SUPPORT
   5389     int vp_routing = FALSE;
   5390     bcm_l3_egress_t nh_info;
   5391     uint32 nh_flags;
   5392 #endif
   5393 #if defined(BCM_HGPROXY_COE_SUPPORT)
   5394     int is_local_subport = FALSE;
   5395 #endif
   5396 
   5397     /* Verify extender_port is a valid EXTENDER port with no match criteria */
   5398     if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) {
   5399         return BCM_E_PARAM;
   5400     }
   5401     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port);
   5402     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   5403         return BCM_E_NOT_FOUND;
   5404     }
   5405     if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   5406         return BCM_E_PARAM;
   5407     }
   5408 
   5409     if (extender_egress == NULL) {
   5410         return BCM_E_PARAM;
   5411     }
   5412 
   5413 #ifdef BCM_TRIDENT2_SUPPORT
   5414     if (soc_feature(unit, soc_feature_virtual_port_routing)) {
   5415         vp_routing = TRUE;
   5416     }
   5417 #endif
   5418 
   5419     if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST)) {
   5420         /* When adding a unicast EXTENDER egress object to a EXTENDER port,
   5421          * check that there are no other EXTENDER egress objects on the
   5422          * EXTENDER port's egress_list. A EXTENDER port cannot be overloaded
   5423          * with multiple unicast EXTENDER egress objects.
   5424          */
   5425         if (NULL != EXTENDER_PORT_INFO(unit, vp)->egress_list) {
   5426             return BCM_E_CONFIG;
   5427         }
   5428         /* BCM_EXTENDER_EGRESS_L3 must be with BCM_EXTENDER_EGRESS_MULTICAST */
   5429         if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) {
   5430             return BCM_E_PARAM;
   5431         }
   5432     } else {
   5433         /* For a multicast EXTENDER egress object, the field
   5434          * match_vlan is not applicable.
   5435          */
   5436         if (extender_egress->match_vlan) {
   5437            return BCM_E_PARAM;
   5438         }
   5439 #ifdef BCM_TRIDENT2_SUPPORT
   5440         if (vp_routing) {
   5441         } else
   5442 #endif
   5443         {
   5444             if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) {
   5445                 return BCM_E_UNAVAIL;
   5446             }
   5447         }
   5448     }
   5449 
   5450     BCM_PBMP_CLEAR(new_pbmp);
   5451     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, extender_egress->port,
   5452                 &mod_out, &port_out, &tgid_out, &id_out));
   5453     if (BCM_TRUNK_INVALID != tgid_out) {
   5454         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit,
   5455                     tgid_out, SOC_MAX_NUM_PORTS, local_member_array,
   5456                     &local_member_count));
   5457         /*
   5458          * For multicast, it will be unnecessary to create next hop
   5459          * if there is no local port member.
   5460          */
   5461         if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5462             if (local_member_count <= 0) {
   5463                 return BCM_E_NONE;
   5464             }
   5465         }
   5466 
   5467         for (i = 0; i < local_member_count; i++) {
   5468             BCM_PBMP_PORT_ADD(new_pbmp, local_member_array[i]);
   5469         }
   5470     } else {
   5471 #if defined(BCM_HGPROXY_COE_SUPPORT)
   5472         BCM_IF_ERROR_RETURN(
   5473             _bcm_esw_port_is_local_subport(
   5474                 unit, extender_egress->port, mod_out, port_out,
   5475                 &is_local_subport, &port_out));
   5476         if (is_local_subport) {
   5477             mod_local = TRUE;
   5478         } else
   5479 #endif
   5480         {
   5481             BCM_IF_ERROR_RETURN(
   5482                 _bcm_esw_modid_is_local(unit, mod_out, &mod_local));
   5483         }
   5484 
   5485         /*
   5486          * For multicast, it will be unnecessary to create next hop
   5487          * if there is no local port member.
   5488          */
   5489         if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5490             if (!mod_local) {
   5491                 return BCM_E_NONE;
   5492             }
   5493         }
   5494 
   5495         if (mod_local) {
   5496             BCM_PBMP_PORT_ADD(new_pbmp, port_out);
   5497         } else {
   5498             return BCM_E_PORT;
   5499         }
   5500     }
   5501 
   5502     /* Traverse extender port's existing list of extender egress objects.
   5503      * If an existing egress object has the same multicast flag,
   5504      * extended_port_vid, match_vlan, PCP, and DE  but different port,
   5505      * its next hop index can be shared with the new extender egress object.
   5506      * Also, create a bitmap of the physical ports on which the VP resides.
   5507      */
   5508     BCM_PBMP_CLEAR(existing_pbmp);
   5509     shared_nh_found = FALSE;
   5510     curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   5511     if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5512         BCM_IF_ERROR_RETURN(
   5513             _bcm_tr3_extender_egress_hash_calc(unit, (void *)extender_egress,
   5514                                               &hash_val));
   5515         bkt_idx  = hash_val % TD_EXTENDER_PORT_HASH_BKT_SIZE;
   5516         if (EXTENDER_PORT_INFO(unit, vp)->egress_list != NULL) {
   5517             curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next;
   5518         }
   5519     }
   5520     while (NULL != curr_ptr) {
   5521         /* Determine if the attributes of the current EXTENDER egress object match
   5522          * those of the new EXTENDER egress object, except for the port attribute.
   5523          */
   5524         BCM_IF_ERROR_RETURN(_bcm_tr3_extender_egress_match_ex_port(unit,
   5525                     extender_egress, curr_ptr, &match_ex_port));
   5526         if (match_ex_port) {
   5527             /* Check if ports also match. If so, the EXTENDER egress object already exists. */
   5528             BCM_IF_ERROR_RETURN(_bcm_tr3_extender_local_port_match(unit,
   5529                         extender_egress->port, curr_ptr->port, &local_port_match));
   5530             if (local_port_match) {
   5531                 return BCM_E_EXISTS;
   5532             }
   5533 
   5534             /* If ports don't match, the next hop index can be shared. */
   5535             shared_nh_found = TRUE;
   5536             nh_index = curr_ptr->next_hop_index;
   5537             break;
   5538         }
   5539         /* Advance to next EXTENDER egress object */
   5540         curr_ptr = curr_ptr->next;
   5541     }
   5542 
   5543     if (!shared_nh_found) {
   5544         /* If match not found,  Configure next hop entry */
   5545 #ifdef BCM_TRIDENT2_SUPPORT
   5546         if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) {
   5547         bcm_l3_egress_t_init(&nh_info);
   5548         nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
   5549         BCM_IF_ERROR_RETURN
   5550             (bcm_xgs3_nh_add(unit, nh_flags, &nh_info, &nh_index));
   5551 
   5552             /* Configure next hop entry for L3MC */
   5553             BCM_IF_ERROR_RETURN
   5554                 (_bcm_tr3_extender_l3mc_nh_info_set(unit, nh_index,
   5555                     EXTENDER_PORT_INFO(unit, vp)->flags, extender_egress->multicast_flags,
   5556                     extender_egress->port, extender_egress->intf,
   5557                     extender_egress->extended_port_vid,
   5558                     extender_egress->qos_map_id, extender_egress->pcp_de_select,
   5559                     extender_egress->pcp, extender_egress->de, vp));
   5560         } else
   5561 #endif
   5562         {
   5563             sal_memset(&extender_sd_tag, 0, sizeof(extender_sd_tag));
   5564             extender_sd_tag.flags = extender_egress->flags;
   5565             extender_sd_tag.service_tpid = extender_egress->service_tpid;
   5566             extender_sd_tag.service_vlan = extender_egress->service_vlan;
   5567             extender_sd_tag.service_pri  = extender_egress->service_pri;
   5568             extender_sd_tag.service_cfi  = extender_egress->service_cfi;
   5569             extender_sd_tag.service_qos_map_id = extender_egress->service_qos_map_id;
   5570 
   5571             BCM_IF_ERROR_RETURN
   5572                 (_bcm_tr3_extender_port_nh_info_set(unit,
   5573                         extender_egress->port, extender_egress->extended_port_vid,
   5574                         extender_egress->match_vlan, extender_egress->pcp,
   5575                         extender_egress->de, extender_egress->pcp_de_select,
   5576                         extender_egress->qos_map_id, &extender_sd_tag, vp, &nh_index));
   5577         }
   5578     } else {
   5579         /* Increment next hop's reference count */
   5580         _bcm_xgs3_nh_ref_cnt_incr(unit, nh_index);
   5581     }
   5582 
   5583     /* Update next hop index in ING_DVP_TABLE */
   5584     intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index;
   5585     BCM_IF_ERROR_RETURN(
   5586         _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigUpdate, vp,
   5587                                ING_DVP_CONFIG_INVALID_VP_TYPE, intf,
   5588                                ING_DVP_CONFIG_INVALID_PORT_TYPE));
   5589 
   5590     /* Configure ingress VLAN translation table for unicast
   5591      * EXTENDER egress object.
   5592      */
   5593     if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST)) {
   5594         BCM_IF_ERROR_RETURN(_bcm_tr3_extender_port_match_add(unit,
   5595                                     extender_egress->port,
   5596                                     extender_egress->extended_port_vid,
   5597                                     extender_egress->match_vlan,
   5598                                     vp));
   5599     }
   5600 
   5601     /* Increment the VP count on the new EXTENDER egress object's physical
   5602      * port(s), unless the physical port(s) match those of VP's
   5603      * other EXTENDER egress objects.
   5604      */
   5605     if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5606         _bcm_tr3_extender_egress_pbmp_get(unit, vp, &existing_pbmp);
   5607     }
   5608     BCM_PBMP_CLEAR(update_pbmp);
   5609     BCM_PBMP_ASSIGN(update_pbmp, new_pbmp);
   5610     BCM_PBMP_REMOVE(update_pbmp, existing_pbmp);
   5611     BCM_PBMP_ITER(update_pbmp, local_port) {
   5612         BCM_IF_ERROR_RETURN
   5613             (bcm_esw_port_gport_get(unit, local_port, &gport));
   5614         BCM_IF_ERROR_RETURN
   5615             (_bcm_tr3_extender_port_cnt_update(unit, gport, vp, TRUE));
   5616     }
   5617 
   5618     if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5619         BCM_IF_ERROR_RETURN(
   5620             _bcm_tr3_extender_egress_pbmp_add(unit, vp, new_pbmp));
   5621     }
   5622 
   5623     /* Insert the new EXTENDER egress object into VP's egress object list */
   5624     curr_ptr = sal_alloc(sizeof(_bcm_tr3_extender_egress_t),
   5625             "EXTENDER egress object");
   5626     if (NULL == curr_ptr) {
   5627         return BCM_E_MEMORY;
   5628     }
   5629     sal_memset(curr_ptr, 0, sizeof(_bcm_tr3_extender_egress_t));
   5630     curr_ptr->flags = extender_egress->flags;
   5631     curr_ptr->port = extender_egress->port;
   5632     curr_ptr->extended_port_vid = extender_egress->extended_port_vid;
   5633     curr_ptr->qos_map_id = extender_egress->qos_map_id;
   5634     curr_ptr->pcp_de_select = extender_egress->pcp_de_select;
   5635     curr_ptr->pcp = extender_egress->pcp;
   5636     curr_ptr->de = extender_egress->de;
   5637     curr_ptr->match_vlan = extender_egress->match_vlan;
   5638     curr_ptr->service_tpid = extender_egress->service_tpid;
   5639     curr_ptr->service_vlan = extender_egress->service_vlan;
   5640     curr_ptr->service_pri = extender_egress->service_pri;
   5641     curr_ptr->service_cfi = extender_egress->service_cfi;
   5642     curr_ptr->service_qos_map_id = extender_egress->service_qos_map_id;
   5643     curr_ptr->next_hop_index = nh_index;
   5644     curr_ptr->intf = extender_egress->intf;
   5645     curr_ptr->multicast_flags = extender_egress->multicast_flags;
   5646     if (!(extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST)) {
   5647         curr_ptr->next = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   5648         EXTENDER_PORT_INFO(unit, vp)->egress_list = curr_ptr;
   5649     } else {
   5650         if ((EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL)) {
   5651             alloc_size = sizeof(_bcm_tr3_extender_egress_t) *
   5652                          TD_EXTENDER_PORT_HASH_BKT_SIZE;
   5653             temp_ptr = sal_alloc(alloc_size, "EXTENDER egress object");
   5654             if (NULL == temp_ptr) {
   5655                 sal_free(curr_ptr);
   5656                 return BCM_E_MEMORY;
   5657             }
   5658             sal_memset(temp_ptr, 0, alloc_size);
   5659             EXTENDER_PORT_INFO(unit, vp)->egress_list = temp_ptr;
   5660         }
   5661         curr_ptr->next = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next;
   5662         EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next = curr_ptr;
   5663     }
   5664     /* Set Extender egress object ID */
   5665     if (extender_egress->flags & BCM_EXTENDER_EGRESS_L3) {
   5666         extender_egress->egress_if = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   5667     }
   5668     else {
   5669         extender_egress->egress_if = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
   5670     }
   5671 
   5672     return BCM_E_NONE;
   5673 }
   5674 
   5675 
   5676 /* Function:
   5677  *      bcm_tr3_extender_egress_delete
   5678  * Purpose:
   5679  *      Delete a Extender egress object from a Extender port
   5680  * Parameters:
   5681  *      unit - (IN) SOC unit Number
   5682  *      extender_port - (IN) Extender port
   5683  *      extender_egress - (IN) Extender egress object
   5684  * Returns:
   5685  *      BCM_E_XXX
   5686  */
   5687 int
   5688 bcm_tr3_extender_egress_delete(
   5689     int unit,
   5690     bcm_gport_t extender_port,
   5691     bcm_extender_egress_t *extender_egress)
   5692 {
   5693     int vp;
   5694     int match_found;
   5695     bcm_pbmp_t remaining_pbmp, pbmp;
   5696     _bcm_tr3_extender_egress_t *curr_ptr, *prev_ptr, **head;
   5697     _bcm_tr3_extender_egress_t *match_ptr = NULL;
   5698     int local_port_match;
   5699     int match_ex_port;
   5700     bcm_module_t mod_out;
   5701     bcm_port_t port_out;
   5702     bcm_trunk_t tgid_out;
   5703     int id_out;
   5704     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
   5705     int local_member_count;
   5706     int i;
   5707     int mod_local = FALSE;
   5708     bcm_port_t local_port;
   5709     bcm_gport_t gport;
   5710     int nh_index;
   5711     bcm_if_t intf;
   5712     uint16   hash_val;
   5713     int      bkt_idx;
   5714 #if defined(BCM_HGPROXY_COE_SUPPORT)
   5715     int is_local_subport = FALSE;
   5716 #endif
   5717 
   5718     /* Verify extender_port is a valid EXTENDER port with no match criteria */
   5719     if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) {
   5720         return BCM_E_PARAM;
   5721     }
   5722     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port);
   5723     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   5724         return BCM_E_NOT_FOUND;
   5725     }
   5726     if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   5727         return BCM_E_PARAM;
   5728     }
   5729 
   5730     if (extender_egress == NULL) {
   5731         return BCM_E_PARAM;
   5732     }
   5733 
   5734     /* Traverse EXTENDER port's list of EXTENDER egress objects to find the egress
   5735      * object to be deleted. Also, among the remaining egress objects,
   5736      * create a bitmap of the physical ports on which the VP resides.
   5737      */
   5738     match_found = FALSE;
   5739     BCM_PBMP_CLEAR(remaining_pbmp);
   5740     prev_ptr = NULL;
   5741     if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5742         if ((EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL)) {
   5743             return BCM_E_NOT_FOUND;
   5744         }
   5745         BCM_IF_ERROR_RETURN(
   5746             _bcm_tr3_extender_egress_hash_calc(unit, (void *)extender_egress,
   5747                                               &hash_val));
   5748         bkt_idx  = hash_val % TD_EXTENDER_PORT_HASH_BKT_SIZE;
   5749         head = &(EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next);
   5750     } else {
   5751         head = &(EXTENDER_PORT_INFO(unit, vp)->egress_list);
   5752     }
   5753     curr_ptr = *head;
   5754     while (NULL != curr_ptr) {
   5755         BCM_IF_ERROR_RETURN(_bcm_tr3_extender_egress_match_ex_port(unit,
   5756                     extender_egress, curr_ptr, &match_ex_port));
   5757         BCM_IF_ERROR_RETURN(_bcm_tr3_extender_local_port_match(unit,
   5758                     extender_egress->port, curr_ptr->port, &local_port_match));
   5759         if (match_ex_port && local_port_match) {
   5760 
   5761             match_found = TRUE;
   5762             match_ptr = curr_ptr;
   5763             if (curr_ptr == *head) {
   5764                 *head = curr_ptr->next;
   5765             } else {
   5766                /*
   5767                 * In the following line of code, Coverity thinks the
   5768                 * prev_ptr variable may still be NULL when dereferenced.
   5769                 * This situation will never occur because if curr_ptr
   5770                 * is not pointing to the head of the linked list,
   5771                 * prev_ptr would not be NULL.
   5772                 */
   5773                 /* coverity[var_deref_op : FALSE] */
   5774                 prev_ptr->next = curr_ptr->next;
   5775             }
   5776             break;
   5777         } else {
   5778             prev_ptr = curr_ptr;
   5779         }
   5780 
   5781         /* Advance to next EXTENDER egress object */
   5782         curr_ptr = curr_ptr->next;
   5783     }
   5784     if (!match_found) {
   5785         return BCM_E_NOT_FOUND;
   5786     }
   5787 
   5788     /* Delete ingress VLAN translation entry */
   5789     if (!(match_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST)) {
   5790         BCM_IF_ERROR_RETURN(_bcm_tr3_extender_port_match_delete(unit,
   5791                     match_ptr->port, match_ptr->extended_port_vid,
   5792                     match_ptr->match_vlan, vp));
   5793     }
   5794 
   5795     /* If the VP's list of remaining egress objects is empty, modify VP's
   5796      * next hop index to invalid next hop index. If not empty,
   5797      * pick one of the next hop indices in the list.
   5798      */
   5799     if (NULL == *head) {
   5800         nh_index = EXTENDER_INFO(unit)->invalid_next_hop_index;
   5801     } else {
   5802         nh_index = (*head)->next_hop_index;
   5803     }
   5804 
   5805     /* Update next hop index in ING_DVP_TABLE */
   5806     intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + nh_index;
   5807     BCM_IF_ERROR_RETURN(
   5808         _bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigUpdate, vp,
   5809                                ING_DVP_CONFIG_INVALID_VP_TYPE, intf,
   5810                                ING_DVP_CONFIG_INVALID_PORT_TYPE));
   5811 
   5812     /* Decrement next hop's reference count. If count reaches zero,
   5813      * free the next hop index and clear next hop table entries.
   5814      */
   5815     BCM_IF_ERROR_RETURN
   5816         (_bcm_tr3_extender_nh_info_delete(unit, match_ptr->next_hop_index));
   5817 
   5818     /* Decrement the VP count on the deleted EXTENDER egress object's physical
   5819      * port(s), unless the physical port(s) are shared by the VP's remaining
   5820      * EXTENDER egress objects.
   5821      */
   5822     BCM_PBMP_CLEAR(pbmp);
   5823     BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, match_ptr->port,
   5824                 &mod_out, &port_out, &tgid_out, &id_out));
   5825     if (BCM_TRUNK_INVALID != tgid_out) {
   5826         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit,
   5827                     tgid_out, SOC_MAX_NUM_PORTS, local_member_array,
   5828                     &local_member_count));
   5829         for (i = 0; i < local_member_count; i++) {
   5830             BCM_PBMP_PORT_ADD(pbmp, local_member_array[i]);
   5831         }
   5832     } else {
   5833 #if defined(BCM_HGPROXY_COE_SUPPORT)
   5834         BCM_IF_ERROR_RETURN(
   5835             _bcm_esw_port_is_local_subport(
   5836                 unit, extender_egress->port, mod_out, port_out,
   5837                 &is_local_subport, &port_out));
   5838         if (is_local_subport) {
   5839             mod_local = TRUE;
   5840         } else
   5841 #endif
   5842         {
   5843             BCM_IF_ERROR_RETURN(
   5844                 _bcm_esw_modid_is_local(unit, mod_out, &mod_local));
   5845         }
   5846         if (mod_local) {
   5847             BCM_PBMP_PORT_ADD(pbmp, port_out);
   5848         } else {
   5849             return BCM_E_INTERNAL;
   5850         }
   5851     }
   5852     if (extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5853         _bcm_tr3_extender_egress_pbmp_delete(unit, vp, pbmp);
   5854         _bcm_tr3_extender_egress_pbmp_get(unit, vp, &remaining_pbmp);
   5855     }
   5856     BCM_PBMP_REMOVE(pbmp, remaining_pbmp);
   5857     BCM_PBMP_ITER(pbmp, local_port) {
   5858         BCM_IF_ERROR_RETURN
   5859             (bcm_esw_port_gport_get(unit, local_port, &gport));
   5860         BCM_IF_ERROR_RETURN
   5861             (_bcm_tr3_extender_port_cnt_update(unit, gport, vp, FALSE));
   5862     }
   5863     if ((extender_egress->flags & BCM_EXTENDER_EGRESS_MULTICAST) &&
   5864          BCM_PBMP_IS_NULL(remaining_pbmp)) {
   5865          sal_free(EXTENDER_PORT_INFO(unit, vp)->egress_list);
   5866          EXTENDER_PORT_INFO(unit, vp)->egress_list = NULL;
   5867     }
   5868     /* Free the deleted EXTENDER egress object */
   5869     sal_free(match_ptr);
   5870 
   5871     return BCM_E_NONE;
   5872 }
   5873 
   5874 /* Function:
   5875  *      bcm_tr3_extender_egress_set
   5876  * Purpose:
   5877  *      Delete existing egress object for a Extender port and add
   5878  *      an array of Extender egress objects for the Extender port
   5879  * Parameters:
   5880  *      unit - (IN) SOC unit Number
   5881  *      extender_port - (IN) Extender port
   5882  *      array_size      - (IN) Number of Extender egress objects.
   5883  *      extender_egress_array - (IN/OUT) Array of Extender egress objects.
   5884  * Returns:
   5885  *      BCM_E_XXX
   5886  */
   5887  int
   5888 bcm_tr3_extender_egress_set(int unit, bcm_gport_t extender_port,
   5889         int array_size, bcm_extender_egress_t *extender_egress_array)
   5890 {
   5891     int vp;
   5892     _bcm_tr3_extender_egress_t *curr_ptr, *next_ptr;
   5893     bcm_pbmp_t pbmp;
   5894     bcm_module_t mod_out;
   5895     bcm_port_t port_out;
   5896     bcm_trunk_t tgid_out;
   5897     int id_out;
   5898     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
   5899     int local_member_count;
   5900     int i;
   5901     int mod_local = FALSE;
   5902     bcm_gport_t gport;
   5903     bcm_port_t local_port;
   5904     bcm_if_t intf;
   5905     int      bkt_idx, bkt_size;
   5906     int      vp_mc = 0;
   5907 #if defined(BCM_HGPROXY_COE_SUPPORT)
   5908     int is_local_subport = FALSE;
   5909 #endif
   5910 
   5911     /* Verify extender_port is a valid EXTENDER port with no match criteria */
   5912     if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) {
   5913         return BCM_E_PARAM;
   5914     }
   5915     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port);
   5916     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   5917         return BCM_E_NOT_FOUND;
   5918     }
   5919     if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   5920         return BCM_E_PARAM;
   5921     }
   5922     if ((array_size > 0) && (extender_egress_array == NULL)) {
   5923         return BCM_E_PARAM;
   5924     }
   5925 
   5926     /* Modify VP's next hop index to invalid next hop index */
   5927     intf = BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + EXTENDER_INFO(unit)->invalid_next_hop_index;
   5928     BCM_IF_ERROR_RETURN(_bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigUpdate,
   5929                         vp, ING_DVP_CONFIG_INVALID_VP_TYPE, intf,
   5930                         ING_DVP_CONFIG_INVALID_PORT_TYPE));
   5931 
   5932     /* Delete the existing EXTENDER egress objects attached to the given EXTENDER port */
   5933     if (EXTENDER_PORT_MC_NH_INFO(unit, vp) != NULL) {
   5934         /* The shared vp associates with mulicast egress objects. */
   5935         if (EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL) {
   5936             return BCM_E_INTERNAL;
   5937         }
   5938         vp_mc = 1;
   5939     }
   5940     BCM_PBMP_CLEAR(pbmp);
   5941     bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1;
   5942     for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) {
   5943         if (vp_mc) {
   5944             curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next;
   5945         } else {
   5946             curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   5947         }
   5948         while (NULL != curr_ptr) {
   5949             /* Delete ingress VLAN translation entry */
   5950             if (!(curr_ptr->flags & BCM_EXTENDER_EGRESS_MULTICAST)) {
   5951                 BCM_IF_ERROR_RETURN(_bcm_tr3_extender_port_match_delete(unit,
   5952                             curr_ptr->port, curr_ptr->extended_port_vid,
   5953                             curr_ptr->match_vlan, vp));
   5954             }
   5955 
   5956             /* Decrement next hop's reference count. If count reaches zero,
   5957              * free the next hop index and clear next hop table entries.
   5958              */
   5959             BCM_IF_ERROR_RETURN
   5960                 (_bcm_tr3_extender_nh_info_delete(unit, curr_ptr->next_hop_index));
   5961 
   5962             /* Add this EXTENDER egress object's port(s) to the bitmap of physical ports
   5963              * on which the VP resides.
   5964              */
   5965             BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, curr_ptr->port,
   5966                         &mod_out, &port_out, &tgid_out, &id_out));
   5967             if (BCM_TRUNK_INVALID != tgid_out) {
   5968                 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit,
   5969                             tgid_out, SOC_MAX_NUM_PORTS, local_member_array,
   5970                             &local_member_count));
   5971                 for (i = 0; i < local_member_count; i++) {
   5972                     BCM_PBMP_PORT_ADD(pbmp, local_member_array[i]);
   5973                 }
   5974             } else {
   5975 #if defined(BCM_HGPROXY_COE_SUPPORT)
   5976                 BCM_IF_ERROR_RETURN(
   5977                     _bcm_esw_port_is_local_subport(
   5978                         unit, curr_ptr->port, mod_out, port_out,
   5979                         &is_local_subport, &port_out));
   5980                 if (is_local_subport) {
   5981                     mod_local = TRUE;
   5982                 } else
   5983 #endif
   5984                 {
   5985                     BCM_IF_ERROR_RETURN(
   5986                         _bcm_esw_modid_is_local(unit, mod_out, &mod_local));
   5987                 }
   5988                 if (mod_local) {
   5989                     BCM_PBMP_PORT_ADD(pbmp, port_out);
   5990                 } else {
   5991                     return BCM_E_INTERNAL;
   5992                 }
   5993             }
   5994 
   5995             /* Free current EXTENDER egress object and advance to the next one */
   5996             next_ptr = curr_ptr->next;
   5997             sal_free(curr_ptr);
   5998             curr_ptr = next_ptr;
   5999         }
   6000 
   6001         if (vp_mc) {
   6002             EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next = NULL;
   6003         } else {
   6004             EXTENDER_PORT_INFO(unit, vp)->egress_list = NULL;
   6005         }
   6006     }
   6007 
   6008     if (vp_mc) {
   6009         sal_free(EXTENDER_PORT_INFO(unit, vp)->egress_list);
   6010         EXTENDER_PORT_INFO(unit, vp)->egress_list = NULL;
   6011         _bcm_tr3_extender_egress_pbmp_clear(unit, vp);
   6012     }
   6013 
   6014     /* Decrement VP count on all the physical ports on which the VP resides */
   6015     BCM_PBMP_ITER(pbmp, local_port) {
   6016         BCM_IF_ERROR_RETURN
   6017             (bcm_esw_port_gport_get(unit, local_port, &gport));
   6018         BCM_IF_ERROR_RETURN
   6019             (_bcm_tr3_extender_port_cnt_update(unit, gport, vp, FALSE));
   6020     }
   6021 
   6022     /* Add new EXTENDER egress objects to EXTENDER port */
   6023     for (i = 0; i < array_size; i++) {
   6024         BCM_IF_ERROR_RETURN
   6025             (bcm_tr3_extender_egress_add(unit, extender_port, &extender_egress_array[i]));
   6026     }
   6027 
   6028     return BCM_E_NONE;
   6029 }
   6030 
   6031 /* Function:
   6032  *      bcm_esw_extender_egress_get
   6033  * Purpose:
   6034  *      get an Extender egress object for Extender Port
   6035  * Parameters:
   6036  *      unit - (IN) SOC unit Number
   6037  *      extender_port - (IN) Extender port
   6038  *      extender_egress - (IN/OUT) Extender egress object
   6039  * Returns:
   6040  *      BCM_E_XXX
   6041  */
   6042 int
   6043 bcm_tr3_extender_egress_get(int unit, bcm_gport_t extender_port,
   6044         bcm_extender_egress_t *extender_egress)
   6045 {
   6046     int vp;
   6047     _bcm_tr3_extender_egress_t *curr_ptr;
   6048     int bkt_idx, bkt_size;
   6049     int vp_mc = 0;
   6050 
   6051     /* Verify extender_port is a valid Extender port with no match criteria */
   6052     if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) {
   6053         return BCM_E_PARAM;
   6054     }
   6055     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port);
   6056     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   6057         return BCM_E_NOT_FOUND;
   6058     }
   6059     if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   6060         return BCM_E_PARAM;
   6061     }
   6062     if (extender_egress == NULL) {
   6063         return BCM_E_PARAM;
   6064     }
   6065 
   6066     /* Traverse Extender port's existing list of Extender egress objects */
   6067     curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   6068 
   6069     if (EXTENDER_PORT_MC_NH_INFO(unit, vp) != NULL) {
   6070         /* The shared vp associates with mulicast egress objects. */
   6071         if (EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL) {
   6072             return BCM_E_INTERNAL;
   6073         }
   6074         vp_mc = 1;
   6075     }
   6076     bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1;
   6077     for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) {
   6078         if (vp_mc) {
   6079             curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next;
   6080         } else {
   6081             curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   6082         }
   6083         while (NULL != curr_ptr) {
   6084             if ((extender_egress->port == curr_ptr->port) &&
   6085                 (extender_egress->extended_port_vid ==
   6086                  curr_ptr->extended_port_vid) &&
   6087                 (extender_egress->flags == curr_ptr->flags)) {
   6088 
   6089                 extender_egress->port = curr_ptr->port;
   6090                 extender_egress->extended_port_vid =
   6091                     curr_ptr->extended_port_vid;
   6092                 extender_egress->qos_map_id = curr_ptr->qos_map_id;
   6093                 extender_egress->pcp_de_select =
   6094                     curr_ptr->pcp_de_select;
   6095                 extender_egress->pcp = curr_ptr->pcp;
   6096                 extender_egress->de = curr_ptr->de;
   6097                 extender_egress->match_vlan = curr_ptr->match_vlan;
   6098                 extender_egress->service_tpid = curr_ptr->service_tpid;
   6099                 extender_egress->service_vlan = curr_ptr->service_vlan;
   6100                 extender_egress->service_pri = curr_ptr->service_pri;
   6101                 extender_egress->service_cfi = curr_ptr->service_cfi;
   6102                 extender_egress->service_qos_map_id =
   6103                     curr_ptr->service_qos_map_id;
   6104                 extender_egress->intf = curr_ptr->intf;
   6105                 extender_egress->multicast_flags =
   6106                     curr_ptr->multicast_flags;
   6107 
   6108                 extender_egress->egress_if = curr_ptr->next_hop_index +
   6109                                                 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   6110                 return BCM_E_NONE;
   6111             } else {
   6112                 curr_ptr = curr_ptr->next;
   6113             }
   6114         }
   6115     }
   6116     return BCM_E_NOT_FOUND;
   6117 }
   6118 
   6119 /* Function:
   6120  *      bcm_tr3_extender_egress_get_all
   6121  * Purpose:
   6122  *      get an Array of Extender egress objects for Extender Port
   6123  * Parameters:
   6124  *      unit - (IN) SOC unit Number
   6125  *      extender_port - (IN) Extender port
   6126  *      array_size      - (IN) Size of Extender egress objects array.
   6127  *      extender_egress_array - (OUT) Array of Extender egress objects.
   6128  *      count - (OUT) Number of Extender egress objects returned.
   6129  * Returns:
   6130  *      BCM_E_XXX
   6131  */
   6132 int
   6133 bcm_tr3_extender_egress_get_all(int unit, bcm_gport_t extender_port,
   6134         int array_size, bcm_extender_egress_t *extender_egress_array, int *count)
   6135 {
   6136     int vp;
   6137     _bcm_tr3_extender_egress_t *curr_ptr;
   6138     int bkt_idx, bkt_size;
   6139     int vp_mc = 0;
   6140 
   6141     /* Verify extender_port is a valid Extender port with no match criteria */
   6142     if (!BCM_GPORT_IS_EXTENDER_PORT(extender_port)) {
   6143         return BCM_E_PARAM;
   6144     }
   6145     vp = BCM_GPORT_EXTENDER_PORT_ID_GET(extender_port);
   6146     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   6147         return BCM_E_NOT_FOUND;
   6148     }
   6149     if (!(EXTENDER_PORT_INFO(unit, vp)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   6150         return BCM_E_PARAM;
   6151     }
   6152     if (array_size < 0) {
   6153         return BCM_E_PARAM;
   6154     }
   6155     if ((array_size > 0) && (extender_egress_array == NULL)) {
   6156         return BCM_E_PARAM;
   6157     }
   6158     if (count == NULL) {
   6159         return BCM_E_PARAM;
   6160     }
   6161 
   6162     /* Traverse Extender port's existing list of Extender egress objects */
   6163     *count = 0;
   6164     curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   6165 
   6166     if (EXTENDER_PORT_MC_NH_INFO(unit, vp) != NULL) {
   6167         /* The shared vp associates with mulicast egress objects. */
   6168         if (EXTENDER_PORT_INFO(unit, vp)->egress_list == NULL) {
   6169             return BCM_E_INTERNAL;
   6170         }
   6171         vp_mc = 1;
   6172     }
   6173     bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1;
   6174 
   6175     for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) {
   6176         if (vp_mc) {
   6177             curr_ptr = EXTENDER_PORT_HASH_BKT(unit, vp, bkt_idx)->next;
   6178         } else {
   6179             curr_ptr = EXTENDER_PORT_INFO(unit, vp)->egress_list;
   6180         }
   6181         while (NULL != curr_ptr) {
   6182             if (array_size > 0) {
   6183                 extender_egress_array[*count].flags = curr_ptr->flags;
   6184                 extender_egress_array[*count].port = curr_ptr->port;
   6185                 extender_egress_array[*count].extended_port_vid=
   6186                     curr_ptr->extended_port_vid;
   6187                 extender_egress_array[*count].match_vlan = curr_ptr->match_vlan;
   6188                 extender_egress_array[*count].pcp_de_select =
   6189                     curr_ptr->pcp_de_select;
   6190                 extender_egress_array[*count].qos_map_id = curr_ptr->qos_map_id;
   6191                 extender_egress_array[*count].pcp = curr_ptr->pcp;
   6192                 extender_egress_array[*count].de = curr_ptr->de;
   6193                 extender_egress_array[*count].service_tpid = curr_ptr->service_tpid;
   6194                 extender_egress_array[*count].service_vlan = curr_ptr->service_vlan;
   6195                 extender_egress_array[*count].service_pri = curr_ptr->service_pri;
   6196                 extender_egress_array[*count].service_cfi = curr_ptr->service_cfi;
   6197                 extender_egress_array[*count].service_qos_map_id =
   6198                     curr_ptr->service_qos_map_id;
   6199                 extender_egress_array[*count].intf = curr_ptr->intf;
   6200                 extender_egress_array[*count].multicast_flags =
   6201                     curr_ptr->multicast_flags;
   6202                 if (curr_ptr->flags & BCM_EXTENDER_EGRESS_L3) {
   6203                     extender_egress_array[*count].egress_if =
   6204                         curr_ptr->next_hop_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   6205                 } else {
   6206                     extender_egress_array[*count].egress_if =
   6207                         curr_ptr->next_hop_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
   6208                 }
   6209             }
   6210             (*count)++;
   6211             if (*count == array_size) {
   6212                 break;
   6213             }
   6214             curr_ptr = curr_ptr->next;
   6215         }
   6216         if ((array_size != 0) && (*count == array_size)) {
   6217             break;
   6218         }
   6219     }
   6220     return BCM_E_NONE;
   6221 }
   6222 
   6223 #ifndef BCM_SW_STATE_DUMP_DISABLE
   6224 /*
   6225  * Function:
   6226  *     _bcm_tr3_extender_sw_dump
   6227  * Purpose:
   6228  *     Displays Extender module information maintained by software.
   6229  * Parameters:
   6230  *     unit - Device unit number
   6231  * Returns:
   6232  *     None
   6233  */
   6234 void
   6235 bcm_tr3_extender_sw_dump(int unit)
   6236 {
   6237     int i, num_vp;
   6238     _bcm_tr3_extender_egress_t *curr_ptr;
   6239     int egr_obj_index;
   6240     char pfmt[SOC_PBMP_FMT_LEN];
   6241     int  bkt_idx, bkt_size;
   6242     int  vp_mc = 0;
   6243     bcm_pbmp_t pbmp;
   6244 
   6245     LOG_CLI((BSL_META_U(unit,
   6246                         "\nSW Information Extender - Unit %d\n"), unit));
   6247 
   6248     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   6249 
   6250     LOG_CLI((BSL_META_U(unit,
   6251                         "\n  Port Info    : \n")));
   6252     for (i = 0; i < num_vp; i++) {
   6253         if (!(EXTENDER_PORT_INFO(unit, i)->flags & BCM_EXTENDER_PORT_MATCH_NONE)) {
   6254             if (EXTENDER_PORT_INFO(unit, i)->port == 0) {
   6255                 continue;
   6256             }
   6257             LOG_CLI((BSL_META_U(unit,
   6258                                 "\n  Extender port vp = %d\n"), i));
   6259             LOG_CLI((BSL_META_U(unit,
   6260                                 "Flags = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->flags));
   6261             LOG_CLI((BSL_META_U(unit,
   6262                                 "Port = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->port));
   6263             LOG_CLI((BSL_META_U(unit,
   6264                                 "ETAG VID = 0x%x\n"),
   6265                      EXTENDER_PORT_INFO(unit, i)->extended_port_vid));
   6266             LOG_CLI((BSL_META_U(unit,
   6267                                 "PCP DE Select = 0x%x\n"), 
   6268                      EXTENDER_PORT_INFO(unit, i)->pcp_de_select));
   6269             LOG_CLI((BSL_META_U(unit,
   6270                                 "Default PCP = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->pcp));
   6271             LOG_CLI((BSL_META_U(unit,
   6272                                 "Default DE = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->de));
   6273             LOG_CLI((BSL_META_U(unit,
   6274                                 "Match VLAN = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->match_vlan));
   6275         }else {
   6276             LOG_CLI((BSL_META_U(unit,
   6277                                 "\n  Extender port vp = %d\n"), i));
   6278             LOG_CLI((BSL_META_U(unit,
   6279                                 "    Flags = 0x%x\n"), EXTENDER_PORT_INFO(unit, i)->flags));
   6280 
   6281             egr_obj_index = 0;
   6282             vp_mc = 0;
   6283             if (EXTENDER_PORT_MC_NH_INFO(unit, i) != NULL) {
   6284                 if (EXTENDER_PORT_INFO(unit, i)->egress_list == NULL) {
   6285                     continue;
   6286                 }
   6287                 vp_mc = 1;
   6288             }
   6289             bkt_size = vp_mc ? TD_EXTENDER_PORT_HASH_BKT_SIZE : 1;
   6290             for (bkt_idx = 0; bkt_idx < bkt_size; bkt_idx++) {
   6291                 /* The shared vp associates with mulicast egress objects. */
   6292                 if (vp_mc) {
   6293                     curr_ptr = EXTENDER_PORT_HASH_BKT(unit, i, bkt_idx)->next;
   6294                     if (curr_ptr) {
   6295                         LOG_CLI((BSL_META_U(unit,
   6296                                             "\n  Bkt_idx = %d\n"), bkt_idx));
   6297                     }
   6298                 } else {
   6299                     curr_ptr = EXTENDER_PORT_INFO(unit, i)->egress_list;
   6300                 }
   6301                 while (NULL != curr_ptr) {
   6302                     LOG_CLI((BSL_META_U(unit,
   6303                                         "    Egress object %d\n"),
   6304                                         egr_obj_index));
   6305                     LOG_CLI((BSL_META_U(unit,
   6306                                         "      Flags = 0x%x\n"),
   6307                                         curr_ptr->flags));
   6308                     LOG_CLI((BSL_META_U(unit,
   6309                                         "      Port = 0x%x\n"),
   6310                                         curr_ptr->port));
   6311                     LOG_CLI((BSL_META_U(unit,
   6312                                         "      ETAG VID = 0x%x\n"),
   6313                              curr_ptr->extended_port_vid));
   6314                     LOG_CLI((BSL_META_U(unit,
   6315                                         "PCP DE Select = 0x%x\n"),
   6316                              curr_ptr->pcp_de_select));
   6317                     LOG_CLI((BSL_META_U(unit,
   6318                                         "Default PCP = 0x%x\n"), curr_ptr->pcp));
   6319                     LOG_CLI((BSL_META_U(unit,
   6320                                         "Default DE = 0x%x\n"), curr_ptr->de));
   6321 
   6322                     LOG_CLI((BSL_META_U(unit,
   6323                                         "      Match VLAN = 0x%x\n"),
   6324                              curr_ptr->match_vlan));
   6325                     LOG_CLI((BSL_META_U(unit,
   6326                                         "      Service TPID = 0x%x\n"),
   6327                              curr_ptr->service_tpid));
   6328                     LOG_CLI((BSL_META_U(unit,
   6329                                         "      Service VLAN = 0x%x\n"),
   6330                              curr_ptr->service_vlan));
   6331                     LOG_CLI((BSL_META_U(unit,
   6332                                         "      Service PRI = 0x%x\n"),
   6333                              curr_ptr->service_pri));
   6334                     LOG_CLI((BSL_META_U(unit,
   6335                                         "      Service CFI = 0x%x\n"),
   6336                              curr_ptr->service_cfi));
   6337                     LOG_CLI((BSL_META_U(unit,
   6338                                         "      Service Qos Map ID = 0x%x\n"),
   6339                              curr_ptr->service_qos_map_id));
   6340                     LOG_CLI((BSL_META_U(unit,
   6341                                         "      Next Hop Index = 0x%x\n"),
   6342                              curr_ptr->next_hop_index));
   6343                     LOG_CLI((BSL_META_U(unit,
   6344                                         "      L3 Intf = 0x%x\n"),
   6345                              curr_ptr->intf));
   6346                     LOG_CLI((BSL_META_U(unit,
   6347                                         "      Multicast_flags = 0x%x\n"),
   6348                              curr_ptr->multicast_flags));
   6349                     egr_obj_index++;
   6350                     curr_ptr = curr_ptr->next;
   6351                 }
   6352             }
   6353 
   6354             if (vp_mc) {
   6355                 BCM_PBMP_CLEAR(pbmp);
   6356                 _bcm_tr3_extender_egress_pbmp_get(unit, i, &pbmp);
   6357                 LOG_CLI((BSL_META_U(unit,
   6358                                     "      pbmp = %s\n"),
   6359                          SOC_PBMP_FMT(pbmp, pfmt)));
   6360             }
   6361 
   6362                 }
   6363     }
   6364 
   6365     return;
   6366 }
   6367 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   6368 
   6369 #ifdef BCM_TOMAHAWK_SUPPORT
   6370 bcm_error_t
   6371 _bcm_extender_gport_get(int unit, int is_trunk, int modid,
   6372                         int port, int etag_vid, bcm_gport_t *ext_gport)
   6373 {
   6374     int vp;
   6375     bcm_trunk_t trunk_id = -1;
   6376     bcm_port_t local_port_id;
   6377     bcm_module_t local_modid;
   6378     int id_out;
   6379 
   6380     if (NULL == EXTENDER_INFO(unit)->port_info) {
   6381         return BCM_E_INIT;
   6382     }
   6383 
   6384     if (NULL == ext_gport) {
   6385         return BCM_E_PARAM;
   6386     }
   6387     for (vp = soc_mem_index_min(unit, SOURCE_VPm);
   6388          vp <= soc_mem_index_max(unit, SOURCE_VPm);
   6389          vp++) {
   6390         if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   6391             if (!(EXTENDER_PORT_INFO(unit, vp)->flags &
   6392                 BCM_EXTENDER_PORT_MULTICAST)) {
   6393                     BCM_IF_ERROR_RETURN
   6394                         (_bcm_esw_gport_resolve(unit, EXTENDER_PORT_INFO(unit, vp)->port,
   6395                                                 &local_modid,
   6396                                                 &local_port_id,
   6397                                                 &trunk_id,
   6398                                                 &id_out));                 
   6399                 if (EXTENDER_PORT_INFO(unit, vp)->extended_port_vid == etag_vid) {
   6400                     if ((is_trunk == 1) && (trunk_id == port)) {
   6401                         BCM_GPORT_EXTENDER_PORT_ID_SET(*ext_gport, vp);
   6402                         return BCM_E_NONE;
   6403                     } else if ((is_trunk != 1) && (trunk_id == -1)) {
   6404                         if ((local_port_id == port) &&
   6405                             (local_modid == modid )) {
   6406                             BCM_GPORT_EXTENDER_PORT_ID_SET(*ext_gport, vp);
   6407                             return BCM_E_NONE;
   6408                         }
   6409                     }
   6410                 }
   6411             }
   6412         }
   6413     }
   6414     return BCM_E_NOT_FOUND;
   6415 }
   6416 #endif /* BCM_TOMAHAWK_SUPPORT */
   6417 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */