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


      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 <shared/bsl.h>
     10 
     11 #include <soc/defs.h>
     12 #include <soc/mem.h>
     13 #include <soc/drv.h>
     14 #include <sal/core/libc.h>
     15 #include <sal/core/sync.h>
     16 #include <soc/scache.h>
     17 
     18 #ifdef INCLUDE_L3
     19 #include <soc/drv.h>
     20 #include <soc/mem.h>
     21 #include <soc/util.h>
     22 #include <soc/l3x.h>
     23 #include <bcm/error.h>
     24 #include <bcm/proxy.h>
     25 #include <bcm/types.h>
     26 #include <bcm/l3.h>
     27 
     28 #include <bcm_int/esw/port.h>
     29 #include <bcm_int/esw/mbcm.h>
     30 #include <bcm_int/esw/firebolt.h>
     31 #include <bcm_int/api_xlate_port.h>
     32 #include <bcm_int/esw_dispatch.h>
     33 #include <bcm_int/esw/l3.h>
     34 #include <bcm_int/esw/stack.h>
     35 #include <bcm_int/esw/proxy.h>
     36 
     37 #ifdef BCM_WARM_BOOT_SUPPORT
     38 #include <bcm_int/esw/switch.h>
     39 #endif /* BCM_WARM_BOOT_SUPPORT */
     40 
     41 #if defined(BCM_TRIDENT2_SUPPORT)
     42 #include <bcm_int/esw/trident2.h>
     43 #endif /* BCM_TRIDENT_SUPPORT*/
     44 
     45 #define _BCM_PROXY_INFO_ENTRY_CREATED   0x00000001
     46 #define _BCM_PROXY_INFO_GROUP_CREATED   0x00000002
     47 #define _BCM_PROXY_INFO_FILTER_CREATED  0x00000004
     48 #define _BCM_PROXY_INFO_INSTALLED       0x00000008
     49 #define _BCM_PROXY_INFO_SERVER          0x00000010
     50 
     51 #define _BCM_PROXY_SERVER_INSTANCES     3
     52 #define _BCM_PROXY_BUD_NODE_0           0
     53 #define _BCM_PROXY_BUD_NODE_1           1
     54 #define _BCM_PROXY_HYBRID               2
     55 
     56 #ifdef BCM_WARM_BOOT_SUPPORT
     57 /* Warm boot scache version to store
     58  * server_gport and server_gport_mask information.
     59  */
     60 #define BCM_PROXY_WB_VERSION_1_0        SOC_SCACHE_VERSION(1,0)
     61 #define BCM_PROXY_WB_DEFAULT_VERSION    BCM_PROXY_WB_VERSION_1_0
     62 #endif
     63 
     64 #define _LOCK(unit) _bcm_proxy_control[unit].proxy_lock
     65 
     66 #define _BCM_PROXY_LOCK(unit) \
     67    _LOCK(unit) ? sal_mutex_take(_LOCK(unit), sal_mutex_FOREVER) : -1
     68 
     69 #define _BCM_PROXY_UNLOCK(unit) sal_mutex_give(_LOCK(unit))
     70 
     71 static bcmi_proxy_bookkeep_t proxy_bookkeep[BCM_MAX_NUM_UNITS];
     72 static int                   proxy_internal_initialized[BCM_MAX_NUM_UNITS] = {0};
     73 
     74 #define CHECK_PROXY_INIT(unit)                       \
     75         if (!proxy_internal_initialized[unit])             \
     76             return BCM_E_INIT
     77 typedef struct _bcm_proxy_info_s {
     78     int                      flags; /* _BCM_PROXY_INFO_* */
     79     bcm_port_t               client_port;
     80     bcm_proxy_proto_type_t   proto_type;
     81     bcm_module_t             server_modid;
     82     bcm_port_t               server_port;
     83     bcm_proxy_mode_t         mode;
     84     bcm_field_entry_t        eid;
     85     bcm_field_group_t        gid;
     86     struct _bcm_proxy_info_s *next;
     87 } _bcm_proxy_info_t;
     88 
     89 typedef struct _bcm_proxy_control_s {
     90     sal_mutex_t       proxy_lock;
     91     _bcm_proxy_info_t *proxy_list;
     92     int               num_clients;
     93 } _bcm_proxy_control_t;
     94 
     95 typedef int (*proxy_install_method_t)(int unit,
     96                                       _bcm_proxy_info_t *dst,
     97                                       _bcm_proxy_info_t *src);
     98 
     99 typedef int (*proxy_uninstall_method_t)(int unit,
    100                                         _bcm_proxy_info_t *src);
    101 
    102 typedef int (*proxy_match_method_t)(_bcm_proxy_info_t *dst,
    103                                     _bcm_proxy_info_t *src);
    104 
    105 typedef struct {
    106     proxy_install_method_t      install;
    107     proxy_uninstall_method_t    uninstall;
    108     proxy_match_method_t        match;
    109 } _bcm_proxy_ifc_t;
    110 
    111 STATIC int
    112 _bcm_esw_proxy_client_install_xgs3(int unit, _bcm_proxy_info_t *info);
    113 
    114 STATIC int
    115 _bcm_esw_proxy_client_install(int unit,
    116                               _bcm_proxy_info_t *dst,
    117                               _bcm_proxy_info_t *src);
    118 
    119 STATIC int
    120 _bcm_esw_proxy_client_uninstall_xgs3(int unit, _bcm_proxy_info_t *info);
    121 
    122 STATIC int
    123 _bcm_esw_proxy_client_uninstall(int unit, _bcm_proxy_info_t *info);
    124 
    125 STATIC int
    126 _bcm_esw_proxy_client_match(_bcm_proxy_info_t *dst, _bcm_proxy_info_t *src);
    127 
    128 STATIC int
    129 _bcm_esw_proxy_server_install(int unit,
    130                               _bcm_proxy_info_t *dst,
    131                               _bcm_proxy_info_t *src);
    132 
    133 STATIC int
    134 _bcm_esw_proxy_server_uninstall(int unit,
    135                                 _bcm_proxy_info_t *src);
    136 
    137 STATIC int
    138 _bcm_esw_proxy_server_match(_bcm_proxy_info_t *dst, _bcm_proxy_info_t *src);
    139 
    140 static _bcm_proxy_control_t _bcm_proxy_control[BCM_MAX_NUM_UNITS];
    141 
    142 STATIC 
    143 _bcm_proxy_ifc_t client_methods = {
    144     _bcm_esw_proxy_client_install,
    145     _bcm_esw_proxy_client_uninstall,
    146     _bcm_esw_proxy_client_match,
    147 };
    148 
    149 STATIC 
    150 _bcm_proxy_ifc_t server_methods = {
    151     _bcm_esw_proxy_server_install,
    152     _bcm_esw_proxy_server_uninstall,
    153     _bcm_esw_proxy_server_match,
    154 };
    155 
    156 /***************************************************************** Utilities */
    157 
    158 /*
    159  * Function:
    160  *      _bcm_esw_proxy_gport_resolve
    161  * Purpose:
    162  *      Decodes gport into port and module id
    163  * Parameters:
    164  *      unit         -  BCM Unit number
    165  *      gport        - GPORT 
    166  *      port_out     - (OUT) port encoded into gport 
    167  *      modid_out    - (OUT) modid encoded into gport
    168  *      isLocal      - Indicator that port encoded in gport must be local
    169  * Returns:
    170  *      BCM_E_XXX
    171  */
    172 STATIC int 
    173 _bcm_esw_proxy_gport_resolve(int unit, bcm_gport_t gport,
    174                              bcm_port_t *port_out,
    175                              bcm_module_t *modid_out, int isLocal)
    176 {
    177 
    178     bcm_port_t      port; 
    179     bcm_module_t    modid;
    180     bcm_trunk_t     tgid;
    181     int             id;
    182 
    183     if (NULL == port_out || NULL == modid_out) {
    184         return BCM_E_PARAM;
    185     }
    186 
    187     BCM_IF_ERROR_RETURN(
    188         _bcm_esw_gport_resolve(unit, gport, &modid, &port, &tgid, &id));
    189 
    190     if ((-1 != id) || (BCM_TRUNK_INVALID != tgid)){
    191         return BCM_E_PORT;
    192     }
    193 
    194     if (isLocal) {
    195         int    ismymodid;
    196         BCM_IF_ERROR_RETURN(
    197             _bcm_esw_modid_is_local(unit, modid, &ismymodid));
    198         if (ismymodid != TRUE) {
    199             return BCM_E_PARAM;
    200         }
    201     } 
    202 
    203     *port_out = port;
    204     *modid_out = modid;
    205     
    206     return BCM_E_NONE;
    207 }
    208 
    209 /****************************************************************** Generics */
    210 
    211 /*
    212  * Function:
    213  *      _bcm_esw_proxy_install
    214  * Purpose:
    215  *      Install proxy client or server
    216  * Parameters:
    217  *      unit           -  BCM Unit number
    218  *      bcm_proxy_ifc  -  local port for which redirection is applied
    219  *      data           -  Packet type to classify for redirection
    220  * Returns:
    221  *      BCM_E_XXX
    222  */
    223 int
    224 _bcm_esw_proxy_install(int unit,
    225                        _bcm_proxy_ifc_t *ifc,
    226                        _bcm_proxy_info_t *src)
    227 {
    228     int rv = BCM_E_INTERNAL;
    229     _bcm_proxy_info_t *dst;
    230 
    231     /* Allocate proxy info structure */
    232     dst = sal_alloc(sizeof(_bcm_proxy_info_t), "bcm_esw_proxy");
    233 
    234     if (dst == NULL) {
    235         return BCM_E_MEMORY;
    236     }
    237 
    238     sal_memset(dst, 0, sizeof(_bcm_proxy_info_t));
    239 
    240     if (_BCM_PROXY_LOCK(unit)) {
    241         sal_free(dst);
    242         return BCM_E_INIT;
    243     }
    244 
    245     rv = ifc->install(unit, dst, src);
    246         
    247     if (BCM_SUCCESS(rv)) {
    248         /* Put onto list */
    249         dst->next = _bcm_proxy_control[unit].proxy_list;
    250         _bcm_proxy_control[unit].proxy_list = dst;
    251     } else {
    252         sal_free(dst);
    253     }
    254 
    255     _BCM_PROXY_UNLOCK(unit);
    256 
    257     return rv;
    258 }
    259 
    260 /*
    261  * Function:
    262  *      _bcm_esw_proxy_uninstall
    263  * Purpose:
    264  *      Uninstall proxy client or server
    265  * Parameters:
    266  *      unit           -  BCM Unit number
    267  *      ifc            -  client/server methods
    268  *      info           -  info record to uninstall
    269  * Returns:
    270  *      BCM_E_XXX
    271  */
    272 int
    273 _bcm_esw_proxy_uninstall(int unit,
    274                          _bcm_proxy_ifc_t *ifc,
    275                          _bcm_proxy_info_t *src)
    276 {
    277     int rv = BCM_E_INTERNAL;
    278     _bcm_proxy_info_t *dst;
    279 
    280     if (_BCM_PROXY_LOCK(unit)) {
    281         return BCM_E_INIT;
    282     }
    283 
    284     /* Uninstall the enabled proxy client if the hardware is still
    285        capable. */
    286     if (SOC_HW_ACCESS_DISABLE(unit) == 0) {
    287         rv = ifc->uninstall(unit, src);
    288     } else {
    289         rv = BCM_E_NONE;
    290     }
    291     /* Unlink from list */
    292     if (_bcm_proxy_control[unit].proxy_list == src) {
    293         /* Info at beginning of the list */
    294         _bcm_proxy_control[unit].proxy_list = src->next;
    295     } else {
    296         for (dst = _bcm_proxy_control[unit].proxy_list;
    297              dst != NULL;
    298              dst = dst->next) {
    299             if (dst->next == src) {
    300                 dst->next = src->next;
    301                 break;
    302             }
    303         }
    304     }
    305     _BCM_PROXY_UNLOCK(unit);
    306 
    307     sal_memset(src, 0, sizeof(_bcm_proxy_info_t));
    308     sal_free(src);
    309 
    310     return rv;
    311 }
    312 
    313 /*
    314  * Function:
    315  *      _bcm_esw_proxy_find
    316  * Purpose:
    317  *      Find a previously created proxy client or server
    318  * Parameters:
    319  *      unit         -  BCM Unit number
    320  *      ifc          -  interface methods
    321  *      src          -  data to find
    322  *      dstp         -  data found, or NULL
    323  * Returns:
    324  *      BCM_E_NONE     - found
    325  *      BCM_E_NOTFOUND - not found
    326  *      BCM_E_INIT     - subsystem not initialized
    327  */
    328 
    329 STATIC int
    330 _bcm_esw_proxy_find(int unit,
    331                     _bcm_proxy_ifc_t *ifc,
    332                     _bcm_proxy_info_t *src,
    333                     _bcm_proxy_info_t **dstp)
    334 {
    335     _bcm_proxy_info_t *dst;
    336     int rv = BCM_E_NOT_FOUND;
    337 
    338     if (_BCM_PROXY_LOCK(unit)) {
    339         return BCM_E_INIT;
    340     }
    341 
    342     for (dst = _bcm_proxy_control[unit].proxy_list;
    343          dst != NULL;
    344          dst = dst->next) {
    345         if (ifc->match(dst, src)) {
    346             rv = BCM_E_EXISTS;
    347             break;
    348         }
    349     }
    350     _BCM_PROXY_UNLOCK(unit);
    351     *dstp = dst;
    352 
    353     return rv;
    354 }
    355 
    356 /*
    357  * Function:
    358  *      _bcm_esw_proxy
    359  * Purpose:
    360  *      Generic proxy client or server install or uninstall
    361  * Parameters:
    362  *      unit         -  BCM Unit number
    363  *      ifc          -  interface methods
    364  *      src          -  data to find
    365  * Returns:
    366  *      Pointer to _bcm_proxy_info_t if found
    367  *      NULL if not found
    368  */
    369 
    370 STATIC int
    371 _bcm_esw_proxy(int unit, _bcm_proxy_ifc_t *ifc,
    372                _bcm_proxy_info_t *src, int enable)
    373 {
    374     int rv;
    375     _bcm_proxy_info_t *dst = NULL;
    376 
    377     rv = _bcm_esw_proxy_find(unit, ifc, src, &dst);
    378 
    379     if (enable) {
    380 
    381         if (rv != BCM_E_NOT_FOUND) {
    382             return rv;
    383         }
    384 
    385         rv = _bcm_esw_proxy_install(unit, ifc, src);
    386 
    387     } else {
    388         /* Disable */
    389 
    390         if (rv != BCM_E_EXISTS) {
    391             return rv;
    392         }
    393         
    394         rv = _bcm_esw_proxy_uninstall(unit, ifc, dst);
    395 
    396     }
    397 
    398     return rv;
    399 }
    400 
    401 /******************************************************************** Client */
    402 
    403 /*
    404  * Function:
    405  *      _bcm_proxy_client_enabled
    406  * Purpose:
    407  *      Returns true if the proxy client is enabled on the given unit
    408  * Parameters:
    409  *      unit         -  BCM Unit number
    410  * Returns:
    411  *      TRUE or FALSE
    412  */
    413 
    414 int
    415 _bcm_proxy_client_enabled(int unit)
    416 {
    417     return (_bcm_proxy_control[unit].num_clients > 0);
    418 }
    419 
    420 /*
    421  * Function:
    422  *      bcm_esw_proxy_client_set
    423  * Purpose:
    424  *      Enables redirection for a certain traffic type using either 
    425  *      FFP or FP rule
    426  * Parameters:
    427  *      unit         -  BCM Unit number
    428  *      client_port  -  local port for which redirection is applied
    429  *      proto_type   -  Packet type to classify for redirection
    430  *      server_modid -  Module ID of remote device which performs lookups
    431  *      server_port  -  Port on remote device where redirected packets are 
    432  *                      destined to
    433  *      enable       -  toggle to enable or disable redirection
    434  * Returns:
    435  *      BCM_E_XXX
    436  */
    437 int
    438 bcm_esw_proxy_client_set(int unit, bcm_port_t client_port, 
    439                          bcm_proxy_proto_type_t proto_type,
    440                          bcm_module_t server_modid, bcm_port_t server_port, 
    441                          int enable)
    442 {
    443     _bcm_proxy_info_t src;
    444 
    445     if (BCM_GPORT_IS_SET(client_port)) {
    446         BCM_IF_ERROR_RETURN(
    447             bcm_esw_port_local_get(unit, client_port, &client_port));
    448     }
    449     if (BCM_GPORT_IS_SET(server_port)) {
    450         BCM_IF_ERROR_RETURN(
    451             _bcm_esw_proxy_gport_resolve(unit, server_port, &server_port,
    452                                          &server_modid, 0));
    453     }
    454 
    455     if (!SOC_PORT_VALID(unit, client_port)) {
    456         return BCM_E_PORT;
    457     }
    458     if (server_port < 0 ) {
    459         return BCM_E_PORT;
    460     }
    461 
    462     sal_memset(&src, 0, sizeof(_bcm_proxy_info_t));
    463     src.client_port  = client_port;
    464     src.proto_type   = proto_type;
    465     src.server_modid = server_modid;
    466     src.server_port  = server_port;
    467 
    468     return _bcm_esw_proxy(unit, &client_methods, &src, enable);
    469 }
    470 
    471 /*
    472  * Function:
    473  *      _bcm_esw_proxy_client_match
    474  * Purpose:
    475  *      Return true if src client record matches dst
    476  * Parameters:
    477  *      dst - 
    478  *      src - 
    479  * Returns:
    480  *      True if matched
    481  */
    482 
    483 STATIC int
    484 _bcm_esw_proxy_client_match(_bcm_proxy_info_t *dst, _bcm_proxy_info_t *src)
    485 {
    486         return (dst->client_port == src->client_port &&
    487                 dst->proto_type == src->proto_type &&
    488                 dst->server_modid == src->server_modid &&
    489                 dst->server_port == src->server_port &&
    490                 (dst->flags & _BCM_PROXY_INFO_SERVER) == 0);
    491 }
    492 
    493 /*
    494  * Function:
    495  *      _bcm_esw_proxy_server_match
    496  * Purpose:
    497  *      Return true if src server record matches dst
    498  * Parameters:
    499  *      dst - 
    500  *      src - 
    501  * Returns:
    502  *      True if matched
    503  */
    504 
    505 STATIC int
    506 _bcm_esw_proxy_server_match(_bcm_proxy_info_t *dst,
    507                             _bcm_proxy_info_t *src)
    508 {
    509     return (dst->mode == src->mode &&
    510             dst->server_port == src->server_port &&
    511             (dst->flags & _BCM_PROXY_INFO_SERVER) != 0);
    512 }
    513 
    514 /*
    515  * Function:
    516  *      _bcm_esw_proxy_client_create_xgs3
    517  * Purpose:
    518  *      Creates proxy client using FP rules, doesn't clean up on error
    519  * Parameters:
    520  *      unit           -  BCM Unit number
    521  *      bcm_proxy_info -  proxy data
    522  * Returns:
    523  *      BCM_E_XXX
    524  */
    525 
    526 STATIC int
    527 _bcm_esw_proxy_client_create_xgs3(int unit, _bcm_proxy_info_t *bcm_proxy_info)
    528 {
    529 #ifdef BCM_XGS3_SWITCH_SUPPORT
    530     _field_stage_t         *stage_fc=NULL;  /* Stage Field control structure.   */
    531     bcm_port_config_t      pc;              /* Port Configuration structure.    */
    532     bcm_field_group_config_t fg;            /* Group configuration structure.   */
    533     int                    instance=0;      /* Pipe instance.                   */
    534     bcm_pbmp_t             mask_pbmp;       /* IPBM mask.                       */
    535     bcm_field_entry_t      eid;
    536     bcm_field_group_t      gid;
    537     bcm_pbmp_t             ingress_pbmp;
    538     bcm_port_t             client_port = bcm_proxy_info->client_port;
    539     bcm_proxy_proto_type_t proto_type = bcm_proxy_info->proto_type;
    540     bcm_module_t           server_modid = bcm_proxy_info->server_modid;
    541     bcm_port_t             server_port = bcm_proxy_info->server_port;
    542 
    543     BCM_PBMP_PORT_SET(ingress_pbmp, client_port);
    544    
    545     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc));
    546     
    547     bcm_port_config_t_init(&pc);
    548     BCM_IF_ERROR_RETURN(bcm_esw_port_config_get(unit, &pc));
    549 
    550     bcm_field_group_config_t_init(&fg);
    551     instance = SOC_INFO(unit).port_pipe[client_port];   
    552     mask_pbmp = PBMP_ALL(unit); 
    553 
    554     /* Replace chip name check with feature check to make it work for TD3 also similar to TH */
    555     if (soc_feature(unit, soc_feature_multi_pipe_mapped_ports) || SOC_IS_TOMAHAWKX(unit)) {
    556         switch (stage_fc->oper_mode) {
    557             case bcmFieldGroupOperModeGlobal:
    558                 break;
    559             case bcmFieldGroupOperModePipeLocal:
    560                 fg.ports = pc.per_pipe[instance];
    561                 fg.flags |= BCM_FIELD_GROUP_CREATE_WITH_PORT; 
    562                 mask_pbmp = PBMP_PIPE(unit,instance);
    563                 break;
    564             default: 
    565                 return (BCM_E_INTERNAL);
    566         }
    567     }
    568            
    569     BCM_FIELD_QSET_INIT(fg.qset);
    570     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
    571         /* TD3 does not support per-port IPBM, instead using
    572            device port will suffice in this scenario */
    573         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyInPort);
    574     } else {
    575         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyInPorts);
    576     }
    577 
    578     switch(proto_type) {
    579     case BCM_PROXY_PROTO_IP4_ALL:
    580         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType);
    581         break;
    582     case BCM_PROXY_PROTO_IP6_ALL:
    583         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType);
    584         break;
    585     case BCM_PROXY_PROTO_IP4_MCAST:
    586         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyDstIp);
    587         break;
    588     case BCM_PROXY_PROTO_IP6_MCAST:
    589         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpType);
    590         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyDstIp6High);
    591         break;
    592     case BCM_PROXY_PROTO_MPLS_UCAST:
    593         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType);
    594         break;
    595     case BCM_PROXY_PROTO_MPLS_MCAST:
    596         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType);
    597         break;
    598     case BCM_PROXY_PROTO_MPLS_ALL:
    599         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType);
    600         break;
    601     case BCM_PROXY_PROTO_IP6_IN_IP4:
    602         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpProtocol);
    603         break;
    604     case BCM_PROXY_PROTO_IP_IN_IP:
    605         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpProtocol);
    606         break;
    607     case BCM_PROXY_PROTO_GRE_IN_IP:
    608         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyIpProtocol);
    609         break;
    610     case BCM_PROXY_PROTO_UNKNOWN_IP4_UCAST:
    611         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType);
    612         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyPacketRes);
    613         break;
    614     /*    coverity[equality_cond]    */
    615     case BCM_PROXY_PROTO_UNKNOWN_IP6_UCAST:
    616         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyEtherType);
    617         BCM_FIELD_QSET_ADD(fg.qset, bcmFieldQualifyPacketRes);
    618         break;
    619     default:
    620         return BCM_E_PARAM;
    621     }
    622     
    623     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
    624         /* For TD3,ensure adding ASET at the group creation phase to avoid
    625            un-necessary usage of intraslice mode by default */
    626         BCM_FIELD_ASET_INIT(fg.aset);
    627         BCM_FIELD_ASET_ADD(fg.aset, bcmFieldActionRedirect);
    628     }
    629     BCM_IF_ERROR_RETURN(bcm_esw_field_group_config_create(unit, &fg));
    630     gid = fg.group;
    631    
    632     bcm_proxy_info->flags |= _BCM_PROXY_INFO_GROUP_CREATED;
    633     bcm_proxy_info->gid = gid;
    634 
    635     BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit, gid, &eid));
    636     bcm_proxy_info->flags |= _BCM_PROXY_INFO_ENTRY_CREATED;
    637     bcm_proxy_info->eid = eid;
    638 
    639     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
    640         /* TD3 does not support per-port IPBM, instead using
    641           device port will suffice in this scenario */
    642         BCM_IF_ERROR_RETURN
    643             (bcm_esw_field_qualify_InPort(unit, eid, client_port,
    644                                            BCM_FIELD_EXACT_MATCH_MASK));
    645     } else {
    646         BCM_IF_ERROR_RETURN
    647             (bcm_esw_field_qualify_InPorts(unit, eid, ingress_pbmp,
    648                                            mask_pbmp));
    649     }
    650 
    651     switch(proto_type) {
    652     case BCM_PROXY_PROTO_IP4_ALL:
    653         BCM_IF_ERROR_RETURN
    654             (bcm_esw_field_qualify_EtherType(unit, eid, 0x0800, 0xffff));
    655         break;
    656     case BCM_PROXY_PROTO_IP6_ALL:
    657         BCM_IF_ERROR_RETURN
    658             (bcm_esw_field_qualify_EtherType(unit, eid, 0x86dd, 0xffff));
    659         break;
    660     case BCM_PROXY_PROTO_IP4_MCAST:
    661         BCM_IF_ERROR_RETURN
    662             (bcm_esw_field_qualify_DstIp(unit, eid, 0xe0000000, 0xf0000000));
    663         break;
    664     case BCM_PROXY_PROTO_IP6_MCAST:
    665         {
    666             bcm_ip6_t addr, mask;
    667             BCM_IF_ERROR_RETURN
    668                 (bcm_esw_field_qualify_IpType(unit, eid, bcmFieldIpTypeIpv6));
    669             sal_memset(addr, 0, 16); /* BCM_IP6_ADDRLEN */
    670             addr[0] = 0xff;
    671             sal_memset(mask, 0, 16); /* BCM_IP6_ADDRLEN */
    672             mask[0] = 0xff;
    673             mask[1] = 0xff;
    674             BCM_IF_ERROR_RETURN
    675                 (bcm_esw_field_qualify_DstIp6High(unit, eid, addr, mask));
    676             break;
    677         }
    678 
    679     case BCM_PROXY_PROTO_MPLS_UCAST:
    680         BCM_IF_ERROR_RETURN
    681             (bcm_esw_field_qualify_EtherType(unit, eid, 0x8847, 0xffff));
    682         break;
    683     case BCM_PROXY_PROTO_MPLS_MCAST:
    684         BCM_IF_ERROR_RETURN
    685             (bcm_esw_field_qualify_EtherType(unit, eid, 0x8848, 0xffff));
    686         break;
    687     case BCM_PROXY_PROTO_MPLS_ALL:
    688         BCM_IF_ERROR_RETURN
    689             (bcm_esw_field_qualify_EtherType(unit, eid, 0x8840, 0xfff0));
    690         break;
    691     case BCM_PROXY_PROTO_IP6_IN_IP4:
    692         BCM_IF_ERROR_RETURN
    693             (bcm_esw_field_qualify_IpProtocol(unit, eid, 0x29, 0xff));
    694         break;
    695     case BCM_PROXY_PROTO_IP_IN_IP:
    696         BCM_IF_ERROR_RETURN
    697             (bcm_esw_field_qualify_IpProtocol(unit, eid, 0x4, 0xff));
    698         break;
    699     case BCM_PROXY_PROTO_GRE_IN_IP:
    700         BCM_IF_ERROR_RETURN
    701             (bcm_esw_field_qualify_IpProtocol(unit, eid, 0x2f, 0xff));
    702         break;
    703     case BCM_PROXY_PROTO_UNKNOWN_IP4_UCAST:
    704         BCM_IF_ERROR_RETURN
    705             (bcm_esw_field_qualify_EtherType(unit, eid, 0x0800, 0xffff));
    706         BCM_IF_ERROR_RETURN
    707             (bcm_esw_field_qualify_PacketRes(unit, eid,
    708                                              BCM_FIELD_PKT_RES_L3UCUNKNOWN,
    709                                              0xf));
    710         break;
    711     case BCM_PROXY_PROTO_UNKNOWN_IP6_UCAST:
    712         BCM_IF_ERROR_RETURN
    713             (bcm_esw_field_qualify_EtherType(unit, eid, 0x86dd, 0xffff));
    714         BCM_IF_ERROR_RETURN
    715             (bcm_esw_field_qualify_PacketRes(unit, eid,
    716                                              BCM_FIELD_PKT_RES_L3UCUNKNOWN,
    717                                              0xf));
    718         break;
    719         /* Defensive Default */
    720         /* coverity[dead_error_begin] */
    721     default:
    722         return BCM_E_PARAM;
    723     }
    724 
    725     BCM_IF_ERROR_RETURN
    726         (bcm_esw_field_action_add(unit, eid, bcmFieldActionRedirect, 
    727                                   server_modid, server_port));
    728     
    729      BCM_IF_ERROR_RETURN
    730          (bcm_esw_field_entry_install(unit, eid));
    731     
    732     bcm_proxy_info->flags |= _BCM_PROXY_INFO_INSTALLED;
    733     return BCM_E_NONE;
    734 #else
    735     return BCM_E_UNAVAIL;
    736 #endif
    737 } 
    738 
    739 /*
    740  * Function:
    741  *      _bcm_esw_proxy_client_uninstall_xgs3
    742  * Purpose:
    743  *      Removes and destroys proxy client FP resources
    744  * Parameters:
    745  *      unit           -  BCM Unit number
    746  *      bcm_proxy_info -  proxy data
    747  * Returns:
    748  *      BCM_E_XXX
    749  */
    750 
    751 STATIC int
    752 _bcm_esw_proxy_client_uninstall_xgs3(int unit,
    753                                      _bcm_proxy_info_t *info)
    754 {
    755 #ifdef BCM_XGS3_SWITCH_SUPPORT
    756     bcm_field_entry_t eid   = info->eid;
    757     bcm_field_group_t gid   = info->gid;
    758     int flags               = info->flags;
    759 
    760     if (flags & _BCM_PROXY_INFO_INSTALLED) {
    761         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_remove(unit, eid));
    762     }
    763 
    764     if (flags & _BCM_PROXY_INFO_ENTRY_CREATED) {
    765         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, eid));
    766     }
    767 
    768     if (flags & _BCM_PROXY_INFO_GROUP_CREATED) {
    769         BCM_IF_ERROR_RETURN(bcm_esw_field_group_destroy(unit, gid));
    770     }
    771 
    772     return BCM_E_NONE;
    773 #else
    774     return BCM_E_UNAVAIL;
    775 #endif
    776 }
    777 
    778 /*
    779  * Function:
    780  *      _bcm_esw_proxy_client_install_xgs3
    781  * Purpose:
    782  *      Creates proxy client using FP rules, clean up on error
    783  * Parameters:
    784  *      unit           -  BCM Unit number
    785  *      bcm_proxy_info -  proxy data
    786  * Returns:
    787  *      BCM_E_XXX
    788  */
    789 
    790 STATIC int
    791 _bcm_esw_proxy_client_install_xgs3(int unit,
    792                                    _bcm_proxy_info_t *info)
    793 {
    794     int rv = BCM_E_INTERNAL;
    795 
    796     rv = _bcm_esw_proxy_client_create_xgs3(unit, info);
    797 
    798     if (BCM_FAILURE(rv)) {
    799         LOG_WARN(BSL_LS_BCM_L3,
    800                  (BSL_META_U(unit,
    801                              "Proxy: could not install client: %s\n"),
    802                   bcm_errmsg(rv)));
    803         /* Ignore errors from uninstall */
    804         _bcm_esw_proxy_client_uninstall_xgs3(unit, info);
    805     }
    806 
    807     return rv;
    808 }
    809 
    810 /*
    811  * Function:
    812  *      _bcm_esw_proxy_client_uninstall
    813  * Purpose:
    814  *      Uninstall proxy client for all device families
    815  * Parameters:
    816  *      unit           -  BCM Unit number
    817  *      bcm_proxy_info -  proxy data
    818  * Returns:
    819  *      BCM_E_XXX
    820  */
    821 
    822 STATIC int
    823 _bcm_esw_proxy_client_uninstall(int unit, _bcm_proxy_info_t *info)
    824 {
    825     int rv = BCM_E_INTERNAL;
    826 
    827     if (SOC_IS_XGS3_SWITCH(unit)) {
    828         rv = _bcm_esw_proxy_client_uninstall_xgs3(unit, info);
    829     }
    830 
    831     if (BCM_SUCCESS(rv)) {
    832         _bcm_proxy_control[unit].num_clients--;
    833     }
    834 
    835     return rv;
    836 }
    837 
    838 
    839 /*
    840  * Function:
    841  *      _bcm_esw_proxy_client_install
    842  * Purpose:
    843  *      Install proxy client for all device families
    844  * Parameters:
    845  *      unit           -  BCM Unit number
    846  *      bcm_proxy_info -  proxy data
    847  * Returns:
    848  *      BCM_E_XXX
    849  */
    850 
    851 STATIC int
    852 _bcm_esw_proxy_client_install(int unit,
    853                               _bcm_proxy_info_t *dst,
    854                               _bcm_proxy_info_t *src)
    855 {
    856     int rv = BCM_E_INTERNAL;
    857 
    858     dst->client_port  = src->client_port;
    859     dst->proto_type   = src->proto_type;
    860     dst->server_modid = src->server_modid;
    861     dst->server_port  = src->server_port;
    862     dst->server_port  = src->server_port;
    863 
    864     if (SOC_IS_XGS3_SWITCH(unit)) {
    865         rv = _bcm_esw_proxy_client_install_xgs3(unit, dst);
    866     }
    867 
    868     if (BCM_SUCCESS(rv)) {
    869         _bcm_proxy_control[unit].num_clients++;
    870     }
    871     return rv;
    872 }
    873 
    874 /******************************************************************** Server */
    875 /*
    876  * Function:
    877  *      bcmi_td3_proxy_server_config (internal function)
    878  * Purpose:
    879  *      Enables various kinds of lookups for packets coming from remote
    880  *      (proxy client) devices on the server side for TD3
    881  * Parameters:
    882  *      unit        -  BCM Unit number
    883  *      server_port -  Local port to which packets from remote devices are
    884  *                     destined to
    885  *      mode        -  Indicates lookup type
    886  *      enable      -  TRUE to enable lookups
    887  *                     FALSE to disable lookups
    888  * Returns:
    889  *      BCM_E_XXX
    890  */
    891 STATIC int
    892 bcmi_td3_proxy_server_config(int unit, bcm_port_t server_port,
    893                           bcm_proxy_mode_t mode, int enable)
    894 {
    895     int ing_port = 0;
    896     uint32 mod = 0;
    897     static soc_field_t fields[5] = {VALIDf, DEST_MODULE_IDf, DEST_PORT_IDf, DEST_MODULE_ID_MASKf, DEST_PORT_ID_MASKf};
    898     uint32 values[5] , field_num = 5;
    899     bcm_module_t    modid_mask;
    900     bcm_gport_t     server_port_mask;
    901     /* Generalize chip specific memory name*/
    902     soc_mem_t port_table = ING_DEVICE_PORTm;
    903     soc_reg_t hg_reg = HG_PKT_SIGNATURE_1r;
    904     uint32 ptab[SOC_MAX_MEM_WORDS];
    905     sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
    906 
    907     BCM_IF_ERROR_RETURN
    908         (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, server_port, ptab));
    909     if (BCM_PROXY_MODE_HIGIG == mode) {
    910        soc_mem_field32_set(unit, port_table, ptab,
    911                            HG_LOOKUP_ENABLEf, enable ? 1 : 0);
    912        soc_mem_field32_set(unit, port_table, ptab,
    913                            HYBRID_MODE_ENABLEf, 0);
    914     } else {
    915         /* BCM_PROXY_MODE_HYBRID */
    916         soc_mem_field32_set(unit, port_table, ptab,
    917                             HYBRID_MODE_ENABLEf, enable ? 1 : 0);
    918         soc_mem_field32_set(unit, port_table, ptab,
    919                             HG_LOOKUP_ENABLEf, 0);
    920     }
    921     soc_mem_field32_set(unit, port_table, ptab,
    922                         USE_MH_VIDf, enable ? 1 : 0);
    923     soc_mem_field32_set(unit, port_table, ptab,
    924                         USE_MH_PKT_PRIf, enable ? 1 : 0);
    925 
    926     BCM_IF_ERROR_RETURN
    927            (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, server_port, ptab));
    928     /*
    929      * Program LPORT table for the HG port;
    930      * HIGIG_PACKET must not be set; MY_MODID must be
    931      * set appropriately, and V4/V6 enable bits
    932     */
    933     mod = soc_mem_field32_get(unit, port_table, ptab, MY_MODIDf);
    934     sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
    935     soc_LPORT_TABm_field32_set(unit, ptab, V4L3_ENABLEf,
    936                                enable ? 1 : 0);
    937     soc_LPORT_TABm_field32_set(unit, ptab, V6L3_ENABLEf,
    938                                enable ? 1 : 0);
    939     soc_LPORT_TABm_field32_set(unit, ptab, V4IPMC_ENABLEf,
    940                                enable ? 1 : 0);
    941     soc_LPORT_TABm_field32_set(unit, ptab, V6IPMC_ENABLEf,
    942                                enable ? 1 : 0);
    943     soc_LPORT_TABm_field32_set(unit, ptab, IPMC_DO_VLANf,
    944                                enable ? 1 : 0);
    945     soc_LPORT_TABm_field32_set(unit, ptab, FILTER_ENABLEf,
    946                                enable ? 1 : 0);
    947 
    948     BCM_IF_ERROR_RETURN
    949         (soc_mem_write(unit, LPORT_TABm, MEM_BLOCK_ALL,
    950                        server_port, ptab));
    951 
    952     /* Set "magic destination" to this server port to
    953        match prior devices' behavior */
    954     modid_mask       = ((1 << soc_reg_field_length(unit, hg_reg, DEST_MODULE_ID_MASKf)) - 1);
    955     server_port_mask = ((1 << soc_reg_field_length(unit, hg_reg, DEST_PORT_ID_MASKf)) - 1);
    956 
    957     values[0] = enable;
    958     values[1] = mod;
    959     values[2] = server_port;
    960     values[3] = modid_mask;
    961     values[4] = server_port_mask;
    962     PBMP_HG_ITER(unit, ing_port) {
    963         SOC_IF_ERROR_RETURN
    964             (soc_reg_fields32_modify(unit, hg_reg, ing_port,
    965                                      field_num, fields, values));
    966     }
    967     return BCM_E_NONE;
    968 }
    969 
    970 /*
    971  * Function:
    972  *      bcmi_td3_proxy_server_retrieve
    973  * Purpose:
    974  *      Retrieves proxy related settings on the server side for TD3 device
    975  * Parameters:
    976  *      unit        - BCM Unit number
    977  *      server_port - Local port to which packets from remote devices are destined to
    978  *      mode        - proxy server mode
    979  *      enable      - (OUT) server status
    980  * Returns:
    981  *      BCM_E_XXX
    982  */
    983 STATIC int
    984 bcmi_td3_proxy_server_retrieve(int unit, bcm_port_t server_port,
    985                           bcm_proxy_mode_t mode, int *enable)
    986 {
    987     uint64 hgld;
    988     int hg_enable;
    989     /* Generalize chip specific memory and reg name */
    990     soc_mem_t port_table = ING_DEVICE_PORTm;
    991     soc_reg_t hg_reg = HG_PKT_SIGNATURE_1r;
    992     uint32 ptab[SOC_MAX_MEM_WORDS];
    993     sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
    994 
    995     BCM_IF_ERROR_RETURN
    996         (soc_reg64_get(unit, hg_reg, server_port, 0, &hgld));
    997 
    998     if (server_port == soc_reg64_field32_get(unit, hg_reg,hgld, DEST_PORT_IDf)) {
    999         BCM_IF_ERROR_RETURN
   1000             (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, server_port, ptab));
   1001         if (BCM_PROXY_MODE_HIGIG == mode) {
   1002             hg_enable = soc_mem_field32_get(unit, port_table, ptab, HG_LOOKUP_ENABLEf);
   1003         } else {
   1004             hg_enable = soc_mem_field32_get(unit, port_table, ptab, HYBRID_MODE_ENABLEf);
   1005         }
   1006         *enable = hg_enable;
   1007     }
   1008     return BCM_E_NONE;
   1009 }
   1010 
   1011 /*
   1012  * Function:
   1013  *      bcmi_td3_proxy_server_signature_match (internal function)
   1014  * Purpose:
   1015  *      Enables programming of the appropiate signature match register
   1016  *      to enable proxy processing on the server device based on the
   1017  *      type of application.(Hybrid mode or Bud-node proxy)
   1018  * Parameters:
   1019  *      unit - (IN) Unit number.
   1020  *      local_ingress_port - (IN) Incoming Higig stack port
   1021  *      proxy_server - (IN) Proxy server configuration
   1022  *      hg_reg - (IN) Register used for singature match.
   1023  *      enable - (IN) Enable proxy server on selected Higig stack port
   1024  * Returns:
   1025  *      BCM_E_xxx
   1026  */
   1027 STATIC int
   1028 bcmi_td3_proxy_server_signature_match(int unit, bcm_gport_t local_ingress_port,
   1029                               bcm_proxy_server_t *proxy_server, soc_reg_t hg_reg, int enable)
   1030 {
   1031     bcm_module_t modid = 0, modid_mask = 0, default_modid_mask;
   1032     bcm_port_t   server_port = 0, server_port_mask = 0, default_port_mask;
   1033     uint32       field_num = 5;
   1034     uint32       values[5] = {0};
   1035     static       soc_field_t fields[5] = {VALIDf, DEST_MODULE_IDf, DEST_PORT_IDf,
   1036         DEST_MODULE_ID_MASKf, DEST_PORT_ID_MASKf};
   1037 
   1038     default_modid_mask = ((1 << soc_reg_field_length(unit, hg_reg, DEST_MODULE_ID_MASKf)) - 1);
   1039     default_port_mask  = ((1 << soc_reg_field_length(unit, hg_reg, DEST_PORT_ID_MASKf)) - 1);
   1040     BCM_IF_ERROR_RETURN
   1041         (_bcm_esw_proxy_gport_resolve(unit, proxy_server->server_gport,
   1042                                       &server_port, &modid, 0));
   1043 
   1044     /* Only valid flags are allowed */
   1045     if (proxy_server->flags > (BCM_PROXY_SERVER_MASK_PORT | BCM_PROXY_SERVER_KEEP_PRIORITY |
   1046         BCM_PROXY_SERVER_KEEP_VID | BCM_PROXY_SERVER_MASK_MODID)) {
   1047        return BCM_E_PARAM;
   1048     }
   1049     /* Logic to flexibly mask the destination port and/or
   1050      * destination modid while performing signature match */
   1051     if (proxy_server->server_gport_mask == BCM_PROXY_SERVER_GPORT_ALL_MASK) {
   1052         /* Use default full mask for modid and port unless appropriate flags are passed */
   1053         modid_mask       = (proxy_server->flags & BCM_PROXY_SERVER_MASK_MODID) ? 0 : default_modid_mask;
   1054         server_port_mask = (proxy_server->flags & BCM_PROXY_SERVER_MASK_PORT) ? 0 : default_port_mask;
   1055     } else {
   1056         modid_mask = BCM_GPORT_PROXY_MODID_GET(proxy_server->server_gport_mask);
   1057         server_port_mask = BCM_GPORT_PROXY_PORT_GET(proxy_server->server_gport_mask);
   1058         if (proxy_server->flags & BCM_PROXY_SERVER_MASK_MODID) {
   1059             if (!(modid_mask == 0)) {
   1060                 /* When this flag is present, if at all user passes server_gport_mask;
   1061                  * then modid_mask has to be zero. Otherwise it is PARAM Error*/
   1062                 return BCM_E_PARAM;
   1063             }
   1064         }
   1065         if (proxy_server->flags & BCM_PROXY_SERVER_MASK_PORT) {
   1066             if (!(server_port_mask == 0)) {
   1067                 /* When this flag is present, if at all user passes server_gport_mask;
   1068                  * then server_port_mask has to be zero. Otherwise it is PARAM Error */
   1069                 return BCM_E_PARAM;
   1070             }
   1071         }
   1072     }
   1073     values[0] = enable;
   1074     values[1] = modid;
   1075     values[2] = server_port;
   1076     values[3] = modid_mask;
   1077     values[4] = server_port_mask;
   1078 
   1079     SOC_IF_ERROR_RETURN
   1080         (soc_reg_fields32_modify(unit, hg_reg, local_ingress_port,
   1081                                  field_num, fields, values));
   1082     return BCM_E_NONE;
   1083 }
   1084 
   1085 /*
   1086  * Function:
   1087  *      bcmi_map_hg_port_to_index(internal function)
   1088  * Purpose:
   1089  *      Creates a mapping of all the HiGig ports to a corresponding index
   1090  *      in an arrya of HiGig ports. Useful in allocating optimal
   1091  *      memory while allocating book keeping structures.
   1092  * Parameters:
   1093  *      unit - (IN) Unit number.
   1094  *      local_ingress_port - (IN) Incoming Higig stack port
   1095  *      mapped_index - (OUT) Index which points to the location of the
   1096  *      localingress port in an arry of HG ports
   1097  * Returns:
   1098  *      BCM_E_xxx
   1099  */
   1100 STATIC int
   1101 bcmi_map_hg_port_to_index(int unit, bcm_gport_t local_ingress_port, int *mapped_index)
   1102 {
   1103     int index = 0;
   1104     int i = 0;
   1105     int ing_port = 0;
   1106     int hg_size;
   1107     int *hg_array = NULL;
   1108 
   1109     BCM_PBMP_COUNT(PBMP_HG_ALL(unit), hg_size);
   1110     hg_array = sal_alloc(sizeof(int) * hg_size, "Hg Array");
   1111     if (hg_array == NULL) {
   1112         return BCM_E_MEMORY;
   1113     }
   1114     sal_memset(hg_array, 0, sizeof(int) * hg_size);
   1115 
   1116     PBMP_HG_ITER(unit, ing_port) {
   1117         hg_array[index] = ing_port;
   1118         index++;
   1119     }
   1120     for (i = 0; i < hg_size; i++) {
   1121         if (hg_array[i] == local_ingress_port) {
   1122             *mapped_index = i;
   1123         }
   1124     }
   1125     sal_free(hg_array);
   1126     return BCM_E_NONE;
   1127 }
   1128 
   1129 /*
   1130  * Function:
   1131  *      bcmi_td3_proxy_server_port_config
   1132  * Purpose:
   1133  *      Enables various kinds of lookups on TD3 device on
   1134  *      behalf of remote legacy or XGS3 devices on a per ingress port
   1135  *      basis.  The local ingress port is expected to be a Higig stack
   1136  *      port.  The server_gport in the proxy_server structure is the
   1137  *      target BCM_GPORT_PROXY (modid,port) destination which
   1138  *      indicates that hybrid proxy lookup is required.
   1139  * Parameters:
   1140  *      unit - (IN) Unit number.
   1141  *      local_ingress_port - (IN) Incoming Higig stack port
   1142  *      proxy_server - (IN) Proxy server configuration
   1143  *      enable - (IN) Enable proxy server on selected Higig stack port
   1144  * Returns:
   1145  *      BCM_E_xxx
   1146  */
   1147 STATIC int
   1148 bcmi_td3_proxy_server_port_config(int unit, bcm_gport_t local_ingress_port,
   1149                               bcm_proxy_server_t *proxy_server,
   1150                               int enable)
   1151 {
   1152     bcm_gport_t  server_gport = 0, server_gport_mask = 0;
   1153     int          i = 0;
   1154     int          mapped_index = 0;
   1155     int          cpu_port = SOC_INFO(unit).cpu_hg_index;
   1156     /* Generalize chip specific memory and reg name */
   1157     soc_mem_t port_table = ING_DEVICE_PORTm;
   1158     soc_reg_t hg_reg = HG_PKT_SIGNATURE_1r;
   1159     static uint32 reg_val_legacy[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   1160     static uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   1161     static soc_reg_t config_regs[] = {
   1162         HG_PKT_SIGNATURE_2r,
   1163         HG_PKT_SIGNATURE_3r
   1164     };
   1165     /* Use legacy registers for Bud node proxy. Will be handled by CCH
   1166        to map into appropriate TD3 programming */
   1167     static soc_reg_t config_regs_legacy[] = {
   1168         ING_PACKET_PROCESSING_CONTROL_0r,
   1169         ING_PACKET_PROCESSING_CONTROL_1r
   1170     };
   1171     static soc_field_t config_reg_fields[] = {
   1172         ING_PACKET_PROCESSING_ENABLE_0f,
   1173         ING_PACKET_PROCESSING_ENABLE_1f
   1174     };
   1175     uint32       ptab[SOC_MAX_MEM_WORDS];
   1176     uint64       const0_64 = COMPILER_64_INIT(0,0);
   1177     sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1178 
   1179     BCM_IF_ERROR_RETURN(soc_mem_read(unit, port_table, MEM_BLOCK_ANY,
   1180                 local_ingress_port, ptab));
   1181     if (enable) {
   1182         server_gport = proxy_server->server_gport;
   1183         if (!BCM_GPORT_IS_PROXY(server_gport)) {
   1184             /* The server gport is required to be in
   1185              * BCM_GPORT_PROXY format */
   1186             return BCM_E_PORT;
   1187         }
   1188         server_gport_mask = proxy_server->server_gport_mask;
   1189         if (!(server_gport_mask == BCM_PROXY_SERVER_GPORT_ALL_MASK) && !BCM_GPORT_IS_PROXY(server_gport_mask)) {
   1190             /* The server gport mask; when specified;
   1191              * is required to be in BCM_GPORT_PROXY format
   1192              */
   1193             return BCM_E_PARAM;
   1194         }
   1195 
   1196         BCM_IF_ERROR_RETURN
   1197             (bcmi_map_hg_port_to_index(unit, local_ingress_port, &mapped_index));
   1198         if (BCM_PROXY_MODE_HIGIG == proxy_server->mode) {
   1199             /* BCM_PROXY_MODE_HIGIG */
   1200             soc_mem_field32_set(unit, port_table, ptab,	HG_LOOKUP_ENABLEf, 1);
   1201             soc_mem_field32_set(unit, port_table, ptab,	HYBRID_MODE_ENABLEf, 0);
   1202         } else if (BCM_PROXY_MODE_HYBRID == proxy_server->mode) {
   1203             /* BCM_PROXY_MODE_HYBRID */
   1204             soc_mem_field32_set(unit, port_table, ptab,	HG_LOOKUP_ENABLEf, 0);
   1205             soc_mem_field32_set(unit, port_table, ptab,	HYBRID_MODE_ENABLEf, 1);
   1206             BCM_IF_ERROR_RETURN
   1207                 (bcmi_td3_proxy_server_signature_match(unit, local_ingress_port,
   1208                                                        proxy_server, hg_reg, enable));
   1209             /* Maintain software state of proxy server in third instance of proxy_bookkeep */
   1210             sal_memcpy(&proxy_bookkeep[unit].proxy_server_copy[_BCM_PROXY_HYBRID][mapped_index],
   1211                     proxy_server, sizeof(bcm_proxy_server_t));
   1212         } else if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) {
   1213             if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) {
   1214                 return BCM_E_UNAVAIL;
   1215             }
   1216             if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) ||
   1217                     (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) {
   1218                 return BCM_E_PARAM;
   1219             }
   1220             /* If exist, update the entry*/
   1221             for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   1222                 /* Flow type is defaulted to "NONE" in CANCUN. CCH is used at SOC layer to overwrite it */
   1223                 /* Retaining the legacy register and field names at BCM layer */
   1224                 SOC_IF_ERROR_RETURN
   1225                     (soc_reg32_get(unit, config_regs_legacy[i], REG_PORT_ANY,
   1226                                    0, &reg_val_legacy[i]));
   1227                 flow_type[i] = soc_reg_field_get(unit,config_regs_legacy[i],
   1228                                               reg_val_legacy[i], FLOW_TYPEf);
   1229                 if (proxy_server->flow_type == flow_type[i]) {
   1230                     soc_reg_field_set(unit,config_regs_legacy[i],
   1231                             &reg_val_legacy[i], FLOW_TYPEf, proxy_server->flow_type);
   1232                     BCM_IF_ERROR_RETURN
   1233                         (bcmi_td3_proxy_server_signature_match(unit, local_ingress_port,
   1234                                                                proxy_server, config_regs[i], enable));
   1235                     /* Maintain software state of proxy server in first two instances of proxy_bookkeep */
   1236                     sal_memcpy(&proxy_bookkeep[unit].proxy_server_copy[i][mapped_index],
   1237                             proxy_server, sizeof(bcm_proxy_server_t));
   1238 
   1239                     SOC_IF_ERROR_RETURN
   1240                         (soc_reg32_set(unit, config_regs_legacy[i], REG_PORT_ANY,
   1241                                        0, reg_val_legacy[i]));
   1242 
   1243                     soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 1);
   1244                     soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0);
   1245                     soc_mem_field32_set(unit, port_table, ptab, REMOVE_MH_SRC_PORTf, 1);
   1246 
   1247                     BCM_IF_ERROR_RETURN
   1248                         (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab));
   1249                     return BCM_E_NONE;
   1250                 }
   1251             }
   1252 
   1253             /* if not exist, create it */
   1254             for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   1255                 if (bcmProxySecondPassFlowTypeNone == flow_type[i]) {
   1256                     soc_reg_field_set(unit,config_regs_legacy[i],
   1257                             &reg_val_legacy[i], FLOW_TYPEf, proxy_server->flow_type);
   1258                     BCM_IF_ERROR_RETURN
   1259                         (bcmi_td3_proxy_server_signature_match(unit, local_ingress_port,
   1260                                                                proxy_server, config_regs[i], enable));
   1261                     /* Maintain software state of proxy server in first two instances of proxy_bookkeep */
   1262                     sal_memcpy(&proxy_bookkeep[unit].proxy_server_copy[i][mapped_index],
   1263                             proxy_server, sizeof(bcm_proxy_server_t));
   1264 
   1265                     SOC_IF_ERROR_RETURN
   1266                         (soc_reg32_set(unit, config_regs_legacy[i], REG_PORT_ANY,
   1267                                        0, reg_val_legacy[i]));
   1268 
   1269                     soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 1);
   1270                     soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0);
   1271                     soc_mem_field32_set(unit, port_table, ptab, REMOVE_MH_SRC_PORTf, 1);
   1272 
   1273                     BCM_IF_ERROR_RETURN
   1274                         (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab));
   1275                     return BCM_E_NONE;
   1276                 }
   1277             }
   1278             return BCM_E_FULL;
   1279         } else {
   1280             /* We don't support BCM_PROXY_MODE_LOOPBACK in this per-port
   1281              * version of the API.
   1282              */
   1283             return BCM_E_PARAM;
   1284         }
   1285         /* Keeping TD3 code consistent with other devices in the
   1286          * interpretation of the two flags for using info from module header */
   1287         soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf,
   1288                 proxy_server->flags & BCM_PROXY_SERVER_KEEP_VID ? 0 : 1);
   1289         soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf,
   1290                 proxy_server->flags & BCM_PROXY_SERVER_KEEP_PRIORITY ? 0 : 1);
   1291 
   1292         BCM_IF_ERROR_RETURN
   1293             (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab));
   1294 
   1295         if (IS_CPU_PORT(unit, local_ingress_port) &&
   1296             (BCM_PROXY_MODE_HYBRID == proxy_server->mode)) {
   1297             sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1298 
   1299             BCM_IF_ERROR_RETURN(soc_mem_read(
   1300                 unit, port_table, MEM_BLOCK_ANY, cpu_port, ptab));
   1301             soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0);
   1302             soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 1);
   1303             soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf,
   1304                 proxy_server->flags & BCM_PROXY_SERVER_KEEP_VID ? 0 : 1);
   1305             soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf,
   1306                 proxy_server->flags & BCM_PROXY_SERVER_KEEP_PRIORITY ? 0 : 1);
   1307             BCM_IF_ERROR_RETURN(soc_mem_write(
   1308                 unit, port_table, MEM_BLOCK_ALL, cpu_port, ptab));
   1309         }
   1310     } else {
   1311         /* when enable is 0 */
   1312         if (NULL == proxy_server) {
   1313             return BCM_E_PARAM;
   1314         }
   1315         if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) {
   1316             if (soc_feature(unit, soc_feature_hg_proxy_second_pass)) {
   1317 
   1318                 if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) ||
   1319                         (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) {
   1320                     return BCM_E_PARAM;
   1321                 }
   1322                 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   1323                     /* Use legacy register and field names at BCM layer.
   1324                      * CCH is used at SOC layer to get the corresponding values */
   1325                     SOC_IF_ERROR_RETURN
   1326                         (soc_reg32_get(unit, config_regs_legacy[i], REG_PORT_ANY,
   1327                                        0, &reg_val_legacy[i]));
   1328                     flow_type[i] = soc_reg_field_get(unit,config_regs_legacy[i],
   1329                             reg_val_legacy[i], FLOW_TYPEf);
   1330 
   1331                     if (proxy_server->flow_type == flow_type[i]) {
   1332                         int dglp_is_shared = 0;
   1333                         bcm_gport_t local_port = 0;
   1334                         uint32 return_val[SOC_MAX_MEM_WORDS];
   1335                         sal_memset(return_val, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1336 
   1337                         soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 0);
   1338                         soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 0);
   1339                         soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 0);
   1340                         soc_mem_field32_set(unit, port_table, ptab, REMOVE_MH_SRC_PORTf, 0);
   1341 
   1342                         BCM_IF_ERROR_RETURN
   1343                             (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab));
   1344                         BCM_PBMP_ITER(PBMP_ALL(unit),local_port) {
   1345                             BCM_IF_ERROR_RETURN
   1346                                 (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, local_port, return_val));
   1347                             if (soc_mem_field32_get(unit, port_table, return_val, config_reg_fields[i])) {
   1348                                 dglp_is_shared = 1;
   1349                             }
   1350                         }
   1351                         if (!dglp_is_shared) {
   1352                             soc_reg_field_set(unit,config_regs_legacy[i],
   1353                                     &reg_val_legacy[i], FLOW_TYPEf,0);
   1354 
   1355                             SOC_IF_ERROR_RETURN
   1356                                 (soc_reg32_set(unit, config_regs_legacy[i], REG_PORT_ANY, 0, reg_val_legacy[i]));
   1357                             SOC_IF_ERROR_RETURN
   1358                                 (soc_reg64_set(unit, config_regs[i], REG_PORT_ANY, 0, const0_64));
   1359                         }
   1360                         return BCM_E_NONE;
   1361                     }
   1362                 }
   1363                 return BCM_E_NOT_FOUND;
   1364             } else {
   1365                 return BCM_E_UNAVAIL;
   1366             }
   1367         }
   1368         /* Clear server configuration, but retain the independent
   1369          * source port knockout configuration REMOVE_MH_SRC_PORTf
   1370          */
   1371         soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0);
   1372         soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 0);
   1373         soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 0);
   1374         soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 0);
   1375         for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   1376             soc_mem_field32_set(unit, port_table, ptab, config_reg_fields[i], 0);
   1377         }
   1378         SOC_IF_ERROR_RETURN
   1379             (soc_mem_write(unit, port_table, MEM_BLOCK_ALL, local_ingress_port, ptab));
   1380 
   1381         if (IS_CPU_PORT(unit, local_ingress_port) &&
   1382             (BCM_PROXY_MODE_HYBRID == proxy_server->mode)) {
   1383             sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1384 
   1385             BCM_IF_ERROR_RETURN(soc_mem_read(
   1386                 unit, port_table, MEM_BLOCK_ANY, cpu_port, ptab));
   1387             soc_mem_field32_set(unit, port_table, ptab, HG_LOOKUP_ENABLEf, 0);
   1388             soc_mem_field32_set(unit, port_table, ptab, HYBRID_MODE_ENABLEf, 0);
   1389             soc_mem_field32_set(unit, port_table, ptab, USE_MH_PKT_PRIf, 0);
   1390             soc_mem_field32_set(unit, port_table, ptab, USE_MH_VIDf, 0);
   1391             BCM_IF_ERROR_RETURN(soc_mem_write(
   1392                 unit, port_table, MEM_BLOCK_ALL, cpu_port, ptab));
   1393         }
   1394 
   1395         /* Clear the HG_PKT_SINGATURE_1 config */
   1396         SOC_IF_ERROR_RETURN
   1397             (soc_reg64_set(unit, hg_reg, local_ingress_port, 0, const0_64));
   1398     }
   1399     /* End of else loop (enable is 0) */
   1400 
   1401     return BCM_E_NONE;
   1402 }
   1403 
   1404 /*
   1405  * Function:
   1406  *      bcmi_td3_proxy_server_port_retrieve
   1407  * Purpose:
   1408  *      Retrieves the current proxy server configuration on a
   1409  *      given Higig stack port in TD3, if any.
   1410  * Parameters:
   1411  *      unit - (IN) Unit number.
   1412  *      local_ingress_port - (IN) Incoming Higig stack port
   1413  *      proxy_server - (OUT) Proxy server configuration
   1414  *      enable - (OUT) Enable proxy server on selected Higig stack port
   1415  * Returns:
   1416  *      BCM_E_xxx
   1417  */
   1418 STATIC int
   1419 bcmi_td3_proxy_server_port_retrieve(int unit, bcm_gport_t local_ingress_port,
   1420                                     bcm_proxy_server_t *proxy_server,
   1421                                     int *enable)
   1422 {
   1423     uint32          hglkup, hybrid;
   1424     int             i = 0;
   1425     int             mapped_index = 0;
   1426     /* Generalize chip specific memory and reg name */
   1427     soc_mem_t port_table = ING_DEVICE_PORTm;
   1428     static uint32 reg_val_legacy[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   1429     static uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   1430     static soc_reg_t config_regs_legacy[] = {
   1431         ING_PACKET_PROCESSING_CONTROL_0r,
   1432         ING_PACKET_PROCESSING_CONTROL_1r
   1433     };
   1434     static soc_field_t config_reg_fields[] = {
   1435         ING_PACKET_PROCESSING_ENABLE_0f,
   1436         ING_PACKET_PROCESSING_ENABLE_1f
   1437     };
   1438     uint32          ptab[SOC_MAX_MEM_WORDS];
   1439     sal_memset(ptab, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1440 
   1441     SOC_IF_ERROR_RETURN
   1442         (soc_mem_read(unit, port_table, MEM_BLOCK_ANY, local_ingress_port, ptab));
   1443     BCM_IF_ERROR_RETURN
   1444         (bcmi_map_hg_port_to_index(unit, local_ingress_port, &mapped_index));
   1445     if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) {
   1446         if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) {
   1447             return BCM_E_UNAVAIL;
   1448         }
   1449 
   1450         for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   1451             SOC_IF_ERROR_RETURN
   1452                 (soc_reg32_get(unit, config_regs_legacy[i], REG_PORT_ANY, 0, &reg_val_legacy[i]));
   1453             flow_type[i] = soc_reg_field_get(unit, config_regs_legacy[i], reg_val_legacy[i], FLOW_TYPEf);
   1454 
   1455             if (proxy_server->flow_type == flow_type[i]) {
   1456                 /* Get proxy server information from software state */
   1457                 sal_memcpy(proxy_server, &proxy_bookkeep[unit].proxy_server_copy[i][mapped_index],
   1458                         sizeof(bcm_proxy_server_t));
   1459                 *enable = soc_mem_field32_get(unit, port_table, ptab, config_reg_fields[i]);
   1460                 return BCM_E_NONE;
   1461             }
   1462         }
   1463         return BCM_E_NOT_FOUND;
   1464     }
   1465     hglkup = soc_mem_field32_get(unit, port_table, ptab, HG_LOOKUP_ENABLEf);
   1466     hybrid = soc_mem_field32_get(unit, port_table, ptab, HYBRID_MODE_ENABLEf);
   1467 
   1468     if (hglkup) {
   1469         *enable = TRUE;
   1470         proxy_server->mode = BCM_PROXY_MODE_HIGIG;
   1471         /* Keeping TD3 code consistent with other devices in the
   1472          * interpretation of the two flags for using info from module header */
   1473         if (!soc_mem_field32_get(unit, port_table, ptab, USE_MH_VIDf)) {
   1474             proxy_server->flags |= BCM_PROXY_SERVER_KEEP_VID;
   1475         }
   1476 
   1477         if (!soc_mem_field32_get(unit, port_table, ptab, USE_MH_PKT_PRIf)) {
   1478             proxy_server->flags |= BCM_PROXY_SERVER_KEEP_PRIORITY;
   1479         }
   1480     } else {
   1481         if (hybrid) {
   1482             *enable = TRUE;
   1483             /*mode = BCM_PROXY_MODE_HYBRID;*/
   1484             /* Get proxy server information from software state */
   1485             sal_memcpy(proxy_server, &proxy_bookkeep[unit].proxy_server_copy[_BCM_PROXY_HYBRID][mapped_index],
   1486                     sizeof(bcm_proxy_server_t));
   1487         } else {
   1488             *enable = FALSE;
   1489             /* Nothing else to do */
   1490             return BCM_E_NONE;
   1491         }
   1492     }
   1493     return BCM_E_NONE;
   1494 }
   1495 
   1496 #ifdef BCM_WARM_BOOT_SUPPORT
   1497 /*
   1498  * Function:
   1499  *      bcmi_proxy_server_wb_alloc
   1500  * Purpose:
   1501  *      Allocates persisitent memory for Warm Boot scache.
   1502  * Parameters:
   1503  *      unit - Device number.
   1504  * Returns:
   1505  *      BCM_E_XXX
   1506  */
   1507 STATIC int
   1508 bcmi_proxy_server_wb_alloc(int unit)
   1509 {
   1510     int rv = BCM_E_NONE;
   1511     int port_size;
   1512     uint8 *proxy_server_scache;
   1513     soc_scache_handle_t scache_handle;
   1514 
   1515     BCM_PBMP_COUNT(PBMP_HG_ALL(unit), port_size);
   1516         SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_PROXY, 0);
   1517         rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   1518                 port_size * sizeof(bcm_proxy_server_t),
   1519                 &proxy_server_scache,
   1520                 BCM_PROXY_WB_DEFAULT_VERSION, NULL);
   1521         if (BCM_E_NOT_FOUND == rv) {
   1522             /* Proceed with Level 1 Warm Boot */
   1523             rv = BCM_E_NONE;
   1524         }
   1525     return rv;
   1526 }
   1527 
   1528 /*
   1529  * Function:
   1530  *      bcmi_proxy_server_sync
   1531  * Purpose:
   1532  *      Stores proxy_server_gport and proxy_server_gport_mask information
   1533  *      in scache so that it can be recovered on warm boot
   1534  * Parameters:
   1535  *      unit - Device number.
   1536  * Returns:
   1537  *      BCM_E_XXX
   1538  */
   1539 int
   1540 bcmi_proxy_server_sync(int unit)
   1541 {
   1542     int alloc_size, port_size, idx = 0;
   1543     soc_scache_handle_t scache_handle;
   1544     uint8               *proxy_server_scache;
   1545 
   1546     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   1547         return BCM_E_NONE;
   1548     }
   1549     BCM_PBMP_COUNT(PBMP_HG_ALL(unit), port_size);
   1550     alloc_size = port_size * sizeof(bcm_proxy_server_t);
   1551 
   1552     CHECK_PROXY_INIT(unit);
   1553     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_PROXY, 0);
   1554     BCM_IF_ERROR_RETURN
   1555         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1556                                  alloc_size * _BCM_PROXY_SERVER_INSTANCES, &proxy_server_scache,
   1557                                  BCM_PROXY_WB_DEFAULT_VERSION, NULL));
   1558     for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) {
   1559         /* copy proxy_server instance into scache and point to the next location */
   1560         sal_memcpy(proxy_server_scache,
   1561                 proxy_bookkeep[unit].proxy_server_copy[idx], alloc_size);
   1562         proxy_server_scache += alloc_size;
   1563     }
   1564     return BCM_E_NONE;
   1565 }
   1566 
   1567 STATIC int
   1568 bcmi_proxy_server_recover(int unit)
   1569 {
   1570     int alloc_size, port_size, idx = 0, rv = BCM_E_NONE;
   1571     soc_scache_handle_t scache_handle;
   1572     uint8               *proxy_server_scache;
   1573 
   1574     BCM_PBMP_COUNT(PBMP_HG_ALL(unit), port_size);
   1575     alloc_size = port_size * sizeof(bcm_proxy_server_t);
   1576 
   1577     /* We can't distinguish boot path for level 1 and level 2 warmboot
   1578      * HR3 is the only chip we need to run level 1 warmboot which
   1579      * means we don't do "exit clean" and not configuring any scache info
   1580      *
   1581      * Work around here is for HR3 only - We return from here
   1582      * if this is level 1 warmboot by checking whether user configures
   1583      * the scache_file
   1584      *
   1585      * Test case to verify this fix is: AT_IFP_wb_lvl1_005
   1586      */
   1587     if (SOC_IS_HURRICANEX(unit)) {
   1588         if ((NULL == soc_property_get_str(unit, spn_STABLE_FILENAME)) &&
   1589             (NULL == soc_property_get_str(unit, "scache_filename"))) {
   1590             return BCM_E_NONE;
   1591         }
   1592     }
   1593 
   1594     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_PROXY, 0);
   1595     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1596               alloc_size * _BCM_PROXY_SERVER_INSTANCES, &proxy_server_scache,
   1597               BCM_PROXY_WB_DEFAULT_VERSION, NULL);
   1598     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   1599         return rv;
   1600     } else if (rv == BCM_E_NOT_FOUND) {
   1601         return bcmi_proxy_server_wb_alloc(unit);
   1602     }
   1603 
   1604     for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) {
   1605         /* copy scache data into proxy_server instance and point to the next location */
   1606         sal_memcpy(proxy_bookkeep[unit].proxy_server_copy[idx],
   1607                 proxy_server_scache, alloc_size);
   1608         proxy_server_scache += alloc_size;
   1609     }
   1610     return BCM_E_NONE;
   1611 }
   1612 #endif /*BCM_WARM_BOOT_SUPPORT*/
   1613 /*
   1614  * Function:
   1615  *      _bcm_esw_proxy_server_set
   1616  * Purpose:
   1617  *      Enables various kinds of lookups for packets coming from remote
   1618  *      (proxy client) devices (internal function)
   1619  * Parameters:
   1620  *      unit        -  BCM Unit number
   1621  *      server_port -  Local port to which packets from remote devices are 
   1622  *                     destined to
   1623  *      mode        -  Indicates lookup type
   1624  *      enable      -  TRUE to enable lookups
   1625  *                     FALSE to disable lookups
   1626  * Returns:
   1627  *      BCM_E_XXX
   1628  */
   1629 int
   1630 _bcm_esw_proxy_server_set(int unit, bcm_port_t server_port, 
   1631                           bcm_proxy_mode_t mode, int enable)
   1632 {
   1633     
   1634     if (BCM_GPORT_IS_SET(server_port)) {
   1635         bcm_module_t    modid;
   1636         BCM_IF_ERROR_RETURN(
   1637             _bcm_esw_proxy_gport_resolve(unit, server_port,
   1638                                          &server_port, &modid, 1));
   1639     }
   1640     
   1641     if (IS_HG_PORT(unit, server_port) || IS_CPU_PORT(unit, server_port)) {
   1642         if ((mode != BCM_PROXY_MODE_HIGIG) && (mode != BCM_PROXY_MODE_HYBRID)) {
   1643             return BCM_E_PARAM;
   1644         }
   1645            
   1646 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1647         if (SOC_IS_FBX(unit)) {
   1648             uint32 dst_bmp;
   1649             bcm_pbmp_t pbmp;
   1650             uint32 val, mod = 0;
   1651             int lport_idx;
   1652             port_tab_entry_t ptab;
   1653             
   1654             if (!soc_feature(unit, soc_feature_higig_lookup)) {
   1655                 return BCM_E_UNAVAIL;
   1656             }
   1657 
   1658             /*
   1659              * Program PORT table V4L3_ENABLE, V6L3_ENABLE;
   1660              * required for IP-IP tunneling on XGS3 devices.
   1661              * This is not necessary for XGS4 and later.
   1662              */
   1663 
   1664             
   1665             if (!SOC_IS_TRX(unit)) {
   1666                 BCM_IF_ERROR_RETURN
   1667                     (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY,
   1668                                   server_port, &ptab));
   1669                 soc_PORT_TABm_field32_set(unit, &ptab, V4L3_ENABLEf,
   1670                                           enable ? 1 : 0);
   1671                 soc_PORT_TABm_field32_set(unit, &ptab, V6L3_ENABLEf,
   1672                                           enable ? 1 : 0);
   1673                 BCM_IF_ERROR_RETURN
   1674                     (soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL,
   1675                                    server_port, &ptab));
   1676             }
   1677 
   1678             if (soc_feature(unit,soc_feature_td3_style_proxy)) {
   1679                /* Program relevant TD3 tables and registers */
   1680                BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_config(unit, server_port, mode, enable));
   1681             } else {
   1682                 /*
   1683                  * Program LPORT table for the HG port;
   1684                  * HIGIG_PACKET must not be set; MY_MODID must be
   1685                  * set appropriately, and V4/V6 enable bits
   1686                  */
   1687                 BCM_IF_ERROR_RETURN
   1688                     (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY,
   1689                                   server_port, &ptab));
   1690                 if (soc_mem_field_valid(unit, PORT_TABm, MY_MODIDf)) {
   1691                     mod = soc_PORT_TABm_field32_get(unit, &ptab, MY_MODIDf);
   1692                 }
   1693                 
   1694                 /* For Triumph, we use entry 0 so all remote ports
   1695                  * will use this entry.  This is the behavior for previous
   1696                  * devices 
   1697                  */
   1698                 lport_idx = SOC_IS_TR_VL(unit) ? 0 : server_port;
   1699                 
   1700                 sal_memset(&ptab, 0, sizeof(port_tab_entry_t));
   1701                 BCM_IF_ERROR_RETURN
   1702                         (soc_mem_read(unit, LPORT_TABm, MEM_BLOCK_ANY,
   1703                                       lport_idx, &ptab));                
   1704                 if (soc_mem_field_valid(unit, LPORT_TABm, MY_MODIDf)) {
   1705                     soc_LPORT_TABm_field32_set(unit, &ptab, MY_MODIDf, mod);
   1706                 }
   1707                 soc_LPORT_TABm_field32_set(unit, &ptab, V4L3_ENABLEf,
   1708                                            enable ? 1 : 0);
   1709                 soc_LPORT_TABm_field32_set(unit, &ptab, V6L3_ENABLEf,
   1710                                            enable ? 1 : 0);
   1711                 soc_LPORT_TABm_field32_set(unit, &ptab, V4IPMC_ENABLEf,
   1712                                            enable ? 1 : 0);
   1713                 soc_LPORT_TABm_field32_set(unit, &ptab, V6IPMC_ENABLEf,
   1714                                            enable ? 1 : 0);
   1715                 soc_LPORT_TABm_field32_set(unit, &ptab, IPMC_DO_VLANf,
   1716                                            enable ? 1 : 0);
   1717                 soc_LPORT_TABm_field32_set(unit, &ptab, FILTER_ENABLEf,
   1718                                            enable ? 1 : 0);
   1719 
   1720                 BCM_IF_ERROR_RETURN
   1721                     (soc_mem_write(unit, LPORT_TABm, MEM_BLOCK_ALL,
   1722                                    lport_idx, &ptab));
   1723 
   1724                 SOC_IF_ERROR_RETURN(READ_IHG_LOOKUPr
   1725                                     (unit, server_port, &val));
   1726                 if (BCM_PROXY_MODE_HIGIG == mode) {
   1727                     /* BCM_PROXY_MODE_HIGIG */
   1728                     soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   1729                                             HG_LOOKUP_ENABLEf, enable ? 1: 0);
   1730                     soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   1731                                             HYBRID_MODE_ENABLEf, 0);
   1732                 } else {
   1733                     /* BCM_PROXY_MODE_HYBRID */
   1734                     soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   1735                                             HG_LOOKUP_ENABLEf, 0);
   1736                     soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   1737                                             HYBRID_MODE_ENABLEf, enable ? 1: 0);
   1738                 }
   1739                 if (SOC_IS_TRX(unit)) {
   1740                     int ing_port;
   1741                     soc_reg_t reg;
   1742                     static soc_field_t fields[2] = { DST_MODIDf, DST_PORTf };
   1743                     uint32 values[2];
   1744                     /* Set "magic destination" to this server port to
   1745                        match prior devices' behavior */
   1746                     reg = HG_LOOKUP_DESTINATIONr;
   1747                     values[0] = mod;
   1748                     values[1] = server_port;
   1749                     if (SOC_REG_INFO(unit, reg).regtype == soc_portreg) {
   1750                         PBMP_HG_ITER(unit, ing_port) {
   1751                             SOC_IF_ERROR_RETURN
   1752                                 (soc_reg_fields32_modify(unit, reg, ing_port,
   1753                                                          2, fields, values));
   1754                         }
   1755                     } else {
   1756                         SOC_IF_ERROR_RETURN
   1757                             (soc_reg_fields32_modify(unit, reg, REG_PORT_ANY,
   1758                                                      2, fields, values));
   1759                     }
   1760                 } else {
   1761                     BCM_PBMP_PORT_SET(pbmp, server_port);
   1762                     dst_bmp = SOC_PBMP_WORD_GET(pbmp, 0);
   1763                     dst_bmp >>= SOC_HG_OFFSET(unit);
   1764                     soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   1765                                       DST_HG_LOOKUP_BITMAPf, dst_bmp);
   1766                 }
   1767                 if (SOC_REG_FIELD_VALID(unit, IHG_LOOKUPr,
   1768                                         LOOKUP_WITH_MH_SRC_PORTf)) {
   1769                     soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   1770                                       LOOKUP_WITH_MH_SRC_PORTf, enable ? 1 :0);
   1771                 }
   1772                 if (SOC_REG_FIELD_VALID(unit, IHG_LOOKUPr,
   1773                                         USE_MH_INTERNAL_PRIf)) {
   1774                     soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   1775                                       USE_MH_INTERNAL_PRIf, enable ? 1: 0);
   1776                 }
   1777                 soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_VIDf,
   1778                                   enable ? 1: 0);
   1779                 soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_PKT_PRIf,
   1780                                   enable ? 1: 0);
   1781                 SOC_IF_ERROR_RETURN(WRITE_IHG_LOOKUPr(unit, server_port, val));
   1782             }
   1783         }
   1784 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   1785      } else {
   1786 
   1787          if (mode != BCM_PROXY_MODE_LOOPBACK) {
   1788              return BCM_E_PARAM;
   1789          }
   1790 
   1791          if (enable) {
   1792              BCM_IF_ERROR_RETURN
   1793                  (bcm_esw_port_loopback_set(unit, server_port,
   1794                                             BCM_PORT_LOOPBACK_MAC));
   1795 	 } else {
   1796              BCM_IF_ERROR_RETURN
   1797                  (bcm_esw_port_loopback_set(unit, server_port,
   1798                                             BCM_PORT_LOOPBACK_NONE));
   1799          }
   1800      }
   1801      return BCM_E_NONE;
   1802 }
   1803 
   1804 /*
   1805  * Function:
   1806  *      bcm_esw_proxy_server_get
   1807  * Purpose:
   1808  *      Get the lookup mode of XGS3 device.
   1809  * Parameters:
   1810  *      unit        -  BCM Unit number
   1811  *      server_port -  Local port to which packets from remote devices are 
   1812  *                     destined to
   1813  *      mode        -  proxy server mode
   1814  *      enable      -  (OUT) server status
   1815  * Returns:
   1816  *      BCM_E_XXX
   1817  */
   1818 int
   1819 bcm_esw_proxy_server_get(int unit, bcm_port_t server_port, 
   1820                          bcm_proxy_mode_t mode, int *enable)
   1821 {
   1822     int rv = BCM_E_NONE;
   1823     *enable = FALSE;
   1824 
   1825     if (BCM_GPORT_IS_SET(server_port)) {
   1826         BCM_IF_ERROR_RETURN(
   1827             bcm_esw_port_local_get(unit, server_port, &server_port));
   1828     }
   1829 
   1830     if (!SOC_PORT_VALID(unit, server_port)) {
   1831         return BCM_E_PORT;
   1832     }
   1833 
   1834     if (!(IS_HG_PORT(unit, server_port) || IS_CPU_PORT(unit, server_port))) {
   1835         int status;
   1836 
   1837 	if (mode != BCM_PROXY_MODE_LOOPBACK) {
   1838 	    return BCM_E_PARAM;
   1839 	}
   1840     /*    coverity[uninit_use_in_call : FALSE]    */
   1841 	    
   1842         rv = bcm_esw_port_loopback_get(unit, server_port, &status);
   1843         if (BCM_SUCCESS(rv)) {
   1844             if (status == BCM_PORT_LOOPBACK_MAC ||
   1845                 status == BCM_PORT_LOOPBACK_PHY) {
   1846                 *enable = TRUE;
   1847             } 
   1848         }
   1849     } else {
   1850 
   1851         if ((mode != BCM_PROXY_MODE_HIGIG) && (mode != BCM_PROXY_MODE_HYBRID)) {
   1852 	        return BCM_E_PARAM;
   1853         }
   1854 
   1855 #ifdef BCM_XGS3_SWITCH_SUPPORT
   1856 	if (soc_feature(unit, soc_feature_higig_lookup)) {
   1857             int port, hg_enable;
   1858             uint32 val, dst_bmp;
   1859             bcm_pbmp_t pbmp, r_pbmp;
   1860             soc_reg_t reg;
   1861 
   1862             if (SOC_IS_TRX(unit)) {
   1863                 uint32 hgld;
   1864                 if (soc_feature(unit,soc_feature_td3_style_proxy)) {
   1865                    BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_retrieve(unit, server_port, mode, enable));
   1866                 } else {
   1867                     /* Set "magic destination" to this server port to
   1868                        match prior devices' behavior */
   1869                     reg = HG_LOOKUP_DESTINATIONr;
   1870                     if (SOC_REG_INFO(unit, reg).regtype == soc_portreg) {
   1871                         SOC_IF_ERROR_RETURN
   1872                                 (soc_reg32_get(unit, reg, server_port, 0, &hgld));
   1873                     } else {
   1874                         SOC_IF_ERROR_RETURN
   1875                             (READ_HG_LOOKUP_DESTINATIONr(unit, &hgld));
   1876                     }
   1877                     if (server_port == soc_reg_field_get(unit,
   1878                                                         HG_LOOKUP_DESTINATIONr,
   1879                                                         hgld,
   1880                                                         DST_PORTf)) {
   1881                         SOC_IF_ERROR_RETURN
   1882                             (READ_IHG_LOOKUPr(unit, server_port, &val));
   1883                         if (BCM_PROXY_MODE_HIGIG == mode) {
   1884                             hg_enable = soc_reg_field_get(unit, IHG_LOOKUPr, val,
   1885                                                           HG_LOOKUP_ENABLEf);
   1886                         } else {
   1887                             hg_enable = soc_reg_field_get(unit, IHG_LOOKUPr, val,
   1888                                                           HYBRID_MODE_ENABLEf);
   1889                         }
   1890                         *enable = hg_enable;
   1891                     }
   1892                 }
   1893             } else {
   1894                 PBMP_HG_ITER(unit, port) {
   1895                     SOC_PBMP_CLEAR(r_pbmp);
   1896                     BCM_PBMP_PORT_SET(pbmp, server_port);
   1897 
   1898                     SOC_IF_ERROR_RETURN(READ_IHG_LOOKUPr(unit, port, &val));
   1899                     hg_enable = soc_reg_field_get(unit, IHG_LOOKUPr, val,
   1900                                                   HG_LOOKUP_ENABLEf);
   1901                     dst_bmp = soc_reg_field_get(unit, IHG_LOOKUPr, val,
   1902                                                 DST_HG_LOOKUP_BITMAPf);
   1903                     dst_bmp <<= SOC_HG_OFFSET(unit);
   1904                     SOC_PBMP_WORD_SET(r_pbmp, 0, dst_bmp);
   1905                     BCM_PBMP_AND(pbmp, r_pbmp);
   1906 
   1907                     if (hg_enable && BCM_PBMP_EQ(pbmp, r_pbmp)) {
   1908                         *enable = TRUE;
   1909                         break;
   1910                     }
   1911                 }
   1912             }
   1913 	}
   1914 #endif
   1915     }
   1916 
   1917     return rv;
   1918 }
   1919 
   1920 /*
   1921  * Function:
   1922  *      _bcm_esw_proxy_server
   1923  * Purpose:
   1924  *      Enable/disable proxy server
   1925  * Parameters:
   1926  *      unit        -  BCM Unit number
   1927  *      dst         -  Proxy server data
   1928  *      enable      -  server enable/diable flag
   1929  * Returns:
   1930  *      BCM_E_XXX
   1931  */
   1932 STATIC int
   1933 _bcm_esw_proxy_server(int unit, _bcm_proxy_info_t *src, int enable)
   1934 {
   1935     int rv = BCM_E_INTERNAL;
   1936 
   1937 
   1938     rv = _bcm_esw_proxy_server_set(unit, src->server_port, src->mode, enable);
   1939 
   1940     return rv;
   1941 }
   1942 
   1943 /*
   1944  * Function:
   1945  *      _bcm_esw_proxy_server_install
   1946  * Purpose:
   1947  *      Install and enable proxy server
   1948  * Parameters:
   1949  *      unit        -  BCM Unit number
   1950  *      dst         -  Proxy server saved data
   1951  *      src         -  Proxy server initial data
   1952  * Returns:
   1953  *      BCM_E_XXX
   1954  */
   1955 STATIC int
   1956 _bcm_esw_proxy_server_install(int unit,
   1957                               _bcm_proxy_info_t *dst,
   1958                               _bcm_proxy_info_t *src)
   1959 {
   1960     dst->server_port  = src->server_port;
   1961     dst->mode  = src->mode;
   1962     dst->flags |= (_BCM_PROXY_INFO_INSTALLED|_BCM_PROXY_INFO_SERVER);
   1963 
   1964     return _bcm_esw_proxy_server(unit, dst, 1);
   1965 }
   1966 
   1967 /*
   1968  * Function:
   1969  *      _bcm_esw_proxy_server_uninstall
   1970  * Purpose:
   1971  *      Uninstall and disable proxy server
   1972  * Parameters:
   1973  *      unit        -  BCM Unit number
   1974  *      dst         -  Proxy server saved data
   1975  * Returns:
   1976  *      BCM_E_XXX
   1977  */
   1978 STATIC int
   1979 _bcm_esw_proxy_server_uninstall(int unit, _bcm_proxy_info_t *src)
   1980 {
   1981     return _bcm_esw_proxy_server(unit, src, 0);
   1982 }
   1983 
   1984 /*
   1985  * Function:
   1986  *      bcm_esw_proxy_server_set
   1987  * Purpose:
   1988  *      Enables various kinds of lookups for packets coming from remote
   1989  *      (proxy client)
   1990  * Parameters:
   1991  *      unit        -  BCM Unit number
   1992  *      server_port -  Local port to which packets from remote devices are 
   1993  *                     destined to
   1994  *      mode        -  Indicates lookup type
   1995  *      enable      -  TRUE to enable lookups
   1996  *                     FALSE to disable lookups
   1997  * Returns:
   1998  *      BCM_E_XXX
   1999  */
   2000 int
   2001 bcm_esw_proxy_server_set(int unit, bcm_port_t server_port, 
   2002                           bcm_proxy_mode_t mode, int enable)
   2003 {
   2004     _bcm_proxy_info_t src;
   2005 
   2006     if (BCM_GPORT_IS_SET(server_port)) {
   2007         BCM_IF_ERROR_RETURN(
   2008             bcm_esw_port_local_get(unit, server_port, &server_port));
   2009     }
   2010 
   2011     sal_memset(&src, 0, sizeof(_bcm_proxy_info_t));
   2012     src.server_port  = server_port;
   2013     src.mode  = mode;
   2014 
   2015     return _bcm_esw_proxy(unit, &server_methods, &src, enable);
   2016 }
   2017 
   2018 /*
   2019  * Function:
   2020  *      bcm_esw_proxy_server_port_set
   2021  * Purpose:
   2022  *      This API enables various kinds of lookups on XGS3 device on
   2023  *      behalf of remote legacy or XGS3 devices on a per ingress port
   2024  *      basis.  The local ingress port is expected to be a Higig stack
   2025  *      port.  The server_gport in the proxy_server structure is the
   2026  *      target BCM_GPORT_PROXY (modid,port) destination which
   2027  *      indicates that hybrid proxy lookup is required.
   2028  * Parameters:
   2029  *      unit - (IN) Unit number.
   2030  *      local_ingress_port - (IN) Incoming Higig stack port
   2031  *      proxy_server - (IN) Proxy server configuration
   2032  *      enable - (IN) Enable proxy server on selected Higig stack port
   2033  * Returns:
   2034  *      BCM_E_xxx
   2035  * Notes:
   2036  */
   2037 int 
   2038 bcm_esw_proxy_server_port_set(int unit, bcm_gport_t local_ingress_port, 
   2039                               bcm_proxy_server_t *proxy_server, 
   2040                               int enable)
   2041 {
   2042     bcm_module_t    modid;
   2043     bcm_gport_t     server_gport, server_port;
   2044     uint32          val, field_num, rmsp;
   2045     static soc_field_t fields[3] =
   2046         { DST_MODIDf, DST_PORTf, DST_PORT_MASKf };
   2047     uint32          values[3];
   2048     int i = 0;
   2049     uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   2050     uint32 reg_val[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   2051     static soc_reg_t config_regs[] = {
   2052         ING_PACKET_PROCESSING_CONTROL_0r,
   2053         ING_PACKET_PROCESSING_CONTROL_1r
   2054     };    
   2055     static soc_field_t config_reg_fields[] = {
   2056         ING_PACKET_PROCESSING_ENABLE_0f,
   2057         ING_PACKET_PROCESSING_ENABLE_1f
   2058     };
   2059 
   2060     if (!soc_feature(unit, soc_feature_proxy_port_property)) {
   2061         return BCM_E_UNAVAIL;
   2062     }
   2063 
   2064     if ((NULL == proxy_server) && enable) {
   2065         /* No configuration to enable */
   2066         return BCM_E_PARAM;
   2067     }
   2068 
   2069     if (BCM_GPORT_IS_SET(local_ingress_port)) {
   2070         /* Note, modid is a throwaway arg here */
   2071         BCM_IF_ERROR_RETURN
   2072             (_bcm_esw_proxy_gport_resolve(unit, local_ingress_port,
   2073                                           &local_ingress_port, &modid, 1));
   2074     } else if (!SOC_PORT_VALID(unit, local_ingress_port)) { 
   2075         return BCM_E_PORT; 
   2076     }
   2077 
   2078     if (!(IS_HG_PORT(unit, local_ingress_port) ||
   2079           IS_CPU_PORT(unit, local_ingress_port))) {
   2080         
   2081         /* Only Higig ports (including the CPU port as
   2082          * Higig) are valid.
   2083          */
   2084         return BCM_E_PORT;
   2085     }
   2086 
   2087     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
   2088        /* Program relevant TD3 tables and registers */
   2089        BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_port_config(unit, local_ingress_port, proxy_server, enable));
   2090     } else {
   2091         SOC_IF_ERROR_RETURN(READ_IHG_LOOKUPr(unit, local_ingress_port, &val));
   2092 
   2093         if (enable) {
   2094             server_gport = proxy_server->server_gport;
   2095             if (!BCM_GPORT_IS_PROXY(server_gport)) {
   2096                 /* The server gport is required to be in
   2097                  * BCM_GPORT_PROXY format */
   2098                 return BCM_E_PORT;
   2099             }
   2100 
   2101             BCM_IF_ERROR_RETURN
   2102                 (_bcm_esw_proxy_gport_resolve(unit, server_gport,
   2103                                               &server_port, &modid, 0));
   2104 
   2105             if (BCM_PROXY_MODE_HIGIG == proxy_server->mode) {
   2106                 /* BCM_PROXY_MODE_HIGIG */
   2107                 soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2108                                   HG_LOOKUP_ENABLEf, 1);
   2109                 soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2110                                   HYBRID_MODE_ENABLEf, 0);
   2111             } else if (BCM_PROXY_MODE_HYBRID == proxy_server->mode) {
   2112                 /* BCM_PROXY_MODE_HYBRID */
   2113                 soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2114                                   HG_LOOKUP_ENABLEf, 0);
   2115                 soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2116                                   HYBRID_MODE_ENABLEf, 1);
   2117             } else if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) {
   2118                 if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) {
   2119                     return BCM_E_UNAVAIL;
   2120                 }
   2121 
   2122                 if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) ||
   2123                     (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) {
   2124                     return BCM_E_PARAM;
   2125                 }
   2126 
   2127                 /* if exist, update the entry */
   2128                 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   2129                     SOC_IF_ERROR_RETURN
   2130                         (soc_reg32_get(unit, config_regs[i], REG_PORT_ANY, 0, &reg_val[i]));
   2131                     flow_type[i] = soc_reg_field_get(unit,config_regs[i], reg_val[i], FLOW_TYPEf);
   2132 
   2133                     if (proxy_server->flow_type == flow_type[i]) {
   2134                         soc_reg_field_set(unit,config_regs[i],
   2135                             &reg_val[i], FLOW_TYPEf,proxy_server->flow_type);
   2136 
   2137                         soc_reg_field_set(unit,config_regs[i],
   2138                             &reg_val[i], DST_MODIDf, modid);
   2139                         soc_reg_field_set(unit,config_regs[i],
   2140                             &reg_val[i], DST_PORTf, server_port);
   2141 
   2142                         SOC_IF_ERROR_RETURN
   2143                             (soc_reg32_set(unit, config_regs[i], REG_PORT_ANY, 0, reg_val[i]));
   2144 
   2145                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2146                             config_reg_fields[i], 1);
   2147                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2148                             HG_LOOKUP_ENABLEf, 0);
   2149                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2150                             USE_MH_VIDf, 1);
   2151                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2152                             USE_MH_PKT_PRIf, 1);
   2153                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2154                             REMOVE_MH_SRC_PORTf, 1);
   2155 
   2156                         SOC_IF_ERROR_RETURN
   2157                             (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val));
   2158                         return BCM_E_NONE;
   2159                     }
   2160                 }
   2161 
   2162                 /* if not exist, create it */
   2163                 for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   2164                     if (bcmProxySecondPassFlowTypeNone == flow_type[i]) {
   2165                         soc_reg_field_set(unit,config_regs[i],
   2166                             &reg_val[i], FLOW_TYPEf,proxy_server->flow_type);
   2167 
   2168                         soc_reg_field_set(unit,config_regs[i],
   2169                             &reg_val[i], DST_MODIDf, modid);
   2170                         soc_reg_field_set(unit,config_regs[i],
   2171                             &reg_val[i], DST_PORTf, server_port);
   2172 
   2173                         SOC_IF_ERROR_RETURN
   2174                             (soc_reg32_set(unit, config_regs[i], REG_PORT_ANY, 0, reg_val[i]));
   2175 
   2176                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2177                             config_reg_fields[i], 1);
   2178                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2179                             HG_LOOKUP_ENABLEf, 0);
   2180                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2181                             USE_MH_VIDf, 1);
   2182                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2183                             USE_MH_PKT_PRIf, 1);
   2184                         soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2185                             REMOVE_MH_SRC_PORTf, 1);
   2186 
   2187                         SOC_IF_ERROR_RETURN
   2188                             (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val));
   2189 
   2190                         return BCM_E_NONE;
   2191                     }
   2192                 }
   2193 
   2194                 return BCM_E_FULL;
   2195             } else {
   2196                 /* We don't support BCM_PROXY_MODE_LOOPBACK in this per-port
   2197                  * version of the API.
   2198                  */
   2199                 return BCM_E_PARAM;
   2200             }
   2201 
   2202             /* Invert sense for HW settings */
   2203             soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_VIDf,
   2204                     proxy_server->flags & BCM_PROXY_SERVER_KEEP_VID ? 0 : 1);
   2205 
   2206             soc_reg_field_set(unit, IHG_LOOKUPr, &val, USE_MH_PKT_PRIf,
   2207                     proxy_server->flags & BCM_PROXY_SERVER_KEEP_PRIORITY ? 0 :1);
   2208 
   2209             /* Set "magic destination" server port to trigger proxy lookups */
   2210             values[0] = modid;
   2211             values[1] = server_port;
   2212 
   2213             if (SOC_REG_FIELD_VALID(unit, HG_LOOKUP_DESTINATIONr,
   2214                                      DST_PORT_MASKf) &&
   2215                 (proxy_server->flags & BCM_PROXY_SERVER_MASK_PORT)) {
   2216                 values[2] = 1;
   2217                 field_num = 3;
   2218             } else {
   2219                 field_num = 2;
   2220             }
   2221 
   2222             SOC_IF_ERROR_RETURN
   2223                 (soc_reg_fields32_modify(unit, HG_LOOKUP_DESTINATIONr,
   2224                                          local_ingress_port, field_num,
   2225                                          fields, values));
   2226 
   2227             SOC_IF_ERROR_RETURN
   2228                 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val));
   2229         } else {
   2230             if (NULL == proxy_server) {
   2231                 return BCM_E_PARAM;
   2232             }
   2233             if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) {
   2234                 if (soc_feature(unit, soc_feature_hg_proxy_second_pass)) {
   2235 
   2236                     if ((proxy_server->flow_type > bcmProxySecondPassFlowTypeTrillTermination) ||
   2237                         (proxy_server->flow_type < bcmProxySecondPassFlowTypeNone)) {
   2238                         return BCM_E_PARAM;
   2239                     }
   2240 
   2241                     for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   2242                         SOC_IF_ERROR_RETURN
   2243                             (soc_reg32_get(unit, config_regs[i], REG_PORT_ANY, 0, &reg_val[i]));
   2244 
   2245                         flow_type[i] = soc_reg_field_get(unit,config_regs[i], reg_val[i], FLOW_TYPEf);
   2246 
   2247                         if (proxy_server->flow_type == flow_type[i]) {
   2248                             int dglp_is_shared = 0;
   2249                             bcm_gport_t local_port = 0;
   2250                             uint32 return_val = 0;
   2251 
   2252                             soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2253                                 config_reg_fields[i], 0);
   2254                             soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2255                                 USE_MH_VIDf, 0);
   2256                             soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2257                                 USE_MH_PKT_PRIf, 0);
   2258                             soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2259                                 REMOVE_MH_SRC_PORTf, 0);
   2260 
   2261                             SOC_IF_ERROR_RETURN
   2262                                 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val));
   2263 
   2264                             BCM_PBMP_ITER(PBMP_ALL(unit),local_port) {
   2265                                 SOC_IF_ERROR_RETURN
   2266                                     (READ_IHG_LOOKUPr(unit, local_port, &return_val));
   2267                                 if (soc_reg_field_get(unit, IHG_LOOKUPr, return_val, config_reg_fields[i])) {
   2268                                     dglp_is_shared = 1;
   2269                                 }
   2270                             }
   2271 
   2272                             if(!dglp_is_shared) {
   2273                                 soc_reg_field_set(unit,config_regs[i],
   2274                                     &reg_val[i], FLOW_TYPEf,0);
   2275 
   2276                                 soc_reg_field_set(unit,config_regs[i],
   2277                                     &reg_val[i], DST_MODIDf, 0);
   2278                                 soc_reg_field_set(unit,config_regs[i],
   2279                                     &reg_val[i], DST_PORTf, 0);
   2280 
   2281                                 SOC_IF_ERROR_RETURN
   2282                                     (soc_reg32_set(unit, config_regs[i], REG_PORT_ANY, 0, reg_val[i]));
   2283                             }
   2284 
   2285                             return BCM_E_NONE;
   2286                         }
   2287                     }
   2288                     return BCM_E_NOT_FOUND;
   2289                 } else {
   2290                     return BCM_E_UNAVAIL;
   2291                 }
   2292             }
   2293             /* Clear server configuration, but retain the independent
   2294              * source port knockout configuration .
   2295              */
   2296             rmsp = soc_reg_field_get(unit, IHG_LOOKUPr, val,
   2297                                      REMOVE_MH_SRC_PORTf);
   2298             val = 0;
   2299             soc_reg_field_set(unit, IHG_LOOKUPr, &val,
   2300                               REMOVE_MH_SRC_PORTf, rmsp);
   2301             SOC_IF_ERROR_RETURN
   2302                 (WRITE_IHG_LOOKUPr(unit, local_ingress_port, val));
   2303 
   2304             /* Clear the HG_LOOKUP_DESTINATION config */
   2305             SOC_IF_ERROR_RETURN
   2306                 (soc_reg32_set(unit, HG_LOOKUP_DESTINATIONr,
   2307                                local_ingress_port, 0, 0));
   2308         }
   2309     }
   2310     return BCM_E_NONE;
   2311 }
   2312 
   2313 /*
   2314  * Function:
   2315  *      bcm_esw_proxy_server_port_get
   2316  * Purpose:
   2317  *      This API retrieves the current proxy server configuration on a
   2318  *      given Higig stack port, if any.
   2319  * Parameters:
   2320  *      unit - (IN) Unit number.
   2321  *      local_ingress_port - (IN) Incoming Higig stack port
   2322  *      proxy_server - (OUT) Proxy server configuration
   2323  *      enable - (OUT) Enable proxy server on selected Higig stack port
   2324  * Returns:
   2325  *      BCM_E_xxx
   2326  * Notes:
   2327  */
   2328 int 
   2329 bcm_esw_proxy_server_port_get(int unit, bcm_gport_t local_ingress_port, 
   2330                               bcm_proxy_server_t *proxy_server, 
   2331                               int *enable)
   2332 {
   2333     bcm_module_t    modid;
   2334     bcm_gport_t     server_port;
   2335     uint32          cfg_val, dst_val;
   2336     int             hglkup, hybrid;
   2337     bcm_proxy_mode_t mode;
   2338     bcm_module_t reserved_modid = 0;
   2339     bcm_gport_t reserved_port = 0;
   2340     bcm_gport_t server_gport = 0;
   2341     int i = 0;
   2342     uint32 flow_type[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   2343     uint32 reg_val[_BCM_PROXY_RESERVED_DGLP_NUMBER] = {0};
   2344     static soc_reg_t config_regs[] = {
   2345         ING_PACKET_PROCESSING_CONTROL_0r,
   2346         ING_PACKET_PROCESSING_CONTROL_1r,
   2347     };    
   2348     static soc_field_t config_reg_fields[] = {
   2349         ING_PACKET_PROCESSING_ENABLE_0f,
   2350         ING_PACKET_PROCESSING_ENABLE_1f
   2351     };
   2352 
   2353 
   2354     if (!soc_feature(unit, soc_feature_proxy_port_property)) {
   2355         return BCM_E_UNAVAIL;
   2356     }
   2357 
   2358     if ((NULL == proxy_server) || (NULL == enable)) {
   2359         /* No way to return configuration */
   2360         return BCM_E_PARAM;
   2361     }
   2362 
   2363     if (BCM_GPORT_IS_SET(local_ingress_port)) {
   2364         /* Note, modid is a throwaway arg here */
   2365         BCM_IF_ERROR_RETURN
   2366             (_bcm_esw_proxy_gport_resolve(unit, local_ingress_port,
   2367                                           &local_ingress_port, &modid, 1));
   2368     } else if (!SOC_PORT_VALID(unit, local_ingress_port)) { 
   2369         return BCM_E_PORT; 
   2370     }
   2371 
   2372     if (!(IS_HG_PORT(unit, local_ingress_port) ||
   2373           IS_CPU_PORT(unit, local_ingress_port))) {
   2374         
   2375         /* Only Higig ports (including the CPU port as
   2376          * Higig) are valid.
   2377          */
   2378         return BCM_E_PORT;
   2379     }
   2380     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
   2381        /* Program relevant TD3 tables and registers */
   2382        BCM_IF_ERROR_RETURN(bcmi_td3_proxy_server_port_retrieve(unit, local_ingress_port, proxy_server, enable));
   2383     } else {
   2384         SOC_IF_ERROR_RETURN
   2385             (READ_IHG_LOOKUPr(unit, local_ingress_port, &cfg_val));
   2386 
   2387         if (BCM_PROXY_MODE_SECOND_PASS == proxy_server->mode) {
   2388             if (!soc_feature(unit, soc_feature_hg_proxy_second_pass)) {
   2389                 return BCM_E_UNAVAIL;
   2390             }
   2391 
   2392             for(i = 0; i < _BCM_PROXY_RESERVED_DGLP_NUMBER; i++) {
   2393                 SOC_IF_ERROR_RETURN
   2394                     (soc_reg32_get(unit, config_regs[i], REG_PORT_ANY, 0, &reg_val[i]));
   2395                 flow_type[i] = soc_reg_field_get(unit,config_regs[i], reg_val[i], FLOW_TYPEf);
   2396 
   2397                 if (proxy_server->flow_type == flow_type[i]) {
   2398                     reserved_modid = soc_reg_field_get(unit,
   2399                                         config_regs[i], reg_val[i], DST_MODIDf);
   2400 
   2401                     reserved_port = soc_reg_field_get(unit,
   2402                                         config_regs[i], reg_val[i], DST_PORTf);
   2403 
   2404                     BCM_GPORT_PROXY_SET(server_gport, reserved_modid, reserved_port);
   2405 
   2406                     proxy_server->server_gport = server_gport;
   2407 
   2408                     *enable = soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val,
   2409                                                 config_reg_fields[i]);
   2410 
   2411                     return BCM_E_NONE;
   2412                 }
   2413             }
   2414             return BCM_E_NOT_FOUND;
   2415         }
   2416 
   2417         hglkup = soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val,
   2418                                    HG_LOOKUP_ENABLEf);
   2419         hybrid = soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val,
   2420                                    HYBRID_MODE_ENABLEf);
   2421 
   2422         if (hglkup) {
   2423             if (hybrid) {
   2424                 /* Illegal configuration */
   2425                 return BCM_E_INTERNAL;
   2426             } else {
   2427                 *enable = TRUE;
   2428                 mode = BCM_PROXY_MODE_HIGIG;
   2429             }
   2430         } else {
   2431             if (hybrid) {
   2432                 *enable = TRUE;
   2433                 mode = BCM_PROXY_MODE_HYBRID;
   2434             } else {
   2435                 *enable = FALSE;
   2436                 /* Nothing else to do */
   2437                 return BCM_E_NONE;
   2438             }
   2439         }
   2440 
   2441         bcm_proxy_server_t_init(proxy_server);
   2442 
   2443         proxy_server->mode = mode;
   2444 
   2445         /* Invert sense from HW settings */
   2446         if (0 == soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val, USE_MH_VIDf)) {
   2447             proxy_server->flags |= BCM_PROXY_SERVER_KEEP_VID;
   2448         }
   2449 
   2450         if (0 == soc_reg_field_get(unit, IHG_LOOKUPr, cfg_val, USE_MH_PKT_PRIf)) {
   2451             proxy_server->flags |= BCM_PROXY_SERVER_KEEP_PRIORITY;
   2452         }
   2453 
   2454         
   2455         SOC_IF_ERROR_RETURN
   2456             (soc_reg32_get(unit, HG_LOOKUP_DESTINATIONr,
   2457                            local_ingress_port, 0, &dst_val));
   2458 
   2459         if (SOC_REG_FIELD_VALID(unit, HG_LOOKUP_DESTINATIONr,
   2460                                 DST_PORT_MASKf) &&
   2461             soc_reg_field_get(unit, HG_LOOKUP_DESTINATIONr,
   2462                               dst_val, DST_PORT_MASKf)) {
   2463             proxy_server->flags |= BCM_PROXY_SERVER_MASK_PORT;
   2464         }
   2465 
   2466         modid = soc_reg_field_get(unit, HG_LOOKUP_DESTINATIONr,
   2467                                   dst_val, DST_MODIDf);
   2468         server_port = soc_reg_field_get(unit, HG_LOOKUP_DESTINATIONr,
   2469                                         dst_val, DST_PORTf);
   2470         BCM_GPORT_PROXY_SET(proxy_server->server_gport, modid, server_port);
   2471     }
   2472         return BCM_E_NONE;
   2473 
   2474 }
   2475 
   2476 /*
   2477  * Function:
   2478  *      _bcm_esw_proxy_cleanup_data
   2479  * Purpose:
   2480  *      Uninstall and release proxy data
   2481  * Parameters:
   2482  *      unit        -  BCM Unit number
   2483  * Returns:
   2484  *      BCM_E_XXX
   2485  */
   2486 STATIC int
   2487 _bcm_esw_proxy_cleanup_data(int unit)
   2488 {
   2489    _bcm_proxy_ifc_t *ifc;
   2490 
   2491     if (_BCM_PROXY_LOCK(unit)) {
   2492         return BCM_E_INIT;
   2493     }
   2494 
   2495     /* Cleanup clients/servers */
   2496 
   2497     while (_bcm_proxy_control[unit].proxy_list) {
   2498         if (_bcm_proxy_control[unit].proxy_list->flags &
   2499             _BCM_PROXY_INFO_SERVER) {
   2500             ifc = &server_methods;
   2501         } else {
   2502             ifc = &client_methods;
   2503         }
   2504         (void)_bcm_esw_proxy_uninstall
   2505             (unit, ifc, _bcm_proxy_control[unit].proxy_list);
   2506     }
   2507 
   2508     _BCM_PROXY_UNLOCK(unit);
   2509 
   2510     return BCM_E_NONE;
   2511 }
   2512 
   2513 /*
   2514  * Function:
   2515  *      bcm_esw_proxy_init
   2516  * Purpose:
   2517  *      Initialize the Proxy subsystem
   2518  * Parameters:
   2519  *      unit        -  BCM Unit number
   2520  * Returns:
   2521  *      BCM_E_XXX
   2522  */
   2523 int
   2524 bcm_esw_proxy_init(int unit)
   2525 {
   2526     int rv = BCM_E_NONE;
   2527     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
   2528         int port_size = soc_mem_index_count(unit, ING_DEVICE_PORTm) - 1;
   2529         int idx = 0;
   2530 
   2531         if (proxy_internal_initialized[unit]) {
   2532             bcm_esw_proxy_cleanup(unit);
   2533         }
   2534 
   2535         proxy_bookkeep[unit].proxy_server_copy =
   2536             (bcm_proxy_server_t **)
   2537             sal_alloc(_BCM_PROXY_SERVER_INSTANCES *
   2538                     sizeof(bcm_proxy_server_t *), "proxy server sw state entry");
   2539 
   2540         sal_memset(proxy_bookkeep[unit].proxy_server_copy, 0,
   2541                 (_BCM_PROXY_SERVER_INSTANCES * sizeof(bcm_proxy_server_t*)));
   2542 
   2543         if (proxy_bookkeep[unit].proxy_server_copy == NULL) {
   2544             return BCM_E_MEMORY;
   2545         }
   2546 
   2547         for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) {
   2548             proxy_bookkeep[unit].proxy_server_copy[idx] =
   2549                 (bcm_proxy_server_t *)
   2550                 sal_alloc(port_size * sizeof(bcm_proxy_server_t),
   2551                         "per instance proxy server entry");
   2552 
   2553             sal_memset(proxy_bookkeep[unit].proxy_server_copy[idx], 0,
   2554                     (port_size * sizeof(bcm_proxy_server_t)));
   2555 
   2556             if (proxy_bookkeep[unit].proxy_server_copy[idx] == NULL) {
   2557                 bcm_esw_proxy_cleanup(unit);
   2558                 return BCM_E_MEMORY;
   2559             }
   2560         }
   2561     }
   2562     if (_LOCK(unit) == NULL) {
   2563         _LOCK(unit) = sal_mutex_create("bcm_proxy_lock");
   2564         rv = (_LOCK(unit) == NULL) ? BCM_E_MEMORY : BCM_E_NONE;
   2565     }
   2566 
   2567     if (BCM_SUCCESS(rv)) {
   2568         rv = _bcm_esw_proxy_cleanup_data(unit);
   2569     }
   2570     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
   2571         if (BCM_FAILURE(rv)) {
   2572             BCM_IF_ERROR_RETURN(bcm_esw_proxy_cleanup(unit));
   2573             return rv;
   2574         }
   2575 #ifdef BCM_WARM_BOOT_SUPPORT
   2576         if (SOC_WARM_BOOT(unit)) {
   2577             rv = bcmi_proxy_server_recover(unit);
   2578         } else { /* Cold Boot */
   2579             rv = bcmi_proxy_server_wb_alloc(unit);
   2580         }
   2581 #endif /* BCM_WARM_BOOT_SUPPORT */
   2582 
   2583         if (BCM_SUCCESS(rv)) {
   2584             proxy_internal_initialized[unit] = 1;
   2585         }
   2586     }
   2587     return rv;
   2588 }
   2589 
   2590 /*
   2591  * Function:
   2592  *      bcm_esw_proxy_cleanup
   2593  * Purpose:
   2594  *      Deinitialize the Proxy subsystem
   2595  * Parameters:
   2596  *      unit        -  BCM Unit number
   2597  * Returns:
   2598  *      BCM_E_XXX
   2599  */
   2600 int
   2601 bcm_esw_proxy_cleanup(int unit)
   2602 {
   2603     int idx = 0;
   2604     if (_LOCK(unit) != NULL) {
   2605         (void) _bcm_esw_proxy_cleanup_data(unit);
   2606         sal_mutex_destroy(_LOCK(unit));
   2607         _LOCK(unit) = NULL;
   2608     }
   2609     if (soc_feature(unit,soc_feature_td3_style_proxy)) {
   2610         for (idx = 0; idx < _BCM_PROXY_SERVER_INSTANCES; idx++) {
   2611             if (NULL != proxy_bookkeep[unit].proxy_server_copy[idx]) {
   2612                 sal_free(proxy_bookkeep[unit].proxy_server_copy[idx]);
   2613                 proxy_bookkeep[unit].proxy_server_copy[idx] = NULL;
   2614             }
   2615         }
   2616         if (NULL != proxy_bookkeep[unit].proxy_server_copy) {
   2617             sal_free(proxy_bookkeep[unit].proxy_server_copy);
   2618             proxy_bookkeep[unit].proxy_server_copy = NULL;
   2619         }
   2620 
   2621         proxy_internal_initialized[unit] = 0;
   2622     }
   2623     return BCM_E_NONE;
   2624 }
   2625 
   2626 /*
   2627  * Function:
   2628  *      bcm_esw_proxy_egress_create
   2629  * Purpose:
   2630  *      Create Proxy Egress forwarding object.
   2631  * Parameters:
   2632  *      unit    - (IN)  bcm device.
   2633  *      flags   - (IN)  BCM_PROXY_REPLACE: replace existing.
   2634  *                      BCM_PROXY_WITH_ID: intf argument is given.
   2635  *      proxy_egress     - (IN) Egress forwarding destination.
   2636  *      proxy_if_id    - (OUT) proxy interface id pointing to Egress object.
   2637  *                      This is an IN argument if either BCM_PROXY_REPLACE
   2638  *                      or BCM_PROXY_WITH_ID are given in flags.
   2639  * Returns:
   2640  *      BCM_E_XXX
   2641  */
   2642 int 
   2643 bcm_esw_proxy_egress_create(int unit, uint32 flags, bcm_proxy_egress_t *proxy_egress, 
   2644                          bcm_if_t *proxy_if_id)
   2645 {
   2646     int rv = BCM_E_UNAVAIL;
   2647 
   2648 #if defined(BCM_TRIDENT2_SUPPORT)
   2649     if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) {
   2650         bcm_proxy_egress_t proxy_egress_local;
   2651 
   2652         /* Input parameters check. */
   2653         if ((NULL == proxy_egress) || (NULL == proxy_if_id)) {
   2654             return (BCM_E_PARAM);
   2655         }
   2656 
   2657         /* Copy provided structure to local so it can be modified. */
   2658         sal_memcpy(&proxy_egress_local, proxy_egress, sizeof(bcm_proxy_egress_t));
   2659 
   2660         L3_LOCK(unit);
   2661         rv = bcm_td2_proxy_egress_create(unit, flags, &proxy_egress_local, proxy_if_id);
   2662         L3_UNLOCK(unit);
   2663     }
   2664 #endif /* BCM_TRIDENT2_SUPPORT*/
   2665 
   2666     return rv;
   2667 }
   2668 
   2669 /*
   2670  * Function:
   2671  *      bcm_esw_proxy_egress_destroy
   2672  * Purpose:
   2673  *      Destroy Proxy Egress forwarding destination.
   2674  * Parameters:
   2675  *      unit    - (IN) bcm device.
   2676  *      proxy_if_id    - (IN) proxy interface id pointing to Egress object
   2677  * Returns:
   2678  *      BCM_E_XXX
   2679  */
   2680 int 
   2681 bcm_esw_proxy_egress_destroy(int unit, bcm_if_t proxy_if_id)
   2682 {
   2683     int rv = BCM_E_UNAVAIL;
   2684 
   2685 #if defined(BCM_TRIDENT2_SUPPORT)
   2686     if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) {
   2687 
   2688         L3_LOCK(unit);
   2689         rv = bcm_td2_proxy_egress_destroy(unit, proxy_if_id);
   2690         L3_UNLOCK(unit);
   2691     }
   2692 #endif /* BCM_TRIDENT2_SUPPORT*/
   2693 
   2694     return rv;
   2695 }
   2696 
   2697 /*
   2698  * Function:
   2699  *      bcm_esw_proxy_egress_get
   2700  * Purpose:
   2701  *      Get Proxy Egress forwarding destination.
   2702  * Parameters:
   2703  *      unit    - (IN) bcm device.
   2704  *      proxy_if_id    - (IN) Proxy Egress destination
   2705  *      proxy_egress    - (OUT) Egress forwarding destination.
   2706  * Returns:
   2707  *      BCM_E_XXX
   2708  */
   2709 int 
   2710 bcm_esw_proxy_egress_get (int unit, bcm_if_t proxy_if_id, bcm_proxy_egress_t *proxy_egress) 
   2711 {
   2712     int rv = BCM_E_UNAVAIL;
   2713 
   2714 #if defined(BCM_TRIDENT2_SUPPORT)
   2715     if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) {
   2716         /* Input parameters check. */
   2717         if (NULL == proxy_egress) {
   2718             return (BCM_E_PARAM);
   2719         }
   2720 
   2721         L3_LOCK(unit);
   2722         rv = bcm_td2_proxy_egress_get (unit, proxy_if_id, proxy_egress);
   2723         L3_UNLOCK(unit);
   2724     }
   2725 #endif /* BCM_TRIDENT2_SUPPORT*/
   2726 
   2727     return rv;
   2728 }
   2729 
   2730 
   2731 /*
   2732  * Function:
   2733  *      bcm_esw_proxy_egress_traverse
   2734  * Purpose:
   2735  *      Goes through proxy egress objects table and runs the user callback
   2736  *      function at each valid egress objects entry passing back the
   2737  *      information for that object.
   2738  * Parameters:
   2739  *      unit       - (IN) bcm device.
   2740  *      trav_fn    - (IN) Callback function. 
   2741  *      user_data  - (IN) User data to be passed to callback function.
   2742  * Returns:
   2743  *      BCM_E_XXX
   2744  */
   2745 int 
   2746 bcm_esw_proxy_egress_traverse(int unit, 
   2747                            bcm_proxy_egress_traverse_cb trav_fn, void *user_data)
   2748 {
   2749     int rv = BCM_E_UNAVAIL;
   2750 
   2751 #if defined(BCM_TRIDENT2_SUPPORT)
   2752     if (SOC_IS_TD2_TT2(unit) && soc_feature(unit, soc_feature_l3)) {
   2753         L3_LOCK(unit);
   2754         rv = bcm_td2_proxy_egress_traverse(unit, trav_fn, user_data);
   2755         L3_UNLOCK(unit);
   2756 
   2757     }
   2758 #endif /* BCM_TRIDENT2_SUPPORT*/
   2759 
   2760     return rv;
   2761 }
   2762 
   2763 #else /* INCLUDE_L3 */
   2764 int _bcm_esw_proxy_not_empty;
   2765 #endif /* INCLUDE_L3 */