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

hash.c (10764B)


      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:        hash.c
      8  * Purpose:     Greyhound2 hash table calculation routines
      9  * Requires:
     10  */
     11 
     12 #include <soc/drv.h>
     13 #include <soc/mem.h>
     14 #include <soc/hash.h>
     15 #include <shared/bsl.h>
     16 
     17 #if defined(BCM_GREYHOUND2_SUPPORT)
     18 
     19 #include <soc/greyhound2.h>
     20 
     21 STATIC int
     22 _soc_gh2_hash_generic_entry_to_key(
     23     int unit,
     24     void *entry,
     25     uint8 *key,
     26     soc_mem_t mem,
     27     soc_field_t *field_list)
     28 {
     29     soc_field_t field;
     30     int index, key_index, val_index, fval_index;
     31     int right_shift_count, left_shift_count;
     32     uint32 val[SOC_MAX_MEM_WORDS], fval[SOC_MAX_MEM_WORDS];
     33     int bits, val_bits, fval_bits;
     34     int8 field_length[16];
     35 
     36     val_bits = 0;
     37     for (index = 0; field_list[index] != INVALIDf; index++) {
     38         field = field_list[index];
     39         field_length[index] = soc_mem_field_length(unit, mem, field);
     40         val_bits += field_length[index];
     41     }
     42 
     43     switch (mem) {
     44         case L2Xm:
     45             val_bits = 63;
     46             break;
     47         case VLAN_XLATEm:
     48             val_bits = soc_mem_field_length(unit, mem, KEY_TYPEf) +
     49                        soc_mem_field_length(unit, mem, KEYf); /* 44 */
     50             break;
     51         case VLAN_MACm:
     52             val_bits = soc_mem_field_length(unit, mem, KEY_TYPEf) +
     53                        soc_mem_field_length(unit, mem, KEYf); /* 52 */
     54             break;
     55         case EGR_VLAN_XLATEm:
     56             val_bits = soc_mem_field_length(unit, mem, ENTRY_TYPEf) +
     57                        soc_mem_field_length(unit, mem, KEYf); /* 42 */
     58             break;
     59         default:
     60             break;
     61     }
     62 
     63     bits = (val_bits + 7) & ~0x7;
     64     sal_memset(val, 0, sizeof(val));
     65     val_bits = bits - val_bits;
     66     for (index = 0; field_list[index] != INVALIDf; index++) {
     67         field = field_list[index];
     68         soc_mem_field_get(unit, mem, entry, field, fval);
     69         fval_bits = field_length[index];
     70 
     71         val_index = val_bits >> 5;
     72         fval_index = 0;
     73         left_shift_count = val_bits & 0x1f;
     74         right_shift_count = 32 - left_shift_count;
     75         val_bits += fval_bits;
     76 
     77         if (left_shift_count) {
     78             for (; fval_bits > 0; fval_bits -= 32) {
     79                 val[val_index++] |= fval[fval_index] << left_shift_count;
     80                 val[val_index] |= fval[fval_index++] >> right_shift_count;
     81             }
     82         } else {
     83             for (; fval_bits > 0; fval_bits -= 32) {
     84                 val[val_index++] = fval[fval_index++];
     85             }
     86         }
     87     }
     88 
     89     key_index = 0;
     90     for (val_index = 0; val_bits > 0; val_index++) {
     91         for (right_shift_count = 0; right_shift_count < 32;
     92              right_shift_count += 8) {
     93             if (val_bits <= 0) {
     94                 break;
     95             }
     96             key[key_index++] = (val[val_index] >> right_shift_count) & 0xff;
     97             val_bits -= 8;
     98         }
     99     }
    100 
    101     if ((bits + 7) / 8 > key_index) {
    102         sal_memset(&key[key_index], 0, (bits + 7) / 8 - key_index);
    103     }
    104 
    105     return bits;
    106 }
    107 
    108 int
    109 soc_gh2_l2x_base_entry_to_key(int unit, uint32 *entry, uint8 *key)
    110 {
    111     int i;
    112     soc_field_t field_list[4];
    113 
    114     for (i=0; i < 4 ; i++) {
    115         field_list[i] = INVALIDf;
    116     }
    117 
    118     switch (soc_mem_field32_get(unit, L2Xm, entry, KEY_TYPEf)) {
    119         case GH2_L2_HASH_KEY_TYPE_BRIDGE:
    120             field_list[0] = KEY_TYPEf;
    121             field_list[1] = VLAN_IDf;
    122             field_list[2] = MAC_ADDRf;
    123             break;
    124         case GH2_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
    125             field_list[0] = KEY_TYPEf;
    126             field_list[1] = OVIDf;
    127             break;
    128         case GH2_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT:
    129             field_list[0] = KEY_TYPEf;
    130             field_list[1] = OVIDf;
    131             field_list[2] = IVIDf;
    132             break;
    133         case GH2_L2_HASH_KEY_TYPE_VFI:
    134         case GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST:
    135             field_list[0] = KEY_TYPEf;
    136             field_list[1] = VFIf;
    137             field_list[2] = MAC_ADDRf;
    138             break;
    139         case GH2_L2_HASH_KEY_TYPE_VIF:
    140             field_list[0] = VIF__KEYf;
    141             break;
    142         case GH2_L2_HASH_KEY_TYPE_PE_VID:
    143             field_list[0] = PE_VID__KEYf;
    144             break;
    145         default:
    146             return 0;
    147     }
    148 
    149     return _soc_gh2_hash_generic_entry_to_key(unit, entry, key,
    150                                               L2Xm, field_list);
    151 }
    152 
    153 int
    154 soc_gh2_vlan_xlate_base_entry_to_key(
    155     int unit,
    156     uint32 *entry,
    157     uint8 *key)
    158 {
    159     int i;
    160     soc_field_t field_list[5];
    161     soc_mem_t mem;
    162 
    163     for (i=0; i < 5; i++) {
    164         field_list[i] = INVALIDf;
    165     }
    166 
    167     field_list[0] = KEY_TYPEf;
    168     field_list[1] = GLPf;
    169     mem = VLAN_XLATEm;
    170 
    171     switch (soc_mem_field32_get(unit, VLAN_XLATEm, entry, KEY_TYPEf)) {
    172         case GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID:
    173         case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_IVID_OVID:
    174             field_list[2] = OVIDf;
    175             field_list[3] = IVIDf;
    176             field_list[4] = INVALIDf;
    177             break;
    178         case GH2_VLXLT_HASH_KEY_TYPE_OTAG:
    179         case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_OTAG:
    180             field_list[2] = OVIDf;
    181             field_list[3] = INVALIDf;
    182             break;
    183         case GH2_VLXLT_HASH_KEY_TYPE_ITAG:
    184         case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_ITAG:
    185             field_list[2] = IVIDf;
    186             field_list[3] = INVALIDf;
    187             break;
    188         case GH2_VLXLT_HASH_KEY_TYPE_OVID:
    189         case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_OVID:
    190             field_list[2] = OVIDf;
    191             field_list[3] = IVIDf;
    192             field_list[4] = INVALIDf;
    193             soc_mem_field32_set(unit, mem, entry, IVIDf, 0);
    194             break;
    195         case GH2_VLXLT_HASH_KEY_TYPE_IVID:
    196         case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_IVID:
    197             field_list[2] = OVIDf;
    198             field_list[3] = IVIDf;
    199             field_list[4] = INVALIDf;
    200             soc_mem_field32_set(unit, mem, entry, OVIDf, 0);
    201             break;
    202         case GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI:
    203             field_list[2] = OVIDf;
    204             field_list[3] = INVALIDf;
    205             soc_mem_field32_set(unit, mem, entry, OVIDf, 0);
    206             break;
    207         case GH2_VLXLT_HASH_KEY_TYPE_VNID:
    208             field_list[2] = VNIDf;
    209             field_list[3] = INVALIDf;
    210             break;
    211         case GH2_VLXLT_HASH_KEY_TYPE_VLAN_MAC:
    212             mem = VLAN_MACm;
    213             field_list[1] = MAC_ADDRf;
    214             field_list[2] = INVALIDf;
    215             break;
    216         case GH2_VLXLT_HASH_KEY_TYPE_HPAE:
    217             mem = VLAN_MACm;
    218             field_list[1] = MAC_IP_BIND__SIPf;
    219             field_list[2] = INVALIDf;
    220             break;
    221         default:
    222             return 0;
    223     }
    224 
    225     return _soc_gh2_hash_generic_entry_to_key(unit,
    226                                                            entry, key, mem, field_list);
    227 }
    228 
    229 uint32
    230 soc_gh2_vlan_xlate_hash(
    231     int unit,
    232     int hash_sel,
    233     int key_nbits,
    234     void *base_entry,
    235     uint8 *key)
    236 {
    237     uint32 rv = 0;
    238 
    239     /*
    240      * Cache bucket mask and shift amount for upper crc
    241      */
    242     if (SOC_CONTROL(unit)->hash_mask_vlan_mac == 0) {
    243         uint32 mask;
    244         int bits;
    245 
    246         /* 8 Entries per bucket */
    247         mask = soc_mem_index_max(unit, VLAN_MACm) >> 3;
    248         bits = 0;
    249         rv = 1;
    250         while (rv && (mask & rv)) {
    251             bits += 1;
    252             rv <<= 1;
    253         }
    254         SOC_CONTROL(unit)->hash_mask_vlan_mac = mask;
    255         SOC_CONTROL(unit)->hash_bits_vlan_mac = bits;
    256     }
    257 
    258     switch (hash_sel) {
    259         case FB_HASH_CRC16_UPPER:
    260             rv = soc_crc16b(key, key_nbits);
    261             rv >>= 16 - SOC_CONTROL(unit)->hash_bits_vlan_mac;
    262             break;
    263         case FB_HASH_CRC16_LOWER:
    264             rv = soc_crc16b(key, key_nbits);
    265             break;
    266         case FB_HASH_LSB:
    267             if (key_nbits == 0) {
    268                 return 0;
    269             }
    270             switch (soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, KEY_TYPEf)) {
    271                 case GH2_VLXLT_HASH_KEY_TYPE_IVID_OVID:
    272                 case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_IVID_OVID:
    273                     rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OVIDf);
    274                     break;
    275                 case GH2_VLXLT_HASH_KEY_TYPE_OTAG:
    276                 case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_OTAG:
    277                     rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OTAGf);
    278                     break;
    279                 case GH2_VLXLT_HASH_KEY_TYPE_ITAG:
    280                 case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_ITAG:
    281                     rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, ITAGf);
    282                     break;
    283                 case GH2_VLXLT_HASH_KEY_TYPE_OVID:
    284                 case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_OVID:
    285                     rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OVIDf);
    286                     break;
    287                 case GH2_VLXLT_HASH_KEY_TYPE_IVID:
    288                 case GH2_VLXLT_HASH_KEY_TYPE_PAYLOAD_IVID:
    289                     rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, IVIDf);
    290                     break;
    291                 case GH2_VLXLT_HASH_KEY_TYPE_PRI_CFI:
    292                     /* Use only the upper 4 bit of OTAG */
    293                     rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OTAGf) >> 12;
    294                     break;
    295                 case GH2_VLXLT_HASH_KEY_TYPE_VNID:
    296                     rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, VNIDf);
    297                     break;
    298                 case GH2_VLXLT_HASH_KEY_TYPE_VLAN_MAC:
    299                     rv = soc_mem_field32_get(unit, VLAN_MACm, base_entry,
    300                                              MAC__MAC_ADDRf);
    301                     break;
    302                 case GH2_VLXLT_HASH_KEY_TYPE_HPAE:
    303                     rv = soc_mem_field32_get(unit, VLAN_MACm, base_entry,
    304                                              MAC_IP_BIND__SIPf);
    305                     break;
    306                 default:
    307                     rv = 0;
    308                     break;
    309             }
    310             break;
    311         case FB_HASH_ZERO:
    312             rv = 0;
    313             break;
    314         case FB_HASH_CRC32_UPPER:
    315             rv = soc_crc32b(key, key_nbits);
    316             rv >>= 32 - SOC_CONTROL(unit)->hash_bits_vlan_mac;
    317             break;
    318         case FB_HASH_CRC32_LOWER:
    319             rv = soc_crc32b(key, key_nbits);
    320             break;
    321         default:
    322             LOG_ERROR(BSL_LS_SOC_HASH,
    323                       (BSL_META_U(unit,
    324                                   "soc_gh2_vlan_xlate_hash: invalid hash_sel %d\n"),
    325                        hash_sel));
    326             rv = 0;
    327             break;
    328     }
    329 
    330     return rv & SOC_CONTROL(unit)->hash_mask_vlan_mac;
    331 }
    332 #endif /* BCM_GREYHOUND2_SUPPORT */
    333