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

mim.c (37514B)


      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  * All Rights Reserved.$
      7  *
      8  * Mac-in-Mac initializers
      9  */
     10 #ifdef INCLUDE_L3
     11 
     12 #include <sal/core/libc.h>
     13 
     14 #include <soc/defs.h>
     15 #include <soc/drv.h>
     16 #include <soc/mem.h>
     17 #include <soc/l2u.h>
     18 #include <soc/util.h>
     19 #include <soc/debug.h>
     20 #include <bcm/l2.h>
     21 #include <bcm/l3.h>
     22 #include <bcm/port.h>
     23 #include <bcm/error.h>
     24 #include <bcm/vlan.h>
     25 #include <bcm/rate.h>
     26 #include <bcm/ipmc.h>
     27 #include <bcm/mim.h>
     28 #include <bcm/stack.h>
     29 #include <bcm/topo.h>
     30 
     31 #include <bcm_int/esw/mbcm.h>
     32 #include <bcm_int/esw/l3.h>
     33 #include <bcm_int/esw/firebolt.h>
     34 #include <bcm_int/esw/flex_ctr.h>
     35 #if defined(BCM_TRIUMPH2_SUPPORT)
     36 #include <bcm_int/esw/triumph2.h>
     37 #endif /* BCM_TRIUMPH2_SUPPORT */
     38 #if defined(BCM_TRIUMPH3_SUPPORT)
     39 #include <bcm_int/esw/triumph3.h>
     40 #endif /* BCM_TRIUMPH3_SUPPORT*/
     41 #include <bcm_int/esw_dispatch.h>
     42 #include <bcm_int/esw/xgs3.h>
     43 #if defined(BCM_TRIDENT2_SUPPORT)
     44 #include <bcm_int/esw/trident2.h>
     45 #endif /* BCM_TRIDENT2_SUPPORT */
     46 
     47 /* Initialize the MIM module. */
     48 int 
     49 bcm_esw_mim_init(int unit)
     50 {
     51     int rv = BCM_E_UNAVAIL;
     52 
     53 #if defined(BCM_TRIUMPH2_SUPPORT)
     54     if (soc_feature(unit, soc_feature_mim)) {
     55         rv = bcm_tr2_mim_init(unit);
     56     }
     57 #endif
     58     return rv;
     59 }
     60 
     61 /* Detach the MIM module. */
     62 int 
     63 bcm_esw_mim_detach(int unit)
     64 {
     65     int rv = BCM_E_NONE;
     66 #if defined(BCM_TRIUMPH2_SUPPORT)
     67     if (soc_feature(unit, soc_feature_mim)) {
     68         rv = bcm_tr2_mim_detach(unit);
     69     }
     70 #endif
     71     return rv;
     72 }
     73 
     74 /* Create a VPN instance. */
     75 int 
     76 bcm_esw_mim_vpn_create(int unit, bcm_mim_vpn_config_t *info)
     77 {
     78     int rv = BCM_E_UNAVAIL;
     79 #if defined(BCM_TRIUMPH2_SUPPORT)
     80     if (soc_feature(unit, soc_feature_mim)) {
     81         rv = bcm_tr2_mim_vpn_create(unit, info);
     82     }
     83 #endif
     84     return rv;
     85 }
     86 
     87 /* Delete a VPN instance. */
     88 int 
     89 bcm_esw_mim_vpn_destroy(int unit, bcm_mim_vpn_t vpn)
     90 {
     91     int rv = BCM_E_UNAVAIL;
     92 #if defined(BCM_TRIUMPH2_SUPPORT)
     93     if (soc_feature(unit, soc_feature_mim)) {
     94         rv = bcm_tr2_mim_vpn_destroy(unit, vpn);
     95     }
     96 #endif
     97     return rv;
     98 }
     99 
    100 
    101 /* Delete all VPN instances. */
    102 int 
    103 bcm_esw_mim_vpn_destroy_all(int unit)
    104 {
    105     int rv = BCM_E_UNAVAIL;
    106 #if defined(BCM_TRIUMPH2_SUPPORT)
    107     if (soc_feature(unit, soc_feature_mim)) {
    108         rv = bcm_tr2_mim_vpn_destroy_all(unit);
    109     }
    110 #endif
    111     return rv;
    112 }
    113 
    114 /* Get a VPN instance by ID. */
    115 int 
    116 bcm_esw_mim_vpn_get(int unit, bcm_mim_vpn_t vpn, 
    117                     bcm_mim_vpn_config_t *info)
    118 {
    119     int rv = BCM_E_UNAVAIL;
    120 #if defined(BCM_TRIUMPH2_SUPPORT)
    121     if (soc_feature(unit, soc_feature_mim)) {
    122         rv = bcm_tr2_mim_vpn_get(unit, vpn, info);
    123     }
    124 #endif
    125     return rv;
    126 }
    127 
    128 /* bcm_mim_vpn_traverse */
    129 int 
    130 bcm_esw_mim_vpn_traverse(int unit, bcm_mim_vpn_traverse_cb cb, 
    131                          void *user_data)
    132 {
    133     int rv = BCM_E_UNAVAIL;
    134 #if defined(BCM_TRIUMPH2_SUPPORT)
    135     if (soc_feature(unit, soc_feature_mim)) {
    136         rv = bcm_tr2_mim_vpn_traverse(unit, cb, user_data);
    137     }
    138 #endif
    139     return rv;
    140 }
    141 
    142 /* bcm_mim_port_add */
    143 int 
    144 bcm_esw_mim_port_add(int unit, bcm_mim_vpn_t vpn, 
    145                      bcm_mim_port_t *mim_port)
    146 {
    147     int rv = BCM_E_UNAVAIL;
    148 #if defined(BCM_TRIUMPH2_SUPPORT)
    149     if (soc_feature(unit, soc_feature_mim)) {
    150         rv = bcm_tr2_mim_port_add(unit, vpn, mim_port);
    151     }
    152 #endif
    153     return rv;
    154 }
    155 
    156 /* bcm_mim_port_delete */
    157 int 
    158 bcm_esw_mim_port_delete(int unit, bcm_mim_vpn_t vpn, 
    159                     bcm_gport_t mim_port_id)
    160 {
    161     int rv = BCM_E_UNAVAIL;
    162 #if defined(BCM_TRIUMPH2_SUPPORT)
    163     if (soc_feature(unit, soc_feature_mim)) {
    164         rv = bcm_tr2_mim_port_delete(unit, vpn, mim_port_id);
    165     }
    166 #endif
    167     return rv;
    168 }
    169 
    170 /* bcm_mim_port_delete_all */
    171 int 
    172 bcm_esw_mim_port_delete_all(int unit, bcm_mim_vpn_t vpn)
    173 {
    174     int rv = BCM_E_UNAVAIL;
    175 #if defined(BCM_TRIUMPH2_SUPPORT)
    176     if (soc_feature(unit, soc_feature_mim)) {
    177         rv = bcm_tr2_mim_port_delete_all(unit, vpn);
    178     }
    179 #endif
    180     return rv;
    181 }
    182 
    183 /* bcm_mim_port_get */
    184 int 
    185 bcm_esw_mim_port_get(int unit, bcm_mim_vpn_t vpn, 
    186                      bcm_mim_port_t *mim_port)
    187 {
    188     int rv = BCM_E_UNAVAIL;
    189 #if defined(BCM_TRIUMPH2_SUPPORT)
    190     if (soc_feature(unit, soc_feature_mim)) {
    191         rv = bcm_tr2_mim_port_get(unit, vpn, mim_port);
    192     }
    193 #endif
    194     return rv;
    195 }
    196 
    197 /* bcm_mim_port_get_all */
    198 int 
    199 bcm_esw_mim_port_get_all(int unit, bcm_mim_vpn_t vpn, int port_max, 
    200                      bcm_mim_port_t *port_array, int *port_count)
    201 {
    202     int rv = BCM_E_UNAVAIL;
    203 #if defined(BCM_TRIUMPH2_SUPPORT)
    204     if (soc_feature(unit, soc_feature_mim)) {
    205         rv = bcm_tr2_mim_port_get_all(unit, vpn, port_max, port_array, 
    206                                       port_count);
    207     }
    208 #endif
    209     return rv;
    210 }
    211 #if defined(BCM_TRIUMPH3_SUPPORT)
    212 /*
    213  * Function:
    214  *      _bcm_esw_mim_lookup_id_stat_get_table_info
    215  * Description:
    216  *      Provides relevant flex table information(table-name,index with
    217  *      direction)  for given MiM I-SID entry.
    218  *
    219  * Parameters:
    220  *      unit             - (IN) unit number
    221  *      lookup_id        - (IN) I-SID value
    222  *      num_of_tables    - (OUT) Number of flex counter tables
    223  *      table_info       - (OUT) Flex counter tables information
    224  *
    225  * Return Value:
    226  *      BCM_E_XXX
    227  * Notes:
    228  */
    229 STATIC
    230 bcm_error_t _bcm_esw_mim_lookup_id_stat_get_table_info(
    231                    int                        unit,
    232                    int                        lookup_id,
    233                    uint32                     *num_of_tables,
    234                    bcm_stat_flex_table_info_t *table_info)
    235 {
    236     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit)
    237         || SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    238         return  _bcm_tr3_mim_lookup_id_stat_get_table_info( unit, 
    239                                 lookup_id, num_of_tables, table_info);
    240     } else {
    241         return BCM_E_UNAVAIL; 
    242     }
    243 }
    244 
    245 /*
    246  * Function:
    247  *      _bcm_esw_mim_vpn_stat_get_table_info
    248  * Description:
    249  *      Provides relevant flex table information(table-name,index with
    250  *      direction)  for given MiM VPN entry
    251  *
    252  * Parameters:
    253  *      unit             - (IN) unit number
    254  *      vpn              - (IN) MiM VPN
    255  *      num_of_tables    - (OUT) Number of flex counter tables
    256  *      table_info       - (OUT) Flex counter tables information
    257  *
    258  * Return Value:
    259  *      BCM_E_XXX
    260  * Notes:
    261  */
    262 STATIC
    263 bcm_error_t _bcm_esw_mim_vpn_stat_get_table_info(
    264                    int                        unit,
    265                    bcm_mim_vpn_t              vpn,
    266                    uint32                     *num_of_tables,
    267                    bcm_stat_flex_table_info_t *table_info)
    268 {
    269 
    270     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2X(unit)) {
    271         return  _bcm_tr3_mim_vpn_stat_get_table_info( unit, 
    272                                 vpn, num_of_tables, table_info);
    273     } else {
    274         return BCM_E_UNAVAIL; 
    275     }
    276 
    277    return BCM_E_UNAVAIL;
    278 }
    279 #endif
    280 
    281 /*
    282  * Function:
    283  *      bcm_esw_mim_lookup_id_stat_attach
    284  * Description:
    285  *      Attach counters entries to the given MiM I-SID entry
    286  *
    287  * Parameters:
    288  *      unit             - (IN) unit number
    289  *      lookup_id        - (IN) I-SID value 
    290  *      stat_counter_id  - (IN) Stat Counter ID.
    291  *
    292  * Return Value:
    293  *      BCM_E_XXX
    294  * Notes:
    295  */
    296 int bcm_esw_mim_lookup_id_stat_attach(
    297             int unit,
    298             int lookup_id,
    299             uint32 stat_counter_id)
    300 {
    301 #if defined(BCM_TRIUMPH3_SUPPORT)
    302     soc_mem_t                 table=0;
    303     bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress;
    304     uint32                    pool_number=0;
    305     uint32                    base_index=0;
    306     bcm_stat_flex_mode_t      offset_mode=0;
    307     bcm_stat_object_t         object=bcmStatObjectIngPort;
    308     bcm_stat_group_mode_t     group_mode= bcmStatGroupModeSingle;
    309     uint32                    count=0;
    310     uint32                     actual_num_tables=0;
    311     uint32                     num_of_tables=0;
    312     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    313 
    314     _bcm_esw_stat_get_counter_id_info(
    315                   unit, stat_counter_id,
    316                   &group_mode,&object,&offset_mode,&pool_number,&base_index);
    317     
    318     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction));
    319     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode));
    320 
    321     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
    322                         unit,object,1,&actual_num_tables,&table,&direction));
    323     BCM_IF_ERROR_RETURN(_bcm_esw_mim_lookup_id_stat_get_table_info(
    324                    unit, lookup_id,&num_of_tables,&table_info[0]));
    325     for (count=0; count < num_of_tables ; count++) {
    326          if ((table_info[count].direction == direction) &&
    327              (table_info[count].table == table)) {
    328              if (direction == bcmStatFlexDirectionIngress) {
    329                  return _bcm_esw_stat_flex_attach_ingress_table_counters(
    330                         unit,
    331                         table_info[count].table,
    332                         table_info[count].index,
    333                         offset_mode,
    334                         base_index,
    335                         pool_number);
    336              } else {
    337                  return _bcm_esw_stat_flex_attach_egress_table_counters(
    338                         unit,
    339                         table_info[count].table,
    340                         table_info[count].index,
    341                         0,
    342                         offset_mode,
    343                         base_index,
    344                         pool_number);
    345              }
    346          }
    347     }
    348     return BCM_E_NOT_FOUND;
    349 #else
    350     return BCM_E_UNAVAIL;
    351 #endif
    352 }
    353 /*
    354  * Function:
    355  *      bcm_esw_mim_lookup_id_stat_detach
    356  * Description:
    357  *      Detach counters entries to the given MiM I-SID entry
    358  *
    359  * Parameters:
    360  *      unit             - (IN) unit number
    361  *      lookup_id        - (IN) I-SID value 
    362  *
    363  * Return Value:
    364  *      BCM_E_XXX
    365  * Notes:
    366  */
    367 int bcm_esw_mim_lookup_id_stat_detach(
    368             int unit,
    369             int lookup_id)
    370 {
    371 #if defined(BCM_TRIUMPH3_SUPPORT)
    372     uint32                     count=0;
    373     uint32                     num_of_tables=0;
    374     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    375     bcm_error_t                rv = BCM_E_NONE;
    376     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
    377 
    378     BCM_IF_ERROR_RETURN(_bcm_esw_mim_lookup_id_stat_get_table_info(
    379                    unit, lookup_id,&num_of_tables,&table_info[0]));
    380 
    381     for (count=0; count < num_of_tables ; count++) {
    382         if (table_info[count].direction == bcmStatFlexDirectionIngress) {
    383             rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
    384                          unit,
    385                          table_info[count].table,
    386                          table_info[count].index);
    387             if (BCM_E_NONE != rv &&
    388                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
    389                 err_code[bcmStatFlexDirectionIngress] = rv;
    390             }
    391         } else {
    392             rv = _bcm_esw_stat_flex_detach_egress_table_counters(
    393                           unit, 0,
    394                           table_info[count].table,
    395                           table_info[count].index);
    396             if (BCM_E_NONE != rv &&
    397                 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) {
    398                 err_code[bcmStatFlexDirectionEgress] = rv;
    399             }
    400         }
    401     }
    402 
    403     BCM_STAT_FLEX_DETACH_RETURN(err_code)
    404 #else
    405     return BCM_E_UNAVAIL;
    406 #endif
    407 }
    408 
    409 /*
    410  * Function:
    411  *      _bcm_esw_mim_lookup_id_stat_counter_get
    412  * Description:
    413  *  	Get counter statistic values for specific MiM I-SID entry
    414  *      if sync_mode is set, sync the sw accumulated count
    415  *      with hw count value first, else return sw count.  
    416  *
    417  * Parameters:
    418  *      unit             - (IN) unit number
    419  *      sync_mode        - (IN) hwcount is to be synced to sw count 
    420  *      lookup_id        - (IN) I-SID value 
    421  *      stat             - (IN) Type of the counter to retrieve
    422  *                              I.e. ingress/egress byte/packet)
    423  *      num_entries      - (IN) Number of counter Entries
    424  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    425  *      counter_values   - (OUT) Pointer to counter values
    426  *
    427  * Return Value:
    428  *      BCM_E_XXX
    429  * Notes:
    430  */
    431 bcm_error_t 
    432  _bcm_esw_mim_lookup_id_stat_counter_get(int unit,
    433                                         int sync_mode,
    434                                         int lookup_id,
    435                                         bcm_mim_stat_t stat,
    436                                         uint32 num_entries,
    437                                         uint32 *counter_indexes,
    438                                         bcm_stat_value_t *counter_values)
    439 {
    440 #if defined(BCM_TRIUMPH3_SUPPORT)
    441     uint32                          table_count=0;
    442     uint32                          index_count=0;
    443     uint32                          num_of_tables=0;
    444     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
    445     uint32                          byte_flag=0;
    446     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    447 
    448     if ((stat == bcmMimStatIngressPackets) ||
    449         (stat == bcmMimStatIngressBytes)) {
    450          direction = bcmStatFlexDirectionIngress;
    451     } else {
    452          direction = bcmStatFlexDirectionEgress; 
    453     }
    454     if ((stat == bcmMimStatIngressPackets) ||
    455         (stat == bcmMimStatEgressPackets)) {
    456         byte_flag=0;
    457     } else {
    458         byte_flag=1;
    459     }
    460 
    461     BCM_IF_ERROR_RETURN(_bcm_esw_mim_lookup_id_stat_get_table_info(
    462                    unit, lookup_id,&num_of_tables,&table_info[0]));
    463 
    464     for (table_count=0; table_count < num_of_tables ; table_count++) {
    465       if (table_info[table_count].direction == direction) {
    466           for (index_count=0; index_count < num_entries ; index_count++) {
    467                /*ctr_offset_info.offset_index = counter_indexes[index_count];*/
    468             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
    469                          unit, sync_mode,
    470                          table_info[table_count].index,
    471                          table_info[table_count].table,
    472                          0,
    473                          byte_flag,
    474                          counter_indexes[index_count],
    475                          &counter_values[index_count]));
    476           }
    477       }
    478     }
    479     return BCM_E_NONE;
    480 #else
    481     return BCM_E_UNAVAIL;
    482 #endif
    483 }
    484 
    485 #ifdef BCM_WARM_BOOT_SUPPORT
    486 /*
    487  * Function:
    488  *      _bcm_esw_mim_sync
    489  *
    490  * Purpose:
    491  *      Record MIM module persistent info for Level 2 Warm Boot
    492  *
    493  * Warm Boot Version Map:
    494  *  WB_VERSION_1_0
    495  *
    496  * Parameters:
    497  *      unit - (IN) Device Unit Number.
    498  *
    499  * Returns:
    500  *      BCM_E_XXX
    501  */
    502 int
    503 _bcm_esw_mim_sync(int unit)
    504 {
    505 #ifdef BCM_TRIUMPH2_SUPPORT
    506     if (soc_feature(unit, soc_feature_mim)) {
    507         return bcm_tr2_mim_sync(unit);
    508     }
    509 #endif /* BCM_TRIUMPH2_SUPPORT */
    510 
    511     return BCM_E_NONE;
    512 }
    513 #endif /* BCM_WARM_BOOT_SUPPORT */
    514 
    515 /*
    516  * Function:
    517  *      bcm_esw_mim_lookup_id_stat_counter_get
    518  * Description:
    519  *  	Get counter statistic values for specific MiM I-SID entry
    520  *
    521  * Parameters:
    522  *      unit             - (IN) unit number
    523  *      lookup_id        - (IN) I-SID value 
    524  *      stat             - (IN) Type of the counter to retrieve
    525  *                              I.e. ingress/egress byte/packet)
    526  *      num_entries      - (IN) Number of counter Entries
    527  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    528  *      counter_values   - (OUT) Pointer to counter values
    529  *
    530  * Return Value:
    531  *      BCM_E_XXX
    532  * Notes:
    533  */
    534 int 
    535 bcm_esw_mim_lookup_id_stat_counter_get(int unit,
    536                                        int lookup_id,
    537                                        bcm_mim_stat_t stat,
    538                                        uint32 num_entries,
    539                                        uint32 *counter_indexes,
    540                                        bcm_stat_value_t *counter_values)
    541 {
    542     return _bcm_esw_mim_lookup_id_stat_counter_get(unit, 0, lookup_id, stat,
    543                                                    num_entries, 
    544                                                    counter_indexes, 
    545                                                    counter_values);
    546 }
    547 
    548 /*
    549  * Function:
    550  *      bcm_esw_mim_lookup_id_stat_counter_sync_get
    551  * Description:
    552  *      Get counter statistic values for specific MiM VPN entry
    553  *      sw accumulated counters synced with hw count.
    554  *
    555  * Parameters:
    556  *      unit             - (IN) unit number
    557  *      lookup_id        - (IN) I-SID value 
    558  *      stat             - (IN) Type of the counter to retrieve
    559  *                              I.e. ingress/egress byte/packet)
    560  *      num_entries      - (IN) Number of counter Entries
    561  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    562  *      counter_values   - (OUT) Pointer to counter values
    563  *
    564  * Return Value:
    565  *      BCM_E_XXX
    566  * Notes:
    567  */
    568 int 
    569 bcm_esw_mim_lookup_id_stat_counter_sync_get(int unit,
    570                                            int lookup_id,
    571                                            bcm_mim_stat_t stat,
    572                                            uint32 num_entries,
    573                                            uint32 *counter_indexes,
    574                                            bcm_stat_value_t *counter_values)
    575 {
    576     return _bcm_esw_mim_lookup_id_stat_counter_get(unit, 1, lookup_id, stat,
    577                                                    num_entries, 
    578                                                    counter_indexes, 
    579                                                    counter_values);
    580 }
    581 /*
    582  * Function:
    583  *      bcm_esw_mim_lookup_id_stat_counter_set
    584  * Description:
    585  *  	Set counter statistic values for specific MiM I-SID entry
    586  *
    587  * Parameters:
    588  *      unit             - (IN) unit number
    589  *      lookup_id        - (IN) I-SID value 
    590  *      stat             - (IN) Type of the counter to retrieve
    591  *                              I.e. ingress/egress byte/packet)
    592  *      num_entries      - (IN) Number of counter Entries
    593  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    594  *      counter_values   - (IN) Pointer to counter values
    595  *
    596  * Return Value:
    597  *      BCM_E_XXX
    598  * Notes:
    599  */
    600 int bcm_esw_mim_lookup_id_stat_counter_set(
    601             int unit,
    602             int lookup_id,
    603             bcm_mim_stat_t stat,
    604             uint32 num_entries,
    605             uint32 *counter_indexes,
    606             bcm_stat_value_t *counter_values)
    607 {
    608 #if defined(BCM_TRIUMPH3_SUPPORT)
    609     uint32                          table_count=0;
    610     uint32                          index_count=0;
    611     uint32                          num_of_tables=0;
    612     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
    613     uint32                          byte_flag=0;
    614     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    615     if ((stat == bcmMimStatIngressPackets) ||
    616         (stat == bcmMimStatIngressBytes)) {
    617          direction = bcmStatFlexDirectionIngress;
    618     } else {
    619          direction = bcmStatFlexDirectionEgress;
    620     }
    621     if (stat == bcmMimStatIngressPackets) {
    622         byte_flag=0;
    623     } else {
    624         byte_flag=1;
    625     }
    626 
    627     BCM_IF_ERROR_RETURN(_bcm_esw_mim_lookup_id_stat_get_table_info(
    628                    unit, lookup_id,&num_of_tables,&table_info[0]));
    629 
    630     for (table_count=0; table_count < num_of_tables ; table_count++) {
    631       if (table_info[table_count].direction == direction) {
    632           for (index_count=0; index_count < num_entries ; index_count++) {
    633             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
    634                                 unit,
    635                                 table_info[table_count].index,
    636                                 table_info[table_count].table,
    637                                 0,
    638                                 byte_flag,
    639                                 counter_indexes[index_count],
    640                                 &counter_values[index_count]));
    641           }
    642       }
    643     }
    644     return BCM_E_NONE;
    645 #else
    646     return BCM_E_UNAVAIL;
    647 #endif
    648 }
    649 /*
    650  * Function:
    651  *      bcm_esw_mim_lookup_id_stat_id_get
    652  * Description:
    653  *      Get stat counter id associated with given MiM I-SID entry
    654  *
    655  * Parameters:
    656  *      unit             - (IN) unit number
    657  *      lookup_id        - (IN) I-SID value 
    658  *      stat             - (IN) Type of the counter to retrieve
    659  *                              I.e. ingress/egress byte/packet)
    660  *      Stat_counter_id  - (OUT) Stat Counter ID
    661  * Return Value:
    662  *      BCM_E_XXX
    663  * Notes:
    664  */
    665 int bcm_esw_mim_lookup_id_stat_id_get(
    666             int unit,
    667             int lookup_id,
    668             bcm_mim_stat_t stat,
    669             uint32 *stat_counter_id)
    670 {
    671 #if defined(BCM_TRIUMPH3_SUPPORT)
    672     bcm_stat_flex_direction_t  direction=bcmStatFlexDirectionIngress;
    673     uint32                     num_of_tables=0;
    674     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    675     uint32                     index=0;
    676     uint32                     num_stat_counter_ids=0;
    677 
    678     if ((stat == bcmMimStatIngressPackets) ||
    679         (stat == bcmMimStatIngressBytes)) {
    680          direction = bcmStatFlexDirectionIngress;
    681     } else {
    682          direction = bcmStatFlexDirectionEgress; 
    683     }
    684 
    685     BCM_IF_ERROR_RETURN(_bcm_esw_mim_lookup_id_stat_get_table_info(
    686                         unit,lookup_id,&num_of_tables,&table_info[0]));
    687     for (index=0; index < num_of_tables ; index++) {
    688          if (table_info[index].direction == direction)
    689              return _bcm_esw_stat_flex_get_counter_id(
    690                                   unit, 1, &table_info[index],
    691                                   &num_stat_counter_ids,stat_counter_id);
    692     }
    693     return BCM_E_NOT_FOUND;
    694 #else
    695     return BCM_E_UNAVAIL;
    696 #endif
    697 }
    698 /*
    699  * Function:
    700  *      bcm_esw_mim_vpn_stat_attach
    701  * Description:
    702  *      Attach counters entries to the given MiM VPN entry
    703  *
    704  * Parameters:
    705  *      unit             - (IN) unit number
    706  *      vpn              - (IN) MiM VPN
    707  *      stat_counter_id  - (IN) Stat Counter ID.
    708  *
    709  * Return Value:
    710  *      BCM_E_XXX
    711  * Notes:
    712  */
    713 int bcm_esw_mim_vpn_stat_attach(
    714             int unit,
    715             bcm_mim_vpn_t vpn,
    716             uint32 stat_counter_id)
    717 {
    718 #if defined(BCM_TRIUMPH3_SUPPORT)
    719     soc_mem_t                 table=0;
    720     bcm_stat_flex_direction_t direction=bcmStatFlexDirectionIngress;
    721     uint32                    pool_number=0;
    722     uint32                    base_index=0;
    723     bcm_stat_flex_mode_t      offset_mode=0;
    724     bcm_stat_object_t         object=bcmStatObjectIngPort;
    725     bcm_stat_group_mode_t     group_mode= bcmStatGroupModeSingle;
    726     uint32                    count=0;
    727     uint32                     actual_num_tables=0;
    728     uint32                     num_of_tables=0;
    729     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    730 
    731     _bcm_esw_stat_get_counter_id_info(
    732                   unit, stat_counter_id,
    733                   &group_mode,&object,&offset_mode,&pool_number,&base_index);
    734     
    735     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_object(unit,object,&direction));
    736     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit,group_mode));
    737 
    738     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
    739                         unit,object,1,&actual_num_tables,&table,&direction));
    740     BCM_IF_ERROR_RETURN(_bcm_esw_mim_vpn_stat_get_table_info(
    741                    unit, vpn,&num_of_tables,&table_info[0]));
    742     for (count=0; count < num_of_tables ; count++) {
    743          if ((table_info[count].direction == direction) &&
    744              (table_info[count].table == table)) {
    745              if (direction == bcmStatFlexDirectionIngress) {
    746                  return _bcm_esw_stat_flex_attach_ingress_table_counters(
    747                         unit,
    748                         table_info[count].table,
    749                         table_info[count].index,
    750                         offset_mode,
    751                         base_index,
    752                         pool_number);
    753              } else {
    754                  return _bcm_esw_stat_flex_attach_egress_table_counters(
    755                         unit,
    756                         table_info[count].table,
    757                         table_info[count].index,
    758                         0,
    759                         offset_mode,
    760                         base_index,
    761                         pool_number);
    762              }
    763          }
    764     }
    765     return BCM_E_NOT_FOUND;
    766 #else
    767     return BCM_E_UNAVAIL;
    768 #endif
    769 }
    770 /*
    771  * Function:
    772  *      bcm_esw_mim_vpn_stat_detach
    773  * Description:
    774  *      Detach counters entries to the given MiM VPN entry
    775  *
    776  * Parameters:
    777  *      unit             - (IN) unit number
    778  *      vpn              - (IN) MiM VPN
    779  *
    780  * Return Value:
    781  *      BCM_E_XXX
    782  * Notes:
    783  */
    784 int bcm_esw_mim_vpn_stat_detach(
    785             int unit,
    786             bcm_mim_vpn_t vpn)
    787 {
    788 #if defined(BCM_TRIUMPH3_SUPPORT)
    789     uint32                     count=0;
    790     uint32                     num_of_tables=0;
    791     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    792     bcm_error_t                rv = BCM_E_NONE;
    793     bcm_error_t                err_code[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION] = {BCM_E_NONE};
    794 
    795     BCM_IF_ERROR_RETURN(_bcm_esw_mim_vpn_stat_get_table_info(
    796                    unit, vpn,&num_of_tables,&table_info[0]));
    797 
    798     for (count=0; count < num_of_tables ; count++) {
    799       if (table_info[count].direction == bcmStatFlexDirectionIngress) {
    800            rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
    801                          unit,
    802                          table_info[count].table,
    803                          table_info[count].index);
    804            if (BCM_E_NONE != rv &&
    805                 BCM_E_NONE == err_code[bcmStatFlexDirectionIngress]) {
    806                 err_code[bcmStatFlexDirectionIngress] = rv;
    807            }
    808       } else {
    809            rv = _bcm_esw_stat_flex_detach_egress_table_counters(
    810                           unit, 0,
    811                           table_info[count].table,
    812                           table_info[count].index);
    813            if (BCM_E_NONE != rv &&
    814                 BCM_E_NONE == err_code[bcmStatFlexDirectionEgress]) {
    815                 err_code[bcmStatFlexDirectionEgress] = rv;
    816            }
    817       }
    818     }
    819 
    820     BCM_STAT_FLEX_DETACH_RETURN(err_code)
    821 #else
    822     return BCM_E_UNAVAIL;
    823 #endif
    824 }
    825 
    826 /*
    827  * Function:
    828  *      _bcm_esw_mim_vpn_stat_counter_get
    829  * Description:
    830  *      Get counter statistic values for specific MiM VPN entry
    831  *      if sync_mode is set, sync the sw accumulated count
    832  *      with hw count value first, else return sw count.  
    833  *
    834  * Parameters:
    835  *      unit             - (IN) unit number
    836  *      sync_mode        - (IN) if 1 sync sw accumulated counter
    837  *                         ihw count else retrieve sw count
    838  *      vpn              - (IN) MiM VPN
    839  *      stat             - (IN) Type of the counter to retrieve
    840  *                              I.e. ingress/egress byte/packet)
    841  *      num_entries      - (IN) Number of counter Entries
    842  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    843  *      counter_values   - (OUT) Pointer to counter values
    844  *
    845  * Return Value:
    846  *      BCM_E_XXX
    847  * Notes:
    848  */
    849 int  
    850 _bcm_esw_mim_vpn_stat_counter_get(int unit,
    851                                   int sync_mode,
    852                                   bcm_mim_vpn_t vpn,
    853                                   bcm_mim_stat_t stat,
    854                                   uint32 num_entries,
    855                                   uint32 *counter_indexes,
    856                                   bcm_stat_value_t *counter_values)
    857 {
    858 #if defined(BCM_TRIUMPH3_SUPPORT)
    859     uint32                          table_count=0;
    860     uint32                          index_count=0;
    861     uint32                          num_of_tables=0;
    862     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
    863     uint32                          byte_flag=0;
    864     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
    865 
    866     if ((stat == bcmMimStatIngressPackets) ||
    867         (stat == bcmMimStatIngressBytes)) {
    868          direction = bcmStatFlexDirectionIngress;
    869     } else {
    870          direction = bcmStatFlexDirectionEgress;
    871     }
    872     if ((stat == bcmMimStatIngressPackets) ||
    873         (stat == bcmMimStatEgressPackets)) {
    874         byte_flag=0;
    875     } else {
    876         byte_flag=1;
    877     }
    878 
    879     BCM_IF_ERROR_RETURN(_bcm_esw_mim_vpn_stat_get_table_info(
    880                    unit, vpn,&num_of_tables,&table_info[0]));
    881 
    882     for (table_count=0; table_count < num_of_tables ; table_count++) {
    883       if (table_info[table_count].direction == direction) {
    884           for (index_count=0; index_count < num_entries ; index_count++) {
    885                /*ctr_offset_info.offset_index = counter_indexes[index_count];*/
    886             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
    887                          unit, sync_mode,
    888                          table_info[table_count].index,
    889                          table_info[table_count].table,
    890                          0,
    891                          byte_flag,
    892                          counter_indexes[index_count],
    893                          &counter_values[index_count]));
    894           }
    895       }
    896     }
    897     return BCM_E_NONE;
    898 #else
    899     return BCM_E_UNAVAIL;
    900 #endif
    901 }
    902 
    903 /*
    904  * Function:
    905  *      bcm_esw_mim_vpn_stat_counter_get
    906  * Description:
    907  *      Get counter statistic values for specific MiM VPN entry
    908  *
    909  * Parameters:
    910  *      unit             - (IN) unit number
    911  *      vpn              - (IN) MiM VPN
    912  *      stat             - (IN) Type of the counter to retrieve
    913  *                              I.e. ingress/egress byte/packet)
    914  *      num_entries      - (IN) Number of counter Entries
    915  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    916  *      counter_values   - (OUT) Pointer to counter values
    917  *
    918  * Return Value:
    919  *      BCM_E_XXX
    920  * Notes:
    921  */
    922 int 
    923 bcm_esw_mim_vpn_stat_counter_get(int unit,
    924                                             bcm_mim_vpn_t vpn,
    925                                             bcm_mim_stat_t stat,
    926                                             uint32 num_entries,
    927                                             uint32 *counter_indexes,
    928                                             bcm_stat_value_t *counter_values)
    929 {
    930     return _bcm_esw_mim_vpn_stat_counter_get(unit, 0, vpn, stat, num_entries,
    931                                              counter_indexes, counter_values);
    932 }
    933 
    934 /*
    935  * Function:
    936  *      bcm_esw_mim_vpn_stat_counter_sync_get
    937  * Description:
    938  *      Get counter statistic values for specific MiM VPN entry
    939  *      Sw accumulated count is synced with hw counters.
    940  *
    941  * ParameterS:
    942  *      unit             - (IN) unit number
    943  *      vpn              - (IN) MiM VPN
    944  *      stat             - (IN) Type of the counter to retrieve
    945  *                              I.e. ingress/egress byte/packet)
    946  *      num_entries      - (IN) Number of counter Entries
    947  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    948  *      counter_values   - (OUT) Pointer to counter values
    949  *
    950  * Return Value:
    951  *      BCM_E_XXX
    952  * Notes:
    953  */
    954 int 
    955 bcm_esw_mim_vpn_stat_counter_sync_get(int unit,
    956             bcm_mim_vpn_t vpn,
    957             bcm_mim_stat_t stat,
    958             uint32 num_entries,
    959             uint32 *counter_indexes,
    960             bcm_stat_value_t *counter_values)
    961 {
    962     return _bcm_esw_mim_vpn_stat_counter_get(unit, 1, vpn, stat, num_entries,
    963                                              counter_indexes, counter_values);
    964 }
    965 
    966 /*
    967  * Function:
    968  *      bcm_esw_mim_vpn_stat_counter_set
    969  * Description:
    970  *      Set counter statistic values for specific MiM VPN entry
    971  *
    972  * Parameters:
    973  *      unit             - (IN) unit number
    974  *      vpn              - (IN) MiM VPN
    975  *      stat             - (IN) Type of the counter to retrieve
    976  *                              I.e. ingress/egress byte/packet)
    977  *      num_entries      - (IN) Number of counter Entries
    978  *      counter_indexes  - (IN) Pointer to Counter indexes entries
    979  *      counter_values   - (IN) Pointer to counter values
    980  *
    981  * Return Value:
    982  *      BCM_E_XXX
    983  * Notes:
    984  */
    985 int bcm_esw_mim_vpn_stat_counter_set(
    986             int unit,
    987             bcm_mim_vpn_t vpn,
    988             bcm_mim_stat_t stat,
    989             uint32 num_entries,
    990             uint32 *counter_indexes,
    991             bcm_stat_value_t *counter_values)
    992 {
    993 #if defined(BCM_TRIUMPH3_SUPPORT)
    994     uint32                          table_count=0;
    995     uint32                          index_count=0;
    996     uint32                          num_of_tables=0;
    997     bcm_stat_flex_direction_t       direction=bcmStatFlexDirectionIngress;
    998     uint32                          byte_flag=0;
    999     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1000 
   1001     if ((stat == bcmMimStatIngressPackets) ||
   1002         (stat == bcmMimStatIngressBytes)) {
   1003          direction = bcmStatFlexDirectionIngress;
   1004     } else {
   1005          direction = bcmStatFlexDirectionEgress;
   1006     }
   1007     if (stat == bcmMimStatIngressPackets) {
   1008         byte_flag=0;
   1009     } else {
   1010         byte_flag=1;
   1011     }
   1012 
   1013     BCM_IF_ERROR_RETURN(_bcm_esw_mim_vpn_stat_get_table_info(
   1014                    unit, vpn,&num_of_tables,&table_info[0]));
   1015 
   1016     for (table_count=0; table_count < num_of_tables ; table_count++) {
   1017       if (table_info[table_count].direction == direction) {
   1018           for (index_count=0; index_count < num_entries ; index_count++) {
   1019             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
   1020                                 unit,
   1021                                 table_info[table_count].index,
   1022                                 table_info[table_count].table,
   1023                                 0,
   1024                                 byte_flag,
   1025                                 counter_indexes[index_count],
   1026                                 &counter_values[index_count]));
   1027           }
   1028       }
   1029     }
   1030     return BCM_E_NONE;
   1031 #else
   1032     return BCM_E_UNAVAIL;
   1033 #endif
   1034 }
   1035 /*
   1036  * Function:
   1037  *      bcm_esw_mim_vpn_stat_id_get
   1038  * Description:
   1039  *      Get stat counter id associated with given MiM VPN entry
   1040  *
   1041  * Parameters:
   1042  *      unit             - (IN) unit number
   1043  *      vpn              - (IN) MiM VPN
   1044  *      stat             - (IN) Type of the counter to retrieve
   1045  *                              I.e. ingress/egress byte/packet)
   1046  *      Stat_counter_id  - (OUT) Stat Counter ID
   1047  * Return Value:
   1048  *      BCM_E_XXX
   1049  * Notes:
   1050  */
   1051 int bcm_esw_mim_vpn_stat_id_get(
   1052             int unit,
   1053             bcm_mim_vpn_t vpn,
   1054             bcm_mim_stat_t stat,
   1055             uint32 *stat_counter_id)
   1056 {
   1057 #if defined(BCM_TRIUMPH3_SUPPORT)
   1058     bcm_stat_flex_direction_t  direction=bcmStatFlexDirectionIngress;
   1059     uint32                     num_of_tables=0;
   1060     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   1061     uint32                     index=0;
   1062     uint32                     num_stat_counter_ids=0;
   1063 
   1064     if ((stat == bcmMimStatIngressPackets) ||
   1065         (stat == bcmMimStatIngressBytes)) {
   1066          direction = bcmStatFlexDirectionIngress;
   1067     } else {
   1068          direction = bcmStatFlexDirectionEgress;
   1069     }
   1070 
   1071     BCM_IF_ERROR_RETURN(_bcm_esw_mim_vpn_stat_get_table_info(
   1072                         unit,vpn,&num_of_tables,&table_info[0]));
   1073     for (index=0; index < num_of_tables ; index++) {
   1074          if (table_info[index].direction == direction)
   1075              return _bcm_esw_stat_flex_get_counter_id(
   1076                                   unit, 1, &table_info[index],
   1077                                   &num_stat_counter_ids,stat_counter_id);
   1078     }
   1079     return BCM_E_NOT_FOUND;
   1080 #else
   1081     return BCM_E_UNAVAIL;
   1082 #endif
   1083 }
   1084 
   1085 /*
   1086  * Function:
   1087  *      _bcm_esw_mim_port_source_vp_lag_set
   1088  * Purpose:
   1089  *      Set source VP LAG for a MIM virtual port.
   1090  * Parameters:
   1091  *      unit      - (IN) SOC unit number.
   1092  *      gport     - (IN) MIM virtual port GPORT ID.
   1093  *      vp_lag_vp - (IN) VP representing the VP LAG.
   1094  * Returns:
   1095  *      BCM_X_XXX
   1096  */
   1097 int
   1098 _bcm_esw_mim_port_source_vp_lag_set(
   1099     int unit, bcm_gport_t gport, int vp_lag_vp)
   1100 {
   1101     int rv = BCM_E_UNAVAIL;
   1102 
   1103 #if defined(BCM_TRIDENT2_SUPPORT)
   1104     if (soc_feature(unit, soc_feature_mim) &&
   1105         soc_feature(unit, soc_feature_vp_lag)) {
   1106         rv = bcm_td2_mim_port_source_vp_lag_set(unit, gport, vp_lag_vp);
   1107     }
   1108 #endif /* BCM_TRIDENT2_SUPPORT */
   1109 
   1110     return rv;
   1111 }
   1112 
   1113 /*
   1114  * Function:
   1115  *      _bcm_esw_mim_port_source_vp_lag_clear
   1116  * Purpose:
   1117  *      Clear source VP LAG for a MIM virtual port.
   1118  * Parameters:
   1119  *      unit      - (IN) SOC unit number.
   1120  *      gport     - (IN) MIM virtual port GPORT ID.
   1121  *      vp_lag_vp - (IN) VP representing the VP LAG.
   1122  * Returns:
   1123  *      BCM_X_XXX
   1124  */
   1125 int
   1126 _bcm_esw_mim_port_source_vp_lag_clear(
   1127     int unit, bcm_gport_t gport, int vp_lag_vp)
   1128 {
   1129     int rv = BCM_E_UNAVAIL;
   1130 
   1131 #if defined(BCM_TRIDENT2_SUPPORT)
   1132     if (soc_feature(unit, soc_feature_mim) &&
   1133         soc_feature(unit, soc_feature_vp_lag)) {
   1134         rv = bcm_td2_mim_port_source_vp_lag_clear(unit, gport, vp_lag_vp);
   1135     }
   1136 #endif /* BCM_TRIDENT2_SUPPORT */
   1137 
   1138     return rv;
   1139 }
   1140 
   1141 /*
   1142  * Function:
   1143  *      _bcm_esw_mim_port_source_vp_lag_get
   1144  * Purpose:
   1145  *      Get source VP LAG for a MIM virtual port.
   1146  * Parameters:
   1147  *      unit      - (IN) SOC unit number.
   1148  *      gport     - (IN) MIM virtual port GPORT ID.
   1149  *      vp_lag_vp - (OUT) VP representing the VP LAG.
   1150  * Returns:
   1151  *      BCM_X_XXX
   1152  */
   1153 int
   1154 _bcm_esw_mim_port_source_vp_lag_get(
   1155     int unit, bcm_gport_t gport, int *vp_lag_vp)
   1156 {
   1157     int rv = BCM_E_UNAVAIL;
   1158 
   1159 #if defined(BCM_TRIDENT2_SUPPORT)
   1160     if (soc_feature(unit, soc_feature_mim) &&
   1161         soc_feature(unit, soc_feature_vp_lag)) {
   1162         rv = bcm_td2_mim_port_source_vp_lag_get(unit, gport, vp_lag_vp);
   1163     }
   1164 #endif /* BCM_TRIDENT2_SUPPORT */
   1165 
   1166     return rv;
   1167 }
   1168 
   1169 #else /* INCLUDE_L3 */
   1170 int _bcm_esw_mim_not_empty;
   1171 #endif  /* INCLUDE_L3 */