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