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

proxy.c (18629B)


      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 
      8 
      9 #include <soc/defs.h>
     10 #include <soc/mem.h>
     11 #include <soc/drv.h>
     12 #include <sal/core/libc.h>
     13 #include <sal/core/sync.h>
     14 
     15 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
     16 #include <soc/drv.h>
     17 #include <soc/mem.h>
     18 #include <soc/util.h>
     19 #include <bcm/error.h>
     20 #include <bcm/proxy.h>
     21 #include <bcm/debug.h>
     22 #include <bcm/types.h>
     23 #include <bcm/l3.h>
     24 
     25 #include <bcm_int/esw/port.h>
     26 #include <bcm_int/esw/mbcm.h>
     27 #include <bcm_int/esw/firebolt.h>
     28 #include <bcm_int/api_xlate_port.h>
     29 #include <bcm_int/esw_dispatch.h>
     30 #include <bcm_int/esw/l3.h>
     31 #include <bcm_int/esw/stack.h>
     32 #include <bcm_int/esw/proxy.h>
     33 #include <bcm_int/esw/vlan.h>
     34 
     35 
     36 /*
     37  * Function:
     38  *      _bcm_td2_proxy_flags_to_shr
     39  * Purpose:
     40  *      Translate proxy specific flags to shared (table management) flags. 
     41  * Parameters:
     42  *    proxy_flags   - (IN)  Proxy flags. 
     43  *    shr_flags  - (OUT) Shared flags. 
     44  * Returns:
     45  *    BCM_E_XXX
     46  */
     47 STATIC INLINE int
     48 _bcm_td2_proxy_flags_to_shr(uint32 proxy_flags, uint32 *shr_flags)
     49 {
     50     uint32 flag;
     51 
     52     if (NULL == shr_flags) {
     53         return (BCM_E_PARAM);
     54     }
     55 
     56     if ((proxy_flags == 0) ||  (proxy_flags & (BCM_PROXY_WITH_ID | BCM_PROXY_REPLACE))) {
     57         flag = 0;
     58     } else {
     59         return BCM_E_PARAM;
     60     }
     61 
     62     if (proxy_flags & BCM_PROXY_REPLACE) {
     63        flag |= _BCM_L3_SHR_UPDATE;
     64     }
     65 
     66     if (proxy_flags & BCM_PROXY_WITH_ID) {
     67        flag |= _BCM_L3_SHR_WITH_ID;
     68     }
     69 
     70     *shr_flags = flag;
     71 
     72     return (BCM_E_NONE);
     73 }
     74 
     75 /*
     76  * Function:
     77  *      _bcm_td2_proxy_flags_valid
     78  * Purpose:
     79  *      Check Validity of Proxy Flags
     80  * Parameters:
     81  *    proxy_flags   - (IN)  Proxy flags. 
     82  * Returns:
     83  *    BCM_E_XXX
     84  */
     85 STATIC INLINE int
     86 _bcm_td2_proxy_flags_valid(uint32 proxy_flags)
     87 {
     88     if ((proxy_flags == 0) || 
     89              (proxy_flags & (BCM_PROXY_PACKET_MODIFY | BCM_PROXY_RSVD_VLAN_ADD |
     90                                        BCM_PROXY_LEARN_DISABLE | BCM_PROXY_L3_FORCE |
     91                                        BCM_PROXY_PACKET_DROP))) {
     92         return (BCM_E_NONE);
     93     }
     94     return (BCM_E_PARAM);
     95 }
     96 
     97 
     98 /*
     99  * Function:
    100  *      bcm_td2_proxy_egress_create
    101  * Purpose:
    102  *      Create Proxy Egress forwarding object.
    103  * Parameters:
    104  *      unit    - (IN)  bcm device.
    105  *      flags   - (IN)  BCM_L3_REPLACE: replace existing.
    106  *                      BCM_L3_WITH_ID: intf argument is given.
    107  *      proxy_egr     - (IN) Egress forwarding destination.
    108  *      proxy_intf_id    - (OUT) L3 interface id pointing to Egress object.
    109  *                      This is an IN argument if either BCM_L3_REPLACE
    110  *                      or BCM_L3_WITH_ID are given in flags.
    111  * Returns:
    112  *      BCM_E_XXX
    113  */
    114 int 
    115 bcm_td2_proxy_egress_create(int unit, uint32 flags, bcm_proxy_egress_t *proxy_egr, 
    116                           bcm_if_t *proxy_intf_id)
    117 {
    118     int err_code = BCM_E_UNAVAIL; /* used for L3_IF_ERROR_CLEANUP_ELSE_RETURN */
    119     int index = -1;                 /* Next hop index.     */ 
    120     uint32  shr_flags;              /* Table shared flags. */
    121 
    122     /*  Make sure module was initialized. */
    123     if (!BCM_XGS3_L3_INITIALIZED(unit)) {
    124         return (BCM_E_INIT);
    125     }
    126 
    127     /* Input parameters check. */
    128     if ((NULL == proxy_egr) || (NULL == proxy_intf_id)) {
    129         return (BCM_E_PARAM);
    130     }
    131 
    132     /* Verify egress object range if BCM_PROXY_WITH_ID flag is set. */ 
    133     if (flags & BCM_PROXY_WITH_ID) {
    134         if (!BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, *proxy_intf_id)) {
    135              return (BCM_E_PARAM);
    136         }
    137         if (BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, *proxy_intf_id)) {
    138             index = *proxy_intf_id - BCM_XGS3_PROXY_EGRESS_IDX_MIN(unit);
    139         }
    140     }
    141 
    142     /* Check validity of Proxy_egr flags */ 
    143     BCM_IF_ERROR_RETURN(_bcm_td2_proxy_flags_valid(proxy_egr->flags));
    144 
    145     /* Convert api flags to shared table management flags. */ 
    146     BCM_IF_ERROR_RETURN(_bcm_td2_proxy_flags_to_shr(flags, &shr_flags));
    147 
    148     /* Disable matching entry lookup. */
    149     shr_flags |= _BCM_L3_SHR_MATCH_DISABLE;
    150 
    151     /* Create next hop entry. */
    152     err_code = bcm_xgs3_proxy_nh_add(unit, shr_flags, proxy_egr, &index);
    153 
    154     if (err_code == BCM_E_NONE) {
    155        /* Return BCM_XGS3_PROXY_EGRESS_IDX_MIN(unit) + nh_index for Proxy object*/
    156        *proxy_intf_id = BCM_XGS3_PROXY_EGRESS_IDX_MIN(unit) + index; 
    157     } 
    158     return err_code;
    159 }
    160 
    161 /*
    162  * Function:
    163  *      bcm_td2_proxy_egress_destroy
    164  * Purpose:
    165  *      Destroy Proxy Egress forwarding object.
    166  * Parameters:
    167  *      unit    - (IN) bcm device.
    168  *      intf    - (IN) L3 interface id pointing to Egress object.
    169  * Returns:
    170  *      BCM_E_XXX
    171  */
    172 int 
    173 bcm_td2_proxy_egress_destroy(int unit, bcm_if_t proxy_intf_id)
    174 {
    175     int nh_idx=0;               /* Next hop index.          */
    176     int rv;                   /* Operation return status. */
    177 
    178     /*  Make sure module was initialized. */
    179     if (!BCM_XGS3_L3_INITIALIZED(unit)) {
    180         return (BCM_E_INIT);
    181     }
    182 
    183     /* Input parameters check. */
    184     if (!BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, proxy_intf_id)) {
    185         return (BCM_E_PARAM);
    186     }
    187 
    188     /* Calculate next hop index. */
    189     if (BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, proxy_intf_id)) {
    190         nh_idx = proxy_intf_id - BCM_XGS3_PROXY_EGRESS_IDX_MIN(unit);
    191     }
    192 
    193     /* If entry is used by hosts/routes or ecmp objects - reject deletion */
    194     if(1 < BCM_XGS3_L3_ENT_REF_CNT
    195        (BCM_XGS3_L3_TBL_PTR(unit, next_hop), nh_idx)) {
    196         return (BCM_E_BUSY);
    197     }
    198 
    199     /* Delete next hop entry. */
    200     rv = bcm_xgs3_nh_del(unit, 0, nh_idx);
    201     return (rv);
    202 }
    203 
    204 
    205 /*
    206  * Function:
    207  *      bcm_td2_proxy_egress_get
    208  * Purpose:
    209  *      Get Proxy Egress forwarding object.
    210  * Parameters:
    211  *      unit    - (IN) bcm device.
    212  *      intf    - (IN) L3 interface id pointing to Egress object.
    213  *      egr     - (OUT) Egress forwarding destination.
    214  * Returns:
    215  *      BCM_E_XXX
    216  */
    217 int 
    218 bcm_td2_proxy_egress_get(int unit, bcm_if_t proxy_intf_id, bcm_proxy_egress_t *proxy_egr) 
    219 {
    220     int offset=0;
    221 
    222     /*  Make sure module was initialized. */
    223     if (!BCM_XGS3_L3_INITIALIZED(unit)) {
    224         return (BCM_E_INIT);
    225     }
    226 
    227     /* Input parameters check. */
    228     if ((NULL == proxy_egr) || (!BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, proxy_intf_id))) {
    229         return (BCM_E_PARAM);
    230     }
    231     if (BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, proxy_intf_id)) {
    232         offset = BCM_XGS3_PROXY_EGRESS_IDX_MIN(unit);
    233     } 
    234 
    235     /* Fill next hop entry info. */
    236     BCM_IF_ERROR_RETURN(bcm_xgs3_proxy_nh_get(unit, (proxy_intf_id - offset), proxy_egr));
    237 
    238     return BCM_E_NONE;
    239 }
    240 
    241 
    242 /*
    243  * Function:
    244  *      _bcm_td2_proxy_nh_add
    245  * Purpose:
    246  *      Routine set proxy next hop entry in the chip.
    247  * Parameters:
    248  *      unit      - (IN)SOC unit number.
    249  *      idx       - (IN)Allocated entry index.
    250  *      buf       - (IN)Next hop entry data.
    251  *      info      - (IN)Additional info
    252  * Returns:
    253  *    BCM_E_XXX
    254  */
    255 int
    256 _bcm_td2_proxy_nh_add(int unit, int idx, void *buf, void *info)
    257 {
    258     ing_l3_next_hop_entry_t in_nh_entry;   /* Buffer to read ingress nh entry. */
    259     egr_l3_next_hop_entry_t eg_nh_entry;   /* Buffer to read egress nh entry.  */
    260     bcm_proxy_egress_t *proxy_nh_entry;    /* Next hop entry passed buffer.    */
    261     soc_mem_t mem;                         /* Next hop table memory.           */
    262     soc_field_t acc_type = ENTRY_TYPEf;    /* Field in egress next hop table   */
    263     uint32 drop = 0;
    264     uint32 glp = 0;
    265 
    266     /* Input parameters check */
    267     if (NULL == buf) {
    268         return (BCM_E_PARAM);
    269     }
    270     proxy_nh_entry = (bcm_proxy_egress_t *) buf;
    271 
    272     /* Zero buffers. */
    273     sal_memset(&in_nh_entry, 0, sizeof(ing_l3_next_hop_entry_t));
    274 
    275     glp = (SOC_GPORT_MODPORT_MODID_GET(proxy_nh_entry->gport) << SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS |
    276            SOC_GPORT_MODPORT_PORT_GET(proxy_nh_entry->gport));
    277     mem = INITIAL_ING_L3_NEXT_HOPm;
    278     /* Read ingress next hop entry. */
    279     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &in_nh_entry));
    280     /* Set module id to initial ingress l3 next hop entry. */
    281     if (soc_feature(unit, soc_feature_generic_dest)) {
    282         soc_mem_field32_dest_set(unit, mem, &in_nh_entry, DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, glp);
    283     } else {
    284         soc_mem_field32_set(unit, mem, &in_nh_entry, MODULE_IDf,
    285                             SOC_GPORT_MODPORT_MODID_GET(proxy_nh_entry->gport));
    286         soc_mem_field32_set(unit, mem, &in_nh_entry, Tf, 0);
    287         soc_mem_field32_set(unit, mem, &in_nh_entry, PORT_NUMf,
    288                             SOC_GPORT_MODPORT_PORT_GET(proxy_nh_entry->gport));
    289     }
    290     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, mem, idx, &in_nh_entry));
    291 
    292     /* Zero buffers. */
    293     sal_memset(&in_nh_entry, 0, sizeof(ing_l3_next_hop_entry_t));
    294 
    295     mem = ING_L3_NEXT_HOPm;
    296     /* Read ingress next hop entry. */
    297     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &in_nh_entry));
    298     if (soc_feature(unit, soc_feature_generic_dest)) {
    299         soc_mem_field32_dest_set(unit, mem, &in_nh_entry, DESTINATIONf, SOC_MEM_FIF_DEST_DGPP, glp);
    300     } else {
    301         soc_mem_field32_set(unit, mem, &in_nh_entry, MODULE_IDf,
    302                             SOC_GPORT_MODPORT_MODID_GET(proxy_nh_entry->gport));
    303         soc_mem_field32_set(unit, mem, &in_nh_entry, Tf, 0);
    304         soc_mem_field32_set(unit, mem, &in_nh_entry, PORT_NUMf,
    305                             SOC_GPORT_MODPORT_PORT_GET(proxy_nh_entry->gport));
    306     }
    307     if (soc_mem_field_valid(unit, mem, MTU_SIZEf)) {
    308         soc_mem_field32_set(unit, mem, &in_nh_entry, MTU_SIZEf, 0x3FFF);
    309     }
    310     drop = proxy_nh_entry->flags &  BCM_PROXY_PACKET_DROP;
    311     soc_mem_field32_set(unit, mem, &in_nh_entry, DROPf, drop);
    312     soc_mem_field32_set(unit, mem, &in_nh_entry, ENTRY_TYPEf, 0x2);
    313 
    314     /* Write ingress next hop entry. */
    315     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, mem, idx, &in_nh_entry));
    316 
    317 
    318     /* Zero buffers. */
    319     sal_memset(&eg_nh_entry, 0, sizeof(egr_l3_next_hop_entry_t));
    320 
    321 
    322     mem = EGR_L3_NEXT_HOPm;
    323     /* Read egress next hop entry. */
    324     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &eg_nh_entry));
    325 
    326             if (soc_feature(unit, soc_feature_mem_access_data_type)) {
    327                 acc_type = DATA_TYPEf;
    328             }
    329             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    330                              acc_type, _BCM_PROXY_EGR_NEXT_HOP_SDTAG_VIEW);
    331             drop = proxy_nh_entry->flags &  BCM_PROXY_PACKET_DROP;
    332             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    333                     SD_TAG__BC_DROPf, drop ? 1 : 0);
    334             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    335                     SD_TAG__UUC_DROPf, drop ? 1 : 0);
    336             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    337                     SD_TAG__UMC_DROPf, drop ? 1 : 0);
    338 
    339             if (proxy_nh_entry->flags &  BCM_PROXY_LEARN_DISABLE) {
    340                  soc_mem_field32_set(unit, mem, &eg_nh_entry,
    341                         SD_TAG__HG_LEARN_OVERRIDEf, 0x1);
    342             }
    343             if (proxy_nh_entry->flags &  BCM_PROXY_PACKET_MODIFY) {
    344                  soc_mem_field32_set(unit, mem, &eg_nh_entry,
    345                         SD_TAG__HG_MODIFY_ENABLEf, 0x1);
    346             }
    347             if (proxy_nh_entry->flags &  BCM_PROXY_RSVD_VLAN_ADD) {
    348                  soc_mem_field32_set(unit, mem, &eg_nh_entry,
    349                         SD_TAG__HG_ADD_SYS_RSVD_VIDf, 0x1);
    350             }
    351             if (proxy_nh_entry->flags &  BCM_PROXY_L3_FORCE) {
    352                  soc_mem_field32_set(unit, mem, &eg_nh_entry, 
    353                         SD_TAG__HG_L3_OVERRIDEf, 0x1);
    354             }
    355             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    356                         SD_TAG__HG_MC_DST_MODIDf,
    357                         SOC_GPORT_MODPORT_MODID_GET(proxy_nh_entry->gport));
    358             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    359                         SD_TAG__HG_MC_DST_PORT_NUMf,
    360                         SOC_GPORT_MODPORT_PORT_GET(proxy_nh_entry->gport));
    361 
    362             /* HG_HDR  must be PPD0 */
    363             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    364                     SD_TAG__HG_HDR_SELf, 0);
    365             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    366                      SD_TAG__HG_CHANGE_DESTINATIONf, 0x1);
    367 
    368             /* Delete VNTAG */
    369             soc_mem_field32_set(unit, mem, &eg_nh_entry,
    370                      SD_TAG__VNTAG_ACTIONSf, 0x3);
    371 
    372     /* Write egress next hop entry. */
    373     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, mem, idx, &eg_nh_entry));
    374 
    375     return (BCM_E_NONE);
    376 }
    377 
    378 /*
    379  * Function:
    380  *      _bcm_td2_proxy_nh_get
    381  * Purpose:
    382  *        Read the Proxy NextHop table info given index.
    383  * Parameters:
    384  *      unit      - (IN) SOC unit number.
    385  *      idx       - (IN) Table index to read. 
    386  *      nh_entry  - (OUT) Next hop entry info. 
    387  * Returns:
    388  *      BCM_E_XXX
    389  */
    390 int
    391 _bcm_td2_proxy_nh_get(int unit, int idx, bcm_proxy_egress_t *proxy_nh_entry)
    392 {
    393     int rv = BCM_E_NONE;
    394     egr_l3_next_hop_entry_t  egr_entry;        /* Egress next hop entry.     */
    395     bcm_module_t  modid_in, modid_out;
    396     bcm_port_t       port_in, port_out;
    397     soc_mem_t       mem;
    398 
    399     /* Input parameters check */
    400     if (NULL == proxy_nh_entry) {
    401         return (BCM_E_PARAM);
    402     }
    403 
    404     sal_memset(&egr_entry, 0, sizeof(egr_l3_next_hop_entry_t));
    405     (void) bcm_proxy_egress_t_init(proxy_nh_entry);
    406 
    407     /*  Read egress next hop entry. */
    408     mem = EGR_L3_NEXT_HOPm;
    409     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, idx, &egr_entry));
    410 
    411     modid_in = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__HG_MC_DST_MODIDf);
    412     port_in = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__HG_MC_DST_PORT_NUMf);
    413     rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
    414                                     modid_in, port_in, &modid_out, &port_out);
    415 
    416     if (BCM_SUCCESS(rv)) {
    417         SOC_GPORT_MODPORT_SET(proxy_nh_entry->gport, modid_out, port_out);
    418     }
    419 
    420     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__HG_L3_OVERRIDEf)) {
    421          proxy_nh_entry->flags |=  BCM_PROXY_L3_FORCE;
    422     }
    423 
    424     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__HG_ADD_SYS_RSVD_VIDf)) {
    425          proxy_nh_entry->flags |=  BCM_PROXY_RSVD_VLAN_ADD;
    426     }
    427 
    428     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__HG_MODIFY_ENABLEf)) {
    429          proxy_nh_entry->flags |=  BCM_PROXY_PACKET_MODIFY;
    430     }
    431 
    432     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__HG_LEARN_OVERRIDEf)) {
    433          proxy_nh_entry->flags |=  BCM_PROXY_LEARN_DISABLE;
    434     }
    435 
    436     if (soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__BC_DROPf) ||
    437          soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__UUC_DROPf) ||
    438          soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_entry, SD_TAG__UMC_DROPf)) {
    439             proxy_nh_entry->flags |=  BCM_PROXY_PACKET_DROP;
    440     }
    441 
    442 
    443     return (BCM_E_NONE);
    444 }
    445 
    446 /*
    447  * Purpose:
    448  *      Traverse all valid Proxy egress entries and call the
    449  * 	 supplied callback routine.
    450  * Parameters:
    451  *     unit   - Device Number
    452  *     cb  - User callback function.
    453  *     user_data - cookie
    454  */
    455 
    456 int
    457 bcm_td2_proxy_egress_traverse(int unit, bcm_proxy_egress_traverse_cb  cb,
    458                                                         void *user_data)
    459 {
    460     bcm_proxy_egress_t proxy_nh_entry;     /* Next hop entry info.           */
    461     int idx;
    462     bcm_if_t proxy_if_id;
    463     char *egr_tbl_ptr;            /* Dma egress nh table pointer.   */
    464     uint32 *egr_entry_ptr = NULL; /* Egress next hop entry pinter.  */ 
    465     int rv = BCM_E_NONE;          /* Operation return status.       */
    466     soc_mem_t mem;                      /* Table location memory.           */
    467     bcm_module_t  modid_in, modid_out;
    468     bcm_port_t       port_in, port_out;
    469 
    470      /* If no callback provided, we are done.  */ 
    471      if (NULL == cb) { 
    472           return BCM_E_NONE; 
    473      } 
    474      mem = EGR_L3_NEXT_HOPm;
    475 
    476     /*  Read egress next hop entry. */
    477     rv = bcm_xgs3_l3_tbl_dma(unit, mem,
    478                              sizeof(egr_l3_next_hop_entry_t), "egr_nh_tbl",
    479                              &egr_tbl_ptr, NULL);
    480     if (rv < 0) {
    481         return rv;
    482     }
    483 
    484     for (idx = 0; idx < BCM_XGS3_L3_NH_TBL_SIZE(unit); idx++) {
    485         /* Skip unused entries. */
    486         if (!BCM_XGS3_L3_ENT_REF_CNT (BCM_XGS3_L3_TBL_PTR(unit, next_hop),
    487                                       idx)) {
    488             continue;
    489         }
    490 
    491         /*  Read egress next hop entry. */
    492         egr_entry_ptr = 
    493             soc_mem_table_idx_to_pointer(unit, EGR_L3_NEXT_HOPm,
    494                                          uint32 *, egr_tbl_ptr, idx);
    495 
    496          if (!soc_mem_field32_get(unit, mem, egr_entry_ptr, SD_TAG__HG_CHANGE_DESTINATIONf)) {
    497             continue;
    498          }
    499          bcm_proxy_egress_t_init(&proxy_nh_entry);
    500 
    501          proxy_if_id = idx + BCM_XGS3_PROXY_EGRESS_IDX_MIN(unit);
    502          modid_in = soc_mem_field32_get(unit, mem, egr_entry_ptr, SD_TAG__HG_MC_DST_MODIDf);
    503          port_in = soc_mem_field32_get(unit, mem,  egr_entry_ptr, SD_TAG__HG_MC_DST_PORT_NUMf);
    504          rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
    505                                     modid_in, port_in, &modid_out, &port_out);
    506 
    507          if (BCM_SUCCESS(rv)) {
    508             SOC_GPORT_MODPORT_SET(proxy_nh_entry.gport, modid_out, port_out);
    509          }
    510 
    511          if (soc_mem_field32_get(unit, mem,  egr_entry_ptr, SD_TAG__HG_L3_OVERRIDEf)) {
    512              proxy_nh_entry.flags |=  BCM_PROXY_L3_FORCE;
    513          }
    514 
    515          if (soc_mem_field32_get(unit, mem,  egr_entry_ptr, SD_TAG__HG_ADD_SYS_RSVD_VIDf)) {
    516              proxy_nh_entry.flags |=  BCM_PROXY_RSVD_VLAN_ADD;
    517          }
    518 
    519          if (soc_mem_field32_get(unit, mem, egr_entry_ptr, SD_TAG__HG_MODIFY_ENABLEf)) {
    520              proxy_nh_entry.flags |=  BCM_PROXY_PACKET_MODIFY;
    521          }
    522 
    523          if (soc_mem_field32_get(unit, mem, egr_entry_ptr, SD_TAG__HG_LEARN_OVERRIDEf)) {
    524              proxy_nh_entry.flags |=  BCM_PROXY_LEARN_DISABLE;
    525          }
    526 
    527          if (soc_mem_field32_get(unit, mem, egr_entry_ptr, SD_TAG__BC_DROPf) ||
    528               soc_mem_field32_get(unit, mem, egr_entry_ptr, SD_TAG__UUC_DROPf) ||
    529               soc_mem_field32_get(unit, mem, egr_entry_ptr, SD_TAG__UMC_DROPf)) {
    530              proxy_nh_entry.flags |=  BCM_PROXY_PACKET_DROP;
    531          }
    532 
    533          /* Execute operation routine if any. */
    534          if (cb) {
    535             rv = (cb)(unit, proxy_if_id, (void *)&proxy_nh_entry, (void *) user_data);
    536             if (rv < 0) {
    537                 break;
    538             }
    539          }
    540     }
    541     soc_cm_sfree(unit, egr_tbl_ptr);
    542     return (rv);
    543 
    544 }
    545 
    546 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    547