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


      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  * Hash table calculation routines
      8  */
      9 
     10 #include <assert.h>
     11 
     12 #include <sal/types.h>
     13 #include <sal/core/thread.h>
     14 #include <shared/bsl.h>
     15 #include <soc/util.h>
     16 #include <soc/hash.h>
     17 #include <soc/mem.h>
     18 #include <soc/drv.h>
     19 #include <soc/debug.h>
     20 #ifdef BCM_KATANA2_SUPPORT
     21 #include <soc/katana2.h>
     22 #endif
     23 #ifdef BCM_GREYHOUND_SUPPORT
     24 #include <soc/greyhound.h>
     25 #endif
     26 #ifdef BCM_TRIDENT2_SUPPORT
     27 #include <soc/trident2.h>
     28 #endif /* BCM_TRIDENT2_SUPPORT */
     29 #ifdef BCM_TRIDENT3_SUPPORT
     30 #include <soc/trident3.h>
     31 #endif /* BCM_TRIDENT3_SUPPORT */
     32 #ifdef BCM_HURRICANE3_SUPPORT
     33 #include <soc/hurricane3.h>
     34 #endif
     35 #ifdef BCM_TOMAHAWK_SUPPORT
     36 #include <soc/tomahawk.h>
     37 #endif
     38 #ifdef BCM_APACHE_SUPPORT
     39 #include <soc/apache.h>
     40 #endif
     41 #ifdef BCM_TOMAHAWK3_SUPPORT
     42 #include <soc/tomahawk3.h>
     43 #endif
     44 #ifdef BCM_MONTEREY_SUPPORT
     45 #include <soc/monterey.h>
     46 #endif
     47 #ifdef BCM_GREYHOUND2_SUPPORT
     48 #include <soc/greyhound2.h>
     49 #endif /* BCM_GREYHOUND2_SUPPORT */
     50 #ifdef BCM_HELIX5_SUPPORT
     51 #include <soc/helix5.h>
     52 #endif /* BCM_HELIX5_SUPPORT */
     53 
     54 #ifdef BCM_XGS_SWITCH_SUPPORT
     55 uint32
     56 soc_crc32b(uint8 *data, int data_nbits)
     57 {
     58     uint32 rv;
     59     rv = _shr_crc32b(0, data, data_nbits);
     60     rv = _shr_bit_rev_by_byte_word32(rv);
     61     return rv;
     62 }
     63 
     64 uint16
     65 soc_crc16b(uint8 *data, int data_nbits)
     66 {
     67     uint16 rv;
     68     rv = _shr_crc16b(0, data, data_nbits);
     69     rv = _shr_bit_rev16(rv);
     70     return rv;
     71 }
     72 
     73 int 
     74 soc_dual_hash_recurse_depth_get(int unit, soc_mem_t mem)
     75 {
     76     switch(mem) {
     77     case L2Xm: return SOC_DUAL_HASH_MOVE_MAX_L2X(unit) ? 
     78         SOC_DUAL_HASH_MOVE_MAX_L2X(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
     79 #if defined(BCM_TRX_SUPPORT)
     80     case MPLS_ENTRYm: return SOC_DUAL_HASH_MOVE_MAX_MPLS(unit) ?
     81          SOC_DUAL_HASH_MOVE_MAX_MPLS(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
     82     case EGR_VLAN_XLATEm:
     83     case EGR_VLAN_XLATE_1_SINGLEm:
     84     case EGR_VLAN_XLATE_2_SINGLEm:
     85     case EGR_VLAN_XLATE_1_DOUBLEm:
     86     case EGR_VLAN_XLATE_2_DOUBLEm:
     87          return SOC_DUAL_HASH_MOVE_MAX_EGRESS_VLAN(unit) ?
     88                 SOC_DUAL_HASH_MOVE_MAX_EGRESS_VLAN(unit) :
     89                 SOC_DUAL_HASH_MOVE_MAX(unit);
     90     case VLAN_XLATEm:
     91     case VLAN_XLATE_1_SINGLEm:
     92     case VLAN_XLATE_2_SINGLEm:
     93     case VLAN_XLATE_1_DOUBLEm:
     94     case VLAN_XLATE_2_DOUBLEm:
     95          return SOC_DUAL_HASH_MOVE_MAX_VLAN(unit) ?
     96                 SOC_DUAL_HASH_MOVE_MAX_VLAN(unit) :
     97                 SOC_DUAL_HASH_MOVE_MAX(unit);
     98 #endif
     99 #if defined(BCM_RAVEN_SUPPORT)
    100     case VLAN_MACm: return SOC_DUAL_HASH_MOVE_MAX_VLAN(unit) ?
    101          SOC_DUAL_HASH_MOVE_MAX_VLAN(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    102 #endif
    103 #if defined(INCLUDE_L3)
    104     case L3_DEFIPm:
    105     case L3_ENTRY_ONLYm:
    106     case L3_ENTRY_IPV4_UNICASTm:
    107     case L3_ENTRY_IPV4_MULTICASTm:
    108     case L3_ENTRY_IPV6_UNICASTm:
    109     case L3_ENTRY_IPV6_MULTICASTm: return SOC_DUAL_HASH_MOVE_MAX_L3X(unit) ?
    110          SOC_DUAL_HASH_MOVE_MAX_L3X(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    111 #endif
    112 #if defined(BCM_TRIUMPH3_SUPPORT)
    113     case AXP_WRX_WCDm: return SOC_DUAL_HASH_MOVE_MAX_WLAN_CLIENT(unit) ?
    114          SOC_DUAL_HASH_MOVE_MAX_WLAN_CLIENT(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    115     case AXP_WRX_SVP_ASSIGNMENTm: return SOC_DUAL_HASH_MOVE_MAX_WLAN_PORT(unit) ?
    116          SOC_DUAL_HASH_MOVE_MAX_WLAN_PORT(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    117     case FT_SESSIONm: return SOC_DUAL_HASH_MAX_FT_SESSION_IPV4(unit) ?
    118          SOC_DUAL_HASH_MAX_FT_SESSION_IPV4(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    119     case FT_SESSION_IPV6m: return SOC_DUAL_HASH_MAX_FT_SESSION_IPV6(unit) ?
    120         SOC_DUAL_HASH_MAX_FT_SESSION_IPV6(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    121 #endif
    122 #if defined(BCM_TRIDENT2_SUPPORT)
    123     case ING_VP_VLAN_MEMBERSHIPm: return SOC_DUAL_HASH_MOVE_MAX_ING_VP_VLAN_MEMBER(unit) ?
    124          SOC_DUAL_HASH_MOVE_MAX_ING_VP_VLAN_MEMBER(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    125     case EGR_VP_VLAN_MEMBERSHIPm: return SOC_DUAL_HASH_MOVE_MAX_EGR_VP_VLAN_MEMBER(unit) ?
    126          SOC_DUAL_HASH_MOVE_MAX_EGR_VP_VLAN_MEMBER(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    127     case ING_DNAT_ADDRESS_TYPEm: return SOC_DUAL_HASH_MOVE_MAX_ING_DNAT_ADDRESS_TYPE(unit) ?
    128          SOC_DUAL_HASH_MOVE_MAX_ING_DNAT_ADDRESS_TYPE(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    129     case L2_ENDPOINT_IDm: return SOC_DUAL_HASH_MOVE_MAX_L2_ENDPOINT_ID(unit) ?
    130          SOC_DUAL_HASH_MOVE_MAX_L2_ENDPOINT_ID(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    131     case ENDPOINT_QUEUE_MAPm: return SOC_DUAL_HASH_MOVE_MAX_ENDPOINT_QUEUE_MAP(unit) ?
    132          SOC_DUAL_HASH_MOVE_MAX_ENDPOINT_QUEUE_MAP(unit) : SOC_DUAL_HASH_MOVE_MAX(unit);
    133 #endif /* BCM_TRIDENT2_SUPPORT */
    134     default: return SOC_DUAL_HASH_MOVE_MAX(unit);
    135     }
    136 }
    137 
    138 int 
    139 soc_multi_hash_recurse_depth_get(int unit, soc_mem_t mem)
    140 {
    141     switch(mem) {
    142     case L2Xm:
    143     case L2_ENTRY_1m:
    144     case L2_ENTRY_2m:
    145         return SOC_MULTI_HASH_MOVE_MAX_L2(unit) ?
    146                 SOC_MULTI_HASH_MOVE_MAX_L2(unit) :
    147                 SOC_MULTI_HASH_MOVE_MAX(unit);
    148 #if defined(INCLUDE_L3)
    149     case L3_ENTRY_1m:
    150     case L3_ENTRY_2m:
    151     case L3_ENTRY_4m: 
    152     case L3_DEFIPm:
    153     case L3_ENTRY_ONLYm:
    154     case L3_ENTRY_IPV4_UNICASTm:
    155     case L3_ENTRY_IPV4_MULTICASTm:
    156     case L3_ENTRY_IPV6_UNICASTm:
    157     case L3_ENTRY_IPV6_MULTICASTm:
    158 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    159     case L3_ENTRY_SINGLEm:
    160     case L3_ENTRY_DOUBLEm:
    161     case L3_ENTRY_QUADm:
    162 #endif
    163         return SOC_MULTI_HASH_MOVE_MAX_L3(unit) ?
    164                 SOC_MULTI_HASH_MOVE_MAX_L3(unit) :
    165                 SOC_MULTI_HASH_MOVE_MAX(unit);
    166 #if defined(BCM_TOMAHAWK3_SUPPORT)
    167     case L3_TUNNEL_SINGLEm:
    168     case L3_TUNNEL_DOUBLEm:
    169     case L3_TUNNEL_QUADm:
    170         return SOC_MULTI_HASH_MOVE_MAX_L3_TUNNEL(unit) ?
    171                 SOC_MULTI_HASH_MOVE_MAX_L3_TUNNEL(unit) :
    172                 SOC_MULTI_HASH_MOVE_MAX(unit);
    173 #endif /* BCM_TOMAHAWK3_SUPPORT */
    174 #endif /* INCLUDE_L3 */
    175     case EXACT_MATCH_2m:
    176     case EXACT_MATCH_2_PIPE0m:
    177     case EXACT_MATCH_2_PIPE1m:
    178     case EXACT_MATCH_2_PIPE2m:
    179     case EXACT_MATCH_2_PIPE3m:
    180     case EXACT_MATCH_4m:
    181     case EXACT_MATCH_4_PIPE0m:
    182     case EXACT_MATCH_4_PIPE1m:
    183     case EXACT_MATCH_4_PIPE2m:
    184     case EXACT_MATCH_4_PIPE3m: return SOC_MULTI_HASH_MOVE_MAX_FPEM(unit) ?
    185          SOC_MULTI_HASH_MOVE_MAX_FPEM(unit) : SOC_MULTI_HASH_MOVE_MAX(unit);
    186     case MPLS_ENTRYm:
    187     case MPLS_ENTRY_1m:
    188     case MPLS_ENTRY_EXTDm:
    189 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    190     case MPLS_ENTRY_SINGLEm:
    191 #endif
    192         return SOC_MULTI_HASH_MOVE_MAX_MPLS(unit) ?
    193                 SOC_MULTI_HASH_MOVE_MAX_MPLS(unit) :
    194                 SOC_MULTI_HASH_MOVE_MAX(unit);
    195     case VLAN_XLATEm:
    196     case VLAN_XLATE_1m:
    197     case VLAN_XLATE_EXTDm:
    198         return SOC_MULTI_HASH_MOVE_MAX_VLAN(unit) ?
    199                 SOC_MULTI_HASH_MOVE_MAX_VLAN(unit) :
    200                 SOC_MULTI_HASH_MOVE_MAX(unit);
    201 #ifdef BCM_TRIDENT3_SUPPORT
    202     case VLAN_XLATE_1_SINGLEm:
    203     case VLAN_XLATE_1_DOUBLEm:
    204         return SOC_MULTI_HASH_MOVE_MAX_VLAN_1(unit) ?
    205                 SOC_MULTI_HASH_MOVE_MAX_VLAN_1(unit) :
    206                 SOC_MULTI_HASH_MOVE_MAX(unit);
    207     case VLAN_XLATE_2_SINGLEm:
    208     case VLAN_XLATE_2_DOUBLEm:
    209         return SOC_MULTI_HASH_MOVE_MAX_VLAN_2(unit) ?
    210                 SOC_MULTI_HASH_MOVE_MAX_VLAN_2(unit) :
    211                 SOC_MULTI_HASH_MOVE_MAX(unit);
    212 #endif
    213     case EP_VLAN_XLATE_1m:
    214     case EGR_VLAN_XLATEm:
    215         return SOC_MULTI_HASH_MOVE_MAX_EGRESS_VLAN(unit) ?
    216                 SOC_MULTI_HASH_MOVE_MAX_EGRESS_VLAN(unit) :
    217                 SOC_MULTI_HASH_MOVE_MAX(unit);
    218 #ifdef BCM_TRIDENT3_SUPPORT
    219     case EGR_VLAN_XLATE_1_SINGLEm:
    220     case EGR_VLAN_XLATE_1_DOUBLEm:
    221         return SOC_MULTI_HASH_MOVE_MAX_EGRESS_VLAN_1(unit) ?
    222                 SOC_MULTI_HASH_MOVE_MAX_EGRESS_VLAN_1(unit) :
    223                 SOC_MULTI_HASH_MOVE_MAX(unit);
    224     case EGR_VLAN_XLATE_2_SINGLEm:
    225     case EGR_VLAN_XLATE_2_DOUBLEm:
    226         return SOC_MULTI_HASH_MOVE_MAX_EGRESS_VLAN_2(unit) ?
    227                 SOC_MULTI_HASH_MOVE_MAX_EGRESS_VLAN_2(unit) :
    228                 SOC_MULTI_HASH_MOVE_MAX(unit);
    229 #endif
    230     default:
    231         return SOC_MULTI_HASH_MOVE_MAX(unit);
    232     }
    233 }
    234 
    235 /*
    236  * Implement the crc32 routines so that the bit ordering matches Draco
    237  */
    238 
    239 uint32
    240 soc_draco_crc32(uint8 *data, int data_size)
    241 {
    242     uint32 rv;
    243     rv = _shr_crc32(0, data, data_size);
    244     rv = _shr_bit_rev_by_byte_word32(rv);
    245     return rv;
    246 }
    247 
    248 uint16
    249 soc_draco_crc16(uint8 *data, int data_size)
    250 {
    251     uint16 rv;
    252     rv = _shr_crc16(0, data, data_size);
    253     rv = _shr_bit_rev16(rv);
    254     return rv;
    255 }
    256 
    257 /*
    258  * And now some routines to deal with details
    259  */
    260 
    261 void
    262 soc_draco_l2x_base_entry_to_key(int unit, l2x_entry_t *entry, uint8 *key)
    263 {
    264     sal_mac_addr_t mac;
    265     int vid;
    266 
    267     soc_L2Xm_mac_addr_get(unit, entry, MAC_ADDRf, mac);
    268 
    269     vid = soc_L2Xm_field32_get(unit, entry, VLAN_IDf);
    270 
    271     soc_draco_l2x_param_to_key(mac, vid, key);
    272 }
    273 
    274 void
    275 soc_draco_l2x_param_to_key(sal_mac_addr_t mac, int vid, uint8 *key)
    276 {
    277     int ix;
    278 
    279     key[0] = 0;
    280     for (ix = 0; ix < 6; ix++) {
    281         key[ix + 1] = (mac[5 - ix] >> 4) & 0x0f;
    282         key[ix + 0] |= (mac[5 - ix] << 4) & 0xf0;
    283     }
    284 
    285     key[6] |= (vid << 4) & 0xf0;
    286     key[7] = (vid >> 4) & 0xff;
    287 }
    288 
    289 void
    290 soc_draco_l3x_param_to_key(ip_addr_t ip, ip_addr_t src_ip,
    291                            uint16 vid, uint8 *key)
    292 {
    293     int ix;
    294 
    295     for (ix = 0; ix < 4; ix++) {
    296         key[ix] = (ip >> (8*ix)) & 0xff;
    297         key[ix + 4] = (src_ip >> (8*ix)) & 0xff;
    298     }
    299 
    300     key[8] = vid & 0xff;
    301     key[9] = (vid >> 8) & 0x0f;
    302 }
    303 
    304 #ifdef BCM_XGS3_SWITCH_SUPPORT
    305 /*
    306  * Get the XGS3 ECMP hash result based on HW
    307  */
    308 uint32 
    309 soc_xgs3_l3_ecmp_hash(int unit, soc_xgs3_ecmp_hash_t *data)
    310 {
    311     uint8    key[SOC_MAX_MEM_BYTES];
    312     uint8    use_l4_port = 0;
    313     uint8    use_dip;
    314     uint8    hash_sel;
    315     uint8    crc_val_shift;
    316     uint32   crc_val;
    317     uint32   regval;
    318     int      index;
    319     int      idx; 
    320     uint8    udf;
    321     uint16   mask;
    322 
    323     if (NULL == data) {
    324         return (SOC_E_PARAM);
    325     }
    326 
    327     SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &regval));
    328     hash_sel = soc_reg_field_get(unit, HASH_CONTROLr,
    329                                  regval, ECMP_HASH_SELf);
    330 
    331     /* If hash is disabled return 0. */
    332     if (FB_HASH_ZERO == hash_sel) {
    333         return 0;
    334     }
    335 
    336     /* If hash is based on LSB of sip. */
    337     if (FB_HASH_LSB == hash_sel) {
    338         if(data->v6) {
    339             crc_val = data->sip6[0] & 0x1f;
    340         }  else {
    341             crc_val = data->sip & 0x1f;
    342         }
    343         return ((crc_val & 0x1F) % (data->ecmp_count + 1));
    344     }
    345 
    346     use_dip = soc_reg_field_get(unit, HASH_CONTROLr,
    347                                  regval, ECMP_HASH_USE_DIPf);
    348 
    349     udf = soc_reg_field_get(unit, HASH_CONTROLr,
    350                             regval, ECMP_HASH_UDFf);
    351 
    352     if (SOC_REG_FIELD_VALID(unit, HASH_CONTROLr, USE_TCP_UDP_PORTSf)) {
    353         use_l4_port = soc_reg_field_get(unit, HASH_CONTROLr,
    354                                         regval, USE_TCP_UDP_PORTSf);
    355     } 
    356 
    357     /* Initialize key structure. */
    358     sal_memset(key, 0, SOC_MAX_MEM_BYTES * sizeof (uint8));
    359 
    360     /*KEY FORMAT IS UDF[12] DST_PORT[10-11] SRC_PORT[8-9] DIP[4-7] SIP[0-3]*/
    361     if (data->v6) {
    362         /* IP[32] = IP[0-31] ^ IP[32-63] ^ IP[64-95] ^ IP[96-127] */
    363         for (idx = 0; idx < 4; idx++) {
    364             for (index = 3 - idx; index < 16; index += 4) {
    365                 key[idx] ^= data->sip6[index]  & 0xff;
    366                 if (use_dip) {
    367                     key[idx + 4] ^= data->dip6[index] & 0xff;
    368                 }
    369             }
    370         }
    371     } else {
    372         for (idx = 0; idx < 4; idx++) {
    373             key[idx] = (data->sip >> (8*idx)) & 0xff;
    374             if (use_dip) {
    375                 key[idx + 4] = (data->dip >> (8*idx)) & 0xff;
    376             }
    377         }
    378     }
    379 
    380     if (use_l4_port) {
    381         for (idx = 0; idx < 2; idx++) {
    382             key[idx + 8] = (data->l4_src_port >> (8*idx)) & 0xff;
    383             key[idx + 10] = (data->l4_dst_port >> (8*idx)) & 0xff;
    384         }
    385     }
    386 
    387     key[12] = udf & 0xff;
    388    
    389     /* XGS3 always uses CRC32 for ECMP hash calculation */
    390     crc_val = soc_draco_crc32(key, 13);
    391 
    392     crc_val_shift = 27;
    393     mask = 0x1F;
    394     if (SOC_IS_APOLLO(unit) || SOC_IS_TRIUMPH2(unit)) {
    395         crc_val_shift = 24;
    396         mask = 0xFF;
    397     } else if (SOC_IS_TRIUMPH3(unit)) {
    398        crc_val_shift = 22;
    399        mask = 0x3FF;
    400     } else if (SOC_IS_TD_TT(unit)) {
    401         crc_val_shift = 16;
    402         mask = 0xFFFF;
    403     }
    404 
    405     if (FB_HASH_CRC32_UPPER == hash_sel) {
    406         return ((crc_val >> crc_val_shift) % (data->ecmp_count + 1));
    407     } else if (FB_HASH_CRC32_LOWER == hash_sel) {
    408         return ((crc_val & mask) % (data->ecmp_count + 1));
    409     }
    410     /* Hopefully never reached. */
    411     return (SOC_E_INTERNAL);
    412 }
    413 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    414 
    415 uint32
    416 soc_draco_trunk_hash(sal_mac_addr_t da, sal_mac_addr_t sa, int tgsize)
    417 {
    418     uint8 key[12];
    419     int ix;
    420     uint32 crc32;
    421 
    422     if (tgsize <= 0 || tgsize > 8) {
    423         return 0;
    424     }
    425 
    426     for (ix = 0; ix < 6; ix++) {
    427         key[ix + 0] = da[5 - ix];
    428     }
    429 
    430     for (ix = 0; ix < 6; ix++) {
    431         key[ix + 6] = sa[5 - ix];
    432     }
    433 
    434     crc32 = soc_draco_crc32(key, 12);
    435 
    436     return (crc32 & 0xffff) % tgsize;
    437 }
    438 
    439 int
    440 soc_draco_hash_set(int unit, int hash_sel)
    441 {
    442     uint32              hash_control, ohash;
    443 
    444     assert(hash_sel >= 0 && hash_sel <= 5);
    445 
    446     SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &hash_control));
    447     ohash = hash_control;
    448     soc_reg_field_set(unit, HASH_CONTROLr, &hash_control,
    449                       HASH_SELECTf, hash_sel);
    450     if (hash_control != ohash) {
    451         SOC_IF_ERROR_RETURN(WRITE_HASH_CONTROLr(unit, hash_control));
    452     }
    453 
    454     return SOC_E_NONE;
    455 }
    456 
    457 int
    458 soc_draco_hash_get(int unit, int *hash_sel)
    459 {
    460     uint32              hash_control;
    461 
    462     SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &hash_control));
    463 
    464     *hash_sel = soc_reg_field_get(unit, HASH_CONTROLr, hash_control,
    465                                   HASH_SELECTf);
    466 
    467     if (*hash_sel > 5) {
    468         *hash_sel = 5;
    469     }
    470 
    471     return SOC_E_NONE;
    472 }
    473 
    474 #ifdef BCM_XGS3_SWITCH_SUPPORT
    475 #define GEN_KEY2(k, ks, k1)                              \
    476     k[ks + 0] |= (k1 << 4) & 0xf0;                       \
    477     k[ks + 1] = (k1 >> 4) & 0xff
    478 
    479 #define GEN_KEY3(k, ks, k1)                              \
    480     k[ks + 0] |= (k1 << 4) & 0xf0;                       \
    481     k[ks + 1] = (k1 >> 4) & 0xff;                        \
    482     k[ks + 2] = (k1 >> 12) & 0xff;                       \
    483     k[ks + 3] = ((k1 >> 20) & 0x0f)
    484 
    485 #define GEN_KEY4(k, ks, k1)                              \
    486     k[ks + 0] |= (k1 << 4) & 0xf0;                       \
    487     k[ks + 1] = (k1 >> 4) & 0xff;                        \
    488     k[ks + 2] = (k1 >> 12) & 0xff;                       \
    489     k[ks + 3] = (k1 >> 20) & 0xff;                       \
    490     k[ks + 4] = ((k1 >> 28) & 0x0f)
    491 #endif /* BCM_XGS3_SWITCH_SUPPORT */
    492 
    493 #ifdef BCM_FIREBOLT_SUPPORT
    494 
    495 uint32
    496 soc_fb_l2_hash(int unit, int hash_sel, uint8 *key)
    497 {
    498     uint32 rv;
    499 
    500     /*
    501      * Cache bucket mask and shift amount for upper crc
    502      */
    503     if (SOC_CONTROL(unit)->hash_mask_l2x == 0) {
    504         uint32  mask, mask_bits;
    505         int     bits;
    506 
    507         /* Get the effective table max for the hash mask */
    508         mask = soc_mem_index_max(unit, L2_HITDA_ONLYm);
    509         /* Need the maximum table size for the shift bits */
    510         mask_bits = SOC_MEM_INFO(unit, L2_HITDA_ONLYm).index_max;
    511         bits = 0;
    512         rv = 1;
    513         while (rv && (mask_bits & rv)) {
    514             bits += 1;
    515             rv <<= 1;
    516         }
    517         SOC_CONTROL(unit)->hash_mask_l2x = mask;
    518         SOC_CONTROL(unit)->hash_bits_l2x = bits;
    519     }
    520 
    521     switch (hash_sel) {
    522     case FB_HASH_CRC16_UPPER:
    523         rv = soc_draco_crc16(key, 8);
    524         if (SOC_IS_HAWKEYE(unit)) {
    525             rv >>= 16 - (SOC_CONTROL(unit)->hash_bits_l2x + 1);
    526         } else {
    527             rv >>= 16 - SOC_CONTROL(unit)->hash_bits_l2x;
    528         }
    529         break;
    530 
    531     case FB_HASH_CRC16_LOWER:
    532         rv = soc_draco_crc16(key, 8);
    533         break;
    534 
    535     case FB_HASH_LSB:
    536         rv = (((uint32)key[0] >> 4) | ((uint32)key[1] << 4) );
    537         break;
    538 
    539     case FB_HASH_ZERO:
    540         rv = 0;
    541         break;
    542 
    543     case FB_HASH_CRC32_UPPER:
    544         rv = soc_draco_crc32(key, 8);
    545         if (SOC_IS_HAWKEYE(unit)) {
    546             rv >>= 32 - (SOC_CONTROL(unit)->hash_bits_l2x + 1);
    547         } else {
    548             rv >>= 32 - SOC_CONTROL(unit)->hash_bits_l2x;
    549         }
    550         break;
    551 
    552     case FB_HASH_CRC32_LOWER:
    553         rv = soc_draco_crc32(key, 8);
    554         break;
    555 
    556     default:
    557         LOG_ERROR(BSL_LS_SOC_HASH,
    558                   (BSL_META_U(unit,
    559                               "soc_fb_l2_hash: invalid hash_sel %d\n"),
    560                    hash_sel));
    561         rv = 0;
    562         break;
    563     }
    564 
    565     return rv & SOC_CONTROL(unit)->hash_mask_l2x;
    566 }
    567 
    568 uint32
    569 soc_fb_l3_hash(int unit, int hash_sel, int key_nbits, uint8 *key)
    570 {
    571     uint32 rv;
    572 #ifdef BCM_SABER2_SUPPORT
    573     uint32 pad_bits = 0, key_size = 0;
    574 #endif
    575     /*
    576      * Cache bucket mask and shift amount for upper crc
    577      */
    578     if (SOC_CONTROL(unit)->hash_mask_l3x == 0) {
    579         uint32  mask, mask_bits;
    580         int     bits;
    581 
    582         /* Get the effective table max for the hash mask */
    583         mask = soc_mem_index_max(unit, L3_ENTRY_HIT_ONLYm);
    584         /* Need the maximum table size for the shift bits */
    585         mask_bits = SOC_MEM_INFO(unit, L3_ENTRY_HIT_ONLYm).index_max;
    586         bits = 0;
    587         rv = 1;
    588         while (rv && (mask_bits & rv)) {
    589             bits += 1;
    590             rv <<= 1;
    591         }
    592         SOC_CONTROL(unit)->hash_mask_l3x = mask;
    593         SOC_CONTROL(unit)->hash_bits_l3x = bits;
    594     }
    595 
    596     switch (hash_sel) {
    597     case FB_HASH_CRC16_UPPER:
    598         rv = soc_crc16b(key, key_nbits);
    599         rv >>= 16 - SOC_CONTROL(unit)->hash_bits_l3x;
    600         break;
    601 
    602     case FB_HASH_CRC16_LOWER:
    603         rv = soc_crc16b(key, key_nbits);
    604         break;
    605 
    606     case FB_HASH_LSB:
    607         rv = ((uint32)key[0]) | ((uint32)key[1] << 8) | ((uint32)key[2] << 16);
    608         /* See _soc_fb_l3x_realign_key() to understand the shift values below */
    609 
    610         if ((key_nbits == 80)  || (key_nbits == 264)) {
    611                 rv >>= 4;
    612         } else if ((key_nbits == 40)  || (key_nbits == 136)) {
    613                 rv >>= 2;
    614         } else if ((key_nbits == 88)  || (key_nbits == 272)) {
    615 #if defined (BCM_SABER2_SUPPORT)
    616                if (SOC_IS_SABER2(unit)) {
    617                    key_size = 271;
    618                    pad_bits = (key_size + 7) & ~0x7;
    619                    pad_bits = pad_bits - key_size;
    620                    rv >>= pad_bits; /*take care of padding bits*/
    621                } else
    622 #endif 
    623 #if defined (BCM_GREYHOUND2_SUPPORT)
    624                if (SOC_IS_GREYHOUND2(unit)) {
    625                    rv >>= 4;
    626                } else
    627 #endif
    628                {
    629                    rv >>= 6;
    630                }
    631         } else if ((key_nbits == 96)  || (key_nbits == 280)) {
    632 #if defined (BCM_TRIUMPH_SUPPORT)
    633             if(SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_MULTICASTm, L3_IIFf)) {
    634                 rv >>= (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 
    635                         SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || 
    636                         SOC_IS_HURRICANEX(unit) ||
    637                         SOC_IS_GREYHOUND(unit) ||
    638                         SOC_IS_GREYHOUND2(unit)) ? 5 : 6;
    639             } else 
    640 #endif /* BCM_TRX_SUPPORT */
    641             {
    642                 rv >>= 7;
    643             }
    644         } else if ((key_nbits == 48)  || (key_nbits == 144)) {
    645 #if defined (BCM_ENDURO_SUPPORT)
    646            if(SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) ||
    647              SOC_IS_GREYHOUND(unit)) {
    648                rv >>= 2;
    649            } else
    650 #endif /* BCM_ENDURO_SUPPORT */
    651            {
    652                 rv >>= 3;
    653             }
    654         }
    655         break;
    656 
    657     case FB_HASH_ZERO:
    658         rv = 0;
    659         break;
    660 
    661     case FB_HASH_CRC32_UPPER:
    662         rv = soc_crc32b(key, key_nbits);
    663         rv >>= 32 - SOC_CONTROL(unit)->hash_bits_l3x;
    664         break;
    665 
    666     case FB_HASH_CRC32_LOWER:
    667         rv = soc_crc32b(key, key_nbits);
    668         break;
    669 
    670     default:
    671         LOG_ERROR(BSL_LS_SOC_HASH,
    672                   (BSL_META_U(unit,
    673                               "soc_fb_l3_hash: invalid hash_sel %d\n"),
    674                    hash_sel));
    675         rv = 0;
    676         break;
    677     }
    678 
    679     return rv & SOC_CONTROL(unit)->hash_mask_l3x;
    680 }
    681 
    682 uint32
    683 soc_fb_vlan_mac_hash(int unit, int hash_sel, uint8 *key)
    684 {
    685     uint32 rv;
    686 
    687     /*
    688      * Cache bucket mask and shift amount for upper crc
    689      */
    690     if (SOC_CONTROL(unit)->hash_mask_vlan_mac == 0) {
    691         uint32  mask;
    692         int     bits;
    693 
    694         /* 4 Entries per bucket */
    695         mask = soc_mem_index_max(unit, VLAN_MACm) >> 2;
    696         bits = 0;
    697         rv = 1;
    698         while (rv && (mask & rv)) {
    699             bits += 1;
    700             rv <<= 1;
    701         }
    702         SOC_CONTROL(unit)->hash_mask_vlan_mac = mask;
    703         SOC_CONTROL(unit)->hash_bits_vlan_mac = bits;
    704     }
    705 
    706     switch (hash_sel) {
    707     case FB_HASH_CRC16_UPPER:
    708         rv = soc_draco_crc16(key, 6);
    709         rv >>= 16 - SOC_CONTROL(unit)->hash_bits_vlan_mac;
    710         break;
    711 
    712     case FB_HASH_CRC16_LOWER:
    713         rv = soc_draco_crc16(key, 6);
    714         break;
    715 
    716     case FB_HASH_LSB:
    717         /* Extract more than required 8 bits. Masked below anyway */
    718         rv = (((uint32)key[0]) | ((uint32)key[1] << 8));
    719         break;
    720 
    721     case FB_HASH_ZERO:
    722         rv = 0;
    723         break;
    724 
    725     case FB_HASH_CRC32_UPPER:
    726         rv = soc_draco_crc32(key, 6);
    727         rv >>= 32 - SOC_CONTROL(unit)->hash_bits_vlan_mac;
    728         break;
    729 
    730     case FB_HASH_CRC32_LOWER:
    731         rv = soc_draco_crc32(key, 6);
    732         break;
    733 
    734     default:
    735         LOG_ERROR(BSL_LS_SOC_HASH,
    736                   (BSL_META_U(unit,
    737                               "soc_fb_vlan_mac_hash: invalid hash_sel %d\n"),
    738                    hash_sel));
    739         rv = 0;
    740         break;
    741     }
    742 
    743     return rv & SOC_CONTROL(unit)->hash_mask_vlan_mac;
    744 }
    745 
    746 /* In Hurricane, VRF_ID field is invalid, but the hashing algorithm retains the space
    747 *   in the key, and expects it to be 0s. So we have special handling for Hu
    748 */
    749 STATIC int
    750 _soc_hash_generic_entry_to_key(int unit, void *entry, uint8 *key,
    751                                soc_mem_t mem, soc_field_t *field_list)
    752 {
    753     soc_field_t field;
    754     int         index, key_index, val_index, fval_index;
    755     int         right_shift_count, left_shift_count;
    756     uint32      val[SOC_MAX_MEM_WORDS], fval[SOC_MAX_MEM_WORDS];
    757     int         bits, val_bits, fval_bits;
    758     int8        field_length[16];
    759 
    760     val_bits = 0;
    761     for (index = 0; index < 16; index++) {
    762         field_length[index] = 0;
    763     }
    764     for (index = 0; field_list[index] != INVALIDf; index++) {
    765         field = field_list[index];
    766         if (field == NUM_SOC_FIELD || !SOC_MEM_FIELD_VALID(unit, mem, field)) {
    767 #ifdef BCM_HURRICANE_SUPPORT 
    768             if((SOC_IS_HURRICANEX(unit)|| SOC_IS_GREYHOUND(unit) ||
    769                 SOC_IS_GREYHOUND2(unit))
    770                  && (field == VRF_IDf)) {
    771                 field_length[index] = 11;
    772                 val_bits += field_length[index];
    773             }
    774 #endif
    775             continue;
    776         }
    777         field_length[index] = soc_mem_field_length(unit, mem, field);
    778 #ifdef BCM_HURRICANE_SUPPORT
    779         if((SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) && 
    780             (field == PORT_GROUP_IDf)) {
    781             field_length[index] = 13;
    782         }
    783 #endif
    784         val_bits += field_length[index];
    785     }
    786 
    787 #ifdef BCM_TRIUMPH2_SUPPORT
    788     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
    789         SOC_IS_VALKYRIE2(unit) || SOC_IS_HURRICANEX(unit) ||
    790         SOC_IS_TD_TT(unit)||SOC_IS_KATANA(unit)||
    791         SOC_IS_GREYHOUND(unit)||SOC_IS_GREYHOUND2(unit)) {
    792         if (mem == L2Xm || mem == VLAN_MACm) {
    793             if (soc_feature(unit, soc_feature_trill)) {
    794                 val_bits = 60 + /* VLAN_ID + MAC_ADDRESS */
    795                     soc_mem_field_length(unit, L2Xm, KEY_TYPEf) +
    796                     soc_mem_field_length(unit, L2Xm,
    797                                          TRILL_NONUC_NETWORK_LONG__TREE_IDf);
    798             } else {
    799                 val_bits = 60 + /* VLAN_ID + MAC_ADDRESS */
    800                     soc_mem_field_length(unit, L2Xm, KEY_TYPEf);
    801             }
    802         } else if (mem == L3_ENTRY_ONLYm ||
    803                  mem == L3_ENTRY_IPV4_UNICASTm ||
    804                  mem == L3_ENTRY_IPV4_MULTICASTm ||
    805                  mem == L3_ENTRY_IPV6_UNICASTm) {
    806             /* Pad to the longest hashing key (L3_ENTRY_IPV6_MULTICAST) */
    807             val_bits = 120 + /* GROUP_IP_ADDR_* */
    808                 128 + /* SOURCE_IP_ADDR_* */
    809                 soc_mem_field_length(unit, L3_ENTRY_IPV6_MULTICASTm, L3_IIFf) +
    810                 ((SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit)) ? 11 :
    811                  soc_mem_field_length(unit, L3_ENTRY_IPV6_MULTICASTm,
    812                                       VRF_IDf)) +
    813                 soc_mem_field_length(unit, L3_ENTRY_IPV6_MULTICASTm,
    814                                      KEY_TYPE_0f);
    815         } else if (mem == VLAN_XLATEm) {
    816             /* Pad to the longest hashing key (VLAN_MAC) */
    817             val_bits = 48 + /* MAC_ADDR */
    818                 soc_mem_field_length(unit, VLAN_MACm, KEY_TYPEf);
    819 #ifdef BCM_HURRICANE_SUPPORT
    820         if(SOC_IS_HURRICANEX(unit)|| SOC_IS_GREYHOUND(unit) ||
    821            SOC_IS_GREYHOUND2(unit)) {
    822             val_bits = 41;
    823         }
    824 #endif
    825         } else if (mem == EGR_VLAN_XLATEm) {
    826             /* Pad to the longest hashing key (WLAN SVP) */
    827             if (SOC_IS_TD_TT(unit)) {
    828                 val_bits =
    829                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, ENTRY_TYPEf) +
    830                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, OVIDf) +
    831                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, DST_MODIDf) +
    832                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, DST_PORTf) +
    833                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, IVIDf);
    834             } else if (SOC_IS_KATANA(unit)|| SOC_IS_GREYHOUND(unit) ||
    835                         SOC_IS_HURRICANE3(unit)||SOC_IS_GREYHOUND2(unit)) { 
    836                 val_bits =
    837                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, ENTRY_TYPEf) +
    838                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, OVIDf) +
    839                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, PORT_GROUP_IDf) +
    840                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, DUMMY_BITSf) +
    841                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, IVIDf);
    842             } else if (!(SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit))) {
    843                 val_bits =
    844                     soc_mem_field_length(unit, EGR_VLAN_XLATEm, ENTRY_TYPEf) +
    845                     soc_mem_field_length(unit, EGR_VLAN_XLATEm,
    846                                          WLAN_SVP__KEYf);
    847             }
    848         } else if (mem == MPLS_ENTRYm) {
    849             /* Pad to the longest hashing key (MIM_NVP) */
    850             val_bits = soc_mem_field_length(unit, MPLS_ENTRYm, KEY_TYPEf) +
    851                 soc_mem_field_length(unit, MPLS_ENTRYm, MIM_NVP__BVIDf) +
    852                 soc_mem_field_length(unit, MPLS_ENTRYm, MIM_NVP__BMACSAf);
    853         }
    854     } else
    855 #endif /* BCM_TRIUMPH2_SUPPORT */
    856 #ifdef BCM_ENDURO_SUPPORT
    857     if (SOC_IS_ENDURO(unit)) {
    858         if (mem == MPLS_ENTRYm) {
    859             /* Pad to the longest hashing key (MIM_NVP) */
    860             val_bits = soc_mem_field_length(unit, MPLS_ENTRYm, KEY_TYPEf) +
    861                 soc_mem_field_length(unit, MPLS_ENTRYm, MIM_NVP__BVIDf) +
    862                 soc_mem_field_length(unit, MPLS_ENTRYm, MIM_NVP__BMACSAf);
    863         }        
    864     } else
    865 #endif /* BCM_ENDURO_SUPPORT */
    866 #ifdef BCM_TRIUMPH3_SUPPORT
    867     if (SOC_IS_TRIUMPH3(unit)) {
    868         if (mem == AXP_WRX_WCDm || mem == AXP_WRX_SVP_ASSIGNMENTm) {
    869             val_bits = 55;
    870         }
    871         if (mem == FT_SESSIONm) {
    872             val_bits =
    873                 soc_mem_field_length(unit, FT_SESSIONm, KEYf);
    874         }
    875         if (mem == FT_SESSION_IPV6m) {
    876             val_bits =
    877                 soc_mem_field_length(unit, FT_SESSION_IPV6m, KEYf) +
    878                 soc_mem_field_length(unit, FT_SESSION_IPV6m, IPV6_LOWER_KEYf);
    879         }
    880     } else 
    881 #endif /* BCM_TRIUMPH3_SUPPORT */
    882     {
    883         if (mem == VLAN_XLATEm) {
    884             /* Pad to the longest hashing key (KEY_TYPE 0) */
    885             val_bits =
    886                 soc_mem_field_length(unit, VLAN_XLATEm, KEY_TYPEf) +
    887                 soc_mem_field_length(unit, VLAN_XLATEm, GLPf) +
    888                 soc_mem_field_length(unit, VLAN_XLATEm, OVIDf) +
    889                 soc_mem_field_length(unit, VLAN_XLATEm, IVIDf);
    890         }
    891     }
    892 
    893     bits = (val_bits + 7) & ~0x7;
    894     sal_memset(val, 0, sizeof(val));
    895     val_bits = bits - val_bits;
    896     for (index = 0; field_list[index] != INVALIDf; index++) {
    897         field = field_list[index];
    898 #ifdef BCM_HURRICANE_SUPPORT
    899         if ((SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit))
    900             && (field == VRF_IDf) ) {
    901             fval[0] = fval[1] = 0;
    902             fval_bits = 11;
    903         } else
    904 #endif
    905         {
    906             if (field == NUM_SOC_FIELD || !SOC_MEM_FIELD_VALID(unit, mem, field)) {
    907                 continue;
    908             }
    909 
    910             soc_mem_field_get(unit, mem, entry, field, fval);
    911             fval_bits = field_length[index];
    912         }
    913 
    914         val_index = val_bits >> 5;
    915         fval_index = 0;
    916         left_shift_count = val_bits & 0x1f;
    917         right_shift_count = 32 - left_shift_count;
    918         val_bits += fval_bits;
    919 
    920         if (left_shift_count) {
    921             for (; fval_bits > 0; fval_bits -= 32) {
    922                 val[val_index++] |= fval[fval_index] << left_shift_count;
    923                 val[val_index] |= fval[fval_index++] >> right_shift_count;
    924             }
    925         } else {
    926             for (; fval_bits > 0; fval_bits -= 32) {
    927                 val[val_index++] = fval[fval_index++];
    928             }
    929         }
    930     }
    931 
    932     key_index = 0;
    933     for (val_index = 0; val_bits > 0; val_index++) {
    934         for (right_shift_count = 0; right_shift_count < 32;
    935              right_shift_count += 8) {
    936             if (val_bits <= 0) {
    937                 break;
    938             }
    939             key[key_index++] = (val[val_index] >> right_shift_count) & 0xff;
    940             val_bits -= 8;
    941         }
    942     }
    943 
    944     if ((bits + 7) / 8 > key_index) {
    945         sal_memset(&key[key_index], 0, (bits + 7) / 8 - key_index);
    946     }
    947 
    948     return bits;
    949 }
    950 
    951 STATIC int
    952 _soc_fb_l3x_ip4ucast_entry_to_key(int unit, uint32 *entry, uint8 *key)
    953 {
    954     static soc_field_t field_list[] = {
    955         IP_ADDRf,
    956         VRF_IDf,
    957         KEY_TYPEf,
    958         INVALIDf
    959     };
    960 
    961     soc_mem_t mem;
    962 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    963     if (soc_mem_is_valid(unit, L3_ENTRY_ONLY_SINGLEm)) {
    964         mem = L3_ENTRY_ONLY_SINGLEm;
    965     } else
    966 #endif
    967     {
    968         mem = L3_ENTRY_IPV4_UNICASTm;
    969     }
    970     return _soc_hash_generic_entry_to_key
    971         (unit, entry, key, mem, field_list);
    972 }
    973 
    974 STATIC int
    975 _soc_fb_l3x_ip4mcast_entry_to_key(int unit, uint32 *entry, uint8 *key)
    976 {
    977     static soc_field_t field_list[] = {
    978         GROUP_IP_ADDRf,
    979         SOURCE_IP_ADDRf,
    980         VLAN_IDf,
    981         VRF_IDf,
    982         KEY_TYPEf,
    983         KEY_TYPE_0f,
    984         INVALIDf
    985     };
    986 
    987     soc_mem_t mem;
    988 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
    989     if (soc_mem_is_valid(unit, L3_ENTRY_ONLY_DOUBLEm)) {
    990         mem = L3_ENTRY_ONLY_DOUBLEm;
    991     } else
    992 #endif
    993     {
    994         mem = L3_ENTRY_IPV4_MULTICASTm;
    995     }
    996     if (SOC_MEM_FIELD_VALID(unit, mem, L3_IIFf) ||
    997         SOC_MEM_FIELD_VALID(unit, mem, L3_IIFf)) {
    998         field_list[2] = L3_IIFf;
    999     }
   1000 
   1001     return _soc_hash_generic_entry_to_key
   1002         (unit, entry, key, mem, field_list);
   1003 }
   1004 
   1005 STATIC int
   1006 _soc_fb_l3x_ip6ucast_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1007 {
   1008     static soc_field_t field_list[] = {
   1009         IP_ADDR_LWR_64f,
   1010         IP_ADDR_UPR_64f,
   1011         VRF_IDf,
   1012         VRF_ID_0f,
   1013         KEY_TYPE_0f,
   1014         INVALIDf
   1015     };
   1016 
   1017     soc_mem_t mem;
   1018 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   1019     if (soc_mem_is_valid(unit, L3_ENTRY_ONLY_DOUBLEm)) {
   1020         mem = L3_ENTRY_ONLY_DOUBLEm;
   1021     } else
   1022 #endif
   1023     {
   1024         mem = L3_ENTRY_IPV6_UNICASTm;
   1025     }
   1026     return _soc_hash_generic_entry_to_key
   1027         (unit, entry, key, mem, field_list);
   1028 }
   1029 
   1030 STATIC int
   1031 _soc_fb_l3x_ip6mcast_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1032 {
   1033     static soc_field_t field_list[] = {
   1034         GROUP_IP_ADDR_LWR_64f,
   1035         GROUP_IP_ADDR_UPR_56f,
   1036         SOURCE_IP_ADDR_LWR_64f,
   1037         SOURCE_IP_ADDR_UPR_64f,
   1038         L3_IIFf,
   1039         VLAN_ID_0f,
   1040         VRF_IDf,
   1041         VRF_ID_0f,
   1042         KEY_TYPE_0f,
   1043         INVALIDf
   1044     };
   1045 
   1046     soc_mem_t mem;
   1047 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   1048     if (soc_mem_is_valid(unit, L3_ENTRY_ONLY_DOUBLEm)) {
   1049         mem = L3_ENTRY_ONLY_QUADm;
   1050     } else
   1051 #endif
   1052     {
   1053         mem = L3_ENTRY_IPV6_MULTICASTm;
   1054     }
   1055     return _soc_hash_generic_entry_to_key
   1056         (unit, entry, key, mem, field_list);
   1057 }
   1058 
   1059 #ifdef BCM_TRIUMPH2_SUPPORT
   1060 STATIC int
   1061 _soc_tr2_l3x_lmep_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1062 {
   1063     static soc_field_t field_list[] = {
   1064         LMEP__SGLPf,
   1065         LMEP__VIDf,
   1066         KEY_TYPEf,
   1067         INVALIDf
   1068     };
   1069 
   1070     return _soc_hash_generic_entry_to_key(unit, entry, key,
   1071                                           L3_ENTRY_ONLYm, field_list);
   1072 }
   1073 
   1074 STATIC int
   1075 _soc_tr2_l3x_rmep_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1076 {
   1077     static soc_field_t field_list[] = {
   1078         RMEP__SGLPf,
   1079         RMEP__VIDf,
   1080         RMEP__MDLf,
   1081         RMEP__MEPIDf,
   1082         KEY_TYPEf,
   1083         INVALIDf
   1084     };
   1085 
   1086     return _soc_hash_generic_entry_to_key(unit, entry, key,
   1087                                           L3_ENTRY_ONLYm, field_list);
   1088 }
   1089 #endif /* BCM_TRIUMPH2_SUPPORT */
   1090 
   1091 #ifdef BCM_TRIDENT_SUPPORT
   1092 STATIC int
   1093 _soc_td_l3x_trill_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1094 {
   1095     static soc_field_t field_list[] = {
   1096         TRILL__INGRESS_RBRIDGE_NICKNAMEf,
   1097         TRILL__TREE_IDf,
   1098         KEY_TYPEf,
   1099         INVALIDf
   1100     };
   1101 
   1102     return _soc_hash_generic_entry_to_key(unit, entry, key,
   1103                                           L3_ENTRY_ONLYm, field_list);
   1104 }
   1105 #endif /* BCM_TRIDENT_SUPPORT */
   1106 
   1107 int
   1108 soc_fb_l3x_base_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1109 {
   1110     uint8 key_type = 0;
   1111 #ifdef BCM_KATANA2_SUPPORT
   1112     if (SOC_IS_KATANA2(unit)) {
   1113         return soc_kt2_l3x_base_entry_to_key(unit, entry, key);
   1114     }
   1115 #endif
   1116 #ifdef BCM_TRIDENT2_SUPPORT
   1117     if (SOC_IS_TRIDENT2X(unit)) {
   1118          return soc_td2_l3x_base_entry_to_key(unit, 0, entry, key);
   1119     }
   1120 #endif /* BCM_TRIDENT2_SUPPORT */
   1121 
   1122     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) {
   1123         key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf);
   1124     } else if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_SINGLEm, KEY_TYPEf)) {
   1125         key_type = soc_mem_field32_get(unit, L3_ENTRY_SINGLEm, entry, KEY_TYPEf);
   1126     }
   1127 
   1128     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf) 
   1129         || SOC_MEM_FIELD_VALID(unit, L3_ENTRY_SINGLEm, KEY_TYPEf)
   1130        ) {
   1131         switch (key_type) {
   1132         case TR_L3_HASH_KEY_TYPE_V4UC:
   1133             return _soc_fb_l3x_ip4ucast_entry_to_key(unit, entry, key);
   1134         case TR_L3_HASH_KEY_TYPE_V4MC:
   1135             return _soc_fb_l3x_ip4mcast_entry_to_key(unit, entry, key);
   1136         case TR_L3_HASH_KEY_TYPE_V6UC:
   1137             return _soc_fb_l3x_ip6ucast_entry_to_key(unit, entry, key);
   1138         case TR_L3_HASH_KEY_TYPE_V6MC:
   1139             return _soc_fb_l3x_ip6mcast_entry_to_key(unit, entry, key);
   1140 #ifdef BCM_TRIUMPH2_SUPPORT
   1141         case TR_L3_HASH_KEY_TYPE_LMEP:
   1142             if (!soc_feature(unit, soc_feature_oam)) {
   1143                 return 0;
   1144             }
   1145             return _soc_tr2_l3x_lmep_entry_to_key(unit, entry, key);
   1146         case TR_L3_HASH_KEY_TYPE_RMEP:
   1147             if (!soc_feature(unit, soc_feature_oam)) {
   1148                 return 0;
   1149             }
   1150             return _soc_tr2_l3x_rmep_entry_to_key(unit, entry, key);
   1151 #endif /* BCM_TRIUMPH2_SUPPORT */
   1152 #ifdef BCM_TRIDENT_SUPPORT
   1153         case TR_L3_HASH_KEY_TYPE_TRILL:
   1154             if (!soc_feature(unit, soc_feature_trill)) {
   1155                 return 0;
   1156             }
   1157             return _soc_td_l3x_trill_entry_to_key(unit, entry, key);
   1158 #endif /* BCM_TRIDENT_SUPPORT */
   1159         default:
   1160             return 0;
   1161         }
   1162     }
   1163 
   1164     if (soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, entry, V6f)) {
   1165         if (soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, entry, IPMCf)) {
   1166             return _soc_fb_l3x_ip6mcast_entry_to_key(unit, entry, key);
   1167         } else {
   1168             return _soc_fb_l3x_ip6ucast_entry_to_key(unit, entry, key);
   1169         }
   1170     } else {
   1171         if (soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, entry, IPMCf)) {
   1172             return _soc_fb_l3x_ip4mcast_entry_to_key(unit, entry, key);
   1173         } else {
   1174             return _soc_fb_l3x_ip4ucast_entry_to_key(unit, entry, key);
   1175         }
   1176     }
   1177 }
   1178 
   1179 uint32
   1180 soc_fb_l3x2_entry_hash(int unit, uint32 *entry)
   1181 {
   1182     int             hash_sel;
   1183     uint32          index;
   1184     int             key_nbits;
   1185     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1186     uint32          tmp_hs;
   1187 
   1188     SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &tmp_hs));
   1189     hash_sel = soc_reg_field_get(unit, HASH_CONTROLr,
   1190                                  tmp_hs, L3_HASH_SELECTf);
   1191     key_nbits = soc_fb_l3x_base_entry_to_key(unit, entry, key);
   1192     index = soc_fb_l3_hash(unit, hash_sel, key_nbits, key);
   1193 
   1194     return index;
   1195 }
   1196 
   1197 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) \
   1198  || defined(BCM_RAVEN_SUPPORT) || defined(BCM_SCORPION_SUPPORT)
   1199 int
   1200 soc_fb_l2x_entry_bank_hash_sel_get(int unit, int bank, int *hash_sel)
   1201 {
   1202     uint32          tmp_hs;
   1203 
   1204     *hash_sel = -1;
   1205     if (bank > 0) {
   1206         SOC_IF_ERROR_RETURN(READ_L2_AUX_HASH_CONTROLr(unit, &tmp_hs));
   1207         if (soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr,
   1208                               tmp_hs, ENABLEf)) {
   1209             *hash_sel = soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr,
   1210                                          tmp_hs, HASH_SELECTf);
   1211         }
   1212     }
   1213 
   1214     if (*hash_sel == -1) {
   1215         SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &tmp_hs));
   1216         *hash_sel = soc_reg_field_get(unit, HASH_CONTROLr,
   1217                                       tmp_hs, L2_AND_VLAN_MAC_HASH_SELECTf);
   1218     }
   1219 
   1220     return SOC_E_NONE;
   1221 }
   1222 
   1223 uint32
   1224 soc_fb_l2x_entry_hash(int unit, int hash_sel, uint32 *entry)
   1225 {
   1226     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1227     uint32          index;
   1228 
   1229     soc_draco_l2x_base_entry_to_key(unit, (l2x_entry_t *)entry, key);
   1230     index = soc_fb_l2_hash(unit, hash_sel, key);
   1231 
   1232     return index;
   1233 }
   1234 
   1235 int
   1236 soc_fb_l3x_entry_bank_hash_sel_get(int unit, int bank, int *hash_sel)
   1237 {
   1238     uint32          tmp_hs;
   1239 
   1240     *hash_sel = -1;
   1241     if (bank > 0) {
   1242         SOC_IF_ERROR_RETURN(READ_L3_AUX_HASH_CONTROLr(unit, &tmp_hs));
   1243         if (soc_reg_field_get(unit, L3_AUX_HASH_CONTROLr,
   1244                               tmp_hs, ENABLEf)) {
   1245             *hash_sel = soc_reg_field_get(unit, L3_AUX_HASH_CONTROLr,
   1246                                          tmp_hs, HASH_SELECTf);
   1247         }
   1248     }
   1249 
   1250     if (*hash_sel == -1) {
   1251         SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &tmp_hs));
   1252         *hash_sel = soc_reg_field_get(unit, HASH_CONTROLr,
   1253                                      tmp_hs, L3_HASH_SELECTf);
   1254     }
   1255 
   1256     return SOC_E_NONE;
   1257 }
   1258 
   1259 uint32
   1260 soc_fb_l3x_entry_hash(int unit, int hash_sel, uint32 *entry)
   1261 {
   1262     int             key_nbits;
   1263     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1264     uint32          index;
   1265 
   1266     key_nbits = soc_fb_l3x_base_entry_to_key(unit, entry, key);
   1267     index = soc_fb_l3_hash(unit, hash_sel, key_nbits, key);
   1268 
   1269     return index;
   1270 }
   1271 
   1272 int
   1273 soc_fb_l3x_bank_entry_hash(int unit, int bank, uint32 *entry)
   1274 {
   1275     int        hash_sel;
   1276 
   1277     SOC_IF_ERROR_RETURN
   1278         (soc_fb_l3x_entry_bank_hash_sel_get(unit, bank, &hash_sel));
   1279 
   1280     return soc_fb_l3x_entry_hash(unit, hash_sel, entry);
   1281 }
   1282 
   1283 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRIUMPH_SUPPORT || BCM_RAVEN_SUPPORT */
   1284 
   1285 int
   1286 soc_fb_rv_vlanmac_hash_sel_get(int unit, int dual, int *hash_sel)
   1287 {
   1288     uint32          tmp_hs;
   1289 
   1290     *hash_sel = -1;
   1291 #if defined(BCM_TRX_SUPPORT)
   1292     if (SOC_IS_TRX(unit)) {
   1293         /* From Triumph onwards VLAN_MAC uses VLAN_XLATE hash select reg */
   1294         return soc_tr_hash_sel_get(unit, VLAN_XLATEm, dual, hash_sel);    
   1295     }
   1296 #endif
   1297 #if defined(BCM_RAVEN_SUPPORT)
   1298     if (dual > 0 && SOC_REG_IS_VALID(unit, VLAN_MAC_AUX_HASH_CONTROLr)) {
   1299         SOC_IF_ERROR_RETURN(READ_VLAN_MAC_AUX_HASH_CONTROLr(unit, &tmp_hs));
   1300         if (soc_reg_field_get(unit, VLAN_MAC_AUX_HASH_CONTROLr,
   1301                               tmp_hs, ENABLEf)) {
   1302             *hash_sel = soc_reg_field_get(unit, VLAN_MAC_AUX_HASH_CONTROLr,
   1303                                          tmp_hs, HASH_SELECTf);
   1304         }
   1305     }
   1306 #endif /* BCM_RAVEN_SUPPORT */
   1307 
   1308     if (*hash_sel == -1) {
   1309         SOC_IF_ERROR_RETURN(READ_HASH_CONTROLr(unit, &tmp_hs));
   1310         *hash_sel = soc_reg_field_get(unit, HASH_CONTROLr,
   1311                                       tmp_hs, L2_AND_VLAN_MAC_HASH_SELECTf);
   1312     }
   1313 
   1314     return SOC_E_NONE;
   1315 }
   1316 
   1317 #endif /* BCM_FIREBOLT_SUPPORT */
   1318 
   1319 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_SCORPION_SUPPORT)
   1320 uint32
   1321 soc_tr_l2x_hash(int unit, int hash_sel, int key_nbits, void *base_entry,
   1322                 uint8 *key)
   1323 {
   1324     uint32 rv;
   1325     uint32 fval[SOC_MAX_MEM_WORDS];
   1326    
   1327     /*
   1328      * Cache bucket mask and shift amount for upper crc
   1329      */
   1330     if (SOC_CONTROL(unit)->hash_mask_l2x == 0) {
   1331         uint32  mask;
   1332         int     bits;
   1333 
   1334         mask = soc_mem_index_max(unit, L2_HITDA_ONLYm);
   1335         bits = 0;
   1336         rv = 1;
   1337         while (rv && (mask & rv)) {
   1338             bits += 1;
   1339             rv <<= 1;
   1340         }
   1341         SOC_CONTROL(unit)->hash_mask_l2x = mask;
   1342         SOC_CONTROL(unit)->hash_bits_l2x = bits;
   1343     }
   1344      
   1345     switch (hash_sel) {
   1346     case FB_HASH_CRC16_UPPER:
   1347         rv = soc_crc16b(key, key_nbits);
   1348         rv >>= 16 - SOC_CONTROL(unit)->hash_bits_l2x;
   1349         break;
   1350 
   1351     case FB_HASH_CRC16_LOWER:
   1352         rv = soc_crc16b(key, key_nbits);
   1353         break;
   1354 
   1355     case FB_HASH_LSB:
   1356         if (key_nbits == 0) {
   1357             return 0;
   1358         }
   1359 #ifdef BCM_GREYHOUND_SUPPORT
   1360         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   1361             SOC_IS_GREYHOUND2(unit)) {
   1362             switch (soc_mem_field32_get(unit, L2Xm, base_entry, KEY_TYPEf)) {
   1363             case GH_L2_HASH_KEY_TYPE_BRIDGE:
   1364                 soc_mem_field_get(unit, L2Xm, base_entry, MAC_ADDRf, fval);
   1365                 rv = fval[0];
   1366                 break;
   1367             case GH_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
   1368                 rv = soc_mem_field32_get(unit, L2Xm, base_entry, OVIDf);
   1369                 break;
   1370             case GH_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT:
   1371                 rv = soc_mem_field32_get(unit, L2Xm, base_entry, OVIDf) |
   1372                     (soc_mem_field32_get(unit, L2Xm, base_entry, IVIDf) <<
   1373                      soc_mem_field_length(unit, L2Xm, OVIDf));
   1374                 break;
   1375             case GH_L2_HASH_KEY_TYPE_VIF:
   1376                 /* use only 12 bit of the 14 bit DST_VIF */
   1377                 rv = (soc_mem_field32_get(unit, L2Xm, base_entry,
   1378                                       VIF__DST_VIFf) & 0xfff) |
   1379                 (soc_mem_field32_get(unit, L2Xm, base_entry,
   1380                                      VIF__NAMESPACEf) << 12);                
   1381                 break;
   1382             case GH_L2_HASH_KEY_TYPE_PE_VID:
   1383                 rv = (soc_mem_field32_get(unit, L2Xm, base_entry,
   1384                                       PE_VID__ETAG_VIDf) & 0xfff) |
   1385                 (soc_mem_field32_get(unit, L2Xm, base_entry,
   1386                                      PE_VID__NAMESPACEf) << 12);                
   1387                 break;
   1388             default:
   1389                 rv = 0;
   1390                 break;
   1391             }
   1392             break;
   1393         }
   1394 #endif  /* BCM_GREYHOUND_SUPPORT */
   1395         switch (soc_mem_field32_get(unit, L2Xm, base_entry, KEY_TYPEf)) {
   1396         case TR_L2_HASH_KEY_TYPE_BRIDGE:
   1397         case TR_L2_HASH_KEY_TYPE_VFI:
   1398             soc_mem_field_get(unit, L2Xm, base_entry, MAC_ADDRf, fval);
   1399             rv = fval[0];
   1400             break;
   1401         case TR_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
   1402             rv = soc_mem_field32_get(unit, L2Xm, base_entry, OVIDf);
   1403             break;
   1404         case TR_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT:
   1405             rv = soc_mem_field32_get(unit, L2Xm, base_entry, OVIDf) |
   1406                 (soc_mem_field32_get(unit, L2Xm, base_entry, IVIDf) <<
   1407                  soc_mem_field_length(unit, L2Xm, OVIDf));
   1408             break;
   1409 #ifdef BCM_TRIDENT_SUPPORT
   1410         case TR_L2_HASH_KEY_TYPE_VIF:
   1411             /* use only 12 bit of the 14 bit DST_VIF */
   1412             rv = (soc_mem_field32_get(unit, L2Xm, base_entry,
   1413                                       VIF__DST_VIFf) & 0xfff) |
   1414                 (soc_mem_field32_get(unit, L2Xm, base_entry,
   1415                                      VIF__NAMESPACEf) << 12);
   1416             break;
   1417         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
   1418             soc_mem_field_get(unit, L2Xm, base_entry,
   1419                               TRILL_NONUC_ACCESS__MAC_ADDRf, fval);
   1420             rv = fval[0];
   1421             break;
   1422         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
   1423             soc_mem_field_get(unit, L2Xm, base_entry,
   1424                               TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, fval);
   1425             rv = fval[0];
   1426             break;
   1427         case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
   1428             rv = soc_mem_field32_get(unit, L2Xm, base_entry,
   1429                                      TRILL_NONUC_NETWORK_SHORT__TREE_IDf) |
   1430                 (soc_mem_field32_get(unit, L2Xm, base_entry,
   1431                                      TRILL_NONUC_NETWORK_SHORT__VLAN_IDf) <<
   1432                  soc_mem_field_length(unit, L2Xm,
   1433                                       TRILL_NONUC_NETWORK_SHORT__TREE_IDf));
   1434             rv = 0;
   1435             break;
   1436 #endif /* BCM_TRIDENT_SUPPORT */
   1437         default:
   1438             rv = 0;
   1439             break;
   1440         }
   1441         break;
   1442 
   1443     case FB_HASH_ZERO:
   1444         rv = 0;
   1445         break;
   1446 
   1447     case FB_HASH_CRC32_UPPER:
   1448         rv = soc_crc32b(key, key_nbits);
   1449         rv >>= 32 - SOC_CONTROL(unit)->hash_bits_l2x;
   1450         break;
   1451 
   1452     case FB_HASH_CRC32_LOWER:
   1453         rv = soc_crc32b(key, key_nbits);
   1454         break;
   1455 
   1456     default:
   1457         LOG_ERROR(BSL_LS_SOC_HASH,
   1458                   (BSL_META_U(unit,
   1459                               "soc_tr_l2_hash: invalid hash_sel %d\n"),
   1460                    hash_sel));
   1461         rv = 0;
   1462         break;
   1463     }
   1464 
   1465     return rv & SOC_CONTROL(unit)->hash_mask_l2x;
   1466 }
   1467 
   1468 STATIC int
   1469 _soc_tr_l2x_bridge_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1470 {
   1471     static soc_field_t field_list[] = {
   1472         KEY_TYPEf,
   1473         VLAN_IDf,
   1474         MAC_ADDRf,
   1475         INVALIDf
   1476     };
   1477 
   1478     return _soc_hash_generic_entry_to_key(unit, entry, key, L2Xm, field_list);
   1479 }
   1480 
   1481 #ifdef BCM_KATANA_SUPPORT
   1482 STATIC int
   1483 _soc_tr_l2x_bfd_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1484 {
   1485     static soc_field_t field_list[] = {
   1486         BFD__KEYf,
   1487         INVALIDf
   1488     };
   1489 
   1490     return _soc_hash_generic_entry_to_key(unit, entry, key, L2Xm, field_list);
   1491 }
   1492 #endif
   1493 
   1494 STATIC int
   1495 _soc_tr_l2x_scc_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1496 {
   1497     static soc_field_t field_list[] = {
   1498         KEY_TYPEf,
   1499         OVIDf,
   1500         INVALIDf
   1501     };
   1502 
   1503     return _soc_hash_generic_entry_to_key(unit, entry, key, L2Xm, field_list);
   1504 }
   1505 
   1506 STATIC int
   1507 _soc_tr_l2x_dcc_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1508 {
   1509     static soc_field_t field_list[] = {
   1510         KEY_TYPEf,
   1511         OVIDf,
   1512         IVIDf,
   1513         INVALIDf
   1514     };
   1515 
   1516     return _soc_hash_generic_entry_to_key(unit, entry, key, L2Xm, field_list);
   1517 }
   1518 
   1519 STATIC int
   1520 _soc_tr_l2x_vfi_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1521 {
   1522     static soc_field_t field_list[] = {
   1523         KEY_TYPEf,
   1524         VLAN_IDf,  /* padded from VFIf */
   1525         MAC_ADDRf,
   1526         INVALIDf
   1527     };
   1528     l2x_entry_t new_entry;
   1529     uint32 vfi;
   1530 
   1531     sal_memcpy(&new_entry, entry, sizeof(new_entry));
   1532     vfi = soc_mem_field32_get(unit, L2Xm, &new_entry, VFIf);
   1533     soc_mem_field32_set(unit, L2Xm, &new_entry, VLAN_IDf, vfi);
   1534 
   1535     return _soc_hash_generic_entry_to_key(unit, &new_entry, key, L2Xm,
   1536                                           field_list);
   1537 }
   1538 
   1539 #ifdef BCM_KATANA_SUPPORT
   1540 STATIC int
   1541 soc_kt_l2x_base_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1542 {
   1543 
   1544     switch (soc_mem_field32_get(unit, L2Xm, entry, KEY_TYPEf)) {
   1545     case KT_L2_HASH_KEY_TYPE_BRIDGE:
   1546         return _soc_tr_l2x_bridge_entry_to_key(unit, entry, key);
   1547         break;
   1548     case KT_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
   1549         return _soc_tr_l2x_scc_entry_to_key(unit, entry, key);
   1550     case KT_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT:
   1551         return _soc_tr_l2x_dcc_entry_to_key(unit, entry, key);
   1552         break;
   1553     case KT_L2_HASH_KEY_TYPE_VFI:
   1554         return _soc_tr_l2x_vfi_entry_to_key(unit, entry, key);
   1555         break;
   1556     case KT_L2_HASH_KEY_TYPE_BFD:
   1557         return _soc_tr_l2x_bfd_entry_to_key(unit, entry, key);
   1558         break;
   1559     default:
   1560         return 0;
   1561     }
   1562 }
   1563 #endif
   1564 
   1565 #ifdef BCM_TRIDENT_SUPPORT
   1566 STATIC int
   1567 _soc_td_l2x_vif_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1568 {
   1569     static soc_field_t field_list[] = {
   1570         KEY_TYPEf,
   1571         VIF__NAMESPACEf,
   1572         VIF__DST_VIFf,
   1573         VIF__Pf,
   1574         INVALIDf
   1575     };
   1576 
   1577     return _soc_hash_generic_entry_to_key(unit, entry, key, L2Xm, field_list);
   1578 }
   1579 
   1580 STATIC int
   1581 _soc_td_l2x_trill_access_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1582 {
   1583     static soc_field_t field_list[] = {
   1584         KEY_TYPEf,
   1585         TRILL_NONUC_ACCESS__VLAN_IDf,
   1586         TRILL_NONUC_ACCESS__MAC_ADDRf,
   1587         INVALIDf
   1588     };
   1589 
   1590     return _soc_hash_generic_entry_to_key(unit, entry, key, L2Xm, field_list);
   1591 }
   1592 
   1593 STATIC int
   1594 _soc_td_l2x_trill_network_long_entry_to_key(int unit, uint32 *entry,
   1595                                             uint8 *key)
   1596 {
   1597     static soc_field_t field_list[] = {
   1598         KEY_TYPEf,
   1599         TRILL_NONUC_NETWORK_LONG__VLAN_IDf,
   1600         TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf,
   1601         TRILL_NONUC_NETWORK_LONG__TREE_IDf,
   1602         INVALIDf
   1603     };
   1604 
   1605     return _soc_hash_generic_entry_to_key(unit, entry, key, L2Xm, field_list);
   1606 }
   1607 
   1608 STATIC int
   1609 _soc_td_l2x_trill_network_short_entry_to_key(int unit, uint32 *entry,
   1610                                              uint8 *key)
   1611 {
   1612     /* The format of the stream fed into hash calculation is the same as
   1613      * TRILL_NONUC_NETWORK_LONG except MAC_ADDRESS portion is all 0's */
   1614     static soc_field_t field_list[] = {
   1615         KEY_TYPEf,
   1616         TRILL_NONUC_NETWORK_LONG__VLAN_IDf,
   1617         TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf,
   1618         TRILL_NONUC_NETWORK_LONG__TREE_IDf,
   1619         INVALIDf
   1620     };
   1621     l2x_entry_t new_entry;
   1622     sal_mac_addr_t mac;
   1623     uint32 tree_id;
   1624 
   1625     sal_memcpy(&new_entry, entry, sizeof(new_entry));
   1626     /* VLAN_ID is at the same location for both SHORT and LONG view */
   1627     sal_memset(&mac, 0, sizeof(mac));
   1628     soc_mem_mac_addr_set(unit, L2Xm, &new_entry,
   1629                          TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac);
   1630     tree_id = soc_mem_field32_get(unit, L2Xm, entry,
   1631                                   TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
   1632     soc_mem_field32_set(unit, L2Xm, &new_entry,
   1633                         TRILL_NONUC_NETWORK_LONG__TREE_IDf, tree_id);
   1634 
   1635     return _soc_hash_generic_entry_to_key(unit, &new_entry, key, L2Xm,
   1636                                           field_list);
   1637 }
   1638 #endif /* BCM_TRIDENT_SUPPORT */
   1639 
   1640 int
   1641 soc_tr_l2x_base_entry_to_key(int unit, void *entry, uint8 *key)
   1642 {
   1643 #ifdef BCM_KATANA2_SUPPORT
   1644 if (SOC_IS_KATANA2(unit)) {
   1645     return soc_kt2_l2x_base_entry_to_key(unit, entry, key);
   1646 } else
   1647 #endif
   1648 
   1649 #ifdef BCM_KATANA_SUPPORT
   1650 if (SOC_IS_KATANA(unit)) {
   1651     return soc_kt_l2x_base_entry_to_key(unit, entry, key);
   1652 } else
   1653 #endif
   1654 
   1655 #ifdef BCM_GREYHOUND_SUPPORT
   1656     if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) {
   1657     return soc_greyhound_l2x_base_entry_to_key(unit, entry, key);
   1658 #ifdef BCM_GREYHOUND2_SUPPORT
   1659     } else if (SOC_IS_GREYHOUND2(unit)) {
   1660         return soc_gh2_l2x_base_entry_to_key(unit, entry, key);
   1661 #endif /* BCM_GREYHOUND2_SUPPORT */
   1662 } else
   1663 #endif /* BCM_GREYHOUND_SUPPORT */
   1664   {
   1665     switch (soc_mem_field32_get(unit, L2Xm, entry, KEY_TYPEf)) {
   1666     case TR_L2_HASH_KEY_TYPE_BRIDGE:
   1667         return _soc_tr_l2x_bridge_entry_to_key(unit, entry, key);
   1668     case TR_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
   1669         return _soc_tr_l2x_scc_entry_to_key(unit, entry, key);
   1670     case TR_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT:
   1671         return _soc_tr_l2x_dcc_entry_to_key(unit, entry, key);
   1672     case TR_L2_HASH_KEY_TYPE_VFI:
   1673         return _soc_tr_l2x_vfi_entry_to_key(unit, entry, key);
   1674 #ifdef BCM_TRIDENT_SUPPORT
   1675     case TR_L2_HASH_KEY_TYPE_VIF:
   1676         if (!soc_feature(unit, soc_feature_niv)) {
   1677             return 0;
   1678         }
   1679         return _soc_td_l2x_vif_entry_to_key(unit, entry, key);
   1680     case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
   1681         if (!soc_feature(unit, soc_feature_trill)) {
   1682             return 0;
   1683         }
   1684         return _soc_td_l2x_trill_access_entry_to_key(unit, entry, key);
   1685     case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
   1686         if (!soc_feature(unit, soc_feature_trill)) {
   1687             return 0;
   1688         }
   1689         return _soc_td_l2x_trill_network_long_entry_to_key(unit, entry, key);
   1690     case TR_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
   1691         if (!soc_feature(unit, soc_feature_trill)) {
   1692             return 0;
   1693         }
   1694         return _soc_td_l2x_trill_network_short_entry_to_key(unit, entry, key);
   1695 #endif /* BCM_TRIDENT_SUPPORT */
   1696     default:
   1697         return 0;
   1698     }
   1699   }
   1700 }
   1701 
   1702 uint32
   1703 soc_tr_l2x_entry_hash(int unit, int hash_sel, uint32 *entry)
   1704 {
   1705     int             key_nbits;
   1706     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1707     uint32          index;
   1708 
   1709     key_nbits = soc_tr_l2x_base_entry_to_key(unit, entry, key);
   1710     index = soc_tr_l2x_hash(unit, hash_sel, key_nbits, entry, key);
   1711 
   1712     return index;
   1713 }
   1714 
   1715 uint32
   1716 soc_tr_l2x_bank_entry_hash(int unit, int bank, uint32 *entry)
   1717 {
   1718     int             rv;
   1719     int             hash_sel = 0;
   1720 
   1721     rv = soc_fb_l2x_entry_bank_hash_sel_get(unit, bank, &hash_sel);
   1722     if (SOC_FAILURE(rv)) {
   1723         return 0;
   1724     }
   1725 
   1726     return soc_tr_l2x_entry_hash(unit, hash_sel, entry);
   1727 }
   1728 
   1729 int
   1730 soc_tr_hash_sel_get(int unit, soc_mem_t mem, int bank, int *hash_sel)
   1731 {
   1732     soc_reg_t reg;
   1733     soc_field_t field;
   1734     uint32 rval;
   1735 
   1736     field = bank > 0 ? HASH_SELECT_Bf : HASH_SELECT_Af;
   1737     switch (mem) {
   1738     case VLAN_XLATEm:
   1739     case VLAN_MACm:
   1740         reg = VLAN_XLATE_HASH_CONTROLr;
   1741         break;
   1742     case EGR_VLAN_XLATEm:
   1743         reg = EGR_VLAN_XLATE_HASH_CONTROLr;
   1744         break;
   1745     case MPLS_ENTRYm: 
   1746         reg = MPLS_ENTRY_HASH_CONTROLr;
   1747         break;
   1748     case AXP_WRX_WCDm:
   1749         reg = AXP_WRX_WCD_HASH_CTRLr;
   1750         field = bank > 0 ? SELECT_Bf : SELECT_Af;
   1751         break;
   1752     case AXP_WRX_SVP_ASSIGNMENTm:
   1753         reg = AXP_WRX_SVP_HASH_CTRLr;
   1754         field = bank > 0 ? SELECT_Bf : SELECT_Af;
   1755         break;
   1756 #ifdef BCM_TRIUMPH3_SUPPORT
   1757     case FT_SESSIONm:
   1758     case FT_SESSION_IPV6m:
   1759         reg = FT_HASH_CONTROLr;
   1760         field = bank > 0 ? HASH_SELECT_Bf : HASH_SELECT_Af;
   1761         break;
   1762 #endif /* BCM_TRIUMPH3_SUPPORT */
   1763 #if defined(INCLUDE_L3)
   1764 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1765     case L3_TUNNEL_SINGLEm:
   1766     case L3_TUNNEL_DOUBLEm:
   1767     case L3_TUNNEL_QUADm:
   1768         return (soc_tomahawk3_hash_offset_get(unit, mem, bank, hash_sel, NULL));
   1769 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1770 #endif /* INCLUDE_L3 */
   1771     default:
   1772         return SOC_E_UNAVAIL;
   1773     }
   1774 
   1775     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1776     *hash_sel = soc_reg_field_get(unit, reg, rval, field);
   1777 
   1778     return SOC_E_NONE;
   1779 }
   1780 
   1781 uint32
   1782 soc_tr_vlan_xlate_hash(int unit, int hash_sel, int key_nbits, void *base_entry,
   1783                        uint8 *key)
   1784 {
   1785     uint32 rv = 0;
   1786     uint32 fval[SOC_MAX_MEM_WORDS];
   1787 
   1788 #ifdef BCM_KATANA2_SUPPORT
   1789     if (SOC_IS_KATANA2(unit)) {
   1790         return soc_kt2_vlan_xlate_hash(unit, hash_sel, key_nbits, base_entry, key);
   1791     }
   1792 #endif
   1793 #ifdef BCM_HURRICANE3_SUPPORT
   1794     if (SOC_IS_HURRICANE3(unit)) {
   1795         return soc_hr3_vlan_xlate_hash(unit, hash_sel, key_nbits, base_entry, key);
   1796     }
   1797 #endif
   1798 #if defined(BCM_GREYHOUND2_SUPPORT)
   1799     if (SOC_IS_GREYHOUND2(unit)) {
   1800         return soc_gh2_vlan_xlate_hash(unit, hash_sel, key_nbits, base_entry, key);
   1801     }
   1802 #endif /* BCM_GREYHOUND2_SUPPORT */
   1803 
   1804     /*
   1805      * Cache bucket mask and shift amount for upper crc
   1806      */
   1807     if (SOC_CONTROL(unit)->hash_mask_vlan_mac == 0) {
   1808         uint32  mask;
   1809         int     bits;
   1810 
   1811         /* 8 Entries per bucket */
   1812         mask = soc_mem_index_max(unit, VLAN_MACm) >> 3;
   1813         bits = 0;
   1814         rv = 1;
   1815         while (rv && (mask & rv)) {
   1816             bits += 1;
   1817             rv <<= 1;
   1818         }
   1819 
   1820         /* For the Variants whose VLAN_XLATE (and VLAN_MAC) memory size are
   1821             limited by Bond Option, The shift amount should be based on the "Original"
   1822             memory size
   1823         */
   1824 #ifdef BCM_KATANA_SUPPORT
   1825         /* Sabre variants has VLAN_XLATE limited by bond option,
   1826             use the original 16K = 11 bits
   1827         */
   1828         if (SOC_IS_KATANA(unit)) {
   1829             bits = 11;
   1830         }
   1831 #endif
   1832         SOC_CONTROL(unit)->hash_mask_vlan_mac = mask;
   1833         SOC_CONTROL(unit)->hash_bits_vlan_mac = bits;
   1834     }
   1835 
   1836     switch (hash_sel) {
   1837     case FB_HASH_CRC16_UPPER:
   1838         rv = soc_crc16b(key, key_nbits);
   1839         rv >>= 16 - SOC_CONTROL(unit)->hash_bits_vlan_mac;
   1840         break;
   1841 
   1842     case FB_HASH_CRC16_LOWER:
   1843         rv = soc_crc16b(key, key_nbits);
   1844         break;
   1845 
   1846     case FB_HASH_LSB:
   1847         if (key_nbits == 0) {
   1848             return 0;
   1849         }
   1850         switch (soc_mem_field32_get(unit, VLAN_XLATEm, base_entry,
   1851                                     KEY_TYPEf)) {
   1852         case TR_VLXLT_HASH_KEY_TYPE_IVID_OVID:
   1853             rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OVIDf);
   1854             break;
   1855         case TR_VLXLT_HASH_KEY_TYPE_OTAG:
   1856             rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OTAGf);
   1857             break;
   1858         case TR_VLXLT_HASH_KEY_TYPE_ITAG:
   1859             rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, ITAGf);
   1860             break;
   1861         case TR_VLXLT_HASH_KEY_TYPE_VLAN_MAC:
   1862             soc_mem_field_get(unit, VLAN_MACm, base_entry, MAC_ADDRf, fval);
   1863             rv = fval[0];
   1864             break;
   1865         case TR_VLXLT_HASH_KEY_TYPE_OVID:
   1866             rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OVIDf);
   1867             break;
   1868         case TR_VLXLT_HASH_KEY_TYPE_IVID:
   1869             rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, IVIDf);
   1870             break;
   1871         case TR_VLXLT_HASH_KEY_TYPE_PRI_CFI:
   1872             /* Use only the upper 4 bit of OTAG */
   1873             rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry, OTAGf) >>
   1874                 12;
   1875             break;
   1876         case TR_VLXLT_HASH_KEY_TYPE_HPAE:
   1877             rv = soc_mem_field32_get(unit, VLAN_MACm, base_entry,
   1878                                      MAC_IP_BIND__SIPf);
   1879             break;
   1880         case TR_VLXLT_HASH_KEY_TYPE_VIF:
   1881         case TR_VLXLT_HASH_KEY_TYPE_VIF_VLAN:
   1882             rv = soc_mem_field32_get(unit, VLAN_XLATEm, base_entry,
   1883                                      VIF__SRC_VIFf);
   1884             break;
   1885         default:
   1886             rv = 0;
   1887             break;
   1888         }
   1889         break;
   1890 
   1891     case FB_HASH_ZERO:
   1892         rv = 0;
   1893         break;
   1894 
   1895     case FB_HASH_CRC32_UPPER:
   1896         rv = soc_crc32b(key, key_nbits);
   1897         rv >>= 32 - SOC_CONTROL(unit)->hash_bits_vlan_mac;
   1898         break;
   1899 
   1900     case FB_HASH_CRC32_LOWER:
   1901         rv = soc_crc32b(key, key_nbits);
   1902         break;
   1903 
   1904     default:
   1905         LOG_ERROR(BSL_LS_SOC_HASH,
   1906                   (BSL_META_U(unit,
   1907                               "soc_tr_vlan_xlate_hash: invalid hash_sel %d\n"),
   1908                    hash_sel));
   1909         rv = 0;
   1910         break;
   1911     }
   1912 
   1913     return rv & SOC_CONTROL(unit)->hash_mask_vlan_mac;
   1914 }
   1915 
   1916 STATIC int
   1917 _soc_tr_vlan_xlate_dtag_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1918 {
   1919     static soc_field_t field_list[] = {
   1920         KEY_TYPEf,
   1921         GLPf,
   1922         OVIDf,
   1923         IVIDf,
   1924         INVALIDf
   1925     };
   1926 
   1927     return _soc_hash_generic_entry_to_key(unit, entry, key, VLAN_XLATEm,
   1928                                           field_list);
   1929 }
   1930 
   1931 STATIC int
   1932 _soc_tr_vlan_xlate_otag_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1933 {
   1934     static soc_field_t field_list[] = {
   1935         KEY_TYPEf,
   1936         GLPf,
   1937         OTAGf,
   1938         INVALIDf
   1939     };
   1940 
   1941     return _soc_hash_generic_entry_to_key(unit, entry, key, VLAN_XLATEm,
   1942                                           field_list);
   1943 }
   1944 
   1945 STATIC int
   1946 _soc_tr_vlan_xlate_itag_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1947 {
   1948     static soc_field_t field_list[] = {
   1949         KEY_TYPEf,
   1950         GLPf,
   1951         ITAGf,
   1952         INVALIDf
   1953     };
   1954 
   1955     return _soc_hash_generic_entry_to_key(unit, entry, key, VLAN_XLATEm,
   1956                                           field_list);
   1957 }
   1958 
   1959 STATIC int
   1960 _soc_tr_vlan_mac_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1961 {
   1962     static soc_field_t field_list[] = {
   1963         KEY_TYPEf,
   1964         MAC_ADDRf,
   1965         INVALIDf
   1966     };
   1967 
   1968     return _soc_hash_generic_entry_to_key(unit, entry, key, VLAN_MACm,
   1969                                           field_list);
   1970 }
   1971 
   1972 STATIC int
   1973 _soc_tr_vlan_xlate_ovid_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1974 {
   1975     static soc_field_t field_list[] = {
   1976         KEY_TYPEf,
   1977         GLPf,
   1978         OVIDf,
   1979         IVIDf, /* zero */
   1980         INVALIDf
   1981     };
   1982     vlan_xlate_entry_t new_entry;
   1983 
   1984     sal_memcpy(&new_entry, entry, sizeof(new_entry));
   1985     soc_mem_field32_set(unit, VLAN_XLATEm, &new_entry, IVIDf, 0);
   1986 
   1987     return _soc_hash_generic_entry_to_key(unit, &new_entry, key, VLAN_XLATEm,
   1988                                           field_list);
   1989 }
   1990 
   1991 STATIC int
   1992 _soc_tr_vlan_xlate_ivid_entry_to_key(int unit, uint32 *entry, uint8 *key)
   1993 {
   1994     static soc_field_t field_list[] = {
   1995         KEY_TYPEf,
   1996         GLPf,
   1997         OVIDf, /* zero */
   1998         IVIDf,
   1999         INVALIDf
   2000     };
   2001     vlan_xlate_entry_t new_entry;
   2002 
   2003     sal_memcpy(&new_entry, entry, sizeof(new_entry));
   2004     soc_mem_field32_set(unit, VLAN_XLATEm, &new_entry, OVIDf, 0);
   2005 
   2006     return _soc_hash_generic_entry_to_key(unit, &new_entry, key, VLAN_XLATEm,
   2007                                           field_list);
   2008 }
   2009 
   2010 STATIC int
   2011 _soc_tr_vlan_xlate_pri_cfi_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2012 {
   2013     static soc_field_t field_list[] = {
   2014         KEY_TYPEf,
   2015         GLPf,
   2016         OTAGf, /* OVID portion of this field is zero */
   2017         INVALIDf
   2018     };
   2019 
   2020     vlan_xlate_entry_t new_entry;
   2021 
   2022     sal_memcpy(&new_entry, entry, sizeof(new_entry));
   2023     soc_mem_field32_set(unit, VLAN_XLATEm, &new_entry, OVIDf, 0);
   2024 
   2025     return _soc_hash_generic_entry_to_key(unit, &new_entry, key, VLAN_XLATEm,
   2026                                           field_list);
   2027 }
   2028 
   2029 #ifdef BCM_TRIUMPH2_SUPPORT
   2030 STATIC int
   2031 _soc_tr2_vlan_xlate_hpae_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2032 {
   2033     static soc_field_t field_list[] = {
   2034         KEY_TYPEf,
   2035         MAC_IP_BIND__SIPf,
   2036         INVALIDf
   2037     };
   2038 
   2039     return _soc_hash_generic_entry_to_key(unit, entry, key, VLAN_MACm,
   2040                                           field_list);
   2041 }
   2042 #endif /* BCM_TRIUMPH2_SUPPORT */
   2043 
   2044 #ifdef BCM_TRIDENT_SUPPORT
   2045 STATIC int
   2046 _soc_td_vlan_xlate_vif_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2047 {
   2048     static soc_field_t field_list[] = {
   2049         KEY_TYPEf,
   2050         VIF__GLPf,
   2051         VIF__SRC_VIFf,
   2052         INVALIDf
   2053     };
   2054 
   2055     return _soc_hash_generic_entry_to_key(unit, entry, key, VLAN_XLATEm,
   2056                                           field_list);
   2057 }
   2058 
   2059 STATIC int
   2060 _soc_td_vlan_xlate_vif_vlan_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2061 {
   2062     static soc_field_t field_list[] = {
   2063         KEY_TYPEf,
   2064         VIF__GLPf,
   2065         VIF__SRC_VIFf,
   2066         VIF__VLANf,
   2067         INVALIDf
   2068     };
   2069 
   2070     return _soc_hash_generic_entry_to_key(unit, entry, key, VLAN_XLATEm,
   2071                                           field_list);
   2072 }
   2073 #endif /* BCM_TRIDENT_SUPPORT */
   2074 
   2075 int
   2076 soc_tr_vlan_xlate_base_entry_to_key(int unit, void *entry, uint8 *key)
   2077 {
   2078 #ifdef BCM_KATANA2_SUPPORT
   2079     if (SOC_IS_KATANA2(unit)) {
   2080         return soc_kt2_vlan_xlate_base_entry_to_key(unit, entry, key);
   2081     }
   2082 #endif
   2083 #ifdef BCM_HURRICANE3_SUPPORT
   2084     if (SOC_IS_HURRICANE3(unit)) {
   2085         return soc_hr3_vlan_xlate_base_entry_to_key(unit, entry, key);
   2086     }
   2087 #endif
   2088 #if defined(BCM_GREYHOUND2_SUPPORT)
   2089     if (SOC_IS_GREYHOUND2(unit)) {
   2090         return soc_gh2_vlan_xlate_base_entry_to_key(unit, entry, key);
   2091     }
   2092 #endif /* BCM_GREYHOUND2_SUPPORT */
   2093 
   2094     switch (soc_mem_field32_get(unit, VLAN_XLATEm, entry, KEY_TYPEf)) {
   2095     case TR_VLXLT_HASH_KEY_TYPE_IVID_OVID:
   2096         return _soc_tr_vlan_xlate_dtag_entry_to_key(unit, entry, key);
   2097     case TR_VLXLT_HASH_KEY_TYPE_OTAG:
   2098         return _soc_tr_vlan_xlate_otag_entry_to_key(unit, entry, key);
   2099     case TR_VLXLT_HASH_KEY_TYPE_ITAG:
   2100         return _soc_tr_vlan_xlate_itag_entry_to_key(unit, entry, key);
   2101     case TR_VLXLT_HASH_KEY_TYPE_VLAN_MAC:
   2102         return _soc_tr_vlan_mac_entry_to_key(unit, entry, key);
   2103     case TR_VLXLT_HASH_KEY_TYPE_OVID:
   2104         return _soc_tr_vlan_xlate_ovid_entry_to_key(unit, entry, key);
   2105     case TR_VLXLT_HASH_KEY_TYPE_IVID:
   2106         return _soc_tr_vlan_xlate_ivid_entry_to_key(unit, entry, key);
   2107     case TR_VLXLT_HASH_KEY_TYPE_PRI_CFI:
   2108         return _soc_tr_vlan_xlate_pri_cfi_entry_to_key(unit, entry, key);
   2109 #ifdef BCM_TRIUMPH2_SUPPORT
   2110     case TR_VLXLT_HASH_KEY_TYPE_HPAE:
   2111         if (!soc_feature(unit, soc_feature_ip_source_bind)) {
   2112             return 0;
   2113         }
   2114         return _soc_tr2_vlan_xlate_hpae_entry_to_key(unit, entry, key);
   2115 #endif /* BCM_TRIUMPH2_SUPPORT */
   2116 #ifdef BCM_TRIDENT_SUPPORT
   2117     case TR_VLXLT_HASH_KEY_TYPE_VIF:
   2118         if (!soc_feature(unit, soc_feature_niv)) {
   2119             return 0;
   2120         }
   2121         return _soc_td_vlan_xlate_vif_entry_to_key(unit, entry, key);
   2122     case TR_VLXLT_HASH_KEY_TYPE_VIF_VLAN:
   2123         if (!soc_feature(unit, soc_feature_niv)) {
   2124             return 0;
   2125         }
   2126         return _soc_td_vlan_xlate_vif_vlan_entry_to_key(unit, entry, key);
   2127 #endif /* BCM_TRIDENT_SUPPORT */
   2128     default:
   2129         return 0;
   2130     }
   2131 }
   2132 
   2133 uint32
   2134 soc_tr_vlan_xlate_entry_hash(int unit, int hash_sel, uint32 *entry)
   2135 {
   2136     int             key_nbits;
   2137     uint8           key[SOC_MAX_MEM_WORDS * 4];
   2138     uint32          index;
   2139 
   2140     key_nbits = soc_tr_vlan_xlate_base_entry_to_key(unit, entry, key);
   2141 
   2142     index = soc_tr_vlan_xlate_hash(unit, hash_sel, key_nbits, entry, key);
   2143 
   2144     return index;
   2145 }
   2146 
   2147 uint32
   2148 soc_tr_vlan_xlate_bank_entry_hash(int unit, int bank, uint32 *entry)
   2149 {
   2150     int     hash_sel;
   2151 
   2152     SOC_IF_ERROR_RETURN
   2153         (soc_tr_hash_sel_get(unit, VLAN_XLATEm, bank, &hash_sel));
   2154     return soc_tr_vlan_xlate_entry_hash(unit, hash_sel, entry);
   2155 }
   2156 
   2157 uint32
   2158 soc_tr_egr_vlan_xlate_hash(int unit, int hash_sel, int key_nbits,
   2159                            void *base_entry, uint8 *key)
   2160 {
   2161     uint32 rv;
   2162     uint32 fval[SOC_MAX_MEM_WORDS];
   2163 
   2164 #ifdef BCM_KATANA2_SUPPORT
   2165     if (SOC_IS_KATANA2(unit)) {
   2166         return soc_kt2_egr_vlan_xlate_hash(unit, hash_sel, key_nbits, base_entry, key);
   2167     }
   2168 #endif
   2169 
   2170     /*
   2171      * Cache bucket mask and shift amount for upper crc
   2172      */
   2173     if (SOC_CONTROL(unit)->hash_mask_egr_vlan_xlate == 0) {
   2174         uint32  mask;
   2175         int     bits;
   2176 
   2177         /* 8 Entries per bucket */
   2178         mask = soc_mem_index_max(unit, EGR_VLAN_XLATEm) >> 3;
   2179         bits = 0;
   2180         rv = 1;
   2181         while (rv && (mask & rv)) {
   2182             bits += 1;
   2183             rv <<= 1;
   2184         }
   2185         SOC_CONTROL(unit)->hash_mask_egr_vlan_xlate = mask;
   2186         SOC_CONTROL(unit)->hash_bits_egr_vlan_xlate = bits;
   2187     }
   2188 
   2189     switch (hash_sel) {
   2190     case FB_HASH_CRC16_UPPER:
   2191         rv = soc_crc16b(key, key_nbits);
   2192         rv >>= 16 - SOC_CONTROL(unit)->hash_bits_egr_vlan_xlate;
   2193         break;
   2194 
   2195     case FB_HASH_CRC16_LOWER:
   2196         rv = soc_crc16b(key, key_nbits);
   2197         break;
   2198 
   2199     case FB_HASH_LSB:
   2200         if (key_nbits == 0) {
   2201             return 0;
   2202         }
   2203         if (SOC_MEM_FIELD_VALID(unit, EGR_VLAN_XLATEm, ENTRY_TYPEf)) {
   2204             switch (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, base_entry,
   2205                                         ENTRY_TYPEf)) {
   2206             case 0: /* VLAN_XLATE */
   2207             case 1: /* VLAN_XLATE_DVP */
   2208             case 2: /* VLAN_XLATE_WLAN */
   2209                 rv = soc_mem_field32_get(unit, EGR_VLAN_XLATEm, base_entry,
   2210                                          OVIDf);
   2211                 break;
   2212             case 3: /* ISID_XLATE */
   2213             case 4: /* ISID_DVP_XLATE */
   2214                 rv = soc_mem_field32_get(unit, EGR_VLAN_XLATEm, base_entry,
   2215                                          MIM_ISID__VFIf) |
   2216                     (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, base_entry,
   2217                                          MIM_ISID__DVPf) <<
   2218                      soc_mem_field_length(unit, EGR_VLAN_XLATEm,
   2219                                           MIM_ISID__VFIf));
   2220                 break;
   2221             case 5: /* WLAN_SVP_TUNNEL */
   2222                 rv = soc_mem_field32_get(unit, EGR_VLAN_XLATEm, base_entry,
   2223                                          WLAN_SVP__TUNNEL_IDf);
   2224                 break;
   2225             case 6: /* WLAN_SVP_BSSID */
   2226                 soc_mem_field_get(unit, MPLS_ENTRYm, base_entry,
   2227                                   WLAN_SVP__BSSIDf, fval);
   2228                 rv = fval[0];
   2229                 break;
   2230             case 7: /* WLAN_SVP_BSSID_RID */
   2231                 soc_mem_field_get(unit, MPLS_ENTRYm, base_entry,
   2232                                   WLAN_SVP__BSSIDf, fval);
   2233                 rv = soc_mem_field32_get(unit, EGR_VLAN_XLATEm, base_entry,
   2234                                          WLAN_SVP__RIDf) |
   2235                     (fval[0] << soc_mem_field_length(unit, EGR_VLAN_XLATEm,
   2236                                                      WLAN_SVP__RIDf));
   2237                 break;
   2238             default:
   2239                 rv = 0;
   2240                 break;
   2241             }
   2242         } else {
   2243             rv = soc_mem_field32_get(unit, EGR_VLAN_XLATEm, base_entry, OVIDf);
   2244         }
   2245         break;
   2246 
   2247     case FB_HASH_ZERO:
   2248         rv = 0;
   2249         break;
   2250 
   2251     case FB_HASH_CRC32_UPPER:
   2252         rv = soc_crc32b(key, key_nbits);
   2253         rv >>= 32 - SOC_CONTROL(unit)->hash_bits_egr_vlan_xlate;
   2254         break;
   2255 
   2256     case FB_HASH_CRC32_LOWER:
   2257         rv = soc_crc32b(key, key_nbits);
   2258         break;
   2259 
   2260     default:
   2261         LOG_ERROR(BSL_LS_SOC_HASH,
   2262                   (BSL_META_U(unit,
   2263                               "soc_tr_vlan_xlate_hash: invalid hash_sel %d\n"),
   2264                    hash_sel));
   2265         rv = 0;
   2266         break;
   2267     }
   2268 
   2269     return rv & SOC_CONTROL(unit)->hash_mask_egr_vlan_xlate;
   2270 }
   2271 
   2272 STATIC int
   2273 _soc_tr_egr_vlan_xlate_xlate_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2274 {
   2275     static soc_field_t field_list[] = {
   2276         ENTRY_TYPEf,
   2277         OVIDf,
   2278         PORT_GROUP_IDf,
   2279         NUM_SOC_FIELD, /* skip mark */
   2280         IVIDf,
   2281         INVALIDf
   2282     };
   2283 
   2284     if (SOC_IS_TD_TT(unit)) {
   2285         field_list[2] = DST_MODIDf;
   2286         field_list[3] = DST_PORTf;
   2287     } else if (SOC_IS_KATANA(unit) || SOC_IS_GREYHOUND(unit) ||
   2288             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2289         field_list[3] = DUMMY_BITSf; 
   2290     } else if (SOC_MEM_FIELD_VALID(unit, EGR_VLAN_XLATEm, DVPf)) {
   2291         field_list[2] = DVPf;
   2292     }
   2293 
   2294     return _soc_hash_generic_entry_to_key(unit, entry, key, EGR_VLAN_XLATEm,
   2295                                           field_list);
   2296 }
   2297 
   2298 #ifdef BCM_TRIUMPH2_SUPPORT
   2299 STATIC int
   2300 _soc_tr_egr_vlan_xlate_mim_isid_entry_to_key(int unit, uint32 *entry,
   2301                                              uint8 *key)
   2302 {
   2303     static soc_field_t field_list[] = {
   2304         ENTRY_TYPEf,
   2305         MIM_ISID__VFIf,
   2306         MIM_ISID__DVPf,
   2307         INVALIDf
   2308     };
   2309 
   2310     return _soc_hash_generic_entry_to_key(unit, entry, key, EGR_VLAN_XLATEm,
   2311                                           field_list);
   2312 }
   2313 
   2314 STATIC int
   2315 _soc_tr_egr_vlan_xlate_wlan_svp_entry_to_key(int unit, uint32 *entry,
   2316                                              uint8 *key)
   2317 {
   2318     static soc_field_t field_list[] = {
   2319         ENTRY_TYPEf,
   2320         WLAN_SVP__RIDf,
   2321         WLAN_SVP__BSSIDf,
   2322         INVALIDf
   2323     };
   2324 
   2325     return _soc_hash_generic_entry_to_key(unit, entry, key, EGR_VLAN_XLATEm,
   2326                                           field_list);
   2327 }
   2328 #endif /* BCM_TRIUMPH2_SUPPORT */
   2329 
   2330 int
   2331 soc_tr_egr_vlan_xlate_base_entry_to_key(int unit, void *entry, uint8 *key)
   2332 {
   2333 #ifdef BCM_KATANA2_SUPPORT
   2334     if (SOC_IS_KATANA2(unit)) {
   2335         return soc_kt2_egr_vlan_xlate_base_entry_to_key(unit, entry, key);
   2336     }
   2337 #endif
   2338 
   2339 #ifdef BCM_TRIUMPH2_SUPPORT
   2340     if (SOC_MEM_FIELD_VALID(unit, EGR_VLAN_XLATEm, ENTRY_TYPEf)) {
   2341         switch (soc_mem_field32_get(unit, EGR_VLAN_XLATEm, entry,
   2342                                     ENTRY_TYPEf)) {
   2343         case 0: /* VLAN_XLATE */
   2344         case 1: /* VLAN_XLATE_DVP */
   2345             return _soc_tr_egr_vlan_xlate_xlate_entry_to_key(unit, entry, key);
   2346         case 2: /* VLAN_XLATE_WLAN */
   2347             if (!soc_feature(unit, soc_feature_wlan)) {
   2348                 return 0;
   2349             }
   2350             return _soc_tr_egr_vlan_xlate_xlate_entry_to_key(unit, entry, key);
   2351         case 3: /* ISID_XLATE */
   2352         case 4: /* ISID_DVP_XLATE */
   2353             if (!soc_feature(unit, soc_feature_mim)) {
   2354                 return 0;
   2355             }
   2356             return _soc_tr_egr_vlan_xlate_mim_isid_entry_to_key(unit, entry,
   2357                                                                 key);
   2358         case 5: /* WLAN_SVP_TUNNEL */
   2359         case 6: /* WLAN_SVP_BSSID */
   2360         case 7: /* WLAN_SVP_BSSID_RID */
   2361             if (!soc_feature(unit, soc_feature_wlan)) {
   2362                 return 0;
   2363             }
   2364             return _soc_tr_egr_vlan_xlate_wlan_svp_entry_to_key(unit, entry,
   2365                                                                 key);
   2366         default:
   2367             return 0;
   2368         }
   2369     }
   2370 #endif /* BCM_TRIUMPH2_SUPPORT */
   2371 
   2372     return _soc_tr_egr_vlan_xlate_xlate_entry_to_key(unit, entry, key);
   2373 }
   2374 
   2375 uint32
   2376 soc_tr_egr_vlan_xlate_entry_hash(int unit, int hash_sel, uint32 *entry)
   2377 {
   2378     int             key_nbits;
   2379     uint8           key[SOC_MAX_MEM_WORDS * 4];
   2380     uint32          index;
   2381 
   2382     key_nbits = soc_tr_egr_vlan_xlate_base_entry_to_key(unit, entry, key);
   2383     index = soc_tr_egr_vlan_xlate_hash(unit, hash_sel, key_nbits, entry, key);
   2384 
   2385     return index;
   2386 }
   2387 
   2388 uint32
   2389 soc_tr_egr_vlan_xlate_bank_entry_hash(int unit, int bank, uint32 *entry)
   2390 {
   2391     int     hash_sel;
   2392 
   2393     SOC_IF_ERROR_RETURN
   2394         (soc_tr_hash_sel_get(unit, EGR_VLAN_XLATEm, bank, &hash_sel));
   2395     return soc_tr_egr_vlan_xlate_entry_hash(unit, hash_sel, entry);
   2396 }
   2397 
   2398 uint32
   2399 soc_tr_mpls_hash(int unit, int hash_sel, int key_nbits, void *base_entry,
   2400                  uint8 *key)
   2401 {
   2402     uint32 rv;
   2403     uint32 fval[SOC_MAX_MEM_WORDS];
   2404 #ifdef BCM_SABER2_SUPPORT
   2405         uint16 dev_id;
   2406         uint8 rev_id;
   2407 #endif
   2408 
   2409     /*
   2410      * Cache bucket mask and shift amount for upper crc
   2411      */
   2412     if (SOC_CONTROL(unit)->hash_mask_mpls == 0) {
   2413         uint32  mask;
   2414         int     bits;
   2415 
   2416         /* 8 Entries per bucket */
   2417         mask = soc_mem_index_max(unit, MPLS_ENTRYm) >> 3;
   2418         bits = 0;
   2419         rv = 1;
   2420         while (rv && (mask & rv)) {
   2421             bits += 1;
   2422             rv <<= 1;
   2423         }
   2424 
   2425         /* For the Variants whose MPLS_ENTRY memory size is limited by Bond
   2426             Option, The shift amount should be based on the "Original" size
   2427         */
   2428 #ifdef BCM_SABER2_SUPPORT
   2429         /* Dagger2 variants has MPLS_ENTRY limited by bond option,
   2430          * use the original 4K = 9 bits
   2431          */
   2432         soc_cm_get_id(unit, &dev_id, &rev_id);
   2433         if (SOC_IS_SABER2(unit) && (dev_id == BCM56233_DEVICE_ID)) {
   2434             bits = 9;
   2435         }
   2436 #endif
   2437 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT)
   2438         /* Saber and Dagger variants has MPLS_ENTRY limited by bond option,
   2439          * use the original 4K = 9 bits
   2440          */
   2441         if (SOC_IS_KATANA(unit) || SOC_IS_ENDURO(unit)) {
   2442             bits = 9;
   2443         }
   2444 #endif /* BCM_KATANA_SUPPORT || BCM_ENDURO_SUPPORT */
   2445         SOC_CONTROL(unit)->hash_mask_mpls = mask;
   2446         SOC_CONTROL(unit)->hash_bits_mpls = bits;
   2447     }
   2448 
   2449     switch (hash_sel) {
   2450     case FB_HASH_CRC16_UPPER:
   2451         rv = soc_crc16b(key, key_nbits);
   2452         rv >>= 16 - SOC_CONTROL(unit)->hash_bits_mpls;
   2453         break;
   2454 
   2455     case FB_HASH_CRC16_LOWER:
   2456         rv = soc_crc16b(key, key_nbits);
   2457         break;
   2458 
   2459     case FB_HASH_LSB:
   2460         if (key_nbits == 0) {
   2461             return 0;
   2462         }
   2463         if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, KEY_TYPEf)) {
   2464             switch (soc_mem_field32_get(unit, MPLS_ENTRYm, base_entry,
   2465                                         KEY_TYPEf)) {
   2466             case 0: /* MPLS */
   2467                 rv = soc_mem_field32_get(unit, MPLS_ENTRYm, base_entry,
   2468                                          MPLS_LABELf);
   2469                 break;
   2470             case 1: /* MIM_NVP */
   2471                 soc_mem_field_get(unit, MPLS_ENTRYm, base_entry,
   2472                                   MIM_NVP__BMACSAf, fval);
   2473                 rv = fval[0];
   2474                 break;
   2475             case 2: /* MIM_ISID */
   2476             case 3: /* MIM_ISID_SVP */
   2477                 rv = soc_mem_field32_get(unit, MPLS_ENTRYm, base_entry,
   2478                                          MIM_ISID__ISIDf);
   2479                 break;
   2480             case 4: /* WLAN_MAC */
   2481                 soc_mem_field_get(unit, MPLS_ENTRYm, base_entry,
   2482                                   WLAN_MAC__MAC_ADDRf, fval);
   2483                 rv = fval[0];
   2484                 break;
   2485             case 5: /* TRILL */
   2486                 rv = soc_mem_field32_get(unit, MPLS_ENTRYm, base_entry,
   2487                                          TRILL__RBRIDGE_NICKNAMEf);
   2488                 break;
   2489             default:
   2490                 rv = 0;
   2491                 break;
   2492             }
   2493         } else {
   2494             rv = soc_mem_field32_get(unit, MPLS_ENTRYm, base_entry,
   2495                                      MPLS_LABELf);
   2496         }
   2497         break;
   2498 
   2499     case FB_HASH_ZERO:
   2500         rv = 0;
   2501         break;
   2502 
   2503     case FB_HASH_CRC32_UPPER:
   2504         rv = soc_crc32b(key, key_nbits);
   2505         rv >>= 32 - SOC_CONTROL(unit)->hash_bits_mpls;
   2506         break;
   2507 
   2508     case FB_HASH_CRC32_LOWER:
   2509         rv = soc_crc32b(key, key_nbits);
   2510         break;
   2511 
   2512     default:
   2513         LOG_ERROR(BSL_LS_SOC_HASH,
   2514                   (BSL_META_U(unit,
   2515                               "soc_tr_mpls_hash: invalid hash_sel %d\n"),
   2516                    hash_sel));
   2517         rv = 0;
   2518         break;
   2519     }
   2520 
   2521     return rv & SOC_CONTROL(unit)->hash_mask_mpls;
   2522 }
   2523 
   2524 STATIC int
   2525 _soc_tr_mpls_legacy_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2526 {
   2527     static soc_field_t field_list[] = {
   2528         KEY_TYPEf,
   2529         PORT_NUMf,
   2530         MODULE_IDf,
   2531         Tf,
   2532         MPLS_LABELf,
   2533         INVALIDf
   2534     };
   2535 
   2536     return _soc_hash_generic_entry_to_key(unit, entry, key, MPLS_ENTRYm,
   2537                                           field_list);
   2538 }
   2539 
   2540 #ifdef BCM_TRIUMPH2_SUPPORT
   2541 STATIC int
   2542 _soc_tr_mpls_mim_nvp_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2543 {
   2544     static soc_field_t field_list[] = {
   2545         KEY_TYPEf,
   2546         MIM_NVP__BVIDf,
   2547         MIM_NVP__BMACSAf,
   2548         INVALIDf
   2549     };
   2550 
   2551     return _soc_hash_generic_entry_to_key(unit, entry, key, MPLS_ENTRYm,
   2552                                           field_list);
   2553 }
   2554 
   2555 STATIC int
   2556 _soc_tr_mpls_mim_isid_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2557 {
   2558     static soc_field_t field_list[] = {
   2559         KEY_TYPEf,
   2560         MIM_ISID__ISIDf,
   2561         INVALIDf
   2562     };
   2563 
   2564     return _soc_hash_generic_entry_to_key(unit, entry, key, MPLS_ENTRYm,
   2565                                           field_list);
   2566 }
   2567 
   2568 STATIC int
   2569 _soc_tr_mpls_mim_isid_svp_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2570 {
   2571     static soc_field_t field_list[] = {
   2572         KEY_TYPEf,
   2573         MIM_ISID__ISIDf,
   2574         MIM_ISID__SVPf,
   2575         INVALIDf
   2576     };
   2577 
   2578     return _soc_hash_generic_entry_to_key(unit, entry, key, MPLS_ENTRYm,
   2579                                           field_list);
   2580 }
   2581 
   2582 STATIC int
   2583 _soc_tr_mpls_wlan_mac_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2584 {
   2585     static soc_field_t field_list[] = {
   2586         KEY_TYPEf,
   2587         WLAN_MAC__MAC_ADDRf,
   2588         INVALIDf
   2589     };
   2590 
   2591     return _soc_hash_generic_entry_to_key(unit, entry, key, MPLS_ENTRYm,
   2592                                           field_list);
   2593 }
   2594 #endif /* BCM_TRIUMPH2_SUPPORT */
   2595 
   2596 #ifdef BCM_TRIDENT_SUPPORT
   2597 STATIC int
   2598 _soc_tr_mpls_trill_entry_to_key(int unit, uint32 *entry, uint8 *key)
   2599 {
   2600     static soc_field_t field_list[] = {
   2601         KEY_TYPEf,
   2602         TRILL__RBRIDGE_NICKNAMEf,
   2603         INVALIDf
   2604     };
   2605 
   2606     return _soc_hash_generic_entry_to_key(unit, entry, key, MPLS_ENTRYm,
   2607                                           field_list);
   2608 }
   2609 #endif /* BCM_TRIDENT_SUPPORT */
   2610 
   2611 int
   2612 soc_tr_mpls_base_entry_to_key(int unit, void *entry, uint8 *key)
   2613 {
   2614 #ifdef BCM_KATANA2_SUPPORT
   2615     if (SOC_IS_KATANA2(unit)) {
   2616         return soc_kt2_mpls_base_entry_to_key(unit, entry, key);
   2617     }
   2618 #endif
   2619     
   2620 #ifdef BCM_TRIUMPH2_SUPPORT
   2621     if (SOC_MEM_FIELD_VALID(unit, MPLS_ENTRYm, KEY_TYPEf)) {
   2622         switch (soc_mem_field32_get(unit, MPLS_ENTRYm, entry, KEY_TYPEf)) {
   2623         case 0: /* MPLS */
   2624             return _soc_tr_mpls_legacy_entry_to_key(unit, entry, key);
   2625         case 1: /* MIM_NVP */
   2626             if (!soc_feature(unit, soc_feature_mim)) {
   2627                 return 0;
   2628             }
   2629             return _soc_tr_mpls_mim_nvp_entry_to_key(unit, entry, key);
   2630         case 2: /* MIM_ISID */
   2631             if (!soc_feature(unit, soc_feature_mim)) {
   2632                 return 0;
   2633             }
   2634             return _soc_tr_mpls_mim_isid_entry_to_key(unit, entry, key);
   2635         case 3: /* MIM_ISID_SVP */
   2636             if (!soc_feature(unit, soc_feature_mim)) {
   2637                 return 0;
   2638             }
   2639             return _soc_tr_mpls_mim_isid_svp_entry_to_key(unit, entry, key);
   2640         case 4: /* WLAN_MAC */
   2641             if (!soc_feature(unit, soc_feature_wlan)) {
   2642                 return 0;
   2643             }
   2644             return _soc_tr_mpls_wlan_mac_entry_to_key(unit, entry, key);
   2645 #ifdef BCM_TRIDENT_SUPPORT
   2646         case 5: /* TRILL */
   2647             if (!soc_feature(unit, soc_feature_trill)) {
   2648                 return 0;
   2649             }
   2650             return _soc_tr_mpls_trill_entry_to_key(unit, entry, key);
   2651 #endif /* BCM_TRIDENT_SUPPORT */
   2652         default:
   2653             return 0;
   2654         }
   2655     }
   2656 #endif /* BCM_TRIUMPH2_SUPPORT */
   2657 
   2658     return _soc_tr_mpls_legacy_entry_to_key(unit, entry, key);
   2659 
   2660 }
   2661 
   2662 uint32
   2663 soc_tr_mpls_entry_hash(int unit, int hash_sel, uint32 *entry)
   2664 {
   2665     int             key_nbits;
   2666     uint8           key[SOC_MAX_MEM_WORDS * 4];
   2667     uint32          index;
   2668 
   2669     key_nbits = soc_tr_mpls_base_entry_to_key(unit, entry, key);
   2670     index = soc_tr_mpls_hash(unit, hash_sel, key_nbits, entry, key);
   2671 
   2672     return index;
   2673 }
   2674 
   2675 uint32
   2676 soc_tr_mpls_bank_entry_hash(int unit, int bank, uint32 *entry)
   2677 {
   2678     int     hash_sel;
   2679     
   2680     SOC_IF_ERROR_RETURN
   2681         (soc_tr_hash_sel_get(unit, MPLS_ENTRYm, bank, &hash_sel));
   2682     return soc_tr_mpls_entry_hash(unit, hash_sel, entry);
   2683 }
   2684 #endif /* BCM_TRIUMPH_SUPPORT || BCM_SCORPION_SUPPORT */
   2685 
   2686 #ifdef BCM_TRIUMPH3_SUPPORT
   2687 int
   2688 soc_tr3_ft_session_entry_to_key(int unit, soc_mem_t mem, void *entry, uint8 *key)
   2689 {
   2690     static soc_field_t field_list_ipv4[] = {
   2691         KEYf,
   2692         INVALIDf
   2693     };
   2694     static soc_field_t field_list_ipv6[] = {
   2695         KEYf,
   2696         IPV6_LOWER_KEYf,
   2697         INVALIDf
   2698     };
   2699 
   2700     if (mem == FT_SESSIONm || mem == FT_SESSION_IPV6m) {
   2701         switch (soc_mem_field32_get(unit, mem, entry,
   2702                                     KEY_TYPEf)) {
   2703         case 0x01: /* IPv4 entry */
   2704             return _soc_hash_generic_entry_to_key(unit, entry, key, mem, field_list_ipv4);
   2705             break;
   2706         case 0x02: /* IPv6 upper - not sure if these can be handled from same entry */
   2707         case 0x03: /* IPv6 lower */
   2708             return _soc_hash_generic_entry_to_key(unit, entry, key, mem, field_list_ipv6);
   2709             break;
   2710         default:
   2711             return 0;
   2712             break;
   2713         }
   2714     }
   2715 
   2716     return 0;
   2717 }
   2718 
   2719 int
   2720 soc_tr3_wlan_base_entry_to_key(int unit, soc_mem_t mem, void *entry, uint8 *key)
   2721 {
   2722     static soc_field_t field_list_port1[] = {
   2723         TUNNEL_IDf,
   2724         INVALIDf
   2725     };
   2726     static soc_field_t field_list_port2[] = {
   2727         BSSIDf,
   2728         INVALIDf
   2729     };
   2730     static soc_field_t field_list_port3[] = {
   2731         RIDf,
   2732         BSSIDf,
   2733         INVALIDf
   2734     };
   2735     static soc_field_t field_list_client[] = {
   2736         MAC_ADDRf,
   2737         INVALIDf
   2738     };
   2739 
   2740     if (mem == AXP_WRX_SVP_ASSIGNMENTm) {
   2741         switch (soc_mem_field32_get(unit, AXP_WRX_SVP_ASSIGNMENTm, entry,
   2742                                     ENTRY_TYPEf)) {
   2743         case 1: /* WLAN_SVP_TUNNEL */
   2744             return _soc_hash_generic_entry_to_key(unit, entry, key, mem, field_list_port1);
   2745         case 2: /* WLAN_SVP_BSSID */
   2746             return _soc_hash_generic_entry_to_key(unit, entry, key, mem, field_list_port2);
   2747         case 3: /* WLAN_SVP_BSSID_RID */
   2748             return _soc_hash_generic_entry_to_key(unit, entry, key, mem, field_list_port3);
   2749         default:
   2750             return 0;
   2751         }
   2752     } else { /* AXP_WRX_WCD:MAC_ADDR */
   2753         return _soc_hash_generic_entry_to_key(unit, entry, key, mem, field_list_client);
   2754     }
   2755 }
   2756 
   2757 uint32
   2758 soc_tr3_ft_session_hash(int unit, soc_mem_t mem, int hash_sel, int key_nbits,
   2759                   void *base_entry, uint8 *key)
   2760 {
   2761     uint32 rv;
   2762     uint32 fval[SOC_MAX_MEM_WORDS];
   2763 
   2764     /*
   2765      * Cache bucket mask and shift amount for upper crc
   2766      */
   2767     if (mem == FT_SESSIONm && SOC_CONTROL(unit)->hash_mask_ft_session_ipv4 == 0) {
   2768         uint32  mask;
   2769         int     bits;
   2770 
   2771         /* 8 Entries per bucket, 1K buckets, = 8192 IPv4, 4096 IPv6 entries */
   2772         mask = soc_mem_index_max(unit, FT_SESSIONm) >> 3;
   2773         bits = 0;
   2774         rv = 1;
   2775         while (rv && (mask & rv)) {
   2776             bits += 1;
   2777             rv <<= 1;
   2778         }
   2779         SOC_CONTROL(unit)->hash_mask_ft_session_ipv4 = mask;
   2780         SOC_CONTROL(unit)->hash_bits_ft_session_ipv4 = bits;
   2781     }
   2782     if (mem == FT_SESSION_IPV6m && SOC_CONTROL(unit)->hash_mask_ft_session_ipv6 == 0) {
   2783         uint32  mask;
   2784         int     bits;
   2785 
   2786         /* 8 Entries per bucket */
   2787         mask = soc_mem_index_max(unit, FT_SESSION_IPV6m) >> 3;
   2788         bits = 0;
   2789         rv = 1;
   2790         while (rv && (mask & rv)) {
   2791             bits += 1;
   2792             rv <<= 1;
   2793         }
   2794         SOC_CONTROL(unit)->hash_mask_ft_session_ipv6 = mask;
   2795         SOC_CONTROL(unit)->hash_bits_ft_session_ipv6 = bits;
   2796     }
   2797 
   2798     switch (hash_sel) {
   2799     case FB_HASH_CRC16_UPPER:
   2800         rv = soc_crc16b(key, key_nbits);
   2801         rv >>= 16 - (mem == FT_SESSIONm ? SOC_CONTROL(unit)->hash_bits_ft_session_ipv4 :
   2802                                            SOC_CONTROL(unit)->hash_bits_ft_session_ipv6);
   2803         break;
   2804 
   2805     case FB_HASH_CRC16_LOWER:
   2806         rv = soc_crc16b(key, key_nbits);
   2807         break;
   2808 
   2809     case FB_HASH_LSB:
   2810         if (key_nbits == 0) {
   2811             return 0;
   2812         }
   2813         if (mem == FT_SESSIONm) {
   2814             soc_mem_field_get(unit, FT_SESSIONm, base_entry,
   2815                               KEYf, fval);
   2816             rv = fval[0];
   2817         } else { /* mem == FT_SESSION_IPV6 */
   2818             soc_mem_field_get(unit, FT_SESSION_IPV6m, base_entry,
   2819                               IPV6_LOWER_KEYf, fval);
   2820             rv = fval[0];
   2821         }
   2822         break;
   2823 
   2824     case FB_HASH_ZERO:
   2825         rv = 0;
   2826         break;
   2827 
   2828     case FB_HASH_CRC32_UPPER:
   2829         rv = soc_crc32b(key, key_nbits);
   2830         rv >>= 32 - (mem == FT_SESSIONm ? SOC_CONTROL(unit)->hash_bits_ft_session_ipv4 :
   2831                                            SOC_CONTROL(unit)->hash_bits_ft_session_ipv6);
   2832         break;
   2833 
   2834     case FB_HASH_CRC32_LOWER:
   2835         rv = soc_crc32b(key, key_nbits);
   2836         break;
   2837 
   2838     default:
   2839         LOG_ERROR(BSL_LS_SOC_HASH,
   2840                   (BSL_META_U(unit,
   2841                               "soc_tr3_ft_session_hash: invalid hash_sel %d\n"),
   2842                    hash_sel));
   2843         rv = 0;
   2844         break;
   2845     }
   2846 
   2847     return rv & (mem == FT_SESSIONm ? SOC_CONTROL(unit)->hash_mask_ft_session_ipv4 :
   2848                                        SOC_CONTROL(unit)->hash_mask_ft_session_ipv6);
   2849 }
   2850 
   2851 uint32
   2852 soc_tr3_wlan_hash(int unit, soc_mem_t mem, int hash_sel, int key_nbits,
   2853                   void *base_entry, uint8 *key)
   2854 {
   2855     uint32 rv;
   2856     uint32 fval[SOC_MAX_MEM_WORDS];
   2857 
   2858     /*
   2859      * Cache bucket mask and shift amount for upper crc
   2860      */
   2861     if (mem == AXP_WRX_WCDm && SOC_CONTROL(unit)->hash_mask_wlan_client == 0) {
   2862         uint32  mask;
   2863         int     bits;
   2864 
   2865         /* 8 Entries per bucket */
   2866         mask = soc_mem_index_max(unit, AXP_WRX_WCDm) >> 3;
   2867         bits = 0;
   2868         rv = 1;
   2869         while (rv && (mask & rv)) {
   2870             bits += 1;
   2871             rv <<= 1;
   2872         }
   2873         SOC_CONTROL(unit)->hash_mask_wlan_client = mask;
   2874         SOC_CONTROL(unit)->hash_bits_wlan_client = bits;
   2875     }
   2876     if (mem == AXP_WRX_SVP_ASSIGNMENTm && SOC_CONTROL(unit)->hash_mask_wlan_port == 0) {
   2877         uint32  mask;
   2878         int     bits;
   2879 
   2880         /* 8 Entries per bucket */
   2881         mask = soc_mem_index_max(unit, AXP_WRX_SVP_ASSIGNMENTm) >> 3;
   2882         bits = 0;
   2883         rv = 1;
   2884         while (rv && (mask & rv)) {
   2885             bits += 1;
   2886             rv <<= 1;
   2887         }
   2888         SOC_CONTROL(unit)->hash_mask_wlan_port = mask;
   2889         SOC_CONTROL(unit)->hash_bits_wlan_port = bits;
   2890     }
   2891 
   2892     switch (hash_sel) {
   2893     case FB_HASH_CRC16_UPPER:
   2894         rv = soc_crc16b(key, key_nbits);
   2895         rv >>= 16 - (mem == AXP_WRX_WCDm ? SOC_CONTROL(unit)->hash_bits_wlan_client : 
   2896                                            SOC_CONTROL(unit)->hash_bits_wlan_port);
   2897         break;
   2898 
   2899     case FB_HASH_CRC16_LOWER:
   2900         rv = soc_crc16b(key, key_nbits);
   2901         break;
   2902 
   2903     case FB_HASH_LSB:
   2904         if (key_nbits == 0) {
   2905             return 0;
   2906         }
   2907         if (mem == AXP_WRX_SVP_ASSIGNMENTm) {
   2908             switch (soc_mem_field32_get(unit, AXP_WRX_SVP_ASSIGNMENTm, base_entry,
   2909                                         ENTRY_TYPEf)) {
   2910             case 1: /* WLAN_SVP_TUNNEL */
   2911                 rv = soc_mem_field32_get(unit, AXP_WRX_SVP_ASSIGNMENTm, base_entry,
   2912                                          TUNNEL_IDf);
   2913                 break;
   2914             case 2: /* WLAN_SVP_BSSID */
   2915                 soc_mem_field_get(unit, AXP_WRX_SVP_ASSIGNMENTm, base_entry,
   2916                                   BSSIDf, fval);
   2917                 rv = fval[0];
   2918                 break;
   2919             case 3: /* WLAN_SVP_BSSID_RID */
   2920                 soc_mem_field_get(unit, AXP_WRX_SVP_ASSIGNMENTm, base_entry,
   2921                                   BSSIDf, fval);
   2922                 rv = soc_mem_field32_get(unit, AXP_WRX_SVP_ASSIGNMENTm, base_entry,
   2923                                          RIDf) |
   2924                     (fval[0] << soc_mem_field_length(unit, AXP_WRX_SVP_ASSIGNMENTm,
   2925                                                      RIDf));
   2926                 break;
   2927             default:
   2928                 rv = 0;
   2929                 break;
   2930             }
   2931         } else { /* AXP_WRX_WCD:MAC_ADDR */
   2932             rv = soc_mem_field32_get(unit, AXP_WRX_WCDm, base_entry, MAC_ADDRf);
   2933         }
   2934         break;
   2935 
   2936     case FB_HASH_ZERO:
   2937         rv = 0;
   2938         break;
   2939 
   2940     case FB_HASH_CRC32_UPPER:
   2941         rv = soc_crc32b(key, key_nbits);
   2942         rv >>= 32 - (mem == AXP_WRX_WCDm ? SOC_CONTROL(unit)->hash_bits_wlan_client : 
   2943                                            SOC_CONTROL(unit)->hash_bits_wlan_port);
   2944         break;
   2945 
   2946     case FB_HASH_CRC32_LOWER:
   2947         rv = soc_crc32b(key, key_nbits);
   2948         break;
   2949 
   2950     default:
   2951         LOG_ERROR(BSL_LS_SOC_HASH,
   2952                   (BSL_META_U(unit,
   2953                               "soc_tr3_wlan_hash: invalid hash_sel %d\n"),
   2954                    hash_sel));
   2955         rv = 0;
   2956         break;
   2957     }
   2958 
   2959     return rv & (mem == AXP_WRX_WCDm ? SOC_CONTROL(unit)->hash_mask_wlan_client : 
   2960                                        SOC_CONTROL(unit)->hash_mask_wlan_port);
   2961 }
   2962 
   2963 uint32
   2964 soc_tr3_ft_session_entry_hash(int unit, soc_mem_t mem, int hash_sel, uint32 *entry)
   2965 {
   2966     int             key_nbits;
   2967     uint8           key[SOC_MAX_MEM_WORDS * 4];
   2968     uint32          index;
   2969 
   2970     key_nbits = soc_tr3_ft_session_entry_to_key(unit, mem, entry, key);
   2971     index = soc_tr3_ft_session_hash(unit, mem, hash_sel, key_nbits, entry, key);
   2972 
   2973     return index;
   2974 }
   2975 
   2976 uint32
   2977 soc_tr3_wlan_entry_hash(int unit, soc_mem_t mem, int hash_sel, uint32 *entry)
   2978 {
   2979     int             key_nbits;
   2980     uint8           key[SOC_MAX_MEM_WORDS * 4];
   2981     uint32          index;
   2982 
   2983     key_nbits = soc_tr3_wlan_base_entry_to_key(unit, mem, entry, key);
   2984     index = soc_tr3_wlan_hash(unit, mem, hash_sel, key_nbits, entry, key);
   2985 
   2986     return index;
   2987 }
   2988 #endif /* BCM_TRIUMPH3_SUPPORT */
   2989 
   2990 
   2991 #ifdef SOC_ROBUST_HASH
   2992 /*
   2993  * Function:
   2994  * soc_robust_hash_get
   2995  * Purpose:
   2996  *      Internal function to compute Robust Hash key transformation
   2997  * Parameters:
   2998  *      unit    - (IN) SOC unit #
   2999  *      rbh_cfg - (IN) Pointer to Robust hash table structure
   3000  *      bank    - (IN) Dual hash bank # (0/1)
   3001  *      key     - (IN/OUT) Hashing key
   3002  *      n_bits  - (IN) Number of bits in the Input hash key
   3003  * Returns:
   3004  *      BCM_E_XXX
   3005 */
   3006 int
   3007 soc_robust_hash_get(int unit, soc_robust_hash_config_t *rbh_cfg, int bank,
   3008                     uint8 *key, int n_bits)
   3009 {
   3010     int ix, n_bytes, byte_offset = 0;
   3011     int append = 0;
   3012     int nibble_swapped_key = 0, key_size = 0;
   3013     int remap_table_index = 0, action_table_index = 0;
   3014     uint32 remap_val;
   3015     uint64 action;
   3016     int sr_bits = 0;
   3017     int sl_bits = 0;
   3018 
   3019     COMPILER_64_ZERO(action);
   3020     n_bytes = (n_bits + 7) / 8;
   3021 
   3022     /* Generate Remap table index */
   3023     for(ix = 0; ix < n_bytes; ix++) {
   3024         remap_table_index = remap_table_index ^ key[ix];
   3025     }
   3026 
   3027     /* Generate Action table index */
   3028     for(ix = 0; ix < n_bytes; ix++) {
   3029         nibble_swapped_key = ((key[ix] & 0x0F) << 4) |
   3030                                     ((key[ix] & 0xF0) >> 4 );
   3031         action_table_index = action_table_index ^ nibble_swapped_key;
   3032     }
   3033 
   3034     /* Read Remap and Action table values from SW cache*/
   3035     if (bank == 1) {
   3036         remap_val = rbh_cfg->remap_data_B[remap_table_index];
   3037         action = rbh_cfg->action_data_B[action_table_index /
   3038                           ROBUST_HASH_ACTION_TABLE_WIDTH];
   3039     } else {
   3040         remap_val = rbh_cfg->remap_data_A[remap_table_index];
   3041         action = rbh_cfg->action_data_A[action_table_index /
   3042                           ROBUST_HASH_ACTION_TABLE_WIDTH];
   3043     }
   3044 
   3045     /* Robust hash key transformation */
   3046     if (COMPILER_64_BITTEST(action,
   3047                 (action_table_index % ROBUST_HASH_ACTION_TABLE_WIDTH)) == 0) {
   3048         /* PREPEND */
   3049         for (ix = n_bytes; ix > 0; ix--) {
   3050             key[ix + 1] = key[ix - 1];
   3051         }
   3052         byte_offset = n_bytes + (ROBUST_HASH_KEY_SPACE_WIDTH / 8);
   3053     } else if (COMPILER_64_BITTEST(action,
   3054                 (action_table_index % ROBUST_HASH_ACTION_TABLE_WIDTH)) == 1) {
   3055         /* APPEND */
   3056         key_size = n_bytes;
   3057         byte_offset = n_bytes;
   3058         append = 1;
   3059     }
   3060 
   3061     /* Trident3 does not have byte boundary aligned robust hash values */
   3062     if ((soc_feature(unit, soc_feature_robust_hash_byte_boundary_alignment)) &&
   3063         (append == 1)){
   3064         key[n_bits / 8] = (remap_val & 0xFF) << (n_bits % 8);
   3065         key[(n_bits / 8) + 1] = ((remap_val & 0xFF) >> (8 - (n_bits % 8))) | ((((remap_val >> 8) & 0xF) |
   3066             ((action_table_index & 0xF) << 4)) << (n_bits % 8));
   3067         if (n_bits % 8) {
   3068             key[(n_bits / 8) + 2] = (((remap_val >> 8) & 0xF) |
   3069             ((action_table_index & 0xF) << 4)) >> (8 - n_bits % 8); 
   3070         }
   3071     } else {
   3072     key[key_size] = remap_val & 0xFF;
   3073     key[key_size + 1] = ((remap_val >> 8) & 0xF) |
   3074         ((action_table_index & 0xF) << 4);
   3075     }
   3076 
   3077     if (!(soc_feature(unit, soc_feature_robust_hash_byte_boundary_alignment))) {
   3078     /* Adjust the byte boundary */
   3079     if (n_bits % 8 != 0) {
   3080         sr_bits = n_bits % 8;
   3081         sl_bits = 8 - sr_bits;
   3082         for (ix = byte_offset - 1; ix > 0; ix--) {
   3083             key[ix] = key[ix] << sl_bits;
   3084             key[ix] |= key[ix - 1] >> sr_bits;
   3085         }
   3086         key[ix] = key[ix] << sl_bits;
   3087     }
   3088     }
   3089 
   3090     return SOC_E_NONE;
   3091 }
   3092 
   3093 /*
   3094  * Function:
   3095  * soc_robust_hash_get2
   3096  * Purpose:
   3097  *      Internal function to compute Robust Hash key transformation
   3098  * Parameters:
   3099  *      unit    - (IN) SOC unit #
   3100  *      rbh_cfg - (IN) Pointer to Robust hash table structure
   3101  *      bank    - (IN) Dual hash bank # (0/1)
   3102  *      key     - (IN/OUT) Hashing key
   3103  *      n_bits  - (IN) Number of bits in the Input hash key
   3104  * Returns:
   3105  *      BCM_E_XXX
   3106 */
   3107 int
   3108 soc_robust_hash_get2(int unit, soc_robust_hash_config_t *rbh_cfg, int bank,
   3109                     uint8 *key, int n_bits)
   3110 {
   3111     int ix, n_bytes, x;
   3112     int append = 0;
   3113     int nibble_swapped_key = 0, key_size = 0;
   3114     int remap_table_index = 0, action_table_index = 0;
   3115     uint32 remap_val;
   3116     uint64 action;
   3117     uint16 temp16;
   3118 
   3119     COMPILER_64_ZERO(action);
   3120     n_bytes = (n_bits + 7) / 8;
   3121 
   3122     /* Generate Remap table index */
   3123     for(ix = 0; ix < n_bytes; ix++) {
   3124         remap_table_index = remap_table_index ^ key[ix];
   3125     }
   3126 
   3127     /* Generate Action table index */
   3128     for(ix = 0; ix < n_bytes; ix++) {
   3129         nibble_swapped_key = ((key[ix] & 0x0F) << 4) |
   3130                                     ((key[ix] & 0xF0) >> 4 );
   3131         action_table_index = action_table_index ^ nibble_swapped_key;
   3132     }
   3133 
   3134     /* Read Remap and Action table values from SW cache*/
   3135     if (bank == 1) {
   3136         remap_val = rbh_cfg->remap_data_B[remap_table_index];
   3137         action = rbh_cfg->action_data_B[action_table_index /
   3138                           ROBUST_HASH_ACTION_TABLE_WIDTH];
   3139     } else {
   3140         remap_val = rbh_cfg->remap_data_A[remap_table_index];
   3141         action = rbh_cfg->action_data_A[action_table_index /
   3142                           ROBUST_HASH_ACTION_TABLE_WIDTH];
   3143     }
   3144 
   3145     /* Robust hash key transformation */
   3146     if (COMPILER_64_BITTEST(action,
   3147                 (action_table_index % ROBUST_HASH_ACTION_TABLE_WIDTH)) == 0) {
   3148         /* PREPEND */
   3149         for (ix = n_bytes; ix > 0; ix--) {
   3150             key[ix + 1] = key[ix - 1];
   3151         }
   3152     } else if (COMPILER_64_BITTEST(action,
   3153                 (action_table_index % ROBUST_HASH_ACTION_TABLE_WIDTH)) == 1) {
   3154         /* APPEND */
   3155         key_size = n_bytes;
   3156         append = 1;
   3157     }
   3158 
   3159     temp16 = (((remap_val >> 8) & 0xF) << 8) | (remap_val & 0xFF);
   3160     temp16 |= (action_table_index & 0xF) << 12;
   3161 
   3162     x = n_bits & 0x7; /* ie n_bits % 8 */
   3163 
   3164     if ((x) && (append == 1)) {
   3165            key[key_size - 1] &= ~((((1 << (8 - x)) - 1)) << x);
   3166            key[key_size - 1] |= (temp16 & ((1 << (8 - x)) - 1)) << x;
   3167            key[key_size] = (temp16 >> (8 - x)) & 0xFF;
   3168            key[key_size + 1] = temp16 >> (16 - x);
   3169     } else {
   3170         key[key_size] = temp16 & 0xFF;
   3171         key[key_size + 1] =  (temp16 >> 8) & 0xFF;
   3172     }
   3173 
   3174     return SOC_E_NONE;
   3175 }
   3176 
   3177 
   3178 /*
   3179  * Function:
   3180  * soc_robust_hash_table_set
   3181  * Purpose:
   3182  *      Internal function to configure Robust hash remapping structures
   3183  * Parameters:
   3184  *      unit    - (IN) SOC unit #
   3185  *      rbh_cfg - (IN) Pointer to Robust hash table structure
   3186  *      seed    - (IN) Random seed
   3187  * Returns:
   3188  *      BCM_E_XXX
   3189 */
   3190 int
   3191 soc_robust_hash_table_set(int unit, soc_robust_hash_config_t *rbh_cfg, int seed)
   3192 {
   3193     int index, num_tables, action = 0, action_lo;
   3194     unsigned int random_data, swap, remap_rand;
   3195     uint8 action_arr[ROBUST_HASH_ACTION_TABLE_SIZE];
   3196     uint64 val64, action_tab_entry;
   3197     uint32 *remapdata[ROBUST_HASH_NUM_MODULES];
   3198     uint64 *actiondata[ROBUST_HASH_NUM_MODULES];
   3199     COMPILER_64_ZERO(val64);
   3200     COMPILER_64_ZERO(action_tab_entry);
   3201 
   3202     remapdata[0] = rbh_cfg->remap_data_A;
   3203     remapdata[1] = rbh_cfg->remap_data_B;
   3204     actiondata[0] = rbh_cfg->action_data_A;
   3205     actiondata[1] = rbh_cfg->action_data_B;
   3206 
   3207     /* Set random seed */
   3208     sal_srand(seed);
   3209 
   3210     /* Fill remap and action tables with random data */
   3211     for (num_tables = 0; num_tables < ROBUST_HASH_NUM_MODULES; num_tables++) {
   3212         /* Initialize local variable to fill action table with equal number
   3213            of 1s and 0s */
   3214         for (index = 0; index < ROBUST_HASH_ACTION_TABLE_SIZE; index++) {
   3215             action_arr[index] = index % 2;
   3216         }
   3217 
   3218         for (index = 0; index < ROBUST_HASH_REMAP_TABLE_SIZE; index++) {
   3219             random_data = sal_rand();
   3220             remap_rand = random_data & 0xFFF;
   3221 
   3222             /* Configure remap table with random data */
   3223             SOC_IF_ERROR_RETURN
   3224                 (soc_mem_write(unit, rbh_cfg->remap_tab[num_tables], MEM_BLOCK_ALL,
   3225                                index, &remap_rand));
   3226 
   3227             /* Copy remap data to SW cache */
   3228             *(remapdata[num_tables] + index) = remap_rand;
   3229 
   3230             /* Randomize action variable values */
   3231             swap = action_arr[index];
   3232             action_arr[index] = action_arr[random_data %
   3233                                            ROBUST_HASH_ACTION_TABLE_SIZE];
   3234             action_arr[random_data % ROBUST_HASH_ACTION_TABLE_SIZE] = swap;
   3235         }
   3236 
   3237         /* Write randomized action table values to memory */
   3238         action_lo = 0;
   3239         for (index = 0; index < ROBUST_HASH_ACTION_TABLE_SIZE; index++) {
   3240             action |= action_arr[index] <<
   3241                                 (index % (ROBUST_HASH_ACTION_TABLE_WIDTH / 2));
   3242             if ((index + 1) % (ROBUST_HASH_ACTION_TABLE_WIDTH / 2) == 0) {
   3243                 if ((index + 1) % ROBUST_HASH_ACTION_TABLE_WIDTH == 0) {
   3244                     COMPILER_64_SET(val64, action, action_lo);
   3245                     /* Action table protected with ECC/Parity are       *
   3246                      * more than 64 bit wide., Code to accommodate ECC. *
   3247                      * Action vector is still 64bit wide                */
   3248                     if (SOC_MEM_FIELD_VALID(unit, rbh_cfg->action_tab[num_tables], ECCPf)) {
   3249                         uint64 act_tab_entry[2];
   3250                         uint32 eccp = 0;
   3251                         sal_memset(act_tab_entry, 0, sizeof(act_tab_entry));
   3252                         soc_mem_field64_set(unit, rbh_cfg->action_tab[num_tables],
   3253                                             (uint64 *)act_tab_entry,
   3254                                             ACTIONf, val64);
   3255                         soc_mem_field32_set(unit, rbh_cfg->action_tab[num_tables],
   3256                                             (uint64 *)act_tab_entry,
   3257                                             ECCPf, eccp);
   3258                         SOC_IF_ERROR_RETURN
   3259                             (soc_mem_write(unit, rbh_cfg->action_tab[num_tables],
   3260                                            MEM_BLOCK_ALL,
   3261                                            index / ROBUST_HASH_ACTION_TABLE_WIDTH,
   3262                                            act_tab_entry));
   3263                     } else {
   3264                         soc_mem_field64_set(unit, rbh_cfg->action_tab[num_tables],
   3265                                             (uint64 *)&action_tab_entry,
   3266                                             ACTIONf, val64);
   3267                         SOC_IF_ERROR_RETURN
   3268                             (soc_mem_write(unit, rbh_cfg->action_tab[num_tables],
   3269                                            MEM_BLOCK_ALL,
   3270                                            index / ROBUST_HASH_ACTION_TABLE_WIDTH,
   3271                                            &action_tab_entry));
   3272                     }
   3273                     /* Copy action data to SW cache */
   3274                     COMPILER_64_SET(*(actiondata[num_tables] +
   3275                                     (index / ROBUST_HASH_ACTION_TABLE_WIDTH)),
   3276                                     action, action_lo);
   3277 
   3278                     action = 0;
   3279                     action_lo = 0;
   3280                 } else {
   3281                     action_lo = action;
   3282                     action = 0;
   3283                 }
   3284             }
   3285         }
   3286     }
   3287 
   3288     return SOC_E_NONE;
   3289 }
   3290 #endif /* SOC_ROBUST_HASH */
   3291 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) || \
   3292     defined(BCM_TOMAHAWK_SUPPORT)
   3293 int
   3294 soc_td2x_th_l2x_hash(int unit, uint32 *base_entry, int *num_banks,
   3295                      int *bucket_array, int *index_array, uint8 *hash_key)
   3296 {
   3297     int bank            = 0;
   3298     int bucket          = 0;
   3299     int entries_per_row = 0;
   3300     int bank_base       = 0;
   3301     int bucket_offset   = 0;
   3302 
   3303     if (NULL == base_entry || NULL == num_banks ||
   3304         NULL == bucket_array || NULL == index_array || NULL == hash_key) {
   3305         return SOC_E_PARAM;
   3306     }
   3307 
   3308 #ifdef BCM_APACHE_SUPPORT
   3309     if (SOC_IS_APACHE(unit)) {
   3310         SOC_IF_ERROR_RETURN(
   3311             soc_apache_hash_bank_count_get(unit, L2Xm, num_banks));
   3312         (void) soc_ap_l2x_base_entry_to_key(unit, base_entry, hash_key);
   3313     } else
   3314 #endif
   3315 #ifdef BCM_HELIX5_SUPPORT
   3316     if (SOC_IS_HELIX5(unit)) {
   3317         SOC_IF_ERROR_RETURN(
   3318             soc_helix5_hash_bank_count_get(unit, L2Xm, num_banks));
   3319         (void) soc_hx5_l2x_base_entry_to_key(unit, 0, base_entry, hash_key);
   3320     } else
   3321 #endif /* BCM_HELIX5_SUPPORT */
   3322 #ifdef BCM_TRIDENT3_SUPPORT
   3323     if (SOC_IS_TRIDENT3X(unit)) {
   3324         SOC_IF_ERROR_RETURN(
   3325             soc_trident3_hash_bank_count_get(unit, L2Xm, num_banks));
   3326        (void) soc_td3_l2x_base_entry_to_key(unit, 0, base_entry, hash_key);
   3327     } else
   3328 #endif
   3329 #ifdef BCM_TOMAHAWK3_SUPPORT
   3330     if (SOC_IS_TOMAHAWK3(unit)) {
   3331         SOC_IF_ERROR_RETURN(
   3332             soc_tomahawk3_hash_bank_count_get(unit, L2Xm, num_banks));
   3333        (void) soc_tomahawk3_l2x_base_entry_to_key(unit, 0, base_entry, hash_key);
   3334     } else
   3335 #endif
   3336 #ifdef BCM_TRIDENT2_SUPPORT
   3337     if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   3338         SOC_IF_ERROR_RETURN(
   3339             soc_trident2_hash_bank_count_get(unit, L2Xm, num_banks));
   3340        (void) soc_td2_l2x_base_entry_to_key(unit, 0, base_entry, hash_key);
   3341     } else
   3342 #endif
   3343 #ifdef BCM_TOMAHAWK_SUPPORT
   3344     if (SOC_IS_TOMAHAWKX(unit)) {
   3345         SOC_IF_ERROR_RETURN(
   3346             soc_tomahawk_hash_bank_count_get(unit, L2Xm, num_banks));
   3347         (void) soc_th_l2x_base_entry_to_key(unit, 0, base_entry, hash_key);
   3348     } else
   3349 #endif
   3350     {
   3351        return SOC_E_INTERNAL;
   3352     }
   3353 
   3354     for (bank = 0; bank < *num_banks; bank++) {
   3355 #ifdef BCM_APACHE_SUPPORT
   3356         if (SOC_IS_APACHE(unit)) {
   3357             int phy_bank;
   3358             SOC_IF_ERROR_RETURN
   3359                 (soc_apache_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   3360             SOC_IF_ERROR_RETURN(
   3361                 soc_apache_hash_bank_info_get(unit, L2Xm, phy_bank, NULL,
   3362                                               &entries_per_row, NULL,
   3363                                               &bank_base, &bucket_offset));
   3364             bucket = soc_ap_l2x_bank_entry_hash(unit, phy_bank, base_entry);
   3365         } else
   3366 #endif
   3367 #ifdef BCM_HELIX5_SUPPORT
   3368         if (SOC_IS_HELIX5(unit)) {
   3369             int phy_bank;
   3370             SOC_IF_ERROR_RETURN
   3371                 (soc_hx5_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   3372             SOC_IF_ERROR_RETURN(
   3373                 soc_hx5_hash_bank_info_get(unit, L2Xm, phy_bank, NULL,
   3374                                                 &entries_per_row, NULL,
   3375                                                 &bank_base, &bucket_offset));
   3376             bucket = soc_hx5_l2x_bank_entry_hash(unit, phy_bank, base_entry);
   3377         } else
   3378 #endif
   3379 #ifdef BCM_TRIDENT3_SUPPORT
   3380         if (SOC_IS_TRIDENT3X(unit)) {
   3381             int phy_bank;
   3382             SOC_IF_ERROR_RETURN
   3383                 (soc_td3_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   3384             SOC_IF_ERROR_RETURN(
   3385                 soc_td3_hash_bank_info_get(unit, L2Xm, phy_bank, NULL,
   3386                                                 &entries_per_row, NULL,
   3387                                                 &bank_base, &bucket_offset));
   3388             bucket = soc_td3_l2x_bank_entry_hash(unit, phy_bank, base_entry);
   3389         } else
   3390 #endif
   3391 #ifdef BCM_TOMAHAWK3_SUPPORT
   3392         if (SOC_IS_TOMAHAWK3(unit)) {
   3393             int phy_bank;
   3394             SOC_IF_ERROR_RETURN
   3395                 (soc_tomahawk3_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   3396             SOC_IF_ERROR_RETURN(
   3397                 soc_tomahawk3_hash_bank_info_get(unit, L2Xm, phy_bank, NULL,
   3398                                                 &entries_per_row, NULL,
   3399                                                 &bank_base, &bucket_offset));
   3400             bucket = soc_tomahawk3_l2x_bank_entry_hash(unit, phy_bank, base_entry);
   3401         } else
   3402 #endif
   3403 #ifdef BCM_TRIDENT2_SUPPORT
   3404         if (!SOC_IS_TOMAHAWKX(unit) && SOC_IS_TD2_TT2(unit)) {
   3405             int phy_bank;
   3406             SOC_IF_ERROR_RETURN
   3407                 (soc_trident2_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   3408             SOC_IF_ERROR_RETURN(
   3409                 soc_trident2_hash_bank_info_get(unit, L2Xm, phy_bank, NULL,
   3410                                                 &entries_per_row, NULL,
   3411                                                 &bank_base, &bucket_offset));
   3412             bucket = soc_td2_l2x_bank_entry_hash(unit, phy_bank, base_entry);
   3413         } else
   3414 #endif
   3415 #ifdef BCM_TOMAHAWK_SUPPORT
   3416         if (SOC_IS_TOMAHAWKX(unit)) {
   3417             int phy_bank;
   3418             SOC_IF_ERROR_RETURN
   3419                 (soc_tomahawk_hash_bank_number_get(unit, L2Xm, bank, &phy_bank));
   3420             SOC_IF_ERROR_RETURN(
   3421                 soc_tomahawk_hash_bank_info_get(unit, L2Xm, phy_bank, NULL,
   3422                                                 &entries_per_row, NULL,
   3423                                                 &bank_base, &bucket_offset));
   3424             bucket = soc_th_l2x_bank_entry_hash(unit, phy_bank, base_entry);
   3425         }
   3426 #endif
   3427        bucket_array[bank] = bucket;
   3428        index_array[bank]  = bank_base + bucket * entries_per_row + bucket_offset;
   3429     }
   3430 
   3431     return SOC_E_NONE;
   3432 }
   3433 
   3434 int
   3435 soc_td2x_th_l3x_hash(int unit, soc_mem_t mem, uint32 *base_entry, int *num_banks,
   3436                      int *bucket_array, int *index_array, int *phy_bank_array,
   3437                      int *entry_num_array)
   3438 {
   3439     int bank             = 0;
   3440     int phy_bank         = 0;
   3441     int bucket           = 0;
   3442     int entries_per_bank = 0;
   3443     int entries_per_row  = 0;
   3444     int bank_base        = 0;
   3445     int bucket_offset    = 0;
   3446 
   3447     if (NULL == base_entry || NULL == num_banks ||
   3448         NULL == bucket_array || NULL == index_array) {
   3449         return SOC_E_PARAM;
   3450     }
   3451 
   3452     switch (mem) {
   3453     case L3_ENTRY_ONLYm:
   3454     case L3_ENTRY_IPV4_UNICASTm:
   3455     case L3_ENTRY_IPV4_MULTICASTm:
   3456     case L3_ENTRY_IPV6_UNICASTm:
   3457     case L3_ENTRY_IPV6_MULTICASTm:
   3458 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   3459     case L3_ENTRY_SINGLEm:
   3460     case L3_ENTRY_DOUBLEm:
   3461     case L3_ENTRY_QUADm:
   3462 #endif /* BCM_TRIDENT3_SUPPORT || BCM_TOMAHAWK3_SUPPORT */
   3463         break;
   3464     default:
   3465         return SOC_E_PARAM;
   3466     }
   3467 #ifdef BCM_HELIX5_SUPPORT
   3468     if (SOC_IS_HELIX5(unit)) {
   3469         SOC_IF_ERROR_RETURN(
   3470             soc_helix5_hash_bank_count_get(unit, mem, num_banks));
   3471     } else
   3472 #endif /* BCM_HELIX5_SUPPORT */
   3473 #ifdef BCM_TRIDENT3_SUPPORT
   3474     if (SOC_IS_TRIDENT3X(unit)) {
   3475         SOC_IF_ERROR_RETURN(
   3476             soc_trident3_hash_bank_count_get(unit, mem, num_banks));
   3477     } else
   3478 #endif
   3479 #ifdef BCM_APACHE_SUPPORT
   3480     if (SOC_IS_APACHE(unit)) {
   3481         SOC_IF_ERROR_RETURN(
   3482             soc_apache_hash_bank_count_get(unit, mem, num_banks));
   3483     } else
   3484 #endif
   3485 #ifdef BCM_TOMAHAWK_SUPPORT
   3486     if (SOC_IS_TOMAHAWKX(unit)) {
   3487         SOC_IF_ERROR_RETURN(
   3488             soc_tomahawk_hash_bank_count_get(unit, mem, num_banks));
   3489     } else
   3490 #endif
   3491 #ifdef BCM_TRIDENT2_SUPPORT
   3492     if (SOC_IS_TD2_TT2(unit)) {
   3493         SOC_IF_ERROR_RETURN(
   3494             soc_trident2_hash_bank_count_get(unit, mem, num_banks));
   3495     } else
   3496 #endif
   3497     {
   3498        return SOC_E_INTERNAL;
   3499     }
   3500 
   3501     for (bank = 0; bank < *num_banks; bank++) {
   3502 #ifdef BCM_TRIDENT3_SUPPORT
   3503         if (SOC_IS_TRIDENT3X(unit)) {
   3504 #ifdef BCM_HELIX5_SUPPORT
   3505             if (SOC_IS_HELIX5(unit)) {
   3506                 SOC_IF_ERROR_RETURN
   3507                     (soc_hx5_hash_bank_number_get(unit, mem, bank, &phy_bank));
   3508                 SOC_IF_ERROR_RETURN(
   3509                         soc_hx5_hash_bank_info_get(unit, mem, phy_bank, &entries_per_bank,
   3510                             &entries_per_row, NULL,
   3511                             &bank_base, &bucket_offset));
   3512                 bucket = soc_hx5_l3x_bank_entry_hash(unit, phy_bank, base_entry);
   3513             } else
   3514 #endif
   3515             {
   3516                 SOC_IF_ERROR_RETURN
   3517                     (soc_td3_hash_bank_number_get(unit, mem, bank, &phy_bank));
   3518                 SOC_IF_ERROR_RETURN(
   3519                         soc_td3_hash_bank_info_get(unit, mem, phy_bank, &entries_per_bank,
   3520                             &entries_per_row, NULL,
   3521                             &bank_base, &bucket_offset));
   3522                 bucket = soc_td3_l3x_bank_entry_hash(unit, phy_bank, base_entry);
   3523             }
   3524  
   3525             /* Bucket is calculated based on SINGLE memory. In case of
   3526              * Double and Quad, the hash bucket to be adjusted correctly.
   3527              * If there are 4096 entires in the bank and 4 entries per row
   3528              * (or bucket), there are 1024 buckets and the mask is 0x3FF.
   3529              */
   3530             bucket &= ((entries_per_bank/entries_per_row)-1);
   3531         } else
   3532 #endif
   3533 #ifdef BCM_APACHE_SUPPORT
   3534         if (SOC_IS_APACHE(unit)) {
   3535             SOC_IF_ERROR_RETURN
   3536                 (soc_apache_hash_bank_number_get(unit, mem, bank, &phy_bank));
   3537             SOC_IF_ERROR_RETURN(
   3538                 soc_apache_hash_bank_info_get(unit, mem, phy_bank, &entries_per_bank,
   3539                                               &entries_per_row, NULL,
   3540                                               &bank_base, &bucket_offset));
   3541             bucket = soc_ap_l3x_bank_entry_hash(unit, phy_bank, base_entry);
   3542         } else
   3543 #endif
   3544 #ifdef BCM_TOMAHAWK_SUPPORT
   3545         if (SOC_IS_TOMAHAWKX(unit)) {
   3546             SOC_IF_ERROR_RETURN
   3547                 (soc_tomahawk_hash_bank_number_get(unit, mem, bank, &phy_bank));
   3548             SOC_IF_ERROR_RETURN(
   3549                 soc_tomahawk_hash_bank_info_get(unit, mem, phy_bank, &entries_per_bank,
   3550                                                 &entries_per_row, NULL,
   3551                                                 &bank_base, &bucket_offset));
   3552             bucket = soc_th_l3x_bank_entry_hash(unit, phy_bank, base_entry);
   3553         } else
   3554 #endif
   3555 #ifdef BCM_TRIDENT2_SUPPORT
   3556         if (SOC_IS_TD2_TT2(unit)) {
   3557             SOC_IF_ERROR_RETURN
   3558                 (soc_trident2_hash_bank_number_get(unit, mem, bank, &phy_bank));
   3559             SOC_IF_ERROR_RETURN(
   3560                 soc_trident2_hash_bank_info_get(unit, mem, phy_bank, &entries_per_bank,
   3561                                                 &entries_per_row, NULL,
   3562                                                 &bank_base, &bucket_offset));
   3563             bucket = soc_td2_l3x_bank_entry_hash(unit, phy_bank, base_entry);
   3564         }
   3565 #endif
   3566         bucket_array[bank] = bucket;
   3567         index_array[bank]  = bank_base + bucket * entries_per_row + bucket_offset;
   3568         if (phy_bank_array) {
   3569             phy_bank_array[bank]  = phy_bank;
   3570         }
   3571         if (entry_num_array) {
   3572             entry_num_array[bank] = entries_per_bank;
   3573         }
   3574     }
   3575 
   3576     return SOC_E_NONE;
   3577 }
   3578 #endif
   3579 
   3580 #endif /* BCM_XGS_SWITCH_SUPPORT */