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

niv.c (25166B)


      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  * Purpose: Implements ESW NIV APIs
      8  */
      9 
     10 #if defined(INCLUDE_L3)
     11 
     12 #include <soc/drv.h>
     13 #include <soc/scache.h>
     14 #include <soc/util.h>
     15 #include <soc/debug.h>
     16 
     17 #include <bcm/types.h>
     18 #include <bcm/error.h>
     19 #include <bcm/niv.h>
     20 
     21 #include <bcm_int/esw/mbcm.h>
     22 #include <bcm_int/esw/switch.h>
     23 #include <bcm_int/esw_dispatch.h>
     24 #include <bcm_int/esw/trident.h>
     25 #include <bcm_int/esw/triumph3.h>
     26 #include <bcm_int/esw/trident2.h>
     27 #include <bcm_int/esw/greyhound.h>
     28 
     29 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
     30     defined(INCLUDE_L3)
     31 /* Flag to check initialized status */
     32 STATIC int niv_initialized[BCM_MAX_NUM_UNITS];
     33 
     34 #define NIV_INIT(unit)                                    \
     35     do {                                                  \
     36         if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {  \
     37             return BCM_E_UNIT;                            \
     38         }                                                 \
     39         if (!niv_initialized[unit]) {                     \
     40             return BCM_E_INIT;                            \
     41         }                                                 \
     42     } while (0)
     43 
     44 /* 
     45  * NIV module lock
     46  */
     47 STATIC sal_mutex_t niv_mutex[BCM_MAX_NUM_UNITS] = {NULL};
     48 
     49 #define NIV_LOCK(unit) \
     50         sal_mutex_take(niv_mutex[unit], sal_mutex_FOREVER);
     51 
     52 #define NIV_UNLOCK(unit) \
     53         sal_mutex_give(niv_mutex[unit]); 
     54 
     55 /*
     56  * Function:
     57  *      _bcm_niv_check_init
     58  * Purpose:
     59  *      Check if NIV is initialized
     60  * Parameters:
     61  *      unit - SOC unit number
     62  * Returns:
     63  *      BCM_E_XXX
     64  */
     65 int
     66 _bcm_niv_check_init(int unit)
     67 {
     68     if (!niv_initialized[unit]) {
     69         return BCM_E_INIT;
     70     }
     71 
     72     return BCM_E_NONE;
     73 }
     74 
     75 /*
     76  * Function:
     77  *      _bcm_esw_niv_free_resources
     78  * Purpose:
     79  *      Free NIV resources
     80  * Parameters:
     81  *      unit - SOC unit number
     82  * Returns:
     83  *      Nothing
     84  */
     85 STATIC void
     86 _bcm_esw_niv_free_resources(int unit)
     87 {
     88     if (niv_mutex[unit]) {
     89         sal_mutex_destroy(niv_mutex[unit]);
     90         niv_mutex[unit] = NULL;
     91     } 
     92 }
     93 #endif /* (BCM_TRIDENT_SUPPORT||BCM_GREYHOUND_SUPPORT) && INCLUDE_L3 */
     94 
     95 #ifdef BCM_WARM_BOOT_SUPPORT
     96 
     97 #define BCM_WB_VERSION_1_0     SOC_SCACHE_VERSION(1,0)
     98 #define BCM_WB_VERSION_1_1     SOC_SCACHE_VERSION(1,1)
     99 #define BCM_WB_VERSION_1_2     SOC_SCACHE_VERSION(1,2)
    100 #define BCM_WB_VERSION_1_3     SOC_SCACHE_VERSION(1,3)
    101 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_3
    102 
    103 /*
    104  * Function:
    105  *      _bcm_esw_niv_sync
    106  * Purpose:
    107  *      Record NIV module persistent info for Level 2 Warm Boot
    108  * Parameters:
    109  *      unit - StrataSwitch unit number.
    110  * Returns:
    111  *      BCM_E_XXX
    112  */
    113 int
    114 _bcm_esw_niv_sync(int unit)
    115 {
    116 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    117     defined(INCLUDE_L3)
    118     if (soc_feature(unit, soc_feature_niv)) {
    119         if (!SOC_IS_GREYHOUND(unit) && !SOC_IS_HURRICANE3(unit) &&
    120             !SOC_IS_GREYHOUND2(unit)) {
    121 #if defined(BCM_TRIDENT_SUPPORT)
    122             soc_scache_handle_t scache_handle;
    123             uint8               *scache_ptr;
    124     
    125             SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_NIV, 0);
    126             BCM_IF_ERROR_RETURN
    127                 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    128                                          0, &scache_ptr,
    129                                          BCM_WB_DEFAULT_VERSION, NULL));
    130     
    131             BCM_IF_ERROR_RETURN(bcm_trident_niv_sync(unit, &scache_ptr));
    132 #endif
    133         }
    134     }
    135 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    136 
    137     return BCM_E_NONE;
    138 }
    139 
    140 #endif /* BCM_WARM_BOOT_SUPPORT */
    141 
    142 /*
    143  * Function:
    144  *      bcm_esw_niv_init
    145  * Purpose:
    146  *      Initialize NIV module
    147  * Parameters:
    148  *      unit - SOC unit number
    149  * Returns:
    150  *      BCM_E_XXX
    151  */
    152 int
    153 bcm_esw_niv_init(int unit)
    154 {
    155 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    156      defined(INCLUDE_L3)
    157     if (soc_feature(unit, soc_feature_niv)) {
    158 
    159 #ifdef BCM_WARM_BOOT_SUPPORT
    160         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    161             SOC_IS_GREYHOUND2(unit))) {
    162 #if defined(BCM_TRIDENT_SUPPORT)			
    163             uint32              required_scache_size;
    164             soc_scache_handle_t scache_handle;
    165             uint8               *scache_ptr;
    166             int                 rv = BCM_E_NONE;
    167 
    168             /* Get the required scache size */
    169             BCM_IF_ERROR_RETURN(bcm_trident_niv_required_scache_size_get(unit,
    170                         &required_scache_size));
    171 
    172             /* Allocate required scache */
    173             SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_NIV, 0);
    174             if (required_scache_size > 0) {
    175                 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 
    176                         (0 == SOC_WARM_BOOT(unit)), required_scache_size,
    177                         &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    178                 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    179                     return rv;
    180                 }
    181             }
    182 #endif /* BCM_TRIDENT_SUPPORT */
    183         }
    184 #endif /* BCM_WARM_BOOT_SUPPORT */
    185 
    186         if (niv_initialized[unit]) {
    187             BCM_IF_ERROR_RETURN(bcm_esw_niv_cleanup(unit));
    188         }
    189 
    190         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    191             SOC_IS_GREYHOUND2(unit))) {
    192 #if defined(BCM_TRIDENT_SUPPORT)
    193             BCM_IF_ERROR_RETURN(bcm_trident_niv_init(unit));
    194 #endif
    195         }
    196 
    197         if (niv_mutex[unit] == NULL) {
    198             niv_mutex[unit] = sal_mutex_create("niv mutex");
    199             if (niv_mutex[unit] == NULL) {
    200                 bcm_esw_niv_cleanup(unit);
    201                 return BCM_E_MEMORY;
    202             }
    203         }
    204 
    205 #ifdef BCM_WARM_BOOT_SUPPORT
    206         if (SOC_WARM_BOOT(unit)) {
    207             if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    208                 SOC_IS_GREYHOUND2(unit))) {
    209 #if defined(BCM_TRIDENT_SUPPORT)			
    210                 int rv = BCM_E_NONE;
    211                 rv = bcm_trident_niv_reinit(unit);
    212                 if (BCM_FAILURE(rv)) {
    213                     (void) bcm_esw_niv_cleanup(unit);
    214                     return rv;
    215                 }
    216 #endif /* BCM_TRIDENT_SUPPORT */
    217             }
    218         }
    219 #endif /* BCM_WARM_BOOT_SUPPORT */
    220 
    221         niv_initialized[unit] = TRUE;
    222 
    223         return BCM_E_NONE;
    224     }
    225 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    226 
    227     return BCM_E_UNAVAIL;
    228 }
    229 
    230 /* Function:
    231  *      bcm_esw_niv_cleanup
    232  * Purpose:
    233  *      Detach NIV module, clear all HW states
    234  * Parameters:
    235  *      unit - SOC unit number
    236  * Returns:
    237  *      BCM_E_XXX
    238  */
    239 int
    240 bcm_esw_niv_cleanup(int unit)
    241 {
    242 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    243      defined(INCLUDE_L3)
    244     if (soc_feature(unit, soc_feature_niv)) {
    245 
    246         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    247             SOC_IS_GREYHOUND2(unit))) {
    248 #if defined(BCM_TRIDENT_SUPPORT)
    249             BCM_IF_ERROR_RETURN(bcm_trident_niv_cleanup(unit));
    250 #endif
    251         }
    252 
    253         _bcm_esw_niv_free_resources(unit);
    254 
    255         niv_initialized[unit] = FALSE;
    256 
    257         return BCM_E_NONE;
    258     }
    259 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    260 
    261     return BCM_E_UNAVAIL;
    262 }
    263 
    264 /* Function:
    265  *      bcm_esw_niv_port_add
    266  * Purpose:
    267  *      Create a NIV port
    268  * Parameters:
    269  *      unit - (IN) SOC unit Number
    270  *      niv_port - (IN/OUT) NIV port information (OUT : niv_port_id)
    271  * Returns:
    272  *      BCM_E_XXX
    273  */
    274 int bcm_esw_niv_port_add(int unit, bcm_niv_port_t *niv_port)
    275 {
    276     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    277         SOC_IS_GREYHOUND2(unit)) {
    278         return BCM_E_UNAVAIL;
    279     }
    280 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    281     if (soc_feature(unit, soc_feature_niv)) {
    282 
    283         int rv;
    284 
    285         NIV_INIT(unit);
    286 
    287         NIV_LOCK(unit);
    288 
    289         rv = bcm_trident_niv_port_add(unit, niv_port);
    290 
    291         NIV_UNLOCK(unit);
    292 
    293         return rv;
    294     }
    295 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    296 
    297     return BCM_E_UNAVAIL;
    298 }
    299   
    300 /* Function:
    301  *      bcm_esw_niv_port_delete
    302  * Purpose:
    303  *      Delete a NIV port
    304  * Parameters:
    305  *      unit - (IN) SOC unit number
    306  *      niv_port_id - (IN) NIV port ID
    307  * Returns:
    308  *      BCM_E_XXX
    309  */
    310 int bcm_esw_niv_port_delete(int unit, bcm_gport_t niv_port_id)
    311 {
    312     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    313         SOC_IS_GREYHOUND2(unit)) {
    314         return BCM_E_UNAVAIL;
    315     }
    316 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    317     if (soc_feature(unit, soc_feature_niv)) {
    318         int rv;
    319 
    320         NIV_INIT(unit);
    321 
    322         NIV_LOCK(unit);
    323 
    324         rv = bcm_trident_niv_port_delete(unit, niv_port_id);
    325 
    326         NIV_UNLOCK(unit);
    327 
    328         return rv;
    329     }
    330 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    331 
    332     return BCM_E_UNAVAIL;
    333 }
    334 
    335 /* Function:
    336  *      bcm_esw_niv_port_delete_all
    337  * Purpose:
    338  *      Delete all NIV ports
    339  * Parameters:
    340  *      unit - (IN) SOC unit number
    341  * Returns:
    342  *      BCM_E_XXX
    343  */
    344 int bcm_esw_niv_port_delete_all(int unit)
    345 {
    346     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    347         SOC_IS_GREYHOUND2(unit)) {
    348         return BCM_E_UNAVAIL;
    349     }
    350 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    351     if (soc_feature(unit, soc_feature_niv)) {
    352         int rv;
    353 
    354         NIV_INIT(unit);
    355 
    356         NIV_LOCK(unit);
    357 
    358         rv = bcm_trident_niv_port_delete_all(unit);
    359 
    360         NIV_UNLOCK(unit);
    361 
    362         return rv;
    363     }
    364 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    365 
    366     return BCM_E_UNAVAIL;
    367 }
    368 
    369 /* Function:
    370  *      bcm_esw_niv_port_get
    371  * Purpose:
    372  *      Get info about a NIV port
    373  * Parameters:
    374  *      unit - (IN) SOC unit number
    375  *      niv_port - (IN/OUT) NIV port information (IN : niv_port_id)
    376  * Returns:
    377  *      BCM_E_XXX
    378  */
    379 int bcm_esw_niv_port_get(int unit, bcm_niv_port_t *niv_port)
    380 {
    381     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    382         SOC_IS_GREYHOUND2(unit)) {
    383         return BCM_E_UNAVAIL;
    384     }
    385 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    386     if (soc_feature(unit, soc_feature_niv)) {
    387         int rv;
    388 
    389         NIV_INIT(unit);
    390 
    391         NIV_LOCK(unit);
    392 
    393         rv = bcm_trident_niv_port_get(unit, niv_port);
    394 
    395         NIV_UNLOCK(unit);
    396 
    397         return rv;
    398     }
    399 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    400 
    401     return BCM_E_UNAVAIL;
    402 }
    403 
    404 /* Function:
    405  *      bcm_esw_niv_port_traverse
    406  * Purpose:
    407  *      Traverse all valid NIV port entries and call the
    408  *      supplied callback routine.
    409  * Parameters:
    410  *      unit      - Device Number
    411  *      cb        - User callback function, called once per NIV Port entry.
    412  *      user_data - cookie
    413  * Returns:
    414  *      BCM_E_XXX
    415  */
    416 int
    417 bcm_esw_niv_port_traverse(int unit,
    418                           bcm_niv_port_traverse_cb cb,
    419                           void *user_data)
    420 {
    421     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    422         SOC_IS_GREYHOUND2(unit)) {
    423         return BCM_E_UNAVAIL;
    424     }
    425 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    426     if (soc_feature(unit, soc_feature_niv)) {
    427         int rv;
    428 
    429         NIV_INIT(unit);
    430 
    431         NIV_LOCK(unit);
    432 
    433         rv = bcm_trident_niv_port_traverse(unit, cb, user_data);
    434 
    435         NIV_UNLOCK(unit);
    436 
    437         return rv;
    438     }
    439 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    440 
    441     return BCM_E_UNAVAIL;
    442 }
    443 
    444 /* Function:
    445  *      bcm_esw_niv_forward_add
    446  * Purpose:
    447  *      Create a NIV forwarding table entry
    448  * Parameters:
    449  *      unit - (IN) Device Number
    450  *      iv_fwd_entry - (IN) NIV forwarding table entry
    451  * Returns:
    452  *      BCM_E_XXX
    453  */
    454 int
    455 bcm_esw_niv_forward_add(int unit, bcm_niv_forward_t *iv_fwd_entry)
    456 {
    457 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    458      defined(INCLUDE_L3)
    459     if (soc_feature(unit, soc_feature_niv)) {
    460         int rv = BCM_E_NONE;
    461 
    462         NIV_INIT(unit);
    463 
    464         NIV_LOCK(unit);
    465 
    466 #ifdef BCM_TRIUMPH3_SUPPORT
    467         if (SOC_IS_TRIUMPH3(unit)) {
    468             rv = bcm_tr3_niv_forward_add(unit, iv_fwd_entry);
    469         } else
    470 #endif /* BCM_TRIUMPH3_SUPPORT */
    471 #ifdef BCM_GREYHOUND_SUPPORT
    472         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    473             SOC_IS_GREYHOUND2(unit)) {
    474             rv = bcm_gh_niv_forward_add(unit, iv_fwd_entry);
    475         } else
    476 #endif /* BCM_GREYHOUND_SUPPORT */
    477         {
    478 #ifdef BCM_TRIDENT_SUPPORT
    479             rv = bcm_trident_niv_forward_add(unit, iv_fwd_entry);
    480 #endif /* BCM_TRIDENT_SUPPORT */
    481         }
    482 
    483         NIV_UNLOCK(unit);
    484 
    485         return rv;
    486     }
    487 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    488 
    489     return BCM_E_UNAVAIL;
    490 }
    491   
    492 /* Function:
    493  *      bcm_esw_niv_forward_delete
    494  * Purpose:
    495  *	Delete a NIV forwarding table entry
    496  * Parameters:
    497  *      unit - (IN) Device Number
    498  *      iv_fwd_entry - (IN) NIV forwarding table entry
    499  * Returns:
    500  *      BCM_E_XXX
    501  */
    502 int
    503 bcm_esw_niv_forward_delete(int unit, bcm_niv_forward_t *iv_fwd_entry)
    504 {
    505 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    506      defined(INCLUDE_L3)
    507     if (soc_feature(unit, soc_feature_niv)) {
    508         int rv = BCM_E_NONE;
    509 
    510         NIV_INIT(unit);
    511 
    512         NIV_LOCK(unit);
    513 
    514 #ifdef BCM_TRIUMPH3_SUPPORT
    515         if (SOC_IS_TRIUMPH3(unit)) {
    516             rv = bcm_tr3_niv_forward_delete(unit, iv_fwd_entry);
    517         } else
    518 #endif /* BCM_TRIUMPH3_SUPPORT */
    519 #ifdef BCM_GREYHOUND_SUPPORT
    520         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    521             SOC_IS_GREYHOUND2(unit)) {
    522             rv = bcm_gh_niv_forward_delete(unit, iv_fwd_entry);
    523         } else
    524 #endif /* BCM_GREYHOUND_SUPPORT */
    525         {
    526 #ifdef BCM_TRIDENT_SUPPORT
    527             rv = bcm_trident_niv_forward_delete(unit, iv_fwd_entry);
    528 #endif /* BCM_TRIDENT_SUPPORT */
    529         }
    530 
    531         NIV_UNLOCK(unit);
    532 
    533         return rv;
    534     }
    535 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    536 
    537     return BCM_E_UNAVAIL;
    538 }
    539 
    540 /* Function:
    541  *      bcm_esw_niv_forward_delete_all
    542  * Purpose:
    543  *      Delete all NIV Forwarding table entries
    544  * Parameters:
    545  *      unit - Device Number
    546  * Returns:
    547  *      BCM_E_XXX
    548  */
    549 int
    550 bcm_esw_niv_forward_delete_all(int unit)
    551 {
    552 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    553      defined(INCLUDE_L3)
    554     if (soc_feature(unit, soc_feature_niv)) {
    555         int rv = BCM_E_NONE;
    556 
    557         NIV_INIT(unit);
    558 
    559         NIV_LOCK(unit);
    560 
    561 #ifdef BCM_TRIUMPH3_SUPPORT
    562         if (SOC_IS_TRIUMPH3(unit)) {
    563             rv = bcm_tr3_niv_forward_delete_all(unit);
    564         } else
    565 #endif /* BCM_TRIUMPH3_SUPPORT */
    566 #ifdef BCM_GREYHOUND_SUPPORT
    567         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    568             SOC_IS_GREYHOUND2(unit)) {
    569             rv = bcm_gh_niv_forward_delete_all(unit);
    570         } else
    571 #endif /* BCM_GREYHOUND_SUPPORT */
    572         {
    573 #ifdef BCM_TRIDENT_SUPPORT
    574             rv = bcm_trident_niv_forward_delete_all(unit);
    575 #endif /* BCM_TRIDENT_SUPPORT */
    576         }
    577 
    578         NIV_UNLOCK(unit);
    579 
    580         return rv;
    581     }
    582 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    583 
    584     return BCM_E_UNAVAIL;
    585 }
    586 
    587 /* Function:
    588  *      bcm_esw_niv_forward_get
    589  * Purpose:
    590  *      Get NIV forwarding table entry
    591  * Parameters:
    592  *      unit - (IN) Device Number
    593  *      iv_fwd_entry - (IN/OUT) NIV forwarding table info
    594  * Returns:
    595  *      BCM_E_XXX
    596  */
    597 int
    598 bcm_esw_niv_forward_get(int unit, bcm_niv_forward_t *iv_fwd_entry)
    599 {
    600 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    601      defined(INCLUDE_L3)
    602     if (soc_feature(unit, soc_feature_niv)) {
    603         int rv = BCM_E_NONE;
    604 
    605         NIV_INIT(unit);
    606 
    607         NIV_LOCK(unit);
    608 
    609 #ifdef BCM_TRIUMPH3_SUPPORT
    610         if (SOC_IS_TRIUMPH3(unit)) {
    611             rv = bcm_tr3_niv_forward_get(unit, iv_fwd_entry);
    612         } else
    613 #endif /* BCM_TRIUMPH3_SUPPORT */
    614 #ifdef BCM_GREYHOUND_SUPPORT
    615         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    616             SOC_IS_GREYHOUND2(unit)) {
    617             rv = bcm_gh_niv_forward_get(unit, iv_fwd_entry);
    618         } else
    619 #endif /* BCM_GREYHOUND_SUPPORT */
    620         {
    621 #ifdef BCM_TRIDENT_SUPPORT
    622             rv = bcm_trident_niv_forward_get(unit, iv_fwd_entry);
    623 #endif /* BCM_TRIDENT_SUPPORT */
    624         }
    625 
    626         NIV_UNLOCK(unit);
    627 
    628         return rv;
    629     }
    630 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    631 
    632     return BCM_E_UNAVAIL;
    633 }
    634 
    635 /* Function:
    636  *      bcm_esw_niv_forward_traverse
    637  * Purpose:
    638  *      Traverse all valid NIV forward entries and call the
    639  *      supplied callback routine.
    640  * Parameters:
    641  *      unit      - Device Number
    642  *      cb        - User callback function, called once per NIV forward entry.
    643  *      user_data - cookie
    644  * Returns:
    645  *      BCM_E_XXX
    646  */
    647 int
    648 bcm_esw_niv_forward_traverse(int unit,
    649                              bcm_niv_forward_traverse_cb cb,
    650                              void *user_data)
    651 {
    652 #if (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)) && \
    653      defined(INCLUDE_L3)
    654     if (soc_feature(unit, soc_feature_niv)) {
    655         int rv = BCM_E_NONE;
    656 
    657         NIV_INIT(unit);
    658 
    659         NIV_LOCK(unit);
    660 
    661 #ifdef BCM_TRIUMPH3_SUPPORT
    662         if (SOC_IS_TRIUMPH3(unit)) {
    663             rv = bcm_tr3_niv_forward_traverse(unit, cb, user_data);
    664         } else
    665 #endif /* BCM_TRIUMPH3_SUPPORT */
    666 #ifdef BCM_GREYHOUND_SUPPORT
    667         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    668             SOC_IS_GREYHOUND2(unit)) {
    669             rv = bcm_gh_niv_forward_traverse(unit, cb, user_data);
    670         } else
    671 #endif /* BCM_GREYHOUND_SUPPORT */
    672         {
    673 #ifdef BCM_TRIDENT_SUPPORT
    674             rv = bcm_trident_niv_forward_traverse(unit, cb, user_data);
    675 #endif /* BCM_TRIDENT_SUPPORT */
    676         }
    677 
    678         NIV_UNLOCK(unit);
    679 
    680         return rv;
    681     }
    682 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    683 
    684     return BCM_E_UNAVAIL;
    685 }
    686 
    687 /*
    688  * Function:
    689  *      _bcm_esw_niv_port_source_vp_lag_set
    690  * Purpose:
    691  *      Set source VP LAG for a NIV virtual port.
    692  * Parameters:
    693  *      unit - (IN) SOC unit number. 
    694  *      gport - (IN) NIV virtual port GPORT ID. 
    695  *      vp_lag_vp - (IN) VP representing the VP LAG. 
    696  * Returns:
    697  *      BCM_X_XXX
    698  */
    699 int
    700 _bcm_esw_niv_port_source_vp_lag_set(int unit, bcm_gport_t gport,
    701         int vp_lag_vp)
    702 {
    703 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
    704     if (soc_feature(unit, soc_feature_niv) &&
    705         soc_feature(unit, soc_feature_vp_lag)) {
    706         int rv;
    707 
    708         NIV_INIT(unit);
    709 
    710         NIV_LOCK(unit);
    711 
    712         rv = bcm_td2_niv_port_source_vp_lag_set(unit, gport, vp_lag_vp);
    713 
    714         NIV_UNLOCK(unit);
    715 
    716         return rv;
    717     }
    718 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    719 
    720     return BCM_E_UNAVAIL;
    721 }
    722 
    723 /*
    724  * Function:
    725  *      _bcm_esw_niv_port_source_vp_lag_clear
    726  * Purpose:
    727  *      Clear source VP LAG for a NIV virtual port.
    728  * Parameters:
    729  *      unit - (IN) SOC unit number. 
    730  *      gport - (IN) NIV virtual port GPORT ID. 
    731  *      vp_lag_vp - (IN) VP representing the VP LAG. 
    732  * Returns:
    733  *      BCM_X_XXX
    734  */
    735 int
    736 _bcm_esw_niv_port_source_vp_lag_clear(int unit, bcm_gport_t gport,
    737         int vp_lag_vp)
    738 {
    739 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
    740     if (soc_feature(unit, soc_feature_niv) &&
    741         soc_feature(unit, soc_feature_vp_lag)) {
    742         int rv;
    743 
    744         NIV_INIT(unit);
    745 
    746         NIV_LOCK(unit);
    747 
    748         rv = bcm_td2_niv_port_source_vp_lag_clear(unit, gport, vp_lag_vp);
    749 
    750         NIV_UNLOCK(unit);
    751 
    752         return rv;
    753     }
    754 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    755 
    756     return BCM_E_UNAVAIL;
    757 }
    758 
    759 /*
    760  * Function:
    761  *      _bcm_esw_niv_port_source_vp_lag_get
    762  * Purpose:
    763  *      Get source VP LAG for a NIV virtual port.
    764  * Parameters:
    765  *      unit - (IN) SOC unit number. 
    766  *      gport - (IN) NIV virtual port GPORT ID. 
    767  *      vp_lag_vp - (OUT) VP representing the VP LAG. 
    768  * Returns:
    769  *      BCM_X_XXX
    770  */
    771 int
    772 _bcm_esw_niv_port_source_vp_lag_get(int unit, bcm_gport_t gport,
    773         int *vp_lag_vp)
    774 {
    775 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3)
    776     if (soc_feature(unit, soc_feature_niv) &&
    777         soc_feature(unit, soc_feature_vp_lag)) {
    778         int rv;
    779 
    780         NIV_INIT(unit);
    781 
    782         NIV_LOCK(unit);
    783 
    784         rv = bcm_td2_niv_port_source_vp_lag_get(unit, gport, vp_lag_vp);
    785 
    786         NIV_UNLOCK(unit);
    787 
    788         return rv;
    789     }
    790 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */
    791 
    792     return BCM_E_UNAVAIL;
    793 }
    794 
    795 /* Function:
    796  *      bcm_esw_niv_egress_add
    797  * Purpose:
    798  *      Add a NIV egress object to a NIV port
    799  * Parameters:
    800  *      unit - (IN) SOC unit Number
    801  *      niv_port - (IN) NIV port
    802  *      niv_egress - (IN/OUT) NIV egress object, the egress_if field is output.
    803  * Returns:
    804  *      BCM_E_XXX
    805  */
    806 int
    807 bcm_esw_niv_egress_add(
    808     int unit, 
    809     bcm_gport_t niv_port, 
    810     bcm_niv_egress_t *niv_egress)
    811 {
    812     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    813         SOC_IS_GREYHOUND2(unit)) {
    814         return BCM_E_UNAVAIL;
    815     }
    816 
    817 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    818     if (soc_feature(unit, soc_feature_niv)) {
    819         int rv;
    820 
    821         NIV_INIT(unit);
    822 
    823         NIV_LOCK(unit);
    824 
    825         rv = bcm_trident_niv_egress_add(unit, niv_port, niv_egress);
    826 
    827         NIV_UNLOCK(unit);
    828 
    829         return rv;
    830     }
    831 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    832 
    833     return BCM_E_UNAVAIL;
    834 }
    835 
    836 /* Function:
    837  *      bcm_esw_niv_egress_delete
    838  * Purpose:
    839  *      Delete a NIV egress object from a NIV port
    840  * Parameters:
    841  *      unit - (IN) SOC unit Number
    842  *      niv_port - (IN) NIV port
    843  *      niv_egress - (IN) NIV egress object
    844  * Returns:
    845  *      BCM_E_XXX
    846  */
    847 int
    848 bcm_esw_niv_egress_delete(
    849     int unit, 
    850     bcm_gport_t niv_port, 
    851     bcm_niv_egress_t *niv_egress)
    852 {
    853     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    854         SOC_IS_GREYHOUND2(unit)) {
    855         return BCM_E_UNAVAIL;
    856     }
    857 
    858 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    859     if (soc_feature(unit, soc_feature_niv)) {
    860         int rv;
    861 
    862         NIV_INIT(unit);
    863 
    864         NIV_LOCK(unit);
    865 
    866         rv = bcm_trident_niv_egress_delete(unit, niv_port, niv_egress);
    867 
    868         NIV_UNLOCK(unit);
    869 
    870         return rv;
    871     }
    872 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    873 
    874     return BCM_E_UNAVAIL;
    875 }
    876 
    877 /* Function:
    878  *      bcm_esw_niv_egress_set
    879  * Purpose:
    880  *      Set an array of NIV egress objects for a NIV port
    881  * Parameters:
    882  *      unit - (IN) SOC unit Number
    883  *      niv_port - (IN) NIV port
    884  *      array_size - (IN) Number of NIV egress objects
    885  *      niv_egress_array - (IN/OUT) Array of NIV egress objects. Each NIV
    886  *                                  egress structure's egress_if field is
    887  *                                  an output.
    888  * Returns:
    889  *      BCM_E_XXX
    890  */
    891 int
    892 bcm_esw_niv_egress_set(
    893     int unit, 
    894     bcm_gport_t niv_port, 
    895     int array_size, 
    896     bcm_niv_egress_t *niv_egress_array)
    897 {
    898     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    899         SOC_IS_GREYHOUND2(unit)) {
    900         return BCM_E_UNAVAIL;
    901     }
    902 
    903 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    904     if (soc_feature(unit, soc_feature_niv)) {
    905         int rv;
    906 
    907         NIV_INIT(unit);
    908 
    909         NIV_LOCK(unit);
    910 
    911         rv = bcm_trident_niv_egress_set(unit, niv_port, array_size,
    912                 niv_egress_array);
    913 
    914         NIV_UNLOCK(unit);
    915 
    916         return rv;
    917     }
    918 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    919 
    920     return BCM_E_UNAVAIL;
    921 }
    922 
    923 /* Function:
    924  *      bcm_esw_niv_egress_get
    925  * Purpose:
    926  *      Get an array of NIV egress objects for a NIV port
    927  * Parameters:
    928  *      unit - (IN) SOC unit Number
    929  *      niv_port - (IN) NIV port
    930  *      array_size - (IN) Size of NIV egress objects array.
    931  *      niv_egress_array - (OUT) Array of NIV egress objects.
    932  *      count - (OUT) Number of NIV egress objects returned.
    933  * Returns:
    934  *      BCM_E_XXX
    935  */
    936 int 
    937 bcm_esw_niv_egress_get(
    938     int unit, 
    939     bcm_gport_t niv_port, 
    940     int array_size, 
    941     bcm_niv_egress_t *niv_egress_array, 
    942     int *count)
    943 {
    944     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
    945         SOC_IS_GREYHOUND2(unit)) {
    946         return BCM_E_UNAVAIL;
    947     }
    948 
    949 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
    950     if (soc_feature(unit, soc_feature_niv)) {
    951         int rv;
    952 
    953         NIV_INIT(unit);
    954 
    955         NIV_LOCK(unit);
    956 
    957         rv = bcm_trident_niv_egress_get(unit, niv_port, array_size,
    958                 niv_egress_array, count);
    959 
    960         NIV_UNLOCK(unit);
    961 
    962         return rv;
    963     }
    964 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
    965 
    966    return BCM_E_UNAVAIL;
    967 }
    968 
    969 /* Function:
    970  *      bcm_esw_niv_egress_delete_all
    971  * Purpose:
    972  *      Delete all NIV egress objects from a NIV port
    973  * Parameters:
    974  *      unit - (IN) SOC unit Number
    975  *      niv_port - (IN) NIV port
    976  * Returns:
    977  *      BCM_E_XXX
    978  */
    979 int 
    980 bcm_esw_niv_egress_delete_all(
    981     int unit, 
    982     bcm_gport_t niv_port)
    983 {
    984     return bcm_esw_niv_egress_set(unit, niv_port, 0, NULL);
    985 }
    986 
    987 
    988 #ifndef BCM_SW_STATE_DUMP_DISABLE
    989 /*
    990  * Function:
    991  *     _bcm_niv_sw_dump
    992  * Purpose:
    993  *     Displays NIV information maintained by software.
    994  * Parameters:
    995  *     unit - Device unit number
    996  * Returns:
    997  *     None
    998  */
    999 void
   1000 _bcm_niv_sw_dump(int unit)
   1001 {
   1002 #if defined(BCM_TRIDENT_SUPPORT) && defined(INCLUDE_L3)
   1003     if (soc_feature(unit, soc_feature_niv)) {
   1004         if (!(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   1005             SOC_IS_GREYHOUND2(unit))) {
   1006             bcm_trident_niv_sw_dump(unit);
   1007         }
   1008     }
   1009 #endif /* BCM_TRIDENT_SUPPORT && INCLUDE_L3 */
   1010 
   1011     return;
   1012 }
   1013 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   1014 
   1015 #else   /* INCLUDE_L3 */
   1016 int bcm_esw_niv_not_empty;
   1017 #endif  /* INCLUDE_L3 */
   1018