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

mpls.c (22072B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  * 
      7  * File:     mpls.c
      8  * Purpose:  Manages MPLS functionality at a system level
      9  */
     10 
     11 #include <sal/core/libc.h>
     12 #include <shared/alloc.h>
     13 
     14 #include <bcm/types.h>
     15 
     16 #include <bcmx/l3.h>
     17 #include <bcmx/lport.h>
     18 #include <bcmx/bcmx.h>
     19 #include <bcmx/lplist.h>
     20 
     21 #include "bcmx_int.h"
     22 
     23 
     24 #include <bcmx/mpls.h>
     25 
     26 #ifdef INCLUDE_L3
     27 
     28 #define BCMX_MPLS_INIT_CHECK    BCMX_READY_CHECK
     29 
     30 #define BCMX_MPLS_ERROR_CHECK(_unit, _check, _rv)    \
     31     BCMX_ERROR_CHECK(_unit, _check, _rv)
     32 
     33 #define BCMX_MPLS_SET_ERROR_CHECK(_unit, _check, _rv)    \
     34     BCMX_SET_ERROR_CHECK(_unit, _check, _rv)
     35 
     36 #define BCMX_MPLS_DELETE_ERROR_CHECK(_unit, _check, _rv)    \
     37     BCMX_DELETE_ERROR_CHECK(_unit, _check, _rv)
     38 
     39 #define BCMX_MPLS_GET_IS_VALID(_unit, _rv)    \
     40     BCMX_ERROR_IS_VALID(_unit, _rv)
     41 
     42 
     43 #define BCMX_MPLS_VPN_CONFIG_T_PTR_TO_BCM(_info)    \
     44     ((bcm_mpls_vpn_config_t *)(_info))
     45 
     46 #define BCMX_MPLS_PORT_T_PTR_TO_BCM(_mpls_port)    \
     47     ((bcm_mpls_port_t *)(_mpls_port))
     48 
     49 #define BCMX_MPLS_EGRESS_LABEL_T_PTR_TO_BCM(_label)    \
     50     ((bcm_mpls_egress_label_t *)(_label))
     51 
     52 #define BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM(_info)    \
     53     ((bcm_mpls_tunnel_switch_t *)(_info))
     54 
     55 
     56 /*
     57  * Function:
     58  *     bcmx_mpls_vpn_config_t_init
     59  * Purpose:
     60  *     Initialize the MPLS VPN config structure.
     61  * Parameters:
     62  *     info - Pointer to the struct to be initialized
     63  * Returns:
     64  *     None
     65  */
     66 void
     67 bcmx_mpls_vpn_config_t_init(bcmx_mpls_vpn_config_t *info)
     68 {
     69     if (info != NULL) {
     70         bcm_mpls_vpn_config_t_init(BCMX_MPLS_VPN_CONFIG_T_PTR_TO_BCM(info));
     71     }
     72 }
     73 
     74 /*
     75  * Function:
     76  *     bcmx_mpls_port_t_init
     77  * Purpose:
     78  *     Initialize the MPLS port structure
     79  * Parameters:
     80  *     mpls_port - Pointer to the struct to be initialized
     81  * Returns:
     82  *     None
     83  */
     84 void
     85 bcmx_mpls_port_t_init(bcmx_mpls_port_t *mpls_port)
     86 {
     87     if (mpls_port != NULL) {
     88         bcm_mpls_port_t_init(BCMX_MPLS_PORT_T_PTR_TO_BCM(mpls_port));
     89     }
     90 }
     91 
     92 /*
     93  * Function:
     94  *     bcmx_mpls_egress_label_t_init
     95  * Purpose:
     96  *     Initialize the MPLS egress label structure
     97  * Parameters:
     98  *     label - Pointer to the struct to be initialized
     99  * Returns:
    100  *     None
    101  */
    102 void
    103 bcmx_mpls_egress_label_t_init(bcmx_mpls_egress_label_t *label)
    104 {
    105     if (label != NULL) {
    106         bcm_mpls_egress_label_t_init(BCMX_MPLS_EGRESS_LABEL_T_PTR_TO_BCM
    107                                      (label));
    108     }
    109 }
    110 
    111 /*
    112  * Function:
    113  *     bcmx_mpls_tunnel_switch_t_init
    114  * Purpose:
    115  *     Initialize the MPLS tunnel switch structure
    116  * Parameters:
    117  *     info - Pointer to the struct to be initialized
    118  * Returns:
    119  *     None
    120  */
    121 void
    122 bcmx_mpls_tunnel_switch_t_init(bcmx_mpls_tunnel_switch_t *info)
    123 {
    124     if (info != NULL) {
    125         bcm_mpls_tunnel_switch_t_init(BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM
    126                                       (info));
    127     }
    128 }
    129 
    130 /*
    131  * Function:
    132  *      bcmx_mpls_init
    133  * Purpose:
    134  *      Initialize MPLS module system-wide
    135  * Parameters:
    136  *      None
    137  * Returns:
    138  *      BCM_E_XXX
    139  */
    140 int
    141 bcmx_mpls_init(void)
    142 {
    143     int rv = BCM_E_UNAVAIL, tmp_rv;
    144     int i, bcm_unit;
    145 
    146     BCMX_MPLS_INIT_CHECK;
    147 
    148     BCMX_UNIT_ITER(bcm_unit, i) {
    149         tmp_rv = bcm_mpls_init(bcm_unit);
    150         BCM_IF_ERROR_RETURN(BCMX_MPLS_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    151     }
    152 
    153     return rv;
    154 }
    155 
    156 /*
    157  * Function:
    158  *     bcmx_mpls_cleanup
    159  * Purpose:
    160  *     Disable MPLS system-wide
    161  * Parameters:
    162  *     None
    163  * Returns:
    164  *     BCM_E_XXX
    165  */
    166 int
    167 bcmx_mpls_cleanup(void)
    168 {
    169     int rv = BCM_E_UNAVAIL, tmp_rv;
    170     int i, bcm_unit;
    171 
    172     BCMX_MPLS_INIT_CHECK;
    173 
    174     BCMX_UNIT_ITER(bcm_unit, i) {
    175         tmp_rv = bcm_mpls_cleanup(bcm_unit);
    176         BCM_IF_ERROR_RETURN(BCMX_MPLS_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    177     }
    178 
    179     return rv;
    180 }
    181 
    182 /*
    183  * Function:
    184  *      bcmx_mpls_exp_map_create
    185  * Purpose:
    186  *      Create an MPLS EXP map instance.
    187  * Parameters:
    188  *      flags       - (IN)  MPLS flags
    189  *      exp_map_id  - (OUT) Allocated EXP map ID
    190  * Returns:
    191  *      BCM_E_XXX
    192  */
    193 int
    194 bcmx_mpls_exp_map_create(uint32 flags, int *exp_map_id)
    195 {
    196     int rv = BCM_E_UNAVAIL, tmp_rv;
    197     int i, bcm_unit;
    198 
    199     BCMX_MPLS_INIT_CHECK;
    200 
    201     BCMX_PARAM_NULL_CHECK(exp_map_id);
    202 
    203     BCMX_UNIT_ITER(bcm_unit, i) {
    204         tmp_rv = bcm_mpls_exp_map_create(bcm_unit, flags, exp_map_id);
    205         BCM_IF_ERROR_RETURN(BCMX_MPLS_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    206     }
    207 
    208     return rv;
    209 }
    210 
    211 /*
    212  * Function:
    213  *      bcmx_mpls_exp_map_destroy
    214  * Purpose:
    215  *      Destroy an existing MPLS EXP map instance.
    216  * Parameters:
    217  *      exp_map_id - (IN) EXP map ID
    218  * Returns:
    219  *      BCM_E_XXX
    220  */
    221 int
    222 bcmx_mpls_exp_map_destroy(int exp_map_id)
    223 {
    224     int rv = BCM_E_UNAVAIL, tmp_rv;
    225     int i, bcm_unit;
    226 
    227     BCMX_MPLS_INIT_CHECK;
    228 
    229     BCMX_UNIT_ITER(bcm_unit, i) {
    230         tmp_rv = bcm_mpls_exp_map_destroy(bcm_unit, exp_map_id);
    231         BCM_IF_ERROR_RETURN
    232             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    233     }
    234 
    235     return rv;
    236 }
    237 
    238 
    239 /*
    240  * Function:
    241  *      bcmx_mpls_exp_map_set
    242  * Purpose:
    243  *      Set the mapping of { internal priority, color }
    244  *      to a EXP value for MPLS headers
    245  *      in the specified EXP map instance.
    246  * Parameters:
    247  *      exp_map_id   - (IN) EXP map ID
    248  *      exp_map      - (IN) EXP map info
    249  * Returns:
    250  *      BCM_E_XXX
    251  */
    252 int
    253 bcmx_mpls_exp_map_set(int exp_map_id,
    254                       bcm_mpls_exp_map_t *exp_map)
    255 {
    256     int rv = BCM_E_UNAVAIL, tmp_rv;
    257     int i, bcm_unit;
    258 
    259     BCMX_MPLS_INIT_CHECK;
    260 
    261     BCMX_PARAM_NULL_CHECK(exp_map);
    262 
    263     BCMX_UNIT_ITER(bcm_unit, i) {
    264         tmp_rv = bcm_mpls_exp_map_set(bcm_unit, exp_map_id, exp_map);
    265         BCM_IF_ERROR_RETURN(BCMX_MPLS_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    266     }
    267 
    268     return rv;
    269 }
    270 
    271 
    272 /*
    273  * Function:
    274  *      bcmx_mpls_exp_map_get
    275  * Purpose:
    276  *      Get the EXP map information for the specified EXP map instance.
    277  * Parameters:
    278  *      exp_map_id   - (IN)  EXP map ID
    279  *      exp_map      - (OUT) Returning EXP map info
    280  * Returns:
    281  *      BCM_E_XXX
    282  */
    283 int
    284 bcmx_mpls_exp_map_get(int exp_map_id,
    285                       bcm_mpls_exp_map_t *exp_map)
    286 {
    287     int    rv;
    288     int    i, bcm_unit;
    289 
    290     BCMX_MPLS_INIT_CHECK;
    291 
    292     BCMX_UNIT_ITER(bcm_unit, i) {
    293         rv = bcm_mpls_exp_map_get(bcm_unit, exp_map_id, exp_map);
    294         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, rv)) {
    295             return rv;
    296         }
    297     }
    298 
    299     return BCM_E_UNAVAIL;
    300 }
    301 
    302 /*
    303  * Function:
    304  *     bcmx_mpls_vpn_id_create
    305  */
    306 int
    307 bcmx_mpls_vpn_id_create(bcmx_mpls_vpn_config_t *info)
    308 {
    309     int  rv = BCM_E_UNAVAIL, tmp_rv;
    310     int  i;
    311     int  bcm_unit;
    312     uint32  flags_orig;
    313 
    314     BCMX_MPLS_INIT_CHECK;
    315 
    316     BCMX_PARAM_NULL_CHECK(info);
    317 
    318     /* Store original 'xxx_WITH_ID' flag bit */
    319     flags_orig = info->flags & BCM_MPLS_VPN_WITH_ID;
    320 
    321     BCMX_UNIT_ITER(bcm_unit, i) {
    322         tmp_rv = bcm_mpls_vpn_id_create(bcm_unit,
    323                                         BCMX_MPLS_VPN_CONFIG_T_PTR_TO_BCM
    324                                         (info));
    325         if (BCM_FAILURE(BCMX_MPLS_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv))) {
    326             break;
    327         }
    328         
    329         /*
    330          * If vpn id is not specified, use returned id from
    331          * first successful 'create' for remaining units.
    332          */
    333         if (!(info->flags & BCM_MPLS_VPN_WITH_ID)) {
    334             if (BCM_SUCCESS(tmp_rv)) {
    335                 info->flags |= BCM_MPLS_VPN_WITH_ID;
    336             }
    337         }
    338     }
    339 
    340     /* Restore 'xxx_WITH_ID' flag bit */
    341     info->flags &= ~BCM_MPLS_VPN_WITH_ID;
    342     info->flags |= flags_orig;
    343 
    344     return rv;
    345 }
    346 
    347 /*
    348  * Function:
    349  *     bcmx_mpls_vpn_id_destroy
    350  */
    351 int
    352 bcmx_mpls_vpn_id_destroy(bcm_vpn_t vpn)
    353 {
    354     int  rv = BCM_E_UNAVAIL, tmp_rv;
    355     int  i;
    356     int  bcm_unit;
    357 
    358     BCMX_MPLS_INIT_CHECK;
    359 
    360     BCMX_UNIT_ITER(bcm_unit, i) {
    361         tmp_rv = bcm_mpls_vpn_id_destroy(bcm_unit, vpn);
    362         BCM_IF_ERROR_RETURN
    363             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    364     }
    365 
    366     return rv;
    367 }
    368 
    369 /*
    370  * Function:
    371  *     bcmx_mpls_vpn_id_destroy_all
    372  */
    373 int
    374 bcmx_mpls_vpn_id_destroy_all(void)
    375 {
    376     int  rv = BCM_E_UNAVAIL, tmp_rv;
    377     int  i;
    378     int  bcm_unit;
    379 
    380     BCMX_MPLS_INIT_CHECK;
    381 
    382     BCMX_UNIT_ITER(bcm_unit, i) {
    383         tmp_rv = bcm_mpls_vpn_id_destroy_all(bcm_unit);
    384         BCM_IF_ERROR_RETURN
    385             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    386     }
    387 
    388     return rv;
    389 }
    390 
    391 /*
    392  * Function:
    393  *     bcmx_mpls_vpn_id_get
    394  */
    395 int
    396 bcmx_mpls_vpn_id_get(bcm_vpn_t vpn, bcmx_mpls_vpn_config_t *info)
    397 {
    398     int  rv;
    399     int  i, bcm_unit;
    400 
    401     BCMX_MPLS_INIT_CHECK;
    402 
    403     BCMX_PARAM_NULL_CHECK(info);
    404 
    405     BCMX_UNIT_ITER(bcm_unit, i) {
    406         rv = bcm_mpls_vpn_id_get(bcm_unit,  vpn,
    407                                  BCMX_MPLS_VPN_CONFIG_T_PTR_TO_BCM(info));
    408         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, rv)) {
    409             return rv;
    410         }
    411     }
    412 
    413     return BCM_E_UNAVAIL;
    414 }
    415 
    416 /*
    417  * Function:
    418  *     bcmx_mpls_port_add
    419  */
    420 int
    421 bcmx_mpls_port_add(bcm_vpn_t vpn, bcmx_mpls_port_t *mpls_port)
    422 {
    423     int  rv = BCM_E_UNAVAIL, tmp_rv;
    424     int  i;
    425     int  bcm_unit;
    426     uint32  flags_orig;
    427 
    428     BCMX_MPLS_INIT_CHECK;
    429 
    430     BCMX_PARAM_NULL_CHECK(mpls_port);
    431 
    432     /* Store original 'xxx_WITH_ID' flag bit */
    433     flags_orig = mpls_port->flags & BCM_MPLS_PORT_WITH_ID;
    434 
    435     /*
    436      * Use returned 'mpls_port_id' from first success 'add'
    437      * to set rest of the units.
    438      */
    439     BCMX_UNIT_ITER(bcm_unit, i) {
    440         tmp_rv = bcm_mpls_port_add(bcm_unit, vpn,
    441                                    BCMX_MPLS_PORT_T_PTR_TO_BCM(mpls_port));
    442         if (BCM_FAILURE(BCMX_MPLS_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv))) {
    443             break;
    444         }
    445 
    446         /*
    447          * If mpls id is not specified, use returned id from
    448          * first successful 'add' for remaining units.
    449          */
    450         if (!(mpls_port->flags & BCM_MPLS_PORT_WITH_ID)) {
    451             if (BCM_SUCCESS(tmp_rv)) {
    452                 mpls_port->flags |= BCM_MPLS_PORT_WITH_ID;
    453             }
    454         }
    455     }
    456 
    457     /* Restore 'xxx_WITH_ID' flag bit */
    458     mpls_port->flags &= ~BCM_MPLS_PORT_WITH_ID;
    459     mpls_port->flags |= flags_orig;
    460 
    461     return rv;
    462 }
    463 
    464 /*
    465  * Function:
    466  *     bcmx_mpls_port_delete
    467  */
    468 int
    469 bcmx_mpls_port_delete(bcm_vpn_t vpn, bcm_gport_t mpls_port_id)
    470 {
    471     int  rv = BCM_E_UNAVAIL, tmp_rv;
    472     int  i;
    473     int  bcm_unit;
    474 
    475     BCMX_MPLS_INIT_CHECK;
    476 
    477     BCMX_UNIT_ITER(bcm_unit, i) {
    478         tmp_rv = bcm_mpls_port_delete(bcm_unit, vpn, mpls_port_id);
    479         BCM_IF_ERROR_RETURN
    480             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    481     }
    482 
    483     return rv;
    484 }
    485 
    486 /*
    487  * Function:
    488  *     bcmx_mpls_port_delete_all
    489  */
    490 int
    491 bcmx_mpls_port_delete_all(bcm_vpn_t vpn)
    492 {
    493     int  rv = BCM_E_UNAVAIL, tmp_rv;
    494     int  i;
    495     int  bcm_unit;
    496 
    497     BCMX_MPLS_INIT_CHECK;
    498 
    499     BCMX_UNIT_ITER(bcm_unit, i) {
    500         tmp_rv = bcm_mpls_port_delete_all(bcm_unit, vpn);
    501         BCM_IF_ERROR_RETURN
    502             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    503     }
    504 
    505     return rv;
    506 }
    507 
    508 /*
    509  * Function:
    510  *     bcmx_mpls_port_get
    511  */
    512 int
    513 bcmx_mpls_port_get(bcm_vpn_t vpn, bcmx_mpls_port_t *mpls_port)
    514 {
    515     int  rv;
    516     int  i, bcm_unit;
    517 
    518     BCMX_MPLS_INIT_CHECK;
    519 
    520     BCMX_PARAM_NULL_CHECK(mpls_port);
    521 
    522     BCMX_UNIT_ITER(bcm_unit, i) {
    523         rv = bcm_mpls_port_get(bcm_unit,  vpn,
    524                                BCMX_MPLS_PORT_T_PTR_TO_BCM(mpls_port));
    525         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, rv)) {
    526             return rv;
    527         }
    528     }
    529 
    530     return BCM_E_UNAVAIL;
    531 }
    532 
    533 /*
    534  * Function:
    535  *     bcmx_mpls_port_get_all
    536  */
    537 int
    538 bcmx_mpls_port_get_all(bcm_vpn_t vpn, int port_max,
    539                        bcmx_mpls_port_t *port_array, int *port_count)
    540 {
    541     int  rv;
    542     int  i, bcm_unit;
    543 
    544     BCMX_MPLS_INIT_CHECK;
    545 
    546     BCMX_PARAM_ARRAY_NULL_CHECK(port_max, port_array);
    547     BCMX_PARAM_NULL_CHECK(port_count);
    548 
    549     BCMX_UNIT_ITER(bcm_unit, i) {
    550         rv = bcm_mpls_port_get_all(bcm_unit,  vpn, port_max,
    551                                    BCMX_MPLS_PORT_T_PTR_TO_BCM(port_array),
    552                                    port_count);
    553         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, rv)) {
    554             return rv;
    555         }
    556     }
    557 
    558     return BCM_E_UNAVAIL;
    559 }
    560 
    561 /*
    562  * Function:
    563  *     bcmx_mpls_tunnel_initiator_set
    564  */
    565 int
    566 bcmx_mpls_tunnel_initiator_set(bcm_if_t intf, int num_labels,
    567                                bcmx_mpls_egress_label_t *label_array)
    568 {
    569     int  rv = BCM_E_UNAVAIL, tmp_rv;
    570     int  i;
    571     int  bcm_unit;
    572 
    573     BCMX_MPLS_INIT_CHECK;
    574 
    575     BCMX_PARAM_NULL_CHECK(label_array);
    576 
    577     BCMX_UNIT_ITER(bcm_unit, i) {
    578         tmp_rv = bcm_mpls_tunnel_initiator_set(bcm_unit, intf, num_labels,
    579                                                BCMX_MPLS_EGRESS_LABEL_T_PTR_TO_BCM
    580                                                (label_array));
    581         BCM_IF_ERROR_RETURN(BCMX_MPLS_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    582     }
    583 
    584     return rv;
    585 }
    586 
    587 /*
    588  * Function:
    589  *     bcmx_mpls_tunnel_initiator_get
    590  */
    591 int
    592 bcmx_mpls_tunnel_initiator_get(bcm_if_t intf, int label_max,
    593                                bcmx_mpls_egress_label_t *label_array,
    594                                int *label_count)
    595 {
    596     int  rv;
    597     int  i, bcm_unit;
    598 
    599     BCMX_MPLS_INIT_CHECK;
    600 
    601     BCMX_PARAM_ARRAY_NULL_CHECK(label_max, label_array);
    602     BCMX_PARAM_NULL_CHECK(label_count);
    603 
    604     BCMX_UNIT_ITER(bcm_unit, i) {
    605         rv = bcm_mpls_tunnel_initiator_get(bcm_unit, intf, label_max,
    606                                            BCMX_MPLS_EGRESS_LABEL_T_PTR_TO_BCM
    607                                            (label_array),
    608                                            label_count);
    609         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, rv)) {
    610             return rv;
    611         }
    612     }
    613 
    614     return BCM_E_UNAVAIL;
    615 }
    616 
    617 /*
    618  * Function:
    619  *     bcmx_mpls_tunnel_initiator_clear
    620  */
    621 int
    622 bcmx_mpls_tunnel_initiator_clear(bcm_if_t intf)
    623 {
    624     int  rv = BCM_E_UNAVAIL, tmp_rv;
    625     int  i;
    626     int  bcm_unit;
    627 
    628     BCMX_MPLS_INIT_CHECK;
    629 
    630     BCMX_UNIT_ITER(bcm_unit, i) {
    631         tmp_rv = bcm_mpls_tunnel_initiator_clear(bcm_unit, intf);
    632         BCM_IF_ERROR_RETURN
    633             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    634     }
    635 
    636     return rv;
    637 }
    638 
    639 /*
    640  * Function:
    641  *     bcmx_mpls_tunnel_initiator_clear_all
    642  */
    643 int
    644 bcmx_mpls_tunnel_initiator_clear_all(void)
    645 {
    646     int  rv = BCM_E_UNAVAIL, tmp_rv;
    647     int  i;
    648     int  bcm_unit;
    649 
    650     BCMX_MPLS_INIT_CHECK;
    651 
    652     BCMX_UNIT_ITER(bcm_unit, i) {
    653         tmp_rv = bcm_mpls_tunnel_initiator_clear_all(bcm_unit);
    654         BCM_IF_ERROR_RETURN
    655             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    656     }
    657 
    658     return rv;
    659 }
    660 
    661 /*
    662  * Function:
    663  *     bcmx_mpls_tunnel_switch_add
    664  */
    665 int
    666 bcmx_mpls_tunnel_switch_add(bcmx_mpls_tunnel_switch_t *info)
    667 {
    668     int         rv = BCM_E_UNAVAIL, tmp_rv;
    669     int         i;
    670     int         bcm_unit;
    671     bcm_port_t  bcm_port;
    672 
    673     BCMX_MPLS_INIT_CHECK;
    674 
    675     BCMX_PARAM_NULL_CHECK(info);
    676 
    677     /*
    678      * If 'port' member is a valid BCMX logical port, then port
    679      * refers to a specific physical port (mod/port or dev/port).
    680      * Else, 'port' is a system-wide value.
    681      */
    682     if (BCM_SUCCESS(_bcmx_dest_to_unit_port(info->port,
    683                                             &bcm_unit, &bcm_port,
    684                                             BCMX_DEST_CONVERT_DEFAULT))) {
    685         return bcm_mpls_tunnel_switch_add(bcm_unit,
    686                                           BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM
    687                                           (info));
    688     }
    689 
    690     BCMX_UNIT_ITER(bcm_unit, i) {
    691         tmp_rv = bcm_mpls_tunnel_switch_add(bcm_unit,
    692                                             BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM
    693                                             (info));
    694         BCM_IF_ERROR_RETURN(BCMX_MPLS_SET_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    695     }
    696 
    697     return rv;
    698 }
    699 
    700 /*
    701  * Function:
    702  *     bcmx_mpls_tunnel_switch_delete
    703  */
    704 int
    705 bcmx_mpls_tunnel_switch_delete(bcmx_mpls_tunnel_switch_t *info)
    706 {
    707     int         rv = BCM_E_UNAVAIL, tmp_rv;
    708     int         i;
    709     int         bcm_unit;
    710     bcm_port_t  bcm_port;
    711 
    712     BCMX_MPLS_INIT_CHECK;
    713 
    714     BCMX_PARAM_NULL_CHECK(info);
    715 
    716     /*
    717      * If 'port' member is a valid BCMX logical port, then port
    718      * refers to a specific physical port (mod/port or dev/port).
    719      * Else, 'port' is a system-wide value.
    720      */
    721     if (BCM_SUCCESS(_bcmx_dest_to_unit_port(info->port,
    722                                             &bcm_unit, &bcm_port,
    723                                             BCMX_DEST_CONVERT_DEFAULT))) {
    724         return bcm_mpls_tunnel_switch_delete(bcm_unit,
    725                                              BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM
    726                                              (info));
    727     }
    728 
    729     BCMX_UNIT_ITER(bcm_unit, i) {
    730         tmp_rv = bcm_mpls_tunnel_switch_delete(bcm_unit,
    731                                                BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM
    732                                                (info));
    733         BCM_IF_ERROR_RETURN
    734             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    735     }
    736 
    737     return rv;
    738 }
    739 
    740 /*
    741  * Function:
    742  *     bcmx_mpls_tunnel_switch_delete_all
    743  */
    744 int
    745 bcmx_mpls_tunnel_switch_delete_all(void)
    746 {
    747     int  rv = BCM_E_UNAVAIL, tmp_rv;
    748     int  i;
    749     int  bcm_unit;
    750 
    751     BCMX_MPLS_INIT_CHECK;
    752 
    753     BCMX_UNIT_ITER(bcm_unit, i) {
    754         tmp_rv = bcm_mpls_tunnel_switch_delete_all(bcm_unit);
    755         BCM_IF_ERROR_RETURN
    756             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    757     }
    758 
    759     return rv;
    760 }
    761 
    762 /*
    763  * Function:
    764  *     bcmx_mpls_tunnel_switch_get
    765  */
    766 int
    767 bcmx_mpls_tunnel_switch_get(bcmx_mpls_tunnel_switch_t *info)
    768 {
    769     int         rv;
    770     int         i;
    771     int         bcm_unit;
    772     bcm_port_t  bcm_port;
    773 
    774     BCMX_MPLS_INIT_CHECK;
    775 
    776     BCMX_PARAM_NULL_CHECK(info);
    777 
    778     /*
    779      * If 'port' member is a valid BCMX logical port, then port
    780      * refers to a specific physical port (mod/port or dev/port).
    781      * Else, 'port' is a system-wide value.
    782      */
    783     if (BCM_SUCCESS(_bcmx_dest_to_unit_port(info->port,
    784                                             &bcm_unit, &bcm_port,
    785                                             BCMX_DEST_CONVERT_DEFAULT))) {
    786         return bcm_mpls_tunnel_switch_get(bcm_unit,
    787                                           BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM
    788                                           (info));
    789     }
    790 
    791     BCMX_UNIT_ITER(bcm_unit, i) {
    792         rv = bcm_mpls_tunnel_switch_get(bcm_unit,
    793                                         BCMX_MPLS_TUNNEL_SWITCH_T_PTR_TO_BCM
    794                                         (info));
    795         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, rv)) {
    796             return rv;
    797         }
    798     }
    799 
    800     return BCM_E_UNAVAIL;
    801 }
    802 
    803 /*
    804  * Function:
    805  *     bcmx_mpls_label_stat_get
    806  */
    807 int
    808 bcmx_mpls_label_stat_get(bcm_mpls_label_t label, bcm_gport_t port,
    809                          bcm_mpls_stat_t stat, uint64 *val)
    810 {
    811     int         rv = BCM_E_UNAVAIL, tmp_rv;
    812     int         i;
    813     int         bcm_unit;
    814     bcm_port_t  bcm_port;
    815     uint64      tmp_val;
    816 
    817     BCMX_MPLS_INIT_CHECK;
    818 
    819     BCMX_PARAM_NULL_CHECK(val);
    820 
    821     /*
    822      * If gport is a valid BCMX logical port, then gport refers to
    823      * a specific physical port (mod/port or dev/port).
    824      * Else, gport is a system-wide value, gather stats from all units.
    825      */
    826     if (BCM_SUCCESS(_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port,
    827                                             BCMX_DEST_CONVERT_DEFAULT))) {
    828         return bcm_mpls_label_stat_get(bcm_unit, label, port, stat, val);
    829     }
    830 
    831     COMPILER_64_ZERO(*val);
    832     BCMX_UNIT_ITER(bcm_unit, i) {
    833         tmp_rv = bcm_mpls_label_stat_get(bcm_unit, label, port, stat,
    834                                          &tmp_val);
    835         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, tmp_rv)) {
    836             rv = tmp_rv;
    837             if (BCM_SUCCESS(tmp_rv)) {
    838                 COMPILER_64_ADD_64(*val, tmp_val);
    839             } else {
    840                 break;
    841             }
    842         }
    843     }
    844 
    845     return rv;
    846 }
    847 
    848 /*
    849  * Function:
    850  *     bcmx_mpls_label_stat_get32
    851  */
    852 int
    853 bcmx_mpls_label_stat_get32(bcm_mpls_label_t label, bcm_gport_t port,
    854                            bcm_mpls_stat_t stat, uint32 *val)
    855 {
    856     int         rv = BCM_E_UNAVAIL, tmp_rv;
    857     int         i;
    858     int         bcm_unit;
    859     bcm_port_t  bcm_port;
    860     uint32      tmp_val;
    861 
    862     BCMX_MPLS_INIT_CHECK;
    863 
    864     BCMX_PARAM_NULL_CHECK(val);
    865 
    866     /*
    867      * If gport is a valid BCMX logical port, then gport refers to
    868      * a specific physical port (mod/port or dev/port).
    869      * Else, gport is a system-wide value, gather stats from all units.
    870      */
    871     if (BCM_SUCCESS(_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port,
    872                                             BCMX_DEST_CONVERT_DEFAULT))) {
    873         return bcm_mpls_label_stat_get32(bcm_unit, label, port, stat, val);
    874     }
    875 
    876     *val = 0;
    877     BCMX_UNIT_ITER(bcm_unit, i) {
    878         tmp_rv = bcm_mpls_label_stat_get32(bcm_unit, label, port, stat,
    879                                            &tmp_val);
    880         if (BCMX_MPLS_GET_IS_VALID(bcm_unit, tmp_rv)) {
    881             rv = tmp_rv;
    882             if (BCM_SUCCESS(tmp_rv)) {
    883                 *val += tmp_val;
    884             } else {
    885                 break;
    886             }
    887         }
    888     }
    889 
    890     return rv;
    891 }
    892 
    893 /*
    894  * Function:
    895  *     bcmx_mpls_label_stat_clear
    896  */
    897 int
    898 bcmx_mpls_label_stat_clear(bcm_mpls_label_t label, bcm_gport_t port,
    899                            bcm_mpls_stat_t stat)
    900 {
    901     int         rv = BCM_E_UNAVAIL, tmp_rv;
    902     int         i;
    903     int         bcm_unit;
    904     bcm_port_t  bcm_port;
    905 
    906     BCMX_MPLS_INIT_CHECK;
    907 
    908     /*
    909      * If gport is a valid BCMX logical port, then gport refers to
    910      * a specific physical port (mod/port or dev/port).
    911      * Else, gport is a system-wide value.
    912      */
    913     if (BCM_SUCCESS(_bcmx_dest_to_unit_port(port, &bcm_unit, &bcm_port,
    914                                             BCMX_DEST_CONVERT_DEFAULT))) {
    915         return bcm_mpls_label_stat_clear(bcm_unit, label, port, stat);
    916     }
    917 
    918     BCMX_UNIT_ITER(bcm_unit, i) {
    919         tmp_rv = bcm_mpls_label_stat_clear(bcm_unit, label, port, stat);
    920         BCM_IF_ERROR_RETURN
    921             (BCMX_MPLS_DELETE_ERROR_CHECK(bcm_unit, tmp_rv, &rv));
    922     }
    923 
    924     return rv;
    925 }
    926 
    927 #endif  /* INCLUDE_L3 */
    928 
    929