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

vlan.c (237621B)


      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:    vlan.c
      8  * Purpose: Manages VLAN virtual port creation and deletion.
      9  *          Also manages addition and removal of virtual
     10  *          ports from VLAN. The types of virtual ports that
     11  *          can be added to or removed from VLAN can be VLAN
     12  *          VPs, NIV VPs, or Extender VPs.
     13  */
     14 
     15 #include <shared/bsl.h>
     16 
     17 #include <soc/defs.h>
     18 #include <sal/core/libc.h>
     19 
     20 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 
     21 
     22 #include <soc/drv.h>
     23 #include <soc/scache.h>
     24 #include <soc/hash.h>
     25 
     26 #include <bcm/error.h>
     27 
     28 #include <bcm_int/esw_dispatch.h>
     29 #include <bcm_int/api_xlate_port.h>
     30 
     31 #include <bcm_int/common/multicast.h>
     32 #include <bcm_int/esw/multicast.h>
     33 #include <bcm_int/esw/virtual.h>
     34 #include <bcm_int/esw/vlan.h>
     35 #include <bcm_int/esw/firebolt.h>
     36 #include <bcm_int/esw/trx.h>
     37 #include <bcm_int/esw/triumph2.h>
     38 #include <bcm_int/esw/trident.h>
     39 #include <bcm_int/esw/stack.h>
     40 #include <bcm_int/esw/trunk.h>
     41 #include <bcm_int/esw/ipmc.h>
     42 #if defined(BCM_TRIUMPH3_SUPPORT)
     43 #include <bcm_int/esw/triumph3.h>
     44 #endif /* BCM_TRIUMPH3_SUPPORT*/
     45 
     46 #if defined(BCM_TRIDENT2_SUPPORT)
     47 #include <bcm_int/esw/trident2.h>
     48 #endif /* BCM_TRIDENT2_SUPPORT*/
     49 
     50 #if defined(BCM_KATANA2_SUPPORT)
     51 #include <bcm_int/esw/katana2.h>
     52 #endif /*BCM_KATANA2_SUPPORT*/
     53 #if defined(BCM_KATANA_SUPPORT)
     54 #include <bcm_int/esw/katana.h>
     55 #endif /*BCM_KATANA_SUPPORT*/
     56 
     57 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     58 #include <bcm_int/esw/trident2plus.h>
     59 #include <bcm_int/esw/xgs5.h>
     60 #include <bcm_int/esw/vlan.h>
     61 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     62 
     63 #include <bcm_int/esw/policer.h>
     64 
     65 
     66 /* -------------------------------------------------------
     67  * Software book keeping for VLAN virtual port information
     68  * -------------------------------------------------------
     69  */
     70 
     71 typedef struct _bcm_tr2_vlan_vp_info_s {
     72     bcm_vlan_port_match_t criteria;
     73     uint32 flags;
     74     int match_count;
     75     bcm_vlan_t match_vlan;
     76     bcm_vlan_t match_inner_vlan;
     77     bcm_vlan_t match_tunnel_value;
     78     bcm_gport_t port;
     79 } _bcm_tr2_vlan_vp_info_t;
     80 
     81 typedef struct _bcm_tr2_vlan_virtual_bookkeeping_s {
     82     int vlan_virtual_initialized; /* Flag to check initialized status */
     83     sal_mutex_t vlan_virtual_mutex; /* VLAN virtual module lock */
     84     _bcm_tr2_vlan_vp_info_t *port_info; /* VP state */
     85 } _bcm_tr2_vlan_virtual_bookkeeping_t;
     86 
     87 STATIC _bcm_tr2_vlan_virtual_bookkeeping_t _bcm_tr2_vlan_virtual_bk_info[BCM_MAX_NUM_UNITS];
     88 
     89 #define VLAN_VIRTUAL_INFO(unit) (&_bcm_tr2_vlan_virtual_bk_info[unit])
     90 
     91 #define VLAN_VIRTUAL_INIT(unit)                                   \
     92     do {                                                          \
     93         if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {          \
     94             return BCM_E_UNIT;                                    \
     95         }                                                         \
     96         if (!VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized) { \
     97             return BCM_E_INIT;                                    \
     98         }                                                         \
     99     } while (0)
    100 
    101 #define VLAN_VIRTUAL_LOCK(unit) \
    102         sal_mutex_take(VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex, sal_mutex_FOREVER);
    103 
    104 #define VLAN_VIRTUAL_UNLOCK(unit) \
    105         sal_mutex_give(VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex);
    106 
    107 #define VLAN_VP_INFO(unit, vp) (&VLAN_VIRTUAL_INFO(unit)->port_info[vp])
    108 
    109 #ifdef BCM_TRIUMPH3_SUPPORT
    110 #define _BCM_VLAN_VPN_INVALID 0xFFFF     /* Invalid VLAN VPN */
    111 #define _BCM_VLAN_VFI_INVALID 0          /* Invalid VFI INDEX */
    112 #define VIRTUAL_INFO(unit)    (&_bcm_virtual_bk_info[unit])
    113 #endif
    114 
    115 /* ---------------------------------------------------------------------------- 
    116  *
    117  * Routines for creation and deletion of VLAN virtual ports
    118  *
    119  * ---------------------------------------------------------------------------- 
    120  */
    121 
    122 /*
    123  * Function:
    124  *      _bcm_tr2_vlan_vp_port_cnt_update
    125  * Purpose:
    126  *      Update port's VP count.
    127  * Parameters:
    128  *      unit  - (IN) SOC unit number. 
    129  *      gport - (IN) GPORT ID.
    130  *      vp    - (IN) Virtual port number.
    131  *      incr  - (IN) If TRUE, increment VP count, else decrease VP count.
    132  * Returns:
    133  *      BCM_X_XXX
    134  */
    135 STATIC int
    136 _bcm_tr2_vlan_vp_port_cnt_update(int unit, bcm_gport_t gport,
    137         int vp, int incr)
    138 {
    139     int mod_out, port_out, tgid_out, id_out;
    140     int idx;
    141     int mod_local = FALSE;
    142     _bcm_port_info_t *port_info;
    143     int local_member_count;
    144     int soc_max_num_ports = SOC_MAX_NUM_PORTS;
    145     uint32 port_flags;
    146 #if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
    147     bcm_port_t local_member_array[SOC_MAX_NUM_PP_PORTS];
    148 #else
    149     bcm_port_t local_member_array[SOC_MAX_NUM_PORTS];
    150 #endif
    151 
    152     if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) {
    153         soc_max_num_ports = SOC_MAX_NUM_PP_PORTS;
    154     }
    155 
    156     BCM_IF_ERROR_RETURN
    157         (_bcm_esw_gport_resolve(unit, gport, &mod_out, 
    158                                 &port_out, &tgid_out, &id_out));
    159     if (-1 != id_out) {
    160         return BCM_E_PARAM;
    161     }
    162 
    163     /* In case of extended queuing on KTX, tgid_out gets updated with
    164      * extended queue value. So set it to invalid value.
    165      */
    166 #ifdef BCM_KATANA_SUPPORT
    167     if (soc_feature(unit, soc_feature_extended_queueing)) {
    168         if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) ||
    169             (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ||
    170             (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport))) {
    171             tgid_out = BCM_TRUNK_INVALID;
    172         }
    173     }
    174 #endif
    175     /* Update the physical port's SW state. If associated with a trunk,
    176      * update each local physical port's SW state.
    177      */
    178 
    179     if (BCM_TRUNK_INVALID != tgid_out) {
    180 
    181         BCM_IF_ERROR_RETURN(_bcm_esw_trunk_local_members_get(unit, tgid_out,
    182                 soc_max_num_ports, local_member_array, &local_member_count));
    183 
    184         for (idx = 0; idx < local_member_count; idx++) {
    185             _bcm_port_info_access(unit, local_member_array[idx], &port_info);
    186             if (incr) {
    187                 port_info->vp_count++;
    188             } else {
    189                 port_info->vp_count--;
    190             }
    191             BCM_IF_ERROR_RETURN(
    192                 bcm_esw_port_vlan_member_get(
    193                     unit, local_member_array[idx], &port_flags));
    194             BCM_IF_ERROR_RETURN(
    195                 bcm_esw_port_vlan_member_set(
    196                     unit, local_member_array[idx], port_flags));
    197         }
    198     } else {
    199 
    200 
    201 #if defined(BCM_HGPROXY_COE_SUPPORT)
    202         if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
    203             BCM_GPORT_IS_SET(gport) &&
    204             _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) {
    205             if(_bcm_xgs5_subport_coe_gport_local(unit, gport)) {
    206 
    207                 BCM_IF_ERROR_RETURN(
    208                     _bcmi_coe_subport_physical_port_get(unit,
    209                                                         gport,
    210                                                         &port_out));
    211 
    212                 _bcm_port_info_access(unit, port_out, &port_info);
    213                 if (incr) {
    214                     port_info->vp_count++;
    215                 } else {
    216                      port_info->vp_count--;
    217                 }
    218                 BCM_IF_ERROR_RETURN(
    219                     bcm_esw_port_vlan_member_get(
    220                         unit, port_out, &port_flags));
    221                 BCM_IF_ERROR_RETURN(
    222                     bcm_esw_port_vlan_member_set(
    223                         unit, port_out, port_flags));
    224             }
    225         } else
    226 #endif
    227 
    228 #if defined(BCM_KATANA2_SUPPORT)
    229         if (BCM_GPORT_IS_SET(gport) &&
    230             _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, gport)) {
    231             BCM_IF_ERROR_RETURN(_bcm_kt2_modport_is_local_coe_subport(unit,
    232                 mod_out, port_out, &mod_local));
    233             if (mod_local) {
    234                 port_out = BCM_GPORT_SUBPORT_PORT_GET(gport);
    235                 _bcm_port_info_access(unit, port_out, &port_info);
    236                 if (incr) {
    237                     port_info->vp_count++;
    238                 } else {
    239                     port_info->vp_count--;
    240                 }
    241                 BCM_IF_ERROR_RETURN(
    242                     bcm_esw_port_vlan_member_get(
    243                         unit, port_out, &port_flags));
    244                 BCM_IF_ERROR_RETURN(
    245                     bcm_esw_port_vlan_member_set(
    246                         unit, port_out, port_flags));
    247             }
    248         }
    249 #endif
    250         BCM_IF_ERROR_RETURN
    251             (_bcm_esw_modid_is_local(unit, mod_out, &mod_local));
    252         if (mod_local) {
    253             if (soc_feature(unit, soc_feature_sysport_remap)) { 
    254                 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 
    255             }
    256             _bcm_port_info_access(unit, port_out, &port_info);
    257             if (incr) {
    258                 port_info->vp_count++;
    259             } else {
    260                 port_info->vp_count--;
    261             }
    262             BCM_IF_ERROR_RETURN(
    263                 bcm_esw_port_vlan_member_get(
    264                     unit, port_out, &port_flags));
    265             BCM_IF_ERROR_RETURN(
    266                 bcm_esw_port_vlan_member_set(
    267                     unit, port_out, port_flags));
    268         }
    269     }
    270 
    271     return BCM_E_NONE;
    272 }
    273 
    274 /*
    275  * Function:
    276  *      _bcm_tr2_vlan_virtual_free_resources
    277  * Purpose:
    278  *      Free all allocated tables and memory
    279  * Parameters:
    280  *      unit - SOC unit number
    281  * Returns:
    282  *      Nothing
    283  */
    284 STATIC void
    285 _bcm_tr2_vlan_virtual_free_resources(int unit)
    286 {
    287     if (VLAN_VIRTUAL_INFO(unit)->port_info) {
    288         sal_free(VLAN_VIRTUAL_INFO(unit)->port_info);
    289         VLAN_VIRTUAL_INFO(unit)->port_info = NULL;
    290     }
    291     if (VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex) {
    292         sal_mutex_destroy(VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex);
    293         VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex = NULL;
    294     } 
    295 }
    296 
    297 /*
    298  * Function:
    299  *      bcm_tr2_vlan_virtual_init
    300  * Purpose:
    301  *      Initialize the VLAN virtual port module.
    302  * Parameters:
    303  *      unit - SOC unit number.
    304  * Returns:
    305  *      BCM_E_XXX
    306  */
    307 int
    308 bcm_tr2_vlan_virtual_init(int unit)
    309 {
    310     int num_vp;
    311     int rv = BCM_E_NONE;
    312 
    313     if (VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized) {
    314         bcm_tr2_vlan_virtual_detach(unit);
    315     }
    316 
    317     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
    318     if (NULL == VLAN_VIRTUAL_INFO(unit)->port_info) {
    319         VLAN_VIRTUAL_INFO(unit)->port_info =
    320             sal_alloc(sizeof(_bcm_tr2_vlan_vp_info_t) * num_vp, "vlan_vp_info");
    321         if (NULL == VLAN_VIRTUAL_INFO(unit)->port_info) {
    322             _bcm_tr2_vlan_virtual_free_resources(unit);
    323             return BCM_E_MEMORY;
    324         }
    325     }
    326     sal_memset(VLAN_VIRTUAL_INFO(unit)->port_info, 0,
    327             sizeof(_bcm_tr2_vlan_vp_info_t) * num_vp);
    328 
    329     if (NULL == VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex) {
    330         VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex =
    331             sal_mutex_create("vlan virtual mutex");
    332         if (NULL == VLAN_VIRTUAL_INFO(unit)->vlan_virtual_mutex) {
    333             _bcm_tr2_vlan_virtual_free_resources(unit);
    334             return BCM_E_MEMORY;
    335         }
    336     }
    337 
    338     VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized = 1;
    339 
    340     /* Warm boot recovery of VLAN_VP_INFO depends on the completion
    341      * of _bcm_virtual_init, but _bcm_virtual_init is after the 
    342      * VLAN module in the init sequence. Hence, warm boot recovery
    343      * of VLAN_VP_INFO is moved to end of _bcm_virtual_init.
    344      */
    345 
    346     return rv;
    347 }
    348 
    349 /*
    350  * Function:
    351  *      bcm_tr2_vlan_virtual_detach
    352  * Purpose:
    353  *      Detach the VLAN virtual port module.
    354  * Parameters:
    355  *      unit - SOC unit number.
    356  * Returns:
    357  *      BCM_E_XXX
    358  */
    359 int
    360 bcm_tr2_vlan_virtual_detach(int unit)
    361 {
    362     _bcm_tr2_vlan_virtual_free_resources(unit);
    363 
    364     VLAN_VIRTUAL_INFO(unit)->vlan_virtual_initialized = 0;
    365 
    366     return BCM_E_NONE;
    367 }
    368 
    369 #ifdef BCM_TRIUMPH3_SUPPORT
    370 /*
    371  * Function:
    372  *      _bcm_tr3_vlan_nh_sd_tag_set
    373  * Purpose:
    374  *      Set SD TAG INFORMATION
    375  * Parameters:
    376  *      unit    - (IN) Device Number
    377  *      egr_nh  - (IN) Egress next hop information
    378  *      vlan_vp - (IN) VLAN port information
    379  *      drop    - (IN) Drop flag
    380  * Returns:
    381  *      BCM_E_XXX
    382  */
    383 STATIC int
    384 _bcm_tr3_vlan_nh_sd_tag_set(int unit, egr_l3_next_hop_entry_t *egr_nh,
    385                             bcm_vlan_port_t *vlan_vp, int drop)
    386 {
    387     int sd_tag_pri = -1;
    388     int sd_tag_cfi = -1;
    389     int sd_tag_vlan = -1;
    390     int sd_tag_action_present = -1;
    391     int sd_tag_action_not_present = -1;
    392     int tpid_index = -1;
    393 
    394     /* Check that unsupported flags are not set */
    395     if (!(vlan_vp->flags & (BCM_VLAN_PORT_SERVICE_VLAN_ADD |
    396                   BCM_VLAN_PORT_SERVICE_VLAN_REPLACE |
    397                   BCM_VLAN_PORT_SERVICE_VLAN_DELETE |
    398                   BCM_VLAN_PORT_SERVICE_VLAN_TPID_REPLACE  |
    399                   BCM_VLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE |
    400                   BCM_VLAN_PORT_SERVICE_VLAN_PRI_REPLACE |
    401                   BCM_VLAN_PORT_SERVICE_PRI_REPLACE |
    402                   BCM_VLAN_PORT_SERVICE_TPID_REPLACE))) {
    403         return BCM_E_NONE;
    404     }
    405 
    406     if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_ADD) {
    407         if (vlan_vp->egress_vlan >= BCM_VLAN_INVALID) {
    408             return BCM_E_PARAM;
    409         }
    410         if (vlan_vp->pkt_pri > BCM_PRIO_MAX) {
    411             return BCM_E_PARAM;
    412         }
    413         if (vlan_vp->pkt_cfi > 1) {
    414             return BCM_E_PARAM;
    415         }
    416 
    417         sd_tag_vlan = vlan_vp->egress_vlan;
    418         sd_tag_pri = vlan_vp->pkt_pri;
    419         sd_tag_cfi = vlan_vp->pkt_cfi;
    420         sd_tag_action_not_present = 0x1; /* ADD */
    421     }
    422 
    423     if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_TPID_REPLACE) {
    424         if (vlan_vp->egress_vlan >= BCM_VLAN_INVALID) {
    425             return BCM_E_PARAM;
    426         }
    427 
    428         /* REPLACE_VID_TPID */
    429         sd_tag_vlan = vlan_vp->egress_vlan;
    430         sd_tag_action_present = 0x1;
    431     } else if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_REPLACE) {
    432         if (vlan_vp->egress_vlan >= BCM_VLAN_INVALID) {
    433             return BCM_E_PARAM;
    434         }
    435         /* REPLACE_VID_ONLY */
    436         sd_tag_vlan = vlan_vp->egress_vlan;
    437         sd_tag_action_present = 0x2;
    438     } else if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_DELETE) {
    439         sd_tag_action_present = 0x3;
    440         sd_tag_action_not_present = 0;
    441     } else if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE) {
    442         if (vlan_vp->egress_vlan >= BCM_VLAN_INVALID) {
    443             return BCM_E_PARAM;
    444         }
    445         if (vlan_vp->pkt_pri > BCM_PRIO_MAX) {
    446             return BCM_E_PARAM;
    447         }
    448         if (vlan_vp->pkt_cfi > 1) {
    449             return BCM_E_PARAM;
    450         }
    451 
    452         /* REPLACE_VID_PRI_TPID */
    453         sd_tag_vlan = vlan_vp->egress_vlan;
    454         sd_tag_pri = vlan_vp->pkt_pri;
    455         sd_tag_cfi = vlan_vp->pkt_cfi;
    456         sd_tag_action_present = 0x4;
    457     } else if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_PRI_REPLACE) {
    458         if (vlan_vp->egress_vlan >= BCM_VLAN_INVALID) {
    459             return BCM_E_PARAM;
    460         }
    461         if (vlan_vp->pkt_pri > BCM_PRIO_MAX) {
    462             return BCM_E_PARAM;
    463         }
    464         if (vlan_vp->pkt_cfi > 1) {
    465             return BCM_E_PARAM;
    466         }
    467 
    468         /* REPLACE_VID_PRI_ONLY */
    469         sd_tag_vlan = vlan_vp->egress_vlan;
    470         sd_tag_pri = vlan_vp->pkt_pri;
    471         sd_tag_cfi = vlan_vp->pkt_cfi;
    472         sd_tag_action_present = 0x5;
    473     } else if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_PRI_REPLACE) {
    474         if (vlan_vp->pkt_pri > BCM_PRIO_MAX) {
    475             return BCM_E_PARAM;
    476         }
    477         if (vlan_vp->pkt_cfi > 1) {
    478             return BCM_E_PARAM;
    479         }
    480 
    481         /* REPLACE_PRI_ONLY */
    482         sd_tag_pri = vlan_vp->pkt_pri;
    483         sd_tag_cfi = vlan_vp->pkt_cfi;
    484         sd_tag_action_present = 0x6;
    485     } else if (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_TPID_REPLACE) {
    486         /* REPLACE_TPID_ONLY */
    487         sd_tag_action_present = 0x7;
    488     }
    489 
    490     if ((vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_ADD) ||
    491         (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_TPID_REPLACE) ||
    492         (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_TPID_REPLACE) ||
    493         (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE)) {
    494         /* TPID value is used */
    495         BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_entry_add(unit, vlan_vp->egress_service_tpid, &tpid_index));
    496     }
    497 
    498     if (sd_tag_vlan != -1) {
    499         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
    500             egr_nh, SD_TAG__SD_TAG_VIDf, sd_tag_vlan);
    501     }
    502 
    503     if (sd_tag_action_present != -1) {
    504         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    505             SD_TAG__SD_TAG_ACTION_IF_PRESENTf,
    506             sd_tag_action_present);
    507     }
    508 
    509     if (sd_tag_action_not_present != -1) {
    510         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    511             SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf,
    512             sd_tag_action_not_present);
    513     }
    514 
    515     if (sd_tag_pri != -1) {
    516         if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_PRIf)) {
    517             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    518                          SD_TAG__NEW_PRIf, sd_tag_pri);
    519         }
    520     }
    521 
    522     if (sd_tag_cfi != -1) {
    523         if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__NEW_CFIf)) {
    524             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    525                          SD_TAG__NEW_CFIf, sd_tag_cfi);
    526         }
    527         if(soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__SD_TAG_REMARK_CFIf)) {
    528             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    529                          SD_TAG__SD_TAG_REMARK_CFIf, 0x1);
    530         }
    531     }
    532 
    533     if (tpid_index != -1) {
    534         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
    535                          egr_nh, SD_TAG__SD_TAG_TPID_INDEXf, tpid_index);
    536     }
    537 
    538     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    539                     SD_TAG__BC_DROPf, drop ? 1 : 0);
    540     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    541                     SD_TAG__UUC_DROPf, drop ? 1 : 0);
    542     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    543                     SD_TAG__UMC_DROPf, drop ? 1 : 0);
    544     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
    545                     egr_nh, SD_TAG__DVP_IS_NETWORK_PORTf,
    546                     0);
    547     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    548                     SD_TAG__HG_LEARN_OVERRIDEf, 0);
    549     /* HG_MODIFY_ENABLE must be 0x0 for Ingress and Egress Chip */
    550     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    551                     SD_TAG__HG_MODIFY_ENABLEf, 0x0);
    552 
    553     return BCM_E_NONE;
    554 }
    555 #endif /* BCM_TRIUMPH3_SUPPORT */
    556 
    557 /*
    558  * Function:
    559  *      _bcm_tr2_vlan_vp_nh_info_set
    560  * Purpose:
    561  *      Get a next hop index and configure next hop tables.
    562  * Parameters:
    563  *      unit       - (IN) SOC unit number. 
    564  *      vlan_vp    - (IN) Pointer to VLAN virtual port structure. 
    565  *      vp         - (IN) Virtual port number. 
    566  *      drop       - (IN) Drop indication. 
    567  *      nh_index   - (IN/OUT) Next hop index. 
    568  * Returns:
    569  *      BCM_X_XXX
    570  */
    571 STATIC int
    572 _bcm_tr2_vlan_vp_nh_info_set(int unit, bcm_vlan_port_t *vlan_vp, int vp,
    573         int drop, int *nh_index)
    574 {
    575     int rv;
    576     uint32 nh_flags;
    577     bcm_l3_egress_t nh_info;
    578     egr_l3_next_hop_entry_t egr_nh;
    579     uint8 egr_nh_entry_type;
    580     bcm_module_t mod_out;
    581     bcm_port_t port_out;
    582     bcm_trunk_t trunk_id;
    583     int id;
    584     int ing_nh_port;
    585     int ing_nh_module;
    586     int ing_nh_trunk;
    587     ing_l3_next_hop_entry_t ing_nh;
    588     initial_ing_l3_next_hop_entry_t initial_ing_nh;
    589     soc_field_t ent_tpf = ENTRY_TYPEf;
    590     int bit_num;
    591     int network_group;
    592 #ifdef BCM_KATANA_SUPPORT
    593     int extended_queue, index;
    594 #endif
    595 
    596 #ifdef BCM_TRIUMPH3_SUPPORT
    597     uint32 mtu_profile_index = 0;
    598 #endif /* BCM_TRIUMPH3_SUPPORT */
    599 
    600     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
    601         ent_tpf = DATA_TYPEf;
    602     }
    603 
    604     /* Get a next hop index */
    605 
    606     if (vlan_vp->flags & BCM_VLAN_PORT_REPLACE) {
    607         if ((*nh_index > soc_mem_index_max(unit, EGR_L3_NEXT_HOPm)) ||
    608                 (*nh_index < soc_mem_index_min(unit, EGR_L3_NEXT_HOPm)))  {
    609             return BCM_E_PARAM;
    610         }
    611     } else {
    612         /*
    613          * Allocate a next-hop entry. By calling bcm_xgs3_nh_add()
    614          * with _BCM_L3_SHR_WRITE_DISABLE flag, a next-hop index is
    615          * allocated but nothing is written to hardware. The "nh_info"
    616          * in this case is not used, so just set to all zeros.
    617          */
    618         bcm_l3_egress_t_init(&nh_info);
    619 
    620         nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
    621         rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info, nh_index);
    622         BCM_IF_ERROR_RETURN(rv);
    623     }
    624 
    625     /* Write EGR_L3_NEXT_HOP entry */
    626 
    627     if (vlan_vp->flags & BCM_VLAN_PORT_REPLACE) {
    628         /* Read the existing egress next_hop entry */
    629         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
    630                 *nh_index, &egr_nh);
    631         BCM_IF_ERROR_RETURN(rv);
    632 
    633         /* Be sure that the existing entry is programmed to SD-tag */
    634         egr_nh_entry_type =
    635             soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ent_tpf);
    636         if (egr_nh_entry_type != 0x2) { /* != SD-tag */
    637             return BCM_E_PARAM;
    638         }
    639     } else {
    640         egr_nh_entry_type = 0x2; /* SD-tag */
    641     }
    642 
    643     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
    644     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    645             ent_tpf, egr_nh_entry_type);
    646 
    647     if ((vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL) ||
    648         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN) ||
    649         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN) ) {
    650         /* Add the LLTAG for outgoing packets */
    651         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
    652                 SD_TAG__LLTAG_VIDf, vlan_vp->match_tunnel_value);
    653        /* Set the LLTAG ACTION as  ADDLLTAG if flag was not set */
    654         if (vlan_vp->flags & BCM_VLAN_PORT_EGRESS_PON_TUNNEL_NONE) {
    655             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
    656                                     SD_TAG__LLTAG_ACTIONSf, 0x0);
    657         } else {
    658             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
    659                                     SD_TAG__LLTAG_ACTIONSf, 0x04); 
    660         }
    661     }
    662 
    663     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    664                 SD_TAG__DVPf, vp);
    665 
    666     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh, 
    667             SD_TAG__HG_HDR_SELf, 1);
    668 
    669     /* Set Egress Class */
    670     if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__CLASS_IDf)) {
    671         bit_num = soc_mem_field_length(unit, EGR_L3_NEXT_HOPm,
    672                                        SD_TAG__CLASS_IDf);
    673         if ( vlan_vp->if_class > ((1 << bit_num) - 1)) {
    674             return BCM_E_PARAM;
    675         } else {
    676             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    677                                 SD_TAG__CLASS_IDf, vlan_vp->if_class);
    678         }
    679     }
    680 
    681     /* Handle Split Horizon */
    682 
    683     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
    684         network_group = vlan_vp->egress_network_group_id;
    685         rv = _bcm_validate_splithorizon_network_group(unit,
    686              vlan_vp->flags & BCM_VLAN_PORT_NETWORK, &network_group);
    687         if (rv < 0) {
    688             goto cleanup;
    689         }
    690         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
    691                                 SD_TAG__DVP_NETWORK_GROUPf)) {
    692             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
    693                                 SD_TAG__DVP_NETWORK_GROUPf,
    694                                 network_group);
    695         }
    696     }
    697 #ifdef BCM_TRIUMPH3_SUPPORT
    698     if (soc_feature(unit, soc_feature_vlan_vfi)) {
    699         rv = _bcm_tr3_vlan_nh_sd_tag_set(unit, &egr_nh, vlan_vp, drop);
    700         if (rv < 0) {
    701             goto cleanup;
    702         }
    703     }
    704 #endif /* BCM_TRIUMPH3_SUPPORT */
    705 
    706     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
    707             MEM_BLOCK_ALL, *nh_index, &egr_nh);
    708     if (rv < 0) {
    709         goto cleanup;
    710     }
    711 
    712     /* Resolve gport */
    713 
    714     rv = _bcm_esw_gport_resolve(unit, vlan_vp->port, &mod_out, 
    715             &port_out, &trunk_id, &id);
    716     if (rv < 0) {
    717         goto cleanup;
    718     }
    719 
    720     ing_nh_port = -1;
    721     ing_nh_module = -1;
    722     ing_nh_trunk = -1;
    723 
    724     if (BCM_GPORT_IS_TRUNK(vlan_vp->port)) {
    725         ing_nh_module = -1;
    726         ing_nh_port = -1;
    727         ing_nh_trunk = trunk_id;
    728     } else {
    729         ing_nh_module = mod_out;
    730         ing_nh_port = port_out;
    731         ing_nh_trunk = -1;
    732     }
    733 
    734     /* Write ING_L3_NEXT_HOP entry */
    735 
    736     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
    737 
    738     if (soc_feature(unit, soc_feature_generic_dest)) {
    739         if (ing_nh_trunk == -1) {
    740             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
    741                 DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
    742                 (ing_nh_module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS |
    743                 ing_nh_port));
    744         } else {
    745             soc_mem_field32_dest_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
    746                 DESTINATIONf, SOC_MEM_FIF_DEST_LAG, ing_nh_trunk);
    747         }
    748     } else {
    749         if (ing_nh_trunk == -1) {
    750             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    751                     &ing_nh, PORT_NUMf, ing_nh_port);
    752             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    753                     &ing_nh, MODULE_IDf, ing_nh_module);
    754         } else {
    755             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    756                     &ing_nh, Tf, 1);
    757             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    758                     &ing_nh, TGIDf, ing_nh_trunk);
    759         }
    760     }
    761 
    762     soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh, DROPf, drop);
    763     
    764     if ((vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL) ||
    765         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN) ||
    766         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN) ) {
    767         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    768                         &ing_nh, ENTRY_TYPEf, 0x03); /* XPON DVP */
    769     } else {
    770         soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    771                 &ing_nh, ENTRY_TYPEf, 0x02); /* L2 DVP */
    772 
    773         /* Configuration of Mtu Size is valid only for L2 DVP Entry type  */
    774         if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm, MTU_SIZEf)) {
    775             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm,
    776                     &ing_nh, MTU_SIZEf, 0x3fff);
    777         }
    778 #ifdef BCM_TRIUMPH3_SUPPORT
    779         else if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,
    780                     DVP_ATTRIBUTE_1_INDEXf)) {
    781             BCM_IF_ERROR_RETURN(
    782                     _bcm_tr3_mtu_profile_index_get(unit, 0x3fff, &mtu_profile_index));
    783             soc_mem_field32_set(unit, ING_L3_NEXT_HOPm, &ing_nh,
    784                     DVP_ATTRIBUTE_1_INDEXf, mtu_profile_index);
    785         }
    786 #endif /*BCM_TRIUMPH3_SUPPORT */
    787     }
    788     rv = soc_mem_write (unit, ING_L3_NEXT_HOPm,
    789             MEM_BLOCK_ALL, *nh_index, &ing_nh);
    790     if (rv < 0) {
    791         goto cleanup;
    792     }
    793 
    794     /* Write INITIAL_ING_L3_NEXT_HOP entry */
    795 
    796     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
    797 
    798     if (soc_feature(unit, soc_feature_generic_dest)) {
    799         if (ing_nh_trunk == -1) {
    800             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm,
    801                 &initial_ing_nh, DESTINATIONf, SOC_MEM_FIF_DEST_DGPP,
    802                 (ing_nh_module << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS |
    803                 ing_nh_port));
    804         } else {
    805             soc_mem_field32_dest_set(unit, INITIAL_ING_L3_NEXT_HOPm,
    806                 &initial_ing_nh, DESTINATIONf, SOC_MEM_FIF_DEST_LAG,
    807                 ing_nh_trunk);
    808         }
    809     } else {
    810         if (ing_nh_trunk == -1) {
    811             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
    812                     &initial_ing_nh, PORT_NUMf, ing_nh_port);
    813             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
    814                     &initial_ing_nh, MODULE_IDf, ing_nh_module);
    815         } else {
    816             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
    817                     &initial_ing_nh, Tf, 1);
    818             soc_mem_field32_set(unit, INITIAL_ING_L3_NEXT_HOPm,
    819                     &initial_ing_nh, TGIDf, ing_nh_trunk);
    820         }
    821     }
    822     rv = soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
    823             MEM_BLOCK_ALL, *nh_index, &initial_ing_nh);
    824     if (rv < 0) {
    825         goto cleanup;
    826     }
    827 
    828 #ifdef BCM_KATANA_SUPPORT
    829     if (BCM_SUCCESS(rv)) {
    830         if (soc_feature(unit, soc_feature_extended_queueing)) {
    831             if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, *nh_index)) {
    832                 index = *nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
    833             } else {
    834                 index = *nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    835             }
    836             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(vlan_vp->port)) ||
    837                 (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(vlan_vp->port)) ||
    838                 (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(vlan_vp->port))) {
    839 #ifdef BCM_KATANA2_SUPPORT
    840                 if (SOC_IS_KATANA2(unit)) {
    841                     BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_index_resolve(unit, vlan_vp->port, 0,
    842                                         _BCM_KT2_COSQ_INDEX_STYLE_BUCKET, NULL,
    843                                         &extended_queue, NULL));
    844                 } else
    845 #endif
    846                 {
    847                     BCM_IF_ERROR_RETURN(_bcm_kt_cosq_index_resolve(unit, vlan_vp->port, 0,
    848                                         _BCM_KT_COSQ_INDEX_STYLE_BUCKET, NULL,
    849                                         &extended_queue, NULL));
    850                 }
    851                 rv = _bcm_kt_extended_queue_config(unit, vlan_vp->flags, vlan_vp->flags,
    852                                                    extended_queue,
    853                       (vlan_vp->qos_map_id & 0x3 /*_BCM_QOS_MAP_TYPE_MASK*/), &index);
    854             } else {
    855                 /* Reset extended queue configuration, if any */
    856                 if (vlan_vp->flags & BCM_L3_REPLACE) {
    857                     rv = _bcm_kt_extended_queue_config(unit, vlan_vp->flags, vlan_vp->flags,
    858                                                        0, 0, &index);
    859                 }
    860             }
    861        }
    862        if (rv < 0) {
    863            goto cleanup;
    864        }
    865     }
    866 #endif
    867     return rv;
    868 
    869 cleanup:
    870     if (!(vlan_vp->flags & BCM_VLAN_PORT_REPLACE)) {
    871         (void) bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, *nh_index);
    872     }
    873     return rv;
    874 }
    875 
    876 /*
    877  * Function:
    878  *      _bcm_tr2_vlan_vp_nh_info_delete
    879  * Purpose:
    880  *      Free next hop index and clear next hop tables.
    881  * Parameters:
    882  *      unit     - (IN) SOC unit number. 
    883  *      nh_index - (IN) Next hop index. 
    884  * Returns:
    885  *      BCM_X_XXX
    886  */
    887 STATIC int
    888 _bcm_tr2_vlan_vp_nh_info_delete(int unit, int nh_index)
    889 {
    890     egr_l3_next_hop_entry_t egr_nh;
    891     ing_l3_next_hop_entry_t ing_nh;
    892     initial_ing_l3_next_hop_entry_t initial_ing_nh;
    893 
    894 #ifdef BCM_TRIUMPH3_SUPPORT
    895     soc_field_t ent_tpf = ENTRY_TYPEf;
    896 
    897     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
    898         ent_tpf = DATA_TYPEf;
    899     }
    900     if (soc_feature(unit, soc_feature_vlan_vfi)) {
    901         int action_present = 0, action_not_present = 0, old_tpid_idx = -1;
    902         uint32  entry_type = 0;
    903 
    904         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm,
    905                                 MEM_BLOCK_ANY, nh_index, &egr_nh));
    906         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, ent_tpf);
    907         if (entry_type == 0x2) {
    908             action_present = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
    909                     SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
    910             action_not_present = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
    911                     SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
    912             if ((action_not_present == 0x1) || (action_present == 0x1) ||
    913                 (action_present == 0x4) || (action_present == 0x7)) {
    914                 old_tpid_idx = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
    915                                  &egr_nh, SD_TAG__SD_TAG_TPID_INDEXf);
    916                 BCM_IF_ERROR_RETURN(
    917                         _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_idx));
    918             }
    919         }
    920     }
    921 #endif /* BCM_TRIUMPH3_SUPPORT */
    922 
    923     /* Clear EGR_L3_NEXT_HOP entry */
    924     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
    925     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
    926                                    MEM_BLOCK_ALL, nh_index, &egr_nh));
    927 
    928     /* Clear ING_L3_NEXT_HOP entry */
    929     sal_memset(&ing_nh, 0, sizeof(ing_l3_next_hop_entry_t));
    930     BCM_IF_ERROR_RETURN(soc_mem_write (unit, ING_L3_NEXT_HOPm,
    931                                    MEM_BLOCK_ALL, nh_index, &ing_nh));
    932 
    933     /* Clear INITIAL_ING_L3_NEXT_HOP entry */
    934     sal_memset(&initial_ing_nh, 0, sizeof(initial_ing_l3_next_hop_entry_t));
    935     BCM_IF_ERROR_RETURN(soc_mem_write(unit, INITIAL_ING_L3_NEXT_HOPm,
    936                                    MEM_BLOCK_ALL, nh_index, &initial_ing_nh));
    937 
    938     /* Free the next-hop index. */
    939     BCM_IF_ERROR_RETURN
    940         (bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index));
    941 
    942     return BCM_E_NONE;
    943 }
    944 
    945 #if defined(BCM_TRIUMPH3_SUPPORT) 
    946 /*
    947  * Function:
    948  *      _tr3_vlan_vp_match_add
    949  * Purpose:
    950  *      Add match criteria for VLAN VP.
    951  * Parameters:
    952  *      unit - (IN) SOC unit number. 
    953  *      vlan_vp - (IN) Pointer to VLAN virtual port structure. 
    954  *      vp - (IN) Virtual port number.
    955  * Returns:
    956  *      BCM_X_XXX
    957  */
    958 STATIC int
    959 _tr3_vlan_vp_match_add(int unit, bcm_vlan_port_t *vlan_vp, int vp)
    960 {
    961     vlan_xlate_entry_t vent;
    962     vlan_xlate_extd_entry_t vxent, old_vxent;
    963     int key_type = 0;
    964     bcm_vlan_action_set_t action;
    965     uint32 profile_idx;
    966     int rv;
    967 
    968     if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_NONE) {
    969        return BCM_E_NONE;
    970     }
    971 
    972     if (!((vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) ||
    973           (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) ||
    974           (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) ||
    975           (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN))) {
    976         return BCM_E_PARAM;
    977     }
    978 
    979     if ((vlan_vp->egress_vlan > BCM_VLAN_MAX) ||
    980         (vlan_vp->egress_inner_vlan > BCM_VLAN_MAX)) {
    981         return BCM_E_PARAM;
    982     } 
    983 
    984     sal_memset(&vent, 0, sizeof(vlan_xlate_entry_t));
    985     sal_memset(&vxent, 0, sizeof(vlan_xlate_extd_entry_t));
    986 
    987     if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) {
    988         key_type = bcmVlanTranslateKeyPortOuter;
    989     } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) {
    990         key_type = bcmVlanTranslateKeyPortDouble;
    991     } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) {
    992         key_type = bcmVlanTranslateKeyPortOuterTag;
    993     } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN) {
    994         key_type = bcmVlanTranslateKeyPortInner;
    995     }
    996     BCM_IF_ERROR_RETURN
    997         (_bcm_trx_vlan_translate_entry_assemble(unit, &vent,
    998                                                 vlan_vp->port,
    999                                                 key_type,
   1000                                                 vlan_vp->match_inner_vlan,
   1001                                                 vlan_vp->match_vlan));
   1002 
   1003     BCM_IF_ERROR_RETURN
   1004         (_bcm_tr3_vxlate2vxlate_extd(unit,&vent,&vxent));
   1005 
   1006     soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_0f, 1);
   1007     soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, VALID_1f, 1);
   1008 
   1009     soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, XLATE__MPLS_ACTIONf, 0x1); /* SVP */
   1010     soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, SOURCE_VPf, vp);
   1011     soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, NEW_OVIDf,
   1012                                 vlan_vp->egress_vlan);
   1013     soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, NEW_IVIDf,
   1014                                 vlan_vp->egress_inner_vlan);
   1015 
   1016     bcm_vlan_action_set_t_init(&action);
   1017 
   1018     if (vlan_vp->flags & BCM_VLAN_PORT_INNER_VLAN_PRESERVE) {
   1019         action.dt_outer = bcmVlanActionReplace;
   1020         action.dt_outer_prio = bcmVlanActionReplace;
   1021         action.dt_inner = bcmVlanActionNone;
   1022         action.dt_inner_prio = bcmVlanActionNone;
   1023     } else {
   1024         if (soc_feature(unit, soc_feature_vlan_copy_action)) {
   1025             action.dt_outer = bcmVlanActionCopy;
   1026             action.dt_outer_prio = bcmVlanActionCopy;
   1027         } else {
   1028             action.dt_outer = bcmVlanActionReplace;
   1029             action.dt_outer_prio = bcmVlanActionReplace;
   1030         }
   1031         action.dt_inner = bcmVlanActionDelete;
   1032         action.dt_inner_prio = bcmVlanActionDelete;
   1033     }
   1034 
   1035     action.ot_outer = bcmVlanActionReplace;
   1036     action.ot_outer_prio = bcmVlanActionReplace;
   1037     if (vlan_vp->flags & BCM_VLAN_PORT_INNER_VLAN_ADD) {
   1038         action.ot_inner = bcmVlanActionAdd;
   1039     } else {
   1040         action.ot_inner = bcmVlanActionNone;
   1041     }
   1042 
   1043     BCM_IF_ERROR_RETURN
   1044         (_bcm_trx_vlan_action_profile_entry_add(unit, &action, &profile_idx));
   1045 
   1046     soc_VLAN_XLATE_EXTDm_field32_set(unit, &vxent, TAG_ACTION_PROFILE_PTRf,
   1047                                 profile_idx);
   1048 
   1049     rv = soc_mem_insert_return_old(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL,
   1050                                    &vxent, &old_vxent);
   1051     if (rv == SOC_E_EXISTS) {
   1052         /* Delete the old vlan translate profile entry */
   1053         profile_idx = soc_VLAN_XLATE_EXTDm_field32_get(unit, &old_vxent,
   1054                                                   TAG_ACTION_PROFILE_PTRf);       
   1055         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   1056     }
   1057     return rv;
   1058 }
   1059 
   1060 /*
   1061  * Function:
   1062  *      _tr3_vlan_vp_match_delete
   1063  * Purpose:
   1064  *      Delete match criteria for VLAN VP.
   1065  * Parameters:
   1066  *      unit - (IN) SOC unit number. 
   1067  *      vp - (IN) Virtual port number.
   1068  * Returns:
   1069  *      BCM_X_XXX
   1070  */
   1071 STATIC int
   1072 _tr3_vlan_vp_match_delete(int unit, int vp)
   1073 {
   1074     vlan_xlate_entry_t vent;
   1075     vlan_xlate_extd_entry_t vxent, old_vxent;
   1076     int key_type = 0;
   1077     uint32 profile_idx;
   1078     int rv;
   1079 
   1080     if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_NONE) {
   1081         return BCM_E_NONE;
   1082     }
   1083 
   1084     if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) {
   1085         key_type = bcmVlanTranslateKeyPortOuter;
   1086     } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) {
   1087         key_type = bcmVlanTranslateKeyPortDouble;
   1088     } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) {
   1089         key_type = bcmVlanTranslateKeyPortOuterTag;
   1090     } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN) {
   1091         key_type = bcmVlanTranslateKeyPortInner;
   1092     } else {
   1093         return BCM_E_INTERNAL;
   1094     }
   1095 
   1096     sal_memset(&vent, 0, sizeof(vlan_xlate_entry_t));
   1097     sal_memset(&vxent, 0, sizeof(vlan_xlate_extd_entry_t));
   1098     BCM_IF_ERROR_RETURN
   1099         (_bcm_trx_vlan_translate_entry_assemble(unit, &vent,
   1100                                                 VLAN_VP_INFO(unit, vp)->port,
   1101                                                 key_type,
   1102                                                 VLAN_VP_INFO(unit, vp)->match_inner_vlan,
   1103                                                 VLAN_VP_INFO(unit, vp)->match_vlan));
   1104     BCM_IF_ERROR_RETURN
   1105         (_bcm_tr3_vxlate2vxlate_extd(unit,&vent,&vxent));
   1106 
   1107     rv = soc_mem_delete_return_old(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL, 
   1108                                    &vxent, &old_vxent);
   1109     if ((rv == SOC_E_NONE) && 
   1110         soc_VLAN_XLATE_EXTDm_field32_get(unit, &old_vxent, VALID_0f)) {
   1111         profile_idx = soc_VLAN_XLATE_EXTDm_field32_get(unit, &old_vxent,
   1112                                                   TAG_ACTION_PROFILE_PTRf);       
   1113         /* Delete the old vlan action profile entry */
   1114         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   1115     }
   1116     return rv;
   1117 }
   1118 
   1119 /*
   1120  * Function:
   1121  *      _tr3_vlan_vp_match_get
   1122  * Purpose:
   1123  *      Get match criteria for VLAN VP.
   1124  * Parameters:
   1125  *      unit - (IN) SOC unit number. 
   1126  *      vp - (IN) Virtual port number.
   1127  *      vlan_vp - (OUT) Pointer to VLAN virtual port structure. 
   1128  * Returns:
   1129  *      BCM_X_XXX
   1130  */
   1131 STATIC int
   1132 _tr3_vlan_vp_match_get(int unit, int vp, bcm_vlan_port_t *vlan_vp)
   1133 {
   1134     vlan_xlate_entry_t vent;
   1135     vlan_xlate_extd_entry_t vxent, vxent_out;
   1136     int key_type = 0;
   1137     int idx;
   1138 
   1139     vlan_vp->criteria = VLAN_VP_INFO(unit, vp)->criteria;
   1140     vlan_vp->match_vlan = VLAN_VP_INFO(unit, vp)->match_vlan;
   1141     vlan_vp->match_inner_vlan = VLAN_VP_INFO(unit, vp)->match_inner_vlan;
   1142     vlan_vp->port = VLAN_VP_INFO(unit, vp)->port;
   1143 
   1144     if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_NONE) {
   1145         return BCM_E_NONE;
   1146     }
   1147 
   1148     if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) {
   1149         key_type = bcmVlanTranslateKeyPortOuter;
   1150     } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) {
   1151         key_type = bcmVlanTranslateKeyPortDouble;
   1152     } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) {
   1153         key_type = bcmVlanTranslateKeyPortOuterTag;
   1154     } else if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN) {
   1155         key_type = bcmVlanTranslateKeyPortInner;
   1156     } else {
   1157         return BCM_E_INTERNAL;
   1158     }
   1159 
   1160     sal_memset(&vent, 0, sizeof(vlan_xlate_entry_t));
   1161     sal_memset(&vxent, 0, sizeof(vlan_xlate_extd_entry_t));
   1162 
   1163     BCM_IF_ERROR_RETURN
   1164         (_bcm_trx_vlan_translate_entry_assemble(unit, &vent,
   1165                                                 VLAN_VP_INFO(unit, vp)->port,
   1166                                                 key_type,
   1167                                                 VLAN_VP_INFO(unit, vp)->match_inner_vlan,
   1168                                                 VLAN_VP_INFO(unit, vp)->match_vlan));
   1169 
   1170     BCM_IF_ERROR_RETURN
   1171         (_bcm_tr3_vxlate2vxlate_extd(unit,&vent,&vxent));
   1172 
   1173     BCM_IF_ERROR_RETURN
   1174         (soc_mem_search(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL,
   1175                         &idx, &vxent, &vxent_out, 0));
   1176     vlan_vp->egress_vlan = soc_VLAN_XLATE_EXTDm_field32_get(unit, &vxent_out,
   1177                                                        NEW_OVIDf);
   1178     vlan_vp->egress_inner_vlan = soc_VLAN_XLATE_EXTDm_field32_get(unit, &vxent_out,
   1179                                                        NEW_IVIDf);
   1180 
   1181     return BCM_E_NONE;
   1182 }
   1183 
   1184 /*
   1185  * Function:
   1186  *      _tr3_vlan_vp_match_cleanup
   1187  * Purpose:
   1188  *      Clean up match criteria for VLAN VP.
   1189  * Parameters:
   1190  *      unit - (IN) SOC unit number.
   1191  *      vlan_vp - (IN) Pointer to VLAN virtual port structure..
   1192  * Returns:
   1193  *      BCM_X_XXX
   1194  */
   1195 STATIC int
   1196 _tr3_vlan_vp_match_cleanup(int unit, bcm_vlan_port_t *vlan_vp)
   1197 {
   1198     vlan_xlate_entry_t vent;
   1199     vlan_xlate_extd_entry_t vxent, old_vxent;
   1200     int key_type = 0;
   1201     uint32 profile_idx;
   1202     int rv;
   1203 
   1204     if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_NONE) {
   1205         return BCM_E_NONE;
   1206     }
   1207 
   1208     if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN) {
   1209         key_type = bcmVlanTranslateKeyPortOuter;
   1210     } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED) {
   1211         key_type = bcmVlanTranslateKeyPortDouble;
   1212     } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_VLAN16) {
   1213         key_type = bcmVlanTranslateKeyPortOuterTag;
   1214     } else if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN) {
   1215         key_type = bcmVlanTranslateKeyPortInner;
   1216     } else {
   1217         return BCM_E_INTERNAL;
   1218     }
   1219 
   1220     sal_memset(&vent, 0, sizeof(vlan_xlate_entry_t));
   1221     sal_memset(&vxent, 0, sizeof(vlan_xlate_extd_entry_t));
   1222     BCM_IF_ERROR_RETURN
   1223         (_bcm_trx_vlan_translate_entry_assemble(unit, &vent,
   1224                                                 vlan_vp->port,
   1225                                                 key_type,
   1226                                                 vlan_vp->match_inner_vlan,
   1227                                                 vlan_vp->match_vlan));
   1228     BCM_IF_ERROR_RETURN
   1229         (_bcm_tr3_vxlate2vxlate_extd(unit,&vent,&vxent));
   1230 
   1231     rv = soc_mem_delete_return_old(unit, VLAN_XLATE_EXTDm, MEM_BLOCK_ALL,
   1232                                    &vxent, &old_vxent);
   1233     if ((rv == SOC_E_NONE) &&
   1234         soc_VLAN_XLATE_EXTDm_field32_get(unit, &old_vxent, VALID_0f)) {
   1235         profile_idx = soc_VLAN_XLATE_EXTDm_field32_get(unit, &old_vxent,
   1236                                                   TAG_ACTION_PROFILE_PTRf);
   1237         /* Delete the old vlan action profile entry */
   1238         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   1239     }
   1240     return rv;
   1241 }
   1242 #endif   /* TRIUMPH3 support */
   1243 
   1244 #ifdef BCM_TRIDENT2_SUPPORT
   1245 
   1246 /*
   1247  * Function:
   1248  *      _bcm_td2_vlan_match_vp_replace
   1249  * Purpose:
   1250  *      Replace VP value in VLAN VP's match entry.
   1251  * Parameters:
   1252  *      unit   - (IN) SOC unit number. 
   1253  *      vp     - (IN) VLAN VP whose match entry is being replaced.
   1254  *      new_vp - (IN) New VP value.
   1255  *      old_vp - (OUT) Old VP value.
   1256  * Returns:
   1257  *      BCM_X_XXX
   1258  */
   1259 STATIC int
   1260 _bcm_td2_vlan_match_vp_replace(int unit, int vp, int new_vp, int *old_vp)
   1261 {
   1262     int rv = BCM_E_NONE;
   1263     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   1264     uint32      old_vent[SOC_MAX_MEM_FIELD_WORDS];
   1265     soc_mem_t   mem = VLAN_XLATEm;
   1266     int key_type;
   1267     int entry_index;
   1268     _bcm_tr2_vlan_vp_info_t *vlan_vp = VLAN_VP_INFO(unit, vp);
   1269 
   1270     switch(vlan_vp->criteria) {
   1271         case BCM_VLAN_PORT_MATCH_NONE:
   1272             return BCM_E_NONE;
   1273             break;
   1274         case BCM_VLAN_PORT_MATCH_PORT_VLAN:
   1275             key_type = bcmVlanTranslateKeyPortOuter;
   1276             break;
   1277         case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED:
   1278             key_type = bcmVlanTranslateKeyPortDouble;
   1279             break;
   1280         case BCM_VLAN_PORT_MATCH_PORT_VLAN16:
   1281             key_type = bcmVlanTranslateKeyPortOuterTag;
   1282             break;
   1283         case BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN:
   1284             key_type = bcmVlanTranslateKeyPortInner;
   1285             break;
   1286         default:
   1287             return BCM_E_INTERNAL;
   1288     }
   1289 
   1290     sal_memset(vent, 0, sizeof(vent));
   1291     sal_memset(old_vent, 0, sizeof(old_vent));
   1292     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   1293         mem = VLAN_XLATE_1_DOUBLEm;
   1294     }
   1295     /* Construct lookup key */
   1296     BCM_IF_ERROR_RETURN
   1297         (_bcm_trx_vlan_translate_entry_assemble(unit, vent,
   1298                                                 vlan_vp->port, key_type,
   1299                                                 vlan_vp->match_inner_vlan,
   1300                                                 vlan_vp->match_vlan));
   1301     /* Lookup existing entry */
   1302     SOC_IF_ERROR_RETURN(
   1303         soc_mem_search(unit, mem, MEM_BLOCK_ALL,
   1304                        &entry_index, vent, old_vent, 0));
   1305     /* Replace entry's VP value */
   1306     *old_vp = soc_mem_field32_get(unit, mem, old_vent, SOURCE_VPf);
   1307     soc_mem_field32_set(unit, mem, old_vent, SOURCE_VPf, new_vp);
   1308 
   1309     /* Insert new entry */
   1310     rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, old_vent);
   1311     if (rv == SOC_E_EXISTS) {
   1312         rv = BCM_E_NONE;
   1313     } else {
   1314         return BCM_E_INTERNAL;
   1315     }
   1316 
   1317     return rv;
   1318 }
   1319 
   1320 /*
   1321  * Function:
   1322  *      bcm_td2_vlan_vp_source_vp_lag_set
   1323  * Purpose:
   1324  *      Set source VP LAG for a VLAN virtual port.
   1325  * Parameters:
   1326  *      unit - (IN) SOC unit number. 
   1327  *      gport - (IN) VLAN virtual port GPORT ID. 
   1328  *      vp_lag_vp - (IN) VP representing VP LAG. 
   1329  * Returns:
   1330  *      BCM_X_XXX
   1331  */
   1332 int
   1333 bcm_td2_vlan_vp_source_vp_lag_set(int unit, bcm_gport_t gport,
   1334         int vp_lag_vp)
   1335 {
   1336     int rv;
   1337     int vp, old_vp;
   1338 
   1339     VLAN_VIRTUAL_INIT(unit);
   1340 
   1341     VLAN_VIRTUAL_LOCK(unit);
   1342 
   1343     if (!BCM_GPORT_IS_VLAN_PORT(gport)) {
   1344         VLAN_VIRTUAL_UNLOCK(unit);
   1345         return BCM_E_PARAM;
   1346     }
   1347 
   1348     vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
   1349 
   1350     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   1351         VLAN_VIRTUAL_UNLOCK(unit);
   1352         return BCM_E_PARAM;
   1353     }
   1354 
   1355     /* Set source VP LAG by replacing the SVP field in VLAN VP's
   1356      * match entry with the VP value representing the VP LAG.
   1357      */
   1358     rv = _bcm_td2_vlan_match_vp_replace(unit, vp, vp_lag_vp, &old_vp);
   1359     
   1360     VLAN_VIRTUAL_UNLOCK(unit);
   1361 
   1362     return rv;
   1363 }
   1364 
   1365 /*
   1366  * Function:
   1367  *      bcm_td2_vlan_vp_source_vp_lag_clear
   1368  * Purpose:
   1369  *      Clear source VP LAG for a VLAN virtual port.
   1370  * Parameters:
   1371  *      unit - (IN) SOC unit number. 
   1372  *      gport - (IN) VLAN virtual port GPORT ID. 
   1373  *      vp_lag_vp - (IN) VP representing VP LAG. 
   1374  * Returns:
   1375  *      BCM_X_XXX
   1376  */
   1377 int
   1378 bcm_td2_vlan_vp_source_vp_lag_clear(int unit, bcm_gport_t gport,
   1379         int vp_lag_vp)
   1380 {
   1381     int rv;
   1382     int vp, old_vp;
   1383 
   1384     VLAN_VIRTUAL_INIT(unit);
   1385 
   1386     VLAN_VIRTUAL_LOCK(unit);
   1387 
   1388     if (!BCM_GPORT_IS_VLAN_PORT(gport)) {
   1389         VLAN_VIRTUAL_UNLOCK(unit);
   1390         return BCM_E_PARAM;
   1391     }
   1392 
   1393     vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
   1394 
   1395     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   1396         VLAN_VIRTUAL_UNLOCK(unit);
   1397         return BCM_E_PARAM;
   1398     }
   1399 
   1400     /* Clear source VP LAG by replacing the SVP field in VLAN VP's
   1401      * match entry with the VP value.
   1402      */
   1403     rv = _bcm_td2_vlan_match_vp_replace(unit, vp, vp, &old_vp);
   1404 
   1405     /* Check that the old VP value matches the VP value representing
   1406      * the VP LAG or has been restored.
   1407      */
   1408     if (BCM_SUCCESS(rv)) {
   1409         if ((old_vp != vp_lag_vp) && (old_vp != vp)) {
   1410             rv = BCM_E_INTERNAL;
   1411         }
   1412     }
   1413 
   1414     VLAN_VIRTUAL_UNLOCK(unit);
   1415 
   1416     return rv;
   1417 }
   1418 
   1419 /*
   1420  * Function:
   1421  *      bcm_td2_vlan_vp_source_vp_lag_get
   1422  * Purpose:
   1423  *      Get source VP LAG for a VLAN virtual port.
   1424  * Parameters:
   1425  *      unit - (IN) SOC unit number. 
   1426  *      gport - (IN) VLAN virtual port GPORT ID. 
   1427  *      vp_lag_vp - (OUT) VP representing VP LAG. 
   1428  * Returns:
   1429  *      BCM_X_XXX
   1430  */
   1431 int
   1432 bcm_td2_vlan_vp_source_vp_lag_get(int unit, bcm_gport_t gport,
   1433         int *vp_lag_vp)
   1434 {
   1435     int rv;
   1436     int vp;
   1437     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   1438     uint32      old_vent[SOC_MAX_MEM_FIELD_WORDS];
   1439     soc_mem_t   mem = VLAN_XLATEm;
   1440     int key_type;
   1441     int entry_index;
   1442     _bcm_tr2_vlan_vp_info_t *vlan_vp = NULL;
   1443 
   1444     VLAN_VIRTUAL_INIT(unit);
   1445 
   1446     VLAN_VIRTUAL_LOCK(unit);
   1447 
   1448     if (!BCM_GPORT_IS_VLAN_PORT(gport)) {
   1449         VLAN_VIRTUAL_UNLOCK(unit);
   1450         return BCM_E_PARAM;
   1451     }
   1452 
   1453     vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
   1454 
   1455     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   1456         VLAN_VIRTUAL_UNLOCK(unit);
   1457         return BCM_E_PARAM;
   1458     }
   1459 
   1460     vlan_vp = VLAN_VP_INFO(unit, vp);
   1461 
   1462     switch(vlan_vp->criteria) {
   1463         case BCM_VLAN_PORT_MATCH_NONE:
   1464             VLAN_VIRTUAL_UNLOCK(unit);
   1465             return BCM_E_NONE;
   1466             break;
   1467         case BCM_VLAN_PORT_MATCH_PORT_VLAN:
   1468             key_type = bcmVlanTranslateKeyPortOuter;
   1469             break;
   1470         case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED:
   1471             key_type = bcmVlanTranslateKeyPortDouble;
   1472             break;
   1473         case BCM_VLAN_PORT_MATCH_PORT_VLAN16:
   1474             key_type = bcmVlanTranslateKeyPortOuterTag;
   1475             break;
   1476         case BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN:
   1477             key_type = bcmVlanTranslateKeyPortInner;
   1478             break;
   1479         default:
   1480             VLAN_VIRTUAL_UNLOCK(unit);
   1481             return BCM_E_INTERNAL;
   1482     }
   1483 
   1484     sal_memset(vent, 0, sizeof(vent));
   1485     sal_memset(old_vent, 0, sizeof(old_vent));
   1486     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   1487         mem = VLAN_XLATE_1_DOUBLEm;
   1488     }
   1489     /* Construct lookup key */
   1490     rv = _bcm_trx_vlan_translate_entry_assemble(unit, vent,
   1491                                                 vlan_vp->port, key_type,
   1492                                                 vlan_vp->match_inner_vlan,
   1493                                                 vlan_vp->match_vlan);
   1494     if (BCM_FAILURE(rv)) {
   1495         VLAN_VIRTUAL_UNLOCK(unit);
   1496         return rv;
   1497     }
   1498 
   1499     /* Lookup existing entry */
   1500     rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL,
   1501                         &entry_index, vent, old_vent, 0);
   1502     if (SOC_FAILURE(rv)) {
   1503         VLAN_VIRTUAL_UNLOCK(unit);
   1504         return rv;
   1505     }
   1506 
   1507     /* Get VP value representing VP LAG */
   1508     *vp_lag_vp = soc_mem_field32_get(unit, mem, old_vent, SOURCE_VPf);
   1509     if (!_bcm_vp_used_get(unit, *vp_lag_vp, _bcmVpTypeVpLag)) {
   1510         VLAN_VIRTUAL_UNLOCK(unit);
   1511         return BCM_E_INTERNAL;
   1512     }
   1513 
   1514     VLAN_VIRTUAL_UNLOCK(unit);
   1515 
   1516     return rv;
   1517 }
   1518 
   1519 #endif /* BCM_TRIDENT2_SUPPORT */
   1520 
   1521 /*
   1522  * Function:
   1523  *      _tr2_vlan_vp_match_add
   1524  * Purpose:
   1525  *      Add match criteria for VLAN VP.
   1526  * Parameters:
   1527  *      unit - (IN) SOC unit number. 
   1528  *      vlan_vp - (IN) Pointer to VLAN virtual port structure. 
   1529  *      vp - (IN) Virtual port number.
   1530  * Returns:
   1531  *      BCM_X_XXX
   1532  */
   1533 STATIC int
   1534 _tr2_vlan_vp_match_add(int unit, bcm_vlan_port_t *vlan_vp, int vp)
   1535 {
   1536     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   1537     uint32      old_vent[SOC_MAX_MEM_FIELD_WORDS];
   1538     soc_mem_t   mem = VLAN_XLATEm;
   1539     int key_type = 0;
   1540     bcm_vlan_action_set_t action;
   1541     uint32 profile_idx;
   1542     int rv;
   1543 
   1544     if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_NONE) {
   1545        return BCM_E_NONE;
   1546     }
   1547 
   1548     switch (vlan_vp->criteria) {
   1549         case BCM_VLAN_PORT_MATCH_PORT_VLAN:
   1550             key_type = bcmVlanTranslateKeyPortOuter;
   1551             break;
   1552         case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED:  
   1553             key_type = bcmVlanTranslateKeyPortDouble;
   1554             break;
   1555         case BCM_VLAN_PORT_MATCH_PORT_VLAN16:
   1556             key_type = bcmVlanTranslateKeyPortOuterTag;
   1557             break;
   1558         case BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN:
   1559             key_type = bcmVlanTranslateKeyPortInner;
   1560             break;
   1561         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1562             key_type = bcmVlanTranslateKeyPortPonTunnel;
   1563             break;
   1564         case  BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1565             key_type = bcmVlanTranslateKeyPortPonTunnelOuter;
   1566             break;
   1567         case  BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   1568             key_type = bcmVlanTranslateKeyPortPonTunnelInner;
   1569             break;
   1570         default:
   1571             return BCM_E_PARAM;
   1572     }
   1573 
   1574     if ((vlan_vp->egress_vlan > BCM_VLAN_MAX) ||
   1575         (vlan_vp->egress_inner_vlan > BCM_VLAN_MAX)) {
   1576         return BCM_E_PARAM;
   1577     } 
   1578 
   1579     sal_memset(vent, 0, sizeof(vent));
   1580     sal_memset(old_vent, 0, sizeof(old_vent));
   1581 
   1582     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   1583         mem = VLAN_XLATE_1_DOUBLEm;
   1584     }
   1585 
   1586     if (soc_feature(unit, soc_feature_base_valid)) {
   1587         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
   1588         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
   1589     } else {
   1590         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
   1591     }
   1592 
   1593     switch (vlan_vp->criteria) {
   1594         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1595             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1596                                                 vlan_vp->port,
   1597                                                 key_type,
   1598                                                 vlan_vp->match_tunnel_value,
   1599                                                 0);
   1600             break;
   1601         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1602             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1603                                                 vlan_vp->port,
   1604                                                 key_type,
   1605                                                 vlan_vp->match_tunnel_value,
   1606                                                 vlan_vp->match_vlan);
   1607             break;
   1608         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   1609             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1610                                                 vlan_vp->port,
   1611                                                 key_type,
   1612                                                 vlan_vp->match_tunnel_value,
   1613                                                 vlan_vp->match_inner_vlan);
   1614             break;
   1615         default:
   1616             rv = _bcm_trx_vlan_translate_entry_assemble(unit, vent,
   1617                                                 vlan_vp->port,
   1618                                                 key_type,
   1619                                                 vlan_vp->match_inner_vlan,
   1620                                                 vlan_vp->match_vlan);
   1621             break;
   1622     }
   1623 
   1624     if(BCM_FAILURE(rv)) {
   1625         return rv;
   1626     }
   1627 
   1628     bcm_vlan_action_set_t_init(&action);
   1629 
   1630     if (vlan_vp->flags & BCM_VLAN_PORT_INNER_VLAN_PRESERVE) {
   1631         action.dt_outer = bcmVlanActionReplace;
   1632         action.dt_outer_prio = bcmVlanActionReplace;
   1633         action.dt_inner = bcmVlanActionNone;
   1634         action.dt_inner_prio = bcmVlanActionNone;
   1635     } else {
   1636         if (soc_feature(unit, soc_feature_vlan_copy_action)) {
   1637             action.dt_outer = bcmVlanActionCopy;
   1638             action.dt_outer_prio = bcmVlanActionCopy;
   1639         } else {
   1640             action.dt_outer = bcmVlanActionReplace;
   1641             action.dt_outer_prio = bcmVlanActionReplace;
   1642         }
   1643         action.dt_inner = bcmVlanActionDelete;
   1644         action.dt_inner_prio = bcmVlanActionDelete;
   1645     }
   1646 
   1647     action.ot_outer = bcmVlanActionReplace;
   1648     action.ot_outer_prio = bcmVlanActionReplace;
   1649     if (vlan_vp->flags & BCM_VLAN_PORT_INNER_VLAN_ADD) {
   1650         action.ot_inner = bcmVlanActionAdd;
   1651     } else {
   1652         action.ot_inner = bcmVlanActionNone;
   1653     }
   1654 
   1655     BCM_IF_ERROR_RETURN
   1656         (_bcm_trx_vlan_action_profile_entry_add(unit, &action, &profile_idx));
   1657 
   1658     if ((vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL) ||
   1659         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN) ||
   1660         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN)) {
   1661         soc_mem_field32_set(unit, mem, vent, LLTAG__MPLS_ACTIONf, 0x1); /* SVP */
   1662         soc_mem_field32_set(unit, mem, vent, LLTAG__SOURCE_VPf, vp);
   1663         soc_mem_field32_set(unit, mem, vent, LLTAG__NEW_OVIDf,
   1664                                 vlan_vp->egress_vlan);
   1665         soc_mem_field32_set(unit, mem, vent, LLTAG__NEW_IVIDf,
   1666                                 vlan_vp->egress_inner_vlan);
   1667         soc_mem_field32_set(unit, mem, vent, LLTAG__TAG_ACTION_PROFILE_PTRf,
   1668                                 profile_idx);
   1669         if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
   1670             soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
   1671         }
   1672     } else {
   1673         soc_mem_field32_set(unit, mem, vent, MPLS_ACTIONf, 0x1); /* SVP */
   1674         soc_mem_field32_set(unit, mem, vent, SOURCE_VPf, vp);
   1675         soc_mem_field32_set(unit, mem, vent, NEW_OVIDf,
   1676                                 vlan_vp->egress_vlan);
   1677         soc_mem_field32_set(unit, mem, vent, NEW_IVIDf,
   1678                                 vlan_vp->egress_inner_vlan);
   1679         soc_mem_field32_set(unit, mem, vent, TAG_ACTION_PROFILE_PTRf,
   1680                                 profile_idx);
   1681     }
   1682 
   1683     if (SOC_MEM_FIELD_VALID(unit, mem, VLAN_ACTION_VALIDf)) {
   1684         soc_mem_field32_set(unit, mem, vent, VLAN_ACTION_VALIDf, 1);
   1685     }
   1686 
   1687     rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL,
   1688                                    vent, old_vent);
   1689     if (rv == SOC_E_EXISTS) {
   1690         /* Delete the old vlan translate profile entry */
   1691         profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   1692                                           TAG_ACTION_PROFILE_PTRf);
   1693         rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   1694     }
   1695     return rv;
   1696 }
   1697 
   1698 /*
   1699  * Function:
   1700  *      _tr2_vlan_vp_match_delete
   1701  * Purpose:
   1702  *      Delete match criteria for VLAN VP.
   1703  * Parameters:
   1704  *      unit - (IN) SOC unit number. 
   1705  *      vp - (IN) Virtual port number.
   1706  *      old_vp - (OUT) Pointer to the old virtual port number of the entry.
   1707  * Returns:
   1708  *      BCM_X_XXX
   1709  */
   1710 STATIC int
   1711 _tr2_vlan_vp_match_delete(int unit, int vp, int *old_vp)
   1712 {
   1713     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   1714     uint32      old_vent[SOC_MAX_MEM_FIELD_WORDS];
   1715     soc_mem_t   mem = VLAN_XLATEm;
   1716     int key_type = 0;
   1717     uint32 profile_idx;
   1718     int rv;
   1719     
   1720     if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_NONE) {
   1721         return BCM_E_NONE;
   1722     }
   1723 
   1724     switch (VLAN_VP_INFO(unit, vp)->criteria) {
   1725         case BCM_VLAN_PORT_MATCH_PORT_VLAN:
   1726             key_type = bcmVlanTranslateKeyPortOuter;
   1727             break;
   1728         case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED:  
   1729             key_type = bcmVlanTranslateKeyPortDouble;
   1730             break;
   1731         case BCM_VLAN_PORT_MATCH_PORT_VLAN16:
   1732             key_type = bcmVlanTranslateKeyPortOuterTag;
   1733             break;
   1734         case BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN:
   1735             key_type = bcmVlanTranslateKeyPortInner;
   1736             break;
   1737         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1738             key_type = bcmVlanTranslateKeyPortPonTunnel;
   1739             break;
   1740         case  BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1741             key_type = bcmVlanTranslateKeyPortPonTunnelOuter;
   1742             break;
   1743         case  BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   1744             key_type = bcmVlanTranslateKeyPortPonTunnelInner;
   1745             break;
   1746         default:
   1747             return BCM_E_INTERNAL;
   1748     }
   1749 
   1750     sal_memset(vent, 0, sizeof(vent));
   1751     sal_memset(old_vent, 0, sizeof(old_vent));
   1752     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   1753         mem = VLAN_XLATE_1_DOUBLEm;
   1754     }
   1755 
   1756     switch (VLAN_VP_INFO(unit, vp)->criteria) {
   1757         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1758             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1759                                                 VLAN_VP_INFO(unit, vp)->port,
   1760                                                 key_type,
   1761                                                 VLAN_VP_INFO(unit, vp)->match_tunnel_value,
   1762                                                 0);
   1763             break;
   1764         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1765             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1766                                                 VLAN_VP_INFO(unit, vp)->port,
   1767                                                 key_type,
   1768                                                 VLAN_VP_INFO(unit, vp)->match_tunnel_value,
   1769                                                 VLAN_VP_INFO(unit, vp)->match_vlan); 
   1770             break;
   1771         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   1772             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1773                                                 VLAN_VP_INFO(unit, vp)->port,
   1774                                                 key_type,
   1775                                                 VLAN_VP_INFO(unit, vp)->match_tunnel_value,
   1776                                                 VLAN_VP_INFO(unit, vp)->match_inner_vlan);
   1777             break;
   1778         default:
   1779             rv = _bcm_trx_vlan_translate_entry_assemble(unit, vent,
   1780                                                 VLAN_VP_INFO(unit, vp)->port,
   1781                                                 key_type,
   1782                                                 VLAN_VP_INFO(unit, vp)->match_inner_vlan,
   1783                                                 VLAN_VP_INFO(unit, vp)->match_vlan);
   1784             break;
   1785     }
   1786 
   1787     if (BCM_FAILURE(rv)) {
   1788         return rv;
   1789     }
   1790 
   1791     rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL, vent, old_vent);
   1792     if (rv == SOC_E_NONE) {
   1793         int is_valid = 0;
   1794         if (soc_feature(unit, soc_feature_base_valid)) {
   1795             is_valid =
   1796                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 &&
   1797                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7;
   1798         } else {
   1799             is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf);
   1800         }
   1801         if (is_valid) {
   1802             if (old_vp != NULL) {
   1803                 *old_vp = soc_mem_field32_get(unit, mem, old_vent, SOURCE_VPf);
   1804             }
   1805             profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   1806                                               TAG_ACTION_PROFILE_PTRf);
   1807             /* Delete the old vlan action profile entry */
   1808             rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   1809         }
   1810     }
   1811 
   1812   /* If the associated the VLAN_XLATE entry was deleted by translation action delete, 
   1813     * it should return NOT FOUND.
   1814     */
   1815     if (rv == BCM_E_NOT_FOUND) {
   1816         rv = BCM_E_NONE;
   1817     }
   1818     return rv;
   1819 }
   1820 
   1821 /*
   1822  * Function:
   1823  *      _tr2_vlan_vp_match_get
   1824  * Purpose:
   1825  *      Get match criteria for VLAN VP.
   1826  * Parameters:
   1827  *      unit - (IN) SOC unit number. 
   1828  *      vp - (IN) Virtual port number.
   1829  *      vlan_vp - (OUT) Pointer to VLAN virtual port structure. 
   1830  * Returns:
   1831  *      BCM_X_XXX
   1832  */
   1833 STATIC int
   1834 _tr2_vlan_vp_match_get(int unit, int vp, bcm_vlan_port_t *vlan_vp)
   1835 {
   1836     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   1837     uint32      vent_out[SOC_MAX_MEM_FIELD_WORDS];
   1838     soc_mem_t   mem = VLAN_XLATEm;
   1839 
   1840     int key_type = 0;
   1841     int idx;
   1842     int rv;
   1843 
   1844     vlan_vp->criteria = VLAN_VP_INFO(unit, vp)->criteria;
   1845     vlan_vp->match_vlan = VLAN_VP_INFO(unit, vp)->match_vlan;
   1846     vlan_vp->match_inner_vlan = VLAN_VP_INFO(unit, vp)->match_inner_vlan;
   1847     vlan_vp->match_tunnel_value = VLAN_VP_INFO(unit, vp)->match_tunnel_value;
   1848     vlan_vp->port = VLAN_VP_INFO(unit, vp)->port;
   1849 
   1850     if (VLAN_VP_INFO(unit, vp)->criteria == BCM_VLAN_PORT_MATCH_NONE) {
   1851         return BCM_E_NONE;
   1852     }
   1853 
   1854     switch (vlan_vp->criteria) {
   1855         case BCM_VLAN_PORT_MATCH_PORT_VLAN:
   1856             key_type = bcmVlanTranslateKeyPortOuter;
   1857             break;
   1858         case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED:
   1859             key_type = bcmVlanTranslateKeyPortDouble;
   1860             break;
   1861         case BCM_VLAN_PORT_MATCH_PORT_VLAN16:
   1862             key_type = bcmVlanTranslateKeyPortOuterTag;
   1863             break;
   1864         case BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN:
   1865             key_type = bcmVlanTranslateKeyPortInner;
   1866             break;
   1867         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1868             key_type = bcmVlanTranslateKeyPortPonTunnel;
   1869             break;
   1870         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1871             key_type = bcmVlanTranslateKeyPortPonTunnelOuter;
   1872             break;
   1873         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   1874             key_type = bcmVlanTranslateKeyPortPonTunnelInner;
   1875             break;
   1876         default:
   1877             return BCM_E_PARAM;
   1878     }
   1879 
   1880     sal_memset(vent, 0, sizeof(vent));
   1881     sal_memset(vent_out, 0, sizeof(vent_out));
   1882     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   1883         mem = VLAN_XLATE_1_DOUBLEm;
   1884     }
   1885 
   1886     switch (vlan_vp->criteria) {
   1887         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1888            rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1889                                                vlan_vp->port,
   1890                                                key_type,
   1891                                                vlan_vp->match_tunnel_value,
   1892                                                0);
   1893            break;
   1894         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1895            rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1896                                                vlan_vp->port,
   1897                                                key_type,
   1898                                                vlan_vp->match_tunnel_value,
   1899                                                vlan_vp->match_vlan);
   1900            break;
   1901         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   1902            rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1903                                                vlan_vp->port,
   1904                                                key_type,
   1905                                                vlan_vp->match_tunnel_value,
   1906                                                vlan_vp->match_inner_vlan);
   1907            break;
   1908         default:
   1909            rv = _bcm_trx_vlan_translate_entry_assemble(unit, vent,
   1910                                                vlan_vp->port,
   1911                                                key_type,
   1912                                                vlan_vp->match_inner_vlan,
   1913                                                vlan_vp->match_vlan);
   1914            break;
   1915         }
   1916 
   1917     if (BCM_FAILURE(rv)) {
   1918         return rv;
   1919     }
   1920 
   1921     BCM_IF_ERROR_RETURN
   1922         (soc_mem_search(unit, mem, MEM_BLOCK_ALL,
   1923                         &idx, vent, vent_out, 0));
   1924     vlan_vp->egress_vlan = soc_mem_field32_get(unit, mem, vent_out, NEW_OVIDf);
   1925     vlan_vp->egress_inner_vlan = soc_mem_field32_get(unit, mem, vent_out,
   1926                                                      NEW_IVIDf);
   1927 
   1928     return BCM_E_NONE;
   1929 }
   1930 
   1931 /*
   1932  * Function:
   1933  *      _tr2_vlan_vp_match_cleanup
   1934  * Purpose:
   1935  *      Clean up match criteria for VLAN VP.
   1936  * Parameters:
   1937  *      unit - (IN) SOC unit number.
   1938  *      vlan_vp - (IN) Pointer to VLAN virtual port structure.
   1939  * Returns:
   1940  *      BCM_X_XXX
   1941  */
   1942 STATIC int
   1943 _tr2_vlan_vp_match_cleanup(int unit, bcm_vlan_port_t *vlan_vp)
   1944 {
   1945     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   1946     uint32      old_vent[SOC_MAX_MEM_FIELD_WORDS];
   1947     soc_mem_t   mem = VLAN_XLATEm;
   1948 
   1949     int key_type = 0;
   1950     uint32 profile_idx;
   1951     int rv;
   1952 
   1953     if (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_NONE) {
   1954         return BCM_E_NONE;
   1955     }
   1956 
   1957     switch (vlan_vp->criteria) {
   1958         case BCM_VLAN_PORT_MATCH_PORT_VLAN:
   1959             key_type = bcmVlanTranslateKeyPortOuter;
   1960             break;
   1961         case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED:
   1962             key_type = bcmVlanTranslateKeyPortDouble;
   1963             break;
   1964         case BCM_VLAN_PORT_MATCH_PORT_VLAN16:
   1965             key_type = bcmVlanTranslateKeyPortOuterTag;
   1966             break;
   1967         case BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN:
   1968             key_type = bcmVlanTranslateKeyPortInner;
   1969             break;
   1970         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1971             key_type = bcmVlanTranslateKeyPortPonTunnel;
   1972             break;
   1973         case  BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1974             key_type = bcmVlanTranslateKeyPortPonTunnelOuter;
   1975             break;
   1976         case  BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   1977             key_type = bcmVlanTranslateKeyPortPonTunnelInner;
   1978             break;
   1979         default:
   1980             return BCM_E_INTERNAL;
   1981     }
   1982 
   1983     sal_memset(vent, 0, sizeof(old_vent));
   1984     sal_memset(old_vent, 0, sizeof(old_vent));
   1985     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   1986         mem = VLAN_XLATE_1_DOUBLEm;
   1987     }
   1988 
   1989     switch (vlan_vp->criteria) {
   1990         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL:
   1991             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1992                                                 vlan_vp->port,
   1993                                                 key_type,
   1994                                                 vlan_vp->match_tunnel_value,
   1995                                                 0);
   1996             break;
   1997         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN:
   1998             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   1999                                                 vlan_vp->port,
   2000                                                 key_type,
   2001                                                 vlan_vp->match_tunnel_value,
   2002                                                 vlan_vp->match_vlan);
   2003             break;
   2004         case BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN:
   2005             rv = _bcm_trx_lltag_vlan_translate_entry_assemble(unit, vent,
   2006                                                 vlan_vp->port,
   2007                                                 key_type,
   2008                                                 vlan_vp->match_tunnel_value,
   2009                                                 vlan_vp->match_inner_vlan);
   2010             break;
   2011         default:
   2012             rv = _bcm_trx_vlan_translate_entry_assemble(unit, vent,
   2013                                                 vlan_vp->port,
   2014                                                 key_type,
   2015                                                 vlan_vp->match_inner_vlan,
   2016                                                 vlan_vp->match_vlan);
   2017             break;
   2018     }
   2019 
   2020     if (BCM_FAILURE(rv)) {
   2021         return rv;
   2022     }
   2023 
   2024     rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL,
   2025                                    vent, old_vent);
   2026     if (rv == SOC_E_NONE) {
   2027         int is_valid = 0;
   2028         if (soc_feature(unit, soc_feature_base_valid)) {
   2029             is_valid =
   2030                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_0f) == 3 &&
   2031                 soc_mem_field32_get(unit, mem, old_vent, BASE_VALID_1f) == 7;
   2032         } else {
   2033             is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf);
   2034         }
   2035         if (is_valid) {
   2036             profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   2037                                               TAG_ACTION_PROFILE_PTRf);
   2038             /* Delete the old vlan action profile entry */
   2039             rv = _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   2040         }
   2041     }
   2042 
   2043    /* If the associated the VLAN_XLATE entry was deleted by translation action delete,
   2044     * it should return NOT FOUND.
   2045     */
   2046     if (rv == BCM_E_NOT_FOUND) {
   2047         rv = BCM_E_NONE;
   2048     }
   2049     return rv;
   2050 }
   2051 
   2052 STATIC int
   2053 _bcm_tr2_vlan_vp_match_add(int unit, bcm_vlan_port_t *vlan_vp, int vp)
   2054 {
   2055 #if defined(BCM_TRIUMPH3_SUPPORT)
   2056     if (SOC_IS_TRIUMPH3(unit)) {
   2057         return _tr3_vlan_vp_match_add(unit, vlan_vp, vp);
   2058     } else
   2059 #endif
   2060     {
   2061         return _tr2_vlan_vp_match_add(unit, vlan_vp, vp);
   2062     }
   2063 }
   2064 
   2065 STATIC int
   2066 _bcm_tr2_vlan_vp_match_delete(int unit, int vp, int *old_vp)
   2067 {
   2068 #if defined(BCM_TRIUMPH3_SUPPORT)
   2069     if (SOC_IS_TRIUMPH3(unit)) {
   2070         return _tr3_vlan_vp_match_delete(unit, vp);
   2071     } else
   2072 #endif
   2073     {
   2074         return _tr2_vlan_vp_match_delete(unit, vp, old_vp);
   2075     }
   2076 }
   2077 
   2078 STATIC int
   2079 _bcm_tr2_vlan_vp_match_get(int unit, int vp, bcm_vlan_port_t *vlan_vp)
   2080 {
   2081 #if defined(BCM_TRIUMPH3_SUPPORT)
   2082     if (SOC_IS_TRIUMPH3(unit)) {
   2083         return _tr3_vlan_vp_match_get(unit, vp, vlan_vp);
   2084     } else
   2085 #endif
   2086     {
   2087         return _tr2_vlan_vp_match_get(unit, vp, vlan_vp);
   2088     }
   2089 }
   2090 
   2091 STATIC int
   2092 _bcm_tr2_vlan_vp_match_cleanup(int unit, bcm_vlan_port_t *vlan_vp)
   2093 {
   2094 #if defined(BCM_TRIUMPH3_SUPPORT)
   2095     if (SOC_IS_TRIUMPH3(unit)) {
   2096         return _tr3_vlan_vp_match_cleanup(unit, vlan_vp);
   2097     } else
   2098 #endif
   2099     {
   2100         return _tr2_vlan_vp_match_cleanup(unit, vlan_vp);
   2101     }
   2102 }
   2103 
   2104 #ifdef BCM_TRIUMPH3_SUPPORT
   2105 
   2106 /*
   2107  * Function:
   2108  *      _bcm_tr3_vlan_eline_vp_map_set
   2109  * Purpose:
   2110  *      Set VLAN ELINE ports from VPN
   2111  * Parameters:
   2112  *      unit      - (IN) Device Number
   2113  *      vfi_index - (IN) VFI Index
   2114  *      vp1       - (IN) VP1
   2115  *      vp1       - (IN) VP2
   2116  * Returns:
   2117  *      BCM_E_XXX
   2118  */
   2119 STATIC int
   2120 _bcm_tr3_vlan_eline_vp_map_set(int unit, int vfi_index, int vp1, int vp2)
   2121 {
   2122     vfi_entry_t vfi_entry;
   2123     int num_vp=0;
   2124 
   2125     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2126         return BCM_E_NOT_FOUND;
   2127     }
   2128 
   2129     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2130     if ((vp1 < 0) || (vp1 >= num_vp) ||
   2131         (vp2 < 0) || (vp2 >= num_vp)) {
   2132         return BCM_E_PARAM;
   2133     }
   2134 
   2135     BCM_IF_ERROR_RETURN
   2136         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   2137 
   2138     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   2139         soc_VFIm_field32_set(unit, &vfi_entry, VP_0f, vp1);
   2140         soc_VFIm_field32_set(unit, &vfi_entry, VP_1f, vp2);
   2141     } else {
   2142         /* ELAN */
   2143         return BCM_E_PARAM;
   2144     }
   2145 
   2146     return WRITE_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry);
   2147 }
   2148 
   2149 /*
   2150  * Function:
   2151  *      _bcm_tr3_vlan_eline_port_add
   2152  * Purpose:
   2153  *      Add VLAN ELINE port to a VPN
   2154  * Parameters:
   2155  *      unit    - (IN) Device Number
   2156  *      vpn     - (IN) VPN instance ID
   2157  *      vlan_port - (IN) VLAN port information
   2158  * Returns:
   2159  *      BCM_E_XXX
   2160  */
   2161 STATIC int
   2162 _bcm_tr3_vlan_eline_port_add(int unit, bcm_vpn_t vpn, bcm_vlan_port_t *vlan_port)
   2163 {
   2164     int active_vp = 0; /* default VP */
   2165     source_vp_entry_t svp;
   2166     int vfi_index = -1;
   2167 
   2168     if (vpn != _BCM_VLAN_VPN_INVALID) {
   2169         _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2170         if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2171             return BCM_E_NOT_FOUND;
   2172         }
   2173     } else {
   2174         vfi_index = _BCM_VLAN_VFI_INVALID;
   2175     }
   2176 
   2177     active_vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_port->vlan_port_id);
   2178     if (active_vp == -1) {
   2179         return BCM_E_PARAM;
   2180     }
   2181 
   2182     if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeVlan)) {
   2183         return BCM_E_NOT_FOUND;
   2184     }
   2185 
   2186     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, active_vp, &svp));
   2187     (void) _bcm_tr3_vlan_eline_vp_map_set(unit, vfi_index, active_vp, 0);
   2188 
   2189     if (vlan_port->flags & BCM_VLAN_PORT_NETWORK) {
   2190         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1);
   2191         soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, 0x0);
   2192     } else {
   2193         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0);
   2194         soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, 0x2);
   2195     }
   2196 
   2197     soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
   2198     soc_SOURCE_VPm_field32_set(unit, &svp,
   2199                            ENTRY_TYPEf, 0x1); /* VFI Type */
   2200     soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi_index);
   2201 
   2202     return WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp);
   2203 }
   2204 
   2205 /*
   2206  * Function:
   2207  *     _bcm_tr3_vlan_elan_port_add
   2208  * Purpose:
   2209  *      Add VLAN ELAN port to a VPN
   2210  * Parameters:
   2211  *   unit - (IN) Device Number
   2212  *   vpn - (IN) VPN instance ID
   2213  *   vlan_vp - (IN) vlan port information
   2214  * Returns:
   2215  *     BCM_E_XXX
   2216  */
   2217 
   2218 STATIC int
   2219 _bcm_tr3_vlan_elan_port_add(int unit, bcm_vpn_t vpn, bcm_vlan_port_t *vlan_vp)
   2220 {
   2221     int vp, vfi = 0;
   2222     source_vp_entry_t svp;
   2223 
   2224     if (vpn != _BCM_VLAN_VPN_INVALID) {
   2225         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   2226         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVlan)) {
   2227             return BCM_E_NOT_FOUND;
   2228         }
   2229     } else {
   2230         vfi = _BCM_VLAN_VFI_INVALID;
   2231     }
   2232 
   2233     vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_vp->vlan_port_id);
   2234     if (vp == -1) {
   2235         return BCM_E_PARAM;
   2236     }
   2237 
   2238     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2239         return BCM_E_NOT_FOUND;
   2240     }
   2241 
   2242     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2243 
   2244 
   2245     /* ======== Configure SVP/DVP Properties ========== */
   2246     if (vpn == _BCM_VLAN_VPN_INVALID) {
   2247         soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x0);
   2248     } else {
   2249         /* Initialize VP parameters */
   2250         soc_SOURCE_VPm_field32_set(unit, &svp, ENTRY_TYPEf, 0x1);
   2251     }
   2252 
   2253     soc_SOURCE_VPm_field32_set(unit, &svp, VFIf, vfi);
   2254     if (vlan_vp->flags & BCM_VLAN_PORT_NETWORK) {
   2255         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 1);
   2256         soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, 0x0);
   2257     } else {
   2258         soc_SOURCE_VPm_field32_set(unit, &svp, NETWORK_PORTf, 0);
   2259         soc_SOURCE_VPm_field32_set(unit, &svp, TPID_SOURCEf, 0x2);
   2260     }
   2261 
   2262     if (soc_mem_field_valid(unit, SOURCE_VPm, DISABLE_VLAN_CHECKSf)) {
   2263         soc_SOURCE_VPm_field32_set(unit, &svp, DISABLE_VLAN_CHECKSf, 1);
   2264     }
   2265 
   2266     return WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   2267 }
   2268 
   2269 /* Function:
   2270   *       _bcm_tr3_vlan_vpn_is_valid
   2271   * Purpose:
   2272   *       Find if given VLAN VPN is Valid
   2273   * Parameters:
   2274   *       unit     - Device Number
   2275   *       vpn      - VLAN VPN
   2276   * Returns:
   2277   *       BCM_E_XXXX
   2278 */
   2279 int
   2280 _bcm_tr3_vlan_vpn_is_valid( int unit, bcm_vpn_t vpn)
   2281 {
   2282     bcm_vpn_t vpn_min=0;
   2283     int vfi_index=-1, num_vfi=0;
   2284 
   2285     num_vfi = soc_mem_index_count(unit, VFIm);
   2286     /* Check for Valid vpn */
   2287     _BCM_VPN_SET(vpn_min, _BCM_VPN_TYPE_VFI, 0);
   2288     if (vpn < vpn_min || vpn > (vpn_min + num_vfi - 1)) {
   2289         return BCM_E_PARAM;
   2290     }
   2291 
   2292     _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2293     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2294         return BCM_E_NOT_FOUND;
   2295     }
   2296 
   2297     return BCM_E_NONE;
   2298 }
   2299 
   2300 /* Function:
   2301  *      _bcm_tr3_vlan_vpn_is_eline
   2302  * Purpose:
   2303  *      Find if given VLAN VPN is ELINE
   2304  * Parameters:
   2305  *      unit     - Device Number
   2306  *      vpn      - VLAN VPN
   2307  *      isEline  - Flag
   2308  * Returns:
   2309  *      BCM_E_XXXX
   2310  * Assumes:
   2311  *      l2vpn is valid
   2312  */
   2313 
   2314 int
   2315 _bcm_tr3_vlan_vpn_is_eline( int unit, bcm_vpn_t vpn, uint8 *isEline)
   2316 {
   2317     int vfi_index=-1;
   2318     vfi_entry_t vfi_entry;
   2319 
   2320     BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_vpn_is_valid(unit, vpn));
   2321 
   2322     _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2323     BCM_IF_ERROR_RETURN(READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   2324 
   2325     /* Set the returned VPN id */
   2326     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   2327         *isEline = 1;  /* ELINE */
   2328     } else {
   2329         *isEline = 0;  /* ELAN */
   2330     }
   2331 
   2332     return BCM_E_NONE;
   2333 }
   2334 
   2335 /*
   2336  * Function:
   2337  *      _bcm_tr3_vlan_port_add
   2338  * Purpose:
   2339  *      Add a VLAN port to the specified VPN.
   2340  * Parameters:
   2341  *      unit  - (IN) SOC unit number.
   2342  *      vlan  - (IN) VLAN ID to add virtual port to as a member.
   2343  *      vlan_vp - (IN) VP port information
   2344  * Returns:
   2345  *      BCM_E_XXX
   2346  */
   2347 STATIC int
   2348 _bcm_tr3_vlan_port_add(int unit, bcm_vpn_t vpn,
   2349                             bcm_vlan_port_t *vlan_vp)
   2350 {
   2351     int mode=0, rv = BCM_E_PARAM;
   2352     uint8 isEline=0xFF;
   2353 
   2354     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode));
   2355     if (!mode) {
   2356         LOG_INFO(BSL_LS_BCM_L3,
   2357                  (BSL_META_U(unit,
   2358                              "L3 egress mode must be set first\n")));
   2359         return BCM_E_DISABLED;
   2360     }
   2361 
   2362     if ((vpn != _BCM_VLAN_VPN_INVALID) && (isEline != 0x0)) {
   2363         BCM_IF_ERROR_RETURN
   2364               (_bcm_tr3_vlan_vpn_is_eline(unit, vpn, &isEline));
   2365     }
   2366 
   2367     if (isEline == 0x1) {
   2368         rv = _bcm_tr3_vlan_eline_port_add(unit, vpn, vlan_vp);
   2369     } else if (isEline == 0x0) {
   2370         rv = _bcm_tr3_vlan_elan_port_add(unit, vpn, vlan_vp);
   2371     }
   2372 
   2373     return rv;
   2374 }
   2375 
   2376 /*
   2377  * Function:
   2378  *      _bcm_tr3_vlan_eline_vp_map_get
   2379  * Purpose:
   2380  *      Get VLAN ELINE ports from VPN
   2381  * Parameters:
   2382  *      unit    - (IN) Device Number
   2383  *      vpn     - (IN) VPN instance ID
   2384  * Returns:
   2385  *      BCM_E_XXX
   2386  */
   2387 
   2388 STATIC int
   2389 _bcm_tr3_vlan_eline_vp_map_get(int unit, int vfi_index, int *vp1, int *vp2)
   2390 {
   2391     vfi_entry_t vfi_entry;
   2392 
   2393     if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2394         return BCM_E_NOT_FOUND;
   2395     }
   2396 
   2397     BCM_IF_ERROR_RETURN
   2398         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   2399 
   2400     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   2401         *vp1 = soc_VFIm_field32_get(unit, &vfi_entry, VP_0f);
   2402         *vp2 = soc_VFIm_field32_get(unit, &vfi_entry, VP_1f);
   2403         return BCM_E_NONE;
   2404     }
   2405 
   2406     return BCM_E_PARAM;
   2407 }
   2408 
   2409 /* Function:
   2410  *      _bcm_tr3_vlan_vp_is_eline
   2411  * Purpose:
   2412  *      Find if given VLAN VP is ELINE
   2413  * Parameters:
   2414  *      unit     - Device Number
   2415  *      vp        - VLAN VP
   2416  *      isEline  - Flag
   2417  * Returns:
   2418  *      BCM_E_XXXX
   2419  * Assumes:
   2420  *      vp is valid
   2421  */
   2422 STATIC int
   2423 _bcm_tr3_vlan_vp_is_eline( int unit, int vp, uint8 *isEline)
   2424 {
   2425     source_vp_entry_t svp;
   2426     vfi_entry_t vfi_entry;
   2427     int vfi_index;
   2428 
   2429     if (vp == -1) {
   2430         return BCM_E_PARAM;
   2431     }
   2432 
   2433     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2434         return BCM_E_NOT_FOUND;
   2435     }
   2436 
   2437     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2438 
   2439     vfi_index = soc_SOURCE_VPm_field32_get(unit, &svp, VFIf);
   2440     BCM_IF_ERROR_RETURN
   2441         (READ_VFIm(unit, MEM_BLOCK_ALL, vfi_index, &vfi_entry));
   2442 
   2443     /* Set the returned VPN id */
   2444     if (soc_VFIm_field32_get(unit, &vfi_entry, PT2PT_ENf)) {
   2445        *isEline = 0x1;
   2446     } else {
   2447        *isEline = 0x0;
   2448     }
   2449 
   2450     return BCM_E_NONE;
   2451 }
   2452 
   2453 /*
   2454  * Function:
   2455  *      _bcm_tr3_vlan_eline_port_delete
   2456  * Purpose:
   2457  *      Delete VLAN ELINE port from a VPN
   2458  * Parameters:
   2459  *      unit       - (IN) Device Number
   2460  *      vpn        - (IN) VPN instance ID
   2461  *      active_vp - (IN) Active vp
   2462  * Returns:
   2463  *      BCM_E_XXX
   2464  */
   2465 
   2466 STATIC int
   2467 _bcm_tr3_vlan_eline_port_delete(int unit, bcm_vpn_t vpn, int active_vp)
   2468 {
   2469     source_vp_entry_t svp;
   2470     int vp1=0, vp2=0, vfi_index= -1;
   2471 
   2472     if (vpn != _BCM_VLAN_VPN_INVALID) {
   2473         _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2474         if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2475             return BCM_E_NOT_FOUND;
   2476         }
   2477     } else {
   2478         vfi_index = _BCM_VLAN_VFI_INVALID;
   2479     }
   2480 
   2481     if (!_bcm_vp_used_get(unit, active_vp, _bcmVpTypeVlan)) {
   2482         return BCM_E_NOT_FOUND;
   2483     }
   2484 
   2485     /* ---- Read in current table values for VP1 and VP2 ----- */
   2486     (void) _bcm_tr3_vlan_eline_vp_map_get(unit, vfi_index, &vp1, &vp2);
   2487 
   2488     /* If the other port is valid, point it to itself */
   2489     if (active_vp == vp1) {
   2490         BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_eline_vp_map_set(unit, vfi_index, 0, vp2));
   2491     } else if (active_vp == vp2) {
   2492         BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_eline_vp_map_set(unit, vfi_index, vp1, 0));
   2493     }
   2494 
   2495     /* Check for Network-Port */
   2496     BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, active_vp, &svp));
   2497 
   2498     /* Invalidate the VP being deleted */
   2499     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   2500     return WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, active_vp, &svp);
   2501 }
   2502 
   2503 /*
   2504  * Function:
   2505  *      _bcm_tr3_vlan_elan_port_delete
   2506  * Purpose:
   2507  *      Delete VLAN ELAN port from a VPN
   2508  * Parameters:
   2509  *      unit       - (IN) Device Number
   2510  *      vpn       - (IN) VPN instance ID
   2511  *      vp         - (IN) vxlan port information
   2512  * Returns:
   2513  *      BCM_E_XXX
   2514  */
   2515 
   2516 STATIC int
   2517 _bcm_tr3_vlan_elan_port_delete(int unit, bcm_vpn_t vpn, int vp)
   2518 {
   2519     source_vp_entry_t svp;
   2520     int network_port_flag=0;
   2521     int vfi_index= -1;
   2522 
   2523     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2524         return BCM_E_NOT_FOUND;
   2525     }
   2526 
   2527     BCM_IF_ERROR_RETURN (READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2528     network_port_flag = soc_SOURCE_VPm_field32_get(unit, &svp, NETWORK_PORTf);
   2529     if (vpn != _BCM_VLAN_VPN_INVALID) {
   2530         _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2531         if (!network_port_flag) {
   2532             if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2533                 return BCM_E_NOT_FOUND;
   2534             }
   2535         }
   2536 
   2537         if (!((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) &&
   2538             (vfi_index == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf)))) {
   2539             return BCM_E_PARAM;
   2540         }
   2541     }
   2542 
   2543     /* Clear the SVP table entries */
   2544     sal_memset(&svp, 0, sizeof(source_vp_entry_t));
   2545     return WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   2546 }
   2547 
   2548 /*
   2549  * Function:
   2550  *      _bcm_tr3_vlan_port_delete
   2551  * Purpose:
   2552  *      Delete VLAN port from a VPN
   2553  * Parameters:
   2554  *      unit       - (IN) Device Number
   2555  *      vpn       - (IN) VPN instance ID
   2556  *      vp      - (IN) vlan port
   2557  * Returns:
   2558  *      BCM_E_XXX
   2559  */
   2560 
   2561 STATIC int
   2562 _bcm_tr3_vlan_port_delete(int unit, bcm_vpn_t vpn, int vp)
   2563 {
   2564     int rv = BCM_E_UNAVAIL;
   2565     uint8 isEline=0;
   2566 
   2567     if (vpn == _BCM_VLAN_VPN_INVALID) {
   2568         return BCM_E_PARAM;
   2569     }
   2570 
   2571     BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_vpn_is_valid(unit, vpn));
   2572     BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_vp_is_eline(unit, vp, &isEline));
   2573     if (isEline == 0x1) {
   2574         rv = _bcm_tr3_vlan_eline_port_delete(unit, vpn, vp);
   2575     } else if (isEline == 0x0) {
   2576         rv = _bcm_tr3_vlan_elan_port_delete(unit, vpn, vp);
   2577     }
   2578 
   2579     return rv;
   2580 }
   2581 
   2582 /*
   2583  * Function:
   2584  *      _bcm_tr3_vlan_port_delete_all
   2585  * Purpose:
   2586  *      Delete all VLAN ports from a VPN
   2587  * Parameters:
   2588  *      unit       - (IN) Device Number
   2589  *      vpn        - (IN) VPN instance ID
   2590  * Returns:
   2591  *      BCM_E_XXX
   2592  */
   2593 STATIC int
   2594 _bcm_tr3_vlan_port_delete_all(int unit, bcm_vpn_t vpn)
   2595 {
   2596     int vfi_index=0;
   2597     int vp1 = 0, vp2 = 0;
   2598     uint8 isEline=0xFF;
   2599     uint32 vp=0;
   2600 
   2601     BCM_IF_ERROR_RETURN
   2602          (_bcm_tr3_vlan_vpn_is_eline(unit, vpn, &isEline));
   2603 
   2604     if (isEline == 0x1) {
   2605         if (vpn != _BCM_VLAN_VPN_INVALID) {
   2606             _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2607             if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2608                 return BCM_E_NOT_FOUND;
   2609             }
   2610         } else {
   2611             vfi_index = _BCM_VLAN_VFI_INVALID;
   2612         }
   2613 
   2614         /* ---- Read in current table values for VP1 and VP2 ----- */
   2615         (void) _bcm_tr3_vlan_eline_vp_map_get(unit, vfi_index, &vp1, &vp2);
   2616         if (vp1 != 0) {
   2617             BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_eline_port_delete(unit, vpn, vp1));
   2618         }
   2619         if (vp2 != 0) {
   2620             BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_eline_port_delete(unit, vpn, vp2));
   2621         }
   2622     } else if (isEline == 0x0) {
   2623         uint32 vfi, num_vp;
   2624         source_vp_entry_t svp;
   2625 
   2626         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   2627         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVlan)) {
   2628             return BCM_E_NOT_FOUND;
   2629         }
   2630         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2631 
   2632         SHR_BIT_ITER(VIRTUAL_INFO(unit)->vlan_vp_bitmap, num_vp, vp) {
   2633 
   2634             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2635             if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) &&
   2636                 (vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf))) {
   2637                 BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_port_delete(unit, vpn, vp));
   2638             }
   2639         }
   2640     }
   2641 
   2642     return BCM_E_NONE;
   2643 }
   2644 
   2645 /*
   2646  * Function:
   2647  *      _bcm_tr3_vlan_port_get_all
   2648  * Purpose:
   2649  *      Get all VLAN ports from a VPN
   2650  * Parameters:
   2651  *      unit      - (IN) SOC unit number.
   2652  *      vlan      - (IN) VLAN ID.
   2653  *      array_max - (IN) Max number of elements in the array.
   2654  *      gport_array - (OUT) Array of virtual ports in GPORT format.
   2655  *      flags_array - (OUT) Array of flags.
   2656  *      array_size  - (OUT) Actual number of elements in the array.
   2657  */
   2658 STATIC int
   2659 _bcm_tr3_vlan_port_get_all(int unit, bcm_vlan_t vpn, int array_max,
   2660               bcm_gport_t *gport_array, int *flags_array, int *array_size)
   2661 {
   2662     int vp;
   2663     int vfi_index=-1;
   2664     int vp1 = 0, vp2 = 0;
   2665     uint8 isEline=0xFF;
   2666 
   2667     if (0 == array_max) {
   2668         return BCM_E_NONE;
   2669     }
   2670 
   2671     *array_size = 0;
   2672 
   2673     BCM_IF_ERROR_RETURN
   2674          (_bcm_tr3_vlan_vpn_is_eline(unit, vpn, &isEline));
   2675 
   2676     if (isEline == 0x1) {
   2677         if (vpn != _BCM_VLAN_VPN_INVALID) {
   2678             _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2679             if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2680                 return BCM_E_NOT_FOUND;
   2681             }
   2682         } else {
   2683             vfi_index = _BCM_VLAN_VFI_INVALID;
   2684         }
   2685 
   2686         /* ---- Read in current table values for VP1 and VP2 ----- */
   2687         (void) _bcm_tr3_vlan_eline_vp_map_get (unit, vfi_index, &vp1, &vp2);
   2688         if (_bcm_vp_used_get(unit, vp1, _bcmVpTypeVlan)) {
   2689             BCM_GPORT_VLAN_PORT_ID_SET(gport_array[*array_size], vp1);
   2690             flags_array[*array_size] = 0;
   2691             (*array_size)++;
   2692         }
   2693 
   2694         if (_bcm_vp_used_get(unit, vp2, _bcmVpTypeVlan)) {
   2695             if (array_max > *array_size) {
   2696                 BCM_GPORT_VLAN_PORT_ID_SET(gport_array[*array_size], vp2);
   2697                 flags_array[*array_size] = 0;
   2698                 (*array_size)++;
   2699             }
   2700         }
   2701     } else if (isEline == 0x0) {
   2702         uint32 vfi, entry_type;
   2703         int num_vp;
   2704         source_vp_entry_t svp;
   2705 
   2706         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   2707         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVlan)) {
   2708             return BCM_E_NOT_FOUND;
   2709         }
   2710         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2711         SHR_BIT_ITER(VIRTUAL_INFO(unit)->vlan_vp_bitmap, num_vp, vp) {
   2712             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2713             entry_type = soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf);
   2714 
   2715             if ((vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf)) &&
   2716                 (entry_type == 0x1)) {
   2717                 if (array_max > *array_size) {
   2718                     BCM_GPORT_VLAN_PORT_ID_SET(gport_array[*array_size], vp);
   2719                     flags_array[*array_size] = 0;
   2720                     (*array_size)++;
   2721                 }
   2722             }
   2723         }
   2724     }
   2725 
   2726     return BCM_E_NONE;
   2727 }
   2728 
   2729 /*
   2730  * Function:
   2731  *      _bcm_tr3_vlan_vp_destroy_all
   2732  * Purpose:
   2733  *      Destroy all virtual port in VPN instance.
   2734  * Parameters:
   2735  *      unit - (IN) SOC unit number.
   2736  *      vpn - (IN) VPN instance ID.
   2737  * Returns:
   2738  *      BCM_X_XXX
   2739  */
   2740 int
   2741 _bcm_tr3_vlan_vp_destroy_all(int unit, bcm_vpn_t vpn)
   2742 {
   2743     int vfi_index=0;
   2744     int vp1 = 0, vp2 = 0;
   2745     uint8 isEline=0xFF;
   2746     uint32 vp=0;
   2747     bcm_gport_t vlan_port_id;
   2748 
   2749     BCM_IF_ERROR_RETURN
   2750          (_bcm_tr3_vlan_vpn_is_eline(unit, vpn, &isEline));
   2751 
   2752     if (isEline == 0x1) {
   2753         if (vpn != _BCM_VLAN_VPN_INVALID) {
   2754             _BCM_VPN_GET(vfi_index, _BCM_VPN_TYPE_VFI, vpn);
   2755             if (!_bcm_vfi_used_get(unit, vfi_index, _bcmVfiTypeVlan)) {
   2756                 return BCM_E_NOT_FOUND;
   2757             }
   2758         } else {
   2759             vfi_index = _BCM_VLAN_VFI_INVALID;
   2760         }
   2761 
   2762         /* ---- Read in current table values for VP1 and VP2 ----- */
   2763         (void) _bcm_tr3_vlan_eline_vp_map_get(unit, vfi_index, &vp1, &vp2);
   2764         if (vp1 != 0) {
   2765             BCM_GPORT_VLAN_PORT_ID_SET(vlan_port_id, vp1);
   2766             BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_destroy(unit, vlan_port_id));
   2767         }
   2768         if (vp2 != 0) {
   2769             BCM_GPORT_VLAN_PORT_ID_SET(vlan_port_id, vp2);
   2770             BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_destroy(unit, vlan_port_id));
   2771         }
   2772     } else if (isEline == 0x0) {
   2773         uint32 vfi, num_vp;
   2774         source_vp_entry_t svp;
   2775 
   2776         _BCM_VPN_GET(vfi, _BCM_VPN_TYPE_VFI, vpn);
   2777         if (!_bcm_vfi_used_get(unit, vfi, _bcmVfiTypeVlan)) {
   2778             return BCM_E_NOT_FOUND;
   2779         }
   2780         num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2781 
   2782         SHR_BIT_ITER(VIRTUAL_INFO(unit)->vlan_vp_bitmap, num_vp, vp) {
   2783             BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   2784             if ((soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) == 0x1) &&
   2785                 (vfi == soc_SOURCE_VPm_field32_get(unit, &svp, VFIf))) {
   2786                 BCM_GPORT_VLAN_PORT_ID_SET(vlan_port_id, vp);
   2787                 BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_destroy(unit, vlan_port_id));
   2788             }
   2789         }
   2790     }
   2791 
   2792     return BCM_E_NONE;
   2793 }
   2794 
   2795 #endif /* BCM_TRIUMPH3_SUPPORT */
   2796 
   2797 /*
   2798  * Function:
   2799  *      _bcm_tr2_vlan_vp_create
   2800  * Purpose:
   2801  *      Create a VLAN virtual port.
   2802  * Parameters:
   2803  *      unit - (IN) SOC unit number. 
   2804  *      vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 
   2805  * Returns:
   2806  *      BCM_X_XXX
   2807  */
   2808 STATIC int
   2809 _bcm_tr2_vlan_vp_create(int unit,
   2810                          bcm_vlan_port_t *vlan_vp)
   2811 {
   2812     int mode;
   2813     int vp, old_vp = 0, matched_vp;
   2814     int rv = BCM_E_NONE;
   2815     int num_vp;
   2816     int nh_index = 0;
   2817     ing_dvp_table_entry_t dvp_entry;
   2818     source_vp_entry_t svp_entry;
   2819     int cml_default_enable=0, cml_default_new=0, cml_default_move=0;
   2820     _bcm_vp_info_t vp_info;
   2821     int tpid_enable = 0, tpid_index=-1;
   2822     int policer_set = 0;
   2823     int network_group;
   2824     _bcm_vp_info_init(&vp_info);
   2825     vp_info.vp_type = _bcmVpTypeVlan;
   2826 
   2827     BCM_IF_ERROR_RETURN(bcm_xgs3_l3_egress_mode_get(unit, &mode));
   2828     if (!mode) {
   2829         LOG_INFO(BSL_LS_BCM_L3,
   2830                  (BSL_META_U(unit,
   2831                              "L3 egress mode must be set first\n")));
   2832         return BCM_E_DISABLED;
   2833     }
   2834 
   2835     if (((vlan_vp->flags &  BCM_VLAN_PORT_EGRESS_PON_TUNNEL_NONE) || 
   2836         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL) ||
   2837         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN) ||
   2838         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN)) && 
   2839         (!soc_feature(unit, soc_feature_lltag)))  {
   2840         return BCM_E_UNAVAIL;
   2841     } else if ((vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL) ||
   2842         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_VLAN) ||
   2843         (vlan_vp->criteria == BCM_VLAN_PORT_MATCH_PORT_PON_TUNNEL_INNER_VLAN)) {
   2844         if (vlan_vp->match_tunnel_value >= BCM_VLAN_INVALID) {
   2845             return BCM_E_PARAM;
   2846         }
   2847     }
   2848 
   2849     if (!(vlan_vp->flags & BCM_VLAN_PORT_REPLACE)) { /* Create new VLAN VP */
   2850 
   2851         if (vlan_vp->flags & BCM_VLAN_PORT_WITH_ID) {
   2852             if (!BCM_GPORT_IS_VLAN_PORT(vlan_vp->vlan_port_id)) {
   2853                 return BCM_E_PARAM;
   2854             }
   2855             vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_vp->vlan_port_id);
   2856             if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) {
   2857                 return BCM_E_PARAM;
   2858             }
   2859             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2860                 return BCM_E_EXISTS;
   2861             } else {
   2862                 rv = _bcm_vp_used_set(unit, vp, vp_info);
   2863                 if (rv < 0) {
   2864                     return rv;
   2865                 }
   2866             }
   2867         } else {
   2868             /* allocate a new VP index */
   2869             num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   2870             rv = _bcm_vp_alloc(unit, 0, (num_vp - 1), 1, SOURCE_VPm,
   2871                     vp_info, &vp);
   2872             if (rv < 0) {
   2873                 return rv;
   2874             }
   2875         }
   2876 
   2877         /* Configure next hop tables */
   2878         rv = _bcm_tr2_vlan_vp_nh_info_set(unit, vlan_vp, vp, 0,
   2879                                               &nh_index);
   2880         if (rv < 0) {
   2881             goto cleanup;
   2882         }
   2883 
   2884         /* Configure DVP table */
   2885         sal_memset(&dvp_entry, 0, sizeof(ing_dvp_table_entry_t));
   2886         soc_ING_DVP_TABLEm_field32_set(unit, &dvp_entry, NEXT_HOP_INDEXf,
   2887                                        nh_index);
   2888         rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry);
   2889         if (rv < 0) {
   2890             goto cleanup;
   2891         }
   2892 
   2893         rv = _bcm_vp_ing_dvp_to_ing_dvp2(unit, &dvp_entry, vp);
   2894         if (rv < 0) {
   2895             goto cleanup;
   2896         }
   2897 
   2898         /* Configure SVP table */
   2899         sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t));
   2900         soc_SOURCE_VPm_field32_set(unit, &svp_entry, ENTRY_TYPEf, 3);
   2901 
   2902 
   2903         /* Set the CML */
   2904         rv = _bcm_vp_default_cml_mode_get (unit, 
   2905                            &cml_default_enable, &cml_default_new, 
   2906                            &cml_default_move);
   2907          if (rv < 0) {
   2908              goto cleanup;
   2909          }
   2910 
   2911         if (cml_default_enable) {
   2912             /* Set the CML to default values */
   2913             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf, cml_default_new);
   2914             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf, cml_default_move);
   2915         } else {
   2916             /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */
   2917             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_NEWf, 0x8);
   2918             soc_SOURCE_VPm_field32_set(unit, &svp_entry, CML_FLAGS_MOVEf, 0x8);
   2919         }
   2920 
   2921 #if defined(BCM_TRIUMPH3_SUPPORT)
   2922         if (soc_feature(unit, soc_feature_vlan_vfi) && (vlan_vp->flags & BCM_VLAN_PORT_SERVICE_TAGGED)) {
   2923             BCM_IF_ERROR_RETURN(_bcm_fb2_outer_tpid_lkup(unit,
   2924                             vlan_vp->egress_service_tpid, &tpid_index));
   2925             tpid_enable = 1 << tpid_index;
   2926             soc_SOURCE_VPm_field32_set(unit, &svp_entry, TPID_ENABLEf, tpid_enable);
   2927             soc_SOURCE_VPm_field32_set(unit, &svp_entry, SD_TAG_MODEf, 1);
   2928         }
   2929 #endif /*BCM_TRIUMPH3_SUPPORT*/
   2930 
   2931         if (vlan_vp->policer_id != 0) {
   2932             if (soc_feature(unit, soc_feature_global_meter)) {
   2933                 rv = _bcm_esw_add_policer_to_table(unit, vlan_vp->policer_id,
   2934                     SOURCE_VPm, vp, &svp_entry);
   2935                 policer_set = 1;
   2936             } else {
   2937                 rv = BCM_E_PARAM;
   2938             }
   2939             if (rv < 0) {
   2940                 goto cleanup;
   2941             }
   2942         }
   2943 #if defined(BCM_SABER2_SUPPORT)
   2944         if (SOC_IS_SABER2(unit)) {
   2945             if (vlan_vp->flags & BCM_VLAN_PORT_USE_SGLP_TPID) {
   2946                 /* Use TPIDs based on SGLP */
   2947                 soc_SOURCE_VPm_field32_set(unit, &svp_entry, TPID_SOURCEf, 2);
   2948             }
   2949         }
   2950 #endif
   2951         rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry);
   2952         if (rv < 0) {
   2953             goto cleanup;
   2954         }
   2955 
   2956         /* Configure ingress VLAN translation table */
   2957         rv = _bcm_tr2_vlan_vp_match_add(unit, vlan_vp, vp);
   2958         if (rv < 0) {
   2959             goto cleanup;
   2960         }
   2961 
   2962         /* Increment port's VP count */
   2963         rv = _bcm_tr2_vlan_vp_port_cnt_update(unit, vlan_vp->port, vp, TRUE);
   2964         if (rv < 0) {
   2965             goto cleanup;
   2966         }
   2967 
   2968     } else { /* Replace properties of existing VLAN VP */
   2969 
   2970         if (!(vlan_vp->flags & BCM_VLAN_PORT_WITH_ID)) {
   2971             return BCM_E_PARAM;
   2972         }
   2973         if (!BCM_GPORT_IS_VLAN_PORT(vlan_vp->vlan_port_id)) {
   2974             return BCM_E_PARAM;
   2975         }
   2976         vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_vp->vlan_port_id);
   2977         if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   2978             return BCM_E_PARAM;
   2979         }
   2980 
   2981         if (soc_feature(unit, soc_feature_global_meter)) {
   2982            /* read Source_VP mem, add, write back */
   2983             BCM_IF_ERROR_RETURN(
   2984                 READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry));
   2985             BCM_IF_ERROR_RETURN(
   2986                 _bcm_esw_add_policer_to_table(unit, vlan_vp->policer_id,
   2987                     SOURCE_VPm, vp, &svp_entry));
   2988 #if defined(BCM_SABER2_SUPPORT)
   2989             if (SOC_IS_SABER2(unit)) {
   2990                 if (vlan_vp->flags & BCM_VLAN_PORT_USE_SGLP_TPID) {
   2991                     /* Use TPIDs based on SGLP */
   2992                     soc_SOURCE_VPm_field32_set(unit, &svp_entry, TPID_SOURCEf, 2);
   2993                 } else {
   2994                     if(soc_SOURCE_VPm_field32_get(unit, &svp_entry, TPID_SOURCEf) == 2) {
   2995                         soc_SOURCE_VPm_field32_set(unit, &svp_entry, TPID_SOURCEf, 0);
   2996                     }
   2997                 }
   2998             }
   2999 #endif
   3000             BCM_IF_ERROR_RETURN(
   3001                 WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry));
   3002         } else {
   3003             if (vlan_vp->policer_id != 0) {
   3004                 return BCM_E_PARAM;
   3005             }
   3006         }
   3007 
   3008         /* For existing vlan vp, NH entry already exists */
   3009         BCM_IF_ERROR_RETURN
   3010             (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   3011 
   3012         nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
   3013                 NEXT_HOP_INDEXf);
   3014 
   3015         /* Update existing next hop entries */
   3016         BCM_IF_ERROR_RETURN
   3017             (_bcm_tr2_vlan_vp_nh_info_set(unit, vlan_vp, vp, 0,
   3018                                               &nh_index));
   3019 
   3020         /* Delete old ingress VLAN translation entry,
   3021          * install new ingress VLAN translation entry
   3022          */
   3023         BCM_IF_ERROR_RETURN
   3024             (_bcm_tr2_vlan_vp_match_delete(unit, vp, &old_vp));
   3025 #ifdef BCM_TRIDENT2_SUPPORT
   3026         /* The vlan port id may be one of members of a vplag. */
   3027         if (_bcm_vp_used_get(unit, old_vp, _bcmVpTypeVpLag)) {
   3028             matched_vp = old_vp;
   3029         } else
   3030 #endif
   3031         {
   3032             matched_vp = vp;
   3033         }
   3034         BCM_IF_ERROR_RETURN
   3035             (_bcm_tr2_vlan_vp_match_add(unit, vlan_vp, matched_vp));
   3036 
   3037         /* Decrement old port's VP count, increment new port's VP count */
   3038         BCM_IF_ERROR_RETURN
   3039             (_bcm_tr2_vlan_vp_port_cnt_update(unit,
   3040                 VLAN_VP_INFO(unit, vp)->port, vp, FALSE));
   3041 
   3042         BCM_IF_ERROR_RETURN
   3043             (_bcm_tr2_vlan_vp_port_cnt_update(unit,
   3044                 vlan_vp->port, vp, TRUE));
   3045     }
   3046     /* Handle Split Horizon */
   3047 
   3048     if (soc_feature(unit, soc_feature_multiple_split_horizon_group)) {
   3049         network_group = vlan_vp->ingress_network_group_id;
   3050         rv = _bcm_validate_splithorizon_network_group(unit,
   3051              vlan_vp->flags & BCM_VLAN_PORT_NETWORK, &network_group);
   3052         if (rv < 0) {
   3053             goto cleanup;
   3054         }
   3055         if (soc_mem_field_valid(unit, SOURCE_VPm, NETWORK_GROUPf)) {
   3056             rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry);
   3057             if (rv < 0) {
   3058                 goto cleanup;
   3059             }
   3060             soc_SOURCE_VPm_field32_set(unit, &svp_entry,
   3061                                        NETWORK_GROUPf,
   3062                                        network_group);
   3063             rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry);
   3064             if (rv < 0) {
   3065                 goto cleanup;
   3066             }
   3067         }
   3068         network_group = vlan_vp->egress_network_group_id;
   3069         rv = _bcm_validate_splithorizon_network_group(unit,
   3070              vlan_vp->flags & BCM_VLAN_PORT_NETWORK, &network_group);
   3071         if (rv < 0) {
   3072             goto cleanup;
   3073         }
   3074         if (soc_mem_field_valid(unit, ING_DVP_TABLEm, NETWORK_GROUPf)) {
   3075             rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry);
   3076             if (rv < 0) {
   3077                 goto cleanup;
   3078             }
   3079             soc_ING_DVP_TABLEm_field32_set(unit, &dvp_entry,
   3080                                            NETWORK_GROUPf,
   3081                                            network_group);
   3082             rv = WRITE_ING_DVP_TABLEm(unit, MEM_BLOCK_ALL, vp, &dvp_entry);
   3083             if (rv < 0) {
   3084                 goto cleanup;
   3085             }
   3086         }
   3087     }
   3088 
   3089 
   3090     /* Set VLAN VP software state */
   3091     VLAN_VP_INFO(unit, vp)->criteria = vlan_vp->criteria;
   3092     VLAN_VP_INFO(unit, vp)->flags = vlan_vp->flags;
   3093     VLAN_VP_INFO(unit, vp)->match_vlan = vlan_vp->match_vlan;
   3094     VLAN_VP_INFO(unit, vp)->match_inner_vlan = vlan_vp->match_inner_vlan;
   3095     VLAN_VP_INFO(unit, vp)->port = vlan_vp->port;
   3096     VLAN_VP_INFO(unit, vp)->match_tunnel_value = vlan_vp->match_tunnel_value;
   3097 
   3098     BCM_GPORT_VLAN_PORT_ID_SET(vlan_vp->vlan_port_id, vp);
   3099     vlan_vp->encap_id = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   3100 
   3101     return rv;
   3102 
   3103 cleanup:
   3104     if (!(vlan_vp->flags & BCM_VLAN_PORT_REPLACE)) {
   3105         (void) _bcm_vp_free(unit, _bcmVpTypeVlan, 1, vp);
   3106         _bcm_tr2_vlan_vp_nh_info_delete(unit, nh_index);
   3107 
   3108         (void)_bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp,
   3109                                ING_DVP_CONFIG_INVALID_VP_TYPE, 
   3110                                ING_DVP_CONFIG_INVALID_INTF_ID, 
   3111                                ING_DVP_CONFIG_INVALID_PORT_TYPE);
   3112 
   3113         if (policer_set) {
   3114             /* Decrement the reference count for the policer */
   3115             if (soc_feature(unit, soc_feature_global_meter)) {
   3116                 (void)_bcm_esw_policer_decrement_ref_count(unit, vlan_vp->policer_id);
   3117             }
   3118         }
   3119         sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t));
   3120         (void)WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry);
   3121 
   3122         (void)_bcm_tr2_vlan_vp_match_cleanup(unit, vlan_vp);
   3123     }
   3124 
   3125     if (tpid_enable) {
   3126         (void) _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index);
   3127     }
   3128 
   3129     return rv;
   3130 }
   3131 
   3132 /*
   3133  * Function:
   3134  *      bcm_tr2_vlan_vp_create
   3135  * Purpose:
   3136  *      Create a VLAN virtual port.
   3137  * Parameters:
   3138  *      unit - (IN) SOC unit number. 
   3139  *      vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 
   3140  * Returns:
   3141  *      BCM_X_XXX
   3142  */
   3143 int
   3144 bcm_tr2_vlan_vp_create(int unit,
   3145                          bcm_vlan_port_t *vlan_vp)
   3146 {
   3147     int rv;
   3148 
   3149     VLAN_VIRTUAL_INIT(unit);
   3150 
   3151     VLAN_VIRTUAL_LOCK(unit);
   3152 
   3153     rv = _bcm_tr2_vlan_vp_create(unit, vlan_vp);
   3154 
   3155     VLAN_VIRTUAL_UNLOCK(unit);
   3156 
   3157     return rv;
   3158 }
   3159 
   3160 /*
   3161  * Function:
   3162  *      _bcm_tr2_vlan_vp_destroy
   3163  * Purpose:
   3164  *      Destroy a VLAN virtual port.
   3165  * Parameters:
   3166  *      unit - (IN) SOC unit number. 
   3167  *      gport - (IN) VLAN VP GPORT ID.
   3168  * Returns:
   3169  *      BCM_X_XXX
   3170  */
   3171 STATIC int
   3172 _bcm_tr2_vlan_vp_destroy(int unit, bcm_gport_t gport)
   3173 {
   3174     int vp;
   3175     source_vp_entry_t svp_entry;
   3176     int nh_index;
   3177     ing_dvp_table_entry_t dvp_entry;
   3178     bcm_policer_t policer = 0;
   3179 
   3180     if (!BCM_GPORT_IS_VLAN_PORT(gport)) {
   3181         return BCM_E_PARAM;
   3182     }
   3183 
   3184     vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
   3185     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   3186         return BCM_E_NOT_FOUND;
   3187     }
   3188 
   3189 #ifdef BCM_TRIDENT_SUPPORT
   3190 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   3191     if (soc_feature(unit, soc_feature_vlan_vfi_membership))  {
   3192         BCM_IF_ERROR_RETURN
   3193             (bcm_td2p_vp_vlan_member_set(unit, gport, 0));
   3194     } else
   3195 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   3196     if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership) ||
   3197         soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) { 
   3198         /* Disable ingress and egress filter modes */
   3199         BCM_IF_ERROR_RETURN
   3200             (bcm_td_vp_vlan_member_set(unit, gport, 0));
   3201     }
   3202 #endif /* BCM_TRIDENT_SUPPORT */
   3203 
   3204     /* Delete ingress VLAN translation entry */
   3205     BCM_IF_ERROR_RETURN
   3206         (_bcm_tr2_vlan_vp_match_delete(unit, vp, NULL));
   3207 
   3208 #ifdef BCM_TRIUMPH3_SUPPORT
   3209     if (soc_feature(unit, soc_feature_vlan_vfi)) {
   3210         bcm_vpn_t vpn;
   3211         int vfi_index;
   3212         BCM_IF_ERROR_RETURN(READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry));
   3213         vfi_index = soc_SOURCE_VPm_field32_get(unit, &svp_entry, VFIf);
   3214         if (vfi_index != _BCM_VLAN_VFI_INVALID) {
   3215             _BCM_VPN_SET(vpn, _BCM_VPN_TYPE_VFI, vfi_index);
   3216             BCM_IF_ERROR_RETURN(_bcm_tr3_vlan_port_delete(unit, vpn, vp));
   3217         }
   3218     }
   3219 #endif /* BCM_TRIUMPH3_SUPPORT */
   3220 
   3221     if (soc_feature(unit, soc_feature_global_meter)) {
   3222         BCM_IF_ERROR_RETURN(_bcm_esw_get_policer_from_table(unit,
   3223                 SOURCE_VPm, vp, &svp_entry, &policer, 0));
   3224         if (policer != 0) {
   3225             /* Decrement reference count */
   3226             BCM_IF_ERROR_RETURN(
   3227                     _bcm_esw_policer_decrement_ref_count(unit, policer));
   3228         }
   3229     }
   3230 
   3231     /* Clear SVP entry */
   3232     sal_memset(&svp_entry, 0, sizeof(source_vp_entry_t));
   3233     BCM_IF_ERROR_RETURN
   3234         (WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp_entry));
   3235 
   3236     /* Clear DVP entry */
   3237     BCM_IF_ERROR_RETURN
   3238         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   3239     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, NEXT_HOP_INDEXf);
   3240 
   3241     BCM_IF_ERROR_RETURN
   3242         (_bcm_vp_ing_dvp_config(unit, _bcmVpIngDvpConfigClear, vp,
   3243                                 ING_DVP_CONFIG_INVALID_VP_TYPE, 
   3244                                 ING_DVP_CONFIG_INVALID_INTF_ID, 
   3245                                 ING_DVP_CONFIG_INVALID_PORT_TYPE));
   3246 
   3247     /* Clear next hop entries and free next hop index */
   3248     BCM_IF_ERROR_RETURN
   3249         (_bcm_tr2_vlan_vp_nh_info_delete(unit, nh_index));
   3250 
   3251     /* Decrement port's VP count */
   3252     BCM_IF_ERROR_RETURN
   3253         (_bcm_tr2_vlan_vp_port_cnt_update(unit,
   3254                                               VLAN_VP_INFO(unit, vp)->port,
   3255                                               vp, FALSE));
   3256     /* Free VP */
   3257     BCM_IF_ERROR_RETURN
   3258         (_bcm_vp_free(unit, _bcmVpTypeVlan, 1, vp));
   3259 
   3260     /* Clear VLAN VP software state */
   3261     sal_memset(VLAN_VP_INFO(unit, vp), 0, sizeof(_bcm_tr2_vlan_vp_info_t));
   3262 
   3263     return BCM_E_NONE;
   3264 }
   3265 
   3266 /*
   3267  * Function:
   3268  *      bcm_tr2_vlan_vp_destroy
   3269  * Purpose:
   3270  *      Destroy a VLAN virtual port.
   3271  * Parameters:
   3272  *      unit - (IN) SOC unit number. 
   3273  *      gport - (IN) VLAN VP GPORT ID.
   3274  * Returns:
   3275  *      BCM_X_XXX
   3276  */
   3277 int
   3278 bcm_tr2_vlan_vp_destroy(int unit, bcm_gport_t gport)
   3279 {
   3280     int rv;
   3281 
   3282     VLAN_VIRTUAL_INIT(unit);
   3283 
   3284     VLAN_VIRTUAL_LOCK(unit);
   3285 
   3286     rv = _bcm_tr2_vlan_vp_destroy(unit, gport);
   3287 
   3288     VLAN_VIRTUAL_UNLOCK(unit);
   3289 
   3290     return rv;
   3291 }
   3292 #define  _BCM_QOS_MAP_SHIFT       10
   3293 /*
   3294  * Function:
   3295  *      _bcm_tr2_vlan_vp_find
   3296  * Purpose:
   3297  *      Get VLAN virtual port info.
   3298  * Parameters:
   3299  *      unit - (IN) SOC unit number. 
   3300  *      vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 
   3301  * Returns:
   3302  *      BCM_X_XXX
   3303  */
   3304 STATIC int
   3305 _bcm_tr2_vlan_vp_find(int unit, bcm_vlan_port_t *vlan_vp)
   3306 {
   3307     int vp;
   3308     ing_dvp_table_entry_t dvp_entry;
   3309     int nh_index;
   3310     source_vp_entry_t svp_entry;
   3311     egr_l3_next_hop_entry_t egr_nh;
   3312 #ifdef BCM_KATANA_SUPPORT
   3313     bcm_if_t intf = 0;
   3314     int profile_index = -1;
   3315 #endif
   3316     if (!BCM_GPORT_IS_VLAN_PORT(vlan_vp->vlan_port_id)) {
   3317         return BCM_E_PARAM;
   3318     }
   3319 
   3320     vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_vp->vlan_port_id);
   3321     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   3322         return BCM_E_NOT_FOUND;
   3323     }
   3324 
   3325     bcm_vlan_port_t_init(vlan_vp);
   3326 
   3327     BCM_IF_ERROR_RETURN(_bcm_tr2_vlan_vp_match_get(unit, vp, vlan_vp));
   3328 
   3329     vlan_vp->flags = VLAN_VP_INFO(unit, vp)->flags;
   3330 
   3331     BCM_IF_ERROR_RETURN
   3332         (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry));
   3333     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, NEXT_HOP_INDEXf);
   3334     vlan_vp->encap_id = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   3335 
   3336     /* Get Egress Class */
   3337     if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, SD_TAG__CLASS_IDf)) {
   3338         /* Read the existing egress next_hop entry */
   3339         BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   3340                             nh_index, &egr_nh));
   3341         vlan_vp->if_class = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   3342                                                &egr_nh, SD_TAG__CLASS_IDf);
   3343     }
   3344 
   3345     BCM_GPORT_VLAN_PORT_ID_SET(vlan_vp->vlan_port_id, vp);
   3346 
   3347     if (soc_feature(unit, soc_feature_global_meter)) {
   3348         BCM_IF_ERROR_RETURN
   3349             (_bcm_esw_get_policer_from_table(unit, SOURCE_VPm, vp, &svp_entry,
   3350                     &(vlan_vp->policer_id), 0));
   3351     }
   3352 
   3353 #ifdef BCM_KATANA_SUPPORT
   3354     if (soc_feature(unit, soc_feature_extended_queueing)) {
   3355         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, nh_index)) {
   3356             intf = nh_index + BCM_XGS3_EGRESS_IDX_MIN(unit);
   3357         } else {
   3358             intf = nh_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   3359         }
   3360         if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(vlan_vp->port)) ||
   3361             (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(vlan_vp->port)) ||
   3362             (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(vlan_vp->port))) {
   3363              BCM_IF_ERROR_RETURN(
   3364                  _bcm_kt_extended_queue_qos_profile_get(unit, intf, &profile_index));
   3365         }
   3366         if (profile_index != -1) {
   3367             profile_index = (profile_index & 0x3) |
   3368             (_BCM_QOS_MAP_TYPE_ING_QUEUE_OFFSET_MAP_TABLE << _BCM_QOS_MAP_SHIFT);
   3369         }
   3370         vlan_vp->qos_map_id =  profile_index;
   3371     }
   3372 #endif
   3373     return BCM_E_NONE;
   3374 }
   3375 
   3376 /*
   3377  * Function:
   3378  *      bcm_tr2_vlan_vp_find
   3379  * Purpose:
   3380  *      Get VLAN virtual port info.
   3381  * Parameters:
   3382  *      unit - (IN) SOC unit number. 
   3383  *      vlan_vp - (IN/OUT) Pointer to VLAN virtual port structure. 
   3384  * Returns:
   3385  *      BCM_X_XXX
   3386  */
   3387 int
   3388 bcm_tr2_vlan_vp_find(int unit, bcm_vlan_port_t *vlan_vp)
   3389 {
   3390     VLAN_VIRTUAL_INIT(unit);
   3391     return _bcm_tr2_vlan_vp_find(unit, vlan_vp);
   3392 }
   3393 /*
   3394  * Function:
   3395  * bcm_tr2_vlan_port_learn_set
   3396  * Purpose:
   3397  * Modifies learning on a l2 logical port.
   3398  * Parameters:
   3399  * unit - SOC unit number
   3400  * vlan_port_if - l2 logical port ID
   3401  * flags - learning control flags
   3402  * Returns:
   3403  * BCM error code (BCM_E_XXX)
   3404  */
   3405 int
   3406 bcm_tr2_vlan_port_learn_set(int unit, bcm_gport_t vlan_port_id, uint32 flags)
   3407 {
   3408     int vp, cml = 0, rv = BCM_E_NONE;
   3409     source_vp_entry_t svp;
   3410 
   3411     cml = 0;
   3412     if (!(flags & BCM_PORT_LEARN_FWD)) {
   3413         cml |= (1 << 0);
   3414     }
   3415     if (flags & BCM_PORT_LEARN_CPU) {
   3416         cml |= (1 << 1);
   3417     }
   3418     if (flags & BCM_PORT_LEARN_PENDING) {
   3419         cml |= (1 << 2);
   3420     }
   3421     if (flags & BCM_PORT_LEARN_ARL) {
   3422         cml |= (1 << 3);
   3423     }
   3424 
   3425     /* Get the VP index from the gport */
   3426     vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_port_id);
   3427     if (vp == -1) {
   3428         return BCM_E_PARAM;
   3429     }
   3430 
   3431     /* Be sure the entry is used and is set for VLAN virtual ports */
   3432     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   3433         return BCM_E_NOT_FOUND;
   3434     }
   3435     rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp);
   3436     if (rv < 0) {
   3437         return rv;
   3438     }
   3439     if (soc_SOURCE_VPm_field32_get(unit, &svp, ENTRY_TYPEf) != 3) { /* VLAN PORT (GPON)*/
   3440         return BCM_E_NOT_FOUND;
   3441     }
   3442 
   3443     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_MOVEf, cml);
   3444     soc_SOURCE_VPm_field32_set(unit, &svp, CML_FLAGS_NEWf, cml);
   3445     rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, vp, &svp);
   3446 
   3447     return rv;
   3448 }
   3449 
   3450 /*
   3451  * Function:
   3452  *      bcm_tr2_vlan_port_phys_gport_get
   3453  * Purpose:
   3454  *      Get the physical gport of a VLAN port.
   3455  * Returns: 
   3456  *      BCM_E_XXX
   3457  */     
   3458 
   3459 int 
   3460 bcm_tr2_vlan_port_phys_gport_get(int unit, int vp, bcm_gport_t *gp)
   3461 {
   3462     int nh_index;
   3463     ing_dvp_table_entry_t dvp;
   3464     ing_l3_next_hop_entry_t ing_nh;
   3465     bcm_module_t mod_out, mod_in;
   3466     bcm_port_t port_out, port_in;
   3467     bcm_trunk_t trunk_id;
   3468 
   3469     BCM_IF_ERROR_RETURN(READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   3470     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf);
   3471     BCM_IF_ERROR_RETURN(soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY, 
   3472                                      nh_index, &ing_nh));
   3473 
   3474     if (soc_feature(unit, soc_feature_generic_dest)) {
   3475         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID, dest = 0;
   3476         dest = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, &ing_nh,
   3477                                          DESTINATIONf, &dest_type);
   3478         if (dest_type == SOC_MEM_FIF_DEST_LAG) {
   3479             trunk_id = (dest & SOC_MEM_FIF_DGPP_TGID_MASK);
   3480             BCM_GPORT_TRUNK_SET(*gp, trunk_id);
   3481         } else if (dest_type == SOC_MEM_FIF_DEST_DGPP) {
   3482             mod_in = (dest & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   3483                       SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   3484             port_in = dest & SOC_MEM_FIF_DGPP_PORT_MASK;
   3485             BCM_IF_ERROR_RETURN
   3486                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_in, port_in,
   3487                                         &mod_out, &port_out));
   3488             BCM_GPORT_MODPORT_SET(*gp, mod_out, port_out);
   3489         }
   3490     } else {
   3491         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   3492             trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   3493             BCM_GPORT_TRUNK_SET(*gp, trunk_id);
   3494         } else {
   3495             mod_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   3496             port_in = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   3497             BCM_IF_ERROR_RETURN
   3498                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_in, port_in,
   3499                                         &mod_out, &port_out));
   3500             BCM_GPORT_MODPORT_SET(*gp, mod_out, port_out);
   3501         }
   3502     }
   3503 
   3504     return BCM_E_NONE;
   3505 }
   3506 
   3507 void 
   3508 bcm_tr2_vlan_port_match_count_adjust(int unit, int vp, int step)
   3509 {
   3510     VLAN_VP_INFO(unit, vp)->match_count += step;
   3511 }
   3512 
   3513 /*
   3514  * Function:
   3515  *      _bcm_tr2_vlan_port_resolve
   3516  * Purpose:
   3517  *      Get the modid, port, trunk values for a VLAN virtual port
   3518  * Parameters:
   3519  *      unit - (IN) BCM device number
   3520  *      gport - (IN) Global port identifier
   3521  *      modid - (OUT) Module ID
   3522  *      port - (OUT) Port number
   3523  *      trunk_id - (OUT) Trunk ID
   3524  *      id - (OUT) Virtual port ID
   3525  * Returns:
   3526  *      BCM_E_XXX
   3527  */
   3528 int
   3529 _bcm_tr2_vlan_port_resolve(int unit, bcm_gport_t vlan_port_id,
   3530                           bcm_module_t *modid, bcm_port_t *port,
   3531                           bcm_trunk_t *trunk_id, int *id)
   3532 
   3533 {
   3534     int rv = BCM_E_NONE, nh_index, vp;
   3535     ing_l3_next_hop_entry_t ing_nh;
   3536     ing_dvp_table_entry_t dvp;
   3537 
   3538     VLAN_VIRTUAL_INIT(unit);
   3539 
   3540     if (!BCM_GPORT_IS_VLAN_PORT(vlan_port_id)) {
   3541         return (BCM_E_BADID);
   3542     }
   3543 
   3544     vp = BCM_GPORT_VLAN_PORT_ID_GET(vlan_port_id);
   3545     if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   3546         return BCM_E_NOT_FOUND;
   3547     }
   3548     BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
   3549     nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
   3550                                               NEXT_HOP_INDEXf);
   3551     BCM_IF_ERROR_RETURN (soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   3552                                       nh_index, &ing_nh));
   3553 
   3554     if ((soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x2) &&
   3555         (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, ENTRY_TYPEf) != 0x3)) {
   3556         /* Entry type is not L2 DVP and is not GPON DVP*/
   3557         return BCM_E_NOT_FOUND;
   3558     }
   3559 
   3560     if (soc_feature(unit, soc_feature_generic_dest)) {
   3561         uint32 dest_type = SOC_MEM_FIF_DEST_INVALID, dest = 0;
   3562         dest = soc_mem_field32_dest_get(unit, ING_L3_NEXT_HOPm, &ing_nh,
   3563                                         DESTINATIONf, &dest_type);
   3564         if (dest_type == SOC_MEM_FIF_DEST_LAG) {
   3565             *trunk_id = (dest & SOC_MEM_FIF_DGPP_TGID_MASK);
   3566         } else if (dest_type == SOC_MEM_FIF_DEST_DGPP) {
   3567             *modid = (dest & SOC_MEM_FIF_DGPP_MOD_ID_MASK) >>
   3568                       SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
   3569             *port = dest & SOC_MEM_FIF_DGPP_PORT_MASK;
   3570         }
   3571     } else {
   3572         if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, Tf)) {
   3573             *trunk_id = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, TGIDf);
   3574         } else {
   3575             /* Only add this to replication set if destination is local */
   3576             *modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, MODULE_IDf);
   3577             *port = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, PORT_NUMf);
   3578         }
   3579     }
   3580     *id = vp;
   3581     return rv;
   3582 }
   3583 
   3584 /* ---------------------------------------------------------------------------- 
   3585  *
   3586  * Routines for adding/removing virtual ports to/from VLAN
   3587  *
   3588  * ---------------------------------------------------------------------------- 
   3589  */
   3590 
   3591 /*
   3592  * Function:
   3593  *      _bcm_tr2_phy_port_trunk_is_local
   3594  * Purpose:
   3595  *      Determine if the given physical port or trunk is local.
   3596  * Parameters:
   3597  *      unit  - (IN) SOC unit number. 
   3598  *      gport - (IN) Physical port or trunk GPORT ID.
   3599  *      is_local - (OUT) Indicates if gport is local.
   3600  * Returns:
   3601  *      BCM_X_XXX
   3602  */
   3603 STATIC int
   3604 _bcm_tr2_phy_port_trunk_is_local(int unit, bcm_gport_t gport, int *is_local)
   3605 {
   3606     bcm_trunk_t trunk_id;
   3607     int rv = BCM_E_NONE;
   3608     int local_member_count;
   3609     bcm_module_t mod_out;
   3610     bcm_port_t port_out;
   3611     int id;
   3612     int modid_local;
   3613 
   3614     *is_local = 0;
   3615 
   3616     if (BCM_GPORT_IS_TRUNK(gport)) {
   3617         trunk_id = BCM_GPORT_TRUNK_GET(gport);
   3618         rv = _bcm_trunk_id_validate(unit, trunk_id);
   3619         if (BCM_FAILURE(rv)) {
   3620             return (BCM_E_PORT);
   3621         }
   3622         rv = _bcm_esw_trunk_local_members_get(unit, trunk_id,
   3623                 0, NULL, &local_member_count);
   3624         if (BCM_FAILURE(rv)) {
   3625             return (BCM_E_PORT);
   3626         }   
   3627         if (local_member_count > 0) {
   3628             *is_local = 1;
   3629         }
   3630     } else {
   3631         BCM_IF_ERROR_RETURN
   3632             (_bcm_esw_gport_resolve(unit, gport, &mod_out, &port_out,
   3633                                     &trunk_id, &id)); 
   3634        /* In case of extended queuing on KTX, trunk_id gets updated with
   3635         * extended queue value. So set it to invalid value.
   3636         */
   3637 #ifdef BCM_KATANA_SUPPORT
   3638     if (soc_feature(unit, soc_feature_extended_queueing)) {
   3639         if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) ||
   3640             (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) ||
   3641             (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(gport))) {
   3642             trunk_id = BCM_TRUNK_INVALID;
   3643         }
   3644    }
   3645 #endif
   3646         if ((trunk_id != -1) || (id != -1)) {
   3647             return BCM_E_PARAM;
   3648         }
   3649 
   3650         BCM_IF_ERROR_RETURN
   3651             (_bcm_esw_modid_is_local(unit, mod_out, &modid_local));
   3652 
   3653         *is_local = modid_local;
   3654     }
   3655 
   3656     return BCM_E_NONE;
   3657 }
   3658 
   3659 /*
   3660  * Function:
   3661  *      _bcm_tr2_vlan_vp_untagged_add
   3662  * Purpose:
   3663  *      Set VLAN VP tagging/untagging status by adding
   3664  *      a (VLAN VP, VLAN) egress VLAN translation entry.
   3665  * Parameters:
   3666  *      unit - (IN) SOC unit number. 
   3667  *      vlan - (IN) VLAN ID. 
   3668  *      vp   - (IN) Virtual port number.
   3669  *      flags - (IN) Untagging indication.
   3670  * Returns:
   3671  *      BCM_X_XXX
   3672  */
   3673 STATIC int
   3674 _bcm_tr2_vlan_vp_untagged_add(int unit, bcm_vlan_t vlan, int vp, int flags)
   3675 {
   3676     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   3677     uint32      old_vent[SOC_MAX_MEM_FIELD_WORDS];
   3678     bcm_vlan_action_set_t action;
   3679     uint32 profile_idx;
   3680     int rv;
   3681     soc_mem_t mem = EGR_VLAN_XLATEm;
   3682 
   3683     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   3684         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   3685     }
   3686 
   3687     sal_memset(vent, 0, sizeof(vent));
   3688     sal_memset(old_vent, 0, sizeof(old_vent));
   3689 
   3690     if (soc_feature(unit, soc_feature_base_valid)) {
   3691         soc_mem_field32_set(unit, mem, vent, BASE_VALID_0f, 3);
   3692         soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
   3693     } else {
   3694         soc_mem_field32_set(unit, mem, vent, VALIDf, 1);
   3695     }
   3696 
   3697     if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) {
   3698         soc_mem_field32_set(unit, mem, vent, DATA_TYPEf, 1);
   3699     }
   3700 
   3701     if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   3702         soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1);
   3703     } else if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) {
   3704         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1);
   3705     }
   3706 
   3707     soc_mem_field32_set(unit, mem, vent, DVPf, vp);
   3708     soc_mem_field32_set(unit, mem, vent, OVIDf, vlan);
   3709 
   3710     if (VLAN_VP_INFO(unit, vp)->flags & BCM_VLAN_PORT_EGRESS_VLAN16) {
   3711         soc_mem_field32_set(unit, mem, vent, NEW_OTAG_VPTAG_SELf, 1);
   3712         soc_mem_field32_set(unit, mem, vent, NEW_OTAG_VPTAGf,
   3713                                         VLAN_VP_INFO(unit, vp)->match_vlan);
   3714         soc_mem_field32_set(unit, mem, vent, NEW_IVIDf, vlan);
   3715     } else {
   3716         soc_mem_field32_set(unit, mem, vent, NEW_OTAG_VPTAG_SELf, 0);
   3717         /* egress_vlan in vlan_vp structure is used as swithcing vlan */
   3718         soc_mem_field32_set(unit, mem, vent, NEW_OVIDf,
   3719                 VLAN_VP_INFO(unit, vp)->match_vlan & 0xfff);
   3720         soc_mem_field32_set(unit, mem, vent, NEW_IVIDf, vlan);
   3721     }
   3722 
   3723     bcm_vlan_action_set_t_init(&action);
   3724     action.dt_outer = bcmVlanActionReplace;
   3725     action.ot_outer = bcmVlanActionReplace;
   3726     if (flags & BCM_VLAN_PORT_UNTAGGED) {
   3727         action.dt_inner = bcmVlanActionNone;
   3728         action.ot_inner = bcmVlanActionNone;
   3729     } else {
   3730         if (soc_feature(unit, soc_feature_vlan_copy_action)) {
   3731             action.dt_inner = bcmVlanActionCopy;
   3732             action.ot_inner = bcmVlanActionCopy;
   3733         } else {
   3734 
   3735             action.dt_inner = bcmVlanActionReplace;
   3736             action.ot_inner = bcmVlanActionAdd;
   3737         }
   3738     }
   3739     BCM_IF_ERROR_RETURN
   3740         (_bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &profile_idx));
   3741 
   3742     soc_mem_field32_set(unit, mem, vent, TAG_ACTION_PROFILE_PTRf, profile_idx);
   3743     rv = soc_mem_insert_return_old(unit, mem, MEM_BLOCK_ALL,
   3744                                    vent, old_vent);
   3745     if (rv == SOC_E_EXISTS) {
   3746         /* Delete the old vlan translate profile entry */
   3747         profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   3748                                           TAG_ACTION_PROFILE_PTRf);
   3749         rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx);
   3750     }
   3751 
   3752     return rv;
   3753 }
   3754 
   3755 /*
   3756  * Function:
   3757  *      _bcm_tr2_vlan_vp_untagged_delete
   3758  * Purpose:
   3759  *      Delete (VLAN VP, VLAN) egress VLAN translation entry.
   3760  * Parameters:
   3761  *      unit - (IN) SOC unit number. 
   3762  *      vlan - (IN) VLAN ID. 
   3763  *      vp   - (IN) Virtual port number.
   3764  * Returns:
   3765  *      BCM_X_XXX
   3766  */
   3767 STATIC int
   3768 _bcm_tr2_vlan_vp_untagged_delete(int unit, bcm_vlan_t vlan, int vp)
   3769 {
   3770     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   3771     uint32      old_vent[SOC_MAX_MEM_FIELD_WORDS];
   3772     uint32 profile_idx;
   3773     int rv;
   3774     soc_mem_t mem = EGR_VLAN_XLATEm;
   3775 
   3776     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   3777         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   3778     }
   3779 
   3780     sal_memset(vent, 0, sizeof(vent));
   3781     sal_memset(old_vent, 0, sizeof(old_vent));
   3782 
   3783     if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   3784         soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1);
   3785     } else if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) {
   3786         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1);
   3787     }
   3788 
   3789     soc_mem_field32_set(unit, mem, vent, DVPf, vp);
   3790     soc_mem_field32_set(unit, mem, vent, OVIDf, vlan);
   3791 
   3792     rv = soc_mem_delete_return_old(unit, mem, MEM_BLOCK_ALL,
   3793                                    vent, old_vent);
   3794     if (rv == SOC_E_NONE) {
   3795         int is_valid = 0;
   3796         if (soc_feature(unit, soc_feature_base_valid)) {
   3797             is_valid = soc_mem_field32_get(unit, mem, old_vent,
   3798                                            BASE_VALID_0f) == 3 &&
   3799                        soc_mem_field32_get(unit, mem, old_vent,
   3800                                            BASE_VALID_1f) == 7;
   3801         } else {
   3802             is_valid = soc_mem_field32_get(unit, mem, old_vent, VALIDf);
   3803         }
   3804         if (is_valid) {
   3805             /* Delete the old vlan translate profile entry */
   3806             profile_idx = soc_mem_field32_get(unit, mem, old_vent,
   3807                                               TAG_ACTION_PROFILE_PTRf);
   3808             rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, profile_idx);
   3809         }
   3810     }
   3811 
   3812     return rv;
   3813 }
   3814 
   3815 /*
   3816  * Function:
   3817  *      _bcm_tr2_vlan_vp_untagged_get
   3818  * Purpose:
   3819  *      Get tagging/untagging status of a VLAN virtual port by
   3820  *      reading the (VLAN VP, VLAN) egress vlan translation entry.
   3821  * Parameters:
   3822  *      unit - (IN) SOC unit number. 
   3823  *      vlan - (IN) VLAN to remove virtual port from.
   3824  *      vp   - (IN) Virtual port number.
   3825  *      flags - (OUT) Untagging status of the VLAN virtual port.
   3826  * Returns:
   3827  *      BCM_E_XXX
   3828  */
   3829 STATIC int
   3830 _bcm_tr2_vlan_vp_untagged_get(int unit, bcm_vlan_t vlan, int vp,
   3831                                   int *flags)
   3832 {
   3833     uint32      vent[SOC_MAX_MEM_FIELD_WORDS];
   3834     uint32      res_vent[SOC_MAX_MEM_FIELD_WORDS];
   3835 
   3836     int rv, idx;
   3837     uint32 profile_idx;
   3838     bcm_vlan_action_set_t action;
   3839     soc_mem_t mem = EGR_VLAN_XLATEm;
   3840 
   3841     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   3842         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   3843     }
   3844 
   3845     *flags = 0;
   3846 
   3847     sal_memset(vent, 0, sizeof(vent));
   3848     sal_memset(res_vent, 0, sizeof(res_vent));
   3849 
   3850     if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   3851         soc_mem_field32_set(unit, mem, vent, ENTRY_TYPEf, 1);
   3852     } else if (soc_mem_field_valid(unit, mem, KEY_TYPEf)) {
   3853         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, 1);
   3854     }
   3855     soc_mem_field32_set(unit, mem, vent, DVPf, vp);
   3856     soc_mem_field32_set(unit, mem, vent, OVIDf, vlan);
   3857 
   3858     rv = soc_mem_search(unit, mem, MEM_BLOCK_ALL, &idx, vent, res_vent, 0);
   3859     if (rv == SOC_E_NONE) {
   3860         int is_valid = 0;
   3861         if (soc_feature(unit, soc_feature_base_valid)) {
   3862             is_valid = soc_mem_field32_get(unit, mem, res_vent,
   3863                                            BASE_VALID_0f) == 3 &&
   3864                        soc_mem_field32_get(unit, mem, res_vent,
   3865                                            BASE_VALID_1f) == 7;
   3866         } else {
   3867             is_valid = soc_mem_field32_get(unit, mem, res_vent, VALIDf);
   3868         }
   3869 
   3870         if (is_valid) {
   3871             profile_idx = soc_mem_field32_get(unit, mem, res_vent,
   3872                                               TAG_ACTION_PROFILE_PTRf);
   3873             _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, profile_idx);
   3874 
   3875             if (bcmVlanActionNone == action.ot_inner) {
   3876                 *flags = BCM_VLAN_PORT_UNTAGGED;
   3877             }
   3878         }
   3879     }
   3880 
   3881     return rv;
   3882 }
   3883 
   3884 /*
   3885  * Function:
   3886  *      bcm_tr2_vlan_gport_add
   3887  * Purpose:
   3888  *      Add a VLAN/NIV/Extender virtual port to the specified vlan.
   3889  * Parameters:
   3890  *      unit  - (IN) SOC unit number. 
   3891  *      vlan  - (IN) VLAN ID to add virtual port to as a member.
   3892  *      gport - (IN) VP Gport ID
   3893  *      flags - (IN) Indicates if packet should egress out of the given
   3894  *                   VLAN virtual port untagged. Not applicable to NIV or
   3895  *                   Extender VPs. 
   3896  * Returns:
   3897  *      BCM_E_XXX
   3898  */
   3899 int
   3900 bcm_tr2_vlan_gport_add(int unit, bcm_vlan_t vlan, bcm_gport_t gport,
   3901                            int flags)
   3902 {
   3903     int rv = BCM_E_NONE;
   3904     int vp;
   3905     bcm_vlan_port_t vlan_vp;
   3906     bcm_gport_t phy_port_trunk = BCM_GPORT_INVALID;
   3907     int is_local;
   3908     vlan_tab_entry_t vtab;
   3909     bcm_pbmp_t vlan_pbmp, vlan_ubmp, l2_pbmp, l3_pbmp;
   3910     int i, mc_idx;
   3911     bcm_if_t encap_id;
   3912     bcm_multicast_t group;
   3913     int bc_idx, umc_idx, uuc_idx;
   3914     int bc_do_not_add = 0, umc_do_not_add = 0, uuc_do_not_add = 0;
   3915     soc_field_t group_type[3] = {BC_IDXf, UMC_IDXf, UUC_IDXf};
   3916     int egr_vt_added = FALSE, is_glp_port = 0;
   3917     int ing_vp_vlan_membership_added = FALSE;
   3918     int egr_vp_vlan_membership_added = FALSE;
   3919     int ing_vp_group_added = FALSE, eg_vp_group_added = FALSE, vlan_vfi, is_vfi;
   3920     _bcm_vp_vlan_mbrship_key_type_e key_type;
   3921 
   3922     COMPILER_REFERENCE(vlan_vfi);
   3923     COMPILER_REFERENCE(key_type);
   3924 
   3925     /* check for specfic combination */
   3926     if (flags & BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP) {
   3927         if ((flags & (BCM_VLAN_GPORT_ADD_INGRESS_ONLY | 
   3928                      BCM_VLAN_GPORT_ADD_EGRESS_ONLY)) ==
   3929             (BCM_VLAN_GPORT_ADD_INGRESS_ONLY | 
   3930              BCM_VLAN_GPORT_ADD_EGRESS_ONLY)) {
   3931              return BCM_E_PARAM;
   3932         }
   3933     }
   3934 
   3935 #ifdef BCM_TRIUMPH3_SUPPORT
   3936     if (_BCM_VPN_VFI_IS_SET(vlan)) {
   3937         is_vfi = 1;
   3938         key_type = _bcm_vp_vlan_mbrship_vp_vfi_type;
   3939         _BCM_VPN_GET(vlan_vfi, _BCM_VPN_TYPE_VFI, vlan);
   3940     } else
   3941 #endif /* BCM_TRIUMPH3_SUPPORT */
   3942     {
   3943         is_vfi = 0;
   3944         key_type = _bcm_vp_vlan_mbrship_vp_vlan_type;
   3945         vlan_vfi = vlan;
   3946 
   3947         /* Check that unsupported flags are not set */
   3948         if (flags & ~(BCM_VLAN_PORT_UNTAGGED |
   3949                       BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP |
   3950                       BCM_VLAN_GPORT_ADD_INGRESS_ONLY |
   3951                       BCM_VLAN_GPORT_ADD_EGRESS_ONLY  |
   3952                       BCM_VLAN_GPORT_ADD_STP_MASK |
   3953                       BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD |
   3954                       BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD |
   3955                       BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD)) {
   3956             return BCM_E_PARAM;
   3957         }
   3958     }
   3959 
   3960     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   3961         vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
   3962 
   3963         /* Get the physical port or trunk the VP resides on */
   3964         bcm_vlan_port_t_init(&vlan_vp);
   3965         vlan_vp.vlan_port_id = gport;
   3966         BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_find(unit, &vlan_vp));
   3967         if (is_vfi) {
   3968 #ifdef BCM_TRIUMPH3_SUPPORT
   3969             if (soc_feature(unit, soc_feature_vlan_vfi)) {
   3970                 return _bcm_tr3_vlan_port_add(unit, vlan, &vlan_vp);
   3971             }
   3972 #endif /* BCM_TRIUMPH3_SUPPORT */
   3973         } else {
   3974             phy_port_trunk = vlan_vp.port;
   3975         }
   3976     } else
   3977 #ifdef BCM_TRIDENT_SUPPORT
   3978     if (BCM_GPORT_IS_NIV_PORT(gport)) {
   3979         bcm_niv_port_t niv_port;
   3980         bcm_niv_egress_t niv_egress;
   3981         int              count;
   3982 
   3983         vp = BCM_GPORT_NIV_PORT_ID_GET(gport);
   3984 
   3985         /* Get the physical port or trunk the VP resides on */
   3986         bcm_niv_port_t_init(&niv_port);
   3987         niv_port.niv_port_id = gport;
   3988         BCM_IF_ERROR_RETURN(bcm_trident_niv_port_get(unit, &niv_port));
   3989         if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) {
   3990             bcm_niv_egress_t_init(&niv_egress);
   3991             rv = bcm_trident_niv_egress_get(unit, niv_port.niv_port_id,
   3992                                             1, &niv_egress, &count);
   3993             if (BCM_SUCCESS(rv)) {
   3994                 if (!(niv_egress.flags & BCM_NIV_EGRESS_MULTICAST)) {
   3995                     phy_port_trunk = niv_egress.port;
   3996                 } 
   3997             }
   3998         } else {
   3999             phy_port_trunk = niv_port.port;
   4000         }
   4001     } else
   4002 #endif /* BCM_TRIDENT_SUPPORT */
   4003 #ifdef BCM_TRIUMPH3_SUPPORT
   4004     if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4005         bcm_extender_port_t extender_port;
   4006         bcm_extender_egress_t extender_egress;
   4007         int count;
   4008         vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   4009 
   4010         /* Get the physical port or trunk the VP resides on */
   4011         bcm_extender_port_t_init(&extender_port);
   4012         extender_port.extender_port_id = gport;
   4013         BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port));
   4014         if (extender_port.flags & BCM_EXTENDER_PORT_MATCH_NONE) {
   4015             bcm_extender_egress_t_init(&extender_egress);
   4016             rv = bcm_tr3_extender_egress_get_all(unit, extender_port.extender_port_id,
   4017                                             1, &extender_egress, &count);
   4018             if (count == 0) {
   4019                 /* No Extender egress object has been added to VP yet. */
   4020                 return BCM_E_CONFIG;
   4021             }
   4022             if (BCM_SUCCESS(rv)) {
   4023                 if (!(extender_egress.flags & BCM_EXTENDER_EGRESS_MULTICAST)) {
   4024                     phy_port_trunk = extender_egress.port;
   4025                 }
   4026             }
   4027         } else {
   4028             phy_port_trunk = extender_port.port;
   4029         }
   4030     } else
   4031 #endif /* BCM_TRIUMPH3_SUPPORT */
   4032 #ifdef BCM_TRIDENT2_SUPPORT
   4033     if (BCM_GPORT_IS_TRUNK(gport)) {
   4034         BCM_IF_ERROR_RETURN(
   4035             _bcm_esw_trunk_tid_to_vp_lag_vp(unit, BCM_GPORT_TRUNK_GET(gport), &vp));
   4036 
   4037         /* VPLAG special process*/
   4038         flags |= (BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD |
   4039                   BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD |
   4040                   BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD);
   4041     } else if (BCM_GPORT_IS_MPLS_PORT(gport)) {
   4042         vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
   4043     } else
   4044 #endif
   4045 
   4046 #ifdef BCM_TRIDENT2_SUPPORT
   4047     if (BCM_GPORT_IS_VXLAN_PORT(gport) &&
   4048         soc_feature(unit, soc_feature_vxlan)) {
   4049         vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
   4050     } else
   4051 #endif /* BCM_TRIDENT2_SUPPORT */
   4052 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4053     if (BCM_GPORT_IS_L2GRE_PORT(gport)) {
   4054         vp = BCM_GPORT_L2GRE_PORT_ID_GET(gport);
   4055     }else if (BCM_GPORT_IS_MIM_PORT(gport)) {
   4056         vp = BCM_GPORT_MIM_PORT_ID_GET(gport);
   4057     } else if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4058 			BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   4059         bcm_trunk_t trunk_id;
   4060         if (BCM_SUCCESS(bcm_esw_trunk_find(unit, 0, gport, &trunk_id))) {
   4061             vp = trunk_id | BCM_TGID_TRUNK_INDICATOR(unit);
   4062         } else {
   4063             /* Put together a VP like value for subport, which will be
   4064                used below, this is a (mod,port) value for GPP */
   4065             if (SOC_IS_TRIDENT3X(unit) && _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) {
   4066                 vp = _BCM_SUBPORT_COE_PORT_GLP_GET(BCM_GPORT_SUBPORT_PORT_GET(gport));
   4067             } else {
   4068                 vp = (BCM_GPORT_SUBPORT_PORT_GET(gport) & 0x7FFF);
   4069             }
   4070         }
   4071         is_glp_port = 1;
   4072 
   4073         /* Set the key_type as glp_vlan type */
   4074         key_type = _bcm_vp_vlan_mbrship_glp_vlan_type;
   4075     } else
   4076 #endif
   4077 #ifdef BCM_TRIDENT3_SUPPORT
   4078     if (soc_feature(unit, soc_feature_flex_flow) &&
   4079             BCM_GPORT_IS_FLOW_PORT(gport)) {
   4080         vp = BCM_GPORT_FLOW_PORT_ID_GET(gport);
   4081     } else
   4082 #endif
   4083 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4084 if (BCM_GPORT_IS_MODPORT(gport)) {
   4085         vp = (BCM_GPORT_MODPORT_MODID_GET(gport) << 8) | BCM_GPORT_MODPORT_PORT_GET(gport);
   4086         is_glp_port = 1;
   4087         key_type = _bcm_vp_vlan_mbrship_glp_vfi_type;
   4088     } else
   4089 #endif
   4090     {
   4091         return BCM_E_PARAM;
   4092     }
   4093 
   4094     if (phy_port_trunk != BCM_GPORT_INVALID) {
   4095         BCM_IF_ERROR_RETURN
   4096             (_bcm_tr2_phy_port_trunk_is_local(unit, phy_port_trunk, &is_local));
   4097         if (!is_local) {
   4098             /* VP is added to replication lists only if it resides on a local port */
   4099             return BCM_E_PORT;
   4100         }
   4101     }
   4102 
   4103     if(!is_vfi && !is_glp_port) {
   4104 
   4105         sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t));
   4106 
   4107         soc_mem_lock(unit, VLAN_TABm);
   4108 
   4109         rv = soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab); 
   4110         if (rv < 0) {
   4111             soc_mem_unlock(unit, VLAN_TABm);
   4112             return rv;
   4113         }
   4114 
   4115         if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) {
   4116             soc_mem_unlock(unit, VLAN_TABm);
   4117             return BCM_E_NOT_FOUND;
   4118         }
   4119 
   4120     /* Enable VP switching on the VLAN */
   4121     if (!SHR_BITGET(vlan_info[unit].vp_mode, vlan) &&
   4122         (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) &&
   4123         (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf))) {
   4124         
   4125         soc_mem_field32_set(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf, 1);
   4126         rv = soc_mem_write(unit, VLAN_TABm, MEM_BLOCK_ALL, vlan, &vtab);
   4127             if (rv < 0) {
   4128                 soc_mem_unlock(unit, VLAN_TABm);
   4129                 return rv;
   4130             }
   4131             soc_mem_unlock(unit, VLAN_TABm);
   4132 
   4133             /* Also need to copy the physical port members to the L2_BITMAP of
   4134             * the IPMC entry for each group once we've gone virtual */
   4135             rv = mbcm_driver[unit]->mbcm_vlan_port_get
   4136                         (unit, vlan, &vlan_pbmp, &vlan_ubmp, NULL);
   4137             if (rv < 0) {
   4138                 return rv;
   4139             }
   4140 
   4141         /* Deal with each group */
   4142         for (i = 0; i < 3; i++) {
   4143             mc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, group_type[i]);
   4144             /* IPMC entry 0 is reserved */
   4145             if (!mc_idx) {
   4146                 continue;
   4147             }
   4148                 rv = _bcm_esw_multicast_ipmc_read(unit, mc_idx, &l2_pbmp, &l3_pbmp);
   4149                 if (rv < 0) {
   4150                     return rv;
   4151                 }
   4152                 rv = _bcm_esw_multicast_ipmc_write(unit, mc_idx, vlan_pbmp,
   4153                            l3_pbmp, TRUE);
   4154                 if (rv < 0) {
   4155                     return rv;
   4156                 }
   4157             }
   4158         } else { 
   4159             soc_mem_unlock(unit, VLAN_TABm);
   4160         }
   4161 
   4162         bc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, BC_IDXf);
   4163         umc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UMC_IDXf);
   4164         uuc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UUC_IDXf);
   4165 
   4166         if (flags & BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD) {
   4167             bc_do_not_add = 1;
   4168         } else {
   4169             bc_do_not_add = 0;
   4170         }
   4171         if (flags & BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD) {
   4172             umc_do_not_add = 1;
   4173         } else {
   4174             umc_do_not_add = 0;
   4175         }
   4176         if (flags & BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD) {
   4177             uuc_do_not_add = 1;
   4178         } else {
   4179             uuc_do_not_add = 0;
   4180         }
   4181 
   4182         if ((bc_idx == umc_idx) && (bc_do_not_add != umc_do_not_add)) {
   4183             return BCM_E_PARAM;
   4184         }
   4185         if ((bc_idx == uuc_idx) && (bc_do_not_add != uuc_do_not_add)) {
   4186             return BCM_E_PARAM;
   4187         }
   4188         if ((umc_idx == uuc_idx) && (umc_do_not_add != uuc_do_not_add)) {
   4189             return BCM_E_PARAM;
   4190         }
   4191 
   4192         if (phy_port_trunk == BCM_GPORT_INVALID) {
   4193             if (!bc_do_not_add || !umc_do_not_add || !uuc_do_not_add) {
   4194                 /* If VP's physical port is invalid, this VP cannot be added
   4195                  * to multicast groups. User should set the DO_NOT_ADD flags.
   4196                  */
   4197                 return BCM_E_PARAM;
   4198             }
   4199         }
   4200     if (!bc_do_not_add) {
   4201         /* Add the VP to the BC group */
   4202         BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, bc_idx,
   4203                     &group));
   4204         if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4205             BCM_IF_ERROR_RETURN
   4206                 (bcm_esw_multicast_vlan_encap_get(unit, group, phy_port_trunk,
   4207                                                   gport, &encap_id));
   4208         } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4209             BCM_IF_ERROR_RETURN
   4210                 (bcm_esw_multicast_niv_encap_get(unit, group, phy_port_trunk,
   4211                                                  gport, &encap_id));
   4212         } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4213             BCM_IF_ERROR_RETURN
   4214                 (bcm_esw_multicast_extender_encap_get(unit, group, phy_port_trunk,
   4215                                                  gport, &encap_id));
   4216         }        
   4217         /* coverity[stack_use_overflow : FALSE] */
   4218         BCM_IF_ERROR_RETURN(bcm_esw_multicast_egress_add(unit, group,
   4219                     phy_port_trunk, encap_id)); 
   4220     }
   4221     if (!umc_do_not_add) {
   4222         /* Add the VP to the UMC group, if UMC group is different from BC group */
   4223         BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, umc_idx,
   4224                     &group));
   4225         if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4226             BCM_IF_ERROR_RETURN
   4227                 (bcm_esw_multicast_vlan_encap_get(unit, group, phy_port_trunk,
   4228                                                   gport, &encap_id));
   4229         } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4230             BCM_IF_ERROR_RETURN
   4231                 (bcm_esw_multicast_niv_encap_get(unit, group, phy_port_trunk,
   4232                                                  gport, &encap_id));
   4233         } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4234             BCM_IF_ERROR_RETURN
   4235                 (bcm_esw_multicast_extender_encap_get(unit, group, phy_port_trunk,
   4236                                                  gport, &encap_id));
   4237         }
   4238         if (umc_idx != bc_idx) {        
   4239             BCM_IF_ERROR_RETURN(bcm_esw_multicast_egress_add(unit, group,
   4240                         phy_port_trunk, encap_id)); 
   4241         }
   4242     }
   4243     if (!uuc_do_not_add) {
   4244         /* Add the VP to the UUC group, if UUC group is different from BC/UMC group */
   4245         BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, uuc_idx,
   4246                     &group));
   4247         if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4248             BCM_IF_ERROR_RETURN
   4249                 (bcm_esw_multicast_vlan_encap_get(unit, group, phy_port_trunk,
   4250                                                   gport, &encap_id));
   4251         } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4252             BCM_IF_ERROR_RETURN
   4253                 (bcm_esw_multicast_niv_encap_get(unit, group, phy_port_trunk,
   4254                                                  gport, &encap_id));
   4255         } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4256             BCM_IF_ERROR_RETURN
   4257                 (bcm_esw_multicast_extender_encap_get(unit, group, phy_port_trunk,
   4258                                                  gport, &encap_id));
   4259         }
   4260         if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) {       
   4261             BCM_IF_ERROR_RETURN(bcm_esw_multicast_egress_add(unit, group,
   4262                         phy_port_trunk, encap_id)); 
   4263         }
   4264     }
   4265 
   4266         /* Add (vlan, vp) to egress vlan translation table and
   4267          * configure the egress untagging status.
   4268          */
   4269         if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4270             BCM_IF_ERROR_RETURN
   4271                 (_bcm_tr2_vlan_vp_untagged_add(unit, vlan, vp, flags));
   4272             egr_vt_added = TRUE;
   4273         }
   4274 #ifdef BCM_TRIDENT_SUPPORT
   4275         else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4276             BCM_IF_ERROR_RETURN
   4277                 (bcm_trident_niv_untagged_add(unit, vlan, vp, flags, &egr_vt_added));
   4278         }
   4279 #endif /* BCM_TRIDENT_SUPPORT */
   4280 #ifdef BCM_TRIUMPH3_SUPPORT
   4281         else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4282             BCM_IF_ERROR_RETURN
   4283                 (bcm_tr3_extender_untagged_add(unit, vlan, vp, flags, &egr_vt_added));
   4284         }
   4285 #endif /* BCM_TRIUMPH3_SUPPORT */
   4286  } else { /* !is_vfi && !is_glp_port */
   4287 
   4288         /* For VFI and GLP types, set the BC/UUC/UMC flags as 1 since they are not
   4289            used, these flags will be validated below for config change */
   4290         bc_do_not_add = uuc_do_not_add = umc_do_not_add = 1;
   4291     }
   4292 
   4293     /* Configure ingress and egress VLAN membership checks */
   4294     if (flags & BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP) {
   4295 
   4296 #ifdef BCM_TRIDENT2_SUPPORT
   4297         if (soc_feature(unit, soc_feature_ing_vp_vlan_membership)) { 
   4298             if (!(flags & BCM_VLAN_GPORT_ADD_EGRESS_ONLY)) {
   4299                 BCM_IF_ERROR_RETURN(bcm_td2_ing_vp_vlan_membership_add(unit, 
   4300                               vp, vlan_vfi, flags, key_type));
   4301                 ing_vp_vlan_membership_added = TRUE;
   4302             }
   4303         } else
   4304 #endif /* BCM_TRIDENT2_SUPPORT */
   4305         {
   4306             if (!(flags & BCM_VLAN_GPORT_ADD_EGRESS_ONLY)) {
   4307                 return BCM_E_UNAVAIL;
   4308             }
   4309         }
   4310 
   4311 #ifdef BCM_TRIDENT2_SUPPORT
   4312         if (soc_feature(unit, soc_feature_egr_vp_vlan_membership)) {
   4313             if (!(flags & BCM_VLAN_GPORT_ADD_INGRESS_ONLY)) {
   4314 
   4315                 BCM_IF_ERROR_RETURN(bcm_td2_egr_vp_vlan_membership_add(unit, 
   4316                              vp, vlan_vfi, flags, key_type));
   4317                 egr_vp_vlan_membership_added = TRUE;
   4318             }
   4319         } else
   4320 #endif /* BCM_TRIDENT2_SUPPORT */
   4321         {
   4322             if (!(flags & BCM_VLAN_GPORT_ADD_INGRESS_ONLY)) {
   4323                 return BCM_E_UNAVAIL;
   4324             }
   4325         }
   4326     } else {
   4327 #ifdef BCM_TRIDENT_SUPPORT
   4328         /* Due to change in VP's VLAN membership, may need to move VP to
   4329          * another VP group.
   4330          */
   4331         uint32 filter_flags;
   4332 
   4333         BCM_IF_ERROR_RETURN(
   4334             bcm_esw_port_vlan_member_get(unit, gport, &filter_flags));
   4335 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4336         if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   4337             if (!bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
   4338                 if (!(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)
   4339                         && (filter_flags & BCM_PORT_VLAN_MEMBER_INGRESS)) {
   4340                     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_move(
   4341                                 unit, gport, vlan, TRUE, FALSE, flags));
   4342                     ing_vp_group_added = TRUE;
   4343                 }
   4344             } else {
   4345                 ing_vp_group_added = FALSE;
   4346             }
   4347 
   4348             if (!bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
   4349                 if (!(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)
   4350                         && (filter_flags & BCM_PORT_VLAN_MEMBER_EGRESS)) {
   4351                     BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_move(unit,
   4352                                             gport, vlan, TRUE, TRUE, flags));
   4353                     eg_vp_group_added = TRUE;
   4354                 }
   4355             } else {
   4356                 eg_vp_group_added = FALSE;
   4357             }
   4358         } else
   4359 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   4360         {
   4361             if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) {
   4362                 if (!bcm_td_ing_vp_group_unmanaged_get(unit)) {
   4363                     if ((filter_flags & BCM_PORT_VLAN_MEMBER_INGRESS) &&
   4364                             !(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) {
   4365                         BCM_IF_ERROR_RETURN
   4366                             (bcm_td_ing_vp_group_move(unit, vp, vlan, TRUE));
   4367                         ing_vp_group_added = TRUE;
   4368                     }
   4369                 } else {
   4370                     ing_vp_group_added = TRUE;
   4371                 }
   4372             }     
   4373             if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) {
   4374                 if (!bcm_td_egr_vp_group_unmanaged_get(unit)) {
   4375                     if ((filter_flags & BCM_PORT_VLAN_MEMBER_EGRESS) &&
   4376                             !(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) {
   4377                         BCM_IF_ERROR_RETURN
   4378                             (bcm_td_eg_vp_group_move(unit, vp, vlan, TRUE));
   4379                         eg_vp_group_added = TRUE;
   4380                     }
   4381                 } else {
   4382                     eg_vp_group_added = TRUE;
   4383                 }
   4384             }
   4385         }
   4386 #endif /* BCM_TRIDENT_SUPPORT */
   4387     } 
   4388 
   4389     if (bc_do_not_add && umc_do_not_add && uuc_do_not_add &&
   4390         !egr_vt_added && !ing_vp_vlan_membership_added &&
   4391         !egr_vp_vlan_membership_added && !ing_vp_group_added &&
   4392         !eg_vp_group_added) {
   4393         /* The given VP has not been added to VLAN's BC, UMC, and UUC groups.
   4394          * It also has not been added to egress VLAN translation table, to
   4395          * VP VLAN membership check table, or to a VP group.
   4396          * This scenario does not make sense. Moreover, bcm_vlan_gport_get_all
   4397          * would not be able to find this VP.
   4398          */
   4399         return BCM_E_PARAM;
   4400     }
   4401 
   4402     return BCM_E_NONE;
   4403 }
   4404 
   4405 /*
   4406  * Function:
   4407  *      bcm_tr2_vlan_gport_delete
   4408  * Purpose:
   4409  *      Remove a VLAN/NIV/Extender virtual port from the specified vlan.
   4410  * Parameters:
   4411  *      unit  - (IN) SOC unit number. 
   4412  *      vlan  - (IN) VLAN to remove virtual port from.
   4413  *      gport - (IN) VP Gport ID
   4414  * Returns:
   4415  *      BCM_E_XXX
   4416  */
   4417 int
   4418 bcm_tr2_vlan_gport_delete(int unit, bcm_vlan_t vlan, bcm_gport_t gport) 
   4419 {
   4420     int rv = BCM_E_NONE;
   4421     int vp;
   4422     bcm_vlan_port_t vlan_vp;
   4423     bcm_gport_t phy_port_trunk = BCM_GPORT_INVALID;
   4424     int is_local;
   4425     vlan_tab_entry_t vtab;
   4426     int bc_idx, umc_idx, uuc_idx;
   4427     bcm_multicast_t group;
   4428     bcm_if_t encap_id;
   4429     int bc_not_found = TRUE;
   4430     int umc_not_found = TRUE;
   4431     int uuc_not_found = TRUE;
   4432     int egr_vt_found = FALSE;
   4433     int ing_vp_vlan_membership_found = FALSE;
   4434     int egr_vp_vlan_membership_found = FALSE;
   4435     int ing_vp_group_found = FALSE, eg_vp_group_found = FALSE;
   4436     int is_glp_port = 0, vlan_vfi = vlan, is_vfi = 0;
   4437     _bcm_vp_vlan_mbrship_key_type_e key_type;
   4438 #ifdef BCM_TRIDENT_SUPPORT
   4439     uint32 filter_flags;
   4440 #endif
   4441 
   4442     COMPILER_REFERENCE(vlan_vfi);
   4443     COMPILER_REFERENCE(key_type);
   4444 
   4445 #ifdef BCM_TRIUMPH3_SUPPORT
   4446     if (_BCM_VPN_VFI_IS_SET(vlan)) {
   4447         is_vfi = 1;
   4448         key_type = _bcm_vp_vlan_mbrship_vp_vfi_type;
   4449         _BCM_VPN_GET(vlan_vfi, _BCM_VPN_TYPE_VFI, vlan);
   4450     } else
   4451 #endif /* BCM_TRIUMPH3_SUPPORT */
   4452     {
   4453         is_vfi = 0;
   4454         key_type = _bcm_vp_vlan_mbrship_vp_vlan_type;
   4455         vlan_vfi = vlan;
   4456     }
   4457 
   4458     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4459         vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
   4460 
   4461         /* Get the physical port or trunk the VP resides on */
   4462         bcm_vlan_port_t_init(&vlan_vp);
   4463         vlan_vp.vlan_port_id = gport;
   4464         BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_find(unit, &vlan_vp));
   4465 
   4466 #ifdef BCM_TRIUMPH3_SUPPORT
   4467         if (is_vfi) {
   4468             if (soc_feature(unit, soc_feature_vlan_vfi)) {
   4469                 return _bcm_tr3_vlan_port_delete(unit, vlan, vp);
   4470             }
   4471         } else
   4472 #endif /* BCM_TRIUMPH3_SUPPORT */
   4473         {
   4474             phy_port_trunk = vlan_vp.port;
   4475         }
   4476     } else
   4477 #ifdef BCM_TRIDENT_SUPPORT
   4478     if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4479         bcm_niv_port_t niv_port;
   4480         bcm_niv_egress_t niv_egress;
   4481         int              count;
   4482 
   4483         vp = BCM_GPORT_NIV_PORT_ID_GET(gport);
   4484 
   4485         /* Get the physical port or trunk the VP resides on */
   4486         bcm_niv_port_t_init(&niv_port);
   4487         niv_port.niv_port_id = gport;
   4488         BCM_IF_ERROR_RETURN(bcm_trident_niv_port_get(unit, &niv_port));
   4489         if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) {
   4490             phy_port_trunk = BCM_GPORT_INVALID;
   4491             bcm_niv_egress_t_init(&niv_egress);
   4492             rv = bcm_trident_niv_egress_get(unit, niv_port.niv_port_id,
   4493                                             1, &niv_egress, &count);
   4494             if (BCM_SUCCESS(rv)) {
   4495                 if (!(niv_egress.flags & BCM_NIV_EGRESS_MULTICAST)) {
   4496                     phy_port_trunk = niv_egress.port;
   4497                 } 
   4498             }
   4499         } else {
   4500             phy_port_trunk = niv_port.port;
   4501         }
   4502     } else
   4503 #endif /* BCM_TRIDENT_SUPPORT */
   4504 #ifdef BCM_TRIUMPH3_SUPPORT
   4505     if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4506         bcm_extender_port_t extender_port;
   4507         bcm_extender_egress_t extender_egress;
   4508         int count;
   4509 
   4510         vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   4511 
   4512         /* Get the physical port or trunk the VP resides on */
   4513         bcm_extender_port_t_init(&extender_port);
   4514         extender_port.extender_port_id = gport;
   4515         BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port));
   4516         if (extender_port.flags & BCM_EXTENDER_PORT_MATCH_NONE) {
   4517             bcm_extender_egress_t_init(&extender_egress);
   4518             rv = bcm_tr3_extender_egress_get_all(unit,
   4519                         extender_port.extender_port_id, 1, &extender_egress, &count);
   4520             if (count == 0) {
   4521                 /* No Extender egress object has been added to VP yet. */
   4522                 return BCM_E_CONFIG;
   4523             }
   4524             if (BCM_SUCCESS(rv)) {
   4525                 if (!extender_egress.flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   4526                     phy_port_trunk = extender_egress.port;
   4527                 }
   4528             }
   4529         } else {
   4530             phy_port_trunk = extender_port.port;
   4531         }
   4532 
   4533     } else
   4534 #endif /* BCM_TRIUMPH3_SUPPORT */
   4535 #ifdef BCM_TRIDENT2_SUPPORT
   4536     if (BCM_GPORT_IS_TRUNK(gport)) {
   4537         BCM_IF_ERROR_RETURN(
   4538             _bcm_esw_trunk_tid_to_vp_lag_vp(unit, BCM_GPORT_TRUNK_GET(gport), &vp));
   4539     } else if (BCM_GPORT_IS_MPLS_PORT(gport)) {
   4540         vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
   4541     } else
   4542 #endif
   4543 
   4544 #ifdef BCM_TRIDENT2_SUPPORT
   4545     if (BCM_GPORT_IS_VXLAN_PORT(gport) &&
   4546         soc_feature(unit, soc_feature_vxlan)) {
   4547         vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
   4548     } else
   4549 #endif /* BCM_TRIDENT2_SUPPORT */
   4550 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4551     if (BCM_GPORT_IS_L2GRE_PORT(gport)) {
   4552         vp = BCM_GPORT_L2GRE_PORT_ID_GET(gport);
   4553     } else if (BCM_GPORT_IS_MIM_PORT(gport)) {
   4554         vp = BCM_GPORT_MIM_PORT_ID_GET(gport);
   4555     } else if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   4556 			BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   4557         bcm_trunk_t trunk_id;
   4558         if (BCM_SUCCESS(bcm_esw_trunk_find(unit, 0, gport, &trunk_id))) {
   4559             vp = trunk_id | BCM_TGID_TRUNK_INDICATOR(unit);
   4560         } else {
   4561             /* Put together a VP like value for subport, which will be
   4562                used below */
   4563             if (SOC_IS_TRIDENT3X(unit) && _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) {
   4564                 vp = _BCM_SUBPORT_COE_PORT_GLP_GET(BCM_GPORT_SUBPORT_PORT_GET(gport));
   4565             } else {
   4566                 vp = (BCM_GPORT_SUBPORT_PORT_GET(gport) & 0x7FFF);
   4567             }
   4568         }
   4569 
   4570         /* Make a note that this is a GPP port we are dealing with */
   4571         is_glp_port = 1;
   4572 
   4573         /* Set the key_type as glp_vlan type */
   4574         key_type = _bcm_vp_vlan_mbrship_glp_vlan_type;
   4575     } else
   4576 #endif
   4577 #ifdef BCM_TRIDENT3_SUPPORT
   4578     if (soc_feature(unit, soc_feature_flex_flow) &&
   4579             BCM_GPORT_IS_FLOW_PORT(gport)) {
   4580         vp = BCM_GPORT_FLOW_PORT_ID_GET(gport);
   4581     } else
   4582 #endif
   4583 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4584 if (BCM_GPORT_IS_MODPORT(gport)) {
   4585         vp = (BCM_GPORT_MODPORT_MODID_GET(gport) << 8) | BCM_GPORT_MODPORT_PORT_GET(gport);
   4586         is_glp_port = 1;
   4587         key_type = _bcm_vp_vlan_mbrship_glp_vfi_type;
   4588     } else
   4589 #endif
   4590     {
   4591         return BCM_E_PARAM;
   4592     }
   4593 
   4594     if (phy_port_trunk != BCM_GPORT_INVALID) {
   4595         BCM_IF_ERROR_RETURN
   4596             (_bcm_tr2_phy_port_trunk_is_local(unit, phy_port_trunk, &is_local));
   4597         if (!is_local) {
   4598             /* VP to be deleted must reside on a local port */
   4599             return BCM_E_PORT;
   4600         }
   4601     }
   4602 
   4603     if(!is_vfi && !is_glp_port) {
   4604 
   4605         sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t));
   4606 
   4607         SOC_IF_ERROR_RETURN
   4608             (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab)); 
   4609 
   4610         if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) {
   4611             return BCM_E_NOT_FOUND;
   4612         }
   4613 
   4614         if (!SHR_BITGET(vlan_info[unit].vp_mode, vlan)) {
   4615             if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
   4616                 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) {
   4617                     /* VP switching is not enabled on the VLAN */
   4618                     return BCM_E_PORT;
   4619                 }
   4620             }
   4621         }
   4622 
   4623         if (phy_port_trunk != BCM_GPORT_INVALID) {
   4624             /* Delete the VP from the BC group */
   4625             bc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, BC_IDXf);
   4626             BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, bc_idx,
   4627                         &group));
   4628             if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4629                 BCM_IF_ERROR_RETURN
   4630                     (bcm_esw_multicast_vlan_encap_get(unit, group, phy_port_trunk,
   4631                                                       gport, &encap_id));
   4632             } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4633                 BCM_IF_ERROR_RETURN
   4634                     (bcm_esw_multicast_niv_encap_get(unit, group, phy_port_trunk,
   4635                                                      gport, &encap_id));
   4636             } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4637                 BCM_IF_ERROR_RETURN
   4638                     (bcm_esw_multicast_extender_encap_get(unit, group, phy_port_trunk,
   4639                                                           gport, &encap_id));
   4640             }
   4641 
   4642             rv = bcm_esw_multicast_egress_delete(unit, group, phy_port_trunk, encap_id); 
   4643             /* BCM_E_NOT_FOUND is tolerated since the VP could have been added to the
   4644              * VLAN with the BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD flag.
   4645              */
   4646             if (BCM_SUCCESS(rv)) {
   4647                 bc_not_found = FALSE;
   4648             } else if (rv == BCM_E_NOT_FOUND) {
   4649                 bc_not_found = TRUE;
   4650                 rv = BCM_E_NONE;
   4651             } else {
   4652                 return rv;
   4653             }
   4654 
   4655             /* Delete the VP from the UMC group, if UMC group is different
   4656              * from BC group.
   4657              */ 
   4658             umc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UMC_IDXf);
   4659             BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, umc_idx,
   4660                         &group));
   4661             if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4662                 BCM_IF_ERROR_RETURN
   4663                     (bcm_esw_multicast_vlan_encap_get(unit, group, phy_port_trunk,
   4664                                                       gport, &encap_id));
   4665             } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4666                 BCM_IF_ERROR_RETURN
   4667                     (bcm_esw_multicast_niv_encap_get(unit, group, phy_port_trunk,
   4668                                                      gport, &encap_id));
   4669             } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4670                 BCM_IF_ERROR_RETURN
   4671                     (bcm_esw_multicast_extender_encap_get(unit, group, phy_port_trunk,
   4672                                                           gport, &encap_id));
   4673             }
   4674 
   4675             if (umc_idx != bc_idx) {
   4676                 rv = bcm_esw_multicast_egress_delete(unit, group, phy_port_trunk, encap_id); 
   4677                 /* BCM_E_NOT_FOUND is tolerated since the VP could have been added to
   4678                  * the VLAN with the BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD flag.
   4679                  */
   4680                 if (BCM_SUCCESS(rv)) {
   4681                     umc_not_found = FALSE;
   4682                 } else if (rv == BCM_E_NOT_FOUND) {
   4683                     umc_not_found = TRUE;
   4684                     rv = BCM_E_NONE;
   4685                 } else {
   4686                     return rv;
   4687                 }
   4688             } else {
   4689                 umc_not_found = bc_not_found;
   4690             }
   4691 
   4692             /* Delete the VP from the UUC group, if UUC group is different
   4693              * from BC and UMC groups.
   4694              */
   4695             uuc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UUC_IDXf);
   4696             BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, uuc_idx,
   4697                         &group));
   4698             if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4699                 BCM_IF_ERROR_RETURN
   4700                     (bcm_esw_multicast_vlan_encap_get(unit, group, phy_port_trunk,
   4701                                                       gport, &encap_id));
   4702             } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4703                 BCM_IF_ERROR_RETURN
   4704                     (bcm_esw_multicast_niv_encap_get(unit, group, phy_port_trunk,
   4705                                                      gport, &encap_id));
   4706             } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4707                 BCM_IF_ERROR_RETURN
   4708                     (bcm_esw_multicast_extender_encap_get(unit, group, phy_port_trunk,
   4709                                                           gport, &encap_id));
   4710             }
   4711 
   4712             if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) {
   4713                 rv = bcm_esw_multicast_egress_delete(unit, group, phy_port_trunk, encap_id); 
   4714                 /* BCM_E_NOT_FOUND is tolerated since the VP could have been added to
   4715                  * the VLAN with the BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD flag.
   4716                  */
   4717                 if (BCM_SUCCESS(rv)) {
   4718                     uuc_not_found = FALSE;
   4719                 } else if (rv == BCM_E_NOT_FOUND) {
   4720                     uuc_not_found = TRUE;
   4721                     rv = BCM_E_NONE;
   4722                 } else {
   4723                     return rv;
   4724                 }
   4725             } else if (uuc_idx == bc_idx) {
   4726                 uuc_not_found = bc_not_found;
   4727             } else {
   4728                 uuc_not_found = umc_not_found;
   4729             }
   4730         }
   4731 
   4732         /* Delete (vlan, vp) from egress vlan translation table */
   4733         if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4734             BCM_IF_ERROR_RETURN
   4735                 (_bcm_tr2_vlan_vp_untagged_delete(unit, vlan, vp));
   4736             egr_vt_found = TRUE;
   4737         }
   4738 #ifdef BCM_TRIDENT_SUPPORT
   4739         else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4740             rv = bcm_trident_niv_untagged_delete(unit, vlan, vp);
   4741             if (BCM_SUCCESS(rv)) {
   4742                 egr_vt_found = TRUE;
   4743             } else if (rv == BCM_E_NOT_FOUND) {
   4744                 egr_vt_found = FALSE;
   4745                 rv = BCM_E_NONE;
   4746             } else {
   4747                 return rv;
   4748             }
   4749         }
   4750 #endif /* BCM_TRIDENT_SUPPORT */
   4751 #ifdef BCM_TRIUMPH3_SUPPORT
   4752         else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4753             rv = bcm_tr3_extender_untagged_delete(unit, vlan, vp);
   4754             if (BCM_SUCCESS(rv)) {
   4755                 egr_vt_found = TRUE;
   4756             } else if (rv == BCM_E_NOT_FOUND) {
   4757                 egr_vt_found = FALSE;
   4758                 rv = BCM_E_NONE;
   4759             } else {
   4760                 return rv;
   4761             }
   4762         }
   4763 #endif /* BCM_TRIUMPH3_SUPPORT */
   4764     }
   4765 
   4766 #ifdef BCM_TRIDENT2_SUPPORT
   4767     if (soc_feature(unit, soc_feature_ing_vp_vlan_membership)) {
   4768         rv = bcm_td2_ing_vp_vlan_membership_delete(unit, vp, vlan_vfi,
   4769                                                    key_type);
   4770         if (BCM_SUCCESS(rv)) {
   4771             ing_vp_vlan_membership_found = TRUE;
   4772         } else if (rv == BCM_E_NOT_FOUND) {
   4773             ing_vp_vlan_membership_found = FALSE;
   4774             rv = BCM_E_NONE;
   4775         } else {
   4776             return rv;
   4777         }
   4778     }
   4779         
   4780     if (soc_feature(unit, soc_feature_egr_vp_vlan_membership)) {
   4781         rv = bcm_td2_egr_vp_vlan_membership_delete(unit, vp, vlan_vfi, 
   4782                                                    key_type);
   4783         if (BCM_SUCCESS(rv)) {
   4784             egr_vp_vlan_membership_found = TRUE;
   4785         } else if (rv == BCM_E_NOT_FOUND) {
   4786             egr_vp_vlan_membership_found = FALSE;
   4787             rv = BCM_E_NONE;
   4788         } else {
   4789             return rv;
   4790         }
   4791     }
   4792 #endif /* BCM_TRIDENT2_SUPPORT */
   4793 
   4794 #ifdef BCM_TRIDENT_SUPPORT
   4795     BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_get(unit, gport, &filter_flags));
   4796 
   4797 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4798     if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   4799         if (!bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
   4800             if (!(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP) &&
   4801                     (filter_flags & BCM_PORT_VLAN_MEMBER_INGRESS)) {
   4802                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_move(unit,
   4803                                         gport, vlan, FALSE, FALSE, 0));
   4804                 ing_vp_group_found = TRUE;
   4805             }
   4806         } else {
   4807             ing_vp_group_found = FALSE;
   4808         }
   4809 
   4810         if (!bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
   4811             if (!(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP) &&
   4812                     (filter_flags & BCM_PORT_VLAN_MEMBER_EGRESS)) {
   4813                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_port_move(unit,
   4814                                         gport, vlan, FALSE, TRUE, 0));
   4815 
   4816                 eg_vp_group_found = TRUE;
   4817             }
   4818         } else {
   4819             eg_vp_group_found = FALSE;
   4820         }
   4821     } else
   4822 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   4823     {
   4824         if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) {
   4825             if (!bcm_td_ing_vp_group_unmanaged_get(unit)) {
   4826                 if ((filter_flags & BCM_PORT_VLAN_MEMBER_INGRESS) &&
   4827                         !(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) {
   4828                     BCM_IF_ERROR_RETURN
   4829                         (bcm_td_ing_vp_group_move(unit, vp, vlan, FALSE));
   4830                     ing_vp_group_found = TRUE;
   4831                 }
   4832             } else {
   4833                 ing_vp_group_found = TRUE;
   4834             }
   4835         } 
   4836         if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) {
   4837             if (!bcm_td_egr_vp_group_unmanaged_get(unit)) {
   4838                 if ((filter_flags & BCM_PORT_VLAN_MEMBER_EGRESS) &&
   4839                         !(filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) {
   4840                     BCM_IF_ERROR_RETURN
   4841                         (bcm_td_eg_vp_group_move(unit, vp, vlan, FALSE));
   4842                     eg_vp_group_found = TRUE;
   4843                 }
   4844             } else {
   4845                 eg_vp_group_found = TRUE;
   4846             }
   4847         }
   4848     }
   4849 #endif /* BCM_TRIDENT_SUPPORT */
   4850 
   4851     if (bc_not_found && umc_not_found && uuc_not_found &&
   4852             !egr_vt_found && !ing_vp_vlan_membership_found &&
   4853             !egr_vp_vlan_membership_found && !ing_vp_group_found &&
   4854             !eg_vp_group_found) {
   4855         return BCM_E_NOT_FOUND;
   4856     }
   4857 
   4858     return BCM_E_NONE;
   4859 }
   4860 
   4861 /*
   4862  * Function:
   4863  *      _bcm_tr2_vlan_mc_group_gport_is_member
   4864  * Purpose:
   4865  *      Determine if the given VP is a member of the multicast group.
   4866  * Parameters:
   4867  *      unit  - (IN) SOC unit number. 
   4868  *      group - (IN) Multicast group
   4869  *      gport - (IN) VP Gport ID
   4870  *      phy_port_trunk - (IN) Gport ID for physical port or trunk on which
   4871  *                            the VP resides
   4872  *      is_member - (OUT) Indicates if given VP belongs to VLAN.
   4873  * Returns:
   4874  *      BCM_E_XXX
   4875  */
   4876 STATIC int
   4877 _bcm_tr2_vlan_mc_group_gport_is_member(int unit, bcm_multicast_t group,
   4878         bcm_gport_t gport, bcm_gport_t phy_port_trunk, int *is_member) 
   4879 {
   4880     int rv = BCM_E_NONE;
   4881     bcm_if_t encap_id;
   4882     bcm_trunk_t trunk_id;
   4883     int soc_max_num_ports = SOC_MAX_NUM_PORTS;
   4884     int trunk_local_ports = 0;
   4885     int if_max;
   4886     bcm_if_t *if_array;
   4887     int if_count, if_cur;
   4888     int i, mc_idx;
   4889 #if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
   4890     bcm_port_t trunk_member_port[SOC_MAX_NUM_PP_PORTS];
   4891 #else
   4892     bcm_port_t trunk_member_port[SOC_MAX_NUM_PORTS];
   4893 #endif
   4894 
   4895     if (NULL == is_member) {
   4896         return BCM_E_PARAM;
   4897     }
   4898     *is_member = FALSE;
   4899 
   4900     if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) {
   4901         soc_max_num_ports = SOC_MAX_NUM_PP_PORTS;
   4902     }
   4903 
   4904     /* Get VP's multicast encap id */
   4905     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   4906         BCM_IF_ERROR_RETURN(bcm_esw_multicast_vlan_encap_get(unit, group,
   4907                     phy_port_trunk, gport, &encap_id));
   4908     } else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   4909         BCM_IF_ERROR_RETURN(bcm_esw_multicast_niv_encap_get(unit, group,
   4910                     phy_port_trunk, gport, &encap_id));
   4911     } else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   4912         BCM_IF_ERROR_RETURN(bcm_esw_multicast_extender_encap_get(unit, group,
   4913                     phy_port_trunk, gport, &encap_id));
   4914     } else {
   4915         return BCM_E_PARAM;
   4916     }
   4917 
   4918     /* Get all the local ports of the trunk */
   4919     if (BCM_GPORT_IS_TRUNK(phy_port_trunk)) {
   4920         trunk_id = BCM_GPORT_TRUNK_GET(phy_port_trunk);
   4921         rv = _bcm_trunk_id_validate(unit, trunk_id);
   4922         if (BCM_FAILURE(rv)) {
   4923             return BCM_E_PORT;
   4924         }
   4925         rv = _bcm_esw_trunk_local_members_get(unit, trunk_id,
   4926                 soc_max_num_ports, trunk_member_port, &trunk_local_ports);
   4927         if (BCM_FAILURE(rv)) {
   4928             return BCM_E_PORT;
   4929         }
   4930     } 
   4931 
   4932     /* Find out if VP is a member of the multicast group */
   4933     if_max = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   4934     if_array = sal_alloc(if_max * sizeof(bcm_if_t),
   4935             "temp repl interface array");
   4936     if (if_array == NULL) {
   4937         return BCM_E_MEMORY;
   4938     }
   4939     mc_idx = _BCM_MULTICAST_ID_GET(group);
   4940     if (BCM_GPORT_IS_TRUNK(phy_port_trunk)) {
   4941         /* Iterate over all local ports in the trunk and search for
   4942          * a match on any local port
   4943          */
   4944         for (i = 0; i < trunk_local_ports; i++) {
   4945             rv = bcm_esw_ipmc_egress_intf_get(unit, mc_idx,
   4946                     trunk_member_port[i], if_max, if_array, &if_count);
   4947             if (BCM_FAILURE(rv)) {
   4948                 sal_free(if_array);
   4949                 return rv;
   4950             }
   4951             for (if_cur = 0; if_cur < if_count; if_cur++) {
   4952                 if (if_array[if_cur] == encap_id) {
   4953                     *is_member = TRUE;
   4954                     sal_free(if_array);
   4955                     return BCM_E_NONE;
   4956                 }
   4957             }
   4958         }
   4959     } else {
   4960         rv = bcm_esw_ipmc_egress_intf_get(unit, mc_idx,
   4961                 phy_port_trunk, if_max, if_array, &if_count);
   4962         if (BCM_FAILURE(rv)) {
   4963             sal_free(if_array);
   4964             return rv;
   4965         }
   4966         for (if_cur = 0; if_cur < if_count; if_cur++) {
   4967             if (if_array[if_cur] == encap_id) {
   4968                 *is_member = TRUE;
   4969                 sal_free(if_array);
   4970                 return BCM_E_NONE;
   4971             }
   4972         }
   4973     }
   4974 
   4975     sal_free(if_array);
   4976     return BCM_E_NONE;
   4977 }
   4978 
   4979 /*
   4980  * Function:
   4981  *      bcm_tr2_vlan_gport_get
   4982  * Purpose:
   4983  *      Get untagging status of a VLAN virtual port.
   4984  * Parameters:
   4985  *      unit  - (IN) SOC unit number. 
   4986  *      vlan  - (IN) VLAN to remove virtual port from.
   4987  *      gport - (IN) VLAN VP Gport ID
   4988  *      flags - (OUT) Untagging status of the VLAN virtual port.
   4989  * Returns:
   4990  *      BCM_E_XXX
   4991  */
   4992 int
   4993 bcm_tr2_vlan_gport_get(int unit, bcm_vlan_t vlan, bcm_gport_t gport,
   4994         int *flags) 
   4995 {
   4996     int rv = BCM_E_NONE;
   4997     int vp;
   4998     bcm_vlan_port_t vlan_vp;
   4999     bcm_gport_t phy_port_trunk = BCM_GPORT_INVALID;
   5000     int is_local;
   5001     vlan_tab_entry_t vtab;
   5002     int bc_idx, umc_idx, uuc_idx;
   5003     bcm_multicast_t group;
   5004     int is_bc_member = FALSE;
   5005     int is_umc_member = FALSE;
   5006     int is_uuc_member = FALSE;
   5007     int untagged_flag = 0;
   5008     int egr_vt_found = FALSE;
   5009     int ing_vp_vlan_membership_found = FALSE;
   5010     int egr_vp_vlan_membership_found = FALSE;
   5011     int ing_vp_group_found = FALSE;
   5012     int eg_vp_group_found = FALSE;
   5013     int is_glp_port = 0, is_vfi = 0, vlan_vfi = vlan;
   5014     _bcm_vp_vlan_mbrship_key_type_e key_type;
   5015 
   5016     COMPILER_REFERENCE(vlan_vfi);
   5017     COMPILER_REFERENCE(key_type);
   5018 
   5019 #ifdef BCM_TRIUMPH3_SUPPORT
   5020     if (_BCM_VPN_VFI_IS_SET(vlan)) {
   5021         is_vfi = 1;
   5022         key_type = _bcm_vp_vlan_mbrship_vp_vfi_type;
   5023         _BCM_VPN_GET(vlan_vfi, _BCM_VPN_TYPE_VFI, vlan);
   5024     } else
   5025 #endif /* BCM_TRIUMPH3_SUPPORT */
   5026     {
   5027         is_vfi = 0;
   5028         key_type = _bcm_vp_vlan_mbrship_vp_vlan_type;
   5029         vlan_vfi = vlan;
   5030     }
   5031 
   5032     *flags = 0;
   5033 
   5034     if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   5035         vp = BCM_GPORT_VLAN_PORT_ID_GET(gport);
   5036 
   5037         /* Get the physical port or trunk the VP resides on */
   5038         bcm_vlan_port_t_init(&vlan_vp);
   5039         vlan_vp.vlan_port_id = gport;
   5040         BCM_IF_ERROR_RETURN(bcm_tr2_vlan_vp_find(unit, &vlan_vp));
   5041 
   5042 #ifdef BCM_TRIUMPH3_SUPPORT
   5043         if (is_vfi) {
   5044             if (soc_feature(unit, soc_feature_vlan_vfi)) {
   5045                 source_vp_entry_t svp;
   5046 
   5047                 BCM_IF_ERROR_RETURN(
   5048                     READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp));
   5049                 if ((soc_mem_field32_get(unit, SOURCE_VPm, &svp, ENTRY_TYPEf) != 1) ||
   5050                     (soc_mem_field32_get(unit, SOURCE_VPm, &svp, VFIf) != vlan_vfi)) {
   5051                     return BCM_E_NOT_FOUND;
   5052                 }
   5053                 return BCM_E_NONE;
   5054             }
   5055         } else
   5056 #endif /* BCM_TRIUMPH3_SUPPORT */
   5057         {
   5058             phy_port_trunk = vlan_vp.port;
   5059         }
   5060     } else
   5061 #ifdef BCM_TRIDENT_SUPPORT
   5062     if (BCM_GPORT_IS_NIV_PORT(gport)) {
   5063         bcm_niv_port_t niv_port;
   5064         bcm_niv_egress_t niv_egress;
   5065         int              count;
   5066 
   5067         vp = BCM_GPORT_NIV_PORT_ID_GET(gport);
   5068 
   5069         /* Get the physical port or trunk the VP resides on */
   5070         bcm_niv_port_t_init(&niv_port);
   5071         niv_port.niv_port_id = gport;
   5072         BCM_IF_ERROR_RETURN(bcm_trident_niv_port_get(unit, &niv_port));
   5073         if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) {
   5074             phy_port_trunk = BCM_GPORT_INVALID;
   5075             bcm_niv_egress_t_init(&niv_egress);
   5076             rv = bcm_trident_niv_egress_get(unit, niv_port.niv_port_id,
   5077                                             1, &niv_egress, &count);
   5078             if (BCM_SUCCESS(rv)) {
   5079                 if (!(niv_egress.flags & BCM_NIV_EGRESS_MULTICAST)) {
   5080                     phy_port_trunk = niv_egress.port;
   5081                 } 
   5082             }
   5083         } else {
   5084             phy_port_trunk = niv_port.port;
   5085         }
   5086     } else
   5087 #endif /* BCM_TRIDENT_SUPPORT */
   5088 #ifdef BCM_TRIUMPH3_SUPPORT
   5089     if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   5090         bcm_extender_port_t extender_port;
   5091         bcm_extender_egress_t extender_egress;
   5092         int count;
   5093         vp = BCM_GPORT_EXTENDER_PORT_ID_GET(gport);
   5094 
   5095         /* Get the physical port or trunk the VP resides on */
   5096         bcm_extender_port_t_init(&extender_port);
   5097         extender_port.extender_port_id = gport;
   5098         BCM_IF_ERROR_RETURN(bcm_tr3_extender_port_get(unit, &extender_port));
   5099         if (extender_port.flags & BCM_EXTENDER_PORT_MATCH_NONE) {
   5100             bcm_extender_egress_t_init(&extender_egress);
   5101             rv = bcm_tr3_extender_egress_get_all(unit,
   5102                         extender_port.extender_port_id, 1, &extender_egress, &count);
   5103             if (count == 0) {
   5104                 /* No Extender egress object has been added to VP yet. */
   5105                 return BCM_E_CONFIG;
   5106             }
   5107             if (BCM_SUCCESS(rv)) {
   5108                 if (!extender_egress.flags & BCM_EXTENDER_EGRESS_MULTICAST) {
   5109                     phy_port_trunk = extender_egress.port;
   5110                 }
   5111             }
   5112         } else {
   5113             phy_port_trunk = extender_port.port;
   5114         }
   5115 
   5116     } else
   5117 #endif /* BCM_TRIDENT_SUPPORT */
   5118 #ifdef BCM_TRIDENT2_SUPPORT
   5119     if (BCM_GPORT_IS_TRUNK(gport)) {
   5120         BCM_IF_ERROR_RETURN(
   5121             _bcm_esw_trunk_tid_to_vp_lag_vp(unit, BCM_GPORT_TRUNK_GET(gport), &vp));
   5122     } else if (BCM_GPORT_IS_MPLS_PORT(gport)) {
   5123         vp = BCM_GPORT_MPLS_PORT_ID_GET(gport);
   5124     } else
   5125 #endif
   5126 
   5127 #ifdef BCM_TRIDENT2_SUPPORT
   5128     if (BCM_GPORT_IS_VXLAN_PORT(gport) &&
   5129         soc_feature(unit, soc_feature_vxlan)) {
   5130         vp = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
   5131     } else
   5132 #endif /* BCM_TRIDENT2_SUPPORT */
   5133 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   5134     if (BCM_GPORT_IS_L2GRE_PORT(gport)) {
   5135         vp = BCM_GPORT_L2GRE_PORT_ID_GET(gport);
   5136     } else if (BCM_GPORT_IS_MIM_PORT(gport)) {
   5137         vp = BCM_GPORT_MIM_PORT_ID_GET(gport);
   5138     } else if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 
   5139             BCM_GPORT_IS_SUBPORT_PORT(gport)) {
   5140         bcm_trunk_t   trunk_id;
   5141         if (BCM_SUCCESS(bcm_esw_trunk_find(unit, 0, gport, &trunk_id))) {
   5142             vp = trunk_id | BCM_TGID_TRUNK_INDICATOR(unit);
   5143         } else {
   5144             /* Put together a VP like value for subport, which will be
   5145                used below, this is a (mod,port) value for GPP */
   5146             if (SOC_IS_TRIDENT3X(unit) && _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) {
   5147                 vp = _BCM_SUBPORT_COE_PORT_GLP_GET(BCM_GPORT_SUBPORT_PORT_GET(gport));
   5148             } else {
   5149                 vp = (BCM_GPORT_SUBPORT_PORT_GET(gport) & 0x7FFF);
   5150             }
   5151         }
   5152 
   5153         /* Mark that this is a GLP port */
   5154         is_glp_port = 1;
   5155 
   5156         /* Set the key_type as glp_vlan type */
   5157         key_type = _bcm_vp_vlan_mbrship_glp_vlan_type;
   5158     } else
   5159 #endif
   5160 #ifdef BCM_TRIDENT3_SUPPORT
   5161     if (soc_feature(unit, soc_feature_flex_flow) &&
   5162             BCM_GPORT_IS_FLOW_PORT(gport)) {
   5163         vp = BCM_GPORT_FLOW_PORT_ID_GET(gport);
   5164     } else
   5165 #endif
   5166 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   5167 if (BCM_GPORT_IS_MODPORT(gport)) {
   5168         vp = (BCM_GPORT_MODPORT_MODID_GET(gport) << 8) | BCM_GPORT_MODPORT_PORT_GET(gport);
   5169         is_glp_port = 1;
   5170         key_type = _bcm_vp_vlan_mbrship_glp_vfi_type;
   5171     } else
   5172 #endif
   5173     {
   5174         return BCM_E_PARAM;
   5175     }
   5176 
   5177     if (phy_port_trunk != BCM_GPORT_INVALID) {
   5178         BCM_IF_ERROR_RETURN
   5179             (_bcm_tr2_phy_port_trunk_is_local(unit, phy_port_trunk, &is_local));
   5180         if (!is_local) {
   5181             return BCM_E_PORT;
   5182         }
   5183     }
   5184 
   5185     if(!is_vfi && !is_glp_port) {
   5186         sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t));
   5187         SOC_IF_ERROR_RETURN
   5188             (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab));
   5189         if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) {
   5190             return BCM_E_NOT_FOUND;
   5191         }
   5192 
   5193         if (!SHR_BITGET(vlan_info[unit].vp_mode, vlan)) {
   5194             if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
   5195                 if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) {
   5196                     /* No virtual port exists for this VLAN */
   5197                     return BCM_E_NOT_FOUND;
   5198                 }
   5199             }
   5200         }
   5201 
   5202         if (phy_port_trunk != BCM_GPORT_INVALID) {
   5203             bc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, BC_IDXf);
   5204             BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, bc_idx,
   5205                         &group));
   5206             BCM_IF_ERROR_RETURN(_bcm_tr2_vlan_mc_group_gport_is_member(unit, group,
   5207                         gport, phy_port_trunk, &is_bc_member));
   5208 
   5209             umc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UMC_IDXf);
   5210             if (umc_idx != bc_idx) {
   5211                 BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, umc_idx,
   5212                             &group));
   5213                 BCM_IF_ERROR_RETURN(_bcm_tr2_vlan_mc_group_gport_is_member(unit, group,
   5214                             gport, phy_port_trunk, &is_umc_member));
   5215             } else {
   5216                 is_umc_member = is_bc_member;
   5217             }
   5218 
   5219             uuc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UUC_IDXf);
   5220             if (uuc_idx != bc_idx && uuc_idx != umc_idx) {
   5221                 BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, uuc_idx,
   5222                             &group));
   5223                 BCM_IF_ERROR_RETURN(_bcm_tr2_vlan_mc_group_gport_is_member(unit, group,
   5224                             gport, phy_port_trunk, &is_uuc_member));
   5225             } else if (uuc_idx == bc_idx) {
   5226                 is_uuc_member = is_bc_member;
   5227             } else {
   5228                 is_uuc_member = is_umc_member;
   5229             }
   5230         }
   5231 
   5232         if (!is_bc_member) {
   5233             *flags |= BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD;
   5234         }
   5235         if (!is_umc_member) {
   5236             *flags |= BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD;
   5237         }
   5238         if (!is_uuc_member) {
   5239             *flags |= BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD;
   5240         }
   5241 
   5242         /* Get untagging status */
   5243         if (BCM_GPORT_IS_VLAN_PORT(gport)) {
   5244             BCM_IF_ERROR_RETURN
   5245                 (_bcm_tr2_vlan_vp_untagged_get(unit, vlan, vp, &untagged_flag));
   5246             egr_vt_found = TRUE;
   5247         }
   5248     #ifdef BCM_TRIDENT_SUPPORT
   5249         else if (BCM_GPORT_IS_NIV_PORT(gport)) {
   5250             rv = bcm_trident_niv_untagged_get(unit, vlan, vp, &untagged_flag);
   5251             if (BCM_SUCCESS(rv)) {
   5252                 egr_vt_found = TRUE;
   5253             } else if (rv == BCM_E_NOT_FOUND) {
   5254                 egr_vt_found = FALSE;
   5255                 rv = BCM_E_NONE;
   5256             } else {
   5257                 return rv;
   5258             }
   5259         }
   5260     #endif /* BCM_TRIDENT_SUPPORT */
   5261     #ifdef BCM_TRIUMPH3_SUPPORT
   5262         else if (BCM_GPORT_IS_EXTENDER_PORT(gport)) {
   5263             rv = bcm_tr3_extender_untagged_get(unit, vlan, vp, &untagged_flag);
   5264             if (BCM_SUCCESS(rv)) {
   5265                 egr_vt_found = TRUE;
   5266             } else if (rv == BCM_E_NOT_FOUND) {
   5267                 egr_vt_found = FALSE;
   5268                 rv = BCM_E_NONE;
   5269             } else {
   5270                 return rv;
   5271             }
   5272         }
   5273     #endif /* BCM_TRIUMPH3_SUPPORT */
   5274 
   5275         *flags |= untagged_flag;
   5276     } /* !is_vfi && !is_glp_port */
   5277 
   5278 #ifdef BCM_TRIDENT2_SUPPORT
   5279     if (soc_feature(unit, soc_feature_ing_vp_vlan_membership)) {
   5280         uint32 ing_flag;
   5281 
   5282         rv = bcm_td2_ing_vp_vlan_membership_get(unit, vp, vlan_vfi,
   5283                                                 &ing_flag, key_type);
   5284         if (BCM_SUCCESS(rv)) {
   5285             ing_vp_vlan_membership_found = TRUE;
   5286             *flags |= ing_flag;
   5287             *flags |= BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP;
   5288         } else if (rv == BCM_E_NOT_FOUND) {
   5289             ing_vp_vlan_membership_found = FALSE;
   5290             rv = BCM_E_NONE;
   5291         } else {
   5292             return rv;
   5293         }
   5294     }
   5295         
   5296     if (soc_feature(unit, soc_feature_egr_vp_vlan_membership)) {
   5297         uint32 egr_flag;
   5298 
   5299         rv = bcm_td2_egr_vp_vlan_membership_get(unit, vp, vlan_vfi,
   5300                                                 &egr_flag, key_type);
   5301         if (BCM_SUCCESS(rv)) {
   5302             egr_vp_vlan_membership_found = TRUE;
   5303             *flags |= egr_flag;
   5304             *flags |= BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP;
   5305         } else if (rv == BCM_E_NOT_FOUND) {
   5306             egr_vp_vlan_membership_found = FALSE;
   5307             rv = BCM_E_NONE;
   5308         } else {
   5309             return rv;
   5310         }
   5311     }
   5312 
   5313     if (ing_vp_vlan_membership_found && !egr_vp_vlan_membership_found) {
   5314         *flags |= BCM_VLAN_GPORT_ADD_INGRESS_ONLY;
   5315     } else if (!ing_vp_vlan_membership_found && egr_vp_vlan_membership_found) {
   5316         *flags |= BCM_VLAN_GPORT_ADD_EGRESS_ONLY;
   5317     }
   5318 #endif /* BCM_TRIDENT2_SUPPORT */
   5319 
   5320 #ifdef BCM_TRIDENT_SUPPORT
   5321     if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) {
   5322         uint32 ing_filter_flags;
   5323 
   5324         BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_get(unit, gport,
   5325                             &ing_filter_flags));
   5326         if ((ing_filter_flags & BCM_PORT_VLAN_MEMBER_INGRESS) &&
   5327             !(ing_filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) {
   5328             ing_vp_group_found = TRUE;
   5329         }
   5330     }
   5331     if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) {
   5332         uint32 eg_filter_flags;
   5333 
   5334         BCM_IF_ERROR_RETURN(bcm_esw_port_vlan_member_get(unit, gport,
   5335                             &eg_filter_flags));
   5336         if ((eg_filter_flags & BCM_PORT_VLAN_MEMBER_EGRESS) &&
   5337             !(eg_filter_flags & BCM_PORT_VLAN_MEMBER_VP_VLAN_MEMBERSHIP)) {
   5338             eg_vp_group_found = TRUE;
   5339         }
   5340     }
   5341 
   5342 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   5343     if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   5344         int ut_state = 0;
   5345         if (eg_vp_group_found) {
   5346             if (!is_vfi) {
   5347                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_ut_state_get(
   5348                                 unit, gport, vlan, &ut_state));
   5349             }
   5350 #if defined(BCM_TRIDENT3_SUPPORT)
   5351             else if(SOC_MEM_IS_VALID(unit, EGR_VLAN_VFI_UNTAGm)) {
   5352                 BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_ut_state_get(
   5353                                 unit, gport, vlan, &ut_state));
   5354             }
   5355 #endif
   5356             if (ut_state) {
   5357                 *flags |= BCM_VLAN_GPORT_ADD_UNTAGGED;
   5358             }
   5359         }
   5360     }
   5361 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   5362 #endif /* BCM_TRIDENT_SUPPORT */
   5363 
   5364     if (!is_bc_member && !is_umc_member && !is_uuc_member &&
   5365             !egr_vt_found && !ing_vp_vlan_membership_found &&
   5366             !egr_vp_vlan_membership_found && !ing_vp_group_found &&
   5367             !eg_vp_group_found) {
   5368         return BCM_E_NOT_FOUND;
   5369     }
   5370 
   5371     return rv;
   5372 }
   5373 
   5374 /*
   5375  * Function:
   5376  *      _bcm_tr2_mc_group_vp_get_all
   5377  * Purpose:
   5378  *      Get all the virtual ports of the given multicast group.
   5379  * Parameters:
   5380  *      unit   - (IN) SOC unit number. 
   5381  *      mc_group - (IN) Multicast group.
   5382  *      vp_bitmap - (OUT) Bitmap of virtual ports.
   5383  * Returns:
   5384  *      BCM_E_XXX
   5385  */
   5386 STATIC int
   5387 _bcm_tr2_mc_group_vp_get_all(int unit, bcm_multicast_t mc_group,
   5388         SHR_BITDCL *vp_bitmap)
   5389 {
   5390     int rv = BCM_E_NONE;
   5391     int num_encap_id;
   5392     bcm_if_t *encap_id_array = NULL;
   5393     int i;
   5394     int nh_index;
   5395     egr_l3_next_hop_entry_t egr_nh;
   5396     int vp;
   5397     soc_field_t type_field = ENTRY_TYPEf;
   5398 
   5399     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm, DATA_TYPEf)) {
   5400         type_field = DATA_TYPEf;
   5401     }
   5402 
   5403     if (NULL == vp_bitmap) {
   5404         return BCM_E_PARAM;
   5405     }
   5406 
   5407     /* Get the number of encap IDs of the multicast group */
   5408     BCM_IF_ERROR_RETURN
   5409         (bcm_esw_multicast_egress_get(unit, mc_group, 0,
   5410                                       NULL, NULL, &num_encap_id));
   5411     /* If no encap IDs in the multicast group, return directly */
   5412     if (num_encap_id == 0) {
   5413         return BCM_E_NONE;
   5414     }
   5415 
   5416     /* Get all the encap IDs of the multicast group */
   5417     encap_id_array = sal_alloc(sizeof(bcm_if_t) * num_encap_id,
   5418             "encap_id_array");
   5419     if (NULL == encap_id_array) {
   5420         return BCM_E_MEMORY;
   5421     }
   5422     sal_memset(encap_id_array, 0, sizeof(bcm_if_t) * num_encap_id);
   5423     rv = bcm_esw_multicast_egress_get(unit, mc_group, num_encap_id,
   5424                                       NULL, encap_id_array, &num_encap_id);
   5425     if (rv < 0) {
   5426         sal_free(encap_id_array);
   5427         return rv;
   5428     }
   5429 
   5430     /* Convert encap IDs to virtual ports */
   5431     for (i = 0; i < num_encap_id; i++) {
   5432         if (BCM_IF_INVALID != encap_id_array[i]) {
   5433             nh_index = encap_id_array[i] - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   5434             rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index, &egr_nh); 
   5435             if (BCM_FAILURE(rv)) {
   5436                 sal_free(encap_id_array);
   5437                 return rv;
   5438             }
   5439             if (2 != soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   5440                         type_field)) {
   5441                 sal_free(encap_id_array);
   5442                 return BCM_E_INTERNAL;
   5443             }
   5444             vp = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh, SD_TAG__DVPf);
   5445             SHR_BITSET(vp_bitmap, vp);
   5446         }
   5447     }
   5448 
   5449     sal_free(encap_id_array);
   5450     return rv;
   5451 }
   5452 
   5453 /*
   5454  * Function:
   5455  *      _bcm_tr2_vp_untagged_get_all
   5456  * Purpose:
   5457  *      Get all the given VLAN's virtual ports and untagged status from egress
   5458  *      VLAN translation table.
   5459  * Parameters:
   5460  *      unit - (IN) SOC unit number. 
   5461  *      vlan - (IN) VLAN.
   5462  *      vp_bitmap - (OUT) Bitmap of virtual ports.
   5463  *      arr_size  - (IN) Number of elements in flags_arr.
   5464  *      flags_arr - (OUT) Array of flags.
   5465  * Returns:
   5466  *      BCM_E_XXX
   5467  */
   5468 STATIC int
   5469 _bcm_tr2_vp_untagged_get_all(int unit, bcm_vlan_t vlan, SHR_BITDCL *vp_bitmap,
   5470         int arr_size, int *flags_arr)
   5471 {
   5472     int rv = BCM_E_NONE;
   5473     int chunk_size, num_chunks, chunk_index;
   5474     int alloc_size;
   5475     uint8 *egr_vt_buf = NULL;
   5476     soc_field_t entry_type_f;
   5477     int i, entry_index_min, entry_index_max;
   5478     uint32 *ent;
   5479     int vp, untagged_flag;
   5480     soc_mem_t mem = EGR_VLAN_XLATEm;
   5481 
   5482     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   5483         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   5484     }
   5485 
   5486     if (NULL == vp_bitmap) {
   5487         return BCM_E_PARAM;
   5488     }
   5489     if (arr_size != soc_mem_index_count(unit, SOURCE_VPm)) {
   5490         return BCM_E_PARAM;
   5491     }
   5492     if (NULL == flags_arr) {
   5493         return BCM_E_PARAM;
   5494     }
   5495 
   5496     chunk_size = 1024;
   5497     num_chunks = soc_mem_index_count(unit, mem) / chunk_size;
   5498     if (soc_mem_index_count(unit, mem) % chunk_size) {
   5499         num_chunks++;
   5500     }
   5501 
   5502     alloc_size = soc_mem_entry_words(unit, mem) * 4 * chunk_size;
   5503     egr_vt_buf = soc_cm_salloc(unit, alloc_size, "EGR_VLAN_XLATE buffer");
   5504     if (NULL == egr_vt_buf) {
   5505         rv = BCM_E_MEMORY;
   5506         goto cleanup;
   5507     }
   5508 
   5509     if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) {
   5510         entry_type_f = DATA_TYPEf;
   5511     } else if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   5512         entry_type_f = ENTRY_TYPEf;
   5513     } else {
   5514         entry_type_f = KEY_TYPEf;
   5515     }
   5516 
   5517     for (chunk_index = 0; chunk_index < num_chunks; chunk_index++) {
   5518 
   5519         /* Get a chunk of entries */
   5520         entry_index_min = chunk_index * chunk_size;
   5521         entry_index_max = entry_index_min + chunk_size - 1;
   5522         if (entry_index_max > soc_mem_index_max(unit, mem)) {
   5523             entry_index_max = soc_mem_index_max(unit, mem);
   5524         }
   5525         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   5526                 entry_index_min, entry_index_max, egr_vt_buf);
   5527         if (SOC_FAILURE(rv)) {
   5528             goto cleanup;
   5529         }
   5530 
   5531         /* Read each entry of the chunk to extract VP and untagged status */
   5532         for (i = 0; i < (entry_index_max - entry_index_min + 1); i++) {
   5533             int is_valid = 0;
   5534             ent = soc_mem_table_idx_to_pointer(unit,
   5535                     mem, uint32 *, egr_vt_buf, i);
   5536 
   5537             if (soc_feature(unit, soc_feature_base_valid)) {
   5538                 is_valid = soc_mem_field32_get(unit, mem, ent,
   5539                                                BASE_VALID_0f) == 3 &&
   5540                            soc_mem_field32_get(unit, mem, ent,
   5541                                                BASE_VALID_1f) == 7;
   5542             } else {
   5543                 is_valid = soc_mem_field32_get(unit, mem, ent, VALIDf);
   5544             }
   5545 
   5546             if (!is_valid) {
   5547                 continue;
   5548             }
   5549 
   5550             if (soc_mem_field32_get(unit, mem, ent, entry_type_f) != 1) {
   5551                 continue;
   5552             }
   5553             if (soc_mem_field32_get(unit, mem, ent, OVIDf) != vlan) {
   5554                 continue;
   5555             }
   5556 
   5557             vp = soc_mem_field32_get(unit, mem, ent, DVPf);
   5558 
   5559             /* Get untagged status */
   5560             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   5561                 rv = _bcm_tr2_vlan_vp_untagged_get(unit, vlan, vp,
   5562                         &untagged_flag);
   5563             }
   5564 #ifdef BCM_TRIDENT_SUPPORT
   5565             else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
   5566                 rv = bcm_trident_niv_untagged_get(unit, vlan, vp,
   5567                         &untagged_flag);
   5568             }
   5569 #endif /* BCM_TRIDENT_SUPPORT */
   5570 #ifdef BCM_TRIUMPH3_SUPPORT
   5571             else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   5572                 rv = bcm_tr3_extender_untagged_get(unit, vlan, vp,
   5573                         &untagged_flag);
   5574             }
   5575 #endif /* BCM_TRIUMPH3_SUPPORT */
   5576             else {
   5577                 continue;
   5578             }
   5579             if (BCM_FAILURE(rv)) {
   5580                 goto cleanup;
   5581             }
   5582 
   5583             SHR_BITSET(vp_bitmap, vp);
   5584             flags_arr[vp] = untagged_flag;
   5585         }
   5586     }
   5587 
   5588 cleanup:
   5589     if (egr_vt_buf) {
   5590         soc_cm_sfree(unit, egr_vt_buf);
   5591     }
   5592 
   5593     return rv;
   5594 }
   5595 
   5596 /*
   5597  * Function:
   5598  *      bcm_tr2_vlan_gport_get_all
   5599  * Purpose:
   5600  *      Get all virtual ports of the given VLAN.
   5601  * Parameters:
   5602  *      unit      - (IN) SOC unit number.
   5603  *      vlan      - (IN) VLAN ID.
   5604  *      array_max - (IN) Max number of elements in the array.
   5605  *      gport_array - (OUT) Array of virtual ports in GPORT format.
   5606  *      flags_array - (OUT) Array of untagging status.
   5607  *      array_size  - (OUT) Actual number of elements in the array.
   5608  * Returns:
   5609  *      BCM_E_XXX
   5610  * Notes: If array_max == 0 and gport_array == NULL, actual number of
   5611  *        virtual ports in the VLAN will be returned in array_size.
   5612  */
   5613 int
   5614 bcm_tr2_vlan_gport_get_all(int unit, bcm_vlan_t vlan, int array_max,
   5615         bcm_gport_t *gport_array, int *flags_array, int *array_size) 
   5616 {
   5617     int rv = BCM_E_NONE;
   5618     vlan_tab_entry_t vtab;
   5619     int num_vp;
   5620     SHR_BITDCL *bc_vp_bitmap = NULL;
   5621     SHR_BITDCL *umc_vp_bitmap = NULL;
   5622     SHR_BITDCL *uuc_vp_bitmap = NULL;
   5623     int bc_idx, umc_idx, uuc_idx;
   5624     bcm_multicast_t mc_group;
   5625     SHR_BITDCL *egr_vt_vp_bitmap = NULL;
   5626     int *egr_vt_flags_arr = NULL;
   5627     SHR_BITDCL *ing_vp_bitmap = NULL;
   5628     int *ing_flags_arr = NULL;
   5629     SHR_BITDCL *egr_vp_bitmap = NULL;
   5630     int *egr_flags_arr = NULL;
   5631     SHR_BITDCL *ing_group_vp_bitmap = NULL;
   5632     SHR_BITDCL *eg_group_vp_bitmap = NULL;
   5633     int i;
   5634 
   5635     if (array_max < 0) {
   5636         return BCM_E_PARAM;
   5637     }
   5638 
   5639     if ((array_max > 0) && (NULL == gport_array)) {
   5640         return BCM_E_PARAM;
   5641     }
   5642 
   5643     if (NULL == array_size) {
   5644         return BCM_E_PARAM;
   5645     }
   5646 
   5647     *array_size = 0;
   5648 
   5649 #ifdef BCM_TRIUMPH3_SUPPORT
   5650     if (soc_feature(unit, soc_feature_vlan_vfi)) {
   5651         rv = _bcm_tr3_vlan_vpn_is_valid(unit, vlan);
   5652         if (rv == BCM_E_NONE) {
   5653             return _bcm_tr3_vlan_port_get_all(unit, vlan, array_max,
   5654                                   gport_array, flags_array, array_size);
   5655         }
   5656     }
   5657 #endif /* BCM_TRIUMPH3_SUPPORT */
   5658 
   5659     BCM_IF_ERROR_RETURN
   5660         (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, (int)vlan, &vtab));
   5661 
   5662     if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
   5663        if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) {
   5664            /* This vlan has no virtual port members. */
   5665            return BCM_E_NONE;
   5666        } 
   5667     }
   5668 
   5669     /* Get VPs from BC group */
   5670     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   5671     bc_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "bc_vp_bitmap");
   5672     if (NULL == bc_vp_bitmap) {
   5673         rv = BCM_E_MEMORY;
   5674         goto cleanup;
   5675     }
   5676     sal_memset(bc_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5677     bc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, BC_IDXf);
   5678     rv = _bcm_tr_multicast_ipmc_group_type_get(unit, bc_idx, &mc_group);
   5679     if (BCM_FAILURE(rv)) {
   5680         goto cleanup;
   5681     }
   5682     rv = _bcm_tr2_mc_group_vp_get_all(unit, mc_group, bc_vp_bitmap);
   5683     if (BCM_FAILURE(rv)) {
   5684         goto cleanup;
   5685     }
   5686 
   5687     /* Get VPs from UMC group, if different from BC group */
   5688     umc_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "umc_vp_bitmap");
   5689     if (NULL == umc_vp_bitmap) {
   5690         rv = BCM_E_MEMORY;
   5691         goto cleanup;
   5692     }
   5693     sal_memset(umc_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5694     umc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UMC_IDXf);
   5695     rv = _bcm_tr_multicast_ipmc_group_type_get(unit, umc_idx, &mc_group);
   5696     if (BCM_FAILURE(rv)) {
   5697         goto cleanup;
   5698     }
   5699     if (umc_idx != bc_idx) {
   5700         rv = _bcm_tr2_mc_group_vp_get_all(unit, mc_group, umc_vp_bitmap);
   5701         if (BCM_FAILURE(rv)) {
   5702             goto cleanup;
   5703         }
   5704     } else {
   5705         sal_memcpy(umc_vp_bitmap, bc_vp_bitmap, SHR_BITALLOCSIZE(num_vp));
   5706     }
   5707 
   5708     /* Get VPs from UUC group, if different from BC and UMC group */
   5709     uuc_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "uuc_vp_bitmap");
   5710     if (NULL == uuc_vp_bitmap) {
   5711         rv = BCM_E_MEMORY;
   5712         goto cleanup;
   5713     }
   5714     sal_memset(uuc_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5715     uuc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UUC_IDXf);
   5716     rv = _bcm_tr_multicast_ipmc_group_type_get(unit, uuc_idx, &mc_group);
   5717     if (BCM_FAILURE(rv)) {
   5718         goto cleanup;
   5719     }
   5720     if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) {
   5721         rv = _bcm_tr2_mc_group_vp_get_all(unit, mc_group, uuc_vp_bitmap);
   5722         if (BCM_FAILURE(rv)) {
   5723             goto cleanup;
   5724         }
   5725     } else if (uuc_idx == bc_idx) {
   5726         sal_memcpy(uuc_vp_bitmap, bc_vp_bitmap, SHR_BITALLOCSIZE(num_vp));
   5727     } else {
   5728         sal_memcpy(uuc_vp_bitmap, umc_vp_bitmap, SHR_BITALLOCSIZE(num_vp));
   5729     }
   5730 
   5731     /* Get VPs and untagged status from egress VLAN translation table */
   5732     egr_vt_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "egr_vt_vp_bitmap");
   5733     if (NULL == egr_vt_vp_bitmap) {
   5734         rv = BCM_E_MEMORY;
   5735         goto cleanup;
   5736     }
   5737     sal_memset(egr_vt_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5738     
   5739     egr_vt_flags_arr = sal_alloc(num_vp * sizeof(int), "egr_vt_flags_arr");
   5740     if (NULL == egr_vt_flags_arr) {
   5741         rv = BCM_E_MEMORY;
   5742         goto cleanup;
   5743     }
   5744     sal_memset(egr_vt_flags_arr, 0, num_vp * sizeof(int));
   5745 
   5746     rv = _bcm_tr2_vp_untagged_get_all(unit, vlan, egr_vt_vp_bitmap,
   5747             num_vp, egr_vt_flags_arr); 
   5748     if (BCM_FAILURE(rv)) {
   5749         goto cleanup;
   5750     }
   5751 
   5752     /* Get VPs and flags from ingress VP VLAN membership table */
   5753     ing_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "ing_vp_bitmap");
   5754     if (NULL == ing_vp_bitmap) {
   5755         rv = BCM_E_MEMORY;
   5756         goto cleanup;
   5757     }
   5758     sal_memset(ing_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5759     
   5760     ing_flags_arr = sal_alloc(num_vp * sizeof(int), "ing_flags_arr");
   5761     if (NULL == ing_flags_arr) {
   5762         rv = BCM_E_MEMORY;
   5763         goto cleanup;
   5764     }
   5765     sal_memset(ing_flags_arr, 0, num_vp * sizeof(int));
   5766 
   5767 #ifdef BCM_TRIDENT2_SUPPORT
   5768     if (soc_feature(unit, soc_feature_ing_vp_vlan_membership)) {
   5769         rv = bcm_td2_ing_vp_vlan_membership_get_all(unit, vlan, ing_vp_bitmap,
   5770                 num_vp, ing_flags_arr);
   5771         if (BCM_FAILURE(rv)) {
   5772             goto cleanup;
   5773         }
   5774     }
   5775 #endif /* BCM_TRIDENT2_SUPPORT */
   5776         
   5777     /* Get VPs and flags from egress VP VLAN membership table */
   5778     egr_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp), "egr_vp_bitmap");
   5779     if (NULL == egr_vp_bitmap) {
   5780         rv = BCM_E_MEMORY;
   5781         goto cleanup;
   5782     }
   5783     sal_memset(egr_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5784     
   5785     egr_flags_arr = sal_alloc(num_vp * sizeof(int), "egr_flags_arr");
   5786     if (NULL == egr_flags_arr) {
   5787         rv = BCM_E_MEMORY;
   5788         goto cleanup;
   5789     }
   5790     sal_memset(egr_flags_arr, 0, num_vp * sizeof(int));
   5791 
   5792 #ifdef BCM_TRIDENT2_SUPPORT
   5793     if (soc_feature(unit, soc_feature_egr_vp_vlan_membership)) {
   5794         rv = bcm_td2_egr_vp_vlan_membership_get_all(unit, vlan, egr_vp_bitmap,
   5795                 num_vp, egr_flags_arr);
   5796         if (BCM_FAILURE(rv)) {
   5797             goto cleanup;
   5798         }
   5799     }
   5800 #endif /* BCM_TRIDENT2_SUPPORT */
   5801 
   5802     /* Get VPs from ingress VLAN VP groups */
   5803     ing_group_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp),
   5804             "ing_group_vp_bitmap");
   5805     if (NULL == ing_group_vp_bitmap) {
   5806         rv = BCM_E_MEMORY;
   5807         goto cleanup;
   5808     }
   5809     sal_memset(ing_group_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5810     
   5811 #ifdef BCM_TRIDENT_SUPPORT
   5812 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   5813     if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   5814         if (!bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
   5815             rv = bcm_td2p_ing_vp_group_vlan_get_all(unit, vlan,
   5816                     ing_group_vp_bitmap);
   5817             if (BCM_FAILURE(rv)) {
   5818                 goto cleanup;
   5819             }
   5820         }
   5821     } else
   5822 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   5823     if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) {
   5824         if (!bcm_td_ing_vp_group_unmanaged_get(unit)) {
   5825             rv = bcm_td_ing_vp_group_vlan_get_all(unit, vlan, ing_group_vp_bitmap);
   5826             if (BCM_FAILURE(rv)) {
   5827                 goto cleanup;
   5828             }
   5829         }
   5830     }
   5831 #endif /* BCM_TRIDENT_SUPPORT */
   5832 
   5833     /* Get VPs from egress VLAN VP groups */
   5834     eg_group_vp_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_vp),
   5835             "eg_group_vp_bitmap");
   5836     if (NULL == eg_group_vp_bitmap) {
   5837         rv = BCM_E_MEMORY;
   5838         goto cleanup;
   5839     }
   5840     sal_memset(eg_group_vp_bitmap, 0, SHR_BITALLOCSIZE(num_vp));
   5841     
   5842 #ifdef BCM_TRIDENT_SUPPORT
   5843 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   5844     if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   5845         if (!bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
   5846             rv = bcm_td2p_eg_vp_group_vlan_get_all(unit, vlan,
   5847                     eg_group_vp_bitmap);
   5848             if (BCM_FAILURE(rv)) {
   5849                 goto cleanup;
   5850             }
   5851         }
   5852     } else
   5853 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   5854     if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) {
   5855         if (!bcm_td_egr_vp_group_unmanaged_get(unit)) {
   5856             rv = bcm_td_eg_vp_group_vlan_get_all(unit, vlan, eg_group_vp_bitmap);
   5857             if (BCM_FAILURE(rv)) {
   5858                 goto cleanup;
   5859             }
   5860         }
   5861     }
   5862 #endif /* BCM_TRIDENT_SUPPORT */
   5863 
   5864     /* Combine the VP bitmaps and the flags arrays */
   5865     for (i = 0; i < num_vp; i++) {
   5866         if (!SHR_BITGET(bc_vp_bitmap, i) &&
   5867             !SHR_BITGET(umc_vp_bitmap, i) &&
   5868             !SHR_BITGET(uuc_vp_bitmap, i) &&
   5869             !SHR_BITGET(egr_vt_vp_bitmap, i) &&
   5870             !SHR_BITGET(ing_vp_bitmap, i) &&
   5871             !SHR_BITGET(egr_vp_bitmap, i) &&
   5872             !SHR_BITGET(ing_group_vp_bitmap, i) &&
   5873             !SHR_BITGET(eg_group_vp_bitmap, i)) {
   5874             /* VP is not a member of this VLAN */
   5875             continue;
   5876         }
   5877 
   5878         if (0 == array_max) {
   5879             (*array_size)++;
   5880         } else {
   5881             if (_bcm_vp_used_get(unit, i, _bcmVpTypeVlan)) {
   5882                 BCM_GPORT_VLAN_PORT_ID_SET(gport_array[*array_size], i);
   5883             } else if (_bcm_vp_used_get(unit, i, _bcmVpTypeNiv)) {
   5884                 BCM_GPORT_NIV_PORT_ID_SET(gport_array[*array_size], i);
   5885             } else if (_bcm_vp_used_get(unit, i, _bcmVpTypeExtender)) {
   5886                 BCM_GPORT_EXTENDER_PORT_ID_SET(gport_array[*array_size], i);
   5887             } else if (_bcm_vp_used_get(unit, i, _bcmVpTypeVpLag)) {
   5888                 bcm_trunk_t tid;
   5889                 rv = _bcm_esw_trunk_vp_lag_vp_to_tid(unit, i, &tid);
   5890                 if (BCM_FAILURE(rv)) {
   5891                     goto cleanup;
   5892                 }
   5893                 BCM_GPORT_TRUNK_SET(gport_array[*array_size], tid);
   5894             } else {
   5895                 /* Unexpected VP type */
   5896                 rv = BCM_E_INTERNAL;
   5897                 goto cleanup;
   5898             }
   5899 
   5900             if (NULL != flags_array) {
   5901                 flags_array[*array_size] = egr_vt_flags_arr[i] |
   5902                     ing_flags_arr[i] | egr_flags_arr[i];
   5903                 if (!SHR_BITGET(bc_vp_bitmap, i)) {
   5904                     flags_array[*array_size] |= BCM_VLAN_GPORT_ADD_BCAST_DO_NOT_ADD;
   5905                 }
   5906                 if (!SHR_BITGET(umc_vp_bitmap, i)) {
   5907                     flags_array[*array_size] |= BCM_VLAN_GPORT_ADD_UNKNOWN_MCAST_DO_NOT_ADD;
   5908                 }
   5909                 if (!SHR_BITGET(uuc_vp_bitmap, i)) {
   5910                     flags_array[*array_size] |= BCM_VLAN_GPORT_ADD_UNKNOWN_UCAST_DO_NOT_ADD;
   5911                 }
   5912                 if (SHR_BITGET(ing_vp_bitmap, i)) {
   5913                     flags_array[*array_size] |= BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP;
   5914                 }
   5915                 if (SHR_BITGET(egr_vp_bitmap, i)) {
   5916                     flags_array[*array_size] |= BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP;
   5917                 }
   5918             }
   5919 
   5920             (*array_size)++;
   5921             if (*array_size == array_max) {
   5922                 break;
   5923             }
   5924         }
   5925     }
   5926 
   5927 cleanup:
   5928     if (NULL != bc_vp_bitmap) {
   5929         sal_free(bc_vp_bitmap);
   5930     }
   5931     if (NULL != umc_vp_bitmap) {
   5932         sal_free(umc_vp_bitmap);
   5933     }
   5934     if (NULL != uuc_vp_bitmap) {
   5935         sal_free(uuc_vp_bitmap);
   5936     }
   5937     if (NULL != egr_vt_vp_bitmap) {
   5938         sal_free(egr_vt_vp_bitmap);
   5939     }
   5940     if (NULL != egr_vt_flags_arr) {
   5941         sal_free(egr_vt_flags_arr);
   5942     }
   5943     if (NULL != ing_vp_bitmap) {
   5944         sal_free(ing_vp_bitmap);
   5945     }
   5946     if (NULL != ing_flags_arr) {
   5947         sal_free(ing_flags_arr);
   5948     }
   5949     if (NULL != egr_vp_bitmap) {
   5950         sal_free(egr_vp_bitmap);
   5951     }
   5952     if (NULL != egr_flags_arr) {
   5953         sal_free(egr_flags_arr);
   5954     }
   5955     if (NULL != ing_group_vp_bitmap) {
   5956         sal_free(ing_group_vp_bitmap);
   5957     }
   5958     if (NULL != eg_group_vp_bitmap) {
   5959         sal_free(eg_group_vp_bitmap);
   5960     }
   5961 
   5962     return rv;
   5963 }
   5964 
   5965 /*
   5966  * Function:
   5967  *      _bcm_tr2_vp_untagged_delete_all
   5968  * Purpose:
   5969  *      Delete all the given VLAN's virtual ports from egress
   5970  *      VLAN translation table.
   5971  * Parameters:
   5972  *      unit - (IN) SOC unit number. 
   5973  *      vlan - (IN) VLAN.
   5974  * Returns:
   5975  *      BCM_E_XXX
   5976  */
   5977 STATIC int
   5978 _bcm_tr2_vp_untagged_delete_all(int unit, bcm_vlan_t vlan)
   5979 {
   5980     int rv = BCM_E_NONE;
   5981     int chunk_size, num_chunks, chunk_index;
   5982     int alloc_size;
   5983     uint8 *egr_vt_buf = NULL;
   5984     soc_field_t entry_type_f;
   5985     int i, entry_index_min, entry_index_max;
   5986     uint32 *ent;
   5987     int vp;
   5988     soc_mem_t mem = EGR_VLAN_XLATEm;
   5989 
   5990     if (soc_mem_is_valid(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   5991         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   5992     }
   5993 
   5994     chunk_size = 1024;
   5995     num_chunks = soc_mem_index_count(unit, mem) / chunk_size;
   5996     if (soc_mem_index_count(unit, mem) % chunk_size) {
   5997         num_chunks++;
   5998     }
   5999 
   6000     alloc_size = soc_mem_entry_words(unit, mem) * 4 * chunk_size;
   6001     egr_vt_buf = soc_cm_salloc(unit, alloc_size, "EGR_VLAN_XLATE buffer");
   6002     if (NULL == egr_vt_buf) {
   6003         rv = BCM_E_MEMORY;
   6004         goto cleanup;
   6005     }
   6006 
   6007     if (soc_mem_field_valid(unit, mem, DATA_TYPEf)) {
   6008         entry_type_f = DATA_TYPEf;
   6009     } else if (soc_mem_field_valid(unit, mem, ENTRY_TYPEf)) {
   6010         entry_type_f = ENTRY_TYPEf;
   6011     } else {
   6012         entry_type_f = KEY_TYPEf;
   6013     }
   6014 
   6015     for (chunk_index = 0; chunk_index < num_chunks; chunk_index++) {
   6016         /* Get a chunk of entries */
   6017         entry_index_min = chunk_index * chunk_size;
   6018         entry_index_max = entry_index_min + chunk_size - 1;
   6019         if (entry_index_max > soc_mem_index_max(unit, mem)) {
   6020             entry_index_max = soc_mem_index_max(unit, mem);
   6021         }
   6022         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   6023                 entry_index_min, entry_index_max, egr_vt_buf);
   6024         if (SOC_FAILURE(rv)) {
   6025             goto cleanup;
   6026         }
   6027 
   6028         /* Read each entry of the chunk */
   6029         for (i = 0; i < (entry_index_max - entry_index_min + 1); i++) {
   6030             int is_valid = 0;
   6031             ent = soc_mem_table_idx_to_pointer(unit,
   6032                     mem, uint32 *, egr_vt_buf, i);
   6033 
   6034             if (soc_feature(unit, soc_feature_base_valid)) {
   6035                 is_valid = soc_mem_field32_get(unit, mem, ent,
   6036                                                BASE_VALID_0f) == 3 &&
   6037                            soc_mem_field32_get(unit, mem, ent,
   6038                                                BASE_VALID_1f) == 7;
   6039             } else {
   6040                 is_valid = soc_mem_field32_get(unit, mem, ent, VALIDf);
   6041             }
   6042 
   6043             if (!is_valid) {
   6044                 continue;
   6045             }
   6046 
   6047             if (soc_mem_field32_get(unit, mem, ent, entry_type_f) != 1) {
   6048                 continue;
   6049             }
   6050             if (soc_mem_field32_get(unit, mem, ent, OVIDf) != vlan) {
   6051                 continue;
   6052             }
   6053 
   6054             vp = soc_mem_field32_get(unit, mem, ent, DVPf);
   6055 
   6056             if (_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   6057                 rv = _bcm_tr2_vlan_vp_untagged_delete(unit, vlan, vp);
   6058             }
   6059 #ifdef BCM_TRIDENT_SUPPORT
   6060             else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeNiv)) {
   6061                 rv = bcm_trident_niv_untagged_delete(unit, vlan, vp);
   6062             }
   6063 #endif /* BCM_TRIDENT_SUPPORT */
   6064 #ifdef BCM_TRIUMPH3_SUPPORT
   6065             else if (_bcm_vp_used_get(unit, vp, _bcmVpTypeExtender)) {
   6066                 rv = bcm_tr3_extender_untagged_delete(unit, vlan, vp);
   6067             }
   6068 #endif /* BCM_TRIUMPH3_SUPPORT */
   6069             else {
   6070                 continue;
   6071             }
   6072             if (BCM_FAILURE(rv)) {
   6073                 goto cleanup;
   6074             }
   6075         }
   6076     }
   6077 
   6078 cleanup:
   6079     if (egr_vt_buf) {
   6080         soc_cm_sfree(unit, egr_vt_buf);
   6081     }
   6082 
   6083     return rv;
   6084 }
   6085 /*
   6086  * Function:
   6087  *      bcm_tr2_vlan_gport_delete_all
   6088  * Purpose:
   6089  *      Remove all VLAN virtual ports from the specified vlan.
   6090  * Parameters:
   6091  *      unit  - (IN) SOC unit number. 
   6092  *      vlan  - (IN) VLAN to remove virtual ports from.
   6093  * Returns:
   6094  *      BCM_E_XXX
   6095  */
   6096 int
   6097 bcm_tr2_vlan_gport_delete_all(int unit, bcm_vlan_t vlan) 
   6098 {
   6099     vlan_tab_entry_t vtab;
   6100     int bc_idx, umc_idx, uuc_idx;
   6101     bcm_multicast_t mc_group;
   6102 
   6103 #ifdef BCM_TRIUMPH3_SUPPORT
   6104     if (soc_feature(unit, soc_feature_vlan_vfi)) {
   6105         int rv;
   6106         rv = _bcm_tr3_vlan_vpn_is_valid(unit, vlan);
   6107         if (rv == BCM_E_NONE) {
   6108             return _bcm_tr3_vlan_port_delete_all(unit, vlan);
   6109         }
   6110     }
   6111 #endif /* BCM_TRIUMPH3_SUPPORT */
   6112 
   6113     sal_memset(&vtab, 0, sizeof(vlan_tab_entry_t));
   6114 
   6115     BCM_IF_ERROR_RETURN
   6116         (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, vlan, &vtab)); 
   6117 
   6118     if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VALIDf)) {
   6119         return BCM_E_NOT_FOUND;
   6120     }
   6121 
   6122     if (SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
   6123        if (!soc_mem_field32_get(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf)) {
   6124            /* There are no virtual ports to remove. */
   6125            return BCM_E_NONE;
   6126        }
   6127     }
   6128 
   6129     /* Delete all VPs from the BC group */
   6130     bc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, BC_IDXf);
   6131     BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, bc_idx,
   6132                 &mc_group));
   6133     BCM_IF_ERROR_RETURN(bcm_esw_multicast_egress_delete_all(unit, mc_group)); 
   6134 
   6135     /* Delete all VPs from the UMC group, if UMC group is different
   6136      * from BC group.
   6137      */ 
   6138     umc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UMC_IDXf);
   6139     if (umc_idx != bc_idx) {
   6140         BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, umc_idx,
   6141                     &mc_group));
   6142         BCM_IF_ERROR_RETURN(bcm_esw_multicast_egress_delete_all(unit, mc_group)); 
   6143     }
   6144 
   6145     /* Delete all VPs from the UUC group, if UUC group is different
   6146      * from BC and UMC groups.
   6147      */
   6148     uuc_idx = _bcm_xgs3_vlan_mcast_idx_get(unit, &vtab, UUC_IDXf);
   6149     if ((uuc_idx != bc_idx) && (uuc_idx != umc_idx)) {
   6150         BCM_IF_ERROR_RETURN(_bcm_tr_multicast_ipmc_group_type_get(unit, uuc_idx,
   6151                     &mc_group));
   6152         BCM_IF_ERROR_RETURN(bcm_esw_multicast_egress_delete_all(unit, mc_group)); 
   6153     }
   6154 
   6155     /* Clear the VIRTUAL_PORT_EN field since there are no virtual ports in
   6156      * this VLAN anymore.
   6157      */
   6158     if (!SHR_BITGET(vlan_info[unit].vp_mode, vlan) && 
   6159         SOC_MEM_FIELD_VALID(unit, VLAN_TABm, VIRTUAL_PORT_ENf)) {
   6160         soc_mem_field32_set(unit, VLAN_TABm, &vtab, VIRTUAL_PORT_ENf, 0);
   6161     }
   6162     SOC_IF_ERROR_RETURN(soc_mem_write(unit, VLAN_TABm, MEM_BLOCK_ALL, vlan,
   6163                 &vtab));
   6164 
   6165     /* Delete given VLAN's (vlan, vp) entries from egress vlan translation table */
   6166     BCM_IF_ERROR_RETURN(_bcm_tr2_vp_untagged_delete_all(unit, vlan));
   6167 
   6168 #ifdef BCM_TRIDENT2_SUPPORT
   6169     /* Delete given VLAN's (vlan, vp) entries from membership tables */
   6170     if (soc_feature(unit, soc_feature_ing_vp_vlan_membership)) {
   6171         BCM_IF_ERROR_RETURN
   6172             (bcm_td2_ing_vp_vlan_membership_delete_all(unit, vlan));
   6173     }
   6174     if (soc_feature(unit, soc_feature_egr_vp_vlan_membership)) {
   6175         BCM_IF_ERROR_RETURN
   6176             (bcm_td2_egr_vp_vlan_membership_delete_all(unit, vlan));
   6177     }
   6178 #endif /* BCM_TRIDENT2_SUPPORT */
   6179 
   6180 #ifdef BCM_TRIDENT_SUPPORT
   6181     /* Delete VP groups from VLAN */
   6182 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   6183     if (soc_feature(unit, soc_feature_vlan_vfi_membership)) {
   6184         if (!bcm_td2p_ing_vp_group_unmanaged_get(unit)) {
   6185             BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_delete_all(unit, vlan, FALSE));
   6186         }
   6187         if (!bcm_td2p_egr_vp_group_unmanaged_get(unit)) {
   6188             BCM_IF_ERROR_RETURN(bcm_td2p_vp_group_delete_all(unit, vlan, TRUE));
   6189         }
   6190     } else
   6191 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   6192     {
   6193         if (soc_feature(unit, soc_feature_vp_group_ingress_vlan_membership)) {
   6194             if (!bcm_td_ing_vp_group_unmanaged_get(unit)) {
   6195                 BCM_IF_ERROR_RETURN(bcm_td_ing_vp_group_vlan_delete_all(unit, vlan));
   6196             }
   6197         } 
   6198         if (soc_feature(unit, soc_feature_vp_group_egress_vlan_membership)) {
   6199             if (!bcm_td_egr_vp_group_unmanaged_get(unit)) {
   6200                 BCM_IF_ERROR_RETURN(bcm_td_eg_vp_group_vlan_delete_all(unit, vlan));
   6201             }
   6202         }
   6203     }
   6204 #endif /* BCM_TRIDENT_SUPPORT */
   6205 
   6206     return BCM_E_NONE;
   6207 }
   6208 
   6209 #ifdef BCM_WARM_BOOT_SUPPORT
   6210 #ifdef BCM_TRIUMPH3_SUPPORT
   6211 /*
   6212  * Function:
   6213  *      _bcm_tr3_vlan_sd_tag_get
   6214  * Purpose:
   6215  *      Get SD TAG FLAG
   6216  * Parameters:
   6217  *      unit      - (IN) Device Number
   6218  *      nh_index  - (IN) Next hop index
   6219  *      flags     - (OUT) SD Tag flag
   6220  * Returns:
   6221  *      BCM_E_XXX
   6222  */
   6223 STATIC int
   6224 _bcm_tr3_vlan_sd_tag_get(int unit, uint32 nh_index, uint32 *flags)
   6225 {
   6226     egr_l3_next_hop_entry_t egr_nh;
   6227     int action_present = 0, action_not_present = 0;
   6228 
   6229     BCM_IF_ERROR_RETURN(READ_EGR_L3_NEXT_HOPm(unit,
   6230                              MEM_BLOCK_ANY, nh_index, &egr_nh));
   6231 
   6232     action_present = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   6233                            &egr_nh, SD_TAG__SD_TAG_ACTION_IF_PRESENTf);
   6234     action_not_present = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   6235                            &egr_nh, SD_TAG__SD_TAG_ACTION_IF_NOT_PRESENTf);
   6236 
   6237     if (action_not_present == 1) {
   6238         *flags |= BCM_VLAN_PORT_SERVICE_VLAN_ADD;
   6239     }
   6240 
   6241     switch (action_present) {
   6242         case 1:
   6243             *flags |= BCM_VLAN_PORT_SERVICE_VLAN_TPID_REPLACE;
   6244             break;
   6245         case 2:
   6246             *flags |= BCM_VLAN_PORT_SERVICE_VLAN_REPLACE;
   6247             break;
   6248         case 3:
   6249             *flags |= BCM_VLAN_PORT_SERVICE_VLAN_DELETE;
   6250             break;
   6251         case 4:
   6252             *flags |= BCM_VLAN_PORT_SERVICE_VLAN_PRI_TPID_REPLACE;
   6253             break;
   6254         case 5:
   6255             *flags |= BCM_VLAN_PORT_SERVICE_VLAN_PRI_REPLACE;
   6256             break;
   6257         case 6:
   6258             *flags |= BCM_VLAN_PORT_SERVICE_PRI_REPLACE;
   6259             break;
   6260         case 7:
   6261             *flags |= BCM_VLAN_PORT_SERVICE_TPID_REPLACE;
   6262             break;
   6263         default:
   6264             break;
   6265     }
   6266 
   6267     return BCM_E_NONE;
   6268 }
   6269 #endif /* BCM_TRIUMPH3_SUPPORT */
   6270 
   6271 #ifdef BCM_TRIDENT2_SUPPORT
   6272 int _bcm_td2_vlan_vp_scache_size_get(int unit, int *size)
   6273 {
   6274     int alloc_sz = 0;
   6275     int num_vp = 0;
   6276 
   6277     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   6278     /* Store VLAN_VP_INFO(unit, vp)->criteria */
   6279     alloc_sz += num_vp * sizeof(bcm_vlan_port_match_t);
   6280 
   6281     /* Store VLAN_VP_INFO(unit, vp)->match_vlan */
   6282     alloc_sz += num_vp * sizeof(bcm_vlan_t);
   6283 
   6284     /* Store VLAN_VP_INFO(unit, vp)->match_inner_vlan */
   6285     alloc_sz += num_vp * sizeof(bcm_vlan_t);
   6286 
   6287     /* Store VLAN_VP_INFO(unit, vp)->port */
   6288     alloc_sz += num_vp * sizeof(bcm_gport_t);
   6289 
   6290     /* Store VLAN_VP_INFO(unit, vp)->flags */
   6291     alloc_sz += num_vp * sizeof(uint32);
   6292 
   6293     if (size != NULL) {
   6294         *size = alloc_sz;
   6295     }
   6296 
   6297     return BCM_E_NONE;
   6298 }
   6299 
   6300 int _bcm_td2_vlan_vp_sync(int unit, uint8 **scache_ptr)
   6301 {
   6302     int num_vp = 0, vp;
   6303     _bcm_tr2_vlan_vp_info_t *vlan_vp;
   6304 
   6305     if ((*scache_ptr) == NULL) {
   6306         return BCM_E_PARAM;
   6307     }
   6308 
   6309     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   6310 
   6311     for (vp = 0; vp < num_vp; vp++) {
   6312         vlan_vp = VLAN_VP_INFO(unit, vp);
   6313         /* sync VLAN_VP_INFO(unit, vp)->criteria */
   6314         sal_memcpy((*scache_ptr),
   6315                    &(vlan_vp->criteria), sizeof(bcm_vlan_port_match_t));
   6316 
   6317         (*scache_ptr) += sizeof(bcm_vlan_port_match_t);
   6318 
   6319         /* sync VLAN_VP_INFO(unit, vp)->match_vlan */
   6320         sal_memcpy((*scache_ptr),
   6321                    &(vlan_vp->match_vlan), sizeof(bcm_vlan_t));
   6322 
   6323         (*scache_ptr) += sizeof(bcm_vlan_t);
   6324 
   6325         /* sync VLAN_VP_INFO(unit, vp)->match_inner_vlan */
   6326         sal_memcpy((*scache_ptr),
   6327                    &(vlan_vp->match_inner_vlan), sizeof(bcm_vlan_t));
   6328 
   6329         (*scache_ptr) += sizeof(bcm_vlan_t);
   6330 
   6331         /* sync VLAN_VP_INFO(unit, vp)->port */
   6332         sal_memcpy((*scache_ptr),
   6333                    &(vlan_vp->port), sizeof(bcm_gport_t));
   6334 
   6335         (*scache_ptr) += sizeof(bcm_gport_t);
   6336 
   6337         /* sync VLAN_VP_INFO(unit, vp)->flags */
   6338         sal_memcpy((*scache_ptr),
   6339                    &(vlan_vp->flags), sizeof(uint32));
   6340 
   6341         (*scache_ptr) += sizeof(uint32);
   6342     }
   6343 
   6344     return BCM_E_NONE;
   6345 }
   6346 
   6347 int _bcm_td2_vlan_vp_recover(int unit, uint8 **scache_ptr)
   6348 {
   6349     int num_vp = 0, vp;
   6350     _bcm_tr2_vlan_vp_info_t *vlan_vp;
   6351 
   6352     if ((*scache_ptr) == NULL) {
   6353         _bcm_tr2_vlan_virtual_free_resources(unit);
   6354         return BCM_E_PARAM;
   6355     }
   6356 
   6357     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   6358 
   6359     for (vp = 0; vp < num_vp; vp++) {
   6360         vlan_vp = VLAN_VP_INFO(unit, vp);
   6361         /* Recover VLAN_VP_INFO(unit, vp)->criteria */
   6362         sal_memcpy(&(vlan_vp->criteria),
   6363                    (*scache_ptr), sizeof(bcm_vlan_port_match_t));
   6364 
   6365         (*scache_ptr) += sizeof(bcm_vlan_port_match_t);
   6366 
   6367         /* Recover VLAN_VP_INFO(unit, vp)->match_vlan */
   6368         sal_memcpy(&(vlan_vp->match_vlan),
   6369                    (*scache_ptr), sizeof(bcm_vlan_t));
   6370 
   6371         (*scache_ptr) += sizeof(bcm_vlan_t);
   6372 
   6373         /* Recover VLAN_VP_INFO(unit, vp)->match_inner_vlan */
   6374         sal_memcpy(&(vlan_vp->match_inner_vlan),
   6375                    (*scache_ptr), sizeof(bcm_vlan_t));
   6376 
   6377         (*scache_ptr) += sizeof(bcm_vlan_t);
   6378 
   6379         /* Recover VLAN_VP_INFO(unit, vp)->port */
   6380         sal_memcpy(&(vlan_vp->port),
   6381                    (*scache_ptr), sizeof(bcm_gport_t));
   6382 
   6383         (*scache_ptr) += sizeof(bcm_gport_t);
   6384 
   6385         /* Recover VLAN_VP_INFO(unit, vp)->flags */
   6386         sal_memcpy(&(vlan_vp->flags),
   6387                    (*scache_ptr), sizeof(uint32));
   6388 
   6389         (*scache_ptr) += sizeof(uint32);
   6390     }
   6391 
   6392     return BCM_E_NONE;
   6393 }
   6394 #endif
   6395 
   6396 /*
   6397  * Function:
   6398  *      bcm_tr2_vlan_virtual_reinit
   6399  * Purpose:
   6400  *      Warm boot recovery for the VLAN virtual software module
   6401  * Parameters:
   6402  *      unit - Device Number
   6403  * Returns:
   6404  *      BCM_E_XXX
   6405  */
   6406 int 
   6407 bcm_tr2_vlan_virtual_reinit(int unit)
   6408 {
   6409     int rv = BCM_E_NONE;
   6410     int stable_size;
   6411     int chunk_size, num_chunks, chunk_index;
   6412     uint8 *vt_buf = NULL;
   6413     uint32 *vt_entry;
   6414     int i, entry_index_min, entry_index_max;
   6415     uint32 key_type, vp, nh_index = -1, trunk_bit;
   6416     source_vp_entry_t svp_entry;
   6417     ing_dvp_table_entry_t dvp_entry;
   6418     ing_l3_next_hop_entry_t ing_nh_entry;
   6419     wlan_svp_table_entry_t wlan_svp_entry;
   6420     bcm_trunk_t tgid;
   6421     bcm_module_t modid, mod_out;
   6422     bcm_port_t port_num, port_out;
   6423     uint32 profile_idx;
   6424     ing_vlan_tag_action_profile_entry_t ing_profile_entry;
   6425     soc_mem_t vt_mem;
   6426     int vt_entry_size;
   6427     soc_field_t valid_f;
   6428     soc_field_t key_type_f;
   6429     int key_type_ovid, key_type_ivid_ovid, key_type_otag, key_type_ivid;
   6430     soc_field_t mpls_action_f;
   6431     soc_field_t source_vp_f;
   6432     soc_field_t ovid_f;
   6433     soc_field_t ivid_f;
   6434     soc_field_t otag_f;
   6435     soc_field_t trunk_f;
   6436     soc_field_t tgid_f;
   6437     soc_field_t module_id_f;
   6438     soc_field_t port_num_f;
   6439     soc_field_t tag_action_profile_ptr_f;
   6440     _bcm_vp_info_t vp_info;
   6441 #ifdef BCM_TRIUMPH3_SUPPORT
   6442     int sd_tag = 0;
   6443     int network_port = 0;
   6444 #endif /* BCM_TRIUMPH3_SUPPORT */
   6445 
   6446     _bcm_vp_info_init(&vp_info);
   6447     vp_info.vp_type = _bcmVpTypeVlan;
   6448 
   6449     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   6450 
   6451 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   6452     if (soc_feature(unit, soc_feature_vfi_profile)) {
   6453         soc_mem_t mem;
   6454         int buf_size;
   6455         uint8 *buf = NULL;
   6456         vfi_entry_t *vfi_entry = NULL;
   6457 
   6458         mem = VFIm;
   6459         entry_index_min = soc_mem_index_min(unit, mem);
   6460         entry_index_max = soc_mem_index_max(unit, mem);
   6461         buf_size = SOC_MEM_TABLE_BYTES(unit, mem);
   6462 
   6463         buf = soc_cm_salloc(unit, buf_size, "VFI_Table buffer");
   6464         if (NULL == buf) {
   6465             rv = BCM_E_MEMORY;
   6466             goto cleanup;
   6467         }
   6468         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   6469                                 entry_index_min, entry_index_max, buf);
   6470         if (SOC_FAILURE(rv)) {
   6471             soc_cm_sfree(unit, buf);
   6472             goto cleanup;
   6473         }
   6474 
   6475         for (i = entry_index_min; i < entry_index_max; i++) {
   6476             vfi_entry = soc_mem_table_idx_to_pointer(unit, mem,
   6477                                                      vfi_entry_t *, buf, i);
   6478             profile_idx = soc_mem_field32_get(unit, mem,
   6479                                               vfi_entry, VFI_PROFILE_PTRf);
   6480 
   6481             rv = _bcm_vfi_profile_entry_reference(unit, profile_idx, 1);
   6482             if (BCM_FAILURE(rv)) {
   6483                 soc_cm_sfree(unit, buf);
   6484                 goto cleanup;
   6485             }
   6486         }
   6487         soc_cm_sfree(unit, buf);
   6488     }
   6489 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   6490 
   6491      /*
   6492         *As to the chips which support vp_lag feature, already recover VLAN_VP_INFO from
   6493         *scache in virtual_reinit, so don't need to recover it from VLAN_XLATE table.
   6494         */
   6495 #ifdef BCM_TRIDENT2_SUPPORT
   6496     if (soc_feature(unit, soc_feature_vp_lag)) {
   6497         if (stable_size !=0 && !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   6498             rv = BCM_E_NONE;
   6499             goto cleanup;
   6500         }
   6501     }
   6502 #endif
   6503 
   6504     /* Recover VLAN virtual ports from VLAN_XLATE table */
   6505 
   6506 #ifdef BCM_TRIUMPH3_SUPPORT
   6507     if (SOC_IS_TRIUMPH3(unit)) {
   6508         vt_mem = VLAN_XLATE_EXTDm;
   6509         vt_entry_size = sizeof(vlan_xlate_extd_entry_t);
   6510         valid_f = VALID_0f;
   6511         key_type_f = KEY_TYPE_0f;
   6512         key_type_ovid = TR3_VLXLT_X_HASH_KEY_TYPE_OVID;
   6513         key_type_ivid_ovid = TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID;
   6514         key_type_otag = TR3_VLXLT_X_HASH_KEY_TYPE_OTAG;
   6515         key_type_ivid = TR3_VLXLT_X_HASH_KEY_TYPE_IVID;
   6516         mpls_action_f = XLATE__MPLS_ACTIONf;
   6517         source_vp_f = XLATE__SOURCE_VPf;
   6518         ovid_f = XLATE__OVIDf;
   6519         ivid_f = XLATE__IVIDf;
   6520         otag_f = XLATE__OTAGf;
   6521         trunk_f = XLATE__Tf;
   6522         tgid_f = XLATE__TGIDf;
   6523         module_id_f = XLATE__MODULE_IDf;
   6524         port_num_f = XLATE__PORT_NUMf;
   6525         tag_action_profile_ptr_f = XLATE__TAG_ACTION_PROFILE_PTRf; 
   6526     } else
   6527 #endif /* BCM_TRIUMPH3_SUPPORT */
   6528     {
   6529         if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   6530             vt_mem = VLAN_XLATE_1_DOUBLEm;
   6531             vt_entry_size = sizeof(vlan_xlate_1_double_entry_t);
   6532         } else {
   6533             vt_mem = VLAN_XLATEm;
   6534             vt_entry_size = sizeof(vlan_xlate_entry_t);
   6535         }
   6536         valid_f = VALIDf;
   6537         key_type_f = KEY_TYPEf;
   6538         /* coverity[mixed_enums] */
   6539         key_type_ovid = TR_VLXLT_HASH_KEY_TYPE_OVID;
   6540         /* coverity[mixed_enums] */
   6541         key_type_ivid_ovid = TR_VLXLT_HASH_KEY_TYPE_IVID_OVID;
   6542         /* coverity[mixed_enums] */
   6543         key_type_otag = TR_VLXLT_HASH_KEY_TYPE_OTAG;
   6544         /* coverity[mixed_enums] */
   6545         key_type_ivid = TR_VLXLT_HASH_KEY_TYPE_IVID;
   6546         mpls_action_f = MPLS_ACTIONf;
   6547         source_vp_f = SOURCE_VPf;
   6548         ovid_f = OVIDf;
   6549         ivid_f = IVIDf;
   6550         otag_f = OTAGf;
   6551         trunk_f = Tf;
   6552         tgid_f = TGIDf;
   6553         module_id_f = MODULE_IDf;
   6554         port_num_f = PORT_NUMf;
   6555         tag_action_profile_ptr_f = TAG_ACTION_PROFILE_PTRf; 
   6556     }
   6557 
   6558     chunk_size = 1024;
   6559     num_chunks = soc_mem_index_count(unit, vt_mem) / chunk_size;
   6560     if (soc_mem_index_count(unit, vt_mem) % chunk_size) {
   6561         num_chunks++;
   6562     }
   6563 
   6564     vt_buf = soc_cm_salloc(unit, vt_entry_size * chunk_size,
   6565             "VLAN_XLATE buffer");
   6566     if (NULL == vt_buf) {
   6567         rv = BCM_E_MEMORY;
   6568         goto cleanup;
   6569     }
   6570 
   6571     for (chunk_index = 0; chunk_index < num_chunks; chunk_index++) {
   6572 
   6573         /* Get a chunk of entries */
   6574         entry_index_min = chunk_index * chunk_size;
   6575         entry_index_max = entry_index_min + chunk_size - 1;
   6576         if (entry_index_max > soc_mem_index_max(unit, vt_mem)) {
   6577             entry_index_max = soc_mem_index_max(unit, vt_mem);
   6578         }
   6579         rv = soc_mem_read_range(unit, vt_mem, MEM_BLOCK_ANY,
   6580                 entry_index_min, entry_index_max, vt_buf);
   6581         if (SOC_FAILURE(rv)) {
   6582             goto cleanup;
   6583         }
   6584 
   6585         /* Read each entry of the chunk */
   6586         for (i = 0; i < (entry_index_max - entry_index_min + 1); i++) {
   6587             vt_entry = soc_mem_table_idx_to_pointer(unit,
   6588                     vt_mem, uint32 *, vt_buf, i);
   6589 
   6590             if (soc_feature(unit, soc_feature_base_valid)) {
   6591                 if (soc_mem_field32_get(unit, vt_mem, vt_entry, BASE_VALID_0f) != 3 ||
   6592                     soc_mem_field32_get(unit, vt_mem, vt_entry, BASE_VALID_1f) != 7) {
   6593                     continue;
   6594                 }
   6595             } else {
   6596                 if (soc_mem_field32_get(unit, vt_mem, vt_entry, valid_f) == 0) {
   6597                     continue;
   6598                 }
   6599             }
   6600 
   6601             key_type = soc_mem_field32_get(unit, vt_mem, vt_entry, key_type_f);
   6602             if ((key_type != key_type_ovid) &&
   6603                 (key_type != key_type_ivid_ovid) &&
   6604                 (key_type != key_type_otag) &&
   6605                 (key_type != key_type_ivid)) {
   6606                 continue;
   6607             }
   6608 
   6609             if (soc_mem_field32_get(unit, vt_mem, vt_entry, mpls_action_f) != 1) {
   6610                 continue;
   6611             }
   6612 
   6613             vp = soc_mem_field32_get(unit, vt_mem, vt_entry, source_vp_f);
   6614             if ((stable_size == 0) || SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   6615                 /* Determine if VP is a VLAN VP by process of elimination.
   6616                  * Can rule out NIV and Extender VPs since they have different
   6617                  * VIF key types in VLAN_XLATEm.
   6618                  */
   6619 
   6620                 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, vp, &svp_entry);
   6621                 if (BCM_FAILURE(rv)) {
   6622                     goto cleanup;
   6623                 }
   6624 
   6625 #ifdef BCM_TRIUMPH3_SUPPORT
   6626                 if (soc_feature(unit, soc_feature_vlan_vfi) &&
   6627                     soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENTRY_TYPEf) == 1) {
   6628                     int vfi_index = soc_SOURCE_VPm_field32_get(unit, &svp_entry, VFIf);
   6629                     if (vfi_index != _BCM_VLAN_VFI_INVALID) {
   6630                         rv = _bcm_vfi_alloc_with_id(unit, VFIm, _bcmVfiTypeVlan, vfi_index);
   6631                         if (BCM_FAILURE(rv)) {
   6632                             goto cleanup;
   6633                         }
   6634                     }
   6635                     sd_tag = soc_SOURCE_VPm_field32_get(unit, &svp_entry, SD_TAG_MODEf);
   6636                     network_port = soc_SOURCE_VPm_field32_get(unit, &svp_entry, NETWORK_PORTf);
   6637                 } else
   6638 #endif /* BCM_TRIUMPH3_SUPPORT */
   6639                 /* Rule out MPLS and MiM VPs, for which ENTRY_TYPE = 1 */
   6640                 if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, ENTRY_TYPEf) != 3) {
   6641                     continue;
   6642                 }
   6643 
   6644                 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp_entry);
   6645                 if (BCM_FAILURE(rv)) {
   6646                     goto cleanup;
   6647                 }
   6648 
   6649                 if (!(soc_mem_field_valid(unit, ING_DVP_TABLEm, VP_TYPEf))) {
   6650                     continue;
   6651                 }
   6652 
   6653                 /* Rule out Trill VPs, for which VP_TYPE = 1 */
   6654                 if (soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry, VP_TYPEf) != 0) {
   6655                     continue;
   6656                 }
   6657 
   6658                 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp_entry,
   6659                         NEXT_HOP_INDEXf);
   6660                 rv = READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, nh_index,
   6661                         &ing_nh_entry);
   6662                 if (BCM_FAILURE(rv)) {
   6663                     goto cleanup;
   6664                 }
   6665                 /* Rule out Subport VPs, for which ENTRY_TYPE = 3 */
   6666                 if (soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh_entry,
   6667                             ENTRY_TYPEf) != 2) {
   6668                     continue;
   6669                 }
   6670 
   6671                 /* Rule out WLAN vp */
   6672                 if (SOC_MEM_IS_VALID(unit, WLAN_SVP_TABLEm)) {
   6673                     if (vp > soc_mem_index_max(unit, WLAN_SVP_TABLEm)) {
   6674                         continue;
   6675                     }
   6676                     rv = READ_WLAN_SVP_TABLEm(unit, MEM_BLOCK_ANY, vp,
   6677                             &wlan_svp_entry);
   6678                     if (BCM_FAILURE(rv)) {
   6679                         goto cleanup;
   6680                     }
   6681                     if (soc_WLAN_SVP_TABLEm_field32_get(unit, &wlan_svp_entry,
   6682                                 VALIDf) == 1) { 
   6683                         continue;
   6684                     }
   6685                 }
   6686 
   6687                 /* At this point, we are sure VP is a VLAN VP. */
   6688 
   6689                 rv = _bcm_vp_used_set(unit, vp, vp_info);
   6690                 if (BCM_FAILURE(rv)) {
   6691                     goto cleanup;
   6692                 }
   6693             } else {
   6694                 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeVlan)) {
   6695                     /* VP bitmap is recovered by virtual_init */
   6696                     continue;
   6697                 }
   6698             }
   6699 
   6700             /* Recover VLAN_VP_INFO(unit, vp)->criteria, match_vlan, and
   6701              * match_inner_vlan.
   6702              */
   6703             if (key_type == key_type_ovid) {
   6704                 VLAN_VP_INFO(unit, vp)->criteria =
   6705                     BCM_VLAN_PORT_MATCH_PORT_VLAN;
   6706                 VLAN_VP_INFO(unit, vp)->match_vlan = 
   6707                     soc_mem_field32_get(unit, vt_mem, vt_entry, ovid_f);
   6708             } else if (key_type == key_type_ivid_ovid) {
   6709                 VLAN_VP_INFO(unit, vp)->criteria =
   6710                     BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED;
   6711                 VLAN_VP_INFO(unit, vp)->match_vlan = 
   6712                     soc_mem_field32_get(unit, vt_mem, vt_entry, ovid_f);
   6713                 VLAN_VP_INFO(unit, vp)->match_inner_vlan = 
   6714                     soc_mem_field32_get(unit, vt_mem, vt_entry, ivid_f);
   6715             } else if (key_type == key_type_otag) {
   6716                 VLAN_VP_INFO(unit, vp)->criteria =
   6717                     BCM_VLAN_PORT_MATCH_PORT_VLAN16;
   6718                 VLAN_VP_INFO(unit, vp)->match_vlan = 
   6719                     soc_mem_field32_get(unit, vt_mem, vt_entry, otag_f);
   6720             } else if (key_type == key_type_ivid) {
   6721                 VLAN_VP_INFO(unit, vp)->criteria =
   6722                     BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN;
   6723                 VLAN_VP_INFO(unit, vp)->match_inner_vlan =
   6724                     soc_mem_field32_get(unit, vt_mem, vt_entry, ivid_f);
   6725             } else {
   6726                 continue;
   6727             }
   6728 
   6729             /* Recover VLAN_VP_INFO(unit, vp)->port */
   6730             trunk_bit = soc_mem_field32_get(unit, vt_mem, vt_entry, trunk_f);
   6731             if (trunk_bit) {
   6732                 tgid = soc_mem_field32_get(unit, vt_mem, vt_entry, tgid_f);
   6733                 BCM_GPORT_TRUNK_SET(VLAN_VP_INFO(unit, vp)->port, tgid);
   6734             } else {
   6735                 modid = soc_mem_field32_get(unit, vt_mem, vt_entry, module_id_f);
   6736                 port_num = soc_mem_field32_get(unit, vt_mem, vt_entry, port_num_f);
   6737                 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   6738                         modid, port_num, &mod_out, &port_out);
   6739                 if (BCM_FAILURE(rv)) {
   6740                     goto cleanup;
   6741                 }
   6742                 BCM_GPORT_MODPORT_SET(VLAN_VP_INFO(unit, vp)->port,
   6743                         mod_out, port_out);
   6744             }
   6745 
   6746             /* Recover VLAN_VP_INFO(unit, vp)->flags */
   6747             profile_idx = soc_mem_field32_get(unit, vt_mem, vt_entry,
   6748                     tag_action_profile_ptr_f);
   6749             rv = READ_ING_VLAN_TAG_ACTION_PROFILEm(unit, MEM_BLOCK_ANY,
   6750                     profile_idx, &ing_profile_entry);
   6751             if (BCM_FAILURE(rv)) {
   6752                 goto cleanup;
   6753             }
   6754             if ((soc_ING_VLAN_TAG_ACTION_PROFILEm_field32_get(unit,
   6755                      &ing_profile_entry, DT_OTAG_ACTIONf) ==
   6756                  bcmVlanActionReplace) &&
   6757                 (soc_ING_VLAN_TAG_ACTION_PROFILEm_field32_get(unit,
   6758                      &ing_profile_entry, DT_ITAG_ACTIONf) ==
   6759                  bcmVlanActionNone)) {
   6760                 VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_INNER_VLAN_PRESERVE;
   6761             }
   6762             if ((soc_ING_VLAN_TAG_ACTION_PROFILEm_field32_get(unit,
   6763                      &ing_profile_entry, SOT_OTAG_ACTIONf) ==
   6764                  bcmVlanActionReplace) &&
   6765                 (soc_ING_VLAN_TAG_ACTION_PROFILEm_field32_get(unit,
   6766                      &ing_profile_entry, SOT_ITAG_ACTIONf) ==
   6767                  bcmVlanActionAdd)) {
   6768                 VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_INNER_VLAN_ADD;
   6769             }
   6770 
   6771             if (VLAN_VP_INFO(unit, vp)->criteria ==
   6772                     BCM_VLAN_PORT_MATCH_PORT_VLAN16) {
   6773                 VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_EGRESS_VLAN16;
   6774             }
   6775 #if defined(BCM_SABER2_SUPPORT)
   6776             if (SOC_IS_SABER2(unit)) {
   6777                 if (soc_SOURCE_VPm_field32_get(unit, &svp_entry, TPID_SOURCEf) == 2) {
   6778                     VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_USE_SGLP_TPID;
   6779                 }
   6780             }
   6781 #endif
   6782 #ifdef BCM_TRIUMPH3_SUPPORT
   6783             if (soc_feature(unit, soc_feature_vlan_vfi) && (sd_tag == 1)) {
   6784                 VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_SERVICE_TAGGED;
   6785             }
   6786 
   6787             if (soc_feature(unit, soc_feature_vlan_vfi) && (network_port == 1)) {
   6788                 VLAN_VP_INFO(unit, vp)->flags |= BCM_VLAN_PORT_NETWORK;
   6789             }
   6790 
   6791             if (soc_feature(unit, soc_feature_vlan_vfi) && (nh_index != -1)) {
   6792                 uint32 flags = 0;
   6793                 rv = _bcm_tr3_vlan_sd_tag_get(unit, nh_index, &flags);
   6794                 if (BCM_FAILURE(rv)) {
   6795                     goto cleanup;
   6796                 }
   6797                 VLAN_VP_INFO(unit, vp)->flags |= flags;
   6798             }
   6799 #endif /* BCM_TRIUMPH3_SUPPORT */
   6800 
   6801             if (stable_size == 0) {
   6802                 /* In the Port module, a port's VP count is not recovered in 
   6803                  * level 1 Warm Boot.
   6804                  */
   6805                 rv = _bcm_tr2_vlan_vp_port_cnt_update(unit,
   6806                         VLAN_VP_INFO(unit, vp)->port, vp, TRUE);
   6807                 if (BCM_FAILURE(rv)) {
   6808                     goto cleanup;
   6809                 }
   6810             }
   6811         }
   6812     }
   6813 
   6814 cleanup:
   6815     if (vt_buf) {
   6816         soc_cm_sfree(unit, vt_buf);
   6817     }
   6818 
   6819     if (BCM_FAILURE(rv)) {
   6820         _bcm_tr2_vlan_virtual_free_resources(unit);
   6821     }
   6822 
   6823     return rv;
   6824 }
   6825 #endif /* BCM_WARM_BOOT_SUPPORT */
   6826 
   6827 #ifndef BCM_SW_STATE_DUMP_DISABLE
   6828 /*
   6829  * Function:
   6830  *     _bcm_tr2_vlan_vp_sw_dump
   6831  * Purpose:
   6832  *     Displays VLAN VP information maintained by software.
   6833  * Parameters:
   6834  *     unit - Device unit number
   6835  * Returns:
   6836  *     None
   6837  */
   6838 void
   6839 bcm_tr2_vlan_vp_sw_dump(int unit)
   6840 {
   6841     int i, num_vp;
   6842 
   6843     LOG_CLI((BSL_META_U(unit,
   6844                         "\nSW Information VLAN VP - Unit %d\n"), unit));
   6845 
   6846     num_vp = soc_mem_index_count(unit, SOURCE_VPm);
   6847 
   6848     for (i = 0; i < num_vp; i++) {
   6849         if (VLAN_VP_INFO(unit, i)->port == 0) {
   6850             continue;
   6851         }
   6852         LOG_CLI((BSL_META_U(unit,
   6853                             "\n  VLAN vp = %d\n"), i));
   6854         LOG_CLI((BSL_META_U(unit,
   6855                             "  Criteria = 0x%x,"), VLAN_VP_INFO(unit, i)->criteria));
   6856         switch (VLAN_VP_INFO(unit, i)->criteria) {
   6857             case BCM_VLAN_PORT_MATCH_PORT_VLAN:
   6858                 LOG_CLI((BSL_META_U(unit,
   6859                                     " port plus outer VLAN ID\n")));
   6860                 break;
   6861             case BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED:
   6862                 LOG_CLI((BSL_META_U(unit,
   6863                                     " port plus outer and inner VLAN IDs\n")));
   6864                 break;
   6865             case BCM_VLAN_PORT_MATCH_PORT_VLAN16:
   6866                 LOG_CLI((BSL_META_U(unit,
   6867                                     " port plus outer VLAN tag\n")));
   6868                 break;
   6869             case BCM_VLAN_PORT_MATCH_PORT_INNER_VLAN:
   6870                 LOG_CLI((BSL_META_U(unit,
   6871                                     " port plus Inner VLAN ID\n")));
   6872                 break;
   6873             default:
   6874                 LOG_CLI((BSL_META_U(unit,
   6875                                     " \n")));
   6876         }
   6877         LOG_CLI((BSL_META_U(unit,
   6878                             "  Flags = 0x%x\n"), VLAN_VP_INFO(unit, i)->flags));
   6879         LOG_CLI((BSL_META_U(unit,
   6880                             "  Match VLAN = 0x%x\n"), VLAN_VP_INFO(unit, i)->match_vlan));
   6881         LOG_CLI((BSL_META_U(unit,
   6882                             "  Match Inner VLAN = 0x%x\n"),
   6883                  VLAN_VP_INFO(unit, i)->match_inner_vlan));
   6884         LOG_CLI((BSL_META_U(unit,
   6885                             "  Port = 0x%x\n"), VLAN_VP_INFO(unit, i)->port));
   6886     }
   6887 
   6888     return;
   6889 }
   6890 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   6891 
   6892 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */