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

bregex.c (149676B)


      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  * COS Queue Management
      8  * Purpose: API to program Regex engine for flow tracking
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <sal/core/libc.h>
     14 #if defined(INCLUDE_REGEX)
     15 
     16 #include <soc/drv.h>
     17 #include <soc/mem.h>
     18 
     19 #include <bcm/error.h>
     20 #include <bcm/cosq.h>
     21 
     22 #include <bcm_int/esw/mbcm.h>
     23 #include <bcm_int/esw/stack.h>
     24 #include <bcm_int/esw/firebolt.h>
     25 #include <bcm_int/esw/triumph.h>
     26 #include <bcm_int/esw/triumph2.h>
     27 #include <bcm_int/esw/policer.h>
     28 #include <bcm_int/esw/mirror.h>
     29 #include <bcm_int/esw/fb4regex.h>
     30 #include <bcm_int/esw/bregex.h>
     31 #include <bcm/bregex.h>
     32 #include <bcm_int/esw_dispatch.h>
     33 
     34 STATIC _bcm_esw_regex_device_info_t *_regex_info[BCM_MAX_NUM_UNITS] = {0};
     35 
     36 #define ESW_REGEX_INFO(_unit)   _regex_info[_unit]
     37 #define ESW_REGEX_LOCK(_unit)   _regex_lock(_unit)
     38 #define ESW_REGEX_UNLOCK(_unit) _regex_unlock(_unit)
     39 
     40 /* This macro will return one less than the physical number of policies because the first
     41  * policy entry is reserved for the default policy. */
     42 #define ESW_REGEX_POLICIES_MAX(_unit)   (ESW_REGEX_INFO(_unit)->policy_index_max - ESW_REGEX_INFO(_unit)->policy_index_min)
     43 /* This macro will return one more than the first index since the first entry is reserved
     44  * for the default policy. */
     45 #define ESW_REGEX_POLICIES_FIRST(_unit) (ESW_REGEX_INFO(_unit)->policy_index_min + 1)
     46 #define ESW_REGEX_POLICIES_LAST(_unit)  (ESW_REGEX_INFO(_unit)->policy_index_max)
     47 
     48 #define IS_FLOW_MODE(f_pl)                          \
     49     ((f_pl)->cfg.mode == bcmPolicerModeCommitted || \
     50      (f_pl)->cfg.mode == bcmPolicerModePeak)
     51 
     52 #define IS_MOD_TRTCM_MODE(f_pl)                                 \
     53     ((f_pl)->cfg.mode == bcmPolicerModeTrTcmDs ||               \
     54      (f_pl)->cfg.mode == bcmPolicerModeCoupledTrTcmDs)
     55 
     56 STATIC int last_allocated_policy = 0;
     57 
     58 STATIC int _regex_policy_create_id(int unit, bcm_regex_policy_t policy);
     59 STATIC int _regex_policy_install(int unit, bcm_regex_policy_t policy);
     60 
     61 STATIC int _regex_lock(int unit)
     62 {
     63     _bcm_esw_regex_device_info_t *device;
     64 
     65     device = ESW_REGEX_INFO(unit);
     66     if (NULL == device) {
     67         return BCM_E_INIT;
     68     }
     69 
     70     sal_mutex_take(device->regex_esw_mutex, sal_mutex_FOREVER);
     71     return BCM_E_NONE;
     72 }
     73 
     74 STATIC void _regex_unlock(int unit)
     75 {
     76     _bcm_esw_regex_device_info_t *device;
     77 
     78     device = ESW_REGEX_INFO(unit);
     79     sal_mutex_give(device->regex_esw_mutex);
     80 }
     81 
     82 void _bcm_esw_regex_policy_action_t_init(_regex_policy_action_t *pa)
     83 {
     84     sal_memset(pa, 0, sizeof(*pa));
     85     pa->hw_index  = _REGEX_INVALID_INDEX;
     86     pa->old_index = _REGEX_INVALID_INDEX;
     87 }
     88 
     89 void _bcm_esw_regex_policy_t_init(_regex_policy_t *policy)
     90 {
     91     int idx;
     92 
     93     sal_memset(policy, 0, sizeof(*policy));
     94 
     95     policy->statistic.sid = _REGEX_INVALID_INDEX;
     96     /* Initialize policer ids as invalid for all policer levels. */
     97     for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) {
     98         policy->policer[idx].pid = _REGEX_INVALID_INDEX;
     99     }
    100 }
    101 
    102 void _bcm_esw_regex_device_info_t_init(_bcm_esw_regex_device_info_t *info)
    103 {
    104     sal_memset(info, 0, sizeof(*info));
    105 }
    106 
    107 /*
    108  * Function:
    109  *     _regex_policy_action_name
    110  * Purpose:
    111  *     Return text name of indicated action enum value.
    112  */
    113 STATIC char *_regex_policy_action_name(bcm_field_action_t action)
    114 {
    115     /* Text names of Actions. These are used for debugging output and CLIs.
    116      * Note that the order needs to match the bcm_field_action_t enum order.
    117      */
    118     static char *action_text[] = BCM_FIELD_ACTION_STRINGS;
    119     assert(COUNTOF(action_text) == bcmFieldActionCount);
    120 
    121     return (action >= bcmFieldActionCount ? "??" : action_text[action]);
    122 }
    123 
    124 /*
    125  * Function:
    126  *     _bcm_regex_policy_action_dest_check
    127  * Purpose:
    128  *     Verify destination prameters for fp actions
    129  * Parameters:
    130  *     unit    - (IN) BCM device number
    131  *     fa      - (IN) Field action structure.
    132  * Returns:
    133  *     BCM_E_XXX
    134  */
    135 int _bcm_regex_policy_action_dest_check(int unit, _regex_policy_action_t *pa)
    136 {
    137     int port_out;     /* Calculated port value.    */
    138     int modid_out;    /* Calculated module id.     */
    139     int rv;           /* Operation return value.   */
    140 
    141     /* Input parameters check. */
    142     if (NULL == pa) {
    143         return (BCM_E_PARAM);
    144     }
    145 
    146     /* No checks for Mirror/Mpls/Mim/Wlan gports  */
    147     if (BCM_GPORT_IS_SET(pa->param[1])) {
    148         return (BCM_E_NONE);
    149     }
    150 
    151     /* Modport/Trunk were resolved in _field_params_api_to_hw_adapt call.*/
    152     if (bcmFieldActionRedirectTrunk == pa->action) {
    153         return  _bcm_trunk_id_validate(unit, pa->param[0]);
    154     }
    155 
    156     /* Check destination module id / port. */
    157     rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
    158                                 pa->param[0], pa->param[1],
    159                                 &modid_out, &port_out);
    160     BCM_IF_ERROR_RETURN(rv);
    161 
    162     if (!SOC_MODID_ADDRESSABLE(unit, modid_out)) {
    163         return (BCM_E_PARAM);
    164     }
    165     if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
    166         return (BCM_E_PORT);
    167     }
    168     return (BCM_E_NONE);
    169 }
    170 
    171 int bcm_esw_regex_config_set(int unit, bcm_regex_config_t *config)
    172 {
    173     _bcm_esw_regex_device_info_t *device;
    174 
    175     if (!soc_feature(unit, soc_feature_regex)) {
    176         return BCM_E_UNAVAIL;
    177     }
    178 
    179     if (NULL == config) {
    180         return BCM_E_PARAM;
    181     }
    182 
    183     device = ESW_REGEX_INFO(unit);
    184     if (NULL == device) {
    185         return BCM_E_INIT;
    186     }
    187 
    188     device->flags = config->flags;
    189     device->report_buffer_size = config->report_buffer_size;
    190 
    191 #if defined(BCM_TRIUMPH3_SUPPORT)
    192     if (SOC_IS_TRIUMPH3(unit)) {
    193         return _bcm_tr3_regex_config_set(unit, config);
    194     }
    195 #endif /* BCM_TRIUMPH3_SUPPORT */    
    196 
    197     return BCM_E_UNAVAIL;
    198 }
    199 
    200 int bcm_esw_regex_config_get(int unit, bcm_regex_config_t *config)
    201 {
    202     _bcm_esw_regex_device_info_t *device;
    203 
    204     if (!soc_feature(unit, soc_feature_regex)) {
    205         return BCM_E_UNAVAIL;
    206     }
    207 
    208     if (NULL == config) {
    209         return BCM_E_PARAM;
    210     }
    211 
    212     device = ESW_REGEX_INFO(unit);
    213     if (NULL == device) {
    214         return BCM_E_INIT;
    215     }
    216 
    217     config->flags = device->flags;
    218     config->report_buffer_size = device->report_buffer_size;
    219 
    220 #if defined(BCM_TRIUMPH3_SUPPORT)
    221     if (SOC_IS_TRIUMPH3(unit)) {
    222         return _bcm_tr3_regex_config_get(unit, config);
    223     }
    224 #endif /* BCM_TRIUMPH3_SUPPORT */    
    225 
    226     return BCM_E_UNAVAIL;
    227 }
    228 
    229 int bcm_esw_regex_exclude_add(int unit, uint8 protocol, 
    230                             uint16 l4_start, uint16 l4_end)
    231 {
    232     if (!soc_feature(unit, soc_feature_regex)) {
    233         return BCM_E_UNAVAIL;
    234     }
    235 
    236 #if defined(BCM_TRIUMPH3_SUPPORT)
    237     if (SOC_IS_TRIUMPH3(unit)) {
    238         return _bcm_tr3_regex_exclude_add(unit, protocol, l4_start, l4_end);
    239     }
    240 #endif /* BCM_TRIUMPH3_SUPPORT */    
    241 
    242     return BCM_E_UNAVAIL;
    243 }
    244 
    245 int bcm_esw_regex_exclude_delete(int unit, uint8 protocol, 
    246                             uint16 l4_start, uint16 l4_end)
    247 {
    248     if (!soc_feature(unit, soc_feature_regex)) {
    249         return BCM_E_UNAVAIL;
    250     }
    251 
    252 #if defined(BCM_TRIUMPH3_SUPPORT)
    253     if (SOC_IS_TRIUMPH3(unit)) {
    254         return _bcm_tr3_regex_exclude_delete(unit, protocol, l4_start, l4_end);
    255     }
    256 #endif /* BCM_TRIUMPH3_SUPPORT */    
    257 
    258     return BCM_E_UNAVAIL;
    259 }
    260 
    261 int bcm_esw_regex_exclude_delete_all(int unit)
    262 {
    263     if (!soc_feature(unit, soc_feature_regex)) {
    264         return BCM_E_UNAVAIL;
    265     }
    266 
    267 #if defined(BCM_TRIUMPH3_SUPPORT)
    268     if (SOC_IS_TRIUMPH3(unit)) {
    269         return _bcm_tr3_regex_exclude_delete_all(unit);
    270     }
    271 #endif /* BCM_TRIUMPH3_SUPPORT */    
    272 
    273     return BCM_E_UNAVAIL;
    274 }
    275 
    276 int bcm_esw_regex_exclude_get(int unit, int array_size, uint8 *protocol, 
    277                                 uint16 *l4low, uint16 *l4high, int *array_count)
    278 {
    279     if (!soc_feature(unit, soc_feature_regex)) {
    280         return BCM_E_UNAVAIL;
    281     }
    282 
    283     if (!(array_size && protocol && l4low && l4high && array_count)) {
    284         return BCM_E_PARAM;
    285     }
    286 
    287 #if defined(BCM_TRIUMPH3_SUPPORT)
    288     if (SOC_IS_TRIUMPH3(unit)) {
    289         return _bcm_tr3_regex_exclude_get(unit, array_size, protocol,
    290                                          l4low, l4high, array_count);
    291     }
    292 #endif /* BCM_TRIUMPH3_SUPPORT */    
    293 
    294     return BCM_E_UNAVAIL;
    295 }
    296 
    297 int bcm_esw_regex_engine_create(int unit, bcm_regex_engine_config_t *config, 
    298                             bcm_regex_engine_t *engid)
    299 {
    300     if (!soc_feature(unit, soc_feature_regex)) {
    301         return BCM_E_UNAVAIL;
    302     }
    303 
    304 #if defined(BCM_TRIUMPH3_SUPPORT)
    305     if (SOC_IS_TRIUMPH3(unit)) {
    306         return _bcm_tr3_regex_engine_create(unit, config, engid);
    307     }
    308 #endif /* BCM_TRIUMPH3_SUPPORT */    
    309 
    310     return BCM_E_UNAVAIL;
    311 }
    312 
    313 int bcm_esw_regex_engine_destroy(int unit, bcm_regex_engine_t engid)
    314 {
    315     if (!soc_feature(unit, soc_feature_regex)) {
    316         return BCM_E_UNAVAIL;
    317     }
    318 
    319 #if defined(BCM_TRIUMPH3_SUPPORT)
    320     if (SOC_IS_TRIUMPH3(unit)) {
    321         return _bcm_tr3_regex_engine_destroy(unit, engid);
    322     }
    323 #endif /* BCM_TRIUMPH3_SUPPORT */    
    324 
    325     return BCM_E_UNAVAIL;
    326 }
    327 
    328 int bcm_esw_regex_engine_traverse(int unit, bcm_regex_engine_traverse_cb cb, 
    329                                 void *user_data)
    330 {
    331     if (!soc_feature(unit, soc_feature_regex)) {
    332         return BCM_E_UNAVAIL;
    333     }
    334 
    335 #if defined(BCM_TRIUMPH3_SUPPORT)
    336     if (SOC_IS_TRIUMPH3(unit)) {
    337         return _bcm_tr3_regex_engine_traverse(unit, cb, user_data);
    338     }
    339 #endif /* BCM_TRIUMPH3_SUPPORT */    
    340 
    341     return BCM_E_UNAVAIL;
    342 }
    343 
    344 int bcm_esw_regex_engine_get(int unit, bcm_regex_engine_t engid, 
    345                             bcm_regex_engine_config_t *config)
    346 {
    347     if (!soc_feature(unit, soc_feature_regex)) {
    348         return BCM_E_UNAVAIL;
    349     }
    350 
    351 #if defined(BCM_TRIUMPH3_SUPPORT)
    352     if (SOC_IS_TRIUMPH3(unit)) {
    353         return _bcm_tr3_regex_engine_get(unit, engid, config);
    354     }
    355 #endif /* BCM_TRIUMPH3_SUPPORT */    
    356 
    357     return BCM_E_UNAVAIL;
    358 }
    359 
    360 int bcm_esw_regex_match_check(int unit, bcm_regex_match_t* match, 
    361                                 int count, int* metric)
    362 {
    363     if (!soc_feature(unit, soc_feature_regex)) {
    364         return BCM_E_UNAVAIL;
    365     }
    366 
    367 #if defined(BCM_TRIUMPH3_SUPPORT)
    368     if (SOC_IS_TRIUMPH3(unit)) {
    369         return _bcm_tr3_regex_match_check(unit, match, count, metric);
    370 
    371     }
    372 #endif /* BCM_TRIUMPH3_SUPPORT */    
    373 
    374     return BCM_E_UNAVAIL;
    375 }
    376 
    377 int _regex_policy_get(int unit, bcm_regex_policy_t policy, _regex_policy_t **policy_p);
    378 
    379 int bcm_esw_regex_match_set(int unit, bcm_regex_engine_t engid,
    380                             bcm_regex_match_t* match, int count)
    381 {
    382     _bcm_esw_regex_device_info_t *device;
    383 
    384 #if defined(BCM_TRIUMPH3_SUPPORT)
    385     int i, rv;
    386     _regex_policy_t *p_policy;
    387 #endif
    388 
    389     if (!soc_feature(unit, soc_feature_regex)) {
    390         return BCM_E_UNAVAIL;
    391     }
    392 
    393     device = ESW_REGEX_INFO(unit);
    394     if (NULL == device) {
    395         return BCM_E_INIT;
    396     }
    397 
    398 #if defined(BCM_TRIUMPH3_SUPPORT)
    399     if (SOC_IS_TRIUMPH3(unit)) {
    400         if (count > 0) {
    401             for (i = 0; i < count; i++) {
    402                 if (match[i].action_flags & BCM_REGEX_MATCH_ACTION_NON_POLICY_ACTIONS) {
    403                     if (0 != (device->flags & BCM_REGEX_USE_POLICY_ID)) {
    404                         return BCM_E_PARAM;
    405                     }
    406                     if (match[i].policy_id != -1) {
    407                         return BCM_E_PARAM;
    408                     }
    409                 }
    410                 else
    411                 {
    412                     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
    413                         return BCM_E_PARAM;
    414                     }
    415                     if (match[i].policy_id == -1) {
    416                         return BCM_E_PARAM;
    417                     }
    418                     rv = _regex_policy_get(unit, match[i].policy_id, &p_policy);
    419                     BCM_IF_ERROR_RETURN(rv);
    420 
    421                     if ((p_policy->flags & _REGEX_POLICY_INSTALLED) == 0) {
    422                         return BCM_E_PARAM;
    423                     }
    424                 }
    425             }
    426         }
    427 
    428         return _bcm_tr3_regex_match_set(unit, engid, match, count);
    429     }
    430 #endif /* BCM_TRIUMPH3_SUPPORT */
    431 
    432     return BCM_E_UNAVAIL;
    433 }
    434 
    435 
    436 int bcm_esw_regex_get_match_id(int unit, int signature_id, int *match_id)
    437 {
    438     if (!soc_feature(unit, soc_feature_regex)) {
    439         return BCM_E_UNAVAIL;
    440     }
    441 
    442 #if defined(BCM_TRIUMPH3_SUPPORT)
    443     if (SOC_IS_TRIUMPH3(unit)) {
    444         return _bcm_tr3_get_match_id(unit, signature_id, match_id);
    445     }
    446 #endif /* BCM_TRIUMPH3_SUPPORT */
    447 
    448     return BCM_E_UNAVAIL;
    449 }
    450 
    451 
    452 int bcm_esw_regex_get_sig_id(int unit, int match_id, int *signature_id)
    453 {
    454     if (!soc_feature(unit, soc_feature_regex)) {
    455         return BCM_E_UNAVAIL;
    456     }
    457 
    458 #if defined(BCM_TRIUMPH3_SUPPORT)
    459     if (SOC_IS_TRIUMPH3(unit)) {
    460         return _bcm_tr3_get_sig_id(unit, match_id, signature_id);
    461     }
    462 #endif /* BCM_TRIUMPH3_SUPPORT */
    463 
    464     return BCM_E_UNAVAIL;
    465 }
    466 
    467 #define BCM_REGEX_NUM_SLOT_PER_CPS 16
    468 
    469 typedef struct _bcm_regex_cps_obj_pub_s {
    470     uint32    flags;
    471     int             foff;
    472     int             alloc_map[BCM_REGEX_NUM_SLOT_PER_CPS];
    473     int             refcnt[BCM_REGEX_NUM_SLOT_PER_CPS];
    474     int             from_line;
    475     int             req_lsz;
    476 } _bcm_regex_cps_obj_pub_t;
    477 
    478 int bcm_esw_regex_engine_info_get(int unit, int engine_id,
    479                               bcm_regex_engine_info_t *engine_info)
    480 {
    481     if (!soc_feature(unit, soc_feature_regex)) {
    482         return BCM_E_UNAVAIL;
    483     }
    484 
    485 #if defined(BCM_TRIUMPH3_SUPPORT)
    486     if (SOC_IS_TRIUMPH3(unit)) {
    487         return _bcm_tr3_get_engine_size_info(unit, engine_id, engine_info);
    488     }
    489 #endif /* BCM_TRIUMPH3_SUPPORT */
    490 
    491     return BCM_E_UNAVAIL;
    492 }
    493 
    494 
    495 int bcm_esw_regex_info_get(int unit, bcm_regex_info_t *regex_info)
    496 {
    497 #if defined(BCM_TRIUMPH3_SUPPORT)
    498     _bcm_esw_regex_device_info_t *device;
    499 #endif
    500 
    501     if (!soc_feature(unit, soc_feature_regex)) {
    502         return BCM_E_UNAVAIL;
    503     }
    504 
    505 #if defined(BCM_TRIUMPH3_SUPPORT)
    506     if (SOC_IS_TRIUMPH3(unit)) {
    507         /*
    508         Assume we are using the new policy tables.  If not,
    509         these values will be overwritten by the old values.
    510         */
    511         regex_info->policy_size = ESW_REGEX_POLICIES_MAX(unit) + 1;
    512         device = ESW_REGEX_INFO(unit);
    513         regex_info->policy_free_size = regex_info->policy_size - device->num_policies;
    514 
    515         return _bcm_tr3_regex_info_get(unit, regex_info);
    516     }
    517 #endif /* BCM_TRIUMPH3_SUPPORT */
    518 
    519     return BCM_E_UNAVAIL;
    520 }
    521 
    522 
    523 int bcm_esw_regex_report_register(int unit, uint32 reports, 
    524                                   bcm_regex_report_cb callback, void *user_data)
    525 {
    526     if (!soc_feature(unit, soc_feature_regex)) {
    527         return BCM_E_UNAVAIL;
    528     }
    529 
    530 #if defined(BCM_TRIUMPH3_SUPPORT)
    531     if (SOC_IS_TRIUMPH3(unit)) {
    532         return _bcm_esw_regex_report_register(unit, reports, 
    533                                              callback, user_data);
    534     }
    535 #endif /* BCM_TRIUMPH3_SUPPORT */    
    536 
    537     return BCM_E_UNAVAIL;
    538 }
    539 
    540 int  bcm_esw_regex_stat_get(int unit, bcm_regex_stat_t type, uint64 *val)
    541 {
    542     if (!soc_feature(unit, soc_feature_regex)) {
    543         return BCM_E_UNAVAIL;
    544     }
    545 
    546 #if defined(BCM_TRIUMPH3_SUPPORT)
    547     if (SOC_IS_TRIUMPH3(unit)) {
    548         return _bcm_tr3_regex_stat_get(unit, type, val);
    549     }
    550 #endif /* BCM_TRIUMPH3_SUPPORT */
    551 
    552     return BCM_E_UNAVAIL;
    553 }
    554 
    555 int  bcm_esw_regex_stat_set(int unit, bcm_regex_stat_t type, uint64 val)
    556 {
    557     if (!soc_feature(unit, soc_feature_regex)) {
    558         return BCM_E_UNAVAIL;
    559     }
    560 
    561 #if defined(BCM_TRIUMPH3_SUPPORT)
    562     if (SOC_IS_TRIUMPH3(unit)) {
    563         return _bcm_tr3_regex_stat_set(unit, type, val);
    564     }
    565 #endif /* BCM_TRIUMPH3_SUPPORT */
    566 
    567     return BCM_E_UNAVAIL;
    568 }
    569 
    570 int bcm_esw_regex_report_unregister(int unit, uint32 reports, 
    571                                 bcm_regex_report_cb callback, void *user_data)
    572 {
    573     if (!soc_feature(unit, soc_feature_regex)) {
    574         return BCM_E_UNAVAIL;
    575     }
    576 
    577 #if defined(BCM_TRIUMPH3_SUPPORT)
    578     if (SOC_IS_TRIUMPH3(unit)) {
    579         return _bcm_esw_regex_report_unregister(unit, reports, 
    580                                                callback, user_data);
    581     }
    582 #endif /* BCM_TRIUMPH3_SUPPORT */    
    583 
    584     return BCM_E_UNAVAIL;
    585 }
    586 
    587 int bcm_esw_regex_init(int unit)
    588 {
    589     int rv = BCM_E_UNAVAIL;
    590     _bcm_esw_regex_device_info_t *info;
    591     _field_stage_t               *field_stage;
    592 
    593     if (!soc_feature(unit, soc_feature_regex)) {
    594         return BCM_E_UNAVAIL;
    595     }
    596 
    597     last_allocated_policy = 0;
    598     /* Init regex info.  */
    599     info = ESW_REGEX_INFO(unit);
    600     if (NULL == info) {
    601         info = sal_alloc(sizeof(*info), "_regex_info");
    602         if (NULL == info) {
    603             return BCM_E_MEMORY;
    604         }
    605         ESW_REGEX_INFO(unit) = info;
    606         _bcm_esw_regex_device_info_t_init(info);
    607     }
    608 
    609 #if defined(BCM_TRIUMPH3_SUPPORT)
    610     if (SOC_IS_TRIUMPH3(unit)) {
    611         rv = _bcm_tr3_regex_init(unit, &info->functions);
    612     }
    613 #endif
    614     if (BCM_FAILURE(rv)) {
    615         return rv;
    616     }
    617 
    618     info->regex_esw_mutex = sal_mutex_create("regex_esw_mutex");
    619 
    620     info->policy_index_min = info->functions->policy_index_min_get(unit);
    621     info->policy_index_max = info->functions->policy_index_max_get(unit);
    622 
    623     /* The last meter pool is reserved for use by the regex component so the Field
    624      * Processor will only have (total pools - 1).  Calculate the starting HW index of the
    625      * last pool and ensure that it is valid. */
    626     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &field_stage));
    627     info->meter_base_hw_index = field_stage->num_meter_pools * field_stage->meter_pool[_FP_DEF_INST][0]->pool_size;
    628     info->meter_pool = field_stage->num_meter_pools;
    629     assert(soc_mem_index_count(unit, FP_METER_TABLEm) > info->meter_base_hw_index);
    630 
    631     /*
    632      * Initialize default policy (which does nothing):
    633      * _bcm_tr3_regex_init creates a empty policy entry 0 (by calling legacy function
    634      * _bcm_tr3_install_action_policy).  Initialize the policy 0 data here.
    635      */
    636     _regex_policy_create_id(unit, _REGEX_DEFAULT_POLICY_ID);
    637     _regex_policy_install(unit, _REGEX_DEFAULT_POLICY_ID);
    638 
    639     return BCM_E_NONE;
    640 }
    641 
    642 int _bcm_esw_regex_sync(int unit)
    643 {
    644 #ifdef BCM_WARM_BOOT_SUPPORT
    645 #if defined(BCM_TRIUMPH3_SUPPORT)
    646     if (SOC_IS_TRIUMPH3(unit) && soc_feature(unit, soc_feature_regex)) {
    647         return _bcm_esw_tr3_regex_sync(unit);
    648     }
    649 #endif
    650 #endif
    651     return BCM_E_UNAVAIL;
    652 }
    653 
    654 /*
    655  * Function:
    656  *     _regex_policy_dirty
    657  * Purpose:
    658  *     Check if policy was modified after last installation
    659  * Parameters:
    660  *     unit        - (IN)  BCM device number.
    661  *     p_ent       - (IN)  Regex policy pointer.
    662  *     dirty       - (OUT) Entry dirty flag.
    663  * Returns:
    664  *     BCM_E_XXX
    665  */
    666 int _regex_policy_dirty(int unit, _regex_policy_t *p_ent, int *dirty)
    667 {
    668     _field_entry_policer_t *f_ent_pl;   /* Field entry policer structure.*/
    669     _field_policer_t       *f_pl;       /* Field policer descriptor.     */
    670     int                     rv;         /* Operation return status.      */
    671     int                     idx;
    672 
    673     /* Input parameters check. */
    674     if ((NULL == p_ent) || (NULL == dirty)) {
    675         return (BCM_E_PARAM);
    676     }
    677 
    678     *dirty = (p_ent->flags & _REGEX_POLICY_DIRTY) ? TRUE : FALSE;
    679 
    680     if (0 == (*dirty)) {
    681         /* Policer configuration updates check. */
    682         for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) {
    683             f_ent_pl = p_ent->policer + idx;
    684             /* Skip invalid policers. */
    685             if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
    686                 continue;
    687             }
    688             /* Read policer configuration.*/
    689             rv = _bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl);
    690             BCM_IF_ERROR_RETURN(rv);
    691 
    692             /* Check if policer was modified. */
    693             if (f_pl->hw_flags & _FP_POLICER_DIRTY) {
    694                 *dirty = TRUE;
    695                 break;
    696             }
    697         }
    698     }
    699 
    700     return (BCM_E_NONE);
    701 }
    702 
    703 /*
    704  * Function:
    705  *      _regex_policy_t_compare
    706  * Purpose:
    707  *      Compare entry id in _regex_policy_t structure.
    708  * Parameters:
    709  *      b - (IN) first  compared qualifier.
    710  *      a - (IN) second compared qualifier.
    711  * Returns:
    712  *      a<=>b
    713  */
    714 STATIC int _regex_policy_t_compare(void *a, void *b)
    715 {
    716     _regex_policy_t **first;     /* First compared entry.  */
    717     _regex_policy_t **second;    /* Second compared entry. */
    718 
    719     first =  (_regex_policy_t **)a;
    720     second = (_regex_policy_t **)b;
    721 
    722     if ((*first)->eid < (*second)->eid) {
    723         return (-1);
    724     } else if ((*first)->eid > (*second)->eid) {
    725         return (1);
    726     }
    727     return (0);
    728 }
    729 
    730 /*
    731  * Function:
    732  *     _regex_policy_get
    733  * Purpose:
    734  *     Lookup a policy (entry) from a unit ID and policy id choice.
    735  * Parmeters:
    736  *     unit     - (IN) BCM device number.
    737  *     policy   - (IN) Policy id.
    738  *     policy_p - (OUT) Entry lookup result.
    739  * Returns:
    740  *     BCM_E_XXX
    741  */
    742 int _regex_policy_get(int unit, bcm_regex_policy_t policy, _regex_policy_t **policy_p)
    743 {
    744     _regex_policy_t               target;         /* Entry lookup pointer.    */
    745     _regex_policy_t              *p_ent;          /* Entry lookup pointer.    */
    746     _bcm_esw_regex_device_info_t *device;         /* Regex control structure. */
    747     int                           idx;            /* Entry index.             */
    748 
    749     /* Reset target entry */
    750     target.eid = policy;
    751     p_ent = &target;
    752 
    753     device = ESW_REGEX_INFO(unit);
    754     if (NULL == device) {
    755         return BCM_E_INIT;
    756     }
    757 
    758     if (NULL == device->policies) {
    759         return (BCM_E_NOT_FOUND);
    760     }
    761 
    762     ESW_REGEX_LOCK(unit);
    763 
    764     idx = _shr_bsearch(device->policies, device->num_policies,
    765                        sizeof(device->policies[0]), &p_ent,
    766                        _regex_policy_t_compare);
    767     ESW_REGEX_UNLOCK(unit);
    768 
    769     if (idx >= 0) {
    770         if (NULL != policy_p) {
    771             *policy_p = device->policies[idx];
    772         }
    773         return (BCM_E_NONE);
    774     }
    775 
    776     /* Rule with id == eid not found. */
    777     return (BCM_E_NOT_FOUND);
    778 }
    779 
    780 /*
    781  * Function:
    782  *     _regex_policy_add
    783  * Purpose:
    784  *     Insert an entry to info entry array.
    785  * Parmeters:
    786  *     unit    - (IN) BCM device number.
    787  *     policy  - (IN) Policy entry.
    788  * Returns:
    789  *     BCM_E_XXX
    790  */
    791 int _regex_policy_add(int unit, _regex_policy_t *policy)
    792 {
    793     int                            idx;    /* Entry insertion index.  */
    794     _bcm_esw_regex_device_info_t  *device; /* Regex control structure. */
    795     _regex_policy_t              **policy_array;
    796 
    797     /* Input parameters check */
    798     if (NULL == policy) {
    799         return (BCM_E_PARAM);
    800     }
    801 
    802     device = ESW_REGEX_INFO(unit);
    803     if (NULL == device) {
    804         return BCM_E_INIT;
    805     }
    806 
    807     /* Verify if entry already present in the group . */
    808     if (BCM_E_NONE == _regex_policy_get(unit, policy->eid, NULL)) {
    809         /* Entry already IN. */
    810         return (BCM_E_NONE);
    811     }
    812 
    813     /* Check if group has enough room for new entry */
    814     if (ESW_REGEX_POLICIES_MAX(unit) > device->num_policies) {
    815 
    816         policy_array = sal_alloc(sizeof(policy_array[0]) * (device->num_policies + 1), "regex_policy_array");
    817         if (NULL == policy_array) {
    818             return (BCM_E_MEMORY);
    819         }
    820 
    821         /* Copy original array to newly allocated one. */
    822         if (NULL != device->policies) {
    823             sal_memcpy(policy_array, device->policies, sizeof(policy_array[0]) * device->num_policies);
    824             sal_free(device->policies);
    825         }
    826 
    827         device->policies = policy_array;
    828         device->num_policies++;
    829     } else {
    830         return (BCM_E_RESOURCE);
    831     }
    832 
    833     /* Insert entry in sorted order.  Note that if the loop breaks, idx will be one less
    834      * than the index at which to add the new policy.  If the loop runs to completion, idx
    835      * will be -1 so the new entry will be inserted at entry 0 (idx + 1) which is
    836      * appropriate since the new entry is less than all the other entries. */
    837     idx = device->num_policies - 2;
    838     if (idx >= 0) {
    839         do {
    840             if (_regex_policy_t_compare(&device->policies[idx], &policy) < 0) {
    841                 break;
    842             }
    843 
    844             device->policies[idx + 1] = device->policies[idx];
    845             idx--;
    846         } while (idx >= 0);
    847         device->policies[idx + 1] = policy;
    848     } else {
    849         device->policies[0] = policy;
    850     }
    851 
    852     return (BCM_E_NONE);
    853 }
    854 
    855 /*
    856  * Function:
    857  *     _regex_policy_delete
    858  * Purpose:
    859  *     Remove an entry from field group entry array.
    860  * Parmeters:
    861  *     unit    - (IN)BCM device number.
    862  *     fg      - (IN)Field group structure.
    863  *     f_ent   - (IN)Removed entry structure.
    864  * Returns:
    865  *     BCM_E_XXX
    866  */
    867 STATIC int _regex_policy_delete(int unit, _regex_policy_t *policy)
    868 {
    869     int                            idx;    /* Entry insertion index.  */
    870     _bcm_esw_regex_device_info_t  *device; /* Regex control structure. */
    871 
    872     /* Input parameters check */
    873     if (NULL == policy) {
    874         return (BCM_E_PARAM);
    875     }
    876 
    877     device = ESW_REGEX_INFO(unit);
    878     if (NULL == device) {
    879         return BCM_E_INIT;
    880     }
    881 
    882     /* Make sure policy array was not deallocated. */
    883     if (NULL == device->policies) {
    884         return (BCM_E_INTERNAL);
    885     }
    886 
    887     /* Verify if entry already present in the group . */
    888     ESW_REGEX_LOCK(unit);
    889     idx = _shr_bsearch(device->policies, device->num_policies,
    890                        sizeof(device->policies[0]), &policy,
    891                        _regex_policy_t_compare);
    892     if (idx < 0) {
    893         ESW_REGEX_UNLOCK(unit);
    894         return (BCM_E_NOT_FOUND);
    895     }
    896 
    897     if (device->num_policies <= 1) {
    898         sal_free(device->policies);
    899         device->policies = NULL;
    900         device->num_policies = 0;
    901     } else {
    902         /* Make room for inserted entry */
    903         while (idx < device->num_policies - 1) {
    904             device->policies[idx] = device->policies[idx + 1];
    905             idx++;
    906         }
    907         device->num_policies--;
    908         device->policies[device->num_policies] = NULL;
    909     }
    910 
    911     ESW_REGEX_UNLOCK(unit);
    912 
    913     return (BCM_E_NONE);
    914 }
    915 
    916 /*
    917  * Function: _regex_policy_params_hw_to_api_adapt
    918  *
    919  * Purpose:
    920  *     Adapts action parameters from HW to API space.
    921  *
    922  * Parameters:
    923  *     unit   - (IN) BCM device number
    924  *     action - (IN)Action to adapt parameters for (bcmFieldActionXXX)
    925  *     param0 - (IN/OUT)Action parameter
    926  *     param1 - (IN/OUT)Action parameter
    927  *
    928  * Returns:
    929  *     BCM_E_NONE      - No errors.
    930  *     BCM_E_XXX       - Otherwise.
    931  */
    932 STATIC int _regex_policy_params_hw_to_api_adapt(int unit, bcm_field_action_t action,
    933                                                 uint32 *param0, uint32 *param1)
    934 {
    935     int                 isGport;
    936     _bcm_gport_dest_t   dest;
    937 
    938     _bcm_gport_dest_t_init(&dest);
    939     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
    940 
    941     switch (action) {
    942         case bcmFieldActionRedirect:
    943             if (isGport) {
    944                 dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
    945                 dest.modid = *param0;
    946                 dest.port = *param1;
    947                 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, (bcm_gport_t *)param1));
    948                 *param0 = -1;   /* If gport requested param0 should be ignored */
    949             }
    950             break;
    951         case bcmFieldActionRedirectTrunk:
    952             if (isGport) {
    953                 dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
    954                 dest.tgid = *param0;
    955                 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, (bcm_gport_t *)param0));
    956                 *param1 = -1;   /* If gport requested param1 should be ignored */
    957             }
    958             break;
    959         default:
    960             break;
    961     }
    962     return (BCM_E_NONE);
    963 }
    964 
    965 /*
    966  * Function: _regex_policy_params_api_to_hw_adapt
    967  *
    968  * Purpose:
    969  *     Adapts action parameters from API to HW space.
    970  *
    971  * Parameters:
    972  *     unit   - (IN) BCM device number
    973  *     action - (IN)Action to adapt parameters for (bcmFieldActionXXX)
    974  *     param0 - (IN/OUT)Action parameter
    975  *     param1 - (IN/OUT)Action parameter
    976  *
    977  * Returns:
    978  *     BCM_E_NONE      - No errors.
    979  *     BCM_E_XXX       - Otherwise.
    980  */
    981 STATIC int _regex_policy_params_api_to_hw_adapt(int unit, bcm_field_action_t action,
    982                                                 uint32 *param0, uint32 *param1)
    983 {
    984     bcm_module_t        l_modid;
    985     bcm_trunk_t         l_tgid;
    986     bcm_port_t          l_port;
    987     int                 id;
    988 
    989     switch (action) {
    990         case bcmFieldActionRedirect:
    991             if (BCM_GPORT_IS_SET(*param1)) {
    992                 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, *param1, &l_modid, &l_port, &l_tgid, &id));
    993                 /* Do not modify param0 and param1 if id != -1 */
    994                 if (-1 == id) {
    995                     if (BCM_TRUNK_INVALID != l_tgid) {
    996                         return BCM_E_PARAM;
    997                     }
    998                     *param1 = l_port;
    999                     *param0 = l_modid;
   1000                 }
   1001             }
   1002             break;
   1003         case bcmFieldActionRedirectTrunk:
   1004             if (BCM_GPORT_IS_SET(*param0)) {
   1005                 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, *param0, &l_modid, &l_port, &l_tgid, &id));
   1006                 if ((-1 != id) || (BCM_TRUNK_INVALID == l_tgid) ){
   1007                     return BCM_E_PARAM;
   1008                 }
   1009                 *param0 = l_tgid;
   1010                 *param1 = -1;   /* if param0 is trunk, param1 ignored */
   1011             }
   1012             break;
   1013         default:
   1014             break;
   1015     }
   1016 
   1017     return (BCM_E_NONE);
   1018 }
   1019 
   1020 /*
   1021  * Function:
   1022  *     _regex_policy_phys_create
   1023  * Purpose:
   1024  *     Initialize a physical policy structure.
   1025  * Parameters:
   1026  *     unit           - (IN) BCM device number.
   1027  *     policy         - (IN) Policy id.
   1028  *     policy_p       - (OUT)Allocated & initialized entry.
   1029  * Returns
   1030  *     BCM_E_XXX
   1031  */
   1032 STATIC int _regex_policy_phys_create(int unit, bcm_regex_policy_t policy, _regex_policy_t **policy_p)
   1033 {
   1034     int                           rv;         /* Operation return status.         */
   1035     _regex_policy_t              *policy_ent; /* Field entry structure.           */
   1036     _bcm_esw_regex_device_info_t *device;     /* Regex control structure. */
   1037 
   1038     LOG_DEBUG(BSL_LS_BCM_REGEX,
   1039               (BSL_META_U(unit,
   1040                           "FT(unit %d) vverb: BEGIN %s(policy=%d)\n"),
   1041                unit, FUNCTION_NAME(), policy));
   1042 
   1043     if (NULL == policy_p) {
   1044         return (BCM_E_PARAM);
   1045     }
   1046 
   1047     /* Get the device info structure. */
   1048     device = ESW_REGEX_INFO(unit);
   1049     if (NULL == device) {
   1050         return BCM_E_INIT;
   1051     }
   1052 
   1053     /* Check if free entries are available in the slice. */
   1054     if (device->num_policies >= ESW_REGEX_POLICIES_MAX(unit)) {
   1055         LOG_ERROR(BSL_LS_BCM_REGEX,
   1056                   (BSL_META_U(unit,
   1057                               "FT(unit %d) Error: No room.\n"),
   1058                    unit));
   1059         return (BCM_E_RESOURCE);
   1060     }
   1061 
   1062     policy_ent = sal_alloc(sizeof(*policy_ent), "regex_policy");
   1063     if (policy_ent == NULL) {
   1064         LOG_ERROR(BSL_LS_BCM_REGEX,
   1065                   (BSL_META_U(unit,
   1066                               "FT(unit %d) Error: allocation failure for policy_entry\n"),
   1067                    unit));
   1068         return (BCM_E_MEMORY);
   1069     }
   1070 
   1071     _bcm_esw_regex_policy_t_init(policy_ent);
   1072 
   1073     /* Fill in entry primitives. */
   1074     policy_ent->eid = policy;
   1075 
   1076 #if 0
   1077     /* Do we want to have a default setting for the FT? */
   1078 
   1079     /* Enable color independent actions based on field control. */
   1080     if (fc->flags & _FP_COLOR_INDEPENDENT) {
   1081         policy_ent->flags |= _REGEX_POLICY_COLOR_INDEPENDENT;
   1082     }
   1083 #endif
   1084 
   1085     /* Mark entry dirty. */
   1086     policy_ent->flags |=  _REGEX_POLICY_DIRTY;
   1087 
   1088     /* Insert the entry into group entry array. */
   1089     rv = _regex_policy_add(unit, policy_ent);
   1090     if (BCM_FAILURE(rv)) {
   1091         sal_free(policy_ent);
   1092         return (rv);
   1093     }
   1094 
   1095     /* Return allocated/filled entry structure to the caller. */
   1096     *policy_p = policy_ent;
   1097     return (BCM_E_NONE);
   1098 }
   1099 
   1100 /*
   1101  * Function:
   1102  *     _regex_policy_phys_destroy
   1103  *
   1104  * Purpose:
   1105  *     Destroy a physical policy. Note that this does not remove
   1106  *     the policy from the hardware.
   1107  *
   1108  * Parameters:
   1109  *     unit      - BCM device number
   1110  *     policy    - Policy ID to remove
   1111  *
   1112  * Returns:
   1113  *     BCM_E_NONE - Success
   1114  */
   1115 STATIC int _regex_policy_phys_destroy(int unit, _regex_policy_t *p_ent)
   1116 {
   1117     int              rv;          /* Operation return status.        */
   1118 
   1119     if (NULL == p_ent) {
   1120         return (BCM_E_PARAM);
   1121     }
   1122 
   1123     /* Remove the entry from group entry array. */
   1124     rv = _regex_policy_delete(unit, p_ent);
   1125     sal_free(p_ent);
   1126     return (rv);
   1127 }
   1128 
   1129 /*
   1130  * Function:
   1131  *     _regex_policy_mirror_dest_delete
   1132  * Purpose:
   1133  *     Unset mirroring destination & disable mirroring for rule matching
   1134  *     packets.
   1135  * Parameters:
   1136  *     unit     - (IN) BCM device number
   1137  *     fa       - (IN) Field action descriptor.
   1138  * Returns:
   1139  *     BCM_E_XXX
   1140  */
   1141 STATIC int _regex_policy_mirror_dest_delete(int unit, _regex_policy_t *p_ent,
   1142                                             _regex_policy_action_t *pa, uint32 flags)
   1143 {
   1144     uint32 mirror_flags;      /* Mirror module flags.     */
   1145     int rv;
   1146 
   1147     /* Input parameters check */
   1148     if ((NULL == pa) || (NULL == p_ent)) {
   1149         return (BCM_E_PARAM);
   1150     }
   1151 
   1152     /* Set mirror flags. */
   1153     if (bcmFieldActionMirrorIngress == pa->action) {
   1154         mirror_flags = BCM_MIRROR_PORT_INGRESS;
   1155     }  else if (bcmFieldActionMirrorEgress == pa->action) {
   1156         /* Stage Ingress */
   1157         mirror_flags = BCM_MIRROR_PORT_EGRESS;
   1158     } else {
   1159         return (BCM_E_PARAM);
   1160     }
   1161 
   1162     if ((flags & _REGEX_ACTION_RESOURCE_FREE) &&
   1163         (_REGEX_INVALID_INDEX != pa->hw_index)) {
   1164         rv = _bcm_esw_mirror_fp_dest_delete(unit, pa->hw_index, mirror_flags);
   1165         BCM_IF_ERROR_RETURN(rv);
   1166         pa->hw_index = _REGEX_INVALID_INDEX;
   1167     }
   1168 
   1169     if ((flags & _REGEX_ACTION_OLD_RESOURCE_FREE) &&
   1170         (_REGEX_INVALID_INDEX != pa->old_index)) {
   1171         rv = _bcm_esw_mirror_fp_dest_delete(unit, pa->old_index, mirror_flags);
   1172         BCM_IF_ERROR_RETURN(rv);
   1173         pa->old_index = _REGEX_INVALID_INDEX;
   1174     }
   1175     return (BCM_E_NONE);
   1176 }
   1177 
   1178 /*
   1179  * Function:
   1180  *     _regex_policy_mirror_dest_add
   1181  * Purpose:
   1182  *     Set mirroring destination & enable mirroring for rule matching
   1183  *     packets.
   1184  * Parameters:
   1185  *     unit     - (IN) BCM device number
   1186  *     fa       - (IN) field action
   1187  * Returns:
   1188  *     BCM_E_XXX
   1189  */
   1190 STATIC int _regex_policy_mirror_dest_add(int unit, _regex_policy_t *p_ent,
   1191                                          _regex_policy_action_t *pa)
   1192 {
   1193     uint32 mirror_flags;      /* Mirror module flags.     */
   1194 
   1195     /* Input parameters check. */
   1196     if ((NULL == pa) || (NULL == p_ent)) {
   1197         return (BCM_E_PARAM);
   1198     }
   1199 
   1200     /* Set mirror flags. */
   1201     if (bcmFieldActionMirrorIngress == pa->action) {
   1202         mirror_flags = BCM_MIRROR_PORT_INGRESS;
   1203     }  else if (bcmFieldActionMirrorEgress == pa->action) {
   1204         /* Stage Ingress */
   1205         mirror_flags = BCM_MIRROR_PORT_EGRESS;
   1206     } else {
   1207         return (BCM_E_PARAM);
   1208     }
   1209 
   1210     return _bcm_esw_mirror_fp_dest_add(unit, pa->param[0], pa->param[1],
   1211                                        mirror_flags, &pa->hw_index);
   1212 }
   1213 
   1214 #if defined(INCLUDE_L3)
   1215 /*
   1216  * Function:
   1217  *     _bcm_regex_policy_set_l3_nh_resolve
   1218  * Purpose:
   1219  *     Install l3 forwarding policy entry.
   1220  * Parameters:
   1221  *     unit      - (IN) BCM device number
   1222  *     value     - (IN) Egress object id or combined next hop information.
   1223  * Returns:
   1224  *     BCM_E_XXX
   1225  */
   1226 int _bcm_regex_policy_set_l3_nh_resolve(int unit, int value,
   1227                                         uint32 *flags, int *nh_ecmp_id)
   1228 {
   1229     int rv;           /* Operation return value.    */
   1230 
   1231     /* Check if egress forwarding mode is enabled. */
   1232     rv = bcm_xgs3_l3_egress_id_parse(unit, value, flags, nh_ecmp_id);
   1233     if (rv == BCM_E_DISABLED) {
   1234         if (_REGEX_L3_ACTION_UNPACK_ECMP_MODE((value))) {
   1235             *flags = BCM_L3_MULTIPATH;
   1236             *nh_ecmp_id = _REGEX_L3_ACTION_UNPACK_ECMP_PTR((value));
   1237         } else {
   1238             *flags = 0;
   1239             *nh_ecmp_id = _REGEX_L3_ACTION_UNPACK_NEXT_HOP((value));
   1240         }
   1241         rv = BCM_E_NONE;
   1242     }
   1243     return (rv);
   1244 }
   1245 
   1246 /*
   1247  * Function:
   1248  *     _regex_policy_l2_actions_nh_destroy
   1249  *
   1250  * Purpose:
   1251  *     Free l3 next hop and egress interface for
   1252  *     l2 fields update action.
   1253  * Parameters:
   1254  *     unit     - (IN) BCM device number.
   1255  *     nh_index - (IN) Next hop index.
   1256  *     egr_intf_set - (IN) Egress interface allocated.
   1257  * Returns:
   1258  *     BCM_E_XXX
   1259  */
   1260 STATIC int _regex_policy_l2_actions_nh_destroy(int unit, int nh_index, int egr_intf_set)
   1261 {
   1262     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry  buffer.            */
   1263     bcm_l3_egress_t egr;                    /* Egress forwarding object.    */
   1264     uint32 intf;                            /* Egress L3 interface id.      */
   1265 
   1266     /* Initialization. */
   1267     bcm_l3_egress_t_init(&egr);
   1268 
   1269     /* Read next hop. */
   1270     sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1271     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ANY,
   1272                                      nh_index, hw_buf));
   1273 
   1274     /* clear egress interface information + free interface resource */
   1275     if (1 == egr_intf_set) {
   1276         /* Get interface id. */
   1277         intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, hw_buf, INTF_NUMf);
   1278         /* Reset interface entry in hw. */
   1279         sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1280         BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   1281                                           intf, hw_buf));
   1282         /* Free interface id. */
   1283         BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_free(unit, intf));
   1284     }
   1285 
   1286     /* clear egress next hop table information + free next hop index */
   1287     sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1288     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   1289                                       SOC_BLOCK_ALL, nh_index, hw_buf));
   1290 
   1291     BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_index));
   1292     return (BCM_E_NONE);
   1293 }
   1294 
   1295 /*
   1296  * Function:
   1297  *     _regex_policy_l2_actions_nh_create
   1298  *
   1299  * Purpose:
   1300  *     Free l3 next hop and egress interface for
   1301  *     l2 fields update action.
   1302  * Parameters:
   1303  *     unit    - (IN) BCM device number.
   1304  *     da_pa   - (IN) Update destination mac action.
   1305  *     sa_pa   - (IN) Update source mac action.
   1306  *     vid_pa  - (IN) Update outer vid action.
   1307  *     vn_new_pa  - (IN) Change VN tag action.
   1308  *     vn_del_pa  - (IN) Delete VN tag action.
   1309  * Returns:
   1310  *     BCM_E_XXX
   1311  */
   1312 STATIC int _regex_policy_l2_actions_nh_create(int unit,
   1313                                               _regex_policy_action_t *da_pa,
   1314                                               _regex_policy_action_t *sa_pa,
   1315                                               _regex_policy_action_t *vid_pa,
   1316                                               _regex_policy_action_t *vn_new_pa,
   1317                                               _regex_policy_action_t *vn_del_pa)
   1318 {
   1319     uint32          hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry  buffer.     */
   1320     bcm_l3_egress_t egr;                             /* Egress forwarding object.     */
   1321     _bcm_l3_intf_cfg_t intf;                            /* Egress L3 interface id.       */
   1322     int             nh_index;                        /* Next hop index.               */
   1323     int             nh_flags = 0;                    /* Next hop flags.               */
   1324     int             rv       = BCM_E_NONE;           /* Operation return status.      */
   1325 
   1326     /* Initialization. */
   1327     bcm_l3_egress_t_init(&egr);
   1328     sal_memset(&intf, 0, sizeof(_bcm_l3_intf_cfg_t));
   1329 
   1330     /* Extract the policy info from the entry structure. */
   1331     if (NULL != da_pa) {
   1332         SAL_MAC_ADDR_FROM_UINT32(egr.mac_addr, da_pa->param);
   1333     }
   1334 
   1335     if (NULL != sa_pa) {
   1336         SAL_MAC_ADDR_FROM_UINT32(intf.l3i_mac_addr, sa_pa->param);
   1337     }
   1338 
   1339     if (NULL != vid_pa) {
   1340         intf.l3i_vid = vid_pa->param[0];
   1341     }
   1342 
   1343     /* Create egress l3 interface. */
   1344     BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_alloc(unit, &intf));
   1345 
   1346     /* Write egress interface to the hw. */
   1347     sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1348 
   1349     /* Set mac address. */
   1350     soc_mem_mac_addr_set(unit, EGR_L3_INTFm, hw_buf,
   1351                          MAC_ADDRESSf, intf.l3i_mac_addr);
   1352 
   1353     /* Set vlan id. */
   1354     soc_mem_field32_set(unit, EGR_L3_INTFm, hw_buf, VIDf, intf.l3i_vid);
   1355 
   1356     /* Write interface configuration to the HW. */
   1357     rv = soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   1358                        intf.l3i_index, hw_buf);
   1359     if (BCM_FAILURE(rv)) {
   1360         (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   1361         return rv;
   1362     }
   1363 
   1364     /* Allocate next hop entry. */
   1365     nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
   1366     rv = bcm_xgs3_nh_add(unit, nh_flags, &egr, &nh_index);
   1367     if (BCM_FAILURE(rv)) {
   1368         sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1369         (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   1370                             intf.l3i_index, hw_buf);
   1371         (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   1372         return (rv);
   1373     }
   1374 
   1375     /* Write egress next hop entry. */
   1376     sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1377 
   1378     /* Set next hop mac address. */
   1379     soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   1380                          MAC_ADDRESSf, egr.mac_addr);
   1381 
   1382     /* Set interface id. */
   1383     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   1384                         INTF_NUMf, intf.l3i_index);
   1385 
   1386     /* Set Disable flags. */
   1387     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   1388                         L3__L3_UC_TTL_DISABLEf, 0x1);
   1389 
   1390     if (NULL == vid_pa) {
   1391         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   1392                             L3__L3_UC_VLAN_DISABLEf, 0x1);
   1393     }
   1394 
   1395     if (NULL == sa_pa) {
   1396         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   1397                             L3__L3_UC_SA_DISABLEf, 0x1);
   1398     }
   1399 
   1400     if (NULL == da_pa) {
   1401         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   1402                             L3__L3_UC_DA_DISABLEf, 0x1);
   1403     }
   1404 
   1405     if (SOC_IS_TRIUMPH3(unit)) {
   1406         soc_mem_field32_set(unit,
   1407                             EGR_L3_NEXT_HOPm,
   1408                             hw_buf,
   1409                             ENTRY_TYPEf,
   1410                             6);
   1411     }
   1412 
   1413 
   1414     /* Insert next hop information. */
   1415     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ALL,
   1416                        nh_index, hw_buf);
   1417     if (BCM_FAILURE(rv)) {
   1418         sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1419         (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   1420                             intf.l3i_index, hw_buf);
   1421         (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   1422         return (rv);
   1423     }
   1424 
   1425     /* Preserve next hop index in the action structure. */
   1426     if (NULL != vid_pa) {
   1427         vid_pa->hw_index = nh_index;
   1428     }
   1429 
   1430     if (NULL != sa_pa) {
   1431         sa_pa->hw_index = nh_index;
   1432     }
   1433 
   1434     if (NULL != da_pa) {
   1435         da_pa->hw_index = nh_index;
   1436     }
   1437 
   1438     if (NULL != vn_new_pa) {
   1439         vn_new_pa->hw_index = nh_index;
   1440     }
   1441 
   1442     if (NULL != vn_del_pa) {
   1443         vn_del_pa->hw_index = nh_index;
   1444     }
   1445     return (BCM_E_NONE);
   1446 }
   1447 
   1448 /*
   1449  * Function:
   1450  *     _regex_policy_l2_actions_hw_alloc
   1451  *
   1452  * Purpose:
   1453  *     Allocate l3 next hop and egress interface for
   1454  *     l2 fields update action.
   1455  * Parameters:
   1456  *     unit      - (IN) BCM device number.
   1457  *     p_ent     - (IN) Regex policy descriptor.
   1458  * Returns:
   1459  *     BCM_E_XXX
   1460  */
   1461 STATIC int _regex_policy_l2_actions_hw_alloc(int unit, _regex_policy_t *p_ent)
   1462 {
   1463     _regex_policy_action_t *vid_pa;        /* Update outer vid action.      */
   1464     _regex_policy_action_t *sa_pa;         /* Update source mac action.     */
   1465     _regex_policy_action_t *da_pa;         /* Update destination mac action.*/
   1466     _regex_policy_action_t *vn_new_pa;     /* Change VN tag.                */
   1467     _regex_policy_action_t *vn_del_pa;     /* Delete VN tag action.         */
   1468     _regex_policy_action_t *pa;            /* Field action descriptor.      */
   1469 
   1470     /*
   1471      * Applicable to stage ingress on devices which support
   1472      * soc_feature_field_action_l2_change feature.
   1473      */
   1474 
   1475     /* Initialization. */
   1476     sa_pa = da_pa = vid_pa = vn_new_pa = vn_del_pa = NULL;
   1477 
   1478     /* Extract the policy info from the entry structure. */
   1479     for (pa = p_ent->actions; ((pa != NULL) && (_REGEX_ACTION_VALID & pa->flags)); pa = pa->next) {
   1480         switch (pa->action) {
   1481             case bcmFieldActionSrcMacNew:
   1482                 if (_REGEX_INVALID_INDEX != pa->hw_index) {
   1483                     pa->old_index = pa->hw_index;
   1484                 }
   1485                 sa_pa = pa;
   1486                 break;
   1487             case bcmFieldActionDstMacNew:
   1488                 if (_REGEX_INVALID_INDEX != pa->hw_index) {
   1489                     pa->old_index = pa->hw_index;
   1490                 }
   1491                 da_pa = pa;
   1492                 break;
   1493             case bcmFieldActionOuterVlanNew:
   1494                 if (_REGEX_INVALID_INDEX != pa->hw_index) {
   1495                     pa->old_index = pa->hw_index;
   1496                 }
   1497                 vid_pa = pa;
   1498                 break;
   1499             case bcmFieldActionVnTagNew:
   1500                 if (_REGEX_INVALID_INDEX != pa->hw_index) {
   1501                     pa->old_index = pa->hw_index;
   1502                 }
   1503                 vn_new_pa = pa;
   1504                 break;
   1505             case bcmFieldActionVnTagDelete:
   1506                 if (_REGEX_INVALID_INDEX != pa->hw_index) {
   1507                     pa->old_index = pa->hw_index;
   1508                 }
   1509                 vn_del_pa = pa;
   1510                 break;
   1511             default:
   1512                 continue;
   1513         }
   1514     }
   1515 
   1516     /* Create nh entry. */
   1517     if ((NULL != vid_pa) || (NULL != da_pa) || (NULL != sa_pa) ||
   1518         (NULL != vn_new_pa) || (NULL != vn_del_pa)) {
   1519         BCM_IF_ERROR_RETURN(_regex_policy_l2_actions_nh_create(unit, da_pa, sa_pa,
   1520                                                                vid_pa, vn_new_pa, vn_del_pa));
   1521     }
   1522     return (BCM_E_NONE);
   1523 }
   1524 
   1525 /*
   1526  * Function:
   1527  *     _regex_policy_l2_actions_hw_free
   1528  *
   1529  * Purpose:
   1530  *     Free l3 next hop and egress interface for
   1531  *     l2 fields update action.
   1532  * Parameters:
   1533  *     unit      - (IN) BCM device number.
   1534  *     p_ent     - (IN) Regex policy descriptor.
   1535  *     flags     - (IN) Free flags (old/new/both).
   1536  * Returns:
   1537  *     BCM_E_XXX
   1538  */
   1539 STATIC int _regex_policy_l2_actions_hw_free(int unit, _regex_policy_t *p_ent,
   1540                                             uint32 flags)
   1541 {
   1542     _regex_policy_action_t *pa;                        /* Field action descriptor.      */
   1543     int                     nh_index;                  /* Next hop index.               */
   1544     int                     old_nh_index;              /* Old next hop index.           */
   1545     int                     egr_intf_set = 0;          /* Egress interface allocated    */
   1546     int                     rv           = BCM_E_NONE; /* Operation return status.      */
   1547 
   1548     /* Applicable to stage ingress on TRX and FB family of devices only. */
   1549 
   1550     /* Initialization. */
   1551     nh_index = old_nh_index = _REGEX_INVALID_INDEX;
   1552 
   1553     /* Extract the policy info from the entry structure. */
   1554     for (pa = p_ent->actions; pa != NULL; pa = pa->next) {
   1555         switch (pa->action) {
   1556             case bcmFieldActionSrcMacNew:
   1557                 egr_intf_set = TRUE;
   1558                 /* passthru */
   1559                 /* coverity[MISSING_BREAK: FALSE] */
   1560             case bcmFieldActionOuterVlanNew:
   1561             case bcmFieldActionDstMacNew:
   1562             case bcmFieldActionVnTagNew:
   1563             case bcmFieldActionVnTagDelete:
   1564                 if ((flags & _REGEX_ACTION_RESOURCE_FREE) &&
   1565                     (_REGEX_INVALID_INDEX != pa->hw_index)) {
   1566                     nh_index = pa->hw_index;
   1567                     pa->hw_index = _REGEX_INVALID_INDEX;
   1568                 }
   1569                 if ((flags & _REGEX_ACTION_OLD_RESOURCE_FREE) &&
   1570                     (_REGEX_INVALID_INDEX != pa->old_index)) {
   1571                     old_nh_index = pa->old_index;
   1572                     pa->old_index = _REGEX_INVALID_INDEX;
   1573                 }
   1574                 break;
   1575             default:
   1576                 break;
   1577         }
   1578     }
   1579 
   1580     /* Destroy old next hop if any. */
   1581     if (_REGEX_INVALID_INDEX != old_nh_index) {
   1582         rv = _regex_policy_l2_actions_nh_destroy(unit, old_nh_index, egr_intf_set);
   1583         BCM_IF_ERROR_RETURN(rv);
   1584     }
   1585     if (_REGEX_INVALID_INDEX != nh_index) {
   1586         rv = _regex_policy_l2_actions_nh_destroy(unit, nh_index, egr_intf_set);
   1587         BCM_IF_ERROR_RETURN(rv);
   1588     }
   1589     return (BCM_E_NONE);
   1590 }
   1591 #endif /* INCLUDE_L3 */
   1592 
   1593 /*
   1594  * Function:
   1595  *      _regex_policy_action_hw_resources_free
   1596  * Purpose:
   1597  *      Free hw resources allocated for regex policy action installation.
   1598  * Parameters:
   1599  *      unit     - (IN) BCM device number
   1600  *      p_ent    - (IN) Regex policy structure.
   1601  *      pa       - (IN) Policy action structure.
   1602  * Returns:
   1603  *      BCM_E_XXX
   1604  * Notes:
   1605  */
   1606 int _regex_policy_action_hw_resources_free(int unit, _regex_policy_t *p_ent,
   1607                                            _regex_policy_action_t *pa, uint32 flags)
   1608 {
   1609     _bcm_esw_regex_device_info_t *device;    /* Regex control structure. */
   1610     int rv;
   1611 
   1612     /* Input parameters check. */
   1613     if ((NULL == p_ent) || (NULL == pa)) {
   1614         return (BCM_E_PARAM);
   1615     }
   1616 
   1617     /* Get the device info structure. */
   1618     device = ESW_REGEX_INFO(unit);
   1619     if (NULL == device) {
   1620         return BCM_E_INIT;
   1621     }
   1622 
   1623     switch (pa->action) {
   1624       case bcmFieldActionMirrorIngress:
   1625       case bcmFieldActionMirrorEgress:
   1626           return _regex_policy_mirror_dest_delete(unit, p_ent, pa, flags);
   1627           break;
   1628       case bcmFieldActionRedirectMcast:
   1629 #if defined(INCLUDE_L3)
   1630       case bcmFieldActionRedirectIpmc:
   1631 #endif /* INCLUDE_L3 */
   1632           if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)) {
   1633               break;
   1634           }
   1635       case bcmFieldActionRedirectPbmp:
   1636       case bcmFieldActionEgressMask:
   1637       case bcmFieldActionEgressPortsAdd:
   1638           /* Applicable to stage ingress on TRX devices only. */
   1639           rv = device->functions->redirect_profile_delete(unit, pa->hw_index);
   1640           BCM_IF_ERROR_RETURN(rv);
   1641           break;
   1642 
   1643 #if defined(INCLUDE_L3)
   1644       case bcmFieldActionSrcMacNew:
   1645       case bcmFieldActionDstMacNew:
   1646       case bcmFieldActionOuterVlanNew:
   1647           if (soc_feature(unit, soc_feature_field_action_l2_change)) {
   1648               rv = _regex_policy_l2_actions_hw_free(unit, p_ent,
   1649                                                  _REGEX_ACTION_HW_FREE);
   1650               BCM_IF_ERROR_RETURN(rv);
   1651           }
   1652           break;
   1653 #endif /* INCLUDE_L3 */
   1654 
   1655       default:
   1656           break;
   1657     }
   1658     pa->hw_index = _REGEX_INVALID_INDEX;
   1659     return (BCM_E_NONE);
   1660 }
   1661 
   1662 /*
   1663  * Function:
   1664  *      _regex_policy_invalid_actions_remove
   1665  * Purpose:
   1666  *      Remove deleted actions from policy actions
   1667  *      linked list.
   1668  * Parameters:
   1669  *      unit  - (IN) BCM device number
   1670  *      p_ent - (IN) Regex policy structure.
   1671  * Returns:
   1672  *      BCM_E_XXX
   1673  * Notes:
   1674  */
   1675 int _regex_policy_invalid_actions_remove(int unit, _regex_policy_t *p_ent)
   1676 {
   1677     _regex_policy_action_t     *pa;
   1678     _regex_policy_action_t     *pa_prev = NULL;
   1679     _regex_policy_action_t     *pa_next = NULL;
   1680     _regex_policy_action_t     *pa_iter;        /* Field entry actions iterator.*/
   1681     int                 rv;
   1682 
   1683     /* Input parameters check. */
   1684     if (NULL == p_ent) {
   1685         return (BCM_E_PARAM);
   1686     }
   1687 
   1688     /* Find the action in the policy */
   1689     pa = p_ent->actions; /* start at head */
   1690     while (pa != NULL) {
   1691         pa_next = pa->next;
   1692         if (pa->flags & _REGEX_ACTION_VALID) {
   1693             pa_prev = pa;
   1694             pa      = pa_next;
   1695             continue;
   1696         }
   1697 
   1698         if (_REGEX_INVALID_INDEX != pa->hw_index) {
   1699             /*
   1700              * Check if a valid instance of this action exists in
   1701              * the entry actions linked list.
   1702              * If TRUE, hardware index must be freed only
   1703              * after updating policy table with new information.
   1704              */
   1705             if ((bcmFieldActionEgressMask        == pa->action) ||
   1706                 (bcmFieldActionRedirectBcastPbmp == pa->action) ||
   1707                 (bcmFieldActionRedirectPbmp      == pa->action) ||
   1708                 (bcmFieldActionEgressPortsAdd    == pa->action) ||
   1709                 (bcmFieldActionRedirectMcast     == pa->action) ||
   1710                 (bcmFieldActionRedirectIpmc      == pa->action) ||
   1711                 (bcmFieldActionMirrorIngress     == pa->action) ||
   1712                 (bcmFieldActionMirrorEgress      == pa->action)) {
   1713 
   1714                 if (_REGEX_ACTION_MODIFY & pa->flags) {
   1715 
   1716                     pa->flags &= ~_REGEX_ACTION_MODIFY;
   1717 
   1718                     pa_iter = p_ent->actions;
   1719 
   1720                     while (pa_iter != NULL) {
   1721                         if ((_REGEX_ACTION_VALID == (pa_iter->flags & _REGEX_ACTION_VALID)) &&
   1722                             (pa_iter->action == pa->action) &&
   1723                             (_REGEX_INVALID_INDEX == pa_iter->hw_index)) {
   1724                             /* Do not free here. Release the hardware
   1725                              * index after policy install operation.
   1726                              */
   1727                             pa_iter->hw_index  = pa->hw_index;
   1728                             pa_iter->flags    |= _REGEX_ACTION_MODIFY;
   1729                             pa->hw_index       = _REGEX_INVALID_INDEX;
   1730                             break;
   1731                         }
   1732                         pa_iter = pa_iter->next;
   1733                     }
   1734 
   1735                     /* Here _REGEX_ACTION_MODIFY flag cleared means, no duplicate
   1736                        actions are found i.e an action is removed from the entry.
   1737                        Those invalid but not modified entries will be removed in
   1738                        the second pass to this function,so just return BCM_E_NONE
   1739                        on first pass */
   1740                     if (!(_REGEX_ACTION_MODIFY & pa->flags)) {
   1741                         return (BCM_E_NONE);
   1742                     }
   1743                 }
   1744             }
   1745 
   1746             /*
   1747              * Action not set for this entry, free the hardware index.
   1748              */
   1749             if (_REGEX_INVALID_INDEX != pa->hw_index) {
   1750                 rv = _regex_policy_action_hw_resources_free(unit, p_ent, pa, _REGEX_ACTION_RESOURCE_FREE);
   1751                 BCM_IF_ERROR_RETURN(rv);
   1752             }
   1753         }
   1754 
   1755         if (pa_prev != NULL) {
   1756             pa_prev->next = pa->next;
   1757         } else { /* matched head of list */
   1758             p_ent->actions = pa_next;
   1759         }
   1760 
   1761         /* okay to free action */
   1762         sal_free(pa);
   1763         pa = pa_next;
   1764     }
   1765     return (BCM_E_NONE);
   1766 }
   1767 
   1768 /*
   1769  * Function:
   1770  *     _regex_policy_mtp_hw_free
   1771  *
   1772  * Purpose:
   1773  *     Free mtp indexes used in regex policy
   1774  *
   1775  * Parameters:
   1776  *     unit      - (IN) BCM device number.
   1777  *     p_ent     - (IN) Regex policy structure.
   1778  * Returns:
   1779  *     BCM_E_XXX
   1780  * Notes:
   1781  */
   1782 STATIC int _regex_policy_mtp_hw_free(int unit, _regex_policy_t *p_ent, uint32 flags)
   1783 {
   1784     _regex_policy_action_t *pa;
   1785     int                     rv;         /* Operation return status. */
   1786 
   1787     /* Extract action info from the entry structure. */
   1788     for (pa = p_ent->actions; pa != NULL; pa = pa->next) {
   1789         /* Allocate mtp destination only for mirroring actions */
   1790         if ((bcmFieldActionMirrorIngress != pa->action) &&
   1791             (bcmFieldActionMirrorEgress != pa->action)) {
   1792             continue;
   1793         }
   1794 
   1795         if ((_REGEX_INVALID_INDEX == pa->hw_index) && (_REGEX_INVALID_INDEX == pa->old_index) ) {
   1796             continue;
   1797         }
   1798 
   1799         rv = _regex_policy_action_hw_resources_free(unit, p_ent, pa, flags);
   1800         BCM_IF_ERROR_RETURN(rv);
   1801     }
   1802 
   1803     return (BCM_E_NONE);
   1804 }
   1805 
   1806 /*
   1807  * Function:
   1808  *     _regex_policy_mtp_hw_alloc
   1809  *
   1810  * Purpose:
   1811  *     Allocate mtp indexes required for policy installation.
   1812  *
   1813  * Parameters:
   1814  *     unit      - (IN) BCM device number.
   1815  *     p_ent     - (IN) Regex policy structure.
   1816  * Returns:
   1817  *     BCM_E_XXX
   1818  * Notes:
   1819  */
   1820 STATIC int _regex_policy_mtp_hw_alloc(int unit, _regex_policy_t *p_ent)
   1821 {
   1822     _regex_policy_action_t *pa;
   1823     int                     rv;         /* Operation return status. */
   1824 
   1825     /* Extract action info from the entry structure. */
   1826     for (pa = p_ent->actions; ((pa != NULL) && (_REGEX_ACTION_VALID & pa->flags)); pa = pa->next) {
   1827         /* Allocate mtp destination only for mirroring actions */
   1828         if ((bcmFieldActionMirrorIngress != pa->action) &&
   1829             (bcmFieldActionMirrorEgress != pa->action)) {
   1830             continue;
   1831         }
   1832         if (_REGEX_ACTION_MODIFY & pa->flags) {
   1833             pa->old_index = pa->hw_index;
   1834             pa->hw_index = _REGEX_INVALID_INDEX;
   1835         }
   1836         if (_REGEX_INVALID_INDEX == pa->hw_index) {
   1837             /* Allocate mirror destination. */
   1838             rv = _regex_policy_mirror_dest_add(unit, p_ent, pa);
   1839             if (BCM_E_RESOURCE == rv) {
   1840                 if (_REGEX_ACTION_MODIFY & pa->flags) {
   1841                     pa->hw_index = pa->old_index;
   1842                     pa->old_index = _REGEX_INVALID_INDEX;
   1843                 }
   1844             }
   1845             BCM_IF_ERROR_RETURN(rv);
   1846         }
   1847     }
   1848     return (BCM_E_NONE);
   1849 }
   1850 
   1851 /*
   1852  * Function:
   1853  *     _regex_policy_redirect_profile_hw_free
   1854  *
   1855  * Purpose:
   1856  *     Free redirect profile indexes required for entry installation.
   1857  *
   1858  * Parameters:
   1859  *     unit      - (IN) BCM device number.
   1860  *     f_ent     - (IN) Field entry descriptor.
   1861  *     flags     - (IN) Free flags (old/new/both).
   1862  * Returns:
   1863  *     BCM_E_XXX
   1864  * Notes:
   1865  */
   1866 STATIC int _regex_policy_redirect_profile_hw_free(int unit, _regex_policy_t *p_ent, uint32 flags)
   1867 {
   1868     _bcm_esw_regex_device_info_t *device;    /* Regex control structure. */
   1869     _regex_policy_action_t       *pa;
   1870     int                           rv = BCM_E_NONE; /* Operation return status. */
   1871 
   1872     /* Get the device info structure. */
   1873     device = ESW_REGEX_INFO(unit);
   1874     if (NULL == device) {
   1875         return BCM_E_INIT;
   1876     }
   1877 
   1878     /* Applicable to stage ingress on TRX devices only. */
   1879 
   1880     /* Extract the policy info from the entry structure. */
   1881     for (pa = p_ent->actions; pa != NULL; pa = pa->next) {
   1882         switch (pa->action) {
   1883             case bcmFieldActionRedirectMcast:
   1884 #if defined(INCLUDE_L3)
   1885             case bcmFieldActionRedirectIpmc:
   1886 #endif /* INCLUDE_L3 */
   1887                 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){
   1888                     break;
   1889                 }
   1890             case bcmFieldActionRedirectPbmp:
   1891             case bcmFieldActionRedirectBcastPbmp:
   1892             case bcmFieldActionEgressMask:
   1893             case bcmFieldActionEgressPortsAdd:
   1894                 if ((flags & _REGEX_ACTION_RESOURCE_FREE) &&
   1895                     (_REGEX_INVALID_INDEX != pa->hw_index)) {
   1896                     rv = device->functions->redirect_profile_delete(unit,
   1897                                                                     pa->hw_index);
   1898                     BCM_IF_ERROR_RETURN(rv);
   1899                     pa->hw_index = _REGEX_INVALID_INDEX;
   1900                 }
   1901 
   1902                 if ((flags & _REGEX_ACTION_OLD_RESOURCE_FREE) &&
   1903                     (_REGEX_INVALID_INDEX != pa->old_index)) {
   1904                     rv = device->functions->redirect_profile_delete(unit,
   1905                                                                     pa->old_index);
   1906                     BCM_IF_ERROR_RETURN(rv);
   1907                     pa->old_index = _REGEX_INVALID_INDEX;
   1908                 }
   1909                 break;
   1910             default:
   1911                 break;
   1912         }
   1913     }
   1914     return (rv);
   1915 }
   1916 
   1917 
   1918 /*
   1919  * Function:
   1920  *     _regex_policy_redirect_profile_hw_alloc
   1921  *
   1922  * Purpose:
   1923  *     Allocate redirect profile index required for profile installation.
   1924  *
   1925  * Parameters:
   1926  *     unit      - (IN) BCM device number.
   1927  *     p_ent     - (IN) Regex profile structure.
   1928  * Returns:
   1929  *     BCM_E_XXX
   1930  * Notes:
   1931  */
   1932 STATIC int _regex_policy_redirect_profile_hw_alloc(int unit, _regex_policy_t *p_ent)
   1933 {
   1934     _bcm_esw_regex_device_info_t *device;    /* Regex control structure. */
   1935     int                     rv = BCM_E_NONE; /* Operation return status.     */
   1936     _regex_policy_action_t *pa;
   1937     int                     ref_count;  /* Profile use reference count. */
   1938 
   1939     /* Get the device info structure. */
   1940     device = ESW_REGEX_INFO(unit);
   1941     if (NULL == device) {
   1942         return BCM_E_INIT;
   1943     }
   1944 
   1945     /* Applicable to stage ingress on TRX devices only. */
   1946 
   1947     /* Extract the policy info from the entry structure. */
   1948     for (pa = p_ent->actions; ((pa != NULL) && (_REGEX_ACTION_VALID & pa->flags)); pa = pa->next) {
   1949         switch (pa->action) {
   1950             case bcmFieldActionRedirectMcast:
   1951 #if defined(INCLUDE_L3)
   1952             case bcmFieldActionRedirectIpmc:
   1953 #endif /* INCLUDE_L3 */
   1954                 if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){
   1955                     break;
   1956                 }
   1957             case bcmFieldActionRedirectPbmp:
   1958             case bcmFieldActionRedirectBcastPbmp:
   1959             case bcmFieldActionEgressMask:
   1960             case bcmFieldActionEgressPortsAdd:
   1961                 /*
   1962                  * Store previous hardware index value in old_index.
   1963                  */
   1964                 pa->old_index = pa->hw_index;
   1965 
   1966                 rv = device->functions->redirect_profile_alloc(unit, p_ent, pa);
   1967                 if ((BCM_E_RESOURCE == rv) &&
   1968                     (_REGEX_INVALID_INDEX != pa->old_index)) {
   1969                     /* Destroy old profile ONLY
   1970                      * if it is not used by other entries.
   1971                      */
   1972                     rv = device->functions->redirect_profile_ref_count_get(unit,
   1973                                                                            pa->old_index,
   1974                                                                            &ref_count);
   1975                     BCM_IF_ERROR_RETURN(rv);
   1976                     if (ref_count > 1) {
   1977                         return (BCM_E_RESOURCE);
   1978                     }
   1979                     rv = device->functions->redirect_profile_delete(unit, pa->old_index);
   1980                     BCM_IF_ERROR_RETURN(rv);
   1981 
   1982                     /* Destroy old profile is no longer required. */
   1983                     pa->old_index = _REGEX_INVALID_INDEX;
   1984 
   1985                     /* Reallocate profile for new action. */
   1986                     rv = device->functions->redirect_profile_alloc(unit, p_ent, pa);
   1987                 }
   1988                 break;
   1989             default:
   1990                 break;
   1991         }
   1992         if (BCM_FAILURE(rv)) {
   1993             _regex_policy_redirect_profile_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE);
   1994             break;
   1995         }
   1996     }
   1997 
   1998     return (rv);
   1999 }
   2000 
   2001 STATIC int _regex_policers_compat(int               unit,
   2002                                   _regex_policy_t  *p_ent,
   2003                                   unsigned          lvl,
   2004                                   _field_policer_t *f_pl)
   2005 {
   2006 #if defined(ESW_REGEX_HIERARCHICAL_METERS)
   2007     const unsigned olvl        = 1 - lvl;
   2008     _field_policer_t *_f_pl[2] = { 0, 0 };
   2009 
   2010     _f_pl[lvl] = f_pl;
   2011 
   2012     if (!(p_ent->policer[olvl].flags & _FP_POLICER_VALID)) {
   2013         return (BCM_E_NONE);
   2014     }
   2015 
   2016     BCM_IF_ERROR_RETURN(_bcm_regex_policer_get(unit,
   2017                                                p_ent->policer[olvl].pid,
   2018                                                &_f_pl[olvl]));
   2019 
   2020     switch (_f_pl[1]->cfg.flags & BCM_POLICER_COLOR_MERGE_MASK) {
   2021         case BCM_POLICER_COLOR_MERGE_AND:
   2022         case BCM_POLICER_COLOR_MERGE_OR:
   2023             /* Level 1 sharing mode is SINGLE_AND or SINGLE_OR
   2024                => level 0 and level 1 must both be in flow or modified
   2025                trTCM mode
   2026             */
   2027 
   2028             if ((IS_FLOW_MODE(_f_pl[0]) && IS_FLOW_MODE(_f_pl[1])) ||
   2029                 (IS_MOD_TRTCM_MODE(_f_pl[0]) && IS_MOD_TRTCM_MODE(_f_pl[1]))) {
   2030                 break;
   2031             }
   2032             return (BCM_E_PARAM);
   2033 
   2034         case BCM_POLICER_COLOR_MERGE_DUAL:
   2035             /* Level 1 sharing mode is DUAL
   2036                => level 0 must be modified trTCM
   2037             */
   2038 
   2039             if (IS_MOD_TRTCM_MODE(_f_pl[0])) {
   2040                 break;
   2041             }
   2042             return (BCM_E_PARAM);
   2043 
   2044         default:
   2045             return (BCM_E_PARAM);
   2046     }
   2047 #endif
   2048     return (BCM_E_NONE);
   2049 }
   2050 
   2051 /*
   2052  * Function:
   2053  *      _regex_policer_mode_support
   2054  * Purpose:
   2055  *      Validate policer mode support.
   2056  * Parameters:
   2057  *      unit    - (IN) BCM device number.
   2058  *      p_ent   - (IN) Policy to which policer is attached.
   2059  *      level   - (IN) Level policer attached.
   2060  *      f_pl    - (IN) Policer descriptor.
   2061  * Returns:
   2062  *      BCM_E_XXX
   2063  */
   2064 STATIC int _regex_policer_mode_support(int               unit,
   2065                                        _regex_policy_t  *p_ent,
   2066                                        int               lvl,
   2067                                        _field_policer_t *f_pl)
   2068 {
   2069     switch (f_pl->cfg.mode) {
   2070         case bcmPolicerModeGreen:
   2071         case bcmPolicerModePassThrough:
   2072         case bcmPolicerModeCommitted:
   2073         case bcmPolicerModeTrTcmDs:
   2074         case bcmPolicerModeCoupledTrTcmDs:
   2075             break;
   2076         case bcmPolicerModeSrTcm:
   2077         case bcmPolicerModeSrTcmModified:
   2078         case bcmPolicerModeTrTcm:
   2079             if (lvl == 1) {
   2080                 return (BCM_E_PARAM);
   2081             }
   2082             break;
   2083         default:
   2084             return (BCM_E_PARAM);
   2085     }
   2086 
   2087     return _regex_policers_compat(unit, p_ent, lvl, f_pl);
   2088 }
   2089 
   2090 /*
   2091  * Function:
   2092  *      _regex_policer_hw_flags_set
   2093  * Purpose:
   2094  *      Update policer installation is required flag.
   2095  * Parameters:
   2096  *      unit    - (IN) Unit number.
   2097  *      f_pl    - (IN/OUT) Internal policer descriptor.
   2098  *      flags   - (IN) Internal flags.
   2099  * Returns:
   2100  *      BCM_E_XXX
   2101  * Notes:
   2102  */
   2103 STATIC int _regex_policer_hw_flags_set(int unit, _field_policer_t *f_pl, uint32 flags)
   2104 {
   2105     /* Input parameters check. */
   2106     if (NULL == f_pl) {
   2107         return (BCM_E_PARAM);
   2108     }
   2109 
   2110     f_pl->hw_flags |= flags;
   2111 
   2112     switch (f_pl->cfg.mode) {
   2113         case bcmPolicerModeSrTcm:
   2114         case bcmPolicerModeTrTcm:
   2115         case bcmPolicerModeTrTcmDs:
   2116         case bcmPolicerModeCoupledTrTcmDs:
   2117         case bcmPolicerModeSrTcmModified:
   2118         case bcmPolicerModeCommitted:
   2119             f_pl->hw_flags |= _FP_POLICER_DIRTY;
   2120             break;
   2121         default:
   2122             return (BCM_E_UNAVAIL);
   2123     }
   2124     return (BCM_E_NONE);
   2125 }
   2126 
   2127 /*
   2128  * Function:
   2129  *     _regex_policer_hw_free
   2130  *
   2131  * Purpose:
   2132  *     Deallocate hw policer from a policy.
   2133  *
   2134  * Parameters:
   2135  *     unit      - (IN) BCM device number.
   2136  *     level     - (IN) Policer level.
   2137  *     p_ent     - (IN) Policy that policer belongs to.
   2138  * Returns:
   2139  *     BCM_E_XXX
   2140  */
   2141 STATIC int _regex_policer_hw_free(int unit, uint8 level, _regex_policy_t *p_ent)
   2142 {
   2143     _field_entry_policer_t *f_ent_pl;  /* Field entry policer structure. */
   2144     _field_policer_t       *f_pl;      /* Policer descriptor.            */
   2145 
   2146     /* Input parameters check. */
   2147     if ((NULL == p_ent) || (level >= _REGEX_POLICER_LEVEL_COUNT)) {
   2148         return (BCM_E_PARAM);
   2149     }
   2150 
   2151     f_ent_pl = p_ent->policer + level;
   2152     /* Skip uninstalled policers. */
   2153     if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) {
   2154         return (BCM_E_NONE);
   2155     }
   2156 
   2157     /* Read policer configuration.*/
   2158     BCM_IF_ERROR_RETURN(_bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl));
   2159 
   2160     /* Decrement hw reference count. */
   2161     if (f_pl->hw_ref_count > 0) {
   2162         f_pl->hw_ref_count--;
   2163     }
   2164 
   2165     /* Policer not used by any other entry. */
   2166     if (f_pl->hw_ref_count == 0) {
   2167         /* Mark policer for reinstallation. */
   2168         BCM_IF_ERROR_RETURN(_regex_policer_hw_flags_set(unit, f_pl, 0));
   2169     }
   2170     f_ent_pl->flags &= ~_FP_POLICER_INSTALLED;
   2171     return (BCM_E_NONE);
   2172 }
   2173 
   2174 /*
   2175  * Function:
   2176  *     _regex_policers_hw_alloc
   2177  *
   2178  * Purpose:
   2179  *     Allocate policers required for policy installation.
   2180  *
   2181  * Parameters:
   2182  *     unit      - (IN) BCM device number.
   2183  *     f_ent     - (IN) Field entry array.
   2184  * Returns:
   2185  *     BCM_E_XXX
   2186  * Notes:
   2187  *     This API should be STATIC but is called by the legacy
   2188  *     bregex code in tr3.
   2189  */
   2190 int _regex_policers_hw_alloc(int unit, _regex_policy_t *p_ent)
   2191 {
   2192     _bcm_esw_regex_device_info_t *device;   /* Regex control structure. */
   2193     _field_entry_policer_t       *f_ent_pl; /* Field entry policer structure.*/
   2194     _field_policer_t             *f_pl;     /* Field policer descriptor.     */
   2195     int                           idx;      /* Policer levels iterator.      */
   2196     int                           rv;       /* Operation return status.      */
   2197 
   2198     /* Input parameters check. */
   2199     if (NULL == p_ent) {
   2200         return (BCM_E_PARAM);
   2201     }
   2202 
   2203     /* Get the device info structure. */
   2204     device = ESW_REGEX_INFO(unit);
   2205     if (NULL == device) {
   2206         return BCM_E_INIT;
   2207     }
   2208 
   2209     /* Allocate policers if necessary. */
   2210     for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) {
   2211         f_ent_pl = p_ent->policer + idx;
   2212         /* Skip invalid policers. */
   2213         if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   2214             continue;
   2215         }
   2216 
   2217         /* Read policer configuration.*/
   2218         rv = _bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl);
   2219         BCM_IF_ERROR_RETURN(rv);
   2220 
   2221         /*
   2222          * Check policer mode support - double check in case
   2223          * attached policer was modified by bcm_policer_set API.
   2224          */
   2225         rv = _regex_policer_mode_support(unit, p_ent, idx, f_pl);
   2226         BCM_IF_ERROR_RETURN(rv);
   2227 
   2228         /* Calculate HW index */
   2229         f_pl->hw_index   = _REGEX_POLICER_ID_TO_INDEX(f_pl->pid);
   2230         f_pl->pool_index = device->meter_pool;
   2231 
   2232         /* Increment hw reference count. */
   2233         if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) {
   2234             f_ent_pl->flags |=  _FP_POLICER_INSTALLED;
   2235             f_pl->hw_ref_count++;
   2236         }
   2237 
   2238         if (f_pl->hw_flags & _FP_POLICER_DIRTY) {
   2239             BCM_IF_ERROR_RETURN(device->functions->policer_install(unit, f_pl));
   2240         }
   2241     }
   2242 
   2243     return (BCM_E_NONE);
   2244 }
   2245 
   2246 /*
   2247  * Function:
   2248  *     _regex_policers_hw_free
   2249  *
   2250  * Purpose:
   2251  *     Free entry policers.
   2252  *
   2253  * Parameters:
   2254  *     unit      - (IN) BCM device number.
   2255  *     p_ent     - (IN) Regex policy structure.
   2256  * Returns:
   2257  *     BCM_E_XXX
   2258  * Notes:
   2259  */
   2260 STATIC int _regex_policers_hw_free(int unit, _regex_policy_t *p_ent)
   2261 {
   2262     _field_entry_policer_t *f_ent_pl;  /* Field entry policer structure.*/
   2263     int                    idx;        /* Policer levels iterator.      */
   2264 
   2265     /* Input parameters check. */
   2266     if (NULL == p_ent) {
   2267         return (BCM_E_PARAM);
   2268     }
   2269 
   2270     /* Free policers if necessary. */
   2271     for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) {
   2272         f_ent_pl = p_ent->policer + idx;
   2273         /* Skip invalid policers. */
   2274         if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   2275             continue;
   2276         }
   2277         /* Skip installed policers. */
   2278         if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) {
   2279             continue;
   2280         }
   2281 
   2282         BCM_IF_ERROR_RETURN(_regex_policer_hw_free(unit, idx, p_ent));
   2283     }
   2284     return (BCM_E_NONE);
   2285 }
   2286 
   2287 /*
   2288  * Function:
   2289  *     _regex_policy_hw_resources_free
   2290  *
   2291  * Purpose:
   2292  *     Free hw resources used in FP entry.
   2293  *
   2294  * Parameters:
   2295  *     unit      - (IN) BCM device number.
   2296  *     p_ent     - (IN) Regex policy structure.
   2297  *     flags     - (IN) Old/installed resource to free.
   2298  * Returns:
   2299  *     BCM_E_XXX
   2300  */
   2301 STATIC int _regex_policy_hw_resources_free(int unit, _regex_policy_t *p_ent, uint32 flags)
   2302 {
   2303     int rv;   /* Operation return status. */
   2304 
   2305     /* Input parameters check. */
   2306     if (NULL == p_ent) {
   2307         return (BCM_E_PARAM);
   2308     }
   2309 
   2310     /* Free redirection profiles. */
   2311     rv = _regex_policy_redirect_profile_hw_free(unit, p_ent, flags);
   2312     BCM_IF_ERROR_RETURN(rv);
   2313 
   2314     /* Free mirror destination indexes. */
   2315     rv = _regex_policy_mtp_hw_free(unit, p_ent, flags);
   2316     BCM_IF_ERROR_RETURN(rv);
   2317 
   2318 #ifdef ESW_REGEX_STAT_SUPPORT
   2319     /* Free counters. */
   2320     if (flags & _REGEX_ACTION_RESOURCE_FREE) {
   2321         rv = _field_stat_hw_free(unit, p_ent);
   2322         BCM_IF_ERROR_RETURN(rv);
   2323     }
   2324 #endif
   2325 
   2326     /* Free policers. */
   2327     if (flags & _REGEX_ACTION_RESOURCE_FREE) {
   2328         rv = _regex_policers_hw_free(unit, p_ent);
   2329         BCM_IF_ERROR_RETURN(rv);
   2330     }
   2331 
   2332 #if defined(INCLUDE_L3)
   2333     if (soc_feature(unit, soc_feature_field_action_l2_change)) {
   2334         rv = _regex_policy_l2_actions_hw_free(unit, p_ent, flags);
   2335         BCM_IF_ERROR_RETURN(rv);
   2336     }
   2337 #endif /* INCLUDE_L3 */
   2338 
   2339     return (BCM_E_NONE);
   2340 }
   2341 
   2342 /*
   2343  * Function:
   2344  *     _regex_policy_hw_resources_alloc
   2345  *
   2346  * Purpose:
   2347  *     Allocate hw resources required for entry installation.
   2348  *
   2349  * Parameters:
   2350  *     unit      - (IN) BCM device number.
   2351  *     f_ent     - (IN) Entry array
   2352  * Returns:
   2353  *     BCM_E_XXX
   2354  */
   2355 STATIC int _regex_policy_hw_resources_alloc(int unit, _regex_policy_t *p_ent)
   2356 {
   2357     int rv;                        /* Operation return status. */
   2358 
   2359     /* Input parameters check. */
   2360     if (NULL == p_ent) {
   2361         return (BCM_E_PARAM);
   2362     }
   2363 
   2364     /* Allocate policers. */
   2365     BCM_IF_ERROR_RETURN(_regex_policers_hw_alloc(unit, p_ent));
   2366 
   2367 #ifdef ESW_REGEX_STAT_SUPPORT
   2368     /* Allocate statistics. */
   2369     rv = _field_stat_hw_alloc(unit, p_ent);
   2370     if (BCM_FAILURE(rv)) {
   2371         _regex_policers_hw_free(unit, p_ent);
   2372         return (rv);
   2373     }
   2374 #endif
   2375 
   2376     /* Allocate mirror destination indexes. */
   2377     /* COVERITY
   2378      * Internally calls bcm_esw_mirror_enable()
   2379      * routine, which has most stack use: 7844 bytes
   2380      */
   2381     /* coverity[stack_use_overflow : FALSE] */
   2382     rv = _regex_policy_mtp_hw_alloc(unit, p_ent);
   2383     if (BCM_FAILURE(rv)) {
   2384 #ifdef ESW_REGEX_STAT_SUPPORT
   2385         _field_stat_hw_free(unit, p_ent);
   2386 #endif
   2387         _regex_policers_hw_free(unit, p_ent);
   2388         return (rv);
   2389     }
   2390 
   2391     /* Allocate redirection profiles. */
   2392     rv = _regex_policy_redirect_profile_hw_alloc(unit, p_ent);
   2393     if (BCM_FAILURE(rv)) {
   2394         _regex_policy_mtp_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE);
   2395 #ifdef ESW_REGEX_STAT_SUPPORT
   2396         _field_stat_hw_free(unit, p_ent);
   2397 #endif
   2398         _regex_policers_hw_free(unit, p_ent);
   2399         return (rv);
   2400     }
   2401 
   2402 #if defined (INCLUDE_L3)
   2403     if (soc_feature(unit, soc_feature_field_action_l2_change)) {
   2404         rv =  _regex_policy_l2_actions_hw_alloc(unit, p_ent);
   2405         if (BCM_FAILURE(rv)) {
   2406             _regex_policy_mtp_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE);
   2407 #ifdef ESW_REGEX_STAT_SUPPORT
   2408             _field_stat_hw_free(unit, p_ent);
   2409 #endif
   2410             _regex_policers_hw_free(unit, p_ent);
   2411             _regex_policy_redirect_profile_hw_free(unit, p_ent, _REGEX_ACTION_HW_FREE);
   2412             return (rv);
   2413         }
   2414     }
   2415 #endif /* INCLUDE_L3 */
   2416 
   2417     return (BCM_E_NONE);
   2418 }
   2419 
   2420 /*
   2421  * Function:
   2422  *     _regex_policy_install
   2423  *
   2424  * Purpose:
   2425  *     Install a regex FT_POLICY entry. This writes the
   2426  *     actions to the hardware.
   2427  *
   2428  * Parameters:
   2429  *     unit   - (IN) BCM device number.
   2430  *     policy - (IN) Policy ID to be installed.
   2431  * Returns:
   2432  *     BCM_E_XXX
   2433  */
   2434 STATIC int _regex_policy_install(int unit, bcm_regex_policy_t policy)
   2435 {
   2436     _regex_policy_t              *p_ent; /* Policy entry pointer. */
   2437     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   2438     int                           rv;   /* Operation return status.  */
   2439 
   2440     LOG_DEBUG(BSL_LS_BCM_REGEX,
   2441               (BSL_META_U(unit,
   2442                           "FT(unit %d) vverb: %s(%d)\n"),
   2443                unit, FUNCTION_NAME(), policy));
   2444 
   2445     /* Get the device info structure. */
   2446     device = ESW_REGEX_INFO(unit);
   2447     if (NULL == device) {
   2448         return BCM_E_INIT;
   2449     }
   2450 
   2451     /* Installing the entry. */
   2452     rv = _regex_policy_get(unit, policy, &p_ent);
   2453     BCM_IF_ERROR_RETURN(rv);
   2454 
   2455     /* If entry was previously installed, we better disable it temporarily,
   2456      * to avoid intermittent actions.
   2457      */
   2458     if (p_ent->flags & _REGEX_POLICY_INSTALLED) {
   2459         /* Disable installed entry. */
   2460         rv = device->functions->policy_remove(unit, p_ent);
   2461         BCM_IF_ERROR_RETURN(rv);
   2462     }
   2463 
   2464     /* Remove deleted actions. */
   2465     rv = _regex_policy_invalid_actions_remove(unit, p_ent);
   2466     BCM_IF_ERROR_RETURN(rv);
   2467 
   2468     /* Allocate hw resources required for policy installation. */
   2469     rv = _regex_policy_hw_resources_alloc(unit, p_ent);
   2470     BCM_IF_ERROR_RETURN(rv);
   2471 
   2472     /* Install physical policy */
   2473     rv = device->functions->policy_install(unit, p_ent);
   2474     if (BCM_FAILURE(rv)) {
   2475         (void)_regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_HW_FREE);
   2476         return (rv);
   2477     }
   2478     p_ent->flags &= ~_REGEX_POLICY_DIRTY;
   2479     p_ent->flags |= _REGEX_POLICY_INSTALLED;
   2480 
   2481     /* In case of policy reinstall free previous installation hw resources. */
   2482     rv = _regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_OLD_RESOURCE_FREE);
   2483     if (BCM_FAILURE(rv)) {
   2484         BCM_IF_ERROR_RETURN(_regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_HW_FREE));
   2485         return (rv);
   2486     }
   2487     return (BCM_E_NONE);
   2488 }
   2489 
   2490 /*
   2491  * Function: _regex_policy_remove
   2492  *
   2493  * Purpose:
   2494  *     Remove a policy from the hardware tables.
   2495  *
   2496  * Parameters:
   2497  *     unit   - (IN) BCM device number
   2498  *     policy - (IN) policy to remove.
   2499  *
   2500  * Returns:
   2501  *     BCM_E_XXX
   2502  */
   2503 int _regex_policy_remove(int unit, bcm_regex_policy_t policy)
   2504 {
   2505     _regex_policy_t              *p_ent; /* Policy entry pointer. */
   2506     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   2507     int                           rv;   /* Operation return status.  */
   2508 
   2509     LOG_DEBUG(BSL_LS_BCM_REGEX,
   2510               (BSL_META_U(unit,
   2511                           "FT(unit %d) vverb: %s(%d)\n"),
   2512                unit, FUNCTION_NAME(), policy));
   2513 
   2514     /* Get the device info structure. */
   2515     device = ESW_REGEX_INFO(unit);
   2516     if (NULL == device) {
   2517         return BCM_E_INIT;
   2518     }
   2519 
   2520     rv = _regex_policy_get(unit, policy, &p_ent);
   2521     if (BCM_FAILURE(rv)) {
   2522         return (rv);
   2523     }
   2524 
   2525     if (!(p_ent->flags & _REGEX_POLICY_INSTALLED)) {
   2526         /* Entry not installed in hardware to perform remove operation. */
   2527         return (BCM_E_NONE);
   2528     }
   2529 
   2530     /* Free hw resources allocated during entry installation. */
   2531     rv = _regex_policy_hw_resources_free(unit, p_ent, _REGEX_ACTION_RESOURCE_FREE);
   2532     BCM_IF_ERROR_RETURN(rv);
   2533 
   2534     rv = device->functions->policy_remove(unit, p_ent);
   2535     BCM_IF_ERROR_RETURN(rv);
   2536 
   2537     p_ent->flags |= _REGEX_POLICY_DIRTY;
   2538     p_ent->flags &= ~_REGEX_POLICY_INSTALLED;
   2539 
   2540 
   2541     /* Remove deleted actions. */
   2542     rv = _regex_policy_invalid_actions_remove(unit, p_ent);
   2543     BCM_IF_ERROR_RETURN(rv);
   2544     return (BCM_E_NONE);
   2545 }
   2546 
   2547 /*
   2548  * Function: _regex_policy_create_id
   2549  *
   2550  * Purpose:
   2551  *     Create a blank entry group based on a group;
   2552  *     allows selection of a specific slot in a slice
   2553  *
   2554  * Parameters:
   2555  *     unit   - (IN) BCM device number.
   2556  *     policy - (IN) Policy id.
   2557  * Returns:
   2558  *     BCM_E_INIT      - unit not initialized
   2559  *     BCM_E_EXISTS    - Policy ID already in use
   2560  *     BCM_E_MEMORY    - allocation failure
   2561  *     BCM_E_NONE      - Success
   2562  */
   2563 STATIC int _regex_policy_create_id(int unit, bcm_regex_policy_t policy)
   2564 {
   2565     _regex_policy_t              *p_ent;  /* Allocated entry buffer.      */
   2566     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   2567     int                           rv;     /* Operation return status.     */
   2568 
   2569     LOG_DEBUG(BSL_LS_BCM_REGEX,
   2570               (BSL_META_U(unit,
   2571                           "FT(unit %d) vverb: %s(policy=%d)\n"),
   2572                unit, FUNCTION_NAME(), policy));
   2573 
   2574     /* Confirm that 'policy' is not already used on unit */
   2575     if (BCM_SUCCESS(_regex_policy_get(unit, policy, &p_ent))) {
   2576         LOG_ERROR(BSL_LS_BCM_REGEX,
   2577                   (BSL_META_U(unit,
   2578                               "FT(unit %d) Error: policy=(%d) already exists.\n"),
   2579                    unit, policy));
   2580         return (BCM_E_EXISTS);
   2581     }
   2582 
   2583     device = ESW_REGEX_INFO(unit);
   2584     if (NULL == device) {
   2585         return BCM_E_INIT;
   2586     }
   2587 
   2588     if (device->num_policies >= ESW_REGEX_POLICIES_MAX(unit)) {
   2589         LOG_ERROR(BSL_LS_BCM_REGEX,
   2590                   (BSL_META_U(unit,
   2591                               "FT(unit %d) Error: No room.\n"),
   2592                    unit));
   2593         return (BCM_E_RESOURCE);
   2594     }
   2595 
   2596     /* Create entry structure. */
   2597     rv = _regex_policy_phys_create(unit, policy, &p_ent);
   2598     if (BCM_FAILURE(rv)) {
   2599         return (rv);
   2600     }
   2601 
   2602     return (BCM_E_NONE);
   2603 }
   2604 
   2605 /*
   2606  * Function:
   2607  *     _regex_policy_action_alloc
   2608  * Purpose:
   2609  *     Allocate and initialize an action structure.
   2610  * Parameters:
   2611  *     unit     - BCM device number.
   2612  *     action   - Action to perform (bcmFieldActionXXX)
   2613  *     param0   - Action parameter (use 0 if not required)
   2614  *     param1   - Action parameter (use 0 if not required)
   2615  *     param2   - Action parameter (use 0 if not required)
   2616  *     param3   - Action parameter (use 0 if not required)
   2617  *     fa (OUT) - pointer to field action structure
   2618  * Returns:
   2619  *     BCM_E_MEMORY - allocation failure
   2620  *     BCM_E_NONE   - Success
   2621  */
   2622 int _regex_policy_action_alloc(int unit, bcm_field_action_t action,
   2623                                uint32 param0, uint32 param1, uint32 param2,
   2624                                uint32 param3, _regex_policy_action_t **pa)
   2625 {
   2626     *pa = sal_alloc(sizeof(**pa), "regex_policy_action");
   2627     if (NULL == *pa) {
   2628         LOG_ERROR(BSL_LS_BCM_REGEX,
   2629                   (BSL_META_U(unit,
   2630                               "FT(unit %d) Error: allocation failure for regex_policy_action\n"),
   2631                    unit));
   2632         return (BCM_E_MEMORY);
   2633     }
   2634     sal_memset(*pa, 0, sizeof(**pa));
   2635 
   2636     (*pa)->action = action;
   2637     (*pa)->param[0] = param0;
   2638     (*pa)->param[1] = param1;
   2639     (*pa)->param[2] = param2;
   2640     (*pa)->param[3] = param3;
   2641     (*pa)->hw_index = _REGEX_INVALID_INDEX;
   2642     (*pa)->old_index = _REGEX_INVALID_INDEX;
   2643     /* mark new action as not yet installed */
   2644     (*pa)->flags |= (_REGEX_ACTION_VALID | _REGEX_ACTION_DIRTY);
   2645 
   2646     return (BCM_E_NONE);
   2647 }
   2648 
   2649 /*
   2650  * Function: _regex_policy_action_add
   2651  *
   2652  * Purpose:
   2653  *     Add action performed when policy is applied to a session.
   2654  *
   2655  * Parameters:
   2656  *     unit   - (IN) BCM device number.
   2657  *     policy - (IN) Policy entry id.
   2658  *     pa     - (IN) Policy action structure.
   2659  * Returns:
   2660  *     BCM_E_XXX
   2661  */
   2662 int _regex_policy_action_add(int unit, bcm_regex_policy_t policy, _regex_policy_action_t *pa)
   2663 {
   2664     _regex_policy_t              *p_ent; /* Field entry structure.       */
   2665     _regex_policy_action_t       *pa_iter; /* Field entry actions iterator.*/
   2666     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   2667     int                           rv;   /* Operation return status.     */
   2668 
   2669     /* Get policy structure pointer. */
   2670     rv = _regex_policy_get(unit, policy, &p_ent);
   2671     BCM_IF_ERROR_RETURN(rv);
   2672 
   2673     device = ESW_REGEX_INFO(unit);
   2674     if (NULL == device) {
   2675         return BCM_E_INIT;
   2676     }
   2677 
   2678     /* Ensure action is supported. */
   2679     rv = device->functions->policy_action_support_check(unit,
   2680                                                         pa->action);
   2681     if (BCM_FAILURE(rv)) {
   2682         LOG_ERROR(BSL_LS_BCM_REGEX,
   2683                   (BSL_META_U(unit,
   2684                               "FT(unit %d) Error: action=%s is not supported.\n"),
   2685                    unit,
   2686                    _regex_policy_action_name(pa->action)));
   2687         return (rv);
   2688     }
   2689 
   2690     /* Check for existing actions that conflict with the new action. */
   2691     pa_iter = p_ent->actions;
   2692     while (pa_iter != NULL) {
   2693         if (0 == (pa_iter->flags & _REGEX_ACTION_VALID)) {
   2694             pa_iter = pa_iter->next;
   2695             continue;
   2696         }
   2697         rv = device->functions->policy_action_conflict_check(unit,
   2698                                                             pa_iter->action,
   2699                                                             pa->action);
   2700         if (BCM_FAILURE(rv)) {
   2701             LOG_ERROR(BSL_LS_BCM_REGEX,
   2702                       (BSL_META_U(unit,
   2703                                   "FT(unit %d) Error: action=%s conflicts with existing action in policy=%d\n"),
   2704                        unit,
   2705                        _regex_policy_action_name(pa->action),
   2706                        policy));
   2707             return (rv);
   2708         }
   2709         pa_iter = pa_iter->next;
   2710     }
   2711 
   2712     /* Check action parameters. */
   2713     rv = device->functions->policy_action_params_check(unit, p_ent, pa);
   2714     if (BCM_FAILURE(rv)) {
   2715         LOG_ERROR(BSL_LS_BCM_REGEX,
   2716                   (BSL_META_U(unit,
   2717                               "FT(unit %d) Error: action=%s parameters check failed (%d)\n"),
   2718                    unit, _regex_policy_action_name(pa->action), rv));
   2719         return (rv);
   2720     }
   2721 
   2722     if (pa->action == bcmFieldActionColorIndependent) {
   2723         if (0 != pa->param[0])  {
   2724             p_ent->flags |= _REGEX_POLICY_COLOR_INDEPENDENT;
   2725         } else {
   2726             p_ent->flags &= ~_REGEX_POLICY_COLOR_INDEPENDENT;
   2727         }
   2728         p_ent->flags  |= _REGEX_POLICY_DIRTY;
   2729         sal_free(pa);
   2730         return (BCM_E_NONE);
   2731     }
   2732 
   2733     /* Add action to front of entry's linked-list. */
   2734     ESW_REGEX_LOCK(unit);
   2735     pa->next = p_ent->actions;
   2736     p_ent->actions  = pa;
   2737     p_ent->flags    |= _REGEX_POLICY_DIRTY;
   2738     ESW_REGEX_UNLOCK(unit);
   2739     return (BCM_E_NONE);
   2740 }
   2741 
   2742 /*
   2743  * Function: _regex_policy_action_ports_add
   2744  *
   2745  * Purpose:
   2746  *     Add action performed when policy is applied to a session.
   2747  *
   2748  * Parameters:
   2749  *     unit   - (IN) BCM device number
   2750  *     policy - (IN) Policy entry id.
   2751  *     action - (IN) Action to perform (bcmFieldActionXXX)
   2752  *     param0 - (IN) Action parameter (use 0 if not required)
   2753  *     param1 - (IN) Action parameter (use 0 if not required)
   2754  *     param2 - (IN) Action parameter (use 0 if not required)
   2755  *     param3 - (IN) Action parameter (use 0 if not required)
   2756  *
   2757  * Returns:
   2758  *     BCM_E_XXX
   2759  */
   2760 STATIC int _regex_policy_action_ports_add(int unit,
   2761                                           bcm_regex_policy_t policy,
   2762                                           bcm_field_action_t action,
   2763                                           uint32 param0,
   2764                                           uint32 param1,
   2765                                           uint32 param2,
   2766                                           uint32 param3)
   2767 {
   2768     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   2769     _regex_policy_action_t       *pa = NULL; /* Policy action descriptor. */
   2770     int                           rv;   /* Operation return status. */
   2771 
   2772     LOG_DEBUG(BSL_LS_BCM_REGEX,
   2773               (BSL_META_U(unit,
   2774                           "FT(unit %d) vverb: %s(policy=%d, action=%s, p0=%d, p1=%d, p2=%d)\n"),
   2775                unit, FUNCTION_NAME(), policy,
   2776                _regex_policy_action_name(action),
   2777                param0, param1, param2));
   2778 
   2779     device = ESW_REGEX_INFO(unit);
   2780     if (NULL == device) {
   2781         return BCM_E_INIT;
   2782     }
   2783     ESW_REGEX_LOCK(unit);
   2784 
   2785     /*
   2786      * Allocate the action  descriptor.
   2787      */
   2788     rv = _regex_policy_action_alloc(unit, action, param0, param1, param2, param3, &pa);
   2789     if (BCM_FAILURE(rv)) {
   2790         LOG_ERROR(BSL_LS_BCM_REGEX,
   2791                   (BSL_META_U(unit,
   2792                               "FT Error: _regex_policy_action_alloc failed\n")));
   2793         ESW_REGEX_UNLOCK(unit);
   2794         return rv;
   2795     }
   2796 
   2797     /*
   2798      * Add action to entry actions list.
   2799      */
   2800     rv = _regex_policy_action_add(unit, policy, pa);
   2801     ESW_REGEX_UNLOCK(unit);
   2802     if (BCM_FAILURE(rv)) {
   2803         sal_free(pa);
   2804         return rv;
   2805     }
   2806     return (BCM_E_NONE);
   2807 }
   2808 
   2809 /*
   2810  * Function: _regex_policy_action_ports_get
   2811  *
   2812  * Purpose:
   2813  *     Get parameters associated with a policy action
   2814  *
   2815  * Parameters:
   2816  *     unit   - (IN) BCM device number
   2817  *     policy - (IN) Policy entry id.
   2818  *     action - (IN) Action to perform (bcmFieldActionXXX)
   2819  *     param0 - (OUT) Action parameter
   2820  *     param1 - (OUT) Action parameter
   2821  *     param2 - (OUT) Action parameter
   2822  *     param3 - (OUT) Action parameter
   2823  *
   2824  * Returns:
   2825  *     BCM_E_INIT      - BCM Unit not initialized
   2826  *     BCM_E_NOT_FOUND - Entry ID not found
   2827  *     BCM_E_NOT_FOUND - No matching Action for entry
   2828  *     BCM_E_PARAM     - paramX is NULL
   2829  *     BCM_E_NONE      - Success
   2830  */
   2831 
   2832 STATIC int _regex_policy_action_ports_get(int unit,
   2833                                           bcm_regex_policy_t policy,
   2834                                           bcm_field_action_t action,
   2835                                           uint32 *param0,
   2836                                           uint32 *param1,
   2837                                           uint32 *param2,
   2838                                           uint32 *param3)
   2839 {
   2840     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   2841     _regex_policy_action_t       *pa = NULL; /* Policy action descriptor. */
   2842     _regex_policy_t              *p_ent; /* Field entry structure.       */
   2843     int                           rv;
   2844 
   2845     /* Input parameters check. */
   2846     if ((NULL == param0) || (NULL == param1) || (NULL == param2)) {
   2847             return (BCM_E_PARAM);
   2848     }
   2849 
   2850     /* Lock the module. */
   2851     device = ESW_REGEX_INFO(unit);
   2852     if (NULL == device) {
   2853         return BCM_E_INIT;
   2854     }
   2855     ESW_REGEX_LOCK(unit);
   2856 
   2857     rv = _regex_policy_get(unit, policy, &p_ent);
   2858     if (BCM_FAILURE(rv)) {
   2859         ESW_REGEX_UNLOCK(unit);
   2860         return (rv);
   2861     }
   2862 
   2863     /* Find matching action in the entry */
   2864     for (pa = p_ent->actions; pa != NULL; pa = pa->next) {
   2865         if (pa->action == action) {
   2866             break;
   2867         }
   2868     }
   2869 
   2870     if (pa == NULL) {
   2871         ESW_REGEX_UNLOCK(unit);
   2872         LOG_VERBOSE(BSL_LS_BCM_REGEX,
   2873                     (BSL_META_U(unit,
   2874                                 "FT(unit %d) Error: action not in policy=%d\n"),
   2875                      unit, policy));
   2876         return (BCM_E_NOT_FOUND);
   2877     }
   2878 
   2879     *param0 = pa->param[0];
   2880     *param1 = pa->param[1];
   2881     *param2 = pa->param[2];
   2882     *param3 = pa->param[3];
   2883 
   2884     /* Unlock the module. */
   2885     ESW_REGEX_UNLOCK(unit);
   2886 
   2887     return (rv);
   2888 }
   2889 
   2890 /*
   2891  * Function:
   2892  *      _regex_policy_action_delete
   2893  * Purpose:
   2894  *      Delete action from a policy.
   2895  * Parameters:
   2896  *      unit   - (IN) BCM device number
   2897  *      policy - (IN) Policy entry id.
   2898  *      action - (IN) Action to remove (bcmFieldActionXXX)
   2899  *      param0 - (IN) Action parameter (use 0 if not required)
   2900  *      param1 - (IN) Action parameter (use 0 if not required)
   2901  * Returns:
   2902  *      BCM_E_XXX
   2903  * Notes:
   2904  */
   2905 int _regex_policy_action_delete(int unit, bcm_regex_policy_t policy,
   2906                                 bcm_field_action_t action,
   2907                                 uint32 param0, uint32 param1)
   2908 {
   2909     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   2910     _regex_policy_action_t       *pa      = NULL; /* Policy action descriptor. */
   2911     _regex_policy_action_t       *pa_prev = NULL;
   2912     _regex_policy_t              *p_ent; /* Field entry structure.       */
   2913     int                           rv;   /* Operation return status. */
   2914 
   2915     device = ESW_REGEX_INFO(unit);
   2916     if (NULL == device) {
   2917         return BCM_E_INIT;
   2918     }
   2919 
   2920     /* Get field entry descriptor. */
   2921     rv = _regex_policy_get(unit, policy, &p_ent);
   2922     if (BCM_FAILURE(rv)) {
   2923         return (rv);
   2924     }
   2925 
   2926     /* Special treatment for pre-historic actions. */
   2927     switch (action) {
   2928         case  bcmFieldActionColorIndependent:
   2929             p_ent->flags |= _REGEX_POLICY_DIRTY;
   2930             p_ent->flags &= ~_REGEX_POLICY_COLOR_INDEPENDENT;
   2931             return (BCM_E_NONE);
   2932         default:
   2933             break;
   2934     }
   2935 
   2936     ESW_REGEX_LOCK(unit);
   2937 
   2938     /* Find the action in the entry */
   2939     pa = p_ent->actions; /* start at head */
   2940 
   2941     while (pa != NULL) {
   2942         if (pa->action != action) {
   2943             pa_prev = pa;
   2944             pa      = pa->next;
   2945             continue;
   2946         }
   2947 
   2948         /* Some actions might be applied multiple times.*/
   2949         if (((action == bcmFieldActionMirrorIngress) ||
   2950              (action == bcmFieldActionMirrorEgress)) &&
   2951             (((uint32)_REGEX_INVALID_INDEX != param0) &&
   2952              ((uint32)_REGEX_INVALID_INDEX != param1)))  {
   2953             if ((pa->param[0] != param0)  || (pa->param[1] != param1)) {
   2954                 pa_prev = pa;
   2955                 pa      = pa->next;
   2956                 continue;
   2957             }
   2958         }
   2959         break;
   2960     }
   2961 
   2962     if (NULL == pa) {
   2963         ESW_REGEX_UNLOCK(unit);
   2964         return (BCM_E_NOT_FOUND);
   2965     }
   2966 
   2967     /* If entry is installed mark action as invalid.
   2968      * Invalid actions will be removed during entry remove/reinstall.
   2969      */
   2970     if (p_ent->flags & _REGEX_POLICY_INSTALLED) {
   2971         pa->flags  &= ~_REGEX_ACTION_VALID;
   2972         pa->flags |= _REGEX_ACTION_MODIFY;
   2973         p_ent->flags |= _REGEX_POLICY_DIRTY;
   2974         ESW_REGEX_UNLOCK(unit);
   2975         return (BCM_E_NONE);
   2976     }
   2977 
   2978     if (pa_prev != NULL) {
   2979         pa_prev->next = pa->next;
   2980     } else { /* matched head of list */
   2981         p_ent->actions = pa->next;
   2982     }
   2983 
   2984     /* okay to free action */
   2985     sal_free(pa);
   2986     pa = NULL;
   2987 
   2988     p_ent->flags |= _REGEX_POLICY_DIRTY;
   2989     ESW_REGEX_UNLOCK(unit);
   2990     return (BCM_E_NONE);
   2991 }
   2992 
   2993 /*
   2994  * Function:
   2995  *      bcm_esw_regex_policy_create
   2996  * Purpose:
   2997  *      Create a blank regex policy.
   2998  * Parameters:
   2999  *      unit   - (IN) Unit number.
   3000  *      flags  - (IN) REGEX_FLOW_xxx flags
   3001  *      policy - (OUT) ID of policy to be created.
   3002  * Returns:
   3003  *      BCM_E_xxx
   3004  * Notes:
   3005  */
   3006 int bcm_esw_regex_policy_create(int unit, int flags, bcm_regex_policy_t *policy)
   3007 {
   3008     _bcm_esw_regex_device_info_t  *device; /* Regex control structure. */
   3009 
   3010     if (!soc_feature(unit, soc_feature_regex)) {
   3011         return BCM_E_UNAVAIL;
   3012     }
   3013 
   3014     /* Get the device info structure. */
   3015     device = ESW_REGEX_INFO(unit);
   3016     if (NULL == device) {
   3017         return BCM_E_INIT;
   3018     }
   3019 
   3020     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3021         return BCM_E_PARAM;
   3022     }
   3023 
   3024     if (0 == (flags & BCM_REGEX_POLICY_WITH_ID))
   3025     {
   3026         /* Generate a policy ID. */
   3027         do {
   3028             last_allocated_policy++;
   3029             if (ESW_REGEX_POLICIES_LAST(unit) < last_allocated_policy) {
   3030                 last_allocated_policy = ESW_REGEX_POLICIES_LAST(unit);
   3031             }
   3032         } while (BCM_SUCCESS(_regex_policy_get(unit, last_allocated_policy, NULL)));
   3033 
   3034         *policy = last_allocated_policy;
   3035     }
   3036 
   3037     return _regex_policy_create_id(unit, *policy);
   3038 }
   3039 
   3040 /*
   3041  * Function:
   3042  *      bcm_esw_regex_policy_destroy
   3043  * Purpose:
   3044  *      Destroy a regex policy. This deallocates memory only.
   3045  * Parameters:
   3046  *      unit   - (IN) Unit number.
   3047  *      policy - (IN) ID of policy to be destroyed.
   3048  * Returns:
   3049  *      BCM_E_xxx
   3050  * Notes:
   3051  */
   3052 int bcm_esw_regex_policy_destroy(int unit, bcm_regex_policy_t policy)
   3053 {
   3054     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3055     _regex_policy_t              *p_ent; /* Allocated entry buffer.      */
   3056     int                           rv;
   3057 
   3058     if (!soc_feature(unit, soc_feature_regex)) {
   3059         return BCM_E_UNAVAIL;
   3060     }
   3061 
   3062     /* Get the device info structure. */
   3063     device = ESW_REGEX_INFO(unit);
   3064     if (NULL == device) {
   3065         return BCM_E_INIT;
   3066     }
   3067 
   3068     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3069         return BCM_E_PARAM;
   3070     }
   3071 
   3072     /* Cannot delete policy 0 since it is used by the flow tracker for new and unmatched
   3073      * sessions. */
   3074     if (_REGEX_DEFAULT_POLICY_ID == policy) {
   3075         return BCM_E_BUSY;
   3076     }
   3077 
   3078     rv = _regex_policy_get(unit, policy, &p_ent);
   3079     if (BCM_FAILURE(rv)) {
   3080         return (rv);
   3081     }
   3082 
   3083     ESW_REGEX_LOCK(unit);
   3084 
   3085     /* Remove policy from hw before destroying sw image. */
   3086     if (p_ent->flags & _REGEX_POLICY_INSTALLED) {
   3087         rv = bcm_esw_regex_policy_remove(unit, policy);
   3088         if (BCM_FAILURE(rv)) {
   3089             ESW_REGEX_UNLOCK(unit);
   3090             return(rv);
   3091         }
   3092     }
   3093 
   3094     /* Destroy policy policers */
   3095     rv = bcm_esw_regex_policy_policer_detach_all(unit, policy);
   3096     if (BCM_FAILURE(rv)) {
   3097         ESW_REGEX_UNLOCK(unit);
   3098         return(rv);
   3099     }
   3100 
   3101 #ifdef ESW_REGEX_STAT_SUPPORT
   3102     /* Destroy policy stats */
   3103     if (p_ent->statistic.flags & _REGEX_POLICY_STAT_VALID) {
   3104         rv = bcm_esw_regex_policy_stat_detach(unit, policy, p_ent->statistic.sid);
   3105         if (BCM_FAILURE(rv)) {
   3106             ESW_REGEX_UNLOCK(unit);
   3107             return(rv);
   3108         }
   3109     }
   3110 #endif
   3111 
   3112     /* Destroy entry sw images. */
   3113     rv = _regex_policy_phys_destroy(unit, p_ent);
   3114     if (BCM_FAILURE(rv)) {
   3115         ESW_REGEX_UNLOCK(unit);
   3116         return(rv);
   3117     }
   3118 
   3119 #ifdef BCM_WARM_BOOT_SUPPORT
   3120     SOC_CONTROL_LOCK(unit);
   3121     SOC_CONTROL(unit)->scache_dirty = 1;
   3122     SOC_CONTROL_UNLOCK(unit);
   3123 #endif
   3124 
   3125     ESW_REGEX_UNLOCK(unit);
   3126 
   3127     return (BCM_E_NONE);
   3128 }
   3129 
   3130 /*
   3131  * Function:
   3132  *      bcm_esw_regex_policy_destroy_all
   3133  * Purpose:
   3134  *      Destroy all regex policy entries.
   3135  * Parameters:
   3136  *      unit - (IN) Unit number.
   3137  * Returns:
   3138  *      BCM_E_xxx
   3139  * Notes:
   3140  */
   3141 int bcm_esw_regex_policy_destroy_all(int unit)
   3142 {
   3143     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3144     int                           idx;
   3145     int                           rv;
   3146 
   3147     if (!soc_feature(unit, soc_feature_regex)) {
   3148         return BCM_E_UNAVAIL;
   3149     }
   3150 
   3151     /* Get the device info structure. */
   3152     device = ESW_REGEX_INFO(unit);
   3153     if (NULL == device) {
   3154         return BCM_E_INIT;
   3155     }
   3156 
   3157     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3158         return BCM_E_PARAM;
   3159     }
   3160 
   3161     LOG_DEBUG(BSL_LS_BCM_REGEX,
   3162               (BSL_META_U(unit,
   3163                           "FT(unit %d) vverb: %s()\n"),
   3164                unit, FUNCTION_NAME()));
   3165 
   3166     ESW_REGEX_LOCK(unit);
   3167 
   3168     /* Scan unit's groups freeing each entry list. */
   3169     for (idx = device->num_policies - 1; idx >= 0; idx--) {
   3170         /* Destroy all policies except the default policy. */
   3171         if (_REGEX_DEFAULT_POLICY_ID == device->policies[idx]->eid) {
   3172             continue;
   3173         }
   3174         rv =  bcm_esw_regex_policy_destroy(unit, (device->policies[idx])->eid);
   3175         if (BCM_FAILURE(rv)) {
   3176             ESW_REGEX_UNLOCK(unit);
   3177             return (rv);
   3178         }
   3179     }
   3180 
   3181     ESW_REGEX_UNLOCK(unit);
   3182 
   3183     return (BCM_E_NONE);
   3184 }
   3185 
   3186 /*
   3187  * Function:
   3188  *      bcm_esw_regex_policy_install
   3189  * Purpose:
   3190  *      Install a regex policy into the hardware tables.
   3191  * Parameters:
   3192  *      unit   - (IN) Unit number.
   3193  *      policy - (IN) ID of policy to be installed.
   3194  * Returns:
   3195  *      BCM_E_xxx
   3196  * Notes:
   3197  */
   3198 int bcm_esw_regex_policy_install(int unit, bcm_regex_policy_t policy)
   3199 {
   3200     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3201     _regex_policy_t              *p_ent; /* Allocated entry buffer.      */
   3202     int                           rv;
   3203     int                           dirty; /* Field entry dirty flag.  */
   3204 
   3205     if (!soc_feature(unit, soc_feature_regex)) {
   3206         return BCM_E_UNAVAIL;
   3207     }
   3208 
   3209     /* Get the device info structure. */
   3210     device = ESW_REGEX_INFO(unit);
   3211     if (NULL == device) {
   3212         return BCM_E_INIT;
   3213     }
   3214 
   3215     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3216         return BCM_E_PARAM;
   3217     }
   3218 
   3219     LOG_DEBUG(BSL_LS_BCM_REGEX,
   3220               (BSL_META_U(unit,
   3221                           "FT(unit %d) vverb: %s()\n"),
   3222                unit, FUNCTION_NAME()));
   3223 
   3224     ESW_REGEX_LOCK(unit);
   3225 
   3226     rv = _regex_policy_get(unit, policy, &p_ent);
   3227     if (BCM_FAILURE(rv)) {
   3228         ESW_REGEX_UNLOCK(unit);
   3229         return rv;
   3230     }
   3231 
   3232     rv = _regex_policy_dirty(unit, p_ent, &dirty);
   3233     if (BCM_FAILURE(rv)) {
   3234         ESW_REGEX_UNLOCK(unit);
   3235         return (rv);
   3236     }
   3237 
   3238     /* Write the Policy entry */
   3239     if (dirty) {
   3240         rv = _regex_policy_install(unit, policy);
   3241     } else {
   3242         rv = BCM_E_NONE;
   3243     }
   3244 
   3245 #ifdef BCM_WARM_BOOT_SUPPORT
   3246     SOC_CONTROL_LOCK(unit);
   3247     SOC_CONTROL(unit)->scache_dirty = 1;
   3248     SOC_CONTROL_UNLOCK(unit);
   3249 #endif
   3250 
   3251     ESW_REGEX_UNLOCK(unit);
   3252     return rv;
   3253 }
   3254 
   3255 /*
   3256  * Function:
   3257  *      bcm_esw_regex_policy_remove
   3258  * Purpose:
   3259  *      Remove a regex policy from the hardware tables.
   3260  * Parameters:
   3261  *      unit   - (IN) Unit number.
   3262  *      policy - (IN) ID of policy to be removed.
   3263  * Returns:
   3264  *      BCM_E_xxx
   3265  * Notes:
   3266  */
   3267 int bcm_esw_regex_policy_remove(int unit, bcm_regex_policy_t policy)
   3268 {
   3269     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3270     int                 rv;          /* Operation return status. */
   3271 
   3272     if (!soc_feature(unit, soc_feature_regex)) {
   3273         return BCM_E_UNAVAIL;
   3274     }
   3275 
   3276     /* Get the device info structure. */
   3277     device = ESW_REGEX_INFO(unit);
   3278     if (NULL == device) {
   3279         return BCM_E_INIT;
   3280     }
   3281 
   3282     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3283         return BCM_E_PARAM;
   3284     }
   3285 
   3286     LOG_DEBUG(BSL_LS_BCM_REGEX,
   3287               (BSL_META_U(unit,
   3288                           "FT(unit %d) vverb: %s()\n"),
   3289                unit, FUNCTION_NAME()));
   3290 
   3291     ESW_REGEX_LOCK(unit);
   3292 
   3293     rv =  _regex_policy_remove(unit, policy);
   3294 
   3295 #ifdef BCM_WARM_BOOT_SUPPORT
   3296     SOC_CONTROL_LOCK(unit);
   3297     SOC_CONTROL(unit)->scache_dirty = 1;
   3298     SOC_CONTROL_UNLOCK(unit);
   3299 #endif
   3300 
   3301     ESW_REGEX_UNLOCK(unit);
   3302     return (rv);
   3303 }
   3304 
   3305 /*
   3306  * Function:
   3307  *      bcm_esw_regex_policy_action_add
   3308  * Purpose:
   3309  *      Add an action to a regex policy.
   3310  * Parameters:
   3311  *      unit   - (IN) Unit number.
   3312  *      policy - (IN) ID of policy to be modified.
   3313  *      action - (IN) Field processor action value
   3314  *      param0 - (IN) Action-dependent value; 0 if not used
   3315  *      param1 - (IN) Action-dependent value; 0 if not used
   3316  * Returns:
   3317  *      BCM_E_xxx
   3318  * Notes:
   3319  */
   3320 int bcm_esw_regex_policy_action_add(int unit, bcm_regex_policy_t policy,
   3321                                     bcm_field_action_t action, uint32 param0, uint32 param1)
   3322 {
   3323     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3324     _regex_policy_action_t       *pa = NULL; /* Policy action descriptor. */
   3325     int                           rv;
   3326 
   3327     if (!soc_feature(unit, soc_feature_regex)) {
   3328         return BCM_E_UNAVAIL;
   3329     }
   3330 
   3331     /* Get the device info structure. */
   3332     device = ESW_REGEX_INFO(unit);
   3333     if (NULL == device) {
   3334         return BCM_E_INIT;
   3335     }
   3336 
   3337     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3338         return BCM_E_PARAM;
   3339     }
   3340 
   3341     LOG_DEBUG(BSL_LS_BCM_REGEX,
   3342               (BSL_META_U(unit,
   3343                           "FT(unit %d) vverb: %s(policy=%d, action=%s, p0=%d, p1=%d)\n"),
   3344                unit, FUNCTION_NAME(), policy,
   3345                _regex_policy_action_name(action), param0, param1));
   3346 
   3347     if ((SOC_PORT_ADDR_MAX(unit) > 31) &&
   3348         ((action == bcmFieldActionRedirectPbmp)   ||
   3349          (action == bcmFieldActionEgressMask)     ||
   3350          (action == bcmFieldActionEgressPortsAdd) ||
   3351          (action == bcmFieldActionRedirectBcastPbmp))) {
   3352         LOG_ERROR(BSL_LS_BCM_REGEX,
   3353                   (BSL_META_U(unit,
   3354                               "FT(unit %d) Error: Use bcm_regex_policy_action_ports_add api.\n"),
   3355                    unit));
   3356         return (BCM_E_PARAM);
   3357     }
   3358 
   3359     /* Adapt action parameters */
   3360     rv = _regex_policy_params_api_to_hw_adapt(unit, action, &param0, &param1);
   3361     BCM_IF_ERROR_RETURN(rv);
   3362 
   3363     ESW_REGEX_LOCK(unit);
   3364 
   3365     /*
   3366      * Allocate the action descriptor, param2 and param3 are not valid here.
   3367      */
   3368     rv = _regex_policy_action_alloc(unit, action, param0, param1, 0, 0, &pa);
   3369     if (BCM_FAILURE(rv)) {
   3370         LOG_ERROR(BSL_LS_BCM_REGEX,
   3371                   (BSL_META_U(unit,
   3372                               "FT(unit %d) Error: failure in _regex_policy_action_alloc()\n"),
   3373                    unit));
   3374         ESW_REGEX_UNLOCK(unit);
   3375         return rv;
   3376     }
   3377 
   3378     /*
   3379      * Add action to entry actions list.
   3380      */
   3381     rv = _regex_policy_action_add(unit, policy, pa);
   3382     ESW_REGEX_UNLOCK(unit);
   3383     if (BCM_FAILURE(rv)) {
   3384         sal_free(pa);
   3385         return rv;
   3386     }
   3387     return (BCM_E_NONE);
   3388 }
   3389 
   3390 /*
   3391  * Function:
   3392  *      bcm_esw_regex_policy_action_mac_add
   3393  * Purpose:
   3394  *      Add an action to a policy.
   3395  * Parameters:
   3396  *      unit   - (IN) Unit number.
   3397  *      policy - (IN) Regex policy Id.
   3398  *      action - (IN) Field action value
   3399  *      mac    - (IN) MAC address for actions involving src/dst MAC.
   3400  * Returns:
   3401  *      BCM_E_xxx
   3402  * Notes:
   3403  */
   3404 int bcm_esw_regex_policy_action_mac_add(int unit,
   3405                                         bcm_regex_policy_t policy,
   3406                                         bcm_field_action_t action,
   3407                                         bcm_mac_t mac)
   3408 {
   3409     uint32 param[_FT_ACTION_PARAM_SZ];
   3410 
   3411     if (!soc_feature(unit, soc_feature_regex)) {
   3412         return BCM_E_UNAVAIL;
   3413     }
   3414 
   3415     if ((action != bcmFieldActionSrcMacNew) &&
   3416         (action != bcmFieldActionDstMacNew)) {
   3417         return (BCM_E_PARAM);
   3418     }
   3419 
   3420     SAL_MAC_ADDR_TO_UINT32(mac, param);
   3421 
   3422     return bcm_esw_regex_policy_action_add(unit, policy, action,
   3423                                            param[0],param[1]);
   3424 }
   3425 
   3426 /*
   3427  * Function:
   3428  *      bcm_esw_regex_policy_action_ports_add
   3429  * Purpose:
   3430  *      Add an action to a regex policy.
   3431  * Parameters:
   3432  *      unit   - (IN) Unit number.
   3433  *      policy - (IN) regex policy ID
   3434  *      action - (IN) Field action value
   3435  *      pbmp   - (IN) pbmp for actions involving port bitmap
   3436  * Returns:
   3437  *      BCM_E_xxx
   3438  * Notes:
   3439  */
   3440 int bcm_esw_regex_policy_action_ports_add(int unit,
   3441                                           bcm_regex_policy_t policy,
   3442                                           bcm_field_action_t action,
   3443                                           bcm_pbmp_t pbmp)
   3444 {
   3445     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3446     uint32 param[_FT_ACTION_PARAM_SZ];
   3447 
   3448     if (!soc_feature(unit, soc_feature_regex)) {
   3449         return BCM_E_UNAVAIL;
   3450     }
   3451 
   3452     /* Get the device info structure. */
   3453     device = ESW_REGEX_INFO(unit);
   3454     if (NULL == device) {
   3455         return BCM_E_INIT;
   3456     }
   3457 
   3458     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3459         return BCM_E_PARAM;
   3460     }
   3461 
   3462     if ((action != bcmFieldActionRedirectPbmp) &&
   3463         (action != bcmFieldActionEgressMask) &&
   3464         (action != bcmFieldActionEgressPortsAdd) &&
   3465         (action != bcmFieldActionRedirectBcastPbmp)) {
   3466         LOG_ERROR(BSL_LS_BCM_REGEX,
   3467                   (BSL_META_U(unit,
   3468                               "FT(unit %d) Error: Incorrect action parameter\n"),
   3469                    unit));
   3470         return (BCM_E_PARAM);
   3471     }
   3472 
   3473     sal_memset(&param, 0, sizeof(param));
   3474 
   3475     param[0] = SOC_PBMP_WORD_GET(pbmp, 0);
   3476     if (soc_feature(unit, soc_feature_table_hi)) {
   3477         param[1] = SOC_PBMP_WORD_GET(pbmp, 1);
   3478         /* Trident device can support more than 64-ports */
   3479         if (SOC_IS_TD_TT(unit)) {
   3480             param[2] = SOC_PBMP_WORD_GET(pbmp, 2);
   3481         }
   3482         /* Trident2 device can support more than 96-ports */
   3483         if (SOC_IS_TD2_TT2(unit)) {
   3484             param[3] = SOC_PBMP_WORD_GET(pbmp, 3);
   3485             param[3] &= 0x3ff; /* TD2 has 106 ports */
   3486         }
   3487     }
   3488 
   3489     return _regex_policy_action_ports_add(unit, policy, action,
   3490                                           param[0], param[1],
   3491                                           param[2], param[3]);
   3492 }
   3493 
   3494 /*
   3495  * Function:
   3496  *      bcm_esw_regex_policy_action_delete
   3497  * Purpose:
   3498  *      Delete an action from a regex policy.
   3499  * Parameters:
   3500  *      unit   - (IN) Unit number.
   3501  *      policy - (IN) ID of policy to be modified.
   3502  *      action - (IN) Field processor action value
   3503  *      param0 - (IN) Action-dependent value; 0 if not used
   3504  *      param1 - (IN) Action-dependent value; 0 if not used
   3505  * Returns:
   3506  *      BCM_E_xxx
   3507  * Notes:
   3508  */
   3509 int bcm_esw_regex_policy_action_delete(int unit,
   3510                                        bcm_regex_policy_t policy,
   3511                                        bcm_field_action_t action,
   3512                                        uint32 param0,
   3513                                        uint32 param1)
   3514 {
   3515     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3516     int                           rv;   /* Operation return status. */
   3517 
   3518     if (!soc_feature(unit, soc_feature_regex)) {
   3519         return BCM_E_UNAVAIL;
   3520     }
   3521 
   3522     if (action < 0 || bcmFieldActionCount <= action) {
   3523         LOG_ERROR(BSL_LS_BCM_REGEX,
   3524                   (BSL_META_U(unit,
   3525                               "FT(unit %d) Error: unknown action=%d\n"),
   3526                    unit, action));
   3527         return (BCM_E_PARAM);
   3528     }
   3529 
   3530     /* Get the device info structure. */
   3531     device = ESW_REGEX_INFO(unit);
   3532     if (NULL == device) {
   3533         return BCM_E_INIT;
   3534     }
   3535 
   3536     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3537         return BCM_E_PARAM;
   3538     }
   3539 
   3540     /* Adapt action parameters */
   3541     rv = _regex_policy_params_api_to_hw_adapt(unit, action, &param0, &param1);
   3542     BCM_IF_ERROR_RETURN(rv);
   3543 
   3544     ESW_REGEX_LOCK(unit);
   3545 
   3546     rv = _regex_policy_action_delete(unit, policy, action, param0, param1);
   3547 
   3548     ESW_REGEX_UNLOCK(unit);
   3549     return rv;
   3550 }
   3551 
   3552 /*
   3553  * Function:
   3554  *      bcm_esw_regex_policy_action_get
   3555  * Purpose:
   3556  *      Retrieve the parameters for an action previously added to a
   3557  *      regex policy.
   3558  * Parameters:
   3559  *      unit   - (IN) Unit number.
   3560  *      policy - (IN) regex policy ID.
   3561  *      action - (IN) Field processor action value
   3562  *      param0 - (OUT) Action-dependent value
   3563  *      param1 - (OUT) Action-dependent value
   3564  * Returns:
   3565  *      BCM_E_xxx
   3566  * Notes:
   3567  */
   3568 int bcm_esw_regex_policy_action_get(int unit,
   3569                                     bcm_regex_policy_t policy,
   3570                                     bcm_field_action_t action,
   3571                                     uint32 *param0,
   3572                                     uint32 *param1)
   3573 {
   3574     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3575     _regex_policy_t              *p_ent; /* Allocated entry buffer.      */
   3576     _regex_policy_action_t       *pa = NULL; /* Policy action descriptor. */
   3577     int                           rv;
   3578 
   3579     if (!soc_feature(unit, soc_feature_regex)) {
   3580         return BCM_E_UNAVAIL;
   3581     }
   3582 
   3583     /* Input parameters check. */
   3584     if ((NULL == param0) || (NULL == param1)) {
   3585         return (BCM_E_PARAM);
   3586     }
   3587 
   3588     /* Get the device info structure. */
   3589     device = ESW_REGEX_INFO(unit);
   3590     if (NULL == device) {
   3591         return BCM_E_INIT;
   3592     }
   3593 
   3594     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3595         return BCM_E_PARAM;
   3596     }
   3597 
   3598     /* Lock the module. */
   3599     ESW_REGEX_LOCK(unit);
   3600 
   3601     rv = _regex_policy_get(unit, policy, &p_ent);
   3602     if (BCM_FAILURE(rv)) {
   3603         ESW_REGEX_UNLOCK(unit);
   3604         return (rv);
   3605     }
   3606 
   3607     if (bcmFieldActionColorIndependent == action) {
   3608         *param0 = (p_ent->flags & _REGEX_POLICY_COLOR_INDEPENDENT) ? 1 : 0;
   3609         *param1 = 0;
   3610         /* Unlock the module. */
   3611         ESW_REGEX_UNLOCK(unit);
   3612         return (BCM_E_NONE);
   3613     }
   3614 
   3615     /* Find matching action in the entry */
   3616     for (pa = p_ent->actions; pa != NULL; pa = pa->next) {
   3617         if (pa->action == action) {
   3618             break;
   3619         }
   3620     }
   3621 
   3622     if (pa == NULL) {
   3623         ESW_REGEX_UNLOCK(unit);
   3624         LOG_DEBUG(BSL_LS_BCM_REGEX,
   3625                   (BSL_META_U(unit,
   3626                               "FT(unit %d) Error: action not in policy=%d\n"),
   3627                    unit, policy));
   3628         return (BCM_E_NOT_FOUND);
   3629     }
   3630 
   3631     *param0 = pa->param[0];
   3632     *param1 = pa->param[1];
   3633 
   3634     /* Unlock the module. */
   3635     ESW_REGEX_UNLOCK(unit);
   3636 
   3637     /* Adapt action parameters */
   3638     rv = _regex_policy_params_hw_to_api_adapt(unit, action, param0, param1);
   3639     return (rv);
   3640 }
   3641 
   3642 /*
   3643  * Function:
   3644  *      bcm_esw_regex_policy_action_mac_get
   3645  * Purpose:
   3646  *      Retrieve the parameters for an action previously added to a
   3647  *      regex policy.
   3648  * Parameters:
   3649  *      unit   - (IN) Unit number.
   3650  *      policy - (IN) Regex policy ID.
   3651  *      action - (IN) Field action value.
   3652  *      mac    - (OUT) MAC address for actions involving src/dst MAC.
   3653  * Returns:
   3654  *      BCM_E_xxx
   3655  * Notes:
   3656  */
   3657 int bcm_esw_regex_policy_action_mac_get(int unit,
   3658                                         bcm_regex_policy_t policy,
   3659                                         bcm_field_action_t action,
   3660                                         bcm_mac_t *mac)
   3661 {
   3662     uint32 param[_FT_ACTION_PARAM_SZ];
   3663     int    rv;
   3664 
   3665     if (!soc_feature(unit, soc_feature_regex)) {
   3666         return BCM_E_UNAVAIL;
   3667     }
   3668 
   3669     /* Input parameter check. */
   3670     if (NULL == mac) {
   3671         return (BCM_E_PARAM);
   3672     }
   3673 
   3674     if ((action != bcmFieldActionSrcMacNew) &&
   3675         (action != bcmFieldActionDstMacNew)) {
   3676         return (BCM_E_PARAM);
   3677     }
   3678 
   3679     /* Extract action information from field entry. */
   3680     rv = bcm_esw_regex_policy_action_get(unit, policy, action,
   3681                                          param, param + 1);
   3682     BCM_IF_ERROR_RETURN(rv);
   3683 
   3684     SAL_MAC_ADDR_FROM_UINT32((*mac), param);
   3685     return (BCM_E_NONE);
   3686 }
   3687 
   3688 /*
   3689  * Function:
   3690  *      bcm_esw_regex_policy_action_ports_get
   3691  * Purpose:
   3692  *      Retrieve the parameters for an action previously added to a
   3693  *      regex policy.
   3694  * Parameters:
   3695  *      unit   - (IN) Unit number.
   3696  *      policy - (IN) Regex policy ID
   3697  *      action - (IN) Field action value
   3698  *      pbmp   - (OUT) pbmp for actions involving port bitmap
   3699  * Returns:
   3700  *      BCM_E_xxx
   3701  * Notes:
   3702  */
   3703 int bcm_esw_regex_policy_action_ports_get(int unit,
   3704                                           bcm_regex_policy_t policy,
   3705                                           bcm_field_action_t action,
   3706                                           bcm_pbmp_t *pbmp)
   3707 {
   3708     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3709     uint32 param[_FT_ACTION_PARAM_SZ];
   3710     int    rv;
   3711 
   3712     if (!soc_feature(unit, soc_feature_regex)) {
   3713         return BCM_E_UNAVAIL;
   3714     }
   3715 
   3716     /* Get the device info structure. */
   3717     device = ESW_REGEX_INFO(unit);
   3718     if (NULL == device) {
   3719         return BCM_E_INIT;
   3720     }
   3721 
   3722     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3723         return BCM_E_PARAM;
   3724     }
   3725 
   3726     /* Input parameter check. */
   3727     if (NULL == pbmp) {
   3728         return (BCM_E_PARAM);
   3729     }
   3730 
   3731     if ((action != bcmFieldActionRedirectPbmp) &&
   3732         (action != bcmFieldActionEgressMask) &&
   3733         (action != bcmFieldActionRedirectBcastPbmp) &&
   3734         (action != bcmFieldActionEgressPortsAdd)) {
   3735         return (BCM_E_PARAM);
   3736     }
   3737 
   3738     sal_memset(param, 0, sizeof(param));
   3739 
   3740     /* Extract action information from policy entry. */
   3741     rv = _regex_policy_action_ports_get(unit, policy, action,
   3742                                         param, param + 1, param + 2, param + 3);
   3743     BCM_IF_ERROR_RETURN(rv);
   3744 
   3745     BCM_PBMP_CLEAR(*pbmp);
   3746     SOC_PBMP_WORD_SET(*pbmp, 0, param[0]);
   3747 
   3748 #if defined(BCM_TRIUMPH_SUPPORT)
   3749     if (soc_feature(unit, soc_feature_table_hi)) {
   3750         SOC_PBMP_WORD_SET(*pbmp, 1, param[1]);
   3751         if (SOC_IS_TD_TT(unit)) {
   3752             SOC_PBMP_WORD_SET(*pbmp, 2, param[2]);
   3753         }
   3754         if (SOC_IS_TD2_TT2(unit)) {
   3755             SOC_PBMP_WORD_SET(*pbmp, 3, param[3]);
   3756         }
   3757     }
   3758 #endif /* BCM_TRIUMPH_SUPPORT */
   3759     return (BCM_E_NONE);
   3760 }
   3761 
   3762 /*
   3763  * Function:
   3764  *      bcm_esw_regex_policy_action_remove
   3765  * Purpose:
   3766  *      Remove an action from a regex_policy.  Same as
   3767  *      bcm_esw_regex_policy_action_delete for actions without parameters.
   3768  * Parameters:
   3769  *      unit   - (IN) Unit number.
   3770  *      policy - (IN) ID of policy to be modified.
   3771  *      action - (IN) Field processor action value
   3772  * Returns:
   3773  *      BCM_E_xxx
   3774  * Notes:
   3775  */
   3776 int bcm_esw_regex_policy_action_remove(int unit,
   3777                                        bcm_regex_policy_t policy,
   3778                                        bcm_field_action_t action)
   3779 {
   3780     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3781     int                           rv;   /* Operation return status. */
   3782 
   3783     if (!soc_feature(unit, soc_feature_regex)) {
   3784         return BCM_E_UNAVAIL;
   3785     }
   3786 
   3787     /* Get the device info structure. */
   3788     device = ESW_REGEX_INFO(unit);
   3789     if (NULL == device) {
   3790         return BCM_E_INIT;
   3791     }
   3792 
   3793     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3794         return BCM_E_PARAM;
   3795     }
   3796 
   3797     /* Lock the module. */
   3798     ESW_REGEX_LOCK(unit);
   3799 
   3800     rv = bcm_esw_regex_policy_action_delete(unit, policy, action,
   3801                                             (uint32)_REGEX_INVALID_INDEX,
   3802                                             (uint32)_REGEX_INVALID_INDEX);
   3803     ESW_REGEX_UNLOCK(unit);
   3804     return (rv);
   3805 }
   3806 
   3807 /*
   3808  * Function:
   3809  *      bcm_esw_regex_policy_action_remove_all
   3810  * Purpose:
   3811  *      Remove all actions from a regex_policy.
   3812  * Parameters:
   3813  *      unit   - (IN) Unit number.
   3814  *      policy - (IN) ID of policy to be modified.
   3815  * Returns:
   3816  *      BCM_E_xxx
   3817  * Notes:
   3818  */
   3819 int bcm_esw_regex_policy_action_remove_all(int unit,
   3820                                            bcm_regex_policy_t policy)
   3821 {
   3822     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3823     _regex_policy_t              *p_ent; /* Allocated entry buffer.      */
   3824     _regex_policy_action_t       *pa = NULL; /* Policy action descriptor. */
   3825     int                           rv;   /* Operation return status.  */
   3826 
   3827     if (!soc_feature(unit, soc_feature_regex)) {
   3828         return BCM_E_UNAVAIL;
   3829     }
   3830 
   3831     /* Get the device info structure. */
   3832     device = ESW_REGEX_INFO(unit);
   3833     if (NULL == device) {
   3834         return BCM_E_INIT;
   3835     }
   3836 
   3837     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   3838         return BCM_E_PARAM;
   3839     }
   3840 
   3841     /* Lock the module. */
   3842     ESW_REGEX_LOCK(unit);
   3843 
   3844     rv = _regex_policy_get(unit, policy, &p_ent);
   3845     if (BCM_FAILURE(rv)) {
   3846         ESW_REGEX_UNLOCK(unit);
   3847         return (rv);
   3848     }
   3849 
   3850     /* start at the head of the actions list and burn them up */
   3851     pa = p_ent->actions;
   3852 
   3853     while (pa != NULL) {
   3854         rv = _regex_policy_action_delete(unit, policy, pa->action,
   3855                                          pa->param[0], pa->param[1]);
   3856         if (BCM_FAILURE(rv)) {
   3857             ESW_REGEX_UNLOCK(unit);
   3858             return (rv);
   3859         }
   3860 
   3861         /*
   3862          * Action might be removed from the entry actions
   3863          * list only if entry was not installed.
   3864          * Otherwise clean up will happen during reinstall.
   3865          */
   3866         pa = (p_ent->flags & _REGEX_POLICY_INSTALLED) ? pa->next : p_ent->actions;
   3867     }
   3868 
   3869     p_ent->flags |= _REGEX_POLICY_DIRTY;
   3870 
   3871     ESW_REGEX_UNLOCK(unit);
   3872     return (rv);
   3873 }
   3874 
   3875 /*
   3876  * Function:
   3877  *     _bcm_regex_policer_get
   3878  * Purpose:
   3879  *     Lookup a Policer description structure by policer id.
   3880  * Parmeters:
   3881  *     unit      - (IN)BCM device number.
   3882  *     pid       - (IN)Policer id.
   3883  *     policer_p - (OUT) Policer lookup result.
   3884  * Returns:
   3885  *     BCM_E_XXX
   3886  */
   3887 int _bcm_regex_policer_get(int unit, bcm_policer_t pid,
   3888                            _field_policer_t **policer_p)
   3889 {
   3890     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   3891     _field_policer_t             *f_pl;   /* Policer lookup pointer.  */
   3892 
   3893     /* Input parameters check. */
   3894     if (NULL == policer_p) {
   3895         return (BCM_E_PARAM);
   3896     }
   3897 
   3898     /* Get the device info structure. */
   3899     device = ESW_REGEX_INFO(unit);
   3900     if (NULL == device) {
   3901         return BCM_E_INIT;
   3902     }
   3903 
   3904     f_pl  =  device->policers[_REGEX_POLICER_ID_TO_INDEX(pid)];
   3905     if (NULL != f_pl) {
   3906         *policer_p = f_pl;
   3907         return (BCM_E_NONE);
   3908     }
   3909 
   3910     /* Policer with pid == pid was not found. */
   3911     return (BCM_E_NOT_FOUND);
   3912 }
   3913 
   3914 /*
   3915  * Function:
   3916  *      _bcm_esw_regex_policer_destroy
   3917  * Purpose:
   3918  *      Destroy a policer entry.
   3919  * Parameters:
   3920  *      unit - (IN) Unit number.
   3921  *      policer_id - (IN) Policer ID.
   3922  * Returns:
   3923  *      BCM_E_XXX
   3924  * Notes:
   3925  */
   3926 int _regex_policer_destroy(int unit, bcm_policer_t pid)
   3927 {
   3928     _bcm_esw_regex_device_info_t *device; /* Regex control structure.     */
   3929     _field_policer_t             *f_pl;   /* Internal policer descriptor. */
   3930     int                           rv;     /* Operation return status.     */
   3931 
   3932     /* Get the device info structure. */
   3933     device = ESW_REGEX_INFO(unit);
   3934     if (NULL == device) {
   3935         return BCM_E_INIT;
   3936     }
   3937 
   3938     /* Find policer info. */
   3939     rv = _bcm_regex_policer_get(unit, pid, &f_pl);
   3940     if (BCM_FAILURE(rv)) {
   3941         return (rv);
   3942     }
   3943 
   3944     /* Reject destroy if policer is in use. */
   3945     if (f_pl->sw_ref_count > 1) {
   3946         return (BCM_E_BUSY);
   3947     }
   3948 
   3949     /* Remove policer from policers table. */
   3950     device->policers[_REGEX_POLICER_ID_TO_INDEX(pid)] = NULL;
   3951 
   3952     /* De-allocate policer descriptor. */
   3953     sal_free(f_pl);
   3954 
   3955     return (BCM_E_NONE);
   3956 }
   3957 
   3958 /*
   3959  * Function:
   3960  *      _regex_policer_id_alloc
   3961  * Purpose:
   3962  *      Allocate a policer id.
   3963  * Parameters:
   3964  *      unit    - (IN) BCM device number.
   3965  *      pid     - (OUT) Policer id.
   3966  * Returns:
   3967  *      BCM_E_XXX
   3968  * Notes:
   3969  */
   3970 int _regex_policer_id_alloc(int unit, bcm_policer_t *pid)
   3971 {
   3972     _bcm_esw_regex_device_info_t *device; /* Regex control structure.     */
   3973     int                           i;
   3974 
   3975     /* Get the device info structure. */
   3976     device = ESW_REGEX_INFO(unit);
   3977     if (NULL == device) {
   3978         return BCM_E_INIT;
   3979     }
   3980     /* Input parameters check. */
   3981     if (NULL == pid) {
   3982         return (BCM_E_PARAM);
   3983     }
   3984 
   3985     for (i = 0; i < _REGEX_POLICER_MAX_NUM; i++) {
   3986         if (NULL == device->policers[i]) {
   3987             *pid = _REGEX_POLICER_ID_ENCODE(unit, i);
   3988             return BCM_E_NONE;
   3989         }
   3990     }
   3991     return (BCM_E_RESOURCE);
   3992 }
   3993 
   3994 /*
   3995  * Function:
   3996  *      _bcm_esw_regex_policer_create
   3997  * Purpose:
   3998  *      Initialize a policer entry.
   3999  * Parameters:
   4000  *      unit    - (IN) BCM device number.
   4001  *      pol_cfg - (IN) Policer configuration.
   4002  *      pid     - (OUT) Policer id.
   4003  * Returns:
   4004  *      BCM_E_XXX
   4005  * Notes:
   4006  */
   4007 int _bcm_esw_regex_policer_create(int unit, bcm_policer_config_t *pol_cfg,
   4008                                   bcm_policer_t *pid)
   4009 {
   4010     _bcm_esw_regex_device_info_t *device;      /* Regex control structure.     */
   4011     _field_policer_t             *f_pl = NULL; /* Internal policer descriptor. */
   4012     int                           rv;          /* Operation return status.     */
   4013 
   4014     if (!soc_feature(unit, soc_feature_regex)) {
   4015         return BCM_E_UNAVAIL;
   4016     }
   4017 
   4018     /* Get the device info structure. */
   4019     device = ESW_REGEX_INFO(unit);
   4020     if (NULL == device) {
   4021         return BCM_E_INIT;
   4022     }
   4023 
   4024     /* Input parameters check. */
   4025     if (NULL == pol_cfg) {
   4026         return (BCM_E_PARAM);
   4027     }
   4028 
   4029     /* Lock the module. */
   4030     ESW_REGEX_LOCK(unit);
   4031 
   4032     /* Generate policer id. */
   4033     if (0 == (pol_cfg->flags & BCM_POLICER_WITH_ID)) {
   4034         rv = _regex_policer_id_alloc(unit, pid);
   4035         if (BCM_FAILURE(rv)) {
   4036             ESW_REGEX_UNLOCK(unit);
   4037             return rv;
   4038         }
   4039     } else {
   4040         /* Check if policer id is already in use. */
   4041         rv = _bcm_regex_policer_get(unit, *pid, &f_pl);
   4042         if (BCM_SUCCESS(rv)) {
   4043 
   4044             /* Verify that replace flag is set. */
   4045             if (0 == (pol_cfg->flags & BCM_POLICER_REPLACE)) {
   4046                 ESW_REGEX_UNLOCK(unit);
   4047                 return (BCM_E_EXISTS);
   4048             }
   4049 
   4050             /* Make sure policer is not attached to any entry. */
   4051             if (1 != f_pl->sw_ref_count) {
   4052                 ESW_REGEX_UNLOCK(unit);
   4053                 return (BCM_E_BUSY);
   4054             }
   4055             /* Copy new configuration. */
   4056             sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(f_pl->cfg));
   4057 
   4058             /* Set policer "dirty" flag and return. */
   4059             rv = _regex_policer_hw_flags_set(unit, f_pl, 0);
   4060             ESW_REGEX_UNLOCK(unit);
   4061             return (rv);
   4062         }
   4063     }
   4064 
   4065     /* Allocate policer descriptor. */
   4066     f_pl = sal_alloc(sizeof(*f_pl), "Regex policer");
   4067     if (NULL == f_pl) {
   4068         ESW_REGEX_UNLOCK(unit);
   4069         return (BCM_E_MEMORY);
   4070     }
   4071 
   4072     /* Copy policer configuration. */
   4073     sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(f_pl->cfg));
   4074 
   4075     /* Set policer "dirty" flags. */
   4076     rv = _regex_policer_hw_flags_set(unit, f_pl, 0);
   4077     if (BCM_FAILURE(rv)) {
   4078         sal_free(f_pl);
   4079         ESW_REGEX_UNLOCK(unit);
   4080         return (rv);
   4081     }
   4082 
   4083     /* Initialize reference count to 1. */
   4084     f_pl->sw_ref_count = 1;
   4085 
   4086     /* Set hw index to - no hw resources allocated. */
   4087     f_pl->hw_index = _FP_INVALID_INDEX;
   4088 
   4089     /* Initialize policer id. */
   4090     f_pl->pid = *pid;
   4091 
   4092     /* Insert policer into policers table. */
   4093     device->policers[_REGEX_POLICER_ID_TO_INDEX(*pid)] = f_pl;
   4094 
   4095     ESW_REGEX_UNLOCK(unit);
   4096     return (BCM_E_NONE);
   4097 }
   4098 
   4099 /*
   4100  * Function:
   4101  *      _bcm_esw_regex_policer_destroy
   4102  * Purpose:
   4103  *      Destroy a policer entry.
   4104  * Parameters:
   4105  *      unit - (IN) Unit number.
   4106  *      policer_id - (IN) Policer ID.
   4107  * Returns:
   4108  *      BCM_E_XXX
   4109  * Notes:
   4110  */
   4111 int _bcm_esw_regex_policer_destroy(int unit, bcm_policer_t pid)
   4112 {
   4113     _bcm_esw_regex_device_info_t *device; /* Regex control structure.     */
   4114     int                           rv = BCM_E_NONE; /* Operation return status. */
   4115 
   4116     if (!soc_feature(unit, soc_feature_regex)) {
   4117         return BCM_E_UNAVAIL;
   4118     }
   4119 
   4120     /* Get the device info structure. */
   4121     device = ESW_REGEX_INFO(unit);
   4122     if (NULL == device) {
   4123         return BCM_E_INIT;
   4124     }
   4125 
   4126     /* Lock the module. */
   4127     ESW_REGEX_LOCK(unit);
   4128 
   4129     /* Destroy policer. */
   4130     rv = _regex_policer_destroy(unit, pid);
   4131 
   4132     ESW_REGEX_UNLOCK(unit);
   4133 
   4134     return rv;
   4135 }
   4136 
   4137 /*
   4138  * Function:
   4139  *      bcm_policer_destroy_all
   4140  * Purpose:
   4141  *      Destroy all policer entries.
   4142  * Parameters:
   4143  *      unit - (IN) Unit number.
   4144  * Returns:
   4145  *      BCM_E_XXX
   4146  * Notes:
   4147  */
   4148 int _bcm_esw_regex_policer_destroy_all(int unit)
   4149 {
   4150     _bcm_esw_regex_device_info_t *device; /* Regex control structure.     */
   4151     int                           rv = BCM_E_NONE; /* Operation return status. */
   4152     int                           idx;
   4153 
   4154     if (!soc_feature(unit, soc_feature_regex)) {
   4155         return BCM_E_UNAVAIL;
   4156     }
   4157 
   4158     /* Get the device info structure. */
   4159     device = ESW_REGEX_INFO(unit);
   4160     if (NULL == device) {
   4161         return BCM_E_INIT;
   4162     }
   4163 
   4164     /* Lock the module. */
   4165     ESW_REGEX_LOCK(unit);
   4166 
   4167     /* Iterate over all entries. */
   4168     for (idx = 0; idx < sizeof(device->policers)/sizeof(device->policers[0]); idx++) {
   4169         if (NULL != device->policers[idx]) {
   4170             rv = _regex_policer_destroy(unit, device->policers[idx]->pid);
   4171             if (BCM_FAILURE(rv)) {
   4172                 break;
   4173             }
   4174         }
   4175     }
   4176 
   4177     ESW_REGEX_UNLOCK(unit);
   4178 
   4179     return (rv);
   4180 }
   4181 
   4182 /*
   4183  * Function:
   4184  *      bcm_policer_traverse
   4185  * Purpose:
   4186  *      Traverse all existing policer entries and call supplied
   4187  *      callback function.
   4188  * Parameters:
   4189  *      unit - (IN) Unit number.
   4190  *      cb - (IN) Callback function.
   4191  *      user_data - (IN) User data.
   4192  * Returns:
   4193  *      BCM_E_XXX
   4194  * Notes:
   4195  *     To speed up traverse operation - no hw read is perfomed.
   4196  */
   4197 int _bcm_esw_regex_policer_traverse(int unit, bcm_policer_traverse_cb cb,
   4198                                     void *user_data)
   4199 {
   4200     _bcm_esw_regex_device_info_t *device;          /* Regex control structure. */
   4201     bcm_policer_config_t          cfg;             /* Policer configuration.   */
   4202     int                           rv = BCM_E_NONE; /* Operation return status. */
   4203     int                           idx;
   4204 
   4205     if (!soc_feature(unit, soc_feature_regex)) {
   4206         return BCM_E_UNAVAIL;
   4207     }
   4208 
   4209     /* Get the device info structure. */
   4210     device = ESW_REGEX_INFO(unit);
   4211     if (NULL == device) {
   4212         return BCM_E_INIT;
   4213     }
   4214 
   4215     /* Lock the module. */
   4216     ESW_REGEX_LOCK(unit);
   4217 
   4218     /* Iterate over all entries. */
   4219     for (idx = 0; idx < sizeof(device->policers)/sizeof(device->policers[0]); idx++) {
   4220         if (NULL != device->policers[idx]) {
   4221             sal_memcpy(&cfg, &device->policers[idx]->cfg, sizeof(cfg));
   4222             rv = (*cb)(unit, device->policers[idx]->pid, &cfg, user_data);
   4223             if (BCM_FAILURE(rv)) {
   4224                 break;
   4225             }
   4226         }
   4227     }
   4228 
   4229     ESW_REGEX_UNLOCK(unit);
   4230 
   4231     return (rv);
   4232 }
   4233 
   4234 /*
   4235  * Function:
   4236  *      _regex_policy_policer_detach
   4237  * Purpose:
   4238  *      Detach a policer from a regex policy
   4239  * Parameters:
   4240  *      unit     - (IN) Unit number.
   4241  *      p_ent    - (IN) Regex policy structure.
   4242  *      level    - (IN) Policer level.
   4243  * Returns:
   4244  *      BCM_E_XXX
   4245  * Notes:
   4246  */
   4247 STATIC int _regex_policy_policer_detach(int unit, _regex_policy_t *p_ent, int level)
   4248 {
   4249     _field_policer_t       *f_pl;    /* Internal policer descriptor.  */
   4250     _field_entry_policer_t *f_ent_pl;/* Field entry policer structure.*/
   4251 
   4252     /* Make sure policer attached to the entry. */
   4253     f_ent_pl = p_ent->policer + level;
   4254     if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   4255         return (BCM_E_EMPTY);
   4256     }
   4257 
   4258     /* Get policer description structure. */
   4259     BCM_IF_ERROR_RETURN(_bcm_regex_policer_get(unit, f_ent_pl->pid, &f_pl));
   4260 
   4261     /* If entry was installed decrement hw reference counter. */
   4262     BCM_IF_ERROR_RETURN(_regex_policer_hw_free(unit, level, p_ent));
   4263 
   4264     /* Decrement policer reference counter. */
   4265     f_pl->sw_ref_count--;
   4266 
   4267     /* If no one else is using the policer and
   4268      * policer is internal destroy it.
   4269      */
   4270     if ((1 == f_pl->sw_ref_count) && (f_pl->hw_flags & _FP_POLICER_INTERNAL)) {
   4271         BCM_IF_ERROR_RETURN(_bcm_esw_regex_policer_destroy(unit, f_ent_pl->pid));
   4272     }
   4273 
   4274     /* Detach policer from an entry. */
   4275     f_ent_pl->pid   = _FP_INVALID_INDEX;
   4276     f_ent_pl->flags = 0;
   4277 
   4278     /* Mark entry for reinstall. */
   4279     p_ent->flags |= _FP_ENTRY_DIRTY;
   4280 
   4281     return (BCM_E_NONE);
   4282 }
   4283 
   4284 /*
   4285  * Function:
   4286  *      bcm_esw_regex_policy_policer_attach
   4287  * Purpose:
   4288  *      Attach a policer to a regex policy.
   4289  * Parameters:
   4290  *      unit       - (IN) Unit number.
   4291  *      policy     - (IN) Regex policy ID.
   4292  *      level      - (IN) Policer level.
   4293  *      policer_id - (IN) Policer ID.
   4294  * Returns:
   4295  *      BCM_E_xxx
   4296  * Notes:
   4297  */
   4298 int bcm_esw_regex_policy_policer_attach(int unit,
   4299                                         bcm_regex_policy_t policy,
   4300                                         int level,
   4301                                         bcm_policer_t policer_id)
   4302 {
   4303     _bcm_esw_regex_device_info_t *device;   /* Regex control structure.      */
   4304     _regex_policy_t              *p_ent;    /* Allocated entry buffer.       */
   4305     _field_entry_policer_t       *f_ent_pl; /* Field entry policer structure.*/
   4306     _field_policer_t             *f_pl;     /* Internal policer descriptor.  */
   4307     int                           idx;      /* Entry policers iterator.      */
   4308     int                           rv;       /* Operation return status.      */
   4309 
   4310     if (!soc_feature(unit, soc_feature_regex)) {
   4311         return BCM_E_UNAVAIL;
   4312     }
   4313 
   4314     /* Input parameters check. */
   4315     if ((level >= _REGEX_POLICER_LEVEL_COUNT) || (level < 0)) {
   4316         return (BCM_E_PARAM);
   4317     }
   4318 
   4319     if (!BCM_POLICER_IS_REGEX_METER(policer_id)) {
   4320         return (BCM_E_PARAM);
   4321     }
   4322 
   4323     /* Get the device info structure. */
   4324     device = ESW_REGEX_INFO(unit);
   4325     if (NULL == device) {
   4326         return BCM_E_INIT;
   4327     }
   4328 
   4329     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   4330         return BCM_E_PARAM;
   4331     }
   4332 
   4333     /* Lock the module. */
   4334     ESW_REGEX_LOCK(unit);
   4335 
   4336     /* Get policy description structure. */
   4337     rv = _regex_policy_get(unit, policy, &p_ent);
   4338     if (BCM_FAILURE(rv)) {
   4339         ESW_REGEX_UNLOCK(unit);
   4340         return (rv);
   4341     }
   4342 
   4343     /* Check if another policer already attached at this level. */
   4344     f_ent_pl = p_ent->policer + level;
   4345     if (f_ent_pl->flags & _FP_POLICER_VALID) {
   4346         ESW_REGEX_UNLOCK(unit);
   4347         return (BCM_E_EXISTS);
   4348     }
   4349 
   4350     /* Check if policer already attached to the entry. */
   4351     for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) {
   4352         f_ent_pl = p_ent->policer + idx;
   4353         if (f_ent_pl->pid == policer_id) {
   4354             ESW_REGEX_UNLOCK(unit);
   4355             return (idx == level) ? (BCM_E_NONE) : (BCM_E_PARAM);
   4356         }
   4357     }
   4358 
   4359     /* Get policer description structure. */
   4360     rv = _bcm_regex_policer_get(unit, policer_id, &f_pl);
   4361     if (BCM_FAILURE(rv)) {
   4362         ESW_REGEX_UNLOCK(unit);
   4363         return (rv);
   4364     }
   4365 
   4366     /* Check that policer can be shared. */
   4367     if (f_pl->sw_ref_count > 1) {
   4368         /* Policer sharing is restricted to a single level. */
   4369         if (level != f_pl->level) {
   4370             ESW_REGEX_UNLOCK(unit);
   4371             return (BCM_E_PARAM);
   4372         }
   4373     }
   4374 
   4375     /* Increment policer reference counter. */
   4376     f_pl->sw_ref_count++;
   4377 
   4378     /* Set policer attachment level. */
   4379     f_pl->level = level;
   4380 
   4381     /* Attach policer to an entry. */
   4382     f_ent_pl = p_ent->policer + level;
   4383     f_ent_pl->flags |= _FP_POLICER_VALID;
   4384     f_ent_pl->pid    = policer_id;
   4385 
   4386     /* Entry must be reinstalled for policer to take effect. */
   4387     p_ent->flags  |= _REGEX_POLICY_DIRTY;
   4388 
   4389     ESW_REGEX_UNLOCK(unit);
   4390     return (BCM_E_NONE);
   4391 }
   4392 
   4393 /*
   4394  * Function:
   4395  *      bcm_esw_regex_policy_policer_detach
   4396  * Purpose:
   4397  *      Detach a policer from a regex policy.
   4398  * Parameters:
   4399  *      unit   - (IN) Unit number.
   4400  *      policy - (IN) Regex policy ID.
   4401  *      level  - (IN) Policer level.
   4402  * Returns:
   4403  *      BCM_E_xxx
   4404  * Notes:
   4405  */
   4406 int bcm_esw_regex_policy_policer_detach(int unit,
   4407                                         bcm_regex_policy_t policy,
   4408                                         int level)
   4409 {
   4410     _bcm_esw_regex_device_info_t *device;   /* Regex control structure.      */
   4411     _regex_policy_t              *p_ent;    /* Allocated entry buffer.       */
   4412     int                           rv;       /* Operation return status.      */
   4413 
   4414     if (!soc_feature(unit, soc_feature_regex)) {
   4415         return BCM_E_UNAVAIL;
   4416     }
   4417 
   4418     /* Input parameters check. */
   4419     if ((level >= _REGEX_POLICER_LEVEL_COUNT) || (level < 0)) {
   4420         return (BCM_E_PARAM);
   4421     }
   4422 
   4423     /* Get the device info structure. */
   4424     device = ESW_REGEX_INFO(unit);
   4425     if (NULL == device) {
   4426         return BCM_E_INIT;
   4427     }
   4428 
   4429     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   4430         return BCM_E_PARAM;
   4431     }
   4432 
   4433     /* Lock the module. */
   4434     ESW_REGEX_LOCK(unit);
   4435 
   4436     /* Get entry description structure. */
   4437     rv = _regex_policy_get(unit, policy, &p_ent);
   4438     if (BCM_FAILURE(rv)) {
   4439         ESW_REGEX_UNLOCK(unit);
   4440         return (rv);
   4441     }
   4442 
   4443     rv = _regex_policy_policer_detach(unit, p_ent, level);
   4444 
   4445     ESW_REGEX_UNLOCK(unit);
   4446     return (rv);
   4447 }
   4448 
   4449 /*
   4450  * Function:
   4451  *      bcm_esw_regex_policy_policer_detach_all
   4452  * Purpose:
   4453  *      Detach all policers from a regex policy.
   4454  * Parameters:
   4455  *      unit   - (IN) Unit number.
   4456  *      policy - (IN) Regex policy ID.
   4457  * Returns:
   4458  *      BCM_E_xxx
   4459  * Notes:
   4460  */
   4461 int bcm_esw_regex_policy_policer_detach_all(int unit,
   4462                                             bcm_regex_policy_t policy)
   4463 {
   4464     int       idx;                /* Entry policers iterator. */
   4465     int       rv = BCM_E_NONE;    /* Operation return status. */
   4466 
   4467     if (!soc_feature(unit, soc_feature_regex)) {
   4468         return BCM_E_UNAVAIL;
   4469     }
   4470 
   4471     /* Detach all the policers attached to an entry. */
   4472     for (idx = 0; idx < _REGEX_POLICER_LEVEL_COUNT; idx++) {
   4473         rv =  bcm_esw_regex_policy_policer_detach(unit, policy, idx);
   4474         if (BCM_E_EMPTY == rv) {
   4475             /* No policer at this level. */
   4476             rv = BCM_E_NONE;
   4477         } else if (BCM_FAILURE(rv)) {
   4478             break;
   4479         }
   4480     }
   4481     return (rv);
   4482 }
   4483 
   4484 /*
   4485  * Function:
   4486  *      bcm_esw_regex_policy_policer_get
   4487  * Purpose:
   4488  *      Get the policer(s) attached to a regex policy.
   4489  * Parameters:
   4490  *      unit       - (IN) Unit number.
   4491  *      policy     - (IN) Regex policy ID.
   4492  *      level      - (IN) Policer level.
   4493  *      policer_id - (OUT) Policer ID.
   4494  * Returns:
   4495  *      BCM_E_xxx
   4496  * Notes:
   4497  */
   4498 int bcm_esw_regex_policy_policer_get(int unit,
   4499                                      bcm_regex_policy_t policy,
   4500                                      int level,
   4501                                      bcm_policer_t *policer_id)
   4502 {
   4503     _bcm_esw_regex_device_info_t *device;   /* Regex control structure.      */
   4504     _field_entry_policer_t       *f_ent_pl; /* Field entry policer structure.*/
   4505     _regex_policy_t              *p_ent;    /* Regex policy structure.       */
   4506     int                           rv;       /* Operation return status.      */
   4507 
   4508     if (!soc_feature(unit, soc_feature_regex)) {
   4509         return BCM_E_UNAVAIL;
   4510     }
   4511 
   4512     /* Input parameters check. */
   4513     if ((level >= _REGEX_POLICER_LEVEL_COUNT) || (level < 0)) {
   4514         return (BCM_E_PARAM);
   4515     }
   4516 
   4517     if (NULL == policer_id) {
   4518         return (BCM_E_PARAM);
   4519     }
   4520 
   4521     /* Get the device info structure. */
   4522     device = ESW_REGEX_INFO(unit);
   4523     if (NULL == device) {
   4524         return BCM_E_INIT;
   4525     }
   4526 
   4527     if (0 == (device->flags & BCM_REGEX_USE_POLICY_ID)) {
   4528         return BCM_E_PARAM;
   4529     }
   4530 
   4531     /* Lock the module. */
   4532     ESW_REGEX_LOCK(unit);
   4533 
   4534     /* Get entry description structure. */
   4535     rv = _regex_policy_get(unit, policy, &p_ent);
   4536     if (BCM_FAILURE(rv)) {
   4537         ESW_REGEX_UNLOCK(unit);
   4538         return (rv);
   4539     }
   4540 
   4541     f_ent_pl = p_ent->policer + level;
   4542     /* Make sure policer attached to the entry. */
   4543     if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   4544         rv = (BCM_E_NOT_FOUND);
   4545     } else {
   4546         *policer_id = f_ent_pl->pid;
   4547     }
   4548 
   4549     ESW_REGEX_UNLOCK(unit);
   4550     return (rv);
   4551 }
   4552 
   4553 /*
   4554  * Function:
   4555  *      bcm_esw_regex_stat_create
   4556  * Purpose:
   4557  *      Create stat collection entity.
   4558  * Parameters:
   4559  *      unit     - (IN) Unit number.
   4560  *      flags    - (IN) REGEX_STAT_xxx flags
   4561  *      nstat    - (IN) Number of elements in stat_arr - counter types array.
   4562  *      stat_arr - (IN) Array of counters to be collected in statistics entity.
   4563  *      stat_id  - (OUT) Statistics entity ID.
   4564  * Returns:
   4565  *      BCM_E_xxx
   4566  * Notes:
   4567  */
   4568 int bcm_esw_regex_stat_create(int unit,
   4569                               int flags,
   4570                               int nstat,
   4571                               bcm_field_stat_t *stat_arr,
   4572                               int *stat_id)
   4573 {
   4574     if (!soc_feature(unit, soc_feature_regex)) {
   4575         return BCM_E_UNAVAIL;
   4576     }
   4577 
   4578 #ifdef UNFINISHED_DRIVER_CHECK
   4579 #error DRIVER UNFINISHED
   4580 #endif
   4581     return BCM_E_UNAVAIL;
   4582 }
   4583 
   4584 /*
   4585  * Function:
   4586  *      bcm_esw_regex_stat_destroy
   4587  * Purpose:
   4588  *      Create stat collection entity.
   4589  * Parameters:
   4590  *      unit    - (IN) Unit number.
   4591  *      stat_id - (IN) Statistics entity ID.
   4592  * Returns:
   4593  *      BCM_E_xxx
   4594  * Notes:
   4595  */
   4596 int bcm_esw_regex_stat_destroy(int unit,
   4597                                int stat_id)
   4598 {
   4599     if (!soc_feature(unit, soc_feature_regex)) {
   4600         return BCM_E_UNAVAIL;
   4601     }
   4602 
   4603 #ifdef UNFINISHED_DRIVER_CHECK
   4604 #error DRIVER UNFINISHED
   4605 #endif
   4606     return BCM_E_UNAVAIL;
   4607 }
   4608 
   4609 /*
   4610  * Function:
   4611  *      bcm_esw_regex_policy_stat_attach
   4612  * Purpose:
   4613  *      Attach statistics entity to Regex policy.
   4614  * Parameters:
   4615  *      unit    - (IN) Unit number.
   4616  *      policy  - (IN) Regex policy ID.
   4617  *      stat_id - (IN) Statistics entity ID.
   4618  * Returns:
   4619  *      BCM_E_xxx
   4620  * Notes:
   4621  */
   4622 int bcm_esw_regex_policy_stat_attach(int unit,
   4623                                      bcm_regex_policy_t policy,
   4624                                      int stat_id)
   4625 {
   4626     if (!soc_feature(unit, soc_feature_regex)) {
   4627         return BCM_E_UNAVAIL;
   4628     }
   4629 
   4630 #ifdef UNFINISHED_DRIVER_CHECK
   4631 #error DRIVER UNFINISHED
   4632 #endif
   4633     return BCM_E_UNAVAIL;
   4634 }
   4635 
   4636 /*
   4637  * Function:
   4638  *      bcm_esw_regex_policy_stat_detach
   4639  * Purpose:
   4640  *      Detach statistics entity from Regex policy.
   4641  * Parameters:
   4642  *      unit    - (IN) Unit number.
   4643  *      policy  - (IN) Regex policy ID.
   4644  *      stat_id - (IN) Statistics entity ID.
   4645  * Returns:
   4646  *      BCM_E_xxx
   4647  * Notes:
   4648  */
   4649 int bcm_esw_regex_policy_stat_detach(int unit,
   4650                                      bcm_regex_policy_t policy,
   4651                                      int stat_id)
   4652 {
   4653     if (!soc_feature(unit, soc_feature_regex)) {
   4654         return BCM_E_UNAVAIL;
   4655     }
   4656 
   4657 #ifdef UNFINISHED_DRIVER_CHECK
   4658 #error DRIVER UNFINISHED
   4659 #endif
   4660     return BCM_E_UNAVAIL;
   4661 }
   4662 
   4663 /*
   4664  * Function:
   4665  *      bcm_esw_regex_policy_stat_get
   4666  * Purpose:
   4667  *      Get 64 bit counter value for specific statistic type.
   4668  * Parameters:
   4669  *      unit    - (IN) Unit number.
   4670  *      policy  - (IN) Regex policy ID.
   4671  *      stat_id - (OUT) Statistics entity ID.
   4672  * Returns:
   4673  *      BCM_E_xxx
   4674  * Notes:
   4675  */
   4676 int bcm_esw_regex_policy_stat_get(int unit,
   4677                                   bcm_regex_policy_t policy,
   4678                                   int *stat_id)
   4679 {
   4680     if (!soc_feature(unit, soc_feature_regex)) {
   4681         return BCM_E_UNAVAIL;
   4682     }
   4683 
   4684 #ifdef UNFINISHED_DRIVER_CHECK
   4685 #error DRIVER UNFINISHED
   4686 #endif
   4687     return BCM_E_UNAVAIL;
   4688 }
   4689 
   4690 /*
   4691  * Function:
   4692  *      bcm_esw_regex_session_add
   4693  * Purpose:
   4694  *      Adds or updates a session entry.
   4695  * Parameters:
   4696  *      unit    - (IN) Unit number.
   4697  *      flags   - (IN) REGEX_SESSION_xxx flags.
   4698  *      key     - (IN) The session key.
   4699  *      session - (IN) The session data.
   4700  * Returns:
   4701  *      BCM_E_xxx
   4702  * Notes:
   4703  */
   4704 int bcm_esw_regex_session_add(int unit,
   4705                               int flags,
   4706                               bcm_regex_session_key_t *key,
   4707                               bcm_regex_session_t *session)
   4708 {
   4709     if (!soc_feature(unit, soc_feature_regex)) {
   4710         return BCM_E_UNAVAIL;
   4711     }
   4712 
   4713 #if defined(BCM_TRIUMPH3_SUPPORT)
   4714     if (SOC_IS_TRIUMPH3(unit)) {
   4715         return _bcm_tr3_regex_session_add(unit, flags, key, session);
   4716     }
   4717 #endif /* BCM_TRIUMPH3_SUPPORT */
   4718 
   4719     return BCM_E_UNAVAIL;
   4720 }
   4721 
   4722 /*
   4723  * Function:
   4724  *      bcm_esw_regex_session_policy_update
   4725  * Purpose:
   4726  *      Updates the policy_id field in an already existing session entry.
   4727  * Parameters:
   4728  *      unit       - (IN) Unit number.
   4729  *      flags      - (IN) REGEX_SESSION_xxx flags.
   4730  *      flow_index - (IN) The session index.
   4731  *      policy     - (IN) The session policy ID.
   4732  * Returns:
   4733  *      BCM_E_xxx
   4734  * Notes:
   4735  */
   4736 int bcm_esw_regex_session_policy_update(int unit, int flags, int flow_index,
   4737                                          bcm_regex_policy_t policy)
   4738 {
   4739     if (!soc_feature(unit, soc_feature_regex)) {
   4740         return BCM_E_UNAVAIL;
   4741     }
   4742 
   4743 #if defined(BCM_TRIUMPH3_SUPPORT)
   4744     if (SOC_IS_TRIUMPH3(unit)) {
   4745         return _bcm_tr3_regex_session_policy_update(unit, flags, flow_index, policy);
   4746     }
   4747 #endif /* BCM_TRIUMPH3_SUPPORT */
   4748 
   4749     return BCM_E_UNAVAIL;
   4750 }
   4751 
   4752 /*
   4753  * Function:
   4754  *      bcm_esw_regex_session_delete_all
   4755  * Purpose:
   4756  *      Deletes all entries from the regex session table.
   4757  * Parameters:
   4758  *      unit - (IN) Unit number.
   4759  * Returns:
   4760  *      BCM_E_xxx
   4761  * Notes:
   4762  */
   4763 int bcm_esw_regex_session_delete_all(int unit)
   4764 {
   4765     if (!soc_feature(unit, soc_feature_regex)) {
   4766         return BCM_E_UNAVAIL;
   4767     }
   4768 
   4769 #if defined(BCM_TRIUMPH3_SUPPORT)
   4770     if (SOC_IS_TRIUMPH3(unit)) {
   4771         return _bcm_tr3_regex_session_delete_all(unit);
   4772     }
   4773 #endif /* BCM_TRIUMPH3_SUPPORT */
   4774 
   4775     return BCM_E_UNAVAIL;
   4776 }
   4777 
   4778 /*
   4779  * Function:
   4780  *      bcm_esw_regex_session_delete
   4781  * Purpose:
   4782  *      Deletes an entry from the regex session table.
   4783  * Parameters:
   4784  *      unit - (IN) Unit number.
   4785  *      key  - (IN) The session key.
   4786  * Returns:
   4787  *      BCM_E_xxx
   4788  * Notes:
   4789  */
   4790 int bcm_esw_regex_session_delete(int unit,
   4791                                  bcm_regex_session_key_t *key)
   4792 {
   4793     if (!soc_feature(unit, soc_feature_regex)) {
   4794         return BCM_E_UNAVAIL;
   4795     }
   4796 
   4797 #if defined(BCM_TRIUMPH3_SUPPORT)
   4798     if (SOC_IS_TRIUMPH3(unit)) {
   4799         return _bcm_tr3_regex_session_delete(unit, key);
   4800     }
   4801 #endif /* BCM_TRIUMPH3_SUPPORT */
   4802 
   4803     return BCM_E_UNAVAIL;
   4804 }
   4805 
   4806 /*
   4807  * Function:
   4808  *      bcm_esw_regex_session_get
   4809  * Purpose:
   4810  *      Returns the session data (if any).
   4811  * Parameters:
   4812  *      unit    - (IN) Unit number.
   4813  *      flags   - (IN) REGEX_SESSION_xxx flags.
   4814  *      key     - (IN) The session key.
   4815  *      session - (OUT) The session data.
   4816  * Returns:
   4817  *      BCM_E_xxx
   4818  * Notes:
   4819  */
   4820 int bcm_esw_regex_session_get(int unit,
   4821                               int flags,
   4822                               bcm_regex_session_key_t *key,
   4823                               bcm_regex_session_t *session)
   4824 {
   4825     if (!soc_feature(unit, soc_feature_regex)) {
   4826         return BCM_E_UNAVAIL;
   4827     }
   4828 
   4829 #if defined(BCM_TRIUMPH3_SUPPORT)
   4830     if (SOC_IS_TRIUMPH3(unit)) {
   4831         return _bcm_tr3_regex_session_get(unit, flags, key, session);
   4832     }
   4833 #endif /* BCM_TRIUMPH3_SUPPORT */
   4834 
   4835     return BCM_E_UNAVAIL;
   4836 }
   4837 
   4838 /*
   4839  * Function:
   4840  *      bcm_esw_regex_session_traverse
   4841  * Purpose:
   4842  *      Traverse regex sessions.
   4843  * Parameters:
   4844  *      unit      - (IN) Unit number.
   4845  *      flags     - (IN) REGEX_SESSION_xxx flags.
   4846  *      cb        - (IN) A pointer to the callback function to call for each session
   4847  *      user_data - (IN) Pointer to user data to supply in the callback
   4848  * Returns:
   4849  *      BCM_E_xxx
   4850  * Notes:
   4851  */
   4852 int bcm_esw_regex_session_traverse(int unit,
   4853                                    int flags,
   4854                                    bcm_regex_session_traverse_cb cb,
   4855                                    void *user_data)
   4856 {
   4857     if (!soc_feature(unit, soc_feature_regex)) {
   4858         return BCM_E_UNAVAIL;
   4859     }
   4860 
   4861 #if defined(BCM_TRIUMPH3_SUPPORT)
   4862     if (SOC_IS_TRIUMPH3(unit)) {
   4863         return _bcm_tr3_regex_session_traverse(unit, flags, cb, user_data);
   4864     }
   4865 #endif /* BCM_TRIUMPH3_SUPPORT */
   4866 
   4867     return BCM_E_UNAVAIL;
   4868 }
   4869 
   4870 void _bcm_esw_policy_dump(int unit, bcm_regex_policy_t policy)
   4871 {
   4872     _regex_policy_t              *policy_ent; /* Regex policy structure.  */
   4873     _regex_policy_action_t       *pa;
   4874     _bcm_esw_regex_device_info_t *device;     /* Regex control structure. */
   4875     int policer_printed = 0;
   4876     int i;
   4877 
   4878     LOG_CLI((BSL_META_U(unit,
   4879                         "\n")));
   4880 
   4881     /* Get the device info structure. */
   4882     device = ESW_REGEX_INFO(unit);
   4883     if (NULL == device) {
   4884         LOG_CLI((BSL_META_U(unit,
   4885                             "Regex module not initialized.\n")));
   4886         return;
   4887     }
   4888 
   4889     /* List the global policy data */
   4890     LOG_CLI((BSL_META_U(unit,
   4891                         "Number of policies: %d\n"), device->num_policies));
   4892     LOG_CLI((BSL_META_U(unit,
   4893                         "Minimum index: %d\n"), device->policy_index_min));
   4894     LOG_CLI((BSL_META_U(unit,
   4895                         "Maximum index: %d\n"), device->policy_index_max));
   4896 
   4897     if (NULL == device->policies) {
   4898         LOG_CLI((BSL_META_U(unit,
   4899                             "No policies are created.\n")));
   4900         return;
   4901     }
   4902 
   4903     ESW_REGEX_LOCK(unit);
   4904 
   4905     if (_REGEX_INVALID_INDEX == policy) {
   4906         /* List all the policy IDs */
   4907         for (i = 0; i < device->num_policies; i++) {
   4908             LOG_CLI((BSL_META_U(unit,
   4909                                 "Policy %d\n"), device->policies[i]->eid));
   4910         }
   4911     } else {
   4912         /* List all the policy data */
   4913         if (BCM_SUCCESS(_regex_policy_get(unit, policy, &policy_ent))) {
   4914             LOG_CLI((BSL_META_U(unit,
   4915                                 "Policy %d, flags = 0x%x\n"), policy_ent->eid, policy_ent->flags));
   4916             LOG_CLI((BSL_META_U(unit,
   4917                                 "Actions:\n")));
   4918             pa = policy_ent->actions;
   4919             if (NULL == pa) {
   4920                 LOG_CLI((BSL_META_U(unit,
   4921                                     "None.\n")));
   4922             } else {
   4923                 do {
   4924                     LOG_CLI((BSL_META_U(unit,
   4925                                         "\t%s: %d, %d\n"), _regex_policy_action_name(pa->action), pa->param[0], pa->param[1]));
   4926                     pa = pa->next;
   4927                 } while (NULL != pa);
   4928                 if (policy_ent->statistic.sid != _REGEX_INVALID_INDEX) {
   4929                     LOG_CLI((BSL_META_U(unit,
   4930                                         "Statistic:\n")));
   4931                     LOG_CLI((BSL_META_U(unit,
   4932                                         "\tID %d (0x%x)\n"), policy_ent->statistic.sid, policy_ent->statistic.sid));
   4933                 }
   4934                 for (i = 0; i < _REGEX_POLICER_LEVEL_COUNT; i++) {
   4935                     if (policy_ent->policer[i].pid != _FP_INVALID_INDEX) {
   4936                         if (!policer_printed) {
   4937                             LOG_CLI((BSL_META_U(unit,
   4938                                                 "Policers:\n")));
   4939                             policer_printed = 1;
   4940                         }
   4941                         LOG_CLI((BSL_META_U(unit,
   4942                                             "\tID %d (0x%x)\n"), policy_ent->policer[i].pid, policy_ent->policer[i].pid));
   4943                     }
   4944                 }
   4945             }
   4946         } else {
   4947             LOG_CLI((BSL_META_U(unit,
   4948                                 "Policy not found.\n")));
   4949         }
   4950     }
   4951 
   4952     ESW_REGEX_UNLOCK(unit);
   4953 }
   4954 
   4955 void _bcm_esw_policer_dump(int unit, bcm_policer_t policer_id)
   4956 {
   4957     _bcm_esw_regex_device_info_t *device; /* Regex control structure. */
   4958     _field_policer_t             *f_pl;   /* Internal policer descriptor.  */
   4959     int                           i;
   4960     int                           count = 0;
   4961 
   4962     if (!soc_feature(unit, soc_feature_regex)) {
   4963         return;
   4964     }
   4965 
   4966     LOG_CLI((BSL_META_U(unit,
   4967                         "\n")));
   4968 
   4969     /* Get the device info structure. */
   4970     device = ESW_REGEX_INFO(unit);
   4971     if (NULL == device) {
   4972         LOG_CLI((BSL_META_U(unit,
   4973                             "Regex module not initialized.\n")));
   4974         return;
   4975     }
   4976 
   4977     /* List the global policy data */
   4978     LOG_CLI((BSL_META_U(unit,
   4979                         "Maximum number of policers: %zu\n"), sizeof(device->policers)/sizeof(device->policers[0])));
   4980 
   4981     /* Lock the module. */
   4982     ESW_REGEX_LOCK(unit);
   4983 
   4984     if (_REGEX_INVALID_INDEX == policer_id) {
   4985         /* Iterate over all entries. */
   4986         for (i = 0; i < sizeof(device->policers)/sizeof(device->policers[0]); i++) {
   4987             if (NULL != device->policers[i]) {
   4988                 LOG_CLI((BSL_META_U(unit,
   4989                                     "Policer %d (0x%x)\n"), device->policers[i]->pid, device->policers[i]->pid));
   4990                 count++;
   4991             }
   4992         }
   4993         LOG_CLI((BSL_META_U(unit,
   4994                             "Policers in use: %d\n"), count));
   4995     } else {
   4996         i = _REGEX_POLICER_ID_TO_INDEX(policer_id);
   4997         if ((NULL != device->policers[i]) &&
   4998             (device->policers[i]->pid == policer_id) &&
   4999             (BCM_SUCCESS(_bcm_regex_policer_get(unit, device->policers[i]->pid, &f_pl)))) {
   5000             LOG_CLI((BSL_META_U(unit,
   5001                                 "Policer %d (0x%x), flags = 0x%x\n"), f_pl->pid, f_pl->pid, f_pl->hw_flags));
   5002             LOG_CLI((BSL_META_U(unit,
   5003                                 "\tSW Ref Count = %d, HW Ref Count = %d\n"), f_pl->sw_ref_count, f_pl->hw_ref_count));
   5004             LOG_CLI((BSL_META_U(unit,
   5005                                 "\tLevel = %d, Pool Index = %d, HW Index = %d\n"), f_pl->level, f_pl->pool_index, f_pl->hw_index));
   5006         } else {
   5007             LOG_CLI((BSL_META_U(unit,
   5008                                 "Policer not found.\n")));
   5009         }
   5010     }
   5011 
   5012     ESW_REGEX_UNLOCK(unit);
   5013 }
   5014 #endif /* INCLUDE_REGEX */