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

l3.c (198690B)


      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:    l3.c
      8  * Purpose: Trident3 L3 functions implementation
      9  */
     10 
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/defs.h>
     15 #if defined(INCLUDE_L3) && defined(BCM_TRIDENT3_SUPPORT)
     16 
     17 #include <soc/drv.h>
     18 #include <soc/scache.h>
     19 #include <bcm/vlan.h>
     20 #include <bcm/error.h>
     21 
     22 #include <bcm/l3.h>
     23 #include <soc/l3x.h>
     24 #include <soc/lpm.h>
     25 #ifdef ALPM_ENABLE
     26 #include <soc/alpm.h>
     27 #include <soc/esw/alpm_int.h>
     28 #endif
     29 #include <bcm/tunnel.h>
     30 #include <bcm/debug.h>
     31 #include <bcm/error.h>
     32 #include <bcm/stack.h>
     33 #include <soc/mem.h>
     34 #include <soc/format.h>
     35 #include <soc/trident2.h>
     36 #include <soc/tomahawk.h>
     37 #include <soc/apache.h>
     38 #include <soc/esw/flow_db.h>
     39 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
     40 #include <soc/esw/ecmp.h>
     41 #endif /*  SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
     42 #include <bcm_int/esw/flow.h>
     43 #include <bcm_int/esw/tomahawk.h>
     44 #include <bcm_int/esw/trident2.h>
     45 #include <bcm_int/esw/trident3.h>
     46 #include <bcm_int/esw/firebolt.h>
     47 #include <bcm_int/esw/triumph.h>
     48 #include <bcm_int/esw/triumph2.h>
     49 #include <bcm_int/esw/triumph3.h>
     50 #include <bcm_int/esw/stack.h>
     51 #include <bcm_int/esw/flex_ctr.h>
     52 #include <bcm_int/esw_dispatch.h>
     53 #include <bcm_int/esw/flex_ctr.h>
     54 #include <bcm_int/esw/virtual.h>
     55 #include <bcm_int/esw/trident2plus.h>
     56 #include <bcm_int/esw/xgs5.h>
     57 #include <bcm_int/esw/trx.h>
     58 #include <bcm_int/esw/qos.h>
     59 #include <bcm_int/common/multicast.h>
     60 #include <soc/trident3.h>
     61 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     62 #include <bcm_int/esw/trident2plus.h>
     63 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     64 #ifdef BCM_HELIX5_SUPPORT
     65 #include <soc/helix5.h>
     66 #endif
     67 
     68 #define _BCM_TD3_L3_MEM_BANKS_ALL     (-1)
     69 #define _BCM_TD3_HOST_ENTRY_NOT_FOUND (-1)
     70 
     71 /* needed for software state of the vc_and_swap label */
     72 extern _bcm_tr_mpls_bookkeeping_t  _bcm_tr_mpls_bk_info[BCM_MAX_NUM_UNITS];
     73 #define MPLS_INFO(_unit_)   (&_bcm_tr_mpls_bk_info[_unit_])
     74 #define VC_AND_SWAP_TABLE_RESV_INDEX 0
     75 
     76     
     77 static soc_profile_mem_t *_bcm_td3_macda_oui_profile[BCM_MAX_NUM_UNITS];
     78 static soc_profile_mem_t *_bcm_td3_vntag_etag_profile[BCM_MAX_NUM_UNITS];
     79 #define L3_EXT_VIEW_INVALID_VNTAG_ETAG_PROFILE 0
     80 
     81 #ifdef BCM_WARM_BOOT_SUPPORT
     82 /* bitmap of egress L3 intf, set indicates the intf is used by IPMC next hop */
     83 int *td3_l3_intf_next_hop_ipmc = NULL;
     84 #endif
     85 
     86 
     87 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
     88 #if 0
     89 int
     90 bcm_td3x_l3_ecmp_free_idx_get(int unit,
     91                               soc_esw_ecmp_bank_lkup_level_t level,
     92                               int count,
     93                               int *free_idx)
     94 {
     95     int bix = 0;
     96     int rv = BCM_E_NONE;
     97     uint32 bank_bmp = 0;
     98 
     99     rv = soc_esw_ecmp_protected_banks_get(unit,
    100                                           level,
    101                                           &bank_bmp);
    102 
    103     BCM_IF_ERROR_RETURN(rv);
    104 
    105     for (bix = 0; bix < BCMI_L3_ECMP_MAX_BANKS(unit); bix++) {
    106         if ((1 << bix) & bank_bmp) {
    107             rv = soc_esw_ecmp_protected_idx_free_get(unit,
    108                                                      bix,
    109                                                      count,
    110                                                      free_idx);
    111             if (rv == BCM_E_NONE) {
    112                 break;
    113             }
    114         }
    115     }
    116 
    117     return rv;
    118 }
    119 #endif
    120 
    121 
    122 
    123 STATIC int
    124 _bcmi_td3x_l3_ecmp_free_idx_attempt(int unit,
    125                                     uint32 bank_bmp[],
    126                                     int count,
    127                                     int *free_idx)
    128 {
    129     int bix;
    130     int rv = BCM_E_NONE;
    131 
    132     for (bix = 0; bix < BCMI_L3_ECMP_MAX_BANKS(unit); bix++) {
    133         if (SHR_BITGET(bank_bmp, bix)) {
    134             rv = soc_esw_ecmp_protected_idx_free_get(unit,
    135                                                      bix,
    136                                                      count,
    137                                                      free_idx);
    138             if (rv == BCM_E_NONE) {
    139                 break;
    140             }
    141         }
    142     }
    143 
    144     return rv;
    145 }
    146 
    147 int
    148 bcm_td3x_l3_ecmp_free_idx_get(int unit,
    149                               soc_esw_ecmp_bank_lkup_level_t level,
    150                               int count,
    151                               int *free_idx)
    152 {
    153     int rv;
    154     int bix;
    155     int free_count = 0;
    156     uint32 bank_bmp[1] = {0};
    157 
    158     /* Get banks mapped to the lkup level */
    159     rv = soc_esw_ecmp_protected_banks_get(unit,
    160                                           level,
    161                                           bank_bmp);
    162 
    163     BCM_IF_ERROR_RETURN(rv);
    164 
    165     /* Attempt to find a free idx that can fit the current group */
    166     rv = _bcmi_td3x_l3_ecmp_free_idx_attempt(unit, bank_bmp, count, free_idx);
    167 
    168     if (rv == BCM_E_FULL) {
    169 
    170         /* Compress ECMP member tables to make room for new group */
    171         for (bix = 0; bix < BCMI_L3_ECMP_MAX_BANKS(unit); bix++) {
    172             if (SHR_BITGET(bank_bmp, bix)) {
    173                 rv = soc_esw_ecmp_bank_free_count_get(unit,
    174                                                       bix,
    175                                                       &free_count);
    176                 BCM_IF_ERROR_RETURN(rv);
    177 
    178                 if (free_count < count) {
    179                     continue;
    180                 }
    181 
    182                 rv = soc_esw_ecmp_protected_bank_defragment(unit,
    183                                                             bix,
    184                                                             -1,
    185                                                             &free_count);
    186                 BCM_IF_ERROR_RETURN(rv);
    187 
    188                 /* If the defragmented bank can fit the new group, break */
    189                 if (free_count >= count) {
    190                     break;
    191                 }
    192             }
    193         }
    194 
    195         if (free_count < count) {
    196             return BCM_E_FULL;
    197         }
    198 
    199         bank_bmp[0] = 0;
    200         rv = soc_esw_ecmp_protected_banks_get(unit,
    201                                               level,
    202                                               bank_bmp);
    203         BCM_IF_ERROR_RETURN(rv);
    204 
    205         /* Check if the free idx can be found now */
    206         rv = _bcmi_td3x_l3_ecmp_free_idx_attempt(unit, bank_bmp, count, free_idx);
    207     }
    208 
    209     return rv;
    210 }
    211 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
    212 
    213 
    214 /*
    215  * Function:
    216  *      bcmi_td3_l3_nh_dest_set
    217  * Purpose:
    218  *      Encode the destination value based on the gport.
    219  * Parameters:
    220  *      unit - SOC device unit number
    221  * Returns:
    222  *      BCM_E_NONE              Success
    223  *      BCM_E_XXX               ERROR
    224  */
    225 
    226 int bcmi_td3_l3_nh_dest_set(int unit, bcm_l3_egress_t *nh_entry, uint32 *nh_dest)
    227 {
    228     int gport_type = 0, port = -1, gport = -1;
    229     uint32 dest_type = SOC_MEM_FIF_DEST_DVP;
    230     uint32 shift_val = 0;
    231     int mc_group = 0;
    232 
    233     if(nh_entry->flags2 & BCM_L3_FLAGS2_MC_GROUP){
    234         if (!_BCM_MULTICAST_IS_L3(nh_entry->mc_group)) {
    235             return BCM_E_PARAM;
    236         }
    237         dest_type = SOC_MEM_FIF_DEST_IPMC;
    238         mc_group = _BCM_MULTICAST_ID_GET(nh_entry->mc_group);
    239         *nh_dest = _soc_mem_dest_value_construct(unit, dest_type, mc_group);
    240         return BCM_E_NONE;
    241     }
    242 
    243     gport = nh_entry->port;
    244     gport_type = BCMI_GPORT_TYPE_GET(gport);
    245 
    246     switch(gport_type) {
    247     case BCM_GPORT_VXLAN_PORT:
    248         port = BCM_GPORT_VXLAN_PORT_ID_GET(gport);
    249         break;
    250     case BCM_GPORT_L2GRE_PORT:
    251         port = BCM_GPORT_L2GRE_PORT_ID_GET(gport);
    252         break;
    253     case BCM_GPORT_MPLS_PORT:
    254         port = BCM_GPORT_MPLS_PORT_ID_GET(gport);
    255         break;
    256     case BCM_GPORT_MIM_PORT:
    257         port = BCM_GPORT_MIM_PORT_ID_GET(gport);
    258         break;
    259     case BCM_GPORT_FLOW_PORT:
    260         port = BCM_GPORT_FLOW_PORT_ID_GET(gport);
    261         break;
    262     default:
    263         if (nh_entry->flags & BCM_L3_TGID) {
    264             int tid_is_vp_lag = 0;
    265             if (soc_feature(unit, soc_feature_vp_lag)) {
    266                 (void)_bcm_esw_trunk_id_is_vp_lag(unit, gport, &tid_is_vp_lag);
    267             }
    268 
    269             if (tid_is_vp_lag) {
    270                 /* Get the VP value representing VP LAG */
    271                 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_tid_to_vp_lag_vp(unit,
    272                     gport, &port));
    273 
    274             } else {
    275                 dest_type = SOC_MEM_FIF_DEST_LAG;
    276                 port = gport;
    277             }
    278         } else {
    279             dest_type = SOC_MEM_FIF_DEST_DGPP;
    280             shift_val = SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS;
    281             port = gport;
    282         }
    283     }
    284 
    285    *nh_dest = _soc_mem_dest_value_construct(unit, dest_type,
    286                    nh_entry->module << shift_val | port);
    287 
    288     return BCM_E_NONE;
    289 }
    290 
    291 /*
    292  * Function:
    293  *      _bcm_td3_mpls_get_vc_and_swap_flex_table_index
    294  * Purpose:
    295  *     Obtain Index into  VC_AND_SWAP_TABLE
    296  *     A software hash is not maintained, so duplicates may be created.
    297  * Parameters:
    298  *     IN  :  Unit
    299  *     IN  :  num_vc
    300  *     IN  :  mpls port entry
    301  *     IN  :  next hop entry
    302  *     IN  :  action
    303  *     OUT :  vc_swap_index
    304  * Returns:
    305  *      BCM_E_XXX
    306  */
    307 STATIC int
    308 _bcm_td3_mpls_get_vc_and_swap_flex_table_index (int unit, int *vc_swap_index)
    309 {
    310     int num_vc;
    311     int imin;
    312     int free_idx = 0, offset = 0;
    313 
    314     imin = soc_mem_index_min(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
    315     num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
    316 
    317     /* we are dividng the table in half to manage counted and
    318      * non-counted entries.
    319      */
    320     num_vc /= 2;
    321 
    322     /* Try getting index from 2nd half of MPLS_VC_AND_SWAP table */
    323     for (free_idx = imin; free_idx < num_vc + imin; free_idx++) {
    324         if (!(_BCM_MPLS_VC_NON_COUNT_USED_GET(unit, free_idx) ||
    325               (soc_feature(unit, soc_feature_vc_and_swap_table_overlaid) &&
    326               _bcm_vp_used_get(unit, free_idx, _bcmVpTypeFlow)))) {
    327             break;
    328         }
    329     }
    330 
    331     if (free_idx == (num_vc + imin)) {
    332 
    333         /* Get index from 1st half of MPLS_VC_AND_SWAP table */
    334         for (free_idx = imin; free_idx < num_vc + imin; free_idx++) {
    335             if (!_BCM_MPLS_VC_COUNT_USED_GET(unit, free_idx - imin)) {
    336                 break;
    337             }
    338         }
    339         if (free_idx == num_vc + imin) {
    340             return  BCM_E_RESOURCE;
    341         }
    342         _BCM_MPLS_VC_COUNT_USED_SET(unit, free_idx - imin);
    343         offset = imin;
    344     } else {
    345         _BCM_MPLS_VC_NON_COUNT_USED_SET(unit, free_idx - imin);
    346         offset = num_vc + imin;
    347     }
    348 
    349     *vc_swap_index = free_idx + offset;
    350 
    351     /* Increase refcount on table idx */
    352     _bcm_tr_mpls_vc_and_swap_ref_count_adjust(unit, *vc_swap_index , 1);
    353 
    354     return BCM_E_NONE;
    355 }
    356 
    357 #ifdef BCM_RIOT_SUPPORT
    358 
    359 /*
    360  * Function:
    361  *      _bcm_td3_vc_and_swap_table_dst_port_set
    362  * Purpose:
    363  *      Set dgpp in vc and swap table for IFA
    364  * Parameters:
    365  *      unit - (IN) SOC unit number.
    366  *      module - (IN) module id.
    367  *      port - (IN) port num.
    368  *      vc_swap_index  - (IN) vc and swap table index
    369  * Returns:
    370  *      BCM_X_XXX
    371  */
    372 int
    373 _bcm_td3_vc_and_swap_table_dst_port_set(int unit, bcm_module_t module,
    374         bcm_port_t port, int vc_swap_index)
    375 {
    376     int idx = 0;
    377     int rv = BCM_E_NONE;
    378     uint32 view_id = 0;
    379     uint32 flow_handle = 0;
    380     uint32 flow_option = 0;
    381     uint32 flex_data_array[128];
    382     uint32 flex_data_count;
    383     uint32 process_vntag_p = 0;
    384     uint32 process_vntag_dst_vif = 0;
    385     uint32 vntag_p = 0;
    386     uint32 vntag_dst_vif = 0;
    387     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
    388 
    389     SOC_IF_ERROR_RETURN(
    390         soc_flow_db_flow_handle_get(unit, "IFA", &flow_handle));
    391     SOC_IF_ERROR_RETURN(
    392         soc_flow_db_flow_option_id_get(
    393             unit, flow_handle, "V6_DGPP_ASSIGN", &flow_option));
    394 
    395     SOC_IF_ERROR_RETURN(soc_flow_db_ffo_to_mem_view_id_get(unit,
    396         flow_handle, flow_option, SOC_FLOW_DB_FUNC_EGRESS_LABEL_ID, &view_id));
    397 
    398     SOC_IF_ERROR_RETURN(soc_mem_read(unit, view_id,
    399         MEM_BLOCK_ANY, vc_swap_index, &vc_entry));
    400 
    401     SOC_IF_ERROR_RETURN(soc_flow_db_mem_view_entry_init(
    402         unit, view_id, (uint32*)&vc_entry));
    403 
    404     SOC_IF_ERROR_RETURN(soc_flow_db_mem_view_field_list_get(
    405         unit, view_id, SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
    406         128, flex_data_array, &flex_data_count));
    407 
    408     for (idx = 0; idx < flex_data_count; idx++) {
    409         switch (flex_data_array[idx]) {
    410             case VNTAG_Pf:
    411                 process_vntag_p = 1;
    412                 break;
    413 
    414             case VNTAG_DST_VIFf:
    415                 process_vntag_dst_vif = 1;
    416                 break;
    417 
    418             default:
    419                 break;
    420         }
    421     }
    422 
    423     if (process_vntag_p) {
    424         vntag_p = (module >> BCMI_TD3_L3_NH_IFA_DST_PORT_SHIFT) & 0x1;
    425         soc_mem_field32_set(unit, view_id, &vc_entry, VNTAG_Pf, vntag_p);
    426     }
    427 
    428     if (process_vntag_dst_vif) {
    429         vntag_dst_vif = (port & BCMI_TD3_L3_NH_IFA_DST_PORT_MASK) |
    430             ((module & BCMI_TD3_L3_NH_IFA_DST_PORT_MASK) <<
    431             BCMI_TD3_L3_NH_IFA_DST_PORT_SHIFT);
    432         soc_mem_field32_set(unit, view_id, &vc_entry, VNTAG_DST_VIFf, vntag_dst_vif);
    433     }
    434 
    435     SOC_IF_ERROR_RETURN(soc_mem_write(
    436         unit, view_id, MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
    437 
    438     return rv;
    439 }
    440 
    441 /*
    442  * Function:
    443  *      _bcm_td3_l3_flex_nh_add
    444  * Purpose:
    445  *      Set L3 multicast / unicast next hop flex entry.
    446  * Parameters:
    447  *      unit - (IN) SOC unit number.
    448  *      nh_index - (IN) Next hop index.
    449  *      l3_egress - (IN) L3 egress structure.
    450  *      ipmc  - (IN) multicast
    451  * Returns:
    452  *      BCM_X_XXX
    453  */
    454 int
    455 _bcm_td3_l3_flex_nh_add(int unit, int nh_index,
    456         bcm_l3_egress_t *l3_egress, uint32 *egr_nh,
    457         int ipmc)
    458 {
    459     int rv = BCM_E_NONE;
    460     int i;
    461     int macda_index = -1;
    462 #ifdef BCM_RIOT_SUPPORT
    463     uint32 vp;
    464 #endif
    465     uint32  view_id;
    466     uint32  flex_data_array[128];
    467     uint32  flex_data_count;
    468     uint32  opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
    469     uint32  opaque_count;
    470     bcm_flow_logical_field_t* user_fields;
    471 
    472     uint32 action_set = 0;
    473     uint32 action_set_field = 0;
    474     uint8 process_l2_edit_controls = 0;
    475     uint8 process_switching_controls = 0;
    476     uint8 process_profiled_assignment_dst_mac = 0;
    477     uint8 process_higig_controls = 0;
    478     uint8 process_higig_change_dest = 0;
    479     uint8 process_ttl_a = 0;
    480     uint8 process_intf = 0;
    481     uint8 process_outer_mac_addr = 0;
    482     uint8 process_inner_mac_addr = 0;
    483     uint8 process_vxlt = 0;
    484     uint8 process_class_id = 0;
    485     uint8 process_next_ptr = 0;
    486 
    487 /*
    488     int flag_set;
    489     uint32 flag_array[] = {
    490         BCM_L3_MULTICAST_L2_DEST_PRESERVE,
    491         BCM_L3_MULTICAST_L2_SRC_PRESERVE,
    492         BCM_L3_MULTICAST_L2_VLAN_PRESERVE,
    493         BCM_L3_MULTICAST_TTL_PRESERVE,
    494         BCM_L3_MULTICAST_DEST_PRESERVE,
    495         BCM_L3_MULTICAST_SRC_PRESERVE,
    496         BCM_L3_MULTICAST_VLAN_PRESERVE,
    497         BCM_L3_MULTICAST_L3_DROP,
    498         BCM_L3_MULTICAST_L2_DROP
    499     };
    500     soc_field_t field_array[] = {
    501         L3MC__L2_MC_DA_DISABLEf,
    502         L3MC__L2_MC_SA_DISABLEf,
    503         L3MC__L2_MC_VLAN_DISABLEf,
    504         L3MC__L3_MC_TTL_DISABLEf,
    505         L3MC__L3_MC_DA_DISABLEf,
    506         L3MC__L3_MC_SA_DISABLEf,
    507         L3MC__L3_MC_VLAN_DISABLEf,
    508         L3MC__L3_DROPf,
    509         L3MC__L2_DROPf
    510     };
    511 */
    512 
    513     /* Get view id corresponding to the specified flow. */
    514     rv = soc_flow_db_ffo_to_mem_view_id_get(unit,
    515                           l3_egress->flow_handle,
    516                           l3_egress->flow_option_handle,
    517                           SOC_FLOW_DB_FUNC_EGRESS_OBJ_ID,
    518                           &view_id);
    519     BCM_IF_ERROR_RETURN(rv);
    520 
    521     /* Configure the egress next hop entry */
    522     SOC_IF_ERROR_RETURN(soc_mem_read(unit, view_id,
    523                 MEM_BLOCK_ANY, nh_index, egr_nh));
    524 
    525     /* Initialize control field list for this view id. */
    526     rv = soc_flow_db_mem_view_entry_init(unit, view_id, egr_nh);
    527 
    528     BCM_IF_ERROR_RETURN(rv);
    529 
    530     /* Get logical field list for this view id. */
    531     rv = soc_flow_db_mem_view_field_list_get(unit,
    532                             view_id,
    533                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
    534                             _BCM_FLOW_LOGICAL_FIELD_MAX,
    535                             opaque_array,
    536                             &opaque_count);
    537     BCM_IF_ERROR_RETURN(rv);
    538 
    539     user_fields = l3_egress->logical_fields;
    540  
    541     for (i=0; i<opaque_count; i++) {
    542         if (user_fields[i].id == opaque_array[i]) {
    543             soc_mem_field32_set(unit, view_id, egr_nh, user_fields[i].id,
    544                                 user_fields[i].value);
    545         }
    546     }
    547 
    548     /* Get PDD field list corresponding to the view id. */
    549     rv = soc_flow_db_mem_view_field_list_get(unit,
    550                             view_id,
    551                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
    552                             128,
    553                             flex_data_array,
    554                             &flex_data_count);
    555     BCM_IF_ERROR_RETURN(rv);
    556 
    557     for (i=0; i<flex_data_count; i++) {
    558         switch (flex_data_array[i]) {
    559             case L2_EDIT_CONTROLS_ACTION_SETf:
    560                 process_l2_edit_controls = 1;
    561                 break;
    562             case HIGIG_CONTROLS_ACTION_SETf:
    563                 process_higig_controls = 1;
    564                 break;
    565             case HIGIG_CHANGE_DEST_ACTION_SETf:
    566                 process_higig_change_dest = 1;
    567                 break;
    568             case SWITCHING_CTRLS_ACTION_SETf:
    569                 process_switching_controls = 1;
    570                 break;
    571             case TTL_A_ACTION_SETf:
    572                 process_ttl_a = 1;
    573                 break;
    574             case CLASS_ID_ACTION_SETf:
    575                 process_class_id = 1;
    576                 break;
    577             case INTF_ACTION_SETf:
    578                 process_intf = 1;
    579                 break;
    580             case DIRECT_ASSIGNMENT_6_ACTION_SETf:
    581                 process_outer_mac_addr = 1;
    582                 break;
    583             case DIRECT_ASSIGNMENT_4_ACTION_SETf:
    584                 process_inner_mac_addr = 1;
    585                 break;
    586             case PROFILED_ASSIGNMENT_DST_MAC_ADDRESS_ACTION_SETf:
    587                 process_profiled_assignment_dst_mac = 1;
    588                 break;
    589             case VXLT_CLASS_IDf:
    590                 process_vxlt = 1;
    591                 break;
    592             case NEXT_PTR_ACTION_SETf:
    593                 process_next_ptr = 1;
    594                 break;
    595             default:
    596                 break;
    597         }
    598     }
    599 
    600     if (process_vxlt) {
    601           soc_mem_field32_set(unit, view_id, egr_nh,
    602                               VXLT_CLASS_IDf, l3_egress->intf_class);
    603     }
    604 
    605     if (process_higig_controls) {
    606           action_set = 0;
    607           soc_format_field32_set(unit, HIGIG_CONTROLS_ACTION_SETfmt,
    608                                &action_set, HG_HDR_SELf, 1);
    609 
    610           soc_mem_field32_set(unit, view_id, egr_nh,
    611                               HIGIG_CONTROLS_ACTION_SETf, action_set);
    612     }
    613 
    614     /* Set interface id. */
    615     if (process_intf) {
    616 
    617           action_set = 0;
    618           soc_format_field32_set(unit, INTF_ACTION_SETfmt,
    619                                &action_set, INTF_TYPEf, 0);
    620           /* INTF_NUMf */
    621           soc_format_field32_set(unit, INTF_ACTION_SETfmt,
    622                                &action_set, INTF_PTRf, l3_egress->intf);
    623           soc_mem_field32_set(unit, view_id, egr_nh,
    624                               INTF_ACTION_SETf, action_set);
    625     }
    626     if (process_outer_mac_addr) {
    627         /* L3UC__MAC_ADDRESSf  */
    628         soc_mem_mac_addr_set(unit, view_id, egr_nh,
    629                              DIRECT_ASSIGNMENT_6_ACTION_SETf,
    630                              l3_egress->mac_addr);
    631     } else if (process_inner_mac_addr) {
    632         soc_mem_mac_addr_set(unit, view_id, egr_nh,
    633                              DIRECT_ASSIGNMENT_4_ACTION_SETf,
    634                              l3_egress->mac_addr);
    635     }
    636 #if 0
    637     for (i = 0; i < COUNTOF(flag_array); i++) {
    638         if (l3_egress->multicast_flags & flag_array[i]) {
    639             flag_set = 1;
    640         } else {
    641             flag_set = 0;
    642         }
    643         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, field_array[i])) {
    644             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, egr_nh,
    645                     field_array[i], flag_set);
    646         } else {
    647             if (flag_set) {
    648                 return BCM_E_PARAM;
    649             }
    650         }
    651     }
    652 #endif
    653 
    654     if (process_l2_edit_controls) {
    655        action_set = 0;
    656        if (ipmc) {
    657           action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags,
    658                                               BCM_L3_MULTICAST_L2_VLAN_PRESERVE);
    659           soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
    660                                &action_set, VLAN_DISABLEf,      /* L3MC__L2_MC_VLAN_DISABLEf */
    661                                action_set_field);
    662           action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags,
    663                                               BCM_L3_MULTICAST_L2_DEST_PRESERVE);
    664           soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
    665                                &action_set, MACDA_DISABLEf,     /* L3MC__L2_MC_DA_DISABLEf */
    666                                action_set_field);
    667           action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags,
    668                                               BCM_L3_MULTICAST_L2_SRC_PRESERVE);
    669           soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
    670                                &action_set, MACSA_DISABLEf,     /* L3MC__L2_MC_SA_DISABLEf */
    671                                action_set_field);
    672        }
    673        else {
    674            action_set_field = _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_VLAN);
    675            soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
    676                                &action_set, VLAN_DISABLEf,      /* L3__L3_UC_VLAN_DISABLEf */
    677                                action_set_field);
    678            action_set_field = _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_DSTMAC);
    679            soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
    680                                &action_set, MACDA_DISABLEf,     /* L3__L3_UC_DA_DISABLEf */
    681                                action_set_field);
    682 
    683            action_set_field = _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_SRCMAC);
    684            soc_format_field32_set(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
    685                                &action_set, MACSA_DISABLEf,     /* L3__L3_UC_SA_DISABLEf */
    686                                action_set_field);
    687        }
    688 
    689        soc_mem_field32_set(unit, view_id, egr_nh,
    690                               L2_EDIT_CONTROLS_ACTION_SETf, action_set);
    691     }
    692     if (process_ttl_a) {
    693         if (ipmc) {
    694             soc_mem_field32_set(unit, view_id, egr_nh,
    695                               TTL_A_ACTION_SETf,   /* L3MC__L3_MC_TTL_DISABLEf */
    696                               _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_TTL_PRESERVE));
    697         }
    698         else {
    699             soc_mem_field32_set(unit, view_id, egr_nh,
    700                               TTL_A_ACTION_SETf,   /* L3__L3_UC_TTL_DISABLEf */
    701                               _SHR_IS_FLAG_SET(l3_egress->flags, BCM_L3_KEEP_TTL));
    702         }
    703     }
    704 
    705     if (process_class_id) {
    706             soc_mem_field32_set(unit, view_id, egr_nh,
    707                     CLASS_ID_ACTION_SETf,  /* L3__CLASS_IDf */
    708                     l3_egress->intf_class);
    709     }
    710 
    711     if (process_next_ptr && (l3_egress->flags2 & BCM_L3_FLAGS2_IFA_DST_PORT)) {
    712         int vc_swap_index = 0;
    713         if (l3_egress->port > (1 << BCMI_TD3_L3_NH_IFA_DST_PORT_SHIFT)) {
    714             return BCM_E_PARAM;
    715         }
    716         BCM_IF_ERROR_RETURN(
    717             _bcm_td3_mpls_get_vc_and_swap_flex_table_index(unit, &vc_swap_index));
    718          BCM_IF_ERROR_RETURN(
    719             _bcm_td3_vc_and_swap_table_dst_port_set(
    720                 unit, l3_egress->module, l3_egress->port, vc_swap_index));
    721 
    722         action_set = 0;
    723         soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    724             &action_set, NEXT_PTR_TYPEf,
    725             BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_DVP_AND_VC_SWAP);
    726         soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    727             &action_set, NEXT_PTRf, vc_swap_index);
    728         soc_mem_field32_set(unit, view_id, egr_nh,
    729              NEXT_PTR_ACTION_SETf, action_set);
    730     }
    731 
    732     if (soc_feature(unit, soc_feature_virtual_port_routing)) {
    733         if (l3_egress->encap_id > 0 &&
    734             l3_egress->encap_id < BCM_XGS3_EGRESS_IDX_MIN(unit)) {
    735             /* encap_id contains the virtual port value if it's greater than 0 and
    736              * less than the starting value of egress object ID.
    737             */
    738             if (process_next_ptr) {
    739                 action_set = 0;
    740                 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    741                                      &action_set, NEXT_PTR_TYPEf,
    742                                      BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP);
    743                 /* L3__DVPf */
    744                 soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    745                                      &action_set, NEXT_PTRf,
    746                                      l3_egress->encap_id);
    747                 soc_mem_field32_set(unit, view_id, egr_nh,
    748                                NEXT_PTR_ACTION_SETf, action_set);
    749             }
    750             /* no support for _bcmVpTypeNiv, _bcmVpTypeExtender in flexflow */
    751         } else if (l3_egress->encap_id >= BCM_XGS3_EGRESS_IDX_MIN(unit)) {
    752             return BCM_E_PARAM;
    753         }
    754     }
    755 
    756     /* for SD-Tag & L3MC views */
    757     if (process_switching_controls) {
    758         if (ipmc) {
    759         action_set = 0;
    760             action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L3_DROP);
    761             soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt,
    762                                &action_set, L3_DROPf,      /* L3MC__L3_DROPf */
    763                                action_set_field);
    764             action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L2_DROP);
    765             soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt,
    766                                &action_set, L2_DROPf,      /* L3MC__L2_DROPf */
    767                                action_set_field);
    768 
    769         }
    770         else {
    771             action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L3_DROP);
    772             soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt,
    773                            &action_set, BC_DROPf,      /* SD_TAG__BC_DROPf */
    774                            action_set_field);
    775 
    776             action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L2_DROP);
    777             soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt,
    778                                &action_set, UUC_DROPf,      /* SD_TAG__UUC_DROPf */
    779                                action_set_field);
    780 
    781             action_set_field = _SHR_IS_FLAG_SET(l3_egress->multicast_flags, BCM_L3_MULTICAST_L2_DROP);
    782             soc_format_field32_set(unit, SWITCHING_CTRLS_ACTION_SETfmt,
    783                                &action_set, UMC_DROPf,      /* SD_TAG__UMC_DROPf */
    784                                action_set_field);
    785 
    786         }
    787         soc_mem_field32_set(unit, view_id, egr_nh,
    788                               SWITCHING_CTRLS_ACTION_SETf, action_set);
    789     }
    790 
    791     /* Write IPUC entry in caller _bcm_fb_nh_add, otherwise continue for IPMC */
    792     if (ipmc == 0) {
    793         return (BCM_E_NONE);
    794     }
    795 
    796 #ifdef BCM_RIOT_SUPPORT
    797     /*
    798      * TD2Plus has multi layer routing.
    799      * The multicast packet can be routed in the overlay
    800      * layer and then underlay encapsulation is performed.
    801      * To achieve this, there will be overlay egr nexthop association
    802      * with undelray egress next hop.
    803      * the overlay egr nexthop will point to underlay next hop.
    804      */
    805     if (process_next_ptr &&
    806         BCMI_RIOT_IS_ENABLED(unit) &&
    807         _bcm_vp_vfi_type_vp_get(unit, l3_egress->port, (int *)&vp)) {
    808         /* This is a overlay NH case */
    809         ing_dvp_table_entry_t dvp;
    810         int vp_nh_index;
    811         /* Get the vp */
    812         SOC_IF_ERROR_RETURN
    813                 (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp));
    814 
    815         /* read vp to get next hop */
    816         vp_nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp,
    817                 NEXT_HOP_INDEXf);
    818 
    819         /* 
    820          * check if nh-nh association is needed.
    821          * else set up nh-dvp association
    822          * NH-NH association will be done for all the 
    823          * nhs other than SDTAG which does not modify any packets field.
    824          * e.g. on access ports, it may be needed to change a vlan/tpid, 
    825          * in that case, we may have to set nh-nh association else we may
    826          * setup vlan/tpid from DVP.
    827          */
    828         if (bcmi_l3_nh_assoc_ol_ul_link_is_required(unit, vp_nh_index)) {
    829             action_set = 0;
    830             action_set_field = BCMI_L3_NH_EGR_NEXT_PTR_TYPE_NH;
    831             soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    832                                  &action_set, NEXT_PTR_TYPEf,       /* L3MC__NEXT_PTR_TYPEf */
    833                                  action_set_field);
    834             action_set_field = (uint32)vp_nh_index;
    835             soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    836                                  &action_set, NEXT_PTRf,
    837                                  action_set_field);  /* L3MC__NEXT_PTRf */
    838             /* Set up the association of NHs in sw */
    839             BCM_IF_ERROR_RETURN(
    840                 bcmi_l3_nh_assoc_ol_ul_link_sw_add(unit, nh_index, 
    841                 vp_nh_index));
    842         } else {
    843             action_set = 0;
    844             action_set_field = BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP;
    845             soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    846                                  &action_set, NEXT_PTR_TYPEf,       /* L3MC__NEXT_PTR_TYPEf */
    847                                  action_set_field);
    848             soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
    849                                  &action_set, NEXT_PTRf,
    850                                  vp);  /* L3MC__NEXT_PTRf */
    851         }
    852         soc_mem_field32_set(unit, view_id, egr_nh,
    853                               NEXT_PTR_ACTION_SETf, action_set);
    854     }
    855 #endif
    856 
    857     /* 
    858      * TD2Plus has a overlaid  mac_address.
    859      * This mac_address field may be overlaid by some other fields
    860      * used for CoE/HG feature. Meanwhile a mac_da_profile_index
    861      * is present for the actual mac_address.
    862      * This index points to EGR_MAC_DA_PROFILE, which is managed in
    863      * Profile mechanism.
    864      */
    865 #ifdef BCM_HGPROXY_COE_SUPPORT
    866     if (process_higig_change_dest &&
    867         _bcm_xgs5_subport_coe_mod_port_local(unit, l3_egress->module,
    868                                              l3_egress->port)) {
    869 
    870         action_set = 0;
    871         action_set_field = l3_egress->module;
    872         soc_format_field32_set(unit, HIGIG_CHANGE_DEST_ACTION_SETfmt,
    873                              &action_set, HG_MC_DST_MODIDf,     /* L3MC__HG_MC_DST_MODIDf */
    874                              action_set_field);
    875         action_set_field = l3_egress->port;
    876         soc_format_field32_set(unit, HIGIG_CHANGE_DEST_ACTION_SETfmt,
    877                              &action_set, HG_MC_DST_PORT_NUMf,  /* L3MC__HG_MC_DST_PORT_NUMf */
    878                              action_set_field);
    879         soc_mem_field32_set(unit, view_id, egr_nh,
    880                             HIGIG_CHANGE_DEST_ACTION_SETf, action_set);
    881             
    882     }
    883 #endif
    884     if (process_profiled_assignment_dst_mac) {
    885         egr_mac_da_profile_entry_t macda;
    886         void *entries[1] = { NULL };
    887 
    888         sal_memset(&macda, 0, sizeof(egr_mac_da_profile_entry_t));
    889         soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm, 
    890                              &macda, MAC_ADDRESSf, l3_egress->mac_addr);
    891         entries[0] = &macda;
    892         rv = _bcm_mac_da_profile_entry_add(unit, entries, 1,
    893                                            (uint32 *)&macda_index);
    894         if (BCM_FAILURE(rv)) {
    895             goto cleanup;
    896         }
    897        /* L3MC__MAC_DA_PROFILE_INDEXf */
    898        soc_mem_field32_set(unit, view_id, egr_nh,
    899                             EGR_MAC_ADDRESS_PROFILEf, macda_index);
    900     }
    901     else {
    902         if (!BCM_MAC_IS_ZERO(l3_egress->mac_addr)) {
    903             if (!soc_feature(unit, soc_feature_ipmc_use_configured_dest_mac)) {
    904                 return BCM_E_CONFIG;
    905             }
    906         }
    907     }
    908 
    909     rv = soc_mem_write(unit, view_id,
    910                        MEM_BLOCK_ALL, nh_index, egr_nh);
    911     if (BCM_FAILURE(rv)) {
    912         goto cleanup;
    913     }
    914     return BCM_E_NONE;
    915 
    916 cleanup:
    917     if (macda_index != -1) {
    918         (void) _bcm_mac_da_profile_entry_delete(unit, macda_index);
    919     }
    920     return rv;
    921 }
    922 /*
    923  * Function:
    924  *      __bcm_td3_l3_flex_nh_entry_parse
    925  * Purpose:
    926  *      Parse the Flex NextHop table entry info.
    927  * Parameters:
    928  *      unit          - (IN) SOC unit number.
    929  *      egr_entry_ptr - (IN) Egress next hop table entry.
    930  *      index         - (IN) Next hop index.
    931  *      nh_entry      - (OUT) Next hop entry info.
    932  * Returns:
    933  *      BCM_E_XXX
    934  */
    935 int 
    936 _bcm_td3_l3_flex_nh_entry_parse(int unit, uint32 *egr_entry_ptr, 
    937         uint32 index, bcm_l3_egress_t *nh_entry)
    938 {
    939 
    940     int rv = BCM_E_NONE;
    941     uint32  view_id;
    942     uint32  flex_data_array[128];
    943     uint32  flex_data_count;
    944     int     ipmc=0;
    945     int     nh_index_out;
    946     int     i;
    947     _bcm_l3_intf_cfg_t intf_info;
    948     int ret_val;
    949     uint32 next_ptr_type;
    950     uint32 next_ptr;
    951 
    952     bcm_flow_logical_field_t* user_fields;
    953     uint32 opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
    954     uint32 opaque_count;
    955     uint32 action_set = 0;
    956     uint32 action_set_field = 0;
    957     soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL];
    958     uint32 num_ffo = 0;
    959 
    960     uint8 process_l2_edit_controls = 0;
    961     uint8 process_switching_controls = 0;
    962     uint8 process_profiled_assignment_dst_mac = 0;
    963     uint8 process_ttl_a = 0;
    964     uint8 process_next_ptr = 0;
    965     uint8 process_intf = 0;
    966     uint8 process_mac_addr = 0;
    967     uint8 process_class_id = 0;
    968     uint8 process_vxlt = 0;
    969     uint8 process_inner_mac_addr = 0;
    970     uint32 data_type;
    971     uint32 intf_type = 0;
    972 
    973     /* Input parameters check */
    974     if (NULL == nh_entry) {
    975         return (BCM_E_PARAM);
    976     }
    977 
    978     if (NULL == egr_entry_ptr) {
    979         return (BCM_E_PARAM);
    980     }
    981 
    982     /* Get view id corresponding to the specified flow. */
    983     if (nh_entry->flow_handle != 0) {
    984         BCM_IF_ERROR_RETURN(
    985             soc_flow_db_ffo_to_mem_view_id_get(unit,
    986                           nh_entry->flow_handle,
    987                           nh_entry->flow_option_handle,
    988                           SOC_FLOW_DB_FUNC_EGRESS_OBJ_ID,
    989                           &view_id));
    990     }
    991     else {
    992         data_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
    993                                         egr_entry_ptr, DATA_TYPEf);
    994 
    995         BCM_IF_ERROR_RETURN(
    996             soc_flow_db_mem_to_view_id_get(unit,
    997                              EGR_L3_NEXT_HOPm,
    998                              SOC_FLOW_DB_KEY_TYPE_INVALID,
    999                              data_type,
   1000                              0,
   1001                              NULL,
   1002                              &view_id));
   1003 
   1004         /* Get the flow handle, function id, option id */
   1005         BCM_IF_ERROR_RETURN(
   1006               soc_flow_db_mem_view_to_ffo_get(unit,
   1007                                          view_id,
   1008                                          SOC_FLOW_DB_MAX_VIEW_FFO_TPL,
   1009                                          ffo,
   1010                                          &num_ffo));
   1011         nh_entry->flow_handle = ffo[0].flow_handle;
   1012         nh_entry->flow_option_handle = ffo[0].option_id;
   1013     }
   1014 
   1015     /* Get logical field list for this view id. */
   1016     rv = soc_flow_db_mem_view_field_list_get(unit,
   1017                             view_id,
   1018                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   1019                             _BCM_FLOW_LOGICAL_FIELD_MAX,
   1020                             opaque_array,
   1021                             &opaque_count);
   1022     BCM_IF_ERROR_RETURN(rv);
   1023 
   1024     user_fields = nh_entry->logical_fields;
   1025 
   1026     for (i=0; i<opaque_count; i++) {
   1027         user_fields[i].id = opaque_array[i];
   1028         user_fields[i].value = soc_mem_field32_get(unit, view_id, egr_entry_ptr, opaque_array[i]);
   1029     }
   1030 
   1031     /* Get PDD field list corresponding to the view id. */
   1032     rv = soc_flow_db_mem_view_field_list_get(unit,
   1033                             view_id,
   1034                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
   1035                             128,
   1036                             flex_data_array,
   1037                             &flex_data_count);
   1038     BCM_IF_ERROR_RETURN(rv);
   1039 
   1040     for (i=0; i<flex_data_count; i++) {
   1041         switch (flex_data_array[i]) {
   1042             case L2_EDIT_CONTROLS_ACTION_SETf:
   1043                 process_l2_edit_controls = 1; 
   1044                 break;
   1045             case SWITCHING_CTRLS_ACTION_SETf:
   1046                 process_switching_controls = 1; 
   1047                 break;
   1048             case TTL_A_ACTION_SETf:
   1049                 process_ttl_a = 1; 
   1050                 break;
   1051             case HIGIG_CONTROLS_ACTION_SETf:
   1052                 break;
   1053             case CLASS_ID_ACTION_SETf:
   1054                 process_class_id = 1; 
   1055                 break;
   1056             case INTF_ACTION_SETf:
   1057                 process_intf = 1; 
   1058                 break;
   1059             case DIRECT_ASSIGNMENT_6_ACTION_SETf:
   1060                 process_mac_addr = 1; 
   1061                 break;
   1062             case PROFILED_ASSIGNMENT_DST_MAC_ADDRESS_ACTION_SETf:
   1063                 process_profiled_assignment_dst_mac = 1; 
   1064                 break;
   1065             case VXLT_CLASS_IDf:
   1066                 process_vxlt = 1;
   1067                 break;
   1068             case NEXT_PTR_ACTION_SETf:
   1069                 process_next_ptr = 1;
   1070                 break;
   1071             case DIRECT_ASSIGNMENT_4_ACTION_SETf:
   1072                 process_inner_mac_addr = 1;
   1073                 break;
   1074             default:
   1075                 /* Unrecongnized acion set or new ones */
   1076                 break;
   1077         }
   1078     }
   1079 
   1080     if (process_vxlt) {
   1081         nh_entry->intf_class = soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1082                                VXLT_CLASS_IDf);
   1083     }
   1084 
   1085    if (process_l2_edit_controls) {
   1086        action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1087                                L2_EDIT_CONTROLS_ACTION_SETf);
   1088 
   1089        if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
   1090                                 &action_set, L3_UC_VLAN_DISABLEf)) {
   1091            /* L3__L3_UC_VLAN_DISABLEf */
   1092            nh_entry->flags |= BCM_L3_KEEP_VLAN;
   1093        }
   1094 
   1095        if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
   1096                                 &action_set, L3_UC_DA_DISABLEf)) {
   1097            /* L3__L3_UC_DA_DISABLEf */
   1098            nh_entry->flags |= BCM_L3_KEEP_DSTMAC;
   1099        }
   1100 
   1101        if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
   1102                                 &action_set, L3_UC_SA_DISABLEf)) {
   1103            /* L3__L3_UC_SA_DISABLEf */
   1104            nh_entry->flags |= BCM_L3_KEEP_SRCMAC;
   1105        }
   1106        if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
   1107                                 &action_set, MACDA_DISABLEf)) {
   1108            /* L3MC__L2_MC_DA_DISABLEf */
   1109            nh_entry->flags |= BCM_L3_MULTICAST_L2_DEST_PRESERVE;
   1110        }
   1111        if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
   1112                                 &action_set, MACSA_DISABLEf)) {
   1113            /* L3MC__L2_MC_SA_DISABLEf */
   1114            nh_entry->flags |= BCM_L3_MULTICAST_L2_SRC_PRESERVE;
   1115        }
   1116        if (soc_format_field32_get(unit, L2_EDIT_CONTROLS_ACTION_SETfmt,
   1117                                 &action_set, VLAN_DISABLEf)) {
   1118            /* L3MC__L2_MC_VLAN_DISABLEf */
   1119            nh_entry->flags |= BCM_L3_MULTICAST_L2_VLAN_PRESERVE;
   1120        }
   1121    }
   1122 
   1123    if (process_intf) {
   1124        action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1125                                INTF_ACTION_SETf);
   1126 
   1127        action_set_field = soc_format_field32_get(unit, INTF_ACTION_SETfmt,
   1128                                &action_set, INTF_PTRf); /* INTF_NUMf */
   1129        nh_entry->intf = action_set_field;
   1130        intf_type = soc_format_field32_get(unit, INTF_ACTION_SETfmt,
   1131                                &action_set, INTF_TYPEf);
   1132 
   1133         /* determine if this is an IPMC entry from the l3 interface */
   1134 #ifdef BCM_WARM_BOOT_SUPPORT
   1135         if (SOC_WARM_BOOT(unit)) {
   1136             if((td3_l3_intf_next_hop_ipmc != NULL) &&
   1137                     SHR_BITSET(td3_l3_intf_next_hop_ipmc, nh_entry->intf )){
   1138                 ipmc = 1;
   1139             }
   1140         } else
   1141 #endif
   1142         {
   1143             _bcm_th_ipmc_l3_intf_next_hop_get(unit, nh_entry->intf,
   1144                                           &nh_index_out);
   1145             if (nh_index_out == -2) {
   1146                 ipmc = 1;
   1147             }
   1148         }
   1149 
   1150    }
   1151    if (nh_entry->intf == BCM_XGS3_L3_L2CPU_INTF_IDX(unit)) {
   1152         nh_entry->flags |= BCM_L3_L2TOCPU;
   1153    }
   1154    if (process_intf && intf_type == 0) {
   1155         /* Now get the vlan */
   1156         sal_memset(&intf_info, 0x0, sizeof(intf_info));
   1157         intf_info.l3i_index = nh_entry->intf;
   1158 
   1159         if (BCM_XGS3_L3_HWCALL_CHECK(unit, if_get)) {
   1160             BCM_XGS3_L3_MODULE_LOCK(unit);
   1161             ret_val = BCM_XGS3_L3_HWCALL_EXEC(unit, if_get) (unit,
   1162                                                              &intf_info);
   1163             BCM_XGS3_L3_MODULE_UNLOCK(unit);
   1164             BCM_IF_ERROR_RETURN(ret_val);
   1165             nh_entry->vlan = intf_info.l3i_vid;
   1166         }
   1167     }
   1168 
   1169     if (process_profiled_assignment_dst_mac) {
   1170        int macda_idx;
   1171        egr_mac_da_profile_entry_t macda;
   1172 
   1173        macda_idx = soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1174                             EGR_MAC_ADDRESS_PROFILEf);
   1175 
   1176        /* Read entry from MAC-DA-PROFILEm */
   1177        BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm,
   1178                             MEM_BLOCK_ANY, macda_idx, &macda));
   1179 
   1180        /* Obtain Mac-Address */
   1181        soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm,
   1182                             &macda, MAC_ADDRESSf, nh_entry->mac_addr);
   1183 
   1184     }
   1185     else if (process_mac_addr) {
   1186         /* L3MC__MAC_ADDRESSf  */
   1187         soc_mem_mac_addr_get(unit, view_id, egr_entry_ptr,
   1188                              DIRECT_ASSIGNMENT_6_ACTION_SETf,
   1189                              nh_entry->mac_addr);
   1190     }
   1191     else if (process_inner_mac_addr) {
   1192         soc_mem_mac_addr_set(unit, view_id, egr_entry_ptr,
   1193                              DIRECT_ASSIGNMENT_4_ACTION_SETf,
   1194                              nh_entry->mac_addr);
   1195     }
   1196     
   1197     if (process_ttl_a) {
   1198        if (soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1199                                TTL_A_ACTION_SETf)) {
   1200            if (ipmc) {
   1201                /* L3MC__L3_MC_TTL_DISABLEf */
   1202                nh_entry->flags |= BCM_L3_MULTICAST_TTL_PRESERVE;
   1203            }
   1204            else {
   1205                /* L3__L3_UC_TTL_DISABLEf */
   1206                nh_entry->flags |= BCM_L3_KEEP_TTL;
   1207            }
   1208        } 
   1209     }
   1210 
   1211     if (process_switching_controls) {
   1212        action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1213                               SWITCHING_CTRLS_ACTION_SETf);
   1214 
   1215        if (soc_format_field32_get(unit, SWITCHING_CTRLS_ACTION_SETfmt,
   1216                                 &action_set, L3_DROPf)) {
   1217            /* L3MC__L3_DROPf */
   1218            nh_entry->flags |= BCM_L3_MULTICAST_L3_DROP;
   1219        }
   1220        if (soc_format_field32_get(unit, SWITCHING_CTRLS_ACTION_SETfmt,
   1221                                 &action_set, L2_DROPf)) {
   1222            /* L3MC__L2_DROPf */
   1223            nh_entry->flags |= BCM_L3_MULTICAST_L2_DROP;
   1224        }
   1225     }
   1226 
   1227     if (process_next_ptr) {
   1228         action_set = soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1229                               NEXT_PTR_ACTION_SETf);
   1230 
   1231        /* L3MC__NEXT_PTR_TYPEf */
   1232          action_set_field =
   1233            soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   1234                                  &action_set, NEXT_PTR_TYPEf);
   1235 
   1236          next_ptr_type = action_set_field;
   1237          action_set_field =
   1238            soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   1239                                  &action_set, NEXT_PTRf);
   1240 
   1241          next_ptr = action_set_field;
   1242          if (next_ptr_type == BCMI_L3_NH_EGR_NEXT_PTR_TYPE_DVP) {
   1243              nh_entry->encap_id = next_ptr;
   1244          }
   1245          else if (next_ptr_type ==
   1246                   BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP) {
   1247               int vc_swap_idx = next_ptr;
   1248 
   1249               if (vc_swap_idx > 0) { /* 0th entry is the default */
   1250                  /* Read entry from EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm */
   1251 
   1252                  BCM_IF_ERROR_RETURN (
   1253                  _bcm_td3_mpls_gre_label_get (unit, vc_swap_idx, nh_entry));
   1254              }
   1255              else {
   1256                 nh_entry->mpls_label = BCM_MPLS_LABEL_INVALID;
   1257              }
   1258          }
   1259     }
   1260 
   1261     if (process_class_id) {  /* L3__CLASS_IDf */
   1262         nh_entry->intf_class =
   1263                  soc_mem_field32_get(unit, view_id, egr_entry_ptr,
   1264                     CLASS_ID_ACTION_SETf);
   1265     }
   1266 
   1267     if (ipmc) {
   1268         nh_entry->flags |= BCM_L3_IPMC; 
   1269     }
   1270 
   1271     return (BCM_E_NONE);
   1272 }
   1273 
   1274 /*
   1275  * Function:
   1276  *      bcmi_td3_get_port_from_destination
   1277  * Purpose:
   1278  *      Decodes the destination value based on programmed field.
   1279  * Parameters:
   1280  *      unit - SOC device unit number
   1281  * Returns:
   1282  *      BCM_E_NONE              Success
   1283  *      BCM_E_XXX               ERROR
   1284  */
   1285 int bcmi_td3_get_port_from_destination(int unit, uint32 dest,
   1286                                         bcm_l3_egress_t *nh)
   1287 {
   1288     int vp;
   1289     uint32 dt, dval;
   1290 
   1291     _soc_mem_dest_value_resolve(unit, dest, &dt, &dval);
   1292 
   1293     switch(dt) {
   1294     case SOC_MEM_FIF_DEST_LAG:
   1295         nh->port = dval;
   1296         nh->flags |= BCM_L3_TGID;
   1297         break;
   1298     case SOC_MEM_FIF_DEST_DGPP:
   1299         nh->port = dval;
   1300         break;
   1301     case SOC_MEM_FIF_DEST_DVP:
   1302         vp = dval;
   1303         _bcm_vp_encode_gport(unit, vp, &(nh->port));
   1304         break;
   1305     case SOC_MEM_FIF_DEST_IPMC:
   1306         _BCM_MULTICAST_GROUP_SET(nh->mc_group,
   1307                                  _BCM_MULTICAST_TYPE_L3, dval);
   1308         nh->flags2 |= BCM_L3_FLAGS2_MC_GROUP;
   1309         break;
   1310     default:
   1311         nh->port = dest;
   1312     }
   1313 
   1314     return BCM_E_NONE;
   1315 
   1316 }
   1317 
   1318 #endif /* BCM_RIOT_SUPPORT */
   1319 
   1320 /*
   1321  * Function:
   1322  *      _bcm_td3_l3_flex_intf_opri_ocfi_set
   1323  * Purpose:
   1324  *      Set L3 Interface OVLAN QoS parameters
   1325  * Parameters:
   1326  *      unit      - (IN)SOC unit number.
   1327  *      view_id   - (IN) memory view
   1328  *      l3_if_entry_p - (IN) Pointer to buffer
   1329  *      vid       - (IN) Intf_info
   1330  * Returns:
   1331  *      BCM_E_XXX.
   1332  */
   1333 STATIC int
   1334 _bcm_td3_l3_flex_intf_opri_ocfi_set(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info)
   1335 {
   1336     int hw_map_idx=0;
   1337 
   1338     uint32 action_set = 0;
   1339 
   1340     /* Input parameters check */
   1341     if (NULL == intf_info) {
   1342         return (BCM_E_PARAM);
   1343     }
   1344 
   1345     if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_COPY) {
   1346         /* OPRI_OCFI_SELf */
   1347         soc_format_field32_set(unit, OTAG_ACTION_SETfmt,
   1348                        &action_set, PCP_DE_SELf, 0x0);
   1349 
   1350     } else if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_SET) {
   1351         /* OPRI_OCFI_SELf */
   1352         soc_format_field32_set(unit, OTAG_ACTION_SETfmt,
   1353                        &action_set, PCP_DE_SELf, 0x1);
   1354         /* OPRIf */
   1355         soc_format_field32_set(unit, OTAG_ACTION_SETfmt,
   1356                        &action_set, PCPf, intf_info->vlan_qos.pri);
   1357         /* OCFIf */
   1358         soc_format_field32_set(unit, OTAG_ACTION_SETfmt,
   1359                        &action_set, DEf, intf_info->vlan_qos.cfi);
   1360 
   1361     } else if (intf_info->vlan_qos.flags & BCM_L3_INTF_QOS_OUTER_VLAN_PRI_REMARK) {
   1362         /* OPRI_OCFI_SELf */
   1363         soc_format_field32_set(unit, OTAG_ACTION_SETfmt,
   1364                        &action_set, PCP_DE_SELf, 0x2);
   1365 
   1366         BCM_IF_ERROR_RETURN
   1367          (_bcm_tr2_qos_id2idx(unit, intf_info->vlan_qos.qos_map_id,
   1368                              &hw_map_idx));
   1369         /* OPRI_OCFI_MAPPING_PROFILEf */
   1370         soc_format_field32_set(unit, OTAG_ACTION_SETfmt,
   1371                              &action_set, PCP_DE_MAPPING_PTRf,
   1372                              hw_map_idx);
   1373     }
   1374 
   1375     soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1376                              OTAG_ACTION_SETf, action_set);
   1377 
   1378     return BCM_E_NONE;
   1379 }
   1380 /*
   1381  * Function:
   1382  *      _bcm_td3_l3_flex_intf_ipri_icfi_set
   1383  * Purpose:
   1384  *      Set L3 Interface IVLAN QoS parameters
   1385  * Parameters:
   1386  *      unit      - (IN)SOC unit number.
   1387  *      view_id   - (IN) memory view
   1388  *      l3_if_entry_p - (IN) Pointer to buffer
   1389  *      vid       - (IN) Intf_info
   1390  * Returns:
   1391  *      BCM_E_XXX.
   1392  */
   1393 STATIC int
   1394 _bcm_td3_l3_flex_intf_ipri_icfi_set(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info)
   1395 {
   1396     int hw_map_idx=0;
   1397     uint32 action_set = 0;
   1398 
   1399     /* Input parameters check */
   1400     if (NULL == intf_info) {
   1401         return (BCM_E_PARAM);
   1402     }
   1403 
   1404     if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_COPY) {
   1405         /* IPRI_OCFI_SELf */
   1406         soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set,
   1407                              PCP_DE_SELf, 0x0);
   1408 
   1409    } else if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_SET) {
   1410         /* IPRI_OCFI_SELf */
   1411         soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set,
   1412                              PCP_DE_SELf, 0x1);
   1413         /* IPRIf */
   1414         soc_format_field32_set(unit, ITAG_ACTION_SETfmt,
   1415                        &action_set, PCPf, intf_info->vlan_qos.pri);
   1416         /* ICFIf */
   1417         soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set,
   1418                              DEf, intf_info->vlan_qos.cfi);
   1419 
   1420    } else if (intf_info->inner_vlan_qos.flags & BCM_L3_INTF_QOS_INNER_VLAN_PRI_REMARK) {
   1421         /* IPRI_OCFI_SELf */
   1422         soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set,
   1423                              PCP_DE_SELf, 0x2);
   1424 
   1425         BCM_IF_ERROR_RETURN
   1426          (_bcm_tr2_qos_id2idx(unit, intf_info->vlan_qos.qos_map_id,
   1427                              &hw_map_idx));
   1428         /* IPRI_ICFI_MAPPING_PROFILEf */
   1429         soc_format_field32_set(unit, ITAG_ACTION_SETfmt, &action_set,
   1430                              PCP_DE_MAPPING_PTRf, hw_map_idx);
   1431 
   1432    }
   1433 
   1434    soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1435                              ITAG_ACTION_SETf, action_set);
   1436 
   1437     return BCM_E_NONE;
   1438 }
   1439 /*
   1440  * Function:
   1441  *      _bcm_td3_l3_flex_intf_dscp_set
   1442  * Purpose:
   1443  *      Set L3 Interface DSCP parameters
   1444  * Parameters:
   1445  *      unit      - (IN)SOC unit number.
   1446  *      view_id   - (IN) memory view
   1447  *      l3_if_entry_p - (IN) Pointer to buffer
   1448  *      vid       - (IN) Intf_info
   1449  * Returns:
   1450  *      BCM_E_XXX.
   1451  */
   1452 STATIC int
   1453 _bcm_td3_l3_flex_intf_dscp_set(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info)
   1454 {
   1455     int hw_map_idx=0;
   1456     uint32 action_set = 0;
   1457 
   1458     /* Input parameters check */
   1459     if (NULL == intf_info) {
   1460         return (BCM_E_PARAM);
   1461     }
   1462 
   1463         if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_COPY) {
   1464          /* DSCP_SELf */
   1465          soc_format_field32_set(unit, QOS_A_ACTION_SETfmt,
   1466                         &action_set, QOS_ACTION_SELf, 0x0);
   1467     } else if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_SET) {
   1468          /* DSCP_SELf */
   1469          soc_format_field32_set(unit, QOS_A_ACTION_SETfmt, &action_set,
   1470                               QOS_ACTION_SELf, 0x1);
   1471          /* DSCPf */
   1472          soc_format_field32_set(unit, QOS_A_ACTION_SETfmt,
   1473                     &action_set, QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf,
   1474                     intf_info->dscp_qos.dscp);
   1475     } else if (intf_info->dscp_qos.flags & BCM_L3_INTF_QOS_DSCP_REMARK) {
   1476          /* DSCP_SELf */
   1477          soc_format_field32_set(unit, QOS_A_ACTION_SETfmt,
   1478                        &action_set, QOS_ACTION_SELf, 0x2);
   1479          BCM_IF_ERROR_RETURN
   1480               (_bcm_tr2_qos_id2idx(unit, intf_info->dscp_qos.qos_map_id,
   1481                                    &hw_map_idx));
   1482          /* DSCP_MAPPING_PTRf */
   1483          soc_format_field32_set(unit, QOS_A_ACTION_SETfmt, &action_set,
   1484                               QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf,
   1485                               hw_map_idx);
   1486     }
   1487 
   1488     soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1489                         QOS_A_ACTION_SETf, action_set);
   1490 
   1491     return BCM_E_NONE;
   1492 }
   1493 
   1494 /*
   1495  * Function:
   1496  *      _bcm_td3_l3_flex_intf_add
   1497  * Purpose:
   1498  *      Add an entry to L3 interface table.
   1499  * Parameters:
   1500  *      unit      - (IN)SOC unit number.
   1501  *      intf_info - (IN)Interface information.
   1502  *      l3_if_entry_p - (IN)  Write buffer address.
   1503  * Returns:
   1504  *      BCM_E_XXX
   1505  */
   1506 int
   1507 _bcm_td3_l3_flex_intf_add(int unit, _bcm_l3_intf_cfg_t *intf_info, uint32 *l3_if_entry_p)
   1508 {
   1509     int rv = BCM_E_NONE;
   1510     int i;
   1511     uint32  view_id;
   1512     uint32  flex_data_array[128];
   1513     uint32  flex_data_count;
   1514     uint32  opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
   1515     uint32  opaque_count;
   1516     bcm_flow_logical_field_t* user_fields;
   1517 
   1518     uint32 action_set = 0;
   1519     uint8  process_fwd_domain = 0;
   1520     uint8  process_otag = 0;
   1521     uint8  process_itag = 0;
   1522     uint8  process_dscp = 0;
   1523     uint8  process_tag_action_profile = 0;
   1524     uint8  process_tunnel_ptr = 0;
   1525     uint8  process_class_id = 0;
   1526     uint8  process_vxlt = 0;
   1527     uint8  process_outer_sa = 0;
   1528     uint8  process_inner_sa = 0;
   1529     uint8  process_ttl_b = 0;
   1530     uint8  process_ttl_a = 0;
   1531     uint8  process_svp = 0;
   1532     bcm_vlan_action_set_t action;
   1533     uint32 profile_idx;
   1534     uint8  process_outer_sa_profile = 0;
   1535 
   1536     /* Input parameters check */
   1537     if (NULL == intf_info) {
   1538         return (BCM_E_PARAM);
   1539     }
   1540 
   1541     if (NULL == l3_if_entry_p) {
   1542         return (BCM_E_PARAM);
   1543     }
   1544 
   1545     /* Get memory fields information.
   1546     fld = (_bcm_l3_intf_fields_t *)BCM_XGS3_L3_MEM_FIELDS(unit, intf);
   1547     */
   1548 
   1549     /* Get view id corresponding to the specified flow. */
   1550     rv = soc_flow_db_ffo_to_mem_view_id_get(unit,
   1551                           intf_info->flow_handle,
   1552                           intf_info->flow_option_handle,
   1553                           SOC_FLOW_DB_FUNC_EGRESS_INTF_ID,
   1554                           &view_id);
   1555     BCM_IF_ERROR_RETURN(rv);
   1556 
   1557     /* Initialize control field list for this view id. */
   1558     rv = soc_flow_db_mem_view_entry_init(unit, view_id, l3_if_entry_p);
   1559 
   1560     BCM_IF_ERROR_RETURN(rv);
   1561 
   1562     /* Get logical field list for this view id. */
   1563     rv = soc_flow_db_mem_view_field_list_get(unit,
   1564                             view_id,
   1565                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   1566                             _BCM_FLOW_LOGICAL_FIELD_MAX,
   1567                             opaque_array,
   1568                             &opaque_count);
   1569     BCM_IF_ERROR_RETURN(rv);
   1570 
   1571     user_fields = intf_info->logical_fields;
   1572 
   1573     for (i=0; i<opaque_count; i++) {
   1574         if (user_fields[i].id == opaque_array[i]) {
   1575             soc_mem_field32_set(unit, view_id, l3_if_entry_p, user_fields[i].id,
   1576                                 user_fields[i].value);
   1577         }
   1578     }
   1579 
   1580     /* Get PDD field list corresponding to the view id. */
   1581     rv = soc_flow_db_mem_view_field_list_get(unit,
   1582                             view_id,
   1583                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
   1584                             128,
   1585                             flex_data_array,
   1586                             &flex_data_count);
   1587     BCM_IF_ERROR_RETURN(rv);
   1588 
   1589     for (i=0; i<flex_data_count; i++) {
   1590         switch (flex_data_array[i]) {
   1591             case FWD_DOMAIN_ACTION_SETf:
   1592                 process_fwd_domain = 1;
   1593                 break;
   1594             case OTAG_ACTION_SETf:
   1595                 process_otag = 1;
   1596                 break;
   1597             case ITAG_ACTION_SETf:
   1598                 process_itag = 1;
   1599                 break;
   1600             case QOS_A_ACTION_SETf:
   1601                 process_dscp = 1;
   1602                 break;
   1603             case TAG_ACTION_PROFILE_ACTION_SETf:
   1604                 process_tag_action_profile = 1;
   1605                 break;
   1606             case TUNNEL_PTR_ACTION_SETf:
   1607                 process_tunnel_ptr = 1;
   1608                 break;
   1609             case CLASS_ID_ACTION_SETf:
   1610                 process_class_id = 1;
   1611                 break;
   1612             case VXLT_CLASS_IDf:
   1613                 process_vxlt = 1;
   1614                 break;
   1615             case DIRECT_ASSIGNMENT_7_ACTION_SETf:
   1616                 process_outer_sa = 1;
   1617                 break;
   1618             case DIRECT_ASSIGNMENT_5_ACTION_SETf:
   1619                 process_inner_sa = 1;
   1620                 break;
   1621             case TTL_B_ACTION_SETf:
   1622                 process_ttl_b = 1;
   1623                 break;
   1624             case TTL_A_ACTION_SETf:
   1625                 process_ttl_a = 1;
   1626                 break;
   1627             case SVP_ACTION_SETf:
   1628                 process_svp = 1;
   1629                 break;
   1630             case PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf:
   1631                 process_outer_sa_profile = 1;
   1632                 break;
   1633             default:
   1634                 /* Unrecongnized acion set */
   1635                 break;
   1636         }
   1637     }
   1638 
   1639     if (process_vxlt) {
   1640           soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1641                               VXLT_CLASS_IDf, intf_info->l3i_class);
   1642     }
   1643 
   1644     /* Set mac address. */
   1645     if (process_outer_sa) {
   1646         /* fld->mac_addr */
   1647         soc_mem_mac_addr_set(unit, view_id, l3_if_entry_p,
   1648                              DIRECT_ASSIGNMENT_7_ACTION_SETf,
   1649                              intf_info->l3i_mac_addr);
   1650     } else if (process_inner_sa) {
   1651         soc_mem_mac_addr_set(unit, view_id, l3_if_entry_p,
   1652                              DIRECT_ASSIGNMENT_5_ACTION_SETf,
   1653                              intf_info->l3i_mac_addr);
   1654     } else if (process_outer_sa_profile) {
   1655         egr_mac_da_profile_entry_t mac_addr;
   1656         uint32 mac_idx ;
   1657         void *entries[1];
   1658 
   1659         sal_memset(&mac_addr, 0, sizeof(egr_mac_da_profile_entry_t));
   1660         soc_mem_mac_addr_set(unit, EGR_MAC_DA_PROFILEm,
   1661             &mac_addr, MAC_ADDRESSf, intf_info->l3i_mac_addr);
   1662         entries[0] = &mac_addr;
   1663         BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_add(unit,
   1664             entries, 1, &mac_idx));
   1665         soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1666             PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf, mac_idx);
   1667     }
   1668 #ifdef BCM_RIOT_SUPPORT
   1669     if (BCMI_L3_INTF_OVERLAY_VALID(unit)) {
   1670         int svp = intf_info->l3i_source_vp;
   1671         if (BCM_GPORT_IS_VXLAN_PORT(svp)) {
   1672             svp = BCM_GPORT_VXLAN_PORT_ID_GET(svp);
   1673         } else if (BCM_GPORT_IS_L2GRE_PORT(svp)) {
   1674             svp = BCM_GPORT_L2GRE_PORT_ID_GET(svp);
   1675         } else if (BCM_GPORT_IS_FLOW_PORT(svp)) {
   1676             svp = BCM_GPORT_FLOW_PORT_ID_GET(svp);
   1677         } else if (BCM_GPORT_IS_MIM_PORT(svp)) {
   1678             svp = BCM_GPORT_MIM_PORT_ID_GET(svp);
   1679         } else if (BCM_GPORT_IS_MPLS_PORT(svp)) {
   1680             svp = BCM_GPORT_MPLS_PORT_ID_GET(svp);
   1681         }
   1682 
   1683         if (process_svp) {
   1684             soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1685                             SVP_ACTION_SETf, svp);     /* SVPf */
   1686         }
   1687 
   1688         if (process_fwd_domain) {
   1689             action_set = 0;
   1690 
   1691             /* VLAN_VFI_OVERLAY_TYPEf */
   1692             soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt,
   1693                 &action_set, FORWARDING_DOMAIN_TYPEf,
   1694                 BCMI_RIOT_VPN_VFI_IS_SET(unit, intf_info->l3i_vid) ? 0x2 : 0x1 );
   1695 
   1696             if (BCMI_RIOT_VPN_VFI_IS_SET(unit, intf_info->l3i_vid)) {
   1697                 int vfi_idx = 0;
   1698                 _BCM_VPN_GET(vfi_idx, _BCM_VPN_TYPE_VFI, intf_info->l3i_vid);
   1699                 /* VFIf */
   1700                 soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt,
   1701                           &action_set, FORWARDING_DOMAINf, vfi_idx);
   1702             } else {
   1703                 /* fld->vlan_id */
   1704                 soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt,
   1705                           &action_set, FORWARDING_DOMAINf, intf_info->l3i_vid);
   1706             }
   1707             soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1708                             FWD_DOMAIN_ACTION_SETf, action_set);
   1709         }
   1710     } else
   1711 #endif
   1712     {
   1713         /* Set vlan id. */
   1714         if (process_fwd_domain) {
   1715             action_set = 0;
   1716             /* fld->vlan_id */
   1717             soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt,
   1718                        &action_set, FORWARDING_DOMAINf, intf_info->l3i_vid);
   1719             soc_format_field32_set(unit, FWD_DOMAIN_ACTION_SETfmt,
   1720                        &action_set, FORWARDING_DOMAIN_TYPEf, 0x1 );
   1721 
   1722             soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1723                             FWD_DOMAIN_ACTION_SETf, action_set);
   1724         }
   1725     }
   1726     /* Set Time To Live. */
   1727     if (process_ttl_b) {
   1728         action_set = 0;
   1729         /* fld->ttl */
   1730         soc_format_field32_set(unit, TTL_B_ACTION_SETfmt,
   1731                        &action_set, TTL_THRESHOLDf, intf_info->l3i_ttl);
   1732 
   1733         soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1734                             TTL_B_ACTION_SETf, action_set);
   1735     } else if (process_ttl_a) {
   1736 
   1737         soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1738                             TTL_A_ACTION_SETf, intf_info->l3i_ttl? 1: 0);
   1739     }
   1740 
   1741     /* Set tunnel index. */
   1742     if (process_tunnel_ptr) {
   1743         action_set = 0;
   1744         /* fld->tnl_id */
   1745         soc_format_field32_set(unit, TUNNEL_PTR_ACTION_SETfmt,
   1746                        &action_set, TUNNEL_INDEXf, intf_info->l3i_tunnel_idx);
   1747 
   1748         soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1749                             TUNNEL_PTR_ACTION_SETf, action_set);
   1750     }
   1751 
   1752     /* Set L2 bridging only flag. */
   1753     if (intf_info->l3i_flags & BCM_L3_L2ONLY) {
   1754         /* fld->l2_switch not supported in flex view */
   1755         return BCM_E_PARAM;
   1756     }
   1757 
   1758     if (process_class_id) {
   1759         /* fld->class_id */
   1760         soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1761                             CLASS_ID_ACTION_SETf, intf_info->l3i_class);
   1762     }
   1763 
   1764     if (process_itag && intf_info->l3i_inner_vlan) {
   1765 
   1766         if (!process_tag_action_profile) {
   1767             return BCM_E_INTERNAL;
   1768         }
   1769         action_set = 0;
   1770         /* IVIDf, IVID_VALIDf */
   1771         soc_format_field32_set(unit, ITAG_ACTION_SETfmt,
   1772                        &action_set, VIDf, intf_info->l3i_inner_vlan);
   1773 
   1774         soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1775                             ITAG_ACTION_SETf, action_set);
   1776     }
   1777 
   1778     /* QoS */
   1779     if (process_otag) {
   1780         BCM_IF_ERROR_RETURN
   1781             (_bcm_td3_l3_flex_intf_opri_ocfi_set(unit, view_id, l3_if_entry_p,
   1782                                              intf_info));
   1783         if (intf_info->l3i_vid) {  /* XXX need to check not VFI */
   1784             action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   1785                             OTAG_ACTION_SETf);
   1786             soc_format_field32_set(unit, OTAG_ACTION_SETfmt,
   1787                        &action_set, VIDf, intf_info->l3i_vid);
   1788             soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1789                                 OTAG_ACTION_SETf, action_set);
   1790         }
   1791     }
   1792     if (process_itag) {
   1793         BCM_IF_ERROR_RETURN
   1794             (_bcm_td3_l3_flex_intf_ipri_icfi_set(unit, view_id, l3_if_entry_p,
   1795                                                  intf_info));
   1796     }
   1797     if (process_dscp) {
   1798         BCM_IF_ERROR_RETURN
   1799             (_bcm_td3_l3_flex_intf_dscp_set(unit, view_id, l3_if_entry_p,
   1800                                             intf_info));
   1801     }
   1802 
   1803     bcm_vlan_action_set_t_init(&action);
   1804 
   1805     /* Program Inner VLAN handling actions */
   1806     if (process_tag_action_profile) {
   1807         if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY) {
   1808             /* IVID_PRESENT_ACTIONf */
   1809             action.dt_inner = bcmVlanActionNone;
   1810             /* IVID_ABSENT_ACTIONf */
   1811             action.ot_inner = bcmVlanActionNone;
   1812         } else {
   1813             if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_ADD) {
   1814                 if (intf_info->l3i_intf_flags &
   1815                     BCM_L3_INTF_INNER_VLAN_REPLACE) {
   1816 
   1817                     /*IVID_PRESENT_ACTIONf*/
   1818                     action.dt_inner = bcmVlanActionReplace;
   1819 
   1820                 } else if (intf_info->l3i_intf_flags &
   1821 
   1822                     BCM_L3_INTF_INNER_VLAN_DELETE) {
   1823 
   1824                     /* IVID_PRESENT_ACTIONf */
   1825                     action.dt_inner = bcmVlanActionDelete;
   1826                 } else {
   1827                     action.dt_inner = bcmVlanActionNone;
   1828                 }
   1829                 /* IVID_ABSENT_ACTIONf */
   1830                 action.ot_inner = bcmVlanActionAdd;
   1831             } else {
   1832                 if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_REPLACE) {
   1833 
   1834                     action.dt_inner = bcmVlanActionReplace;
   1835                     action.ot_inner = bcmVlanActionNone;
   1836                 } else {
   1837                     if (intf_info->l3i_intf_flags & BCM_L3_INTF_INNER_VLAN_DELETE) {
   1838 
   1839                         action.dt_inner = bcmVlanActionDelete;
   1840                         action.ot_inner = bcmVlanActionNone;
   1841                     }
   1842                 }
   1843             }
   1844         }
   1845         if (intf_info->l3i_vid) {  /* XXX need to check not VFI */
   1846             action.ut_outer = bcmVlanActionAdd;
   1847             action.ut_outer_pkt_prio = bcmVlanActionAdd;
   1848             action.ut_outer_cfi = bcmVlanActionAdd;
   1849         }
   1850 
   1851         BCM_IF_ERROR_RETURN
   1852          (_bcm_trx_egr_vlan_action_profile_entry_add(unit, &action, &profile_idx));
   1853 
   1854         action_set = 0;
   1855         soc_format_field32_set(unit, TAG_ACTION_PROFILE_ACTION_SETfmt,
   1856                        &action_set, TAG_ACTION_PROFILE_PTRf, profile_idx);
   1857 
   1858         soc_mem_field32_set(unit, view_id, l3_if_entry_p,
   1859                             TAG_ACTION_PROFILE_ACTION_SETf, action_set);
   1860 
   1861     }
   1862 
   1863     return (BCM_E_NONE);
   1864 
   1865 }
   1866 
   1867 /*
   1868  * Function:
   1869  *      _bcm_td3_l3_intf_flex_opri_ocfi_get
   1870  * Purpose:
   1871  *      Get L3 Interface OVLAN QoS parameters for flex views
   1872  * Parameters:
   1873  *      unit      - (IN)SOC unit number.
   1874  *      view_id   - (IN) memory view
   1875  *      l3_if_entry_p - entry buffer
   1876  *      vid       - (IN) Intf_info
   1877  * Returns:
   1878  *      BCM_E_XXX.
   1879  */
   1880 STATIC int
   1881 _bcm_td3_l3_intf_flex_opri_ocfi_get(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info)
   1882 {
   1883     uint32 action_set;
   1884 
   1885     /* Input parameters check */
   1886     if (NULL == intf_info) {
   1887         return (BCM_E_PARAM);
   1888     }
   1889 
   1890     action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   1891                         OTAG_ACTION_SETf);
   1892 
   1893     if (soc_format_field32_get(unit, OTAG_ACTION_SETfmt,
   1894                    &action_set, PCP_DE_SELf) ==  0x0) { /* OPRI_OCFI_SELf */
   1895           intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_COPY;
   1896     } else if (soc_format_field32_get(unit, OTAG_ACTION_SETfmt,
   1897                    &action_set, PCP_DE_SELf) ==  0x1) { /* OPRI_OCFI_SELf */
   1898           intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_SET;
   1899           /* OPRIf */
   1900           intf_info->vlan_qos.pri =
   1901                soc_format_field32_get(unit, OTAG_ACTION_SETfmt, &action_set, PCPf);
   1902           /* OCFIf */
   1903           intf_info->vlan_qos.cfi =
   1904                soc_format_field32_get(unit, OTAG_ACTION_SETfmt, &action_set, DEf);
   1905     } else if (soc_format_field32_get(unit, OTAG_ACTION_SETfmt,
   1906                    &action_set, PCP_DE_SELf) ==  0x2) { /* OPRI_OCFI_SELf */
   1907           intf_info->vlan_qos.flags |= BCM_L3_INTF_QOS_OUTER_VLAN_PRI_REMARK;
   1908           BCM_IF_ERROR_RETURN
   1909                (_bcm_tr2_qos_idx2id(unit,
   1910                     soc_format_field32_get(unit, OTAG_ACTION_SETfmt,
   1911                             &action_set, PCP_DE_MAPPING_PTRf), 0x2,
   1912                     &intf_info->vlan_qos.qos_map_id));
   1913     }
   1914 
   1915     return BCM_E_NONE;
   1916 }
   1917 /*
   1918  * Function:
   1919  *      _bcm_td3_l3_intf_flex_ipri_icfi_get
   1920  * Purpose:
   1921  *      Get L3 Interface IVLAN QoS parameters for flex views
   1922  * Parameters:
   1923  *      unit      - (IN)SOC unit number.
   1924  *      view_id   - (IN) memory view
   1925  *      l3_if_entry_p - entry buffer
   1926  *      vid       - (IN) Intf_info
   1927  * Returns:
   1928  *      BCM_E_XXX.
   1929  */
   1930 STATIC int
   1931 _bcm_td3_l3_intf_flex_ipri_icfi_get(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info)
   1932 {
   1933     uint32 action_set;
   1934 
   1935     /* Input parameters check */
   1936     if (NULL == intf_info) {
   1937         return (BCM_E_PARAM);
   1938     }
   1939 
   1940     action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   1941                         ITAG_ACTION_SETf);
   1942 
   1943     if (soc_format_field32_get(unit, ITAG_ACTION_SETfmt,
   1944                    &action_set, PCP_DE_SELf) ==  0x0) { /* IPRI_ICFI_SELf */
   1945           intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_COPY;
   1946     } else if (soc_format_field32_get(unit, ITAG_ACTION_SETfmt,
   1947                    &action_set, PCP_DE_SELf) ==  0x1) { /* IPRI_ICFI_SELf */
   1948           intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_SET;
   1949           /* OPRIf */
   1950           intf_info->inner_vlan_qos.pri =
   1951                soc_format_field32_get(unit, ITAG_ACTION_SETfmt, &action_set, PCPf);
   1952           /* OCFIf */
   1953           intf_info->inner_vlan_qos.cfi =
   1954                soc_format_field32_get(unit, ITAG_ACTION_SETfmt, &action_set, DEf);
   1955     } else if (soc_format_field32_get(unit, ITAG_ACTION_SETfmt,
   1956                    &action_set, PCP_DE_SELf) ==  0x2) { /* IPRI_ICFI_SELf */
   1957           intf_info->inner_vlan_qos.flags |= BCM_L3_INTF_QOS_INNER_VLAN_PRI_REMARK;
   1958           BCM_IF_ERROR_RETURN
   1959                (_bcm_tr2_qos_idx2id(unit,
   1960                     soc_format_field32_get(unit, ITAG_ACTION_SETfmt,
   1961                             &action_set, PCP_DE_MAPPING_PTRf), 0x2,
   1962                     &intf_info->inner_vlan_qos.qos_map_id));
   1963     }
   1964     return BCM_E_NONE;
   1965 }
   1966 /*
   1967  * Function:
   1968  *      _bcm_td3_l3_intf_flex_dscp_get
   1969  * Purpose:
   1970  *      Get L3 Interface DSCP parameters for flex views
   1971  * Parameters:
   1972  *      unit      - (IN)SOC unit number.
   1973  *      view_id   - (IN) memory view
   1974  *      l3_if_entry_p - entry buffer
   1975  *      vid       - (IN) Intf_info
   1976  * Returns:
   1977  *      BCM_E_XXX.
   1978  */
   1979 STATIC int
   1980 _bcm_td3_l3_intf_flex_dscp_get(int unit, uint32 view_id, uint32 *l3_if_entry_p, _bcm_l3_intf_cfg_t *intf_info)
   1981 {
   1982     uint32 action_set;
   1983 
   1984     /* Input parameters check */
   1985     if (NULL == intf_info) {
   1986         return (BCM_E_PARAM);
   1987     }
   1988 
   1989     action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   1990                         QOS_A_ACTION_SETf);
   1991 
   1992     if (soc_format_field32_get(unit, QOS_A_ACTION_SETfmt,
   1993                   &action_set, PCP_DE_SELf) ==  0x0) { /* DSCP_SELf */
   1994          intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_COPY;
   1995     } else if (soc_format_field32_get(unit, QOS_A_ACTION_SETfmt,
   1996                   &action_set, PCP_DE_SELf) ==  0x1) { /* DSCP_SELf */
   1997          intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_SET;
   1998           /* DSCPf */
   1999          intf_info->dscp_qos.dscp =
   2000               soc_format_field32_get(unit, QOS_A_ACTION_SETfmt, &action_set,
   2001                                    QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf);
   2002     } else if (soc_format_field32_get(unit, QOS_A_ACTION_SETfmt,
   2003                   &action_set, PCP_DE_SELf) ==  0x2) { /* DSCP_SELf */
   2004          intf_info->dscp_qos.flags |= BCM_L3_INTF_QOS_DSCP_REMARK;
   2005          BCM_IF_ERROR_RETURN
   2006               (_bcm_tr2_qos_idx2id(unit,
   2007                    soc_format_field32_get(unit, QOS_A_ACTION_SETfmt, &action_set,
   2008                            QOS_VALUE_OR_MAPPING_PTR_OR_ZONE_IDf), 0x4,
   2009                    &intf_info->dscp_qos.qos_map_id));
   2010     }
   2011 
   2012     return BCM_E_NONE;
   2013 }
   2014 /*
   2015  * Function:
   2016  *      _bcm_td3_l3_flex_intf_get
   2017  * Purpose:
   2018  *      Get an flex view entry from L3 interface table.
   2019  * Parameters:
   2020  *      unit      - (IN)SOC unit number.
   2021  *      intf_info - (IN/OUT)Pointer to memory for interface information.
   2022  *      l3_if_entry - Buffer to read interface info.
   2023  * Returns:
   2024  *      BCM_E_XXX
   2025  */
   2026 int
   2027 _bcm_td3_l3_flex_intf_get(int unit, _bcm_l3_intf_cfg_t *intf_info, uint32 *l3_if_entry_p)
   2028 {
   2029     int rv = BCM_E_NONE;
   2030     int i;
   2031     uint32  view_id;
   2032     uint32  flex_data_array[128];
   2033     uint32  flex_data_count;
   2034     soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL];
   2035     uint32 num_ffo = 0;
   2036     uint32  opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
   2037     uint32  opaque_count;
   2038     bcm_flow_logical_field_t* user_fields;
   2039 
   2040     uint32 action_set = 0;
   2041     uint8  process_fwd_domain = 0;
   2042     uint8  process_otag = 0;
   2043     uint8  process_itag = 0;
   2044     uint8  process_dscp = 0;
   2045     uint8  process_tag_action_profile = 0;
   2046     uint8  process_tunnel_ptr = 0;
   2047     uint8  process_class_id = 0;
   2048     uint8  process_outer_sa = 0;
   2049     uint8  process_inner_sa = 0;
   2050     uint8 process_vxlt = 0;
   2051     uint8  process_ttl_b = 0;
   2052     uint8  process_ttl_a = 0;
   2053     uint8  process_svp = 0;
   2054     uint8  data_type;
   2055     soc_mem_t mem;
   2056     uint8 process_outer_sa_profile = 0;
   2057 
   2058     /* Input parameters check */
   2059     if (NULL == intf_info) {
   2060         return (BCM_E_PARAM);
   2061     }
   2062 
   2063     if (NULL == l3_if_entry_p) {
   2064         return (BCM_E_PARAM);
   2065     }
   2066 
   2067     mem = BCM_XGS3_L3_MEM(unit,  intf);
   2068 
   2069     /* Get view id corresponding to the specified flow. */
   2070     if (intf_info->flow_handle != 0) {
   2071         BCM_IF_ERROR_RETURN(
   2072             soc_flow_db_ffo_to_mem_view_id_get(unit,
   2073                             intf_info->flow_handle,
   2074                             intf_info->flow_option_handle,
   2075                             SOC_FLOW_DB_FUNC_EGRESS_INTF_ID,
   2076                             &view_id));
   2077      }
   2078     else {
   2079         soc_flow_db_ctrl_field_t   field_list;
   2080         int num_fields = 0;
   2081 
   2082         data_type = soc_mem_field32_get(unit, mem, l3_if_entry_p, DATA_TYPEf);
   2083 
   2084         if(soc_mem_field_valid(unit, mem, FLOW_SELECT_CTRL_IDf)) {
   2085             field_list.field_id = FLOW_SELECT_CTRL_IDf;
   2086             field_list.value = soc_mem_field32_get(unit, mem,
   2087                                    l3_if_entry_p, FLOW_SELECT_CTRL_IDf);
   2088             num_fields = 1;
   2089         }
   2090 
   2091         /* coverity[callee_ptr_arith : FALSE] */
   2092         BCM_IF_ERROR_RETURN(
   2093             soc_flow_db_mem_to_view_id_get(unit,
   2094                              mem,
   2095                              SOC_FLOW_DB_KEY_TYPE_INVALID,
   2096                              data_type,
   2097                              num_fields,
   2098                              &field_list,
   2099                              &view_id));
   2100 
   2101         /* Get the flow handle, function id, option id */
   2102         BCM_IF_ERROR_RETURN(
   2103               soc_flow_db_mem_view_to_ffo_get(unit,
   2104                                          view_id,
   2105                                          SOC_FLOW_DB_MAX_VIEW_FFO_TPL,
   2106                                          ffo,
   2107                                          &num_ffo));
   2108 
   2109         intf_info->flow_handle = ffo[0].flow_handle;
   2110         intf_info->flow_option_handle = ffo[0].option_id;
   2111     }
   2112 
   2113     /* Get logical field list for this view id. */
   2114     rv = soc_flow_db_mem_view_field_list_get(unit,
   2115                             view_id,
   2116                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   2117                             _BCM_FLOW_LOGICAL_FIELD_MAX,
   2118                             opaque_array,
   2119                             &opaque_count);
   2120     BCM_IF_ERROR_RETURN(rv);
   2121 
   2122     user_fields = intf_info->logical_fields;
   2123 
   2124     for (i=0; i<opaque_count; i++) {
   2125         user_fields[i].id = opaque_array[i];
   2126         user_fields[i].value = soc_mem_field32_get(unit, view_id, l3_if_entry_p, opaque_array[i]);
   2127     }
   2128 
   2129     /* Get PDD field list corresponding to the view id. */
   2130     rv = soc_flow_db_mem_view_field_list_get(unit,
   2131                             view_id,
   2132                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
   2133                             128,
   2134                             flex_data_array,
   2135                             &flex_data_count);
   2136     BCM_IF_ERROR_RETURN(rv);
   2137 
   2138     for (i=0; i<flex_data_count; i++) {
   2139         switch (flex_data_array[i]) {
   2140             case FWD_DOMAIN_ACTION_SETf:
   2141                 process_fwd_domain = 1;
   2142                 break;
   2143             case OTAG_ACTION_SETf:
   2144                 process_otag = 1;
   2145                 break;
   2146             case ITAG_ACTION_SETf:
   2147                 process_itag = 1;
   2148                 break;
   2149             case QOS_A_ACTION_SETf:
   2150                 process_dscp = 1;
   2151                 break;
   2152             case TAG_ACTION_PROFILE_ACTION_SETf:
   2153                 process_tag_action_profile = 1;
   2154                 break;
   2155             case TUNNEL_PTR_ACTION_SETf:
   2156                 process_tunnel_ptr = 1;
   2157                 break;
   2158             case CLASS_ID_ACTION_SETf:
   2159                 process_class_id = 1;
   2160                 break;
   2161             case VXLT_CLASS_IDf:
   2162                 process_vxlt = 1;
   2163                 break;
   2164             case DIRECT_ASSIGNMENT_7_ACTION_SETf:
   2165                 process_outer_sa = 1;
   2166                 break;
   2167             case DIRECT_ASSIGNMENT_5_ACTION_SETf:
   2168                 process_inner_sa = 1;
   2169                 break;
   2170             case TTL_B_ACTION_SETf:
   2171                 process_ttl_b = 1;
   2172                 break;
   2173             case TTL_A_ACTION_SETf:
   2174                 process_ttl_a = 1;
   2175                 break;
   2176             case SVP_ACTION_SETf:
   2177                 process_svp = 1;
   2178                 break;
   2179             case PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf:
   2180                 process_outer_sa_profile = 1;
   2181                 break;
   2182             default:
   2183                 break;
   2184         }
   2185     }
   2186 
   2187     if (process_vxlt) {
   2188         intf_info->l3i_class =
   2189           soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2190                               VXLT_CLASS_IDf);
   2191     }
   2192 
   2193     /* Get mac address. */
   2194     if (process_outer_sa) {
   2195        soc_mem_mac_addr_get(unit, view_id, l3_if_entry_p,
   2196                DIRECT_ASSIGNMENT_7_ACTION_SETf, intf_info->l3i_mac_addr);
   2197     } else if (process_inner_sa) {
   2198        soc_mem_mac_addr_get(unit, view_id, l3_if_entry_p,
   2199                DIRECT_ASSIGNMENT_5_ACTION_SETf, intf_info->l3i_mac_addr);
   2200     } else if (process_outer_sa_profile) {
   2201         egr_mac_da_profile_entry_t mac_addr;
   2202         uint32 mac_idx ;
   2203 
   2204         mac_idx = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2205                 PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf);
   2206         BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm,
   2207                 MEM_BLOCK_ANY, mac_idx, &mac_addr));
   2208         soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, &mac_addr,
   2209                 MAC_ADDRESSf, intf_info->l3i_mac_addr);
   2210     }
   2211 
   2212     if (soc_feature(unit, soc_feature_riot)) {
   2213 
   2214         if (process_svp) {
   2215             intf_info->l3i_source_vp =
   2216                 soc_mem_field32_get(unit, view_id, l3_if_entry_p, SVP_ACTION_SETf);
   2217         }
   2218 
   2219         if (process_fwd_domain) {
   2220             action_set = 0;
   2221 
   2222             action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2223                             FWD_DOMAIN_ACTION_SETf);
   2224 
   2225             /* VLAN_VFI_OVERLAY_TYPEf */
   2226             if (soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt,
   2227                 &action_set, FORWARDING_DOMAIN_TYPEf) == 0x2) {
   2228 
   2229             /* VFIf */
   2230             _BCM_VPN_SET(intf_info->l3i_vid, _BCM_VPN_TYPE_VFI,
   2231                 soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt,
   2232                 &action_set, FORWARDING_DOMAINf));
   2233             } else {
   2234 
   2235             /* fld->vlan_id */
   2236             intf_info->l3i_vid =
   2237                 soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt,
   2238                 &action_set, FORWARDING_DOMAINf);
   2239             }
   2240 
   2241         }
   2242 
   2243     } else
   2244     {
   2245         /* Get vlan id. */
   2246         if (process_fwd_domain) {
   2247             action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2248                             FWD_DOMAIN_ACTION_SETf);
   2249             /* fld->vlan_id */
   2250             intf_info->l3i_vid =
   2251                 soc_format_field32_get(unit, FWD_DOMAIN_ACTION_SETfmt,
   2252                 &action_set, FORWARDING_DOMAINf);
   2253         }
   2254     }
   2255     /* Get Time To Live. */
   2256     if (process_ttl_b) {
   2257         action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2258                         TTL_B_ACTION_SETf);
   2259         /* fld->ttl */
   2260         intf_info->l3i_ttl =
   2261                 soc_format_field32_get(unit, TTL_B_ACTION_SETfmt,
   2262                 &action_set, TTL_B_ACTION_SETf);
   2263     } else if (process_ttl_a) {
   2264         intf_info->l3i_ttl = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2265                                 TTL_A_ACTION_SETf);
   2266     }
   2267 
   2268     /* Get tunnel index. */
   2269     if (process_tunnel_ptr) {
   2270         action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2271                         TUNNEL_PTR_ACTION_SETf);
   2272         /* fld->tnl_id */
   2273         intf_info->l3i_tunnel_idx =
   2274                 soc_format_field32_get(unit, TUNNEL_PTR_ACTION_SETfmt,
   2275                 &action_set, TUNNEL_INDEXf);
   2276     }
   2277 
   2278     /* Set L2 bridging only flag. */
   2279     /* not available in flex views */
   2280     /*
   2281     if (soc_mem_field32_get(unit, mem, l3_if_entry_p, fld->l2_switch)) {
   2282         intf_info->l3i_flags |= BCM_L3_L2ONLY;
   2283     }
   2284     */
   2285 
   2286     /* QoS */
   2287     if (process_otag) {
   2288          BCM_IF_ERROR_RETURN
   2289             (_bcm_td3_l3_intf_flex_opri_ocfi_get(unit, view_id,
   2290                                                  l3_if_entry_p, intf_info));
   2291     }
   2292     if (process_itag) {
   2293          BCM_IF_ERROR_RETURN
   2294             (_bcm_td3_l3_intf_flex_ipri_icfi_get(unit, view_id,
   2295                                                 l3_if_entry_p, intf_info));
   2296     }
   2297     if (process_dscp) {
   2298          BCM_IF_ERROR_RETURN
   2299             (_bcm_td3_l3_intf_flex_dscp_get(unit, view_id,
   2300                                             l3_if_entry_p, intf_info));
   2301     }
   2302 
   2303     if (process_itag) {
   2304         action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2305                         ITAG_ACTION_SETf);
   2306 
   2307         /* IVIDf, IVID_VALIDf */
   2308         intf_info->l3i_inner_vlan =
   2309                 soc_format_field32_get(unit, ITAG_ACTION_SETfmt,
   2310                 &action_set, VIDf);
   2311     }
   2312 
   2313     /*Program Inner VLAN handling actions */
   2314     if (process_tag_action_profile) {
   2315         uint32 profile_idx;
   2316         bcm_vlan_action_set_t action;
   2317 
   2318         action_set = soc_mem_field32_get(unit, view_id, l3_if_entry_p,
   2319                                               TAG_ACTION_PROFILE_ACTION_SETf);
   2320 
   2321         profile_idx = soc_format_field32_get(unit, TAG_ACTION_PROFILE_ACTION_SETfmt,
   2322                 &action_set, TAG_ACTION_PROFILE_PTRf);
   2323 
   2324         _bcm_trx_egr_vlan_action_profile_entry_get(unit, &action, profile_idx);
   2325 
   2326         /* IVID_PRESENT_ACTIONf */
   2327         switch (action.dt_inner) {
   2328             case bcmVlanActionNone:
   2329                 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY;
   2330                 break;
   2331             case bcmVlanActionReplace:
   2332                 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_REPLACE;
   2333                 break;
   2334             case bcmVlanActionDelete:
   2335                 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_DELETE;
   2336                 break;
   2337             default :
   2338                 intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY;
   2339         }
   2340 
   2341         /*  IVID_ABSENT_ACTIONf */
   2342         if (action.ot_inner == bcmVlanActionAdd) {
   2343             intf_info->l3i_intf_flags |= BCM_L3_INTF_INNER_VLAN_ADD;
   2344             intf_info->l3i_intf_flags &= ~(BCM_L3_INTF_INNER_VLAN_DO_NOT_MODIFY);
   2345         }
   2346         /* IVIDf */
   2347         intf_info->l3i_inner_vlan =
   2348                 soc_format_field32_get(unit, ITAG_ACTION_SETfmt,
   2349                 &action_set, VIDf);
   2350     }
   2351 
   2352     if (process_class_id) {
   2353         /* fld->class_id */
   2354         intf_info->l3i_class =
   2355         soc_mem_field32_get(unit, view_id, l3_if_entry_p, CLASS_ID_ACTION_SETf);
   2356     }
   2357 
   2358     return (BCM_E_NONE);
   2359 }
   2360 /*
   2361  * Function:
   2362  *      _bcm_td3_l3_flex_intf_profile_delete
   2363  * Purpose:
   2364  *      Delete mac profile in an L3 interface entry.
   2365  * Parameters:
   2366  *      unit      - (IN)SOC unit number.
   2367  *      ifindex   - (IN)Interface index.
   2368  * Returns:
   2369  *      BCM_E_XXX
   2370  */
   2371 int
   2372 _bcm_td3_l3_flex_intf_profile_delete(int unit, int ifindex)
   2373 {
   2374     uint32 l3_if_entry[SOC_MAX_MEM_WORDS];
   2375     soc_mem_t mem;
   2376     uint32 view_id;
   2377     uint32 data_type = 0;
   2378     soc_flow_db_ctrl_field_t field_list;
   2379     int num_fields = 0;
   2380     int rv = BCM_E_NONE;
   2381 
   2382     mem = BCM_XGS3_L3_MEM(unit,  intf);
   2383     sal_memset(&l3_if_entry, 0, sizeof(l3_if_entry));
   2384 
   2385     BCM_IF_ERROR_RETURN
   2386         (BCM_XGS3_MEM_READ(unit, mem, ifindex, &l3_if_entry));
   2387 
   2388     if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   2389         data_type = soc_mem_field32_get(unit, mem, &l3_if_entry, DATA_TYPEf);
   2390     }
   2391     if(soc_mem_field_valid(unit, mem, FLOW_SELECT_CTRL_IDf)) {
   2392         field_list.field_id = FLOW_SELECT_CTRL_IDf;
   2393         field_list.value = soc_mem_field32_get(unit, mem,
   2394             &l3_if_entry, FLOW_SELECT_CTRL_IDf);
   2395         num_fields = 1;
   2396     }
   2397     /* coverity[callee_ptr_arith : FALSE] */
   2398     rv = soc_flow_db_mem_to_view_id_get(unit,
   2399             mem,
   2400             SOC_FLOW_DB_KEY_TYPE_INVALID,
   2401             data_type,
   2402             num_fields,
   2403             &field_list,
   2404             &view_id);
   2405 
   2406     if ((rv == BCM_E_NONE) && soc_mem_field_valid(unit, view_id,
   2407         PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf)) {
   2408 
   2409         egr_mac_da_profile_entry_t mac_addr;
   2410         uint32 mac_idx ;
   2411         bcm_mac_t mac_sa;
   2412 
   2413         mac_idx = soc_mem_field32_get(unit, view_id, &l3_if_entry,
   2414             PROFILED_ASSIGNMENT_SRC_MAC_ADDRESS_ACTION_SETf);
   2415         BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_MAC_DA_PROFILEm,
   2416             MEM_BLOCK_ANY, mac_idx, &mac_addr));
   2417         soc_mem_mac_addr_get(unit, EGR_MAC_DA_PROFILEm, &mac_addr,
   2418             MAC_ADDRESSf, mac_sa);
   2419         if (mac_sa[0] | mac_sa[1] | mac_sa[2] | mac_sa[3] | mac_sa[4] |
   2420                 mac_sa[5]) {
   2421             BCM_IF_ERROR_RETURN(_bcm_mac_da_profile_entry_delete(unit,
   2422                 mac_idx));
   2423         }
   2424     }
   2425 
   2426     return (BCM_E_NONE);
   2427 }
   2428 
   2429 /*
   2430  * Function:
   2431  *      _bcm_td3_l3_flex_ent_init
   2432  * Purpose:
   2433  *      TD2 helper routine used to init l3 host entry buffer
   2434  * Parameters:
   2435  *      unit      - (IN) SOC unit number.
   2436  *      mem       - (IN) L3 table memory.
   2437  *      l3cfg     - (IN/OUT) l3 entry  lookup key & search result.
   2438  *      l3x_entry - (IN) hw buffer.
   2439  * Returns:
   2440  *      void
   2441  */
   2442 STATIC int
   2443 _bcm_td3_l3_flex_ent_init(int unit, soc_mem_t view_id,
   2444                       _bcm_l3_cfg_t *l3cfg, uint32 *buf_p)
   2445 {
   2446     int ipv6;                     /* Entry is IPv6 flag.         */
   2447     int ipmc;                     /* Entry is IPMC flag.         */
   2448     uint32  opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
   2449     uint32  opaque_count;
   2450     bcm_flow_logical_field_t* user_fields;
   2451     int rv;
   2452     int i;
   2453     int j;
   2454 
   2455     /* Get entry type. */
   2456     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   2457     /* Check if IPMC entry */
   2458     ipmc = (l3cfg->l3c_flags & BCM_L3_IPMC);
   2459 
   2460     /* Get logical KEY field list for this view id. */
   2461     rv = soc_flow_db_mem_view_field_list_get(unit,
   2462                             view_id,
   2463                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   2464                             _BCM_FLOW_LOGICAL_FIELD_MAX,
   2465                             opaque_array,
   2466                             &opaque_count);
   2467     BCM_IF_ERROR_RETURN(rv);
   2468 
   2469     user_fields = l3cfg->l3c_logical_fields;
   2470 
   2471     for (i=0; i<opaque_count; i++) {
   2472         for (j = 0; j < l3cfg->l3c_num_of_fields; j++) {
   2473             if (user_fields[j].id == opaque_array[i]) {
   2474                 soc_mem_field32_set(unit, view_id, buf_p, user_fields[j].id,
   2475                                 user_fields[j].value);
   2476                 break;
   2477             }
   2478         }
   2479     }
   2480 
   2481     soc_mem_field32_set(unit, view_id, buf_p, VRFf,
   2482                         l3cfg->l3c_vrf);
   2483 
   2484     if (SOC_MEM_FIELD_VALID(unit, view_id, L3_IIFf)) {
   2485         soc_mem_field32_set(unit, view_id, buf_p, L3_IIFf,
   2486                             l3cfg->l3c_ing_intf);
   2487     }
   2488     if (ipv6) { /* ipv6 entry */
   2489         if (SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_LWR_64f)) {
   2490             soc_mem_ip6_addr_set(unit, view_id, buf_p, IP_ADDR_LWR_64f,
   2491                              l3cfg->l3c_ip6, SOC_MEM_IP6_LOWER_ONLY);
   2492         }
   2493         if (SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDR_UPR_64f)) {
   2494             soc_mem_ip6_addr_set(unit, view_id, buf_p, IP_ADDR_UPR_64f,
   2495                              l3cfg->l3c_ip6, SOC_MEM_IP6_UPPER_ONLY);
   2496         }
   2497         if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIPf)) {
   2498             soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__DIPf,
   2499                              l3cfg->l3c_ip6, SOC_MEM_IP6_FULL_ADDR);
   2500         } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) {
   2501             soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__SIPf,
   2502                              l3cfg->l3c_ip6, SOC_MEM_IP6_FULL_ADDR);
   2503         }
   2504         if (ipmc) {
   2505             if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__DIP_V6f)) {
   2506                 soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__DIP_V6f,
   2507                                  l3cfg->l3c_ip6, SOC_MEM_IP6_FULL_ADDR);
   2508             }
   2509             if (SOC_MEM_FIELD_VALID(unit, view_id, IPV6__SIPf)) {
   2510                 soc_mem_ip6_addr_set(unit, view_id, buf_p, IPV6__SIPf,
   2511                                  l3cfg->l3c_sip6, SOC_MEM_IP6_FULL_ADDR);
   2512             }
   2513         }
   2514     } else { /* ipv4 entry */
   2515         if (SOC_MEM_FIELD_VALID(unit, view_id, IP_ADDRf)) {
   2516             soc_mem_field32_set(unit, view_id, buf_p, IP_ADDRf,
   2517                                            l3cfg->l3c_ip_addr);
   2518         } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV4__DIPf)) {
   2519             soc_mem_field32_set(unit, view_id, buf_p, IPV4__DIPf,
   2520                                            l3cfg->l3c_ip_addr);
   2521         } else if (SOC_MEM_FIELD_VALID(unit, view_id, IPV4__SIPf)) {
   2522             soc_mem_field32_set(unit, view_id, buf_p, IPV4__SIPf,
   2523                                            l3cfg->l3c_ip_addr);
   2524         }
   2525         if (ipmc) {
   2526             if (SOC_MEM_FIELD_VALID(unit, view_id, IPV4__SIPf)) {
   2527                 soc_mem_field32_set(unit, view_id, buf_p, IPV4__SIPf,
   2528                                l3cfg->l3c_src_ip_addr);
   2529             }
   2530         }
   2531     }
   2532     return BCM_E_NONE;
   2533 }
   2534 /*
   2535  * Function:
   2536  *      _bcm_td3_flex_get_extended_profile_index
   2537  * Purpose:
   2538  *      TD3 helper routine used to get profile index for EGR_MACDA_OUI_PROFILE
   2539  *      and EGR_VNTAG_ETAG_PROFILE
   2540  * Parameters:
   2541  *      unit                      - (IN) SOC unit number.
   2542  *      mem                       - (IN) L3 Extended table memory.
   2543  *      l3cfg                     - (IN) L3 entry info.
   2544  *      macda_oui_profile_index   - (out) EGR_MACDA_OUI profile index.
   2545  *      vntag_etag_profile_index  - (out) EGR_VNTAG_ETAG profile index.
   2546  * Returns:
   2547  *      BCM_X_XXX
   2548  */
   2549 bcm_error_t _bcm_td3_flex_get_extended_profile_index(int unit, soc_mem_t view_id,
   2550                                                _bcm_l3_cfg_t *l3cfg,
   2551                                                int *macda_oui_profile_index,
   2552                                                int *vntag_etag_profile_index,
   2553                                                int *ref_count) {
   2554 
   2555     int rv = BCM_E_NONE;               /* Operation return status. */
   2556     uint32 buf_key[SOC_MAX_MEM_WORDS];      /* Key buffer ptr */
   2557     uint32 buf_entry[SOC_MAX_MEM_WORDS];    /* Entry buffer ptr */
   2558     uint32 action_set;
   2559 #if 0
   2560     l3_entry_ipv4_unicast_entry_t l3v4_key, l3v4_entry;            /* IPv4 */
   2561     l3_entry_ipv4_multicast_entry_t l3v4_ext_key, l3v4_ext_entry; /* IPv4-Embedded */
   2562     l3_entry_ipv6_unicast_entry_t l3v6_key, l3v6_entry;           /* IPv6 */
   2563     l3_entry_ipv6_multicast_entry_t l3v6_ext_key, l3v6_ext_entry; /* IPv6-Embedded */
   2564 #endif
   2565 
   2566     if (!SOC_MEM_FIELD_VALID(unit, view_id, EXTENDED_VIEW_MACDA_ACTION_SETf)) {
   2567         return BCM_E_NOT_FOUND;
   2568     }
   2569 
   2570     sal_memset(buf_key, 0, SOC_MAX_MEM_WORDS * sizeof(uint32));
   2571 
   2572     /* Initialize control field list for this view id. */
   2573     rv = soc_flow_db_mem_view_entry_init(unit, view_id, buf_key);
   2574 
   2575     BCM_IF_ERROR_RETURN(rv);
   2576 
   2577     /* Prepare lookup key. */
   2578     BCM_IF_ERROR_RETURN
   2579     (_bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, buf_key));
   2580 
   2581     /* Perform lookup hw. */
   2582     rv = soc_mem_generic_lookup(unit, view_id, MEM_BLOCK_ANY,
   2583                                 _BCM_TD3_L3_MEM_BANKS_ALL,
   2584                                 buf_key, buf_entry, &l3cfg->l3c_hw_index);
   2585     if (BCM_SUCCESS(rv)) {
   2586 
   2587        action_set = soc_mem_field32_get(unit, view_id, buf_entry,
   2588                                EXTENDED_VIEW_MACDA_ACTION_SETf);
   2589 
   2590        *macda_oui_profile_index = soc_format_field32_get(unit,
   2591                                 EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2592                                 &action_set, MACDA_OUI_PROFILEf);
   2593 
   2594        *vntag_etag_profile_index = soc_format_field32_get(unit,
   2595                                 EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2596                                 &action_set, VNTAG_ETAG_PROFILE_IDf);
   2597 
   2598         rv = soc_profile_mem_ref_count_get(unit,
   2599                                            _bcm_td3_macda_oui_profile[unit],
   2600                                            *macda_oui_profile_index,
   2601                                            ref_count);
   2602     }
   2603 
   2604     return rv;
   2605 }
   2606 /*
   2607  * Function:
   2608  *      _bcm_td3_l3_flex_vp_entry_add
   2609  * Purpose:
   2610  *      TD3 helper routine used to parse hw flex l3 entry to api format
   2611  * Parameters:
   2612  *      unit      - (IN) SOC unit number.
   2613  *      mem       - (IN) L3 table memory.
   2614  *      l3cfg     - (IN) L3 entry info.
   2615  *      buf_p     - (IN) hw buffer.
   2616  * Returns:
   2617  *      BCM_X_XXX
   2618  */
   2619 bcm_error_t
   2620 _bcm_td3_l3_flex_vp_entry_add(int unit, soc_mem_t view_id, _bcm_l3_cfg_t *l3cfg,
   2621                         uint32 *buf_p, int *macda_oui_profile_index,
   2622                         int *vntag_etag_profile_index)
   2623 {
   2624 
   2625     int rv = BCM_E_NONE;
   2626     int rv1 = BCM_E_NONE;
   2627     uint32 *bufp;                 /* HW buffer address.          */
   2628     uint32 profile_idx;
   2629     uint32 mac_field;
   2630     uint32 vntag_actions;
   2631     void *entries[1];
   2632     uint32  action_set = 0;
   2633 
   2634     egr_macda_oui_profile_entry_t macda_oui_profile_entry;
   2635     egr_vntag_etag_profile_entry_t vntag_etag_profile_entry;
   2636 
   2637     /* Set table fields */
   2638     bufp = buf_p;
   2639 
   2640     if (soc_feature(unit, soc_feature_virtual_port_routing) &&
   2641         (l3cfg->l3c_encap_id > 0 &&
   2642          l3cfg->l3c_encap_id < BCM_XGS3_EGRESS_IDX_MIN(unit))) {
   2643         int virtual_interface_id;
   2644         uint32 hg_vntag_modify = 1;
   2645         if (_bcm_vp_used_get(unit, l3cfg->l3c_encap_id,
   2646                              _bcmVpTypeNiv)) { /* NIV */
   2647             bcm_niv_port_t niv_port;
   2648             bcm_niv_egress_t niv_egress;
   2649             int count;
   2650             BCM_GPORT_NIV_PORT_ID_SET(niv_port.niv_port_id,
   2651                                       l3cfg->l3c_encap_id);
   2652             BCM_IF_ERROR_RETURN(bcm_esw_niv_port_get(unit, &niv_port));
   2653             if (niv_port.flags & BCM_NIV_PORT_MATCH_NONE) {
   2654                 BCM_IF_ERROR_RETURN(bcm_esw_niv_egress_get(unit,
   2655                                     niv_port.niv_port_id, 1,
   2656                                     &niv_egress, &count));
   2657                 if (count == 0) {
   2658                     return BCM_E_CONFIG;
   2659                 }
   2660                 if (niv_egress.flags & BCM_NIV_EGRESS_MULTICAST) {
   2661                     return BCM_E_PARAM;
   2662                 }
   2663                 virtual_interface_id = niv_egress.virtual_interface_id;
   2664             } else {
   2665                 if (niv_port.flags & BCM_NIV_PORT_MULTICAST) {
   2666                     return BCM_E_PARAM;
   2667                 }
   2668                 virtual_interface_id = niv_port.virtual_interface_id;
   2669             }
   2670             /* fld->dst_vif */
   2671             soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2672                            &action_set, DST_VIFf,
   2673                            virtual_interface_id);
   2674 
   2675             sal_memset(&vntag_etag_profile_entry, 0, sizeof(vntag_etag_profile_entry));
   2676             vntag_actions = 1;
   2677             soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry,
   2678                                                   VNTAG_ACTIONSf, &vntag_actions);
   2679             if (l3cfg->l3c_flags2 & BCM_L3_FLAGS2_NIV_ENCAP_LOCAL) {
   2680                 soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry,
   2681                                                       HG_VNTAG_MODIFY_ENABLEf, &hg_vntag_modify);
   2682             }
   2683             entries[0] = &vntag_etag_profile_entry;
   2684             BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, _bcm_td3_vntag_etag_profile[unit],
   2685                                                     entries, 1, &profile_idx));
   2686             *vntag_etag_profile_index = profile_idx;
   2687             soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2688                            &action_set, VNTAG_ETAG_PROFILE_IDf,
   2689                            profile_idx);
   2690             soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2691                            &action_set, MACDA_OUI_PROFILE_VALIDf, 1);
   2692         } else if (_bcm_vp_used_get(unit, l3cfg->l3c_encap_id,
   2693                                     _bcmVpTypeExtender)) { /* PE */
   2694             bcm_extender_port_t ep;
   2695             int etag_dot1p_mapping_ptr = 0;
   2696             BCM_GPORT_EXTENDER_PORT_ID_SET(ep.extender_port_id,
   2697                                            l3cfg->l3c_encap_id);
   2698             BCM_IF_ERROR_RETURN(bcm_esw_extender_port_get(unit, &ep));
   2699             if (ep.flags & BCM_EXTENDER_PORT_MULTICAST) {
   2700                 return BCM_E_PARAM;
   2701             }
   2702             sal_memset(&vntag_etag_profile_entry, 0, sizeof(vntag_etag_profile_entry));
   2703             vntag_actions = 2;
   2704             soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry,
   2705                                                   VNTAG_ACTIONSf, &vntag_actions);
   2706             if (l3cfg->l3c_flags2 & BCM_L3_FLAGS2_NIV_ENCAP_LOCAL) {
   2707                 soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry,
   2708                                                       HG_VNTAG_MODIFY_ENABLEf, &hg_vntag_modify);
   2709             }
   2710             bcm_td2_qos_egr_etag_id2profile(unit, ep.qos_map_id,
   2711                                             &etag_dot1p_mapping_ptr);
   2712             soc_EGR_VNTAG_ETAG_PROFILEm_field_set(unit, &vntag_etag_profile_entry,
   2713                                                   ETAG_DOT1P_MAPPING_PTRf,
   2714                                                   (uint32 *)&etag_dot1p_mapping_ptr);
   2715 
   2716             entries[0] = &vntag_etag_profile_entry;
   2717             BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit, _bcm_td3_vntag_etag_profile[unit],
   2718                                                     entries, 1, &profile_idx));
   2719             *vntag_etag_profile_index = profile_idx;
   2720             soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2721                            &action_set, VNTAG_ETAG_PROFILE_IDf,
   2722                            profile_idx);
   2723             virtual_interface_id = ep.extended_port_vid;
   2724             soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2725                            &action_set, DST_VIFf,
   2726                            virtual_interface_id);
   2727             soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2728                            &action_set, MACDA_OUI_PROFILE_VALIDf, 1);
   2729         } else {
   2730             return BCM_E_PARAM;
   2731         }
   2732     } else {
   2733         soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2734                            &action_set, MACDA_OUI_PROFILE_VALIDf, 0);
   2735     }
   2736     mac_field = ((l3cfg->l3c_mac_addr[3] << 16) |
   2737                 (l3cfg->l3c_mac_addr[4] << 8)  |
   2738                 (l3cfg->l3c_mac_addr[5] << 0));
   2739     soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2740                            &action_set, MACDA_23_0f, mac_field);
   2741     mac_field = ((l3cfg->l3c_mac_addr[0] << 16) |
   2742                  (l3cfg->l3c_mac_addr[1] << 8)  |
   2743                  (l3cfg->l3c_mac_addr[2] << 0));
   2744     sal_memset(&macda_oui_profile_entry, 0, sizeof(macda_oui_profile_entry));
   2745     soc_EGR_MACDA_OUI_PROFILEm_field_set(unit, &macda_oui_profile_entry,
   2746                                          MACDA_OUIf, &mac_field);
   2747     entries[0] = &macda_oui_profile_entry;
   2748     rv = soc_profile_mem_add(unit, _bcm_td3_macda_oui_profile[unit],
   2749                              entries, 1, &profile_idx);
   2750     if (BCM_FAILURE(rv)) {
   2751         /* delete previously added entry or decrement ref count
   2752          * from EGR_VNTAG_ETAG_PROFILE table
   2753          */
   2754         soc_mem_lock(unit, EGR_VNTAG_ETAG_PROFILEm);
   2755         /* profile 0 is reserved for NON NIV/PE entries */
   2756         if (*vntag_etag_profile_index != 0) {
   2757             rv1 = soc_profile_mem_delete(unit, _bcm_td3_vntag_etag_profile[unit],
   2758                                          *vntag_etag_profile_index);
   2759         }
   2760         if (BCM_FAILURE(rv1)) {
   2761             soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm);
   2762             return rv1;
   2763         }
   2764         soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm);
   2765         return rv;
   2766     }
   2767 
   2768     *macda_oui_profile_index = profile_idx;
   2769     soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2770                            &action_set, MACDA_OUI_PROFILEf, profile_idx);
   2771 
   2772     soc_mem_field32_set(unit, view_id, bufp,
   2773                         EXTENDED_VIEW_MACDA_ACTION_SETf,
   2774                         action_set);
   2775     return rv;
   2776 }
   2777 /*
   2778  * Function:
   2779  *      _bcm_td3_l3_flex_vp_entry_del
   2780  * Purpose:
   2781  *      Delete entry from profile table
   2782  * Parameters:
   2783  *      unit     - (IN) SOC unit number.
   2784  *      ipv6     - (IN) IPV4 or IPv6 flag
   2785  *      l3cfg    - (IN) L3 entry info.
   2786  *      bufentry - (IN) hw buffer
   2787  * Returns:
   2788  */
   2789 bcm_error_t
   2790 _bcm_td3_l3_flex_vp_entry_del(int unit, _bcm_l3_cfg_t *l3cfg,
   2791                         int macda_oui_profile_index ,int vntag_etag_profile_index)
   2792 {
   2793 
   2794     int rv = BCM_E_NONE;
   2795 
   2796     if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) {
   2797 
   2798         /* delete an entry or decrement ref count from EGR_MACDA_OUI_PROFILE table */
   2799         soc_mem_lock(unit, EGR_MACDA_OUI_PROFILEm);
   2800         if (macda_oui_profile_index != -1) {
   2801             rv = soc_profile_mem_delete(unit, _bcm_td3_macda_oui_profile[unit],
   2802                                         macda_oui_profile_index);
   2803         }
   2804         if (BCM_FAILURE(rv)) {
   2805             soc_mem_unlock(unit, EGR_MACDA_OUI_PROFILEm);
   2806             return rv;
   2807         }
   2808         soc_mem_unlock(unit, EGR_MACDA_OUI_PROFILEm);
   2809 
   2810         /* delete an entry or decrement ref count from EGR_VNTAG_ETAG_PROFILE table */
   2811         soc_mem_lock(unit, EGR_VNTAG_ETAG_PROFILEm);
   2812         /* profile 0 is reserved for NON NIV/PE entries */
   2813         if (vntag_etag_profile_index != 0) {
   2814             rv = soc_profile_mem_delete(unit, _bcm_td3_vntag_etag_profile[unit],
   2815                                         vntag_etag_profile_index);
   2816         }
   2817         if (BCM_FAILURE(rv)) {
   2818             soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm);
   2819             return rv;
   2820         }
   2821         soc_mem_unlock(unit, EGR_VNTAG_ETAG_PROFILEm);
   2822 
   2823     }
   2824 
   2825     return rv;
   2826 }
   2827 /*
   2828  * Function:
   2829  *      _bcm_td3_l3_flex_vp_ent_parse
   2830  * Purpose:
   2831  *      TD3 helper routine used to parse hw flex l3 entry to api format
   2832  * Parameters:
   2833  *      unit      - (IN) SOC unit number.
   2834  *      mem       - (IN) L3 table memory.
   2835  *      l3cfg     - (IN) L3 entry info.
   2836  *      l3x_entry - (IN) hw buffer.
   2837  * Returns:
   2838  */
   2839 bcm_error_t
   2840 _bcm_td3_l3_flex_vp_ent_parse(int unit, soc_mem_t view_id, _bcm_l3_cfg_t *l3cfg, void *l3x_entry)
   2841 {
   2842 
   2843     uint32 profile_index;
   2844     uint32 dst_vif;
   2845     uint32 mac_field;
   2846     bcm_gport_t vp_gport;
   2847     uint32 vntag_actions;
   2848     int rv = BCM_E_NONE;
   2849     uint32 glp;                   /* Global port.                */
   2850     uint32 *buf_p;                /* HW buffer address.          */
   2851     egr_macda_oui_profile_entry_t macda_oui_profile_entry;
   2852     egr_vntag_etag_profile_entry_t vntag_etag_profile_entry;
   2853     int is_trunk = -1;
   2854     uint32 HG_VNTAG_MODIFY_ENABLE_FLAG = 0;
   2855     uint32 action_set;
   2856 
   2857     buf_p = (uint32 *)l3x_entry;
   2858 
   2859     action_set =  soc_mem_field32_get(unit, view_id, buf_p,
   2860                             DESTINATION_ACTION_SETf);
   2861     /* fld->glp */
   2862     glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   2863                                &action_set, DGPPf);
   2864 
   2865     _bcm_th_glp_resolve_embedded_nh(unit, glp, &l3cfg->l3c_modid,
   2866                                     &l3cfg->l3c_port_tgid, &is_trunk);
   2867     if (is_trunk == 1) {
   2868         l3cfg->l3c_flags |= BCM_L3_TGID;
   2869     }
   2870 
   2871     action_set = soc_mem_field32_get(unit, view_id, buf_p,
   2872                         EXTENDED_VIEW_MACDA_ACTION_SETf);
   2873 
   2874     /* Set table fields */
   2875     /* fld->macda_low */
   2876     mac_field = soc_format_field32_get(unit,
   2877                            EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2878                            &action_set, MACDA_23_0f);
   2879 
   2880     l3cfg->l3c_mac_addr[3] = (uint8) (mac_field >> 16 & 0xff);
   2881     l3cfg->l3c_mac_addr[4] = (uint8) (mac_field >> 8 & 0xff);
   2882     l3cfg->l3c_mac_addr[5] = (uint8) (mac_field & 0xff);
   2883     /* Read upper 3 bytes of MAC address from profile table */
   2884     /* fld->oui_profile_id */
   2885     profile_index = soc_format_field32_get(unit,
   2886                      EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2887                     &action_set, MACDA_OUI_PROFILEf);
   2888 
   2889     SOC_IF_ERROR_RETURN
   2890         (READ_EGR_MACDA_OUI_PROFILEm(unit, MEM_BLOCK_ANY, profile_index,
   2891                                      &macda_oui_profile_entry));
   2892     soc_EGR_MACDA_OUI_PROFILEm_field_get(unit, &macda_oui_profile_entry,
   2893                                          MACDA_OUIf, &mac_field);
   2894     l3cfg->l3c_mac_addr[0] = (uint8) (mac_field >> 16 & 0xff);
   2895     l3cfg->l3c_mac_addr[1] = (uint8) (mac_field >> 8 & 0xff);
   2896     l3cfg->l3c_mac_addr[2] = (uint8) (mac_field & 0xff);
   2897 
   2898     /* fld->dst_vif */
   2899     dst_vif = soc_format_field32_get(unit,
   2900                      EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2901                     &action_set, DST_VIFf);
   2902     /* fld->vntag_etag_profile_id */
   2903     profile_index = soc_format_field32_get(unit,
   2904                      EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   2905                     &action_set, VNTAG_ETAG_PROFILE_IDf);
   2906 
   2907     if (profile_index != L3_EXT_VIEW_INVALID_VNTAG_ETAG_PROFILE) {
   2908         SOC_IF_ERROR_RETURN
   2909             (READ_EGR_VNTAG_ETAG_PROFILEm(unit, MEM_BLOCK_ANY, profile_index,
   2910                                          &vntag_etag_profile_entry));
   2911         soc_EGR_VNTAG_ETAG_PROFILEm_field_get(unit, &vntag_etag_profile_entry,
   2912                                               HG_VNTAG_MODIFY_ENABLEf,
   2913                                               &HG_VNTAG_MODIFY_ENABLE_FLAG);
   2914         l3cfg->l3c_flags2 = HG_VNTAG_MODIFY_ENABLE_FLAG;
   2915         soc_EGR_VNTAG_ETAG_PROFILEm_field_get(unit, &vntag_etag_profile_entry,
   2916                                               VNTAG_ACTIONSf, &vntag_actions);
   2917         switch (vntag_actions) {
   2918             case VNTAG_ACTIONS_NIV: /* NIV encap */
   2919                 if (_bcm_niv_gport_get(unit, is_trunk, l3cfg->l3c_modid,
   2920                                        l3cfg->l3c_port_tgid, dst_vif,
   2921                                        &vp_gport) == BCM_E_NONE) {
   2922                     l3cfg->l3c_port_tgid = vp_gport;
   2923                 }
   2924                 break;
   2925             case VNTAG_ACTIONS_ETAG: /* PE encap */
   2926                 if (_bcm_extender_gport_get(unit, is_trunk, l3cfg->l3c_modid,
   2927                                             l3cfg->l3c_port_tgid, dst_vif,
   2928                                             &vp_gport) == BCM_E_NONE) {
   2929                     l3cfg->l3c_port_tgid = vp_gport;
   2930                 }
   2931                 break;
   2932             default:
   2933                 break;
   2934         }
   2935     }
   2936 
   2937     return rv;
   2938 }
   2939 
   2940 /*
   2941  * Function:
   2942  *      _bcm_td3_l3_flex_entry_add
   2943  * Purpose:
   2944  *      Add and entry to flex view in TD3 L3 host table.
   2945  * Parameters:
   2946  *      unit   - (IN) SOC unit number.
   2947  *      l3cfg  - (IN) L3 entry info.
   2948  *      nh_idx - (IN) Next hop index.
   2949  * Returns:
   2950  *      BCM_E_XXX
   2951  */
   2952 int
   2953 _bcm_td3_l3_flex_entry_add(int unit, _bcm_l3_cfg_t *l3cfg, int nh_idx)
   2954 {
   2955     int ipv6;
   2956     uint32 bufp[SOC_MAX_MEM_WORDS];   /* Hardware buffer ptr     */
   2957     int rv = BCM_E_NONE;      /* Operation status.       */
   2958     int embedded_nh = FALSE;
   2959     uint32 glp = 0, port_id = 0, modid = 0;
   2960     _bcm_l3_intf_cfg_t l3_intf;
   2961 #if 0
   2962     l3_entry_ipv4_unicast_entry_t l3v4_entry;       /* IPv4 */
   2963     l3_entry_ipv4_multicast_entry_t l3v4_ext_entry;   /* IPv4-Embedded */
   2964     l3_entry_ipv6_unicast_entry_t l3v6_entry;       /* IPv6 */
   2965     l3_entry_ipv6_multicast_entry_t l3v6_ext_entry;   /* IPv6-Embedded */
   2966 #endif
   2967     uint32 port_addr_max = 0, modid_max  = 0;
   2968     int macda_oui_profile_index = -1;
   2969     int macda_oui_profile_index1 = -1;
   2970     int vntag_etag_profile_index = 0;
   2971     int vntag_etag_profile_index1 = 0;
   2972     int ref_count = 0;
   2973 #ifdef BCM_RIOT_SUPPORT
   2974     int dvp = -1;
   2975 #endif
   2976     soc_flow_db_mem_view_info_t mem_view_info;
   2977     int     i;
   2978     uint32  view_id;
   2979     uint32  field_array[128];
   2980     uint32  field_count;
   2981     uint32  opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
   2982     uint32  opaque_count;
   2983     bcm_flow_logical_field_t* user_fields;
   2984 
   2985     uint32 action_set = 0;
   2986     uint32 mac_action_set[2];
   2987 
   2988     uint8 process_destination = 0;
   2989     uint8 process_class_id = 0;
   2990     uint8 process_qos = 0;
   2991     uint8 process_fwd_attributes = 0;
   2992     uint8 process_fwd_2_attributes = 0;
   2993     uint8 process_qtag = 0;
   2994     uint8 process_macda = 0;
   2995     uint8 process_l3_if = 0;
   2996     uint8 process_source = 0;
   2997 
   2998     /* Marking the l3c_hw_index INVALID
   2999      * when l3 host entry flag is not BCM_L3_REPLACE
   3000      */
   3001     if (!(l3cfg->l3c_flags & BCM_L3_REPLACE)) {
   3002         l3cfg->l3c_hw_index = BCM_XGS3_L3_INVALID_INDEX;
   3003     }
   3004     /* Get view id corresponding to the specified flow. */
   3005     rv = soc_flow_db_ffo_to_mem_view_id_get(unit,
   3006                           l3cfg->l3c_flow_handle,
   3007                           l3cfg->l3c_flow_option_handle,
   3008                           SOC_FLOW_DB_FUNC_L3_HOST_ID,
   3009                           &view_id);
   3010     BCM_IF_ERROR_RETURN(rv);
   3011 
   3012     rv = soc_flow_db_mem_view_info_get(unit,
   3013                           view_id,
   3014                           &mem_view_info);
   3015 
   3016     BCM_IF_ERROR_RETURN(rv);
   3017 
   3018     /* Get entry type. */
   3019     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   3020 
   3021 #if 0
   3022     /* Assign entry buf based on table being used */
   3023     BCM_TD3_L3_HOST_ENTRY_BUF(ipv6, mem, bufp,
   3024                                   l3v4_entry,
   3025                                   l3v4_ext_entry,
   3026                                   l3v6_entry,
   3027                                   l3v6_ext_entry);
   3028 #endif
   3029 
   3030     /* Initialize control field list for this view id. */
   3031     sal_memset(bufp, 0, sizeof(bufp));
   3032     rv = soc_flow_db_mem_view_entry_init(unit, view_id, bufp);
   3033 
   3034     BCM_IF_ERROR_RETURN(rv);
   3035 
   3036     /* Prepare host entry for addition. */
   3037     rv = _bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, bufp);
   3038 
   3039     BCM_IF_ERROR_RETURN(rv);
   3040 
   3041     /* Get logical PDD field list for this view id. */
   3042     rv = soc_flow_db_mem_view_field_list_get(unit,
   3043                             view_id,
   3044                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   3045                             _BCM_FLOW_LOGICAL_FIELD_MAX,
   3046                             opaque_array,
   3047                             &opaque_count);
   3048     BCM_IF_ERROR_RETURN(rv);
   3049 
   3050     user_fields = l3cfg->l3c_logical_fields;
   3051 
   3052     for (i=0; i<opaque_count; i++) {
   3053         if (user_fields[i].id == opaque_array[i]) {
   3054             soc_mem_field32_set(unit, view_id, bufp, user_fields[i].id,
   3055                                 user_fields[i].value);
   3056         }
   3057     }
   3058 
   3059     /* Get PDD field list corresponding to the view id. */
   3060     rv = soc_flow_db_mem_view_field_list_get(unit,
   3061                             view_id,
   3062                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
   3063                             128,
   3064                             field_array,
   3065                             &field_count);
   3066     BCM_IF_ERROR_RETURN(rv);
   3067 
   3068     for (i=0; i<field_count; i++) {
   3069         switch (field_array[i]) {
   3070             case DESTINATION_ACTION_SETf:
   3071                 process_destination = 1;
   3072                 break;
   3073             case CLASS_ID_ACTION_SETf:
   3074                 process_class_id = 1;
   3075                 break;
   3076             case QOS_ACTION_SETf:
   3077                 process_qos = 1;
   3078                 break;
   3079             case FWD_ATTRIBUTES_ACTION_SETf:
   3080                 process_fwd_attributes = 1;
   3081                 break;
   3082             case FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf:
   3083                 process_fwd_2_attributes = 1;
   3084                 break;
   3085             case QTAG_ACTION_SETf:
   3086                 process_qtag = 1;
   3087                 break;
   3088             case EXTENDED_VIEW_MACDA_ACTION_SETf:
   3089                 process_macda = 1;
   3090                 break;
   3091             case EXTENDED_VIEW_L3_OIF_ACTION_SETf:
   3092                 process_l3_if = 1;
   3093                 break;
   3094             case SOURCE_ACTION_SETf:
   3095                 process_source = 1;
   3096                 break;
   3097             default:
   3098                 break;
   3099         }
   3100     }
   3101 
   3102 #ifdef BCM_RIOT_SUPPORT
   3103     if ((BCMI_RIOT_IS_ENABLED(unit))
   3104         && (_bcm_vp_is_vfi_type(unit, l3cfg->l3c_port_tgid))) {
   3105         _bcm_vp_vfi_type_vp_get(unit, l3cfg->l3c_port_tgid, &dvp);
   3106     } else
   3107 #endif
   3108     {
   3109         port_addr_max = SOC_PORT_ADDR_MAX(unit) + 1;
   3110         modid_max = SOC_MODID_MAX(unit) + 1;
   3111         if (l3cfg->l3c_flags & BCM_L3_TGID) {
   3112             glp = (BCM_TGID_PORT_TRUNK_MASK(unit) & l3cfg->l3c_port_tgid);
   3113             glp |= (port_addr_max * modid_max);
   3114         } else {
   3115             port_id = (SOC_PORT_ADDR_MAX(unit) & l3cfg->l3c_port_tgid);
   3116             modid = (SOC_MODID_MAX(unit) & l3cfg->l3c_modid) * port_addr_max;
   3117             glp = modid | port_id;
   3118         }
   3119     }
   3120 
   3121     /* Set hit bit. */
   3122     if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) {
   3123         if (l3cfg->l3c_flags & BCM_L3_HIT) {
   3124             soc_mem_field32_set(unit, view_id, bufp, HITf, 1);
   3125         }
   3126     }
   3127     /*  Set priority. */
   3128     action_set = 0;
   3129     if (SOC_MEM_FIELD_VALID(unit, view_id, QOS_ACTION_SETf)) {
   3130         soc_format_field32_set(unit, QOS_ACTION_SETfmt,
   3131                                &action_set, PRIf, l3cfg->l3c_prio);
   3132     }
   3133     /* Set priority override bit. */
   3134     if (l3cfg->l3c_flags & BCM_L3_RPE) {
   3135         if (!process_qos) {
   3136             return BCM_E_PARAM;
   3137         }
   3138         soc_format_field32_set(unit, QOS_ACTION_SETfmt,
   3139                                &action_set, RPEf, 1);
   3140     }
   3141 
   3142     if (process_qos) {
   3143         soc_mem_field32_set(unit, view_id, bufp,
   3144                         QOS_ACTION_SETf, action_set);
   3145     }
   3146 
   3147     /* Set destination discard bit. */
   3148     action_set = 0;
   3149     if (l3cfg->l3c_flags & BCM_L3_DST_DISCARD) {
   3150         if (!process_fwd_attributes) {
   3151             return BCM_E_PARAM;
   3152         }
   3153         soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
   3154                                &action_set, DST_DISCARDf, 1);
   3155     }
   3156 
   3157     if (process_fwd_attributes) {
   3158         soc_mem_field32_set(unit, view_id, bufp,
   3159                         FWD_ATTRIBUTES_ACTION_SETf, action_set);
   3160     }
   3161 
   3162     /* Set local addr bit. */
   3163     action_set = 0;
   3164     if (l3cfg->l3c_flags & BCM_L3_HOST_LOCAL) {
   3165         if (!process_fwd_2_attributes) {
   3166             return BCM_E_PARAM;
   3167         }
   3168         soc_format_field32_set(unit, FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETfmt,
   3169                                &action_set, LOCAL_ADDRESSf, 1);
   3170     }
   3171 
   3172     if (process_fwd_2_attributes) {
   3173         soc_mem_field32_set(unit, view_id, bufp,
   3174                         FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf, action_set);
   3175     }
   3176 
   3177     /* Set classification group id. */
   3178     if (process_class_id) {
   3179         soc_mem_field32_set(unit, view_id, bufp, CLASS_ID_ACTION_SETf,
   3180                             l3cfg->l3c_lookup_class);
   3181     }
   3182 
   3183     if (!process_destination) {
   3184         return BCM_E_INTERNAL;
   3185     }
   3186 
   3187 /* Check if embedded NH table is being used */
   3188     embedded_nh = BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, l3cfg->l3c_intf, nh_idx);
   3189 
   3190     if (l3cfg->l3c_flags & BCM_L3_IPMC) {
   3191         if (process_source) {
   3192             action_set = 0;
   3193 
   3194             if (dvp != -1) {
   3195                 soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3196                           &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DVP );
   3197                 soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3198                           &action_set, DVPf, dvp);
   3199             } else {
   3200                 if (l3cfg->l3c_flags & BCM_L3_TGID) {
   3201                     soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3202                              &action_set, DEST_TYPE2f, BCMI_TD3_DEST_TYPE2_LAG);
   3203                 } else {
   3204                     soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3205                             &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DGPP);
   3206                 }
   3207                 soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3208                           &action_set, DGPPf, glp);
   3209             }
   3210         soc_mem_field32_set(unit, view_id, bufp, SOURCE_ACTION_SETf,
   3211                             action_set);
   3212         }
   3213 
   3214         action_set = 0;
   3215         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3216                                &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_IPMC);
   3217         soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3218                                &action_set, IPMC_GROUPf, l3cfg->l3c_ipmc_ptr);
   3219         soc_mem_field32_set(unit, view_id, bufp,
   3220                             DESTINATION_ACTION_SETf, action_set);
   3221     } else if (embedded_nh) {
   3222         if (!process_l3_if || !process_macda) {
   3223             return BCM_E_PARAM;
   3224         }
   3225         sal_memset(&l3_intf, 0, sizeof(_bcm_l3_intf_cfg_t));
   3226         BCM_XGS3_L3_INTF_IDX_SET(l3_intf, l3cfg->l3c_intf);
   3227 
   3228         BCM_XGS3_L3_MODULE_LOCK(unit);
   3229         rv = BCM_XGS3_L3_HWCALL_EXEC(unit, if_get) (unit, &l3_intf);
   3230         BCM_XGS3_L3_MODULE_UNLOCK(unit);
   3231 
   3232         soc_mem_field32_set(unit, view_id, bufp,
   3233                             EXTENDED_VIEW_L3_OIF_ACTION_SETf,
   3234                             l3cfg->l3c_intf);
   3235         action_set = 0;
   3236         if (dvp != -1) {
   3237             soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3238                                &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DVP);
   3239             soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3240                                &action_set, DVPf, dvp);
   3241         } else {
   3242             if (l3cfg->l3c_flags & BCM_L3_TGID) {
   3243                 soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3244                                &action_set, DEST_TYPE2f, BCMI_TD3_DEST_TYPE2_LAG);
   3245             } else {
   3246                 soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3247                                &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_DGPP);
   3248             }
   3249             soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3250                                &action_set, DGPPf, glp);
   3251         }
   3252         soc_mem_field32_set(unit, view_id, bufp,
   3253                             DESTINATION_ACTION_SETf, action_set);
   3254 
   3255         mac_action_set[0] = 0;
   3256         mac_action_set[1] = 0;
   3257         if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) {
   3258             if (l3cfg->l3c_flags & BCM_L3_REPLACE) {
   3259                 /* For BCM_L3_REPLACE, get profile index for EGR_MACDA_OUI_PROFILE
   3260                  * and EGR_VNTAG_ETAG_PROFILE table. Delete the profile entry if
   3261                  * it's not used by any other host.
   3262                  */
   3263                 rv = _bcm_td3_flex_get_extended_profile_index(unit, view_id, l3cfg,
   3264                                                     &macda_oui_profile_index,
   3265                                                     &vntag_etag_profile_index,
   3266                                                     &ref_count);
   3267                 if (BCM_FAILURE(rv) && (rv!=BCM_E_NOT_FOUND)) {
   3268                     return rv;
   3269                 }
   3270                 if (macda_oui_profile_index == -1) {
   3271                     /* Host entry was done in regular L3_ENTRY table view */
   3272                     BCM_IF_ERROR_RETURN
   3273                     (_bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp,
   3274                                              &macda_oui_profile_index1,
   3275                                              &vntag_etag_profile_index1));
   3276                 } else {
   3277                     if (ref_count > 1) {
   3278                         rv = _bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp,
   3279                                                      &macda_oui_profile_index1,
   3280                                                      &vntag_etag_profile_index1);
   3281                         if (BCM_SUCCESS(rv)) {
   3282                             BCM_IF_ERROR_RETURN
   3283                             (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg,
   3284                                                     macda_oui_profile_index,
   3285                                                     vntag_etag_profile_index));
   3286                         } else {
   3287                             return rv;
   3288                         }
   3289                     } else {
   3290                         BCM_IF_ERROR_RETURN
   3291                         (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg,
   3292                                                 macda_oui_profile_index,
   3293                                                 vntag_etag_profile_index));
   3294                         BCM_IF_ERROR_RETURN
   3295                         (_bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp,
   3296                                                  &macda_oui_profile_index1,
   3297                                                  &vntag_etag_profile_index1));
   3298 
   3299                     }
   3300                 }
   3301 
   3302             } else {
   3303                 BCM_IF_ERROR_RETURN
   3304                 (_bcm_td3_l3_flex_vp_entry_add(unit, view_id, l3cfg, bufp,
   3305                                          &macda_oui_profile_index1,
   3306                                          &vntag_etag_profile_index1));
   3307 
   3308             }
   3309 
   3310         } else
   3311         {
   3312             uint32              mac_field[2];
   3313             /* fld->mac_addr */
   3314             SAL_MAC_ADDR_TO_UINT32(l3cfg->l3c_mac_addr, mac_field);
   3315 
   3316             soc_format_field_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   3317                                    mac_action_set,
   3318                                    MAC_ADDRf, mac_field);
   3319             soc_format_field32_set(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   3320                                    mac_action_set,
   3321                                    MACDA_OUI_PROFILE_VALIDf, 0);
   3322         }
   3323         soc_mem_field_set(unit, view_id, bufp,
   3324                             EXTENDED_VIEW_MACDA_ACTION_SETf, mac_action_set);
   3325 
   3326         action_set = 0;
   3327         if (process_qtag) {
   3328             soc_format_field32_set(unit, QTAG_ACTION_SETfmt, &action_set,
   3329                                    EH_TAG_TYPEf, l3cfg->l3c_eh_q_tag_type);
   3330             soc_format_field32_set(unit, QTAG_ACTION_SETfmt, &action_set,
   3331                                    EH_QUEUE_TAGf, l3cfg->l3c_eh_q_tag);
   3332             soc_mem_field32_set(unit, view_id, bufp,
   3333                                 QTAG_ACTION_SETf, action_set);
   3334         }
   3335 
   3336         /* Set copy_to_cpu bit. */
   3337         if (l3cfg->l3c_flags & BCM_L3_COPY_TO_CPU) {
   3338             if (!process_fwd_attributes) {
   3339                  return BCM_E_PARAM;
   3340             }
   3341             soc_format_field32_set(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
   3342                                &action_set, COPY_TO_CPUf, 1);
   3343             soc_mem_field32_set(unit, view_id, bufp,
   3344                          FWD_ATTRIBUTES_ACTION_SETf, action_set);
   3345         }
   3346     } else {
   3347         /* Set next hop index. */
   3348         action_set = 0;
   3349         if (l3cfg->l3c_flags & BCM_L3_MULTIPATH) {
   3350             soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3351                                &action_set, DEST_TYPE1f, BCMI_TD3_DEST_TYPE1_ECMP);
   3352             soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3353                                &action_set, ECMP_GROUPf, nh_idx);
   3354         } else {
   3355             soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3356                                &action_set, DEST_TYPE0f, BCMI_TD3_DEST_TYPE0_NH);
   3357             soc_format_field32_set(unit, DESTINATION_FORMATfmt,
   3358                                &action_set, NEXT_HOP_INDEXf, nh_idx);
   3359         }
   3360         soc_mem_field32_set(unit, view_id, bufp,
   3361                             DESTINATION_ACTION_SETf, action_set);
   3362     }
   3363 
   3364     /* Insert in table */
   3365     rv = soc_mem_insert(unit, view_id, MEM_BLOCK_ANY, bufp);
   3366 
   3367     /* Handle host entry 'replace' actions */
   3368     if ((BCM_E_EXISTS == rv) && (l3cfg->l3c_flags & BCM_L3_REPLACE)) {
   3369         rv = BCM_E_NONE;
   3370     }
   3371 
   3372 
   3373     if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) {
   3374         if (BCM_FAILURE(rv)) {
   3375             /* if host add is not successful, then corresponding entries in the
   3376              * profile table need to be removed for extended view hosts.
   3377              */
   3378             BCM_IF_ERROR_RETURN
   3379             (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg,
   3380                                      macda_oui_profile_index1,
   3381                                      vntag_etag_profile_index1));
   3382         }
   3383     }
   3384 
   3385     /* Write status check. */
   3386     if ((rv >= 0) && (BCM_XGS3_L3_INVALID_INDEX == l3cfg->l3c_hw_index)) {
   3387         (ipv6) ?  BCM_XGS3_L3_IP6_CNT(unit)++ : BCM_XGS3_L3_IP4_CNT(unit)++;
   3388     }
   3389 
   3390     return rv;
   3391 }
   3392 /*
   3393  * Function:
   3394  *      _bcm_td3_l3_flex_ent_parse
   3395  * Purpose:
   3396  *      TD3 helper routine used to parse hw flex l3 entry to api format.
   3397  * Parameters:
   3398  *      unit      - (IN) SOC unit number.
   3399  *      mem       - (IN) L3 table memory.
   3400  *      l3cfg     - (IN/OUT) l3 entry key & parse result.
   3401  *      nh_idx    - (IN/OUT) Next hop index.
   3402  *      l3x_entry - (IN) hw buffer.
   3403  * Returns:
   3404  *      void
   3405  */
   3406 int
   3407 _bcm_td3_l3_flex_ent_parse(int unit, soc_mem_t mem, _bcm_l3_cfg_t *l3cfg,
   3408                                         int *nh_idx, void *l3x_entry)
   3409 {
   3410     int ipv6;                     /* Entry is IPv6 flag.         */
   3411     uint32 hit = 0;               /* composite hit = hit_x|hit_y */
   3412     uint32 *buf_p;                /* HW buffer address.          */
   3413     uint32 glp;                   /* Global port. */
   3414     int embedded_nh = FALSE;
   3415     l3_entry_hit_only_x_entry_t hit_x;
   3416     int idx, idx_max, idx_offset, hit_idx_shift;
   3417     soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f};
   3418 
   3419     int     i;
   3420     int     rv;
   3421     uint32  view_id;
   3422     uint32  field_array[128];
   3423     uint32  field_count;
   3424     uint32  action_set;
   3425     uint32  dst_type;
   3426     uint8   data_type;
   3427 
   3428     uint8 process_destination = 0;
   3429     uint8 process_class_id = 0;
   3430     uint8 process_qos = 0;
   3431     uint8 process_fwd_attributes = 0;
   3432     uint8 process_fwd_2_attributes = 0;
   3433     uint8 process_qtag = 0;
   3434     uint8 process_macda = 0;
   3435     uint8 process_l3_if = 0;
   3436     uint8 process_source = 0;
   3437     soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL];
   3438     uint32 num_ffo = 0;
   3439     uint32 data_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS];
   3440     uint32 key_ids[BCM_FLOW_MAX_NOF_LOGICAL_FIELDS];
   3441     uint32 key_cnt = 0;
   3442     uint32 data_cnt = 0;
   3443 
   3444     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   3445     buf_p = (uint32 *)l3x_entry;
   3446 
   3447     /* Reset entry flags */
   3448     l3cfg->l3c_flags = (ipv6) ? BCM_L3_IP6 : 0;
   3449 
   3450     /* Read hit bits */
   3451     idx_max = 1;
   3452     idx_offset = (l3cfg->l3c_hw_index & 0x3);
   3453     hit_idx_shift = 2;
   3454     if (mem == L3_ENTRY_IPV4_MULTICASTm ||
   3455         mem == L3_ENTRY_IPV6_UNICASTm ||
   3456         (mem == L3_ENTRY_DOUBLEm)) {
   3457         idx_max = 2;
   3458         hit_idx_shift = 1;
   3459         idx_offset = (l3cfg->l3c_hw_index & 0x1) << 1;
   3460     } else if ((mem == L3_ENTRY_IPV6_MULTICASTm) ||
   3461                (mem == L3_ENTRY_QUADm)) {
   3462         idx_max = 4;
   3463         hit_idx_shift = 0;
   3464         idx_offset = 0;
   3465     }
   3466 
   3467     if (soc_feature(unit, soc_feature_multi_pipe_mapped_ports)) {
   3468         /* Get info from L3 and next hop table */
   3469         BCM_IF_ERROR_RETURN(
   3470             BCM_XGS3_MEM_READ(unit, L3_ENTRY_HIT_ONLYm,
   3471               (l3cfg->l3c_hw_index >> hit_idx_shift), &hit_x));
   3472 
   3473         hit = 0;
   3474         for (idx = idx_offset; idx < (idx_offset + idx_max); idx++) {
   3475             hit |= soc_mem_field32_get(unit, L3_ENTRY_HIT_ONLYm,
   3476                                        &hit_x, hitf[idx]);
   3477         }
   3478     }
   3479 
   3480     /* Get view id corresponding to the specified flow. */
   3481     if (l3cfg->l3c_flow_handle != 0) {
   3482         BCM_IF_ERROR_RETURN(soc_flow_db_ffo_to_mem_view_id_get(unit,
   3483                           l3cfg->l3c_flow_handle,
   3484                           l3cfg->l3c_flow_option_handle,
   3485                           SOC_FLOW_DB_FUNC_L3_HOST_ID,
   3486                           &view_id));
   3487     }
   3488     else {
   3489         data_type = soc_mem_field32_get(unit, mem, buf_p, DATA_TYPEf);
   3490 
   3491         BCM_IF_ERROR_RETURN(soc_flow_db_mem_to_view_id_get(unit,
   3492                              mem,
   3493                              SOC_FLOW_DB_KEY_TYPE_INVALID,
   3494                              data_type,
   3495                              0,
   3496                              NULL,
   3497                              &view_id));
   3498         /* get the flow handle, function id, option id */
   3499         BCM_IF_ERROR_RETURN(
   3500               soc_flow_db_mem_view_to_ffo_get(unit,
   3501                                          view_id,
   3502                                          SOC_FLOW_DB_MAX_VIEW_FFO_TPL,
   3503                                          ffo,
   3504                                          &num_ffo));
   3505         l3cfg->l3c_flow_handle = ffo[0].flow_handle;
   3506         l3cfg->l3c_flow_option_handle = ffo[0].option_id;
   3507     }
   3508 
   3509     /* Get PDD field list corresponding to the view id. */
   3510     rv = soc_flow_db_mem_view_field_list_get(unit,
   3511                             view_id,
   3512                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
   3513                             128,
   3514                             field_array,
   3515                             &field_count);
   3516     BCM_IF_ERROR_RETURN(rv);
   3517 
   3518     if (SOC_MEM_FIELD_VALID(unit, view_id, HITf)) {
   3519         soc_mem_field32_set(unit, view_id, buf_p, HITf, hit);
   3520     }
   3521 
   3522     for (i=0; i<field_count; i++) {
   3523         switch (field_array[i]) {
   3524             case DESTINATION_ACTION_SETf:
   3525                 process_destination = 1;
   3526                 break;
   3527             case CLASS_ID_ACTION_SETf:
   3528                 process_class_id = 1;
   3529                 break;
   3530             case QOS_ACTION_SETf:
   3531                 process_qos = 1;
   3532                 break;
   3533             case FWD_ATTRIBUTES_ACTION_SETf:
   3534                 process_fwd_attributes = 1;
   3535                 break;
   3536             case FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf:
   3537                 process_fwd_2_attributes = 1;
   3538                 break;
   3539             case QTAG_ACTION_SETf:
   3540                 process_qtag = 1;
   3541                 break;
   3542             case EXTENDED_VIEW_MACDA_ACTION_SETf:
   3543                 process_macda = 1;
   3544                 break;
   3545             case EXTENDED_VIEW_L3_OIF_ACTION_SETf:
   3546                 process_l3_if = 1;
   3547                 break;
   3548             case SOURCE_ACTION_SETf:
   3549                 process_source = 1;
   3550                 break;
   3551             default:
   3552                 break;
   3553         }
   3554     }
   3555 
   3556     if (!process_destination) {
   3557        return BCM_E_INTERNAL;
   3558     }
   3559 
   3560     embedded_nh = process_macda && process_l3_if;
   3561 
   3562     if (hit) {
   3563         l3cfg->l3c_flags |= BCM_L3_HIT;
   3564     }
   3565 
   3566     /* Get priority override flag, and priority. */
   3567     if (process_qos) {
   3568         /* fld->rpe */
   3569         action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3570                      QOS_ACTION_SETf);
   3571         if (soc_format_field32_get(unit, QOS_ACTION_SETfmt,
   3572             &action_set, RPEf)) {
   3573             l3cfg->l3c_flags |= BCM_L3_RPE;
   3574         }
   3575         /* fld->priority */
   3576         l3cfg->l3c_prio = soc_format_field32_get(unit, QOS_ACTION_SETfmt,
   3577             &action_set, PRIf);
   3578     }
   3579 
   3580     /* Get destination discard flag. */
   3581     if (process_fwd_attributes) {
   3582         /* fld->dst_discard*/
   3583         action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3584                      FWD_ATTRIBUTES_ACTION_SETf);
   3585         if (soc_format_field32_get(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
   3586             &action_set, DST_DISCARDf)) {
   3587             l3cfg->l3c_flags |= BCM_L3_DST_DISCARD;
   3588         }
   3589     }
   3590 
   3591     /* Get local addr bit. */
   3592     if (process_fwd_2_attributes) {
   3593         /* fld->local_addr */
   3594         action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3595                      FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETf);
   3596         if (soc_format_field32_get(unit,
   3597             FORWARDING_2_MISC_ATTRIBUTES_ACTION_SETfmt,
   3598             &action_set, LOCAL_ADDRESSf)) {
   3599             l3cfg->l3c_flags |= BCM_L3_HOST_LOCAL;
   3600         }
   3601     }
   3602 
   3603     /* Get classification group id. */
   3604     if (process_class_id) {
   3605         /* fld->class_id */
   3606         l3cfg->l3c_lookup_class =
   3607         soc_mem_field32_get(unit, view_id, buf_p,
   3608                      CLASS_ID_ACTION_SETf);
   3609     }
   3610 
   3611     /* Get virtual router id. */
   3612     /* fld->vrf */
   3613     l3cfg->l3c_vrf = soc_mem_field32_get(unit, view_id, buf_p, VRFf);
   3614 
   3615     if (embedded_nh) {
   3616         uint32 port_addr_max = 0, modid_max  = 0;
   3617 #ifdef BCM_RIOT_SUPPORT
   3618         int dvp = -1;
   3619 #endif
   3620 
   3621         l3cfg->l3c_flags |= BCM_L3_DEREFERENCED_NEXTHOP;
   3622         if (nh_idx) {
   3623             *nh_idx = BCM_XGS3_L3_INVALID_INDEX; /* Embedded NH */
   3624         }
   3625         /* fld->l3_intf */
   3626         l3cfg->l3c_intf = soc_mem_field32_get(unit, view_id, buf_p,
   3627                      EXTENDED_VIEW_L3_OIF_ACTION_SETf);
   3628         if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) {
   3629             BCM_IF_ERROR_RETURN
   3630                 (_bcm_td3_l3_flex_vp_ent_parse(unit, view_id, l3cfg, buf_p));
   3631         } else {
   3632             uint32              mac_action_set[2];
   3633             uint32              mac_field[2];
   3634             uint32 dtype0;
   3635 
   3636             soc_mem_field_get(unit, view_id, buf_p,
   3637                             EXTENDED_VIEW_MACDA_ACTION_SETf, mac_action_set);
   3638 
   3639             /* fld->mac_addr */
   3640             soc_mem_field_get(unit, mem, buf_p, MAC_ADDRf, mac_field);
   3641 
   3642             soc_format_field_get(unit, EXTENDED_VIEW_MACDA_ACTION_SETfmt,
   3643                                    mac_action_set,
   3644                                    MAC_ADDRf, mac_field);
   3645 
   3646             SAL_MAC_ADDR_FROM_UINT32(l3cfg->l3c_mac_addr, mac_field);
   3647 
   3648             action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3649                             DESTINATION_ACTION_SETf);
   3650 
   3651             dtype0 = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3652                                &action_set, DEST_TYPE0f);
   3653 
   3654             /* fld->dest */
   3655             glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3656                                &action_set, DGPPf);
   3657 
   3658             port_addr_max = SOC_PORT_ADDR_MAX(unit) + 1;
   3659             modid_max = SOC_MODID_MAX(unit) + 1;
   3660 
   3661 #ifdef BCM_RIOT_SUPPORT
   3662             if (BCMI_RIOT_IS_ENABLED(unit)) {
   3663                     if (dtype0 == BCMI_TD3_DEST_TYPE0_DVP) {
   3664                         dvp = glp; /*glp already holds the DEST value from earlier call */
   3665                         _bcm_vp_encode_gport(unit, dvp, &(l3cfg->l3c_port_tgid));
   3666                         l3cfg->l3c_modid = 0;
   3667                     }
   3668             }
   3669             if (dvp == -1)
   3670 #endif
   3671             {
   3672                 if (glp & (port_addr_max * modid_max)) {
   3673                     l3cfg->l3c_flags |= BCM_L3_TGID;
   3674                     l3cfg->l3c_port_tgid = glp & BCM_TGID_PORT_TRUNK_MASK(unit);
   3675                     l3cfg->l3c_modid = 0;
   3676                 } else {
   3677                     l3cfg->l3c_port_tgid = glp & SOC_PORT_ADDR_MAX(unit);
   3678                     l3cfg->l3c_modid = (glp / port_addr_max) & SOC_MODID_MAX(unit);
   3679                 }
   3680             }
   3681         }
   3682         if (process_qtag) {
   3683             action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3684                      QTAG_ACTION_SETf);
   3685             /* fld->eh_tag_type */
   3686             l3cfg->l3c_eh_q_tag_type =
   3687              soc_format_field32_get(unit, QTAG_ACTION_SETfmt,
   3688              &action_set, EH_TAG_TYPEf);
   3689             /* fld->eh_queue_tag */
   3690             l3cfg->l3c_eh_q_tag =
   3691              soc_format_field32_get(unit, QTAG_ACTION_SETfmt,
   3692              &action_set, EH_QUEUE_TAGf);
   3693         }
   3694         /* Get copy_to_cpu bit. */
   3695         /* fld->copy_to_cpu */
   3696         if (process_fwd_attributes) {
   3697             action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3698                      FWD_ATTRIBUTES_ACTION_SETf);
   3699             if (soc_format_field32_get(unit, FWD_ATTRIBUTES_ACTION_SETfmt,
   3700                  &action_set, COPY_TO_CPUf)) {
   3701                 l3cfg->l3c_flags |= BCM_L3_COPY_TO_CPU;
   3702             }
   3703         }
   3704     } else {
   3705        uint32 dtype0, dtype1;
   3706         /* Get next hop info. */
   3707         if (nh_idx) {
   3708 
   3709             action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3710                             DESTINATION_ACTION_SETf);
   3711 
   3712             dtype0 = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3713                                &action_set, DEST_TYPE0f);
   3714 
   3715             /* fld->dest */
   3716             if (dtype0 == BCMI_TD3_DEST_TYPE0_NH) {
   3717                 *nh_idx = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3718                                &action_set, NEXT_HOP_INDEXf);
   3719             }
   3720         }
   3721         dtype1 = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3722                            &action_set, DEST_TYPE1f);
   3723 
   3724         if (dtype1 == BCMI_TD3_DEST_TYPE1_ECMP) {
   3725             /* Mark entry as ecmp */
   3726             l3cfg->l3c_ecmp  = TRUE;
   3727             l3cfg->l3c_flags |= BCM_L3_MULTIPATH;
   3728         } else if (dtype1 == BCMI_TD3_DEST_TYPE1_IPMC){
   3729             /* Mark the flag IPMC */
   3730             l3cfg->l3c_flags |= BCM_L3_IPMC;
   3731             l3cfg->l3c_ipmc_ptr = soc_format_field32_get(unit,
   3732                                DESTINATION_FORMATfmt,
   3733                                &action_set, IPMC_GROUPf);
   3734         } else {
   3735             l3cfg->l3c_ecmp  = FALSE;
   3736             l3cfg->l3c_flags &= ~BCM_L3_MULTIPATH;
   3737             l3cfg->l3c_flags &= ~BCM_L3_IPMC;
   3738             l3cfg->l3c_ipmc_ptr = FALSE;
   3739         }
   3740     }
   3741 
   3742     if (process_source) {
   3743         action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3744                             SOURCE_ACTION_SETf);
   3745         dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3746                              &action_set,DEST_TYPE0f);
   3747         glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3748                           &action_set, DGPPf);
   3749 
   3750         if (dst_type) {
   3751             if (dst_type == BCMI_TD3_DEST_TYPE0_DGPP) {
   3752                 l3cfg->l3c_port_tgid = glp & SOC_PORT_ADDR_MAX(unit);
   3753                 l3cfg->l3c_modid = (glp / (SOC_PORT_ADDR_MAX(unit) + 1)) & 
   3754                                    SOC_MODID_MAX(unit);
   3755             }
   3756         } else {
   3757             dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3758                              &action_set,DEST_TYPE1f);
   3759             if (!dst_type) {
   3760                 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3761                              &action_set,DEST_TYPE2f);
   3762                 if (dst_type == BCMI_TD3_DEST_TYPE2_LAG) {  
   3763                     l3cfg->l3c_flags |= BCM_L3_TGID;
   3764                     l3cfg->l3c_port_tgid = glp & BCM_TGID_PORT_TRUNK_MASK(unit);
   3765                     l3cfg->l3c_modid = 0;
   3766                 }
   3767             }
   3768         }
   3769     }
   3770     l3cfg->l3c_num_of_fields = 0;
   3771     BCM_IF_ERROR_RETURN(
   3772            soc_flow_db_mem_view_field_list_get(unit,
   3773                             view_id,
   3774                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY,
   3775                             BCM_FLOW_MAX_NOF_LOGICAL_FIELDS,
   3776                             key_ids,
   3777                             &key_cnt));
   3778 
   3779     if (key_cnt) {
   3780         for (i = 0;
   3781              (i <  key_cnt) ; i++) {
   3782             l3cfg->l3c_logical_fields[i].id =  key_ids[i];
   3783             l3cfg->l3c_logical_fields[i].value =
   3784                          soc_mem_field32_get(unit, view_id, buf_p,
   3785                          key_ids[i]);
   3786 
   3787         }
   3788         l3cfg->l3c_num_of_fields = key_cnt;
   3789     }
   3790     BCM_IF_ERROR_RETURN(
   3791            soc_flow_db_mem_view_field_list_get(unit,
   3792                       view_id,
   3793                       SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   3794                       BCM_FLOW_MAX_NOF_LOGICAL_FIELDS, data_ids, &data_cnt));
   3795     if (data_cnt) {
   3796         /* Entry traverse */
   3797         for ( ;
   3798              ((i < data_cnt) &&
   3799               ( i < SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA));
   3800               i++) {
   3801             l3cfg->l3c_logical_fields[i].id = data_ids[i];
   3802             l3cfg->l3c_logical_fields[i].value =
   3803                          soc_mem_field32_get(unit, view_id, buf_p,
   3804                          data_ids[i]);
   3805         }
   3806         l3cfg->l3c_num_of_fields += data_cnt;
   3807     }
   3808 
   3809     if (process_source) {
   3810         action_set = soc_mem_field32_get(unit, view_id, buf_p,
   3811                             SOURCE_ACTION_SETf);
   3812         dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3813                              &action_set,DEST_TYPE0f);
   3814         glp = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3815                           &action_set, DGPPf);
   3816 
   3817         if (dst_type) {
   3818             if (dst_type == BCMI_TD3_DEST_TYPE0_DGPP) {
   3819                 l3cfg->l3c_port_tgid = glp & SOC_PORT_ADDR_MAX(unit);
   3820                 l3cfg->l3c_modid = (glp / (SOC_PORT_ADDR_MAX(unit) + 1)) & 
   3821                                    SOC_MODID_MAX(unit);
   3822             }
   3823         } else {
   3824             dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3825                              &action_set,DEST_TYPE1f);
   3826             if (!dst_type) {
   3827                 dst_type = soc_format_field32_get(unit, DESTINATION_FORMATfmt,
   3828                              &action_set,DEST_TYPE2f);
   3829                 if (dst_type == BCMI_TD3_DEST_TYPE2_LAG) {  
   3830                     l3cfg->l3c_flags |= BCM_L3_TGID;
   3831                     l3cfg->l3c_port_tgid = glp & BCM_TGID_PORT_TRUNK_MASK(unit);
   3832                     l3cfg->l3c_modid = 0;
   3833                 }
   3834             }
   3835         }
   3836     }
   3837     return BCM_E_NONE;
   3838 }
   3839 /*
   3840  * Function:
   3841  *      _bcm_td3_l3_flex_entry_del
   3842  * Purpose:
   3843  *      Delete an flex entry from TD3 L3 host table.
   3844  * Parameters:
   3845  *      unit     - (IN) SOC unit number.
   3846  *      l3cfg    - (IN/OUT) L3 entry  lookup key & search result.
   3847  *      nh_index - (IN/OUT) Next hop index.
   3848  * Returns:
   3849  *      BCM_E_XXX
   3850  */
   3851 int
   3852 _bcm_td3_l3_flex_entry_del(int unit, _bcm_l3_cfg_t *l3cfg)
   3853 {
   3854     int ipv6;                     /* IPv6 entry indicator. */
   3855     soc_mem_t view_id;            /* L3 table memory view. */
   3856     soc_flow_db_mem_view_info_t mem_view_info;
   3857     int rv = BCM_E_NONE;          /* Operation status.     */
   3858     uint32 buf_entry[SOC_MAX_MEM_WORDS];    /* Entry buffer ptrs    */
   3859 #if 0
   3860     l3_entry_ipv4_unicast_entry_t l3v4_entry;       /* IPv4 */
   3861     l3_entry_ipv4_multicast_entry_t l3v4_ext_entry;   /* IPv4-Embedded */
   3862     l3_entry_ipv6_unicast_entry_t l3v6_entry;       /* IPv6 */
   3863     l3_entry_ipv6_multicast_entry_t l3v6_ext_entry;   /* IPv6-Embedded */
   3864 #endif
   3865     int macda_oui_profile_index = -1;
   3866     int vntag_etag_profile_index = 0;
   3867     int ref_count = 0;
   3868 
   3869     /* Get entry type. */
   3870     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   3871 
   3872     /* Get view id corresponding to the specified flow. */
   3873     rv = soc_flow_db_ffo_to_mem_view_id_get(unit,
   3874                           l3cfg->l3c_flow_handle,
   3875                           l3cfg->l3c_flow_option_handle,
   3876                           SOC_FLOW_DB_FUNC_L3_HOST_ID,
   3877                           (uint32 *) &view_id);
   3878     BCM_IF_ERROR_RETURN(rv);
   3879 
   3880     rv = soc_flow_db_mem_view_info_get(unit,
   3881                           view_id,
   3882                           &mem_view_info);
   3883 
   3884     BCM_IF_ERROR_RETURN(rv);
   3885 
   3886     sal_memset(buf_entry, 0, SOC_MAX_MEM_WORDS * sizeof(uint32));
   3887 
   3888     /* Initialize control field list for this view id. */
   3889     rv = soc_flow_db_mem_view_entry_init(unit, view_id, buf_entry);
   3890 
   3891     BCM_IF_ERROR_RETURN(rv);
   3892 
   3893     /* Prepare lookup key. */
   3894     BCM_IF_ERROR_RETURN(_bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, buf_entry));
   3895 
   3896     rv = soc_mem_delete(unit, view_id, MEM_BLOCK_ANY, (void*) buf_entry);
   3897 
   3898     if (rv >= 0) {
   3899         (ipv6) ?  BCM_XGS3_L3_IP6_CNT(unit)-- : BCM_XGS3_L3_IP4_CNT(unit)--;
   3900     }
   3901 
   3902     if ((BCM_E_NOT_FOUND == rv) &&
   3903         (soc_feature(unit, soc_feature_l3_extended_host_entry))) {
   3904         /* Delete from  the extended tables only if the extended host entry
   3905          * feature is supported and if the entry was not found in the
   3906          * regular host entry */
   3907 
   3908         if (BCM_L3_BK_FLAG_GET(unit, BCM_L3_BK_ENABLE_MACDA_OUI_PROFILE)) {
   3909             BCM_IF_ERROR_RETURN
   3910             (_bcm_td3_flex_get_extended_profile_index(unit, view_id, l3cfg,
   3911                                                 &macda_oui_profile_index,
   3912                                                 &vntag_etag_profile_index,
   3913                                                 &ref_count));
   3914        }
   3915 
   3916         BCM_IF_ERROR_RETURN
   3917             (_bcm_td3_l3_flex_vp_entry_del(unit, l3cfg,
   3918                                      macda_oui_profile_index,
   3919                                      vntag_etag_profile_index));
   3920     }
   3921 
   3922     return rv;
   3923 }
   3924 
   3925 int
   3926 _bcm_td3_l3_flex_entry_flags_cmp(int unit, int req_flags, int ent_flags, int *idx)
   3927 {
   3928     /* If protocol doesn't match skip the entry. */
   3929     if (req_flags & BCM_L3_IP6) {
   3930         if (!(ent_flags & BCM_L3_IP6)) {
   3931             return (BCM_L3_CMP_NOT_EQUAL);
   3932         }
   3933     } else if (ent_flags & BCM_L3_IP6) {
   3934 #ifdef BCM_FIREBOLT_SUPPORT
   3935         BCM_XGS3_INC_IF_FIREBOLT(unit, (*idx));
   3936 #endif /* BCM_FIREBOLT_SUPPORT */
   3937         return (BCM_L3_CMP_NOT_EQUAL);
   3938     }
   3939 
   3940     /* Check ipmc flag.
   3941       Do not exit on mismatch for L3 host IPMC */
   3942     if ((!(req_flags & BCM_L3_IPMC)) && (ent_flags & BCM_L3_IPMC)) {
   3943 #ifdef BCM_FIREBOLT_SUPPORT
   3944         if (req_flags & BCM_L3_IP6) {
   3945             BCM_XGS3_INC_IF_FIREBOLT(unit, (*idx));
   3946         }
   3947 #endif /* BCM_FIREBOLT_SUPPORT */
   3948     }
   3949     return (BCM_L3_CMP_EQUAL);
   3950 }
   3951 
   3952 /*
   3953  * Function:
   3954  *      _bcm_td3_l3_clear_hit
   3955  * Purpose:
   3956  *      Clear hit bit on flex l3 entry
   3957  * Parameters:
   3958  *      unit      - (IN)SOC unit number.
   3959  *      mem       - (IN)L3 table memory.
   3960  *      l3cfg     - (IN)l3 entry info.
   3961  *      l3x_entry - (IN)l3 entry filled hw buffer.
   3962  * Returns:
   3963  *      BCM_E_XXX
   3964  */
   3965 STATIC int
   3966 _bcm_td3_l3_clear_hit(int unit, soc_mem_t mem, _bcm_l3_cfg_t *l3cfg,
   3967                                    void *l3x_entry, int l3_entry_idx)
   3968 {
   3969     int ipv6;                     /* Entry is IPv6 flag.      */
   3970     int mcast;                    /* Entry is multicast flag. */
   3971     uint32 *buf_p;                /* HW buffer address.       */
   3972     soc_field_t hitf[] = { HIT_0f, HIT_1f, HIT_2f, HIT_3f };
   3973     int idx;
   3974 
   3975     /* Input parameters check */
   3976     if ((NULL == l3cfg) || (NULL == l3x_entry)) {
   3977         return (BCM_E_PARAM);
   3978     }
   3979 
   3980     /* Get entry type. */
   3981     ipv6 = (l3cfg->l3c_flags & BCM_L3_IP6);
   3982     mcast = (l3cfg->l3c_flags & BCM_L3_IPMC);
   3983 
   3984     /* Init memory pointers. */
   3985     buf_p = (uint32 *)l3x_entry;
   3986 
   3987     /* If entry was not hit  there is nothing to clear */
   3988     if (!(l3cfg->l3c_flags & BCM_L3_HIT)) {
   3989         return (BCM_E_NONE);
   3990     }
   3991 
   3992     /* Reset hit bit. */
   3993     soc_mem_field32_set(unit, mem, buf_p, HITf, 0);
   3994 
   3995     if (ipv6 && mcast) {
   3996         /* IPV6 multicast entry hit reset. */
   3997         for (idx = 0; idx < 4; idx++) {
   3998             soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0);
   3999         }
   4000     } else if (ipv6 || mcast) {
   4001         /* Reset IPV6 unicast and IPV4 multicast hit bits. */
   4002         for (idx = 0; idx < 2; idx++) {
   4003             soc_mem_field32_set(unit, mem, buf_p, hitf[idx], 0);
   4004         }
   4005     }
   4006 
   4007     /* Write entry back to hw. */
   4008     return BCM_XGS3_MEM_WRITE(unit, mem, l3_entry_idx, buf_p);
   4009 }
   4010 /*
   4011  * Function:
   4012  *      _bcm_td3_l3_flex_entry_get
   4013  * Purpose:
   4014  *      Get an flex entry from TD3 L3 host table.
   4015  * Parameters:
   4016  *      unit     - (IN) SOC unit number.
   4017  *      l3cfg    - (IN/OUT) L3 entry  lookup key & search result.
   4018  *      nh_index - (IN/OUT) Next hop index.
   4019  *      embd     - (OUT) If TRUE, entry was found as embedded NH.
   4020  * Returns:
   4021  *      BCM_E_XXX
   4022  */
   4023 int
   4024 _bcm_td3_l3_flex_entry_get(int unit, _bcm_l3_cfg_t *l3cfg, int *nh_idx, int *embd)
   4025 {
   4026     int clear_hit;                              /* Clear hit bit.           */
   4027     int rv = BCM_E_NONE;                        /* Operation return status. */
   4028     uint32 buf_key[SOC_MAX_MEM_WORDS];          /* Key buffer ptr*/
   4029     uint32 buf_entry[SOC_MAX_MEM_WORDS];        /* Entry buffer ptr*/
   4030     uint32 view_id;
   4031     soc_flow_db_mem_view_info_t mem_view_info;
   4032 
   4033     /* Indexed NH entry */
   4034     *embd = _BCM_TD3_HOST_ENTRY_NOT_FOUND;
   4035 
   4036     /* Preserve clear_hit value. */
   4037     clear_hit = l3cfg->l3c_flags & BCM_L3_HIT_CLEAR;
   4038 
   4039     /* Get view id corresponding to the specified flow. */
   4040     rv = soc_flow_db_ffo_to_mem_view_id_get(unit,
   4041                           l3cfg->l3c_flow_handle,
   4042                           l3cfg->l3c_flow_option_handle,
   4043                           SOC_FLOW_DB_FUNC_L3_HOST_ID,
   4044                           &view_id);
   4045     BCM_IF_ERROR_RETURN(rv);
   4046 
   4047     /* Get mem id corresponding to the view_id . */
   4048     rv = soc_flow_db_mem_view_info_get(unit,
   4049                           view_id,
   4050                           &mem_view_info);
   4051 
   4052     BCM_IF_ERROR_RETURN(rv);
   4053 
   4054     sal_memset(buf_key, 0, SOC_MAX_MEM_WORDS * sizeof(uint32));
   4055 
   4056     /* Initialize control field list for this view id. */
   4057     rv = soc_flow_db_mem_view_entry_init(unit, view_id, buf_key);
   4058 
   4059     BCM_IF_ERROR_RETURN(rv);
   4060 
   4061     /* Prepare lookup key. */
   4062     BCM_IF_ERROR_RETURN(_bcm_td3_l3_flex_ent_init(unit, view_id, l3cfg, buf_key));
   4063 
   4064     /* Perform lookup */
   4065     rv = soc_mem_generic_lookup(unit, view_id, MEM_BLOCK_ANY,
   4066                                 _BCM_TD3_L3_MEM_BANKS_ALL,
   4067                                 buf_key, buf_entry, &l3cfg->l3c_hw_index);
   4068     if (BCM_SUCCESS(rv)) {
   4069         /* Indexed NH entry */
   4070         *embd = FALSE;
   4071         /* Extract entry info. */
   4072         BCM_IF_ERROR_RETURN(_bcm_td3_l3_flex_ent_parse(unit,
   4073                                                   mem_view_info.mem, l3cfg,
   4074                                                   nh_idx, buf_entry));
   4075         /* Clear the HIT bit */
   4076         if (clear_hit) {
   4077             BCM_IF_ERROR_RETURN(_bcm_td3_l3_clear_hit(unit, view_id,
   4078                                        l3cfg, buf_entry, l3cfg->l3c_hw_index));
   4079         }
   4080     }
   4081 
   4082     return rv;
   4083 }
   4084 
   4085 /*
   4086  * Function:
   4087  *       _bcm_td3_mpls_vc_and_swap_flex_table_reset
   4088  * Purpose:
   4089  *       Reset  VC_AND_SWAP_TABLE entry
   4090  * Parameters:
   4091  *           IN :  Unit
   4092  *           IN : vc_swap_index
   4093  * Returns:
   4094  *            BCM_E_XXX
   4095  */
   4096 STATIC int
   4097 _bcm_td3_mpls_vc_and_swap_flex_table_index_reset (int unit, int vc_swap_index)
   4098 {
   4099     egr_mpls_vc_and_swap_label_table_entry_t  vc_entry;
   4100     int rv = BCM_E_NONE;
   4101     _bcm_tr_mpls_bookkeeping_t *mpls_info = MPLS_INFO(unit);
   4102     int num_vc;
   4103 
   4104     /* Entry 0 is reserved with _bcm_tr_mpls_default_entry_setup during init */
   4105     if (vc_swap_index == VC_AND_SWAP_TABLE_RESV_INDEX) {
   4106         LOG_INFO(BSL_LS_BCM_L3,
   4107                  (BSL_META_U(unit,"Not resetting reserved index: %d in "
   4108                          "VC AND SWAP TABLE\n"), 0));
   4109         return BCM_E_NONE;
   4110     }
   4111     if ( mpls_info->vc_swap_ref_count[vc_swap_index] != 0 ) {
   4112          return BCM_E_NONE;
   4113     }
   4114 
   4115     num_vc = soc_mem_index_count(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm);
   4116     num_vc /= 2;
   4117 
   4118     if (vc_swap_index >= num_vc) {
   4119         _BCM_MPLS_VC_NON_COUNT_USED_CLR(unit, vc_swap_index - num_vc);
   4120     } else {
   4121         _BCM_MPLS_VC_COUNT_USED_CLR(unit, vc_swap_index);
   4122     }
   4123 
   4124     sal_memset(&vc_entry, 0,
   4125               sizeof(egr_mpls_vc_and_swap_label_table_entry_t));
   4126 
   4127     rv = soc_mem_write(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   4128               MEM_BLOCK_ALL, vc_swap_index,
   4129               &vc_entry);
   4130 
   4131     
   4132 
   4133     return rv;
   4134 }
   4135 /*
   4136  * Function:
   4137  *       _bcm_td3_mpls_vc_and_swap_table_flex_entry_set
   4138  * Purpose:
   4139  *       Set  VC_AND_SWAP_TABLE entry
   4140  * Parameters:
   4141  *       IN : Unit
   4142  *       IN : egress object
   4143  *       IN : View ID for memory
   4144  *       IN : label action
   4145  *       IN : vc_swap entry
   4146  *       IN : hw_map_idx: qos map table
   4147  *       IN : vc_swap_index
   4148  * Returns:
   4149  *            BCM_E_XXX
   4150  */
   4151 STATIC int
   4152 _bcm_td3_mpls_vc_and_swap_table_flex_entry_set (int unit,
   4153                                        bcm_l3_egress_t *egr_obj,
   4154                                         soc_mem_t view_id,
   4155                                        int label_action,
   4156                                        egr_mpls_vc_and_swap_label_table_entry_t *vc_entry,
   4157                                        int hw_map_idx, int vc_swap_index)
   4158 {
   4159     int rv;
   4160     bcm_mpls_label_t mpls_label = BCM_MPLS_LABEL_INVALID;
   4161     uint8 mpls_ttl = 0;
   4162     uint32 mpls_flags = 0;
   4163     uint8 mpls_exp = 0;
   4164     uint8 mpls_pkt_pri = 0;
   4165     uint8 mpls_pkt_cfi = 0;
   4166 
   4167     uint32  flex_data_array[128];
   4168     uint32  flex_data_count;
   4169     uint32  opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
   4170     uint32  opaque_count;
   4171     bcm_flow_logical_field_t* user_fields;
   4172     uint32  mpls_hdr;
   4173 
   4174     int i;
   4175     uint32 action_set = 0;
   4176     uint8 process_mpls_entry = 0;
   4177     uint8 process_label = 0;
   4178 
   4179     if (egr_obj == NULL) {
   4180         return BCM_E_PARAM;
   4181     }
   4182 
   4183     mpls_label = egr_obj->mpls_label;
   4184     mpls_ttl = egr_obj->mpls_ttl;
   4185     mpls_flags = egr_obj->mpls_flags;
   4186     mpls_pkt_pri = egr_obj->mpls_pkt_pri;
   4187     mpls_pkt_cfi = egr_obj->mpls_pkt_cfi;
   4188     mpls_exp = egr_obj->mpls_exp;
   4189 
   4190     if ((mpls_exp > 7) || (mpls_pkt_pri > 7) ||
   4191         (mpls_pkt_cfi > 1)) {
   4192         return BCM_E_PARAM;
   4193     }
   4194 
   4195     sal_memset(vc_entry, 0,
   4196                sizeof(egr_mpls_vc_and_swap_label_table_entry_t));
   4197 
   4198     /* Initialize control field list for this view id. */
   4199     rv = soc_flow_db_mem_view_entry_init(unit, view_id, (uint32 *) vc_entry);
   4200 
   4201     BCM_IF_ERROR_RETURN(rv);
   4202 
   4203     /* Get logical field list for this view id. */
   4204     rv = soc_flow_db_mem_view_field_list_get(unit,
   4205                             view_id,
   4206                             SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   4207                             _BCM_FLOW_LOGICAL_FIELD_MAX,
   4208                             opaque_array,
   4209                             &opaque_count);
   4210     BCM_IF_ERROR_RETURN(rv);
   4211 
   4212     user_fields = egr_obj->logical_fields;
   4213 
   4214     for (i=0; i<opaque_count; i++) {
   4215         if (user_fields[i].id == opaque_array[i]) {
   4216             soc_mem_field32_set(unit, view_id, vc_entry, user_fields[i].id,
   4217                                 user_fields[i].value);
   4218         }
   4219     }
   4220 
   4221     /* Get PDD field list corresponding to the view id. */
   4222     rv = soc_flow_db_mem_view_field_list_get(unit,
   4223                             view_id,
   4224                             SOC_FLOW_DB_FIELD_TYPE_POLICY_DATA,
   4225                             128,
   4226                             flex_data_array,
   4227                             &flex_data_count);
   4228     BCM_IF_ERROR_RETURN(rv);
   4229 
   4230     for (i=0; i<flex_data_count; i++) {
   4231         switch (flex_data_array[i]) {
   4232             case MPLS_ENTRY_0_ACTION_SETf:
   4233                 process_mpls_entry = 1;
   4234                 break;
   4235             case SD_TAG_ACTION_SETf:
   4236                 break;
   4237             case DIRECT_ASSIGNMENT_21_ACTION_SETf:
   4238                 process_label = 1;
   4239                 break;
   4240             default:
   4241                 break;
   4242         }
   4243     }
   4244 
   4245     if (process_mpls_entry) {
   4246         action_set = 0;
   4247         if (_BCM_MPLS_EGRESS_LABEL_PRESERVE(unit, mpls_flags)) {
   4248                 /* set label select to 1 to get label from metadata */
   4249                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4250                                     &action_set, LABEL_SELECTf,
   4251                                     1);
   4252                 /* CANCUN has fixed the container 1 for swap to self */
   4253                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4254                                     &action_set, CONTAINER_IDf,
   4255                                     1);
   4256                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4257                                     &action_set, MPLS_PUSH_ACTIONf,
   4258                                     _BCM_MPLS_ACTION_PUSH);
   4259                 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] =
   4260                     _BCM_MPLS_ACTION_PRESERVED;
   4261         } else {
   4262             if (BCM_XGS3_L3_MPLS_LBL_VALID(mpls_label)) {
   4263                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4264                                     &action_set, MPLS_LABELf,
   4265                                     mpls_label);
   4266                 MPLS_INFO(unit)->egr_vc_swap_lbl_action[vc_swap_index] =
   4267                             label_action;
   4268                 if (label_action == _BCM_MPLS_ACTION_SWAP) {
   4269                     /*VC SWAP HW Tbl supports Label actions NOOP,PUSH in TD3.
   4270                      *Record software defined label actions in software
   4271                      *state to reuse existing code for L3MPLS*/
   4272                     label_action =  _BCM_MPLS_ACTION_PUSH;
   4273                 }
   4274                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4275                                     &action_set, MPLS_PUSH_ACTIONf,
   4276                                     _BCM_MPLS_ACTION_PUSH);
   4277             } else {
   4278                 soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4279                                     &action_set, MPLS_PUSH_ACTIONf,
   4280                                     _BCM_MPLS_ACTION_NOOP);
   4281             }
   4282         }
   4283 
   4284         if (mpls_flags & BCM_MPLS_EGRESS_LABEL_TTL_SET) {
   4285             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4286                                 &action_set, MPLS_TTLf,
   4287                                 mpls_ttl);
   4288         } else {
   4289             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4290                                 &action_set, MPLS_TTLf,
   4291                                 0x0);
   4292         }
   4293 
   4294         if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
   4295             (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
   4296 
   4297             if ((mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) ||
   4298                 (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ||
   4299                 (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_REMARK)) {
   4300                 return  BCM_E_PARAM;
   4301             }
   4302             /* Use the specified EXP, PRI and CFI */
   4303             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4304                                 &action_set, MPLS_EXP_SELECTf,
   4305                                 0x0); /* USE_FIXED */
   4306             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4307                                 &action_set, MPLS_EXPf,
   4308                                 mpls_exp);
   4309             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4310                                 &action_set, NEW_PRIf,
   4311                                 mpls_pkt_pri);
   4312             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4313                                 &action_set, NEW_CFIf,
   4314                                 mpls_pkt_cfi);
   4315         } else if (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
   4316             if (mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET) {
   4317                 return BCM_E_PARAM;
   4318             }
   4319             /* Use EXP-map for EXP, PRI and CFI */
   4320             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4321                                 &action_set, MPLS_EXP_SELECTf,
   4322                                 0x1); /* USE_MAPPING */
   4323             soc_format_field32_set(unit, MPLS_ENTRY_ACTION_SETfmt,
   4324                                 &action_set, MPLS_EXP_MAPPING_PTRf,
   4325                                 hw_map_idx);
   4326         } else if ((label_action != _BCM_MPLS_ACTION_SWAP) &&
   4327                         (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) {
   4328             /* not support for MPLSoGRE flow */
   4329             return BCM_E_PARAM;
   4330         } else if ((label_action == _BCM_MPLS_ACTION_SWAP) &&
   4331                         (mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_COPY) ) {
   4332             /* not support for MPLSoGRE flow */
   4333             return BCM_E_PARAM;
   4334         }
   4335         soc_mem_field32_set(unit, view_id, vc_entry,
   4336                             MPLS_ENTRY_0_ACTION_SETf, action_set);
   4337     }
   4338     if (process_label) {
   4339         mpls_hdr = mpls_label<<12 | mpls_exp<<9 | 1<<8 | mpls_ttl;
   4340         soc_mem_field32_set(unit, view_id, vc_entry,
   4341                             DIRECT_ASSIGNMENT_21_ACTION_SETf, mpls_hdr);
   4342     }
   4343     return BCM_E_NONE;
   4344 }
   4345 /*
   4346  * Function:
   4347  *       _bcm_td3_mpls_gre_label_add
   4348  * Purpose:
   4349  *       Updates MPLSoGRE within VC_AND_SWAP_TABLE for a given EGR_NH Index
   4350  * Parameters:
   4351  *       IN :  Unit
   4352  *       IN :  egr object
   4353  *       IN :  nh_index, available when BCM_L3_REPLACE
   4354  *       IN :  mpls_flags
   4355  * Returns:
   4356  *       BCM_E_XXX
   4357  */
   4358 int
   4359 _bcm_td3_mpls_gre_label_add (int unit, bcm_l3_egress_t *egr, int nh_index, uint32 flags)
   4360 {
   4361     int  rv=BCM_E_NONE;
   4362     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   4363     int      vc_swap_index=-1;
   4364     uint32    view_id;
   4365     egr_l3_next_hop_entry_t egr_nh;
   4366     uint32    nh_entry_type;
   4367     uint32    nh_view_id;
   4368     int       hw_map_idx, num_mpls_map;
   4369     uint32 action_set;
   4370 
   4371     if (egr == NULL) {
   4372         return BCM_E_PARAM;
   4373     }
   4374 
   4375     rv = soc_flow_db_ffo_to_mem_view_id_get(unit,
   4376                           egr->flow_handle,
   4377                           egr->flow_label_option_handle,
   4378                           SOC_FLOW_DB_FUNC_EGRESS_LABEL_ID,
   4379                           &view_id);
   4380     BCM_IF_ERROR_RETURN(rv);
   4381 
   4382     sal_memset(&vc_entry, 0,
   4383             sizeof(egr_mpls_vc_and_swap_label_table_entry_t));
   4384 
   4385     /* Retrieve EGR L3 NHOP Entry from given index */
   4386     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   4387                                       nh_index, &egr_nh));
   4388 
   4389     nh_entry_type =
   4390         soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, &egr_nh, DATA_TYPEf);
   4391 
   4392     rv = soc_flow_db_mem_to_view_id_get(unit,
   4393                          EGR_L3_NEXT_HOPm,
   4394                          SOC_FLOW_DB_KEY_TYPE_INVALID,
   4395                          nh_entry_type,
   4396                          0,
   4397                          NULL,
   4398                          &nh_view_id);
   4399 
   4400     /* Be sure that the existing entry is already setup to
   4401      * egress into an MPLS tunnel. If not, return BCM_E_PARAM.
   4402      */
   4403 
   4404     if (!BCMI_L3_NH_FLEX_VIEW(nh_entry_type)) {
   4405         return BCM_E_PARAM;
   4406     }
   4407 
   4408     if ((egr->mpls_label != BCM_MPLS_LABEL_INVALID) &&
   4409         (flags & BCM_L3_REPLACE)) {
   4410 
   4411         action_set = soc_mem_field32_get(unit, nh_view_id, &egr_nh,
   4412                                NEXT_PTR_ACTION_SETf);
   4413 
   4414         if (soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   4415                                &action_set, NEXT_PTR_TYPEf) !=
   4416                                BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP) {
   4417             /* this entry doesn't have a vc_swap index */
   4418             return BCM_E_PARAM;
   4419         }
   4420         /* Retrieve VC_AND_SWAP_INDEX */
   4421         vc_swap_index = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   4422                                  &action_set, NEXT_PTRf);
   4423 
   4424         if (vc_swap_index == 0) {
   4425 
   4426             BCM_IF_ERROR_RETURN(
   4427                 _bcm_td3_mpls_get_vc_and_swap_flex_table_index(unit,
   4428                     &vc_swap_index));
   4429         } else {
   4430             /* Retrieve VC_AND_SWAP_TABLE entry */
   4431             BCM_IF_ERROR_RETURN(
   4432                 soc_mem_read(unit, view_id,
   4433                      MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
   4434         }
   4435     } else if ((egr->mpls_label == BCM_MPLS_LABEL_INVALID) &&
   4436               (flags & BCM_L3_REPLACE)) {
   4437         rv = _bcm_td3_mpls_gre_label_delete (unit, nh_index, nh_view_id);
   4438         return rv;
   4439     } else {
   4440 
   4441         BCM_IF_ERROR_RETURN(
   4442             _bcm_td3_mpls_get_vc_and_swap_flex_table_index(unit,
   4443                 &vc_swap_index));
   4444     }
   4445     /* Retrieve hardware index for mapping pointer */
   4446     if ((egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_SET) ||
   4447         (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_PRI_SET)) {
   4448         /* Mapping pointer not used */
   4449         hw_map_idx = -1;
   4450     } else {
   4451         num_mpls_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64;
   4452         rv = _egr_qos_id2hw_idx(unit,egr->mpls_qos_map_id,&hw_map_idx);
   4453         if ((rv != BCM_E_NONE) || hw_map_idx < 0 || hw_map_idx >= num_mpls_map) {
   4454             if (egr->mpls_flags & BCM_MPLS_EGRESS_LABEL_EXP_REMARK) {
   4455                 rv = BCM_E_PARAM;
   4456                 goto cleanup;
   4457             } else {
   4458                 hw_map_idx = 0; /* use default */
   4459             }
   4460         }
   4461     }
   4462 
   4463     /* Program the MPLS_VC_AND_SWAP table entry */
   4464     rv = _bcm_td3_mpls_vc_and_swap_table_flex_entry_set(unit, egr, view_id,
   4465                                              _BCM_MPLS_ACTION_PUSH, &vc_entry,
   4466                                              hw_map_idx, vc_swap_index);
   4467     if (rv < 0){
   4468        goto cleanup;
   4469     }
   4470 
   4471     rv = soc_mem_write(unit, view_id,
   4472                    MEM_BLOCK_ALL, vc_swap_index,
   4473                    &vc_entry);
   4474     if (rv < 0){
   4475        goto cleanup;
   4476     }
   4477 /*
   4478     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   4479                         &egr_nh, nh_entry_type_field,
   4480                         entry_type);
   4481 */
   4482 
   4483     action_set = 0;
   4484     soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
   4485                          &action_set, NEXT_PTR_TYPEf,
   4486                          BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP);
   4487     /* VC_AND_SWAP_INDEXf */
   4488     soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
   4489                          &action_set, NEXT_PTRf,
   4490                          vc_swap_index);
   4491     soc_mem_field32_set(unit, nh_view_id, &egr_nh,
   4492                    NEXT_PTR_ACTION_SETf, action_set);
   4493 
   4494     /* Enable HG.L3_bit
   4495     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   4496             &egr_nh, MPLS__HG_L3_OVERRIDEf, 0x1);
   4497     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   4498              &egr_nh, MPLS__HG_MODIFY_ENABLEf, 0x1);
   4499     */
   4500 
   4501     rv = soc_mem_write(unit, nh_view_id,
   4502                        MEM_BLOCK_ALL, nh_index, &egr_nh);
   4503 
   4504     if (rv < 0) {
   4505        goto cleanup;
   4506     }
   4507 #ifdef BCM_WARM_BOOT_SUPPORT
   4508     SOC_CONTROL_LOCK(unit);
   4509     SOC_CONTROL(unit)->scache_dirty = 1;
   4510     SOC_CONTROL_UNLOCK(unit);
   4511 #endif
   4512 
   4513     return rv;
   4514 
   4515 cleanup:
   4516     if (vc_swap_index != -1) {
   4517          _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1);
   4518         /* Free VC_AND_SWAP_LABEL entry */
   4519         (void)_bcm_td3_mpls_vc_and_swap_flex_table_index_reset (unit, vc_swap_index);
   4520     }
   4521     return rv;
   4522 }
   4523 /*
   4524  * Function:
   4525  *		_bcm_td3_mpls_gre_label_get
   4526  * Purpose:
   4527  *		Retrieves the  Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
   4528  * Parameters:
   4529  *		IN :  Unit
   4530  *           IN :  mpls_label
   4531  *           IN :  nh_index
   4532  * Returns:
   4533  *		BCM_E_XXX
   4534  */
   4535 
   4536 int
   4537 _bcm_td3_mpls_gre_label_get (int unit, int vc_swap_index, bcm_l3_egress_t *egr)
   4538 {
   4539     int rv=BCM_E_NONE;
   4540     egr_mpls_vc_and_swap_label_table_entry_t vc_entry;
   4541     uint32 label_action;
   4542     uint32 action_set;
   4543     uint32  opaque_array[_BCM_FLOW_LOGICAL_FIELD_MAX];
   4544     uint32  opaque_count;
   4545     int8    data_type;
   4546     uint32  view_id;
   4547     bcm_flow_logical_field_t* user_fields;
   4548     soc_flow_db_ffo_t ffo[SOC_FLOW_DB_MAX_VIEW_FFO_TPL];
   4549     uint32 num_ffo = 0;
   4550     uint32  mpls_hdr;
   4551     int     i;
   4552 
   4553     if (vc_swap_index != -1) {
   4554         /* Retrieve VC_AND_SWAP_TABLE entry */
   4555         BCM_IF_ERROR_RETURN(
   4556             soc_mem_read(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   4557                          MEM_BLOCK_ALL, vc_swap_index, &vc_entry));
   4558 
   4559         data_type = soc_mem_field32_get(unit,
   4560                          EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, &vc_entry, DATA_TYPEf);
   4561 
   4562         if (data_type == 0) {   /* fixed view */
   4563             egr->mpls_label = BCM_MPLS_LABEL_INVALID;
   4564             return rv;
   4565         }
   4566 
   4567         BCM_IF_ERROR_RETURN(
   4568             soc_flow_db_mem_to_view_id_get(unit,
   4569                              EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm,
   4570                              SOC_FLOW_DB_KEY_TYPE_INVALID,
   4571                              data_type,
   4572                              0,
   4573                              NULL,
   4574                              &view_id));
   4575 
   4576         BCM_IF_ERROR_RETURN(
   4577              soc_flow_db_mem_view_to_ffo_get(unit,
   4578                                          view_id,
   4579                                          SOC_FLOW_DB_MAX_VIEW_FFO_TPL,
   4580                                          ffo,
   4581                                          &num_ffo));
   4582 
   4583         egr->flow_label_option_handle = ffo[0].option_id;
   4584 
   4585         /* Get logical field list for this view id. */
   4586         BCM_IF_ERROR_RETURN(
   4587             soc_flow_db_mem_view_field_list_get(unit,
   4588                                  view_id,
   4589                                  SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA,
   4590                                  _BCM_FLOW_LOGICAL_FIELD_MAX,
   4591                                  opaque_array,
   4592                                  &opaque_count));
   4593 
   4594          user_fields = egr->logical_fields;
   4595 
   4596          for (i=0; i<opaque_count; i++) {
   4597              user_fields[i].id = opaque_array[i];
   4598              user_fields[i].value = soc_mem_field32_get(unit, view_id, &vc_entry, user_fields[i].id);
   4599          }
   4600 
   4601         if (SOC_MEM_FIELD_VALID(unit, view_id, MPLS_ENTRY_0_ACTION_SETf)) {
   4602             egr->mpls_label = BCM_MPLS_LABEL_INVALID;
   4603 
   4604             action_set = soc_mem_field32_get(unit, view_id, &vc_entry,
   4605                                    MPLS_ENTRY_0_ACTION_SETf);
   4606 
   4607             label_action = soc_format_field32_get(unit,
   4608                                     MPLS_ENTRY_ACTION_SETfmt,
   4609                                     &action_set, MPLS_PUSH_ACTIONf);
   4610 
   4611             if (label_action == _BCM_MPLS_ACTION_PUSH) { /* PUSH */
   4612                 egr->flags2 |= BCM_L3_MPLS_GRE_LABEL;
   4613                 egr->mpls_label =
   4614                     soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
   4615                                         &action_set, MPLS_LABELf);
   4616                 egr->mpls_ttl =
   4617                     soc_format_field32_get(unit, MPLS_ENTRY_ACTION_SETfmt,
   4618                                         &action_set, MPLS_TTLf);
   4619                 if (egr->mpls_ttl) {
   4620                     egr->mpls_flags |= BCM_MPLS_EGRESS_LABEL_TTL_SET;
   4621                 }
   4622 
   4623             } else {
   4624                 egr->mpls_label = BCM_MPLS_LABEL_INVALID;
   4625             }
   4626         }
   4627         if (SOC_MEM_FIELD_VALID(unit, view_id, DIRECT_ASSIGNMENT_21_ACTION_SETf)) {
   4628             mpls_hdr = soc_mem_field32_get(unit, view_id, &vc_entry,
   4629                             DIRECT_ASSIGNMENT_21_ACTION_SETf);
   4630             egr->mpls_label = mpls_hdr & 0xfffff;
   4631             egr->mpls_exp = (mpls_hdr >> 20) & 0xf;
   4632             egr->mpls_ttl = (mpls_hdr >> 24) & 0xff;
   4633         }
   4634     } else {
   4635         egr->mpls_label = BCM_MPLS_LABEL_INVALID;
   4636     }
   4637     egr->flags2 |= BCM_L3_MPLS_GRE_LABEL;
   4638 
   4639     return rv;
   4640 }
   4641 /*
   4642  * Function:
   4643  *		_bcm_td3_mpls_gre_label_delete
   4644  * Purpose:
   4645  *		Deletes  Inner_LABEL within VC_AND_SWAP_TABLE for a specific EGR_NH Index
   4646  * Parameters:
   4647  *		IN :  Unit
   4648  *              IN :  nh_index
   4649  *              IN :  view_id
   4650  * Returns:
   4651  *		BCM_E_XXX
   4652  */
   4653 int
   4654 _bcm_td3_mpls_gre_label_delete (int unit, int index, soc_mem_t view_id)
   4655 {
   4656     int rv=BCM_E_NONE;
   4657     int  vc_swap_index=-1;
   4658     egr_l3_next_hop_entry_t egr_nh;
   4659     uint8  entry_type;
   4660     /*int  macda_index=-1;*/
   4661     uint32 action_set;
   4662 
   4663     BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   4664                                       index, &egr_nh));
   4665 
   4666     /* Retrieve  and Verify  ENTRY_TYPE */
   4667     entry_type =
   4668         soc_mem_field32_get(unit, view_id, &egr_nh, DATA_TYPEf);
   4669 
   4670     if (!BCMI_L3_NH_FLEX_VIEW(entry_type)) {
   4671         return BCM_E_PARAM;
   4672     }
   4673 
   4674     /* Don't change the Entry_Type to Normal since this is a flex view */
   4675 
   4676     /* Delete MAC_DA_PROFILE_INDEX
   4677     if (soc_feature(unit, soc_feature_mpls_enhanced)) {
   4678         macda_index =
   4679               soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh,
   4680                                          MPLS__MAC_DA_PROFILE_INDEXf);
   4681     }
   4682 
   4683     if (macda_index != -1) {
   4684         _bcm_mac_da_profile_entry_delete(unit, macda_index);
   4685     }
   4686    */
   4687 
   4688     /* Retrieve VC_AND_SWAP_INDEX */
   4689     action_set = soc_mem_field32_get(unit, view_id, &egr_nh,
   4690                            NEXT_PTR_ACTION_SETf);
   4691 
   4692     if (soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   4693                            &action_set, NEXT_PTR_TYPEf) !=
   4694                            BCMI_TD3_L3_NH_EGR_NEXT_PTR_TYPE_VC_SWAP) {
   4695         /* this entry doesn't have a vc_swap index */
   4696         return BCM_E_PARAM;
   4697     }
   4698     /* Retrieve VC_AND_SWAP_INDEX */
   4699     vc_swap_index = soc_format_field32_get(unit, NEXT_PTR_ACTION_SETfmt,
   4700                              &action_set, NEXT_PTRf);
   4701 
   4702     /* Decrease refcount on table idx */
   4703     _bcm_tr_mpls_vc_and_swap_ref_count_adjust (unit, vc_swap_index, -1);
   4704 
   4705     BCM_IF_ERROR_RETURN
   4706          (_bcm_td3_mpls_vc_and_swap_flex_table_index_reset (unit, vc_swap_index));
   4707 
   4708     vc_swap_index = 0;
   4709     soc_format_field32_set(unit, NEXT_PTR_ACTION_SETfmt,
   4710                              &action_set, NEXT_PTRf,
   4711                              vc_swap_index);
   4712 
   4713     soc_mem_field32_set(unit, view_id, &egr_nh,
   4714                          NEXT_PTR_ACTION_SETf, action_set);
   4715 
   4716     rv = soc_mem_write(unit, view_id,
   4717                        MEM_BLOCK_ALL, index, &egr_nh);
   4718 
   4719 #ifdef BCM_WARM_BOOT_SUPPORT
   4720     SOC_CONTROL_LOCK(unit);
   4721     SOC_CONTROL(unit)->scache_dirty = 1;
   4722     SOC_CONTROL_UNLOCK(unit);
   4723 #endif
   4724 
   4725     return rv;
   4726 }
   4727 
   4728 /*
   4729  * Function:
   4730  *      bcm_td3_ipmc_egr_nh_mac_da_profile_entry_delete
   4731  * Purpose:
   4732  *      Release the MACDA Profile pointed to by this Egress NH entry.
   4733  * Parameters:
   4734  *      unit - SOC device unit number
   4735  *      nh_idx - next hop index
   4736  * Returns:
   4737  *      BCM_E_NONE              Success
   4738  *      BCM_E_XXX               ERROR
   4739  */
   4740 int
   4741 bcm_td3_ipmc_egr_nh_mac_da_profile_entry_delete(int unit, int nh_idx)
   4742 {
   4743     soc_mem_t mem = EGR_L3_NEXT_HOPm;
   4744     egr_l3_next_hop_entry_t  egr_nh;  /* Egress next hop entry. */
   4745     int ent_type;                     /* Entry type */
   4746 
   4747     if (!soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm, L3MC__USE_MAC_DA_PROFILEf)) {
   4748         return BCM_E_NONE;
   4749     }
   4750     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   4751 
   4752     SOC_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, nh_idx, &egr_nh));
   4753 
   4754     if (soc_feature(unit, soc_feature_mem_access_data_type)) {
   4755         ent_type = soc_mem_field32_get(unit, mem, &egr_nh, DATA_TYPEf);
   4756     } else {
   4757         ent_type = soc_mem_field32_get(unit, mem, &egr_nh, ENTRY_TYPEf);
   4758     }
   4759 
   4760     /* check if IPMC entry */
   4761     if ((ent_type == 7) && soc_mem_field32_get(unit, mem, &egr_nh,
   4762         L3MC__USE_MAC_DA_PROFILEf)) {
   4763         uint32 macda_index;
   4764         macda_index = soc_mem_field32_get(unit, mem, &egr_nh,
   4765                             L3MC__MAC_DA_PROFILE_INDEXf);
   4766         BCM_IF_ERROR_RETURN(
   4767             _bcm_mac_da_profile_entry_delete(unit, macda_index));
   4768     }
   4769     return BCM_E_NONE;
   4770 }
   4771 
   4772 int
   4773 bcm_td3_l3_conflict_get(int unit, bcm_l3_key_t *ipkey, bcm_l3_key_t *cf_array,
   4774                         int cf_max, int *cf_count)
   4775 {
   4776     _bcm_l3_cfg_t l3cfg;
   4777     uint32 *bufp;      /* Hardware buffer ptr     */
   4778     soc_mem_t mem;            /* L3 table memory type.   */
   4779     int nh_idx, index, rv = BCM_E_NONE;      /* Operation status.       */
   4780     _bcm_l3_fields_t *fld;    /* L3 table common fields. */
   4781     l3_entry_ipv4_unicast_entry_t l3v4_entry;
   4782     l3_entry_ipv4_multicast_entry_t l3v4_ext_entry;
   4783     l3_entry_ipv6_unicast_entry_t l3v6_entry;
   4784     l3_entry_ipv6_multicast_entry_t l3v6_ext_entry;
   4785     uint8 i, bidx, num_ent;
   4786     uint32 l3_entry[SOC_MAX_MEM_WORDS];
   4787     uint32 ipmc, ipv6, embedded_nh;
   4788     uint32 bucket;
   4789     int num_banks, bank_id;
   4790 
   4791     /*  Make sure module was initialized. */
   4792     if (!BCM_XGS3_L3_INITIALIZED(unit)) {
   4793         return (BCM_E_INIT);
   4794     }
   4795 
   4796     /* Input parameters check. */
   4797     if ((NULL == ipkey) || (NULL == cf_count) ||
   4798         (NULL == cf_array) || (cf_max <= 0)) {
   4799         return (BCM_E_PARAM);
   4800     }
   4801 
   4802     embedded_nh = ipkey->l3k_flags & BCM_L3_DEREFERENCED_NEXTHOP;
   4803     nh_idx = (embedded_nh) ? BCM_XGS3_L3_INVALID_INDEX : 0;
   4804 
   4805     /* Translate lookup key to l3cfg format. */
   4806     BCM_IF_ERROR_RETURN(_bcm_td2_ip_key_to_l3cfg(unit, ipkey, &l3cfg));
   4807 
   4808     /* Get entry type. */
   4809     ipv6 = (l3cfg.l3c_flags & BCM_L3_IP6);
   4810     ipmc = (l3cfg.l3c_flags & BCM_L3_IPMC);
   4811 
   4812     /* Get table memory. */
   4813     BCM_TD3_L3_HOST_TABLE_MEM(unit, l3cfg.l3c_intf, ipv6, mem, nh_idx);
   4814     mem = (ipmc) ? (ipv6 ? L3_ENTRY_QUADm : L3_ENTRY_DOUBLEm) : mem;
   4815     BCM_TD3_L3_HOST_TABLE_FLD(unit, mem, ipv6, fld);
   4816     BCM_TD3_L3_HOST_ENTRY_BUF(ipv6, mem, bufp,
   4817                                     l3v4_entry,
   4818                                     l3v4_ext_entry,
   4819                                     l3v6_entry,
   4820                                     l3v6_ext_entry);
   4821 
   4822     /* Prepare host entry for addition. */
   4823     if (ipmc) {
   4824         /*  Zero entry buffer. */
   4825         sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
   4826                    soc_mem_entry_words(unit,mem) * 4);
   4827         BCM_IF_ERROR_RETURN(_bcm_td2_l3_ipmc_ent_init(unit, bufp, &l3cfg));
   4828     } else {
   4829         BCM_IF_ERROR_RETURN(_bcm_td2_l3_ent_init(unit, mem, &l3cfg, bufp));
   4830     }
   4831 
   4832     *cf_count = 0;
   4833 
   4834     /* Get entries of each banks */
   4835     switch (mem) {
   4836     case L3_ENTRY_SINGLEm:
   4837     case L3_ENTRY_DOUBLEm:
   4838     case L3_ENTRY_QUADm:
   4839         num_ent =  4;
   4840         break;
   4841 
   4842     /* coverity[dead_error_begin] */
   4843     default:
   4844         return BCM_E_PARAM;
   4845     }
   4846 #ifdef BCM_HELIX5_SUPPORT
   4847    if (SOC_IS_HELIX5(unit)) {
   4848        /* Get number of L3 banks */
   4849        SOC_IF_ERROR_RETURN
   4850            (soc_helix5_hash_bank_count_get(unit, mem, &num_banks));
   4851        /* bank 9 and 8 are dedicated L3 banks in HX5 */
   4852        bank_id = 9;
   4853    } else
   4854 #endif /* BCM_HELIX5_SUPPORT */
   4855    {
   4856        /* Get number of L3 banks */
   4857        SOC_IF_ERROR_RETURN
   4858            (soc_trident3_hash_bank_count_get(unit, mem, &num_banks));
   4859        bank_id = 11;
   4860    }
   4861     /* bank 11 to 10 are dedicated L3 banks, 9 to 5 are dedicated, depends on
   4862      * mode how many shared banks are assigned to l3
   4863      */
   4864     for (bidx = bank_id; bidx >= (bank_id - num_banks + 1); bidx--) {
   4865         /* Calculate hash index */
   4866 #ifdef BCM_HELIX5_SUPPORT
   4867         if (SOC_IS_HELIX5(unit)) {
   4868             rv = soc_hx5_hash_bucket_get(unit, mem, bidx, bufp, &bucket);
   4869         } else
   4870 #endif /* BCM_HELIX5_SUPPORT */
   4871         {
   4872             rv = soc_td3_hash_bucket_get(unit, mem, bidx, bufp, &bucket);
   4873         }
   4874         if (SOC_FAILURE(rv)) {
   4875             return rv;
   4876         }
   4877 #ifdef BCM_HELIX5_SUPPORT
   4878         if (SOC_IS_HELIX5(unit)) {
   4879             index = soc_hx5_hash_index_get(unit, mem, bidx, bucket);
   4880         } else
   4881 #endif /* BCM_HELIX5_SUPPORT */
   4882         {
   4883             index = soc_td3_hash_index_get(unit, mem, bidx, bucket);
   4884         }
   4885 
   4886         /* Get conflicting IPs from all HW entries in current bank */
   4887         for (i = 0; (i < num_ent) && (*cf_count < cf_max);) {
   4888             rv = soc_mem_read(unit, mem, COPYNO_ALL, index + i, l3_entry);
   4889             if (SOC_FAILURE(rv)) {
   4890                 return BCM_E_MEMORY;
   4891             }
   4892             if (soc_mem_field32_get(unit, mem, &l3_entry, fld->valid)) {
   4893                 switch(soc_mem_field32_get(unit, mem, &l3_entry, fld->key_type)) {
   4894                 case TD3_L3_HASH_DATA_TYPE_V4UC:
   4895                       l3cfg.l3c_flags = 0;
   4896                       break;
   4897                 case TD3_L3_HASH_DATA_TYPE_V4UC_EXT:
   4898                       l3cfg.l3c_flags = BCM_L3_DEREFERENCED_NEXTHOP;
   4899                       break;
   4900                 case TD3_L3_HASH_DATA_TYPE_V4MC:
   4901                       l3cfg.l3c_flags = BCM_L3_IPMC;
   4902                       break;
   4903                 case TD3_L3_HASH_DATA_TYPE_V6UC:
   4904                       l3cfg.l3c_flags = BCM_L3_IP6;
   4905                       break;
   4906                 case TD3_L3_HASH_DATA_TYPE_V6UC_EXT:
   4907                       l3cfg.l3c_flags = BCM_L3_IP6 | BCM_L3_DEREFERENCED_NEXTHOP;
   4908                       break;
   4909                 case TD3_L3_HASH_DATA_TYPE_V6MC:
   4910                       l3cfg.l3c_flags = BCM_L3_IP6 | BCM_L3_IPMC;
   4911                       break;
   4912                 case TD3_L3_HASH_DATA_TYPE_V4L2MC:
   4913                 case TD3_L3_HASH_DATA_TYPE_V4L2VPMC:
   4914                       l3cfg.l3c_flags = BCM_L3_IPMC | BCM_L3_L2ONLY;
   4915                       break;
   4916                 case TD3_L3_HASH_DATA_TYPE_V6L2MC:
   4917                 case TD3_L3_HASH_KEY_TYPE_V6L2VPMC:
   4918                       l3cfg.l3c_flags = BCM_L3_IP6 | BCM_L3_IPMC | BCM_L3_L2ONLY;
   4919                 default:
   4920                       break;
   4921                 }
   4922                 /* Get host ip address. */
   4923                 rv = _bcm_td2_l3_get_by_idx(unit, NULL, index + i, &l3cfg, &nh_idx);
   4924                 if (BCM_FAILURE(rv)) {
   4925                     continue;
   4926                 }
   4927 
   4928                 BCM_IF_ERROR_RETURN
   4929                     (_bcm_td2_l3cfg_to_ipkey(unit, cf_array + (*cf_count), &l3cfg));
   4930                 if ((++(*cf_count)) >= cf_max) {
   4931                     break;
   4932                 }
   4933             }
   4934             /* increment based upon existing entry */
   4935             i += (mem == L3_ENTRY_QUADm) ? 2 : 1;
   4936         }
   4937 
   4938         /* Stop loop if conflicting IPs got from HW is no less than cf_max. */
   4939         if ((*cf_count) >= cf_max) {
   4940             break;
   4941         }
   4942     }
   4943     return BCM_E_NONE;
   4944 }
   4945 
   4946 
   4947 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   4948 /*
   4949  * Function:
   4950  *      bcm_td3x_l3_ecmp_protected_grp_get
   4951  * Purpose:
   4952  *      Get ecmp group next hop members by index.
   4953  * Parameters:
   4954  *      unit            - (IN)SOC unit number.
   4955  *      ecmp_grp        - (IN)Ecmp group id to read.
   4956  *      ecmp_group_size - (IN)Maximum number of entries to read.
   4957  *      nh_list         - (OUT)Next hop index list.
   4958  * Returns:
   4959  *      BCM_E_XXX
   4960  */
   4961 int
   4962 bcm_td3x_l3_ecmp_protected_grp_get(int unit,
   4963                                    int ecmp_grp,
   4964                                    int ecmp_group_size,
   4965                                    int *nh_list)
   4966 {
   4967     int rv = BCM_E_UNAVAIL;
   4968     int i = 0;
   4969     uint32 alloc_sz = 0;
   4970     soc_esw_ecmp_group_info_t grp_info = {0};
   4971     soc_esw_ecmp_member_info_t *mem_array = NULL;
   4972 
   4973     /* Input parameters sanity check. */
   4974     if ((NULL == nh_list) || (ecmp_group_size < 1)) {
   4975          return (BCM_E_PARAM);
   4976     }
   4977 
   4978     /* Zero all next hop indexes first. */
   4979     sal_memset(nh_list, 0, ecmp_group_size * sizeof(int));
   4980 
   4981     alloc_sz = (ecmp_group_size * sizeof(soc_esw_ecmp_member_info_t));
   4982     mem_array = sal_alloc(alloc_sz, "NH array");
   4983     if (NULL == mem_array) {
   4984         return BCM_E_MEMORY;
   4985     }
   4986 
   4987     sal_memset(mem_array, 0, alloc_sz);
   4988 
   4989     SOC_ESW_ECMP_LOCK(unit);
   4990 
   4991     /* Calculate Base_ptr table index. */
   4992     grp_info.ecmp_grp = ecmp_grp;
   4993     rv = soc_esw_ecmp_protected_grp_get(unit, &grp_info, mem_array);
   4994     if (rv != BCM_E_NONE) {
   4995         goto exit;
   4996     }
   4997 
   4998     for (i = 0; i < ecmp_group_size; i++) {
   4999         nh_list[i] = mem_array[i].nh;
   5000     }
   5001 
   5002 exit:
   5003     if (mem_array != NULL) {
   5004         sal_free(mem_array);
   5005     }
   5006     SOC_ESW_ECMP_UNLOCK(unit);
   5007 
   5008     return rv;
   5009 }
   5010 
   5011 /*
   5012  * Function:
   5013  *      bcm_td3x_l3_ecmp_protected_grp_add
   5014  * Purpose:
   5015  *      Add ecmp group next hop members, or reset ecmp group entry.
   5016  *      NOTE: Function always writes all the entries in ecmp group.
   5017  *            If there is not enough nh indexes - next hops written
   5018  *            in cycle.
   5019  * Parameters:
   5020  *      unit       - (IN)SOC unit number.
   5021  *      ecmp_grp   - (IN)ecmp group id to write.
   5022  *      buf        - (IN)Next hop indexes or NULL for entry reset.
   5023  *      info       - (IN)ECMP additional info
   5024  * Returns:
   5025  *      BCM_E_XXX
   5026  */
   5027 int
   5028 bcm_td3x_l3_ecmp_protected_grp_add(int unit,
   5029                                    int ecmp_grp,
   5030                                    void *buf,
   5031                                    void *info)
   5032 {
   5033     uint32 l3_ecmp_grp_buf[SOC_MAX_MEM_FIELD_WORDS];
   5034     uint32 reg_val, value, alloc_sz;
   5035     int max_grp_size = 0;  /* Maximum ecmp group size.*/
   5036     int old_max_paths = 0;
   5037     int ecmp_idx; /* Ecmp table entry index. */
   5038     int idx; /* Iteration index. */
   5039     int *nh_list; /* Ecmp group nh indexes.  */
   5040     int rv = BCM_E_NONE; /* Operation return value. */
   5041     int entry_type;
   5042     int intf_count = 0;
   5043     int grp_exists = 0;
   5044     uint8 grp_added = 0;
   5045     soc_esw_ecmp_bank_lkup_level_t level;
   5046     _bcm_l3_tbl_op_t data;
   5047     soc_mem_t grp_mem = L3_ECMP_COUNTm;
   5048     int ecmp_table_incr = 0;
   5049     _bcm_l3_ecmp_group_info_t *ecmp_info = info;
   5050     _bcm_l3_ecmp_group_buffer_t *ecmp_buffer = buf;
   5051     ing_l3_next_hop_entry_t ing_nh;
   5052     initial_l3_ecmp_group_entry_t initial_l3_ecmp_group_entry;
   5053     int l3_ecmp_oif_flds[8] = {
   5054         L3_OIF_0f,
   5055         L3_OIF_1f,
   5056         L3_OIF_2f,
   5057         L3_OIF_3f,
   5058         L3_OIF_4f,
   5059         L3_OIF_5f,
   5060         L3_OIF_6f,
   5061         L3_OIF_7f};
   5062     int l3_ecmp_oif_type_flds[8] ={
   5063         L3_OIF_0_TYPEf,
   5064         L3_OIF_1_TYPEf,
   5065         L3_OIF_2_TYPEf,
   5066         L3_OIF_3_TYPEf,
   5067         L3_OIF_4_TYPEf,
   5068         L3_OIF_5_TYPEf,
   5069         L3_OIF_6_TYPEf,
   5070         L3_OIF_7_TYPEf };
   5071 
   5072     soc_esw_ecmp_group_info_t grp_info = {0};
   5073     soc_esw_ecmp_member_info_t *mem_array = NULL;
   5074 
   5075     /* Input parameters check. */
   5076     if (NULL == ecmp_buffer || NULL == ecmp_info ||
   5077         NULL == ecmp_buffer->group_buffer) {
   5078         return (BCM_E_PARAM);
   5079     }
   5080 
   5081     /* Cast input buffer. */
   5082     nh_list = ecmp_buffer->group_buffer;
   5083     max_grp_size = ecmp_info->max_paths;
   5084 
   5085     alloc_sz = (max_grp_size * sizeof(soc_esw_ecmp_member_info_t));
   5086     mem_array = sal_alloc(alloc_sz, "NH array");
   5087     if (NULL == mem_array) {
   5088         return BCM_E_MEMORY;
   5089     }
   5090     sal_memset(mem_array, 0, alloc_sz);
   5091 
   5092     SOC_ESW_ECMP_LOCK(unit);
   5093     for (idx = 0; idx < max_grp_size; idx++) {
   5094         mem_array[idx].nh = nh_list[idx];
   5095     }
   5096 
   5097     if (BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit,
   5098                                                     ecmp_grp), ecmp_grp)) {
   5099         /* Group already exists, get base ptr from group table */
   5100         rv = _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp_grp, NULL, &ecmp_idx);
   5101         _BCM_TD3X_L3_ERR_EXIT(rv);
   5102 
   5103         rv = _bcm_xgs3_ecmp_max_grp_size_get(unit, ecmp_grp,
   5104                                              &old_max_paths);
   5105         _BCM_TD3X_L3_ERR_EXIT(rv);
   5106 
   5107         grp_exists = 1;
   5108     } else {
   5109         /* Get index to the first slot in the ECMP table
   5110          * that can accomodate max_grp_size */
   5111         data.width = ecmp_info->max_paths;
   5112         data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp);
   5113         data.oper_flags = _BCM_L3_SHR_TABLE_TRAVERSE_CONTROL;
   5114         /*
   5115          * we can look into the ecmp_grp index to know if this
   5116          * is overlay entry or underlay entry.
   5117          */
   5118         if (BCMI_L3_ECMP_IS_MULTI_LEVEL(unit)) {
   5119             if (ecmp_grp < BCMI_L3_ECMP_OVERLAY_ENTRIES(unit)) {
   5120 
   5121                 data.oper_flags |= _BCM_L3_SHR_OVERLAY_OBJECT;
   5122             }
   5123         }
   5124         data.entry_index = -1;
   5125         if (ecmp_info->ecmp_flags & BCM_L3_ECMP_OVERLAY) {
   5126             level = socEswEcmpBankLkupLevelOverlay;
   5127         } else {
   5128             level = socEswEcmpBankLkupLevelUnderlay;
   5129         }
   5130         rv = bcm_td3x_l3_ecmp_free_idx_get(unit,
   5131                                            level,
   5132                                            ecmp_info->max_paths,
   5133                                            &ecmp_idx);
   5134         _BCM_TD3X_L3_ERR_EXIT(rv);
   5135 
   5136         data.entry_index = ecmp_idx;
   5137         BCM_XGS3_L3_ENT_REF_CNT_INC(data.tbl_ptr, ecmp_idx, max_grp_size);
   5138         ecmp_table_incr = 1;
   5139     }
   5140 
   5141     soc_esw_ecmp_group_info_t_init(&grp_info);
   5142     grp_info.ecmp_grp = ecmp_grp;
   5143     grp_info.ecmp_member_base = ecmp_idx;
   5144     grp_info.max_paths = max_grp_size;
   5145     grp_info.flags = ecmp_info->ecmp_flags;
   5146     rv = soc_esw_ecmp_protected_grp_add(unit, &grp_info, mem_array);
   5147     _BCM_TD3X_L3_ERR_EXIT(rv);
   5148 
   5149     grp_added = 1;
   5150     if (ecmp_idx != grp_info.ecmp_member_base) {
   5151         if (grp_exists == 1) {
   5152             BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp),
   5153                                         ecmp_idx, old_max_paths);
   5154         }
   5155         ecmp_idx = grp_info.ecmp_member_base;
   5156         BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, ecmp),
   5157                                     ecmp_idx, max_grp_size);
   5158     }
   5159 
   5160     if (BCM_SUCCESS(rv)) {
   5161         /* mode 0 = 512 ecmp groups */
   5162         if (!BCM_XGS3_L3_MAX_ECMP_MODE(unit)) {
   5163             /* Set Max Group Size. */
   5164             sal_memset(l3_ecmp_grp_buf, 0,
   5165                        SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   5166             rv = _bcm_xgs3_l3_ecmp_grp_info_set(unit, (ecmp_grp + 1),
   5167                                                 l3_ecmp_grp_buf,
   5168                                                 NULL, 0,
   5169                                                 max_grp_size, -1, 0,
   5170                                                 ecmp_info->ecmp_flags);
   5171             _BCM_TD3X_L3_ERR_EXIT(rv);
   5172 
   5173             rv = soc_mem_write(unit, grp_mem, MEM_BLOCK_ALL,
   5174                                (ecmp_grp + 1), l3_ecmp_grp_buf);
   5175             _BCM_TD3X_L3_ERR_EXIT(rv);
   5176         }
   5177 
   5178         sal_memset(l3_ecmp_grp_buf,
   5179                    0,
   5180                    SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   5181 
   5182         sal_memset (&initial_l3_ecmp_group_entry,
   5183                     0,
   5184                     sizeof(initial_l3_ecmp_group_entry_t));
   5185 
   5186         for (idx = 0; idx < max_grp_size; idx++) {
   5187             if (!nh_list[idx]) {
   5188                 break;
   5189             }
   5190             if (soc_feature(unit, soc_feature_urpf)) {
   5191                 /* Check if URPF is enabled on device */
   5192                 rv = READ_L3_DEFIP_RPF_CONTROLr(unit, &reg_val);
   5193                 _BCM_TD3X_L3_ERR_EXIT(rv);
   5194 
   5195                 if (reg_val) {
   5196                     if (idx < 8) {
   5197                         rv = soc_mem_read(unit, ING_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   5198                                           nh_list[idx], &ing_nh);
   5199                         _BCM_TD3X_L3_ERR_EXIT(rv);
   5200 
   5201                         entry_type =
   5202                             soc_ING_L3_NEXT_HOPm_field32_get(unit,
   5203                                                              &ing_nh, ENTRY_TYPEf);
   5204 
   5205                         if (entry_type == 0x0) {
   5206                             if (SOC_MEM_FIELD_VALID(unit, ING_L3_NEXT_HOPm,
   5207                                                     L3_OIFf)) {
   5208                                 value = soc_ING_L3_NEXT_HOPm_field32_get(
   5209                                     unit, &ing_nh, L3_OIFf);
   5210                             } else {
   5211                                 value = soc_ING_L3_NEXT_HOPm_field32_get(
   5212                                     unit, &ing_nh, VLAN_IDf);
   5213                             }
   5214                             soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf,
   5215                                                 l3_ecmp_oif_type_flds[idx], entry_type);
   5216                             soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf,
   5217                                                 l3_ecmp_oif_flds[idx], value);
   5218                         } else if (entry_type == 0x1) {
   5219                             value  = soc_ING_L3_NEXT_HOPm_field32_get(unit, &ing_nh, L3_OIFf);
   5220                             soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf,
   5221                                                 l3_ecmp_oif_type_flds[idx], entry_type);
   5222                             soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf,
   5223                                                 l3_ecmp_oif_flds[idx], value);
   5224                         }
   5225                         soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, URPF_COUNTf, idx);
   5226                     } else {
   5227                         /* Inorder to avoid TRAP_TO_CPU, urpf_mode on L3_IIF/PORT must be set
   5228                            to STRICT_MODE / LOOSE_MODE */
   5229                         soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf, ECMP_GT8f , 1);
   5230                     }
   5231                 }
   5232             }
   5233         }
   5234         intf_count = idx;
   5235         rv = _bcm_xgs3_l3_ecmp_grp_info_set(unit, ecmp_grp,
   5236                                             l3_ecmp_grp_buf,
   5237                                             &initial_l3_ecmp_group_entry, TRUE,
   5238                                             intf_count,
   5239                                             ecmp_idx,
   5240                                             ecmp_info->alternate_cnt,
   5241                                             ecmp_info->ecmp_flags);
   5242         _BCM_TD3X_L3_ERR_EXIT(rv);
   5243 
   5244         rv = soc_mem_write(unit, INITIAL_L3_ECMP_GROUPm, MEM_BLOCK_ALL,
   5245                            ecmp_grp, &initial_l3_ecmp_group_entry);
   5246         _BCM_TD3X_L3_ERR_EXIT(rv);
   5247 
   5248         /* Preserve the fields related to resilient hashing */
   5249         if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) {
   5250             ecmp_count_entry_t old_ecmp_count_entry;
   5251             int enhanced_hashing_enable;
   5252             int rh_flow_set_base;
   5253             int rh_flow_set_size;
   5254 
   5255             rv = READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY,
   5256                                      ecmp_grp, &old_ecmp_count_entry);
   5257             _BCM_TD3X_L3_ERR_EXIT(rv);
   5258 
   5259             enhanced_hashing_enable = soc_mem_field32_get(unit, L3_ECMP_COUNTm,
   5260                                                           &old_ecmp_count_entry, LB_MODEf);
   5261             rh_flow_set_base = soc_mem_field32_get(unit, L3_ECMP_COUNTm,
   5262                                                    &old_ecmp_count_entry, RH_FLOW_SET_BASEf);
   5263             rh_flow_set_size = soc_mem_field32_get(unit, L3_ECMP_COUNTm,
   5264                                                    &old_ecmp_count_entry, RH_FLOW_SET_SIZEf);
   5265             soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf,
   5266                                 LB_MODEf, enhanced_hashing_enable);
   5267             soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf,
   5268                                 RH_FLOW_SET_BASEf, rh_flow_set_base);
   5269             soc_mem_field32_set(unit, L3_ECMP_COUNTm, l3_ecmp_grp_buf,
   5270                                 RH_FLOW_SET_SIZEf, rh_flow_set_size);
   5271         }
   5272 
   5273         rv = soc_mem_write(unit, grp_mem, MEM_BLOCK_ALL,
   5274                            ecmp_grp, l3_ecmp_grp_buf);
   5275         _BCM_TD3X_L3_ERR_EXIT(rv);
   5276 
   5277         /* mode 1 = max possible ecmp groups */
   5278         if (BCM_XGS3_L3_MAX_ECMP_MODE(unit)) {
   5279             /* Save the max possible paths for this ECMP group in s/w */
   5280             BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)[ecmp_grp] = ecmp_info->max_paths;
   5281         }
   5282     }
   5283 
   5284     _BCM_TD3X_L3_ERR_EXIT(rv);
   5285 
   5286 exit:
   5287     if (mem_array != NULL) {
   5288         sal_free(mem_array);
   5289     }
   5290     if (rv != BCM_E_NONE) {
   5291         if (ecmp_table_incr == 1) {
   5292             BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp),
   5293                                         ecmp_idx, max_grp_size);
   5294         }
   5295 
   5296         if (grp_added == 1) {
   5297             soc_esw_ecmp_protected_grp_delete(unit, &grp_info);
   5298         }
   5299     }
   5300     SOC_ESW_ECMP_UNLOCK(unit);
   5301     return rv;
   5302 }
   5303 
   5304 
   5305 /*
   5306  * Function:
   5307  *      bcm_td3x_l3_ecmp_protected_grp_del
   5308  * Purpose:
   5309  *      Reset ecmp group next hop members
   5310  * Parameters:
   5311  *      unit       - (IN)SOC unit number.
   5312  *      ecmp_grp   - (IN)ecmp group id to write.
   5313  *      info       - (IN)ECMP additional info
   5314  * Returns:
   5315  *      BCM_E_XXX
   5316  */
   5317 int
   5318 bcm_td3x_l3_ecmp_protected_grp_del(int unit,
   5319                                    int ecmp_grp,
   5320                                    void *info)
   5321 {
   5322     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to write hw entry.*/
   5323     int ecmp_idx = 0; /* Ecmp table entry index. */
   5324     int rv = BCM_E_UNAVAIL; /* Operation return value. */
   5325     int max_ent_count = 0; /* Number of entries to read.*/
   5326     _bcm_l3_tbl_op_t data;
   5327     soc_mem_t mem = L3_ECMP_COUNTm;
   5328     _bcm_l3_ecmp_group_info_t *ecmp_info = info;
   5329     soc_esw_ecmp_group_info_t grp_info = {0};
   5330 
   5331     data.tbl_ptr = BCM_XGS3_L3_TBL_PTR(unit, ecmp);
   5332 
   5333     if (NULL == info) {
   5334         return BCM_E_INTERNAL;
   5335     }
   5336     /* Initialize ecmp entry. */
   5337     sal_memset (hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   5338 
   5339     SOC_ESW_ECMP_LOCK(unit);
   5340 
   5341     rv = _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp_grp, &max_ent_count, &ecmp_idx);
   5342     _BCM_TD3X_L3_ERR_EXIT(rv);
   5343 
   5344     grp_info.ecmp_grp = ecmp_grp;
   5345     rv = soc_esw_ecmp_protected_grp_delete(unit, &grp_info);
   5346 
   5347     /* Decrement ref count for the entries in ecmp table
   5348      * Ref count for ecmp_group table is decremented in common table del func. */
   5349     BCM_XGS3_L3_ENT_REF_CNT_DEC(data.tbl_ptr, ecmp_idx,
   5350                                 ecmp_info->max_paths);
   5351 
   5352     if (SOC_MEM_IS_VALID(unit, mem)) {
   5353         /* Set group base pointer. */
   5354         ecmp_idx = ecmp_grp;
   5355 
   5356         if (SOC_MEM_IS_VALID(unit, INITIAL_L3_ECMP_GROUPm)) {
   5357             rv = soc_mem_write(unit, INITIAL_L3_ECMP_GROUPm, MEM_BLOCK_ALL,
   5358                     ecmp_idx, hw_buf);
   5359 
   5360             _BCM_TD3X_L3_ERR_EXIT(rv);
   5361         }
   5362 
   5363         if (!BCM_XGS3_L3_MAX_ECMP_MODE(unit)) {
   5364             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   5365                     (ecmp_idx + 1), hw_buf);
   5366             _BCM_TD3X_L3_ERR_EXIT(rv);
   5367         }
   5368 
   5369         /* Preserve the fields related to resilient hashing */
   5370         if (soc_feature(unit, soc_feature_ecmp_resilient_hash)) {
   5371             ecmp_count_entry_t old_ecmp_count_entry;
   5372             int enhanced_hashing_enable;
   5373             int rh_flow_set_base;
   5374             int rh_flow_set_size;
   5375 
   5376             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   5377                               ecmp_grp, &old_ecmp_count_entry);
   5378             _BCM_TD3X_L3_ERR_EXIT(rv);
   5379 
   5380             enhanced_hashing_enable = soc_mem_field32_get(unit, mem,
   5381                                                           &old_ecmp_count_entry, LB_MODEf);
   5382             rh_flow_set_base = soc_mem_field32_get(unit, mem,
   5383                                                    &old_ecmp_count_entry, RH_FLOW_SET_BASEf);
   5384             rh_flow_set_size = soc_mem_field32_get(unit, mem,
   5385                                                    &old_ecmp_count_entry, RH_FLOW_SET_SIZEf);
   5386             soc_mem_field32_set(unit, mem, hw_buf,
   5387                                 LB_MODEf, enhanced_hashing_enable);
   5388             soc_mem_field32_set(unit, mem, hw_buf,
   5389                                 RH_FLOW_SET_BASEf, rh_flow_set_base);
   5390             soc_mem_field32_set(unit, mem, hw_buf,
   5391                                 RH_FLOW_SET_SIZEf, rh_flow_set_size);
   5392         }
   5393 
   5394         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   5395                 ecmp_idx, hw_buf);
   5396         _BCM_TD3X_L3_ERR_EXIT(rv);
   5397     }
   5398 
   5399     if (BCM_XGS3_L3_MAX_ECMP_MODE(unit) &&
   5400         BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)) {
   5401         /* Reset max paths of the deleted group */
   5402         BCM_XGS3_L3_MAX_PATHS_PERGROUP_PTR(unit)[ecmp_grp] = 0;
   5403     }
   5404 
   5405 exit:
   5406     SOC_ESW_ECMP_UNLOCK(unit);
   5407     return rv;
   5408 }
   5409 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   5410 
   5411 #ifdef BCM_WARM_BOOT_SUPPORT
   5412 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
   5413 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
   5414 
   5415 /*
   5416  * Function:
   5417  *      _bcm_td3_l3_repl_l3_intf_recover
   5418  * Purpose:
   5419  *      Recover L3 interface bitmap from scache.
   5420  * Parameters:
   5421  *      unit - (IN) SOC unit number.
   5422  * Returns:
   5423  *      BCM_E_XXX
   5424  */
   5425 int
   5426 _bcm_td3_l3_repl_l3_intf_recover(int unit){
   5427     soc_scache_handle_t scache_handle;
   5428     uint8               *ipmc_scache_ptr;
   5429     uint16              recovered_ver;
   5430     uint32 temp_size = 0;
   5431     int num_l3_intf;
   5432     int rv = BCM_E_UNAVAIL;
   5433 
   5434     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   5435     td3_l3_intf_next_hop_ipmc = sal_alloc(SHR_BITALLOCSIZE(num_l3_intf),
   5436                                     "TD3 l3 interface bitmap");
   5437     if (NULL == td3_l3_intf_next_hop_ipmc) {
   5438         return BCM_E_MEMORY;
   5439     }
   5440     sal_memset(td3_l3_intf_next_hop_ipmc, 0, SHR_BITALLOCSIZE(num_l3_intf));
   5441 
   5442 #ifdef BCM_TRIDENT2_SUPPORT
   5443     if (soc_feature(unit, soc_feature_pim_bidir)) {
   5444         BCM_IF_ERROR_RETURN
   5445                 (bcm_td2_ipmc_pim_bidir_scache_size_get(unit, &temp_size));
   5446     }
   5447 #endif /* BCM_TRIDENT2_SUPPORT */
   5448     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_IPMC, 0);
   5449     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   5450                                     0, &ipmc_scache_ptr,
   5451                                     BCM_WB_VERSION_1_5, &recovered_ver);
   5452     if (BCM_SUCCESS(rv)) {
   5453         ipmc_scache_ptr += temp_size;
   5454         if (recovered_ver >= BCM_WB_VERSION_1_1) {
   5455             if (soc_feature(unit, soc_feature_repl_l3_intf_use_next_hop)) {
   5456                 sal_memcpy(td3_l3_intf_next_hop_ipmc, ipmc_scache_ptr,
   5457                                 SHR_BITALLOCSIZE(num_l3_intf));
   5458             }
   5459         }
   5460     }
   5461 
   5462     return rv;
   5463 }
   5464 #endif /* BCM_WARM_BOOT_SUPPORT */
   5465 
   5466 #endif /*(INCLUDE_L3) && (BCM_TRIDENT3_SUPPORT) */