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


      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:    niv.c
      8  * Purpose: Implements bcm_niv_forward_* APIs for Triumph3.
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 
     14 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3)
     15 
     16 #include <soc/mem.h>
     17 #include <soc/ism_hash.h>
     18 
     19 #include <bcm/error.h>
     20 
     21 #include <bcm_int/common/multicast.h>
     22 #include <bcm_int/esw/triumph3.h>
     23 
     24 /*
     25  * Purpose:
     26  *	Create NIV Forwarding table entry
     27  * Parameters:
     28  *	unit - (IN) Device Number
     29  *	iv_fwd_entry - (IN) NIV Forwarding table entry
     30  */
     31 int
     32 bcm_tr3_niv_forward_add(int unit, bcm_niv_forward_t *iv_fwd_entry)
     33 {
     34     int rv = BCM_E_NONE;
     35     bcm_module_t mod_out;
     36     bcm_port_t port_out;
     37     bcm_trunk_t tgid_out;
     38     int id_out;
     39     l2_entry_1_entry_t l2_entry;
     40 
     41     if (iv_fwd_entry->name_space > 0xfff) {
     42         return BCM_E_PARAM;
     43     }
     44 
     45     if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) {
     46         if (iv_fwd_entry->virtual_interface_id > 0xfff) {
     47             return BCM_E_PARAM;
     48         }
     49 
     50         BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit,
     51                     iv_fwd_entry->dest_port,
     52                     &mod_out, &port_out, &tgid_out, &id_out));
     53         if (-1 != id_out) {
     54             return BCM_E_PARAM;
     55         }
     56 
     57         sal_memset(&l2_entry, 0, sizeof(l2_entry));
     58         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VALIDf, 1);
     59         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
     60                 SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF);
     61         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__NAMESPACEf,
     62                 iv_fwd_entry->name_space);
     63         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__Pf, 0);
     64         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__DST_VIFf,
     65                 iv_fwd_entry->virtual_interface_id);
     66         if (-1 != tgid_out) {
     67             BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, tgid_out));
     68             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__DEST_TYPEf, 1);
     69             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__TGIDf, tgid_out);
     70         } else {
     71             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__MODULE_IDf, mod_out);
     72             soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__PORT_NUMf, port_out);
     73         }
     74         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, STATIC_BITf, 1);
     75 
     76     } else { /* Multicast forward entry */
     77         if (iv_fwd_entry->virtual_interface_id > 0x3fff) {
     78             return BCM_E_PARAM;
     79         }
     80         if (!_BCM_MULTICAST_IS_L2(iv_fwd_entry->dest_multicast)) {
     81             return BCM_E_PARAM;
     82         }
     83 
     84         sal_memset(&l2_entry, 0, sizeof(l2_entry));
     85         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VALIDf, 1);
     86         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
     87                 SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF);
     88         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__NAMESPACEf,
     89                 iv_fwd_entry->name_space);
     90         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__Pf, 1);
     91         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__DST_VIFf,
     92                 iv_fwd_entry->virtual_interface_id);
     93         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__L2MC_PTRf,
     94                 _BCM_MULTICAST_ID_GET(iv_fwd_entry->dest_multicast));
     95         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, STATIC_BITf, 1);
     96     }
     97 
     98     soc_mem_lock(unit, L2_ENTRY_1m);
     99 
    100     if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_REPLACE)) {
    101         l2_entry_1_entry_t  l2x_lookup;
    102         int                 l2_index;
    103 
    104         /* See if the entry already exists */
    105         rv = soc_mem_generic_lookup(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, 0,
    106                                     &l2_entry, &l2x_lookup, &l2_index);
    107         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    108             soc_mem_unlock(unit, L2_ENTRY_1m);
    109             return rv;
    110         }
    111         if (BCM_SUCCESS(rv)) {
    112             soc_mem_unlock(unit, L2_ENTRY_1m);
    113             return BCM_E_EXISTS;
    114         }
    115 
    116         rv = soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
    117         if (SOC_FAILURE(rv)) {
    118             soc_mem_unlock(unit, L2_ENTRY_1m);
    119             return rv;
    120         }
    121     } else { /* Replace existing entry */
    122         rv = soc_mem_delete(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
    123         if (SOC_FAILURE(rv)) {
    124             soc_mem_unlock(unit, L2_ENTRY_1m);
    125             return rv;
    126         }
    127         rv = soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
    128         if (SOC_FAILURE(rv)) {
    129             soc_mem_unlock(unit, L2_ENTRY_1m);
    130             return rv;
    131         }
    132     }
    133 
    134     soc_mem_unlock(unit, L2_ENTRY_1m);
    135 
    136     return rv;
    137 }
    138 
    139 /*
    140  * Purpose:
    141  *	Delete NIV Forwarding table entry
    142  * Parameters:
    143  *      unit - (IN) Device Number
    144  *      iv_fwd_entry - (IN) NIV Forwarding table entry
    145  */
    146 int
    147 bcm_tr3_niv_forward_delete(int unit, bcm_niv_forward_t *iv_fwd_entry)
    148 {
    149     int rv = BCM_E_NONE;
    150     l2_entry_1_entry_t l2_entry;
    151 
    152     if (iv_fwd_entry->name_space > 0xfff) {
    153         return BCM_E_PARAM;
    154     }
    155 
    156     if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) {
    157         if (iv_fwd_entry->virtual_interface_id > 0xfff) {
    158             return BCM_E_PARAM;
    159         }
    160 
    161         sal_memset(&l2_entry, 0, sizeof(l2_entry));
    162         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
    163                 SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF);
    164         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__NAMESPACEf,
    165                 iv_fwd_entry->name_space);
    166         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__Pf, 0);
    167         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__DST_VIFf,
    168                 iv_fwd_entry->virtual_interface_id);
    169 
    170     } else { /* Multicast forward entry */
    171         if (iv_fwd_entry->virtual_interface_id > 0x3fff) {
    172             return BCM_E_PARAM;
    173         }
    174 
    175         sal_memset(&l2_entry, 0, sizeof(l2_entry));
    176         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
    177                 SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF);
    178         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__NAMESPACEf,
    179                 iv_fwd_entry->name_space);
    180         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__Pf, 1);
    181         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__DST_VIFf,
    182                 iv_fwd_entry->virtual_interface_id);
    183     }
    184 
    185     soc_mem_lock(unit, L2_ENTRY_1m);
    186     rv = soc_mem_delete(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &l2_entry);
    187     soc_mem_unlock(unit, L2_ENTRY_1m);
    188 
    189     return rv;
    190 }
    191 
    192 /*
    193  * Purpose:
    194  *	Delete all NIV Forwarding table entries
    195  * Parameters:
    196  *	unit - Device Number
    197  */
    198 int
    199 bcm_tr3_niv_forward_delete_all(int unit)
    200 {
    201     int rv = BCM_E_NONE;
    202     int seconds, enabled;
    203     l2_entry_1_entry_t match_mask;
    204     l2_entry_1_entry_t match_data;
    205     l2_bulk_entry_t l2_bulk;
    206     int match_mask_index, match_data_index;
    207     uint32 rval;
    208     int field_len;
    209 
    210     SOC_IF_ERROR_RETURN
    211         (SOC_FUNCTIONS(unit)->soc_age_timer_get(unit, &seconds, &enabled));
    212     if (enabled) {
    213         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_stop(unit));
    214     }
    215 
    216     soc_mem_lock(unit, L2_ENTRY_1m);
    217 
    218     /* Set match mask and data */
    219     sal_memset(&match_mask, 0, sizeof(match_mask));
    220     sal_memset(&match_data, 0, sizeof(match_data));
    221 
    222     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, VALIDf, 1);
    223     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, VALIDf, 1);
    224 
    225     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, WIDEf, 1);
    226     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, WIDEf, 0);
    227 
    228     field_len = soc_mem_field_length(unit, L2_ENTRY_1m, KEY_TYPEf);
    229     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_mask, KEY_TYPEf,
    230             (1 << field_len) - 1);
    231     soc_mem_field32_set(unit, L2_ENTRY_1m, &match_data, KEY_TYPEf,
    232             SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF);
    233 
    234     sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
    235     sal_memcpy(&l2_bulk, &match_mask, sizeof(match_mask));
    236     match_mask_index = 1;
    237     rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_mask_index, &l2_bulk);
    238     if (BCM_SUCCESS(rv)) {
    239         sal_memset(&l2_bulk, 0, sizeof(l2_bulk));
    240         sal_memcpy(&l2_bulk, &match_data, sizeof(match_data));
    241         match_data_index = 0;
    242         rv = WRITE_L2_BULKm(unit, MEM_BLOCK_ALL, match_data_index, &l2_bulk);
    243     }
    244 
    245     /* Set bulk control */
    246     rval = 0;
    247     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, L2_MOD_FIFO_RECORDf, 0);
    248     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ACTIONf, 1);
    249     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, BURST_ENTRIESf, 
    250                       _SOC_TR3_L2_BULK_BURST_MAX);
    251     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, ENTRY_WIDTHf, 0);
    252     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, NUM_ENTRIESf, 
    253                       soc_mem_index_count(unit, L2_ENTRY_1m));
    254     soc_reg_field_set(unit, L2_BULK_CONTROLr, &rval, EXTERNAL_L2_ENTRYf, 0);
    255     if (BCM_SUCCESS(rv)) {
    256         rv = WRITE_L2_BULK_CONTROLr(unit, rval);
    257     }
    258     if (BCM_SUCCESS(rv)) {
    259         rv = soc_tr3_l2_port_age(unit, L2_BULK_CONTROLr, INVALIDr);
    260     }
    261 
    262     soc_mem_unlock(unit, L2_ENTRY_1m);
    263 
    264     if(enabled) {
    265         SOC_IF_ERROR_RETURN(soc_tr3_l2_bulk_age_start(unit, seconds));
    266     }
    267 
    268     return rv;
    269 }
    270 
    271 /*
    272  * Purpose:
    273  *      Get NIV Forwarding table entry
    274  * Parameters:
    275  *      unit - (IN) Device Number
    276  *      iv_fwd_entry - (IN/OUT) NIV forwarding table info
    277  */
    278 int
    279 bcm_tr3_niv_forward_get(int unit, bcm_niv_forward_t *iv_fwd_entry)
    280 {
    281     int rv = BCM_E_NONE;
    282     l2_entry_1_entry_t l2_entry, l2_entry_out;
    283     int idx;
    284     _bcm_gport_dest_t dest;
    285     int l2mc_index;
    286 
    287     if (iv_fwd_entry->name_space > 0xfff) {
    288         return BCM_E_PARAM;
    289     }
    290 
    291     if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) {
    292         if (iv_fwd_entry->virtual_interface_id > 0xfff) {
    293             return BCM_E_PARAM;
    294         }
    295 
    296         sal_memset(&l2_entry, 0, sizeof(l2_entry));
    297         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
    298                 SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF);
    299         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__NAMESPACEf,
    300                 iv_fwd_entry->name_space);
    301         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__Pf, 0);
    302         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__DST_VIFf,
    303                 iv_fwd_entry->virtual_interface_id);
    304 
    305     } else { /* Multicast forward entry */
    306         if (iv_fwd_entry->virtual_interface_id > 0x3fff) {
    307             return BCM_E_PARAM;
    308         }
    309 
    310         sal_memset(&l2_entry, 0, sizeof(l2_entry));
    311         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, KEY_TYPEf,
    312                 SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF);
    313         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__NAMESPACEf,
    314                 iv_fwd_entry->name_space);
    315         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__Pf, 1);
    316         soc_L2_ENTRY_1m_field32_set(unit, &l2_entry, VIF__DST_VIFf,
    317                 iv_fwd_entry->virtual_interface_id);
    318     }
    319 
    320     soc_mem_lock(unit, L2_ENTRY_1m);
    321     rv = soc_mem_search(unit, L2_ENTRY_1m, MEM_BLOCK_ALL, &idx, &l2_entry,
    322             &l2_entry_out, 0);
    323     soc_mem_unlock(unit, L2_ENTRY_1m);
    324 
    325     if (SOC_SUCCESS(rv)) {
    326         if (!(iv_fwd_entry->flags & BCM_NIV_FORWARD_MULTICAST)) {
    327             if (soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
    328                         VIF__DEST_TYPEf)) {
    329                 dest.tgid = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
    330                     VIF__TGIDf);
    331                 dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
    332             } else {
    333                 dest.modid = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
    334                         VIF__MODULE_IDf);
    335                 dest.port = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
    336                         VIF__PORT_NUMf);
    337                 dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
    338             }
    339             BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest,
    340                         &(iv_fwd_entry->dest_port)));
    341         } else {
    342             l2mc_index = soc_L2_ENTRY_1m_field32_get(unit, &l2_entry_out,
    343                     VIF__L2MC_PTRf);
    344             _BCM_MULTICAST_GROUP_SET(iv_fwd_entry->dest_multicast,
    345                     _BCM_MULTICAST_TYPE_L2, l2mc_index);
    346         }
    347     }
    348 
    349     return rv;
    350 }
    351 
    352 /*
    353  * Purpose:
    354  *      Traverse all valid NIV forward entries and call the
    355  *      supplied callback routine.
    356  * Parameters:
    357  *      unit      - Device Number
    358  *      cb        - User callback function, called once per NIV forward entry.
    359  *      user_data - cookie
    360  * Returns:
    361  *      BCM_E_XXX
    362  */
    363 int
    364 bcm_tr3_niv_forward_traverse(int unit,
    365                              bcm_niv_forward_traverse_cb cb,
    366                              void *user_data)
    367 {
    368     int rv = BCM_E_NONE;
    369     int chunk_entries, chunk_bytes;
    370     uint8 *l2_tbl_chunk = NULL;
    371     int chunk_idx_min, chunk_idx_max, chunk_end;
    372     int ent_idx, mem_idx_min, mem_idx_max;
    373     l2_entry_1_entry_t *l2_entry;
    374     bcm_niv_forward_t iv_fwd_entry;
    375     int l2mc_index;
    376     _bcm_gport_dest_t dest;
    377 
    378     chunk_entries = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    379                                  L2_MEM_CHUNKS_DEFAULT);
    380     chunk_bytes = 4 * SOC_MEM_WORDS(unit, L2_ENTRY_1m) * chunk_entries;
    381     l2_tbl_chunk = soc_cm_salloc(unit, chunk_bytes, "niv forward traverse");
    382     if (NULL == l2_tbl_chunk) {
    383         return BCM_E_MEMORY;
    384     }
    385 
    386     mem_idx_min = soc_mem_index_min(unit, L2_ENTRY_1m);
    387     mem_idx_max = soc_mem_index_max(unit, L2_ENTRY_1m);
    388     for (chunk_idx_min = mem_idx_min; chunk_idx_min <= mem_idx_max; 
    389          chunk_idx_min += chunk_entries) {
    390         sal_memset(l2_tbl_chunk, 0, chunk_bytes);
    391 
    392         chunk_idx_max = chunk_idx_min + chunk_entries - 1;
    393         if (chunk_idx_max > mem_idx_max) {
    394             chunk_idx_max = mem_idx_max;
    395         }
    396 
    397         rv = soc_mem_read_range(unit, L2_ENTRY_1m, MEM_BLOCK_ANY,
    398                                 chunk_idx_min, chunk_idx_max, l2_tbl_chunk);
    399         if (SOC_FAILURE(rv)) {
    400             break;
    401         }
    402 
    403         chunk_end = (chunk_idx_max - chunk_idx_min);
    404         for (ent_idx = 0; ent_idx <= chunk_end; ent_idx++) {
    405             l2_entry = soc_mem_table_idx_to_pointer(unit, L2_ENTRY_1m,
    406                     l2_entry_1_entry_t *, l2_tbl_chunk, ent_idx);
    407 
    408             if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, VALIDf) == 0) {
    409                 continue;
    410             }
    411 
    412             if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, KEY_TYPEf) != 
    413                     SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF) {
    414                 continue;
    415             }
    416 
    417             bcm_niv_forward_t_init(&iv_fwd_entry);
    418 
    419             iv_fwd_entry.name_space = soc_L2_ENTRY_1m_field32_get(unit,
    420                     l2_entry, VIF__NAMESPACEf);
    421             iv_fwd_entry.virtual_interface_id = soc_L2_ENTRY_1m_field32_get(unit,
    422                     l2_entry, VIF__DST_VIFf);
    423 
    424             if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry, VIF__Pf)) {
    425                 /* Multicast NIV forward entry */
    426                 iv_fwd_entry.flags |= BCM_NIV_FORWARD_MULTICAST;
    427                 l2mc_index = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
    428                         VIF__L2MC_PTRf);
    429                 _BCM_MULTICAST_GROUP_SET(iv_fwd_entry.dest_multicast,
    430                         _BCM_MULTICAST_TYPE_L2, l2mc_index);
    431             } else {
    432                 if (soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
    433                             VIF__DEST_TYPEf)) {
    434                     dest.tgid = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
    435                             VIF__TGIDf);
    436                     dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
    437                 } else {
    438                     dest.modid = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
    439                             VIF__MODULE_IDf);
    440                     dest.port = soc_L2_ENTRY_1m_field32_get(unit, l2_entry,
    441                             VIF__PORT_NUMf);
    442                     dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
    443                 }
    444                 rv = _bcm_esw_gport_construct(unit, &dest,
    445                         &(iv_fwd_entry.dest_port));
    446                 if (BCM_FAILURE(rv)) {
    447                     break;
    448                 }
    449             }
    450 
    451             rv = cb(unit, &iv_fwd_entry, user_data);
    452             if (BCM_FAILURE(rv)) {
    453                 break;
    454             }
    455         }
    456         if (BCM_FAILURE(rv)) {
    457             break;
    458         }
    459     }
    460     soc_cm_sfree(unit, l2_tbl_chunk);
    461 
    462     return rv;
    463 }
    464 
    465 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */