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

tunnel.c (13253B)


      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:        tunnel.c
      8  *
      9  * Provides:
     10  *      soc_internal_tunnel_entry_ins
     11  *
     12  * Requires:
     13  */
     14 
     15 #include <shared/bsl.h>
     16 
     17 #include <soc/mem.h>
     18 #include <soc/hash.h>
     19 #include <soc/drv.h>
     20 #include "pcid.h"
     21 #include "mem.h"
     22 #include "cmicsim.h"
     23 #ifdef BCM_TOMAHAWK3_SUPPORT
     24 #include <soc/tomahawk3.h>
     25 
     26 #ifdef BCM_XGS_SWITCH_SUPPORT
     27 #ifdef BCM_FIREBOLT_SUPPORT
     28 /*
     29  * Tomahawk3 L3_TUNNEL Table Simulation
     30  *
     31  * The L3_TUNNEL table is hashed.
     32  *
     33  * There are 3 view of the same
     34  *      L3_TUNNEL, L3_TUNNEL_2, L3_TUNNEL_4
     35  */
     36 enum {
     37         ENT3f,
     38         ENT2f,
     39         ENT1f,
     40         ENT0f
     41 } soc_L3_TUNNEL_DUMMYm_ftype;
     42 
     43 static soc_field_info_t soc_L3_TUNNEL_DUMMYm_fields[] = {
     44     { ENT3f, 92, 276, SOCF_LE },
     45     { ENT2f, 92, 184, SOCF_LE },
     46     { ENT1f, 92, 92, SOCF_LE },
     47     { ENT0f, 92, 0, SOCF_LE },
     48 };
     49 static soc_mem_info_t l3_tunnel_minfo = {
     50                         /* mem            L3_TUNNELXXXm */
     51                         /* flags       */ 0,
     52                         /* cmp_fn      */ _soc_mem_cmp_undef,
     53                         /* *null_entry */ _soc_mem_entry_null_zeroes,
     54                         /* index_min   */ 0,
     55                         /* index_max   */ 0,
     56                         /* minblock    */ 0,
     57                         /* maxblock    */ 0,
     58                         /* blocks      */ 0,
     59                         /* blocks_hi   */ 0,
     60                         /* base        */ 0,
     61                         /* gran        */ 1,
     62                         /* bytes       */ 46,
     63                         /* nFields     */ 4, /* Used */
     64                         /* *fields     */ soc_L3_TUNNEL_DUMMYm_fields, /* Used*/
     65                         };
     66 
     67 int
     68 soc_internal_tunnel_entry_size_get(pcid_info_t *pcid_info, void *entry,
     69                                  soc_mem_t *mem, int *num_vbits)
     70 {
     71     int unit = pcid_info->unit;
     72 
     73     if (SOC_IS_TOMAHAWK3(unit) &&
     74         SOC_MEM_FIELD_VALID(unit, L3_TUNNEL_SINGLEm, KEY_TYPEf)) {
     75         int key_type;
     76 
     77         key_type = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm,
     78                                        entry, KEY_TYPEf);
     79         switch (key_type) {
     80             case TH3_TUNNEL_HASH_KEY_TYPE_MPLS:
     81                 *num_vbits = 1;
     82                 *mem = L3_TUNNEL_SINGLEm;
     83                 break;
     84 
     85             case TH3_TUNNEL_HASH_KEY_TYPE_V4:
     86                 *num_vbits = 2;
     87                 *mem = L3_TUNNEL_DOUBLEm;
     88                 break;
     89 
     90             case TH3_TUNNEL_HASH_KEY_TYPE_V6:
     91                 *num_vbits = 4;
     92                 *mem = L3_TUNNEL_QUADm;
     93                 break;
     94 
     95             default:
     96                 return -1;
     97         }
     98         return 0;
     99     } else {
    100         return -1;
    101     }
    102 }
    103 
    104 STATIC void
    105 soc_internal_tunnel_bank_map_get(pcid_info_t *pcid_info, uint32 *bank_map,
    106                                int *bank_start, int *bank_inc,
    107                                int *do_first_fit)
    108 {
    109     *bank_start = 0;
    110     *bank_inc = 1;
    111     *bank_map = soc_feature(pcid_info->unit, soc_feature_dual_hash)? 0x3 : 0x1;
    112 
    113     if (do_first_fit) {
    114         *do_first_fit = FALSE;
    115     }
    116 }
    117 
    118 STATIC void
    119 soc_internal_tunnel_bank_size_get(pcid_info_t *pcid_info, int bank,
    120                                 int *entries_per_bank, int *entries_per_row,
    121                                 int *entries_per_bucket, int *bank_base,
    122                                 int *bucket_offset)
    123 {
    124     /*
    125      * entry index =
    126      *     bank_base + bucket * entries_per_row + bucket_offset + slot;
    127      */
    128     if (SOC_IS_TOMAHAWK3(pcid_info->unit)) {
    129         soc_tomahawk3_hash_bank_info_get(pcid_info->unit, L3_TUNNEL_SINGLEm,
    130                                              bank, entries_per_bank,
    131                                              entries_per_row,
    132                                              entries_per_bucket,
    133                                              bank_base, bucket_offset);
    134     } else {
    135         /*
    136          * first half of entries (slot 0) in each bucket are for bank 0
    137          * the other half of entries (slot 1) in each bucket are for bank 1
    138          */
    139         if (entries_per_bank != NULL) {
    140             *entries_per_bank =
    141                 soc_mem_index_count(pcid_info->unit, L3_TUNNEL_SINGLEm) / 2;
    142         }
    143         *entries_per_row = SOC_L3_TUNNEL_BUCKET_SIZE;
    144         *entries_per_bucket = *entries_per_row / 2;
    145         *bank_base = 0;
    146         *bucket_offset = bank * *entries_per_bucket;
    147     }
    148 }
    149 
    150 STATIC int
    151 soc_internal_tunnel_hash(pcid_info_t * pcid_info, uint8 bank, void *entry)
    152 {
    153     int     index = 0;
    154 
    155     if (SOC_IS_TOMAHAWK3(pcid_info->unit)) {
    156         
    157         index = soc_tomahawk3_tunnel_bank_entry_hash(
    158                     pcid_info->unit, bank, (uint32*) entry);
    159     }
    160 
    161     return index;
    162 }
    163 
    164 int
    165 soc_internal_tunnel_entry_ins(pcid_info_t *pcid_info, uint8 inv_bank_map,
    166                             void *entry, uint32 *result)
    167 {
    168     uint32          tmp[SOC_MAX_MEM_WORDS];
    169     uint32          ent[SOC_MAX_MEM_WORDS];
    170     int             rv;
    171     uint32          bank_map;
    172     int             bank, entries_per_bank, bank_start, bank_inc, free_bank;
    173     int             bucket, entries_per_row, bank_base, free_bucket;
    174     int             slot, entries_per_bucket, bucket_offset, free_slot;
    175     int             sub_slot;
    176     int             index, free_index;
    177     int             first_free_slot, free_slot_count, do_first_fit;
    178     int             best_free_slot_count, best_entries_per_bank;
    179     int             num_vbits;
    180     int             validslot_cnt;
    181     soc_mem_t       mem;
    182     int             ss_field[] = {ENT0f, ENT1f, ENT2f, ENT3f};
    183     int             unit = pcid_info->unit;
    184     schan_genresp_t *genresp = (schan_genresp_t *) result;
    185     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result;
    186     int             blk;
    187     soc_block_t     sblk;
    188     uint8           acc_type;
    189     uint32          addr;
    190 
    191     LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "L3_TUNNEL Insert\n")));
    192 
    193     rv = soc_internal_tunnel_entry_size_get(pcid_info, entry, &mem, &num_vbits);
    194     if (rv < 0) {
    195         return rv;
    196     }
    197 
    198     sal_memset(ent, 0, SOC_MAX_MEM_WORDS * sizeof(uint32));
    199     sal_memset(tmp, 0, SOC_MAX_MEM_WORDS * sizeof(uint32));
    200 
    201     blk = SOC_MEM_BLOCK_ANY(unit, L3_TUNNEL_SINGLEm);
    202     sblk = SOC_BLOCK2SCH(unit, blk);
    203 
    204     free_index = -1;
    205 
    206     soc_internal_tunnel_bank_map_get(
    207         pcid_info, &bank_map, &bank_start, &bank_inc, &do_first_fit);
    208     bank_map &= ~inv_bank_map;
    209 
    210     best_free_slot_count = 0;
    211     /* only 2 banks supported*/
    212     for (bank = bank_start; bank_map != 0; bank += bank_inc) {
    213         if (!(bank_map & (1 << bank))) {
    214             continue;
    215         }
    216         bank_map &= ~(1 << bank);
    217 
    218         soc_internal_tunnel_bank_size_get(pcid_info, bank, &entries_per_bank,
    219                                         &entries_per_row, &entries_per_bucket,
    220                                         &bank_base, &bucket_offset);
    221         bucket = soc_internal_tunnel_hash(pcid_info, bank, entry);
    222 
    223         /*
    224         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    225                 (BSL_META_U(unit, "bucket:%d, bank#%d, entry/bank:%d,"
    226                         " entry/row:%d, entry/bucket:%d, base:%d, offset:%d\n"),
    227                             bucket, bank, entries_per_bank, entries_per_row,
    228                                 entries_per_bucket, bank_base, bucket_offset));
    229         */
    230 
    231         free_slot_count = 0;
    232         first_free_slot = -1;
    233 
    234         for (slot = 0; slot < entries_per_bucket; slot += num_vbits) {
    235             validslot_cnt = 0;
    236             for (sub_slot = 0; sub_slot < num_vbits; sub_slot++) {
    237                 index = bank_base + bucket * entries_per_row + bucket_offset +
    238                     slot + sub_slot;
    239                 addr = soc_mem_addr_get(unit, L3_TUNNEL_SINGLEm, 0, blk, index,
    240                                         &acc_type);
    241                 soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr,
    242                                                tmp);
    243                 if (soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, tmp, BASE_VALIDf)) {
    244                     soc_meminfo_field_set(mem, &l3_tunnel_minfo, ent,
    245                                           ss_field[sub_slot], tmp);
    246                     validslot_cnt++;
    247                 }
    248             }
    249 
    250             if (validslot_cnt == num_vbits) {
    251                 if (_soc_mem_cmp_l3_tunnel(unit, entry, ent) == 0) {
    252                     if (num_vbits > 0) {
    253                         index /= num_vbits;
    254                     }
    255                     addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type);
    256 
    257                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    258                                 (BSL_META_U(unit,
    259                                             "write sblk %d acc_type %d bank %d "
    260                                             "bucket %d, slot %d, index %d\n"),
    261                                  sblk, acc_type, bank, bucket, slot, index));
    262 
    263                     /* Overwrite the existing entry */
    264                     soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    265                                                     addr, entry);
    266 
    267                     if (soc_feature(unit, soc_feature_generic_table_ops)) {
    268                         /* Copy old entry immediately after response word */
    269                         memcpy(&result[1], ent,
    270                                soc_mem_entry_bytes(unit, mem));
    271                         result[0] = 0;
    272                         if (soc_feature(unit, soc_feature_new_sbus_format) &&
    273                             !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    274                             genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    275                             genresp_v2->index = index;
    276                         } else {
    277                             genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    278                             genresp->index = index;
    279                         }
    280                     }
    281                     PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    282 
    283                     return 0;
    284                 }
    285             } else if (validslot_cnt == 0) {
    286                 free_slot_count++;
    287                 if (first_free_slot == -1) {
    288                     first_free_slot = slot;
    289                 }
    290             }
    291         }
    292         if (free_slot_count > 0) {
    293             if (do_first_fit) {
    294                 if (free_index != -1) {
    295                     continue;
    296                 }
    297             } else {
    298                 if (free_slot_count < best_free_slot_count) {
    299                     continue;
    300                 } else if (free_slot_count == best_free_slot_count) {
    301                     if (entries_per_bank < best_entries_per_bank) {
    302                         continue;
    303                     } else if (entries_per_bank == best_entries_per_bank) {
    304                         if (free_index != -1 && bank > free_bank) {
    305                             continue;
    306                         }
    307                     }
    308                 }
    309                 best_free_slot_count = free_slot_count;
    310                 best_entries_per_bank = entries_per_bank;
    311             }
    312             free_index = (index + 1 - entries_per_bucket + first_free_slot) /
    313                 num_vbits;
    314             free_bank = bank;
    315             free_bucket = bucket;
    316             free_slot = first_free_slot;
    317         }
    318     }
    319 
    320     /* Find first unused slot in bucket */
    321     if (free_index != -1) {
    322         index = free_index;
    323         addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type);
    324 
    325         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    326                     (BSL_META_U(unit,
    327                                 "write sblk %d acc_type %d bank %d bucket %d, "
    328                                 "slot %d, index %d\n"),
    329                      sblk, acc_type, free_bank, free_bucket, free_slot, index));
    330 
    331         /* Write the entry */
    332         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
    333                                         entry);
    334 
    335         if (soc_feature(unit, soc_feature_generic_table_ops)) {
    336             result[0] = 0;
    337             if (soc_feature(unit, soc_feature_new_sbus_format) &&
    338                 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    339                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    340                 genresp_v2->index = index;
    341             } else {
    342                 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    343                 genresp->index = index;
    344             }
    345         }
    346         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    347 
    348         return 0;
    349     }
    350 
    351     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    352                 (BSL_META_U(unit,
    353                             "Bucket full\n")));
    354     if (soc_feature(unit, soc_feature_generic_table_ops)) {
    355         result[0] = 0;
    356         if (soc_feature(unit, soc_feature_new_sbus_format) &&
    357             !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    358             genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
    359         } else {
    360             genresp->type = SCHAN_GEN_RESP_TYPE_FULL;
    361         }
    362     }
    363     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    364 
    365     return 0;
    366 }
    367 
    368 #endif /* BCM_FIREBOLT_SUPPORT */
    369 #endif /* BCM_XGS_SWITCH_SUPPORT */
    370 #endif /* BCM_TOMAHAWK3_SUPPORT */