hashing.c (76397B)
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: hashing.c 8 * Purpose: Hash calcualtions for trunk and ECMP packets. 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/drv.h> 14 #include <soc/hash.h> 15 #include <bcm/switch.h> 16 #include <bcm/error.h> 17 18 #include <bcm_int/esw_dispatch.h> 19 #include <bcm_int/esw/firebolt.h> 20 #include <bcm_int/esw/port.h> 21 #include <bcm_int/esw/stack.h> 22 #include <bcm_int/esw/switch.h> 23 24 typedef struct bcm_rtag7_base_hash_s { 25 uint32 rtag7_hash16_value_a_0; /* hash a0 result */ 26 uint32 rtag7_hash16_value_a_1; /* hash a1 result */ 27 uint32 rtag7_hash16_value_b_0; /* hash b0 result */ 28 uint32 rtag7_hash16_value_b_1; /* hash b1 result */ 29 uint32 rtag7_macro_flow_id; /* hash micro flow result */ 30 uint32 rtag7_port_lbn; /* port LBN value from the port table*/ 31 uint32 rtag7_lbid_hash; /* LBID hash calculation*/ 32 bcm_port_t dev_src_port; /* Local source port */ 33 bcm_port_t src_port; /* System source port */ 34 bcm_module_t src_modid; /* System source modid */ 35 uint8 is_nonuc; /* Non-unicast */ 36 uint8 hash_a_valid; /* Hash A result use valid input */ 37 uint8 hash_b_valid; /* Hash B result use valid input */ 38 uint8 lbid_hash_valid; /* LBID Hash value is valid */ 39 } bcm_rtag7_base_hash_t; 40 41 #define ETHERTYPE_IPV6 0x86dd /* ipv6 ethertype */ 42 #define ETHERTYPE_IPV4 0x0800 /* ipv4 ethertype */ 43 #define ETHERTYPE_MIN 0x0600 /* minimum ethertype for hashing */ 44 45 #define IP_PROT_TCP 0x6 /* TCP protocol number */ 46 #define IP_PROT_UDP 0x11 /* TCP protocol number */ 47 48 #define RTAG7_L2_ONLY 0x0 49 #define RTAG7_UNKNOWN_HIGIG 0x1 50 #define RTAG7_MPLS 0x2 51 #define RTAG7_MIM 0x3 52 #define RTAG7_IPV4 0x4 53 #define RTAG7_IPV6 0x5 54 #define RTAG7_FCOE 0x6 55 #define RTAG7_TRILL 0x7 56 57 58 59 STATIC int 60 main__do_rtag7_hashing(int unit, 61 bcm_switch_pkt_info_t *pkt_info, 62 bcm_rtag7_base_hash_t *hash_res) 63 { 64 /* regular var declaration */ 65 uint32 hash_src_port; 66 uint32 hash_src_modid; 67 uint32 rtag7_a_sel; 68 bcm_ip_t sip_a; /* Source IPv4 address. */ 69 bcm_ip_t dip_a; /* Destination IPv4 address. */ 70 uint32 rtag7_b_sel; 71 bcm_ip_t sip_b; /* Source IPv4 address. */ 72 bcm_ip_t dip_b; /* Destination IPv4 address. */ 73 uint32 hash_field_bmap_a; /* block A chosen bitmap*/ 74 uint32 hash_field_bmap_b; /* block B chosen bitmap*/ 75 76 uint32 hash_word[7]; 77 uint32 hash[13]; 78 int elem, elem_bit; 79 uint32 hash_element_valid_bits; 80 /* int ip6_addrs = FALSE, ip4_addrs = FALSE; */ 81 int sip_valid = FALSE, dip_valid = FALSE; 82 uint32 macro_flow_id; 83 84 uint32 hash_crc16_bisync; 85 uint32 hash_crc16_ccitt; 86 uint32 hash_crc32; 87 uint32 hash_xor16; 88 uint32 hash_xor8; 89 uint32 hash_xor4; 90 uint32 hash_xor2; 91 uint32 hash_xor1; 92 uint32 xor32; 93 94 /* register var declaration */ 95 uint8 rtag7_disable_hash_ipv4_a; 96 uint8 rtag7_disable_hash_ipv6_a; 97 98 uint8 rtag7_disable_hash_ipv4_b; 99 uint8 rtag7_disable_hash_ipv6_b; 100 uint8 rtag7_ipv6_addr_use_lsb_a; 101 uint8 rtag7_ipv6_addr_use_lsb_b; 102 uint8 rtag7_pre_processing_enable_a; 103 uint8 rtag7_pre_processing_enable_b; 104 uint8 rtag7_en_flow_label_ipv6_a; 105 uint8 rtag7_en_flow_label_ipv6_b; 106 uint8 rtag7_en_bin_12_overlay_a; 107 uint8 rtag7_en_bin_12_overlay_b; 108 uint32 rtag7_hash_seed_a; 109 uint32 rtag7_hash_seed_b; 110 uint32 rtag7_hash_a0_function_select; 111 uint32 rtag7_hash_a1_function_select; 112 uint32 rtag7_hash_b0_function_select; 113 uint32 rtag7_hash_b1_function_select; 114 uint32 rtag7_macro_flow_hash_function_select; 115 uint8 rtag7_macro_flow_hash_byte_sel; 116 117 uint64 rtag7_hash_control; 118 uint32 rtag7_hash_control_2, rtag7_hash_control_3; 119 uint32 rtag7_hash_seed_a_reg, rtag7_hash_seed_b_reg; 120 soc_reg_t sc_reg; 121 soc_field_t sc_field; 122 uint32 sc_val; 123 124 SOC_IF_ERROR_RETURN 125 (READ_RTAG7_HASH_CONTROLr(unit, &rtag7_hash_control)); 126 SOC_IF_ERROR_RETURN 127 (READ_RTAG7_HASH_CONTROL_2r(unit, &rtag7_hash_control_2)); 128 129 SOC_IF_ERROR_RETURN 130 (READ_RTAG7_HASH_CONTROL_3r(unit, &rtag7_hash_control_3)); 131 SOC_IF_ERROR_RETURN 132 (READ_RTAG7_HASH_SEED_Ar(unit, &rtag7_hash_seed_a_reg)); 133 SOC_IF_ERROR_RETURN 134 (READ_RTAG7_HASH_SEED_Br(unit, &rtag7_hash_seed_b_reg)); 135 136 /* RTAG7 hash registers */ 137 rtag7_disable_hash_ipv4_a = 138 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 139 DISABLE_HASH_IPV4_Af); 140 rtag7_disable_hash_ipv6_a = 141 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 142 DISABLE_HASH_IPV6_Af); 143 rtag7_disable_hash_ipv4_b = 144 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 145 DISABLE_HASH_IPV4_Bf); 146 rtag7_disable_hash_ipv6_b = 147 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 148 DISABLE_HASH_IPV6_Bf); 149 rtag7_ipv6_addr_use_lsb_a = 150 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 151 IPV6_COLLAPSED_ADDR_SELECT_Af); 152 rtag7_ipv6_addr_use_lsb_b = 153 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 154 IPV6_COLLAPSED_ADDR_SELECT_Bf); 155 156 rtag7_pre_processing_enable_a = 157 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 158 HASH_PRE_PROCESSING_ENABLE_Af); 159 rtag7_pre_processing_enable_b = 160 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 161 HASH_PRE_PROCESSING_ENABLE_Bf); 162 rtag7_hash_a0_function_select = 163 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 164 HASH_A0_FUNCTION_SELECTf); 165 rtag7_hash_a1_function_select = 166 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 167 HASH_A1_FUNCTION_SELECTf); 168 rtag7_hash_b0_function_select = 169 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 170 HASH_B0_FUNCTION_SELECTf); 171 rtag7_hash_b1_function_select = 172 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 173 HASH_B1_FUNCTION_SELECTf); 174 175 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 176 ENABLE_FLOW_LABEL_IPV6_Af)) { 177 rtag7_en_flow_label_ipv6_a = 178 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 179 rtag7_hash_control_2, 180 ENABLE_FLOW_LABEL_IPV6_Af); 181 } else { 182 rtag7_en_flow_label_ipv6_a = 0; /* A0 bincomp value */ 183 } 184 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 185 ENABLE_FLOW_LABEL_IPV6_Bf)) { 186 rtag7_en_flow_label_ipv6_b = 187 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 188 rtag7_hash_control_2, 189 ENABLE_FLOW_LABEL_IPV6_Bf); 190 } else { 191 rtag7_en_flow_label_ipv6_b = 0; /* A0 bincomp value */ 192 } 193 rtag7_en_bin_12_overlay_a = 194 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2, 195 ENABLE_BIN_12_OVERLAY_Af); 196 rtag7_en_bin_12_overlay_b = 197 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2, 198 ENABLE_BIN_12_OVERLAY_Bf); 199 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 200 MACRO_FLOW_HASH_FUNC_SELf)) { 201 rtag7_macro_flow_hash_function_select = 202 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 203 rtag7_hash_control_2, 204 MACRO_FLOW_HASH_FUNC_SELf); 205 } else { 206 rtag7_macro_flow_hash_function_select = 0; /* A0 bincomp value */ 207 } 208 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 209 MACRO_FLOW_HASH_BYTE_SELf)) { 210 rtag7_macro_flow_hash_byte_sel = 211 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 212 rtag7_hash_control_2, 213 MACRO_FLOW_HASH_BYTE_SELf); 214 } else { 215 rtag7_macro_flow_hash_byte_sel = 0; /* A0 bincomp value */ 216 } 217 218 rtag7_hash_seed_a = 219 soc_reg_field_get(unit, RTAG7_HASH_SEED_Ar, rtag7_hash_seed_a_reg, 220 HASH_SEED_Af); 221 rtag7_hash_seed_b = 222 soc_reg_field_get(unit, RTAG7_HASH_SEED_Br, rtag7_hash_seed_b_reg, 223 HASH_SEED_Bf); 224 225 /* RTAG7 tables */ 226 /* the first step is to choose the paket type and to fold the ipv6 227 * addresses in case of IPv6 packet*/ 228 229 /* option A ip folding for rtag 7 */ 230 if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 231 (pkt_info->ethertype == ETHERTYPE_IPV6)) && 232 (rtag7_disable_hash_ipv6_a == 0)) { 233 234 /* ip6_addrs = TRUE; */ 235 rtag7_a_sel = RTAG7_IPV6; 236 237 /* This section will fold the Ipv6 address to single 32 bit address 238 * by using of of the methose LSB or xor */ 239 if (rtag7_ipv6_addr_use_lsb_a) { 240 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 241 sip_a = (pkt_info->sip6[12] << 24) | 242 (pkt_info->sip6[13] << 16) | 243 (pkt_info->sip6[14] << 8) | 244 (pkt_info->sip6[15]); 245 sip_valid = TRUE; 246 } else { 247 sip_a = 0; 248 } 249 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 250 dip_a = (pkt_info->dip6[12] << 24) | 251 (pkt_info->dip6[13] << 16) | 252 (pkt_info->dip6[14] << 8) | 253 (pkt_info->dip6[15]); 254 dip_valid = TRUE; 255 } else { 256 dip_a = 0; 257 } 258 } else { 259 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 260 sip_a = 261 ((pkt_info->sip6[12] << 24) | 262 (pkt_info->sip6[13] << 16) | 263 (pkt_info->sip6[14] << 8) | 264 (pkt_info->sip6[15])) ^ 265 ((pkt_info->sip6[8] << 24) | 266 (pkt_info->sip6[9] << 16) | 267 (pkt_info->sip6[10] << 8) | 268 (pkt_info->sip6[11])) ^ 269 ((pkt_info->sip6[4] << 24) | 270 (pkt_info->sip6[5] << 16) | 271 (pkt_info->sip6[6] << 8) | 272 (pkt_info->sip6[7])) ^ 273 ((pkt_info->sip6[0] << 24) | 274 (pkt_info->sip6[1] << 16) | 275 (pkt_info->sip6[2] << 8) | 276 (pkt_info->sip6[3])); 277 sip_valid = TRUE; 278 } else { 279 sip_a = 0; 280 } 281 282 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 283 dip_a = 284 ((pkt_info->dip6[12] << 24) | 285 (pkt_info->dip6[13] << 16) | 286 (pkt_info->dip6[14] << 8) | 287 (pkt_info->dip6[15])) ^ 288 ((pkt_info->dip6[8] << 24) | 289 (pkt_info->dip6[9] << 16) | 290 (pkt_info->dip6[10] << 8) | 291 (pkt_info->dip6[11])) ^ 292 ((pkt_info->dip6[4] << 24) | 293 (pkt_info->dip6[5] << 16) | 294 (pkt_info->dip6[6] << 8) | 295 (pkt_info->dip6[7])) ^ 296 ((pkt_info->dip6[0] << 24) | 297 (pkt_info->dip6[1] << 16) | 298 (pkt_info->dip6[2] << 8) | 299 (pkt_info->dip6[3])); 300 dip_valid = TRUE; 301 } else { 302 dip_a = 0; 303 } 304 } 305 } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 306 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 307 (rtag7_disable_hash_ipv4_a == 0)) { 308 309 /* ip4_addrs = TRUE; */ 310 rtag7_a_sel = RTAG7_IPV4; 311 312 /* only one IPv4 hdr */ 313 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) { 314 sip_a = pkt_info->sip; 315 sip_valid = TRUE; 316 } else { 317 sip_a = 0; 318 } 319 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) { 320 dip_a = pkt_info->dip; 321 dip_valid = TRUE; 322 } else { 323 dip_a = 0; 324 } 325 } else { 326 rtag7_a_sel = RTAG7_L2_ONLY; 327 sip_a = dip_a = 0; 328 } 329 330 /* End of option A ip folding for rtag 7 */ 331 332 /* option B ip folding for rtag 7 */ 333 if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 334 (pkt_info->ethertype == ETHERTYPE_IPV6)) && 335 (rtag7_disable_hash_ipv6_b == 0)) { 336 337 /* ip6_addrs = TRUE; */ 338 rtag7_b_sel = RTAG7_IPV6; 339 340 /* This section will fold the Ipv6 address to single 32 bit address 341 * by using of of the methose LSB or xor */ 342 if (rtag7_ipv6_addr_use_lsb_b) { 343 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 344 sip_b = (pkt_info->sip6[12] << 24) | 345 (pkt_info->sip6[13] << 16) | 346 (pkt_info->sip6[14] << 8) | 347 (pkt_info->sip6[15]); 348 sip_valid = TRUE; 349 } else { 350 sip_b = 0; 351 } 352 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 353 dip_b = (pkt_info->dip6[12] << 24) | 354 (pkt_info->dip6[13] << 16) | 355 (pkt_info->dip6[14] << 8) | 356 (pkt_info->dip6[15]); 357 dip_valid = TRUE; 358 } else { 359 dip_b = 0; 360 } 361 } else { 362 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 363 sip_b = 364 ((pkt_info->sip6[12] << 24) | 365 (pkt_info->sip6[13] << 16) | 366 (pkt_info->sip6[14] << 8) | 367 (pkt_info->sip6[15])) ^ 368 ((pkt_info->sip6[8] << 24) | 369 (pkt_info->sip6[9] << 16) | 370 (pkt_info->sip6[10] << 8) | 371 (pkt_info->sip6[11])) ^ 372 ((pkt_info->sip6[4] << 24) | 373 (pkt_info->sip6[5] << 16) | 374 (pkt_info->sip6[6] << 8) | 375 (pkt_info->sip6[7])) ^ 376 ((pkt_info->sip6[0] << 24) | 377 (pkt_info->sip6[1] << 16) | 378 (pkt_info->sip6[2] << 8) | 379 (pkt_info->sip6[3])); 380 sip_valid = TRUE; 381 } else { 382 sip_b = 0; 383 } 384 385 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 386 dip_b = 387 ((pkt_info->dip6[12] << 24) | 388 (pkt_info->dip6[13] << 16) | 389 (pkt_info->dip6[14] << 8) | 390 (pkt_info->dip6[15])) ^ 391 ((pkt_info->dip6[8] << 24) | 392 (pkt_info->dip6[9] << 16) | 393 (pkt_info->dip6[10] << 8) | 394 (pkt_info->dip6[11])) ^ 395 ((pkt_info->dip6[4] << 24) | 396 (pkt_info->dip6[5] << 16) | 397 (pkt_info->dip6[6] << 8) | 398 (pkt_info->dip6[7])) ^ 399 ((pkt_info->dip6[0] << 24) | 400 (pkt_info->dip6[1] << 16) | 401 (pkt_info->dip6[2] << 8) | 402 (pkt_info->dip6[3])); 403 dip_valid = TRUE; 404 } else { 405 dip_b = 0; 406 } 407 } 408 } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 409 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 410 (rtag7_disable_hash_ipv4_b == 0)) { 411 412 /* ip4_addrs = TRUE; */ 413 rtag7_b_sel = RTAG7_IPV4; 414 415 /* only one IPv4 hdr */ 416 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) { 417 sip_b = pkt_info->sip; 418 sip_valid = TRUE; 419 } else { 420 sip_b = 0; 421 } 422 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) { 423 dip_b = pkt_info->dip; 424 dip_valid = TRUE; 425 } else { 426 dip_b = 0; 427 } 428 } else { 429 rtag7_b_sel = RTAG7_L2_ONLY; 430 sip_b = dip_b = 0; 431 } 432 /* End of option B ip folding for rtag 7 */ 433 434 435 436 /* 437 * ============= 438 * RTAG7 HASHING 439 * ============= 440 */ 441 442 /* The inputs to the RTAG7 hash function were reduced in the begining 443 * of this function. 444 * This logic takes the hash inputs and computes both A and B RTAG7 445 * hash values. 446 */ 447 448 /* Change source modid/port to PORT32 space for hashing */ 449 hash_src_port = hash_res->src_port; 450 hash_src_modid = hash_res->src_modid; 451 452 /* Only if the packet was sourced by this chip, make sure to use 453 * PORT32 space modid and port if dual modid is enabled 454 * Need to do this because of front panel ports. 455 * 456 * Already handled by API gport resolve */ 457 458 /* initialize the variables */ 459 sal_memset(hash,0x0,(sizeof(uint32))*13); 460 sal_memset(hash_word,0x0,(sizeof(uint32))*7); 461 462 hash_crc16_bisync = 0; 463 hash_crc16_ccitt = 0; 464 hash_crc32 = 0; 465 hash_xor16 = 0; 466 hash_xor8 = 0; 467 hash_xor4 = 0; 468 hash_xor2 = 0; 469 hash_xor1 = 0; 470 xor32 = 0; 471 472 hash[12] = 0; 473 hash[3] = hash_src_port; 474 hash[2] = hash_src_modid & 0xff; 475 hash[1] = 0; 476 hash[0] = 0; 477 478 hash_element_valid_bits = 0x1fff; /* Init to valid fields above */ 479 480 /* option A hash calculation for rtag 7 */ 481 482 if ((rtag7_a_sel == RTAG7_IPV6) || (rtag7_a_sel == RTAG7_IPV4)) { 483 484 if (sip_valid) { 485 hash[11] = (sip_a >> 16) & 0xffff; 486 hash[10] = sip_a & 0xffff; 487 } else { 488 hash_element_valid_bits &= ~0xc00; 489 } 490 if (dip_valid) { 491 hash[9] = (dip_a >> 16) & 0xffff; 492 hash[8] = dip_a & 0xffff; 493 } else { 494 hash_element_valid_bits &= ~0x300; 495 } 496 497 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 498 hash[7] = pkt_info->vid & 0xfff; 499 } else { 500 hash_element_valid_bits &= ~0x80; 501 } 502 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) { 503 hash[6] = pkt_info->src_l4_port; 504 } else { 505 hash_element_valid_bits &= ~0x40; 506 } 507 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) { 508 hash[5] = pkt_info->dst_l4_port; 509 } else { 510 hash_element_valid_bits &= ~0x20; 511 } 512 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) { 513 hash[4] = pkt_info->protocol; 514 } else { 515 hash_element_valid_bits &= ~0x10; 516 } 517 518 if ((rtag7_a_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_a) { 519 LOG_VERBOSE(BSL_LS_BCM_COMMON, 520 (BSL_META_U(unit, 521 "Hash calculation: The system is set to use ipv6 flow label and the code can't get this info\n"))); 522 } 523 524 if (rtag7_a_sel == RTAG7_IPV4) { /* Use IPv4 BITMAPs */ 525 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 526 ((pkt_info->protocol == IP_PROT_TCP) || 527 (pkt_info->protocol == IP_PROT_UDP))) { 528 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 529 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 530 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 531 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r; 532 sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af; 533 LOG_VERBOSE(BSL_LS_BCM_COMMON, 534 (BSL_META_U(unit, 535 "Hash calculation: Bitmap is block A IPv4 TCP=UDP\n"))); 536 } else { 537 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r; 538 sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Af; 539 LOG_VERBOSE(BSL_LS_BCM_COMMON, 540 (BSL_META_U(unit, 541 "Hash calculation: Bitmap is block A IPv4 L4 tcp/udp\n"))); 542 } 543 } else { 544 sc_reg = RTAG7_HASH_FIELD_BMAP_1r; 545 sc_field = IPV4_FIELD_BITMAP_Af; 546 LOG_VERBOSE(BSL_LS_BCM_COMMON, 547 (BSL_META_U(unit, 548 "Hash calculation: Bitmap is block A IPv4 \n"))); 549 } 550 551 } else { /* Use IPv6 BITMAPs */ 552 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 553 ((pkt_info->protocol == IP_PROT_TCP) || 554 (pkt_info->protocol == IP_PROT_UDP))) { 555 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 556 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 557 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 558 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r; 559 sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af; 560 LOG_VERBOSE(BSL_LS_BCM_COMMON, 561 (BSL_META_U(unit, 562 "Hash calculation: Bitmap is block A IPv6 TCP=UDP\n"))); 563 } else { 564 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r; 565 sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Af; 566 LOG_VERBOSE(BSL_LS_BCM_COMMON, 567 (BSL_META_U(unit, 568 "Hash calculation: Bitmap is block A IPv6 L4 tcp/udp\n"))); 569 } 570 } else { 571 sc_reg = RTAG7_HASH_FIELD_BMAP_2r; 572 sc_field = IPV6_FIELD_BITMAP_Af; 573 LOG_VERBOSE(BSL_LS_BCM_COMMON, 574 (BSL_META_U(unit, 575 "Hash calculation: Bitmap is block A IPv6 \n"))); 576 } 577 } 578 579 } else { /* Catch-all for RTAG7_L2_ONLY */ 580 581 /* L2 only hash key */ 582 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) { 583 hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1]; 584 hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3]; 585 hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5]; 586 } else { 587 hash_element_valid_bits &= ~0xe00; 588 } 589 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) { 590 hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1]; 591 hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3]; 592 hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5]; 593 } else { 594 hash_element_valid_bits &= ~0x1c0; 595 } 596 597 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) { 598 hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ? 599 pkt_info->ethertype : 0; 600 } else { 601 hash_element_valid_bits &= ~0x20; 602 } 603 604 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 605 hash[4] = pkt_info->vid & 0xfff; 606 } else { 607 hash_element_valid_bits &= ~0x10; 608 } 609 610 sc_reg = RTAG7_HASH_FIELD_BMAP_3r; 611 sc_field = L2_FIELD_BITMAP_Af; 612 LOG_VERBOSE(BSL_LS_BCM_COMMON, 613 (BSL_META_U(unit, 614 "Hash calculation: Bitmap is block A L2\n"))); 615 } 616 617 BCM_IF_ERROR_RETURN 618 (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val)); 619 hash_field_bmap_a = soc_reg_field_get(unit, sc_reg, sc_val, sc_field); 620 621 /* Pre-Processing */ 622 623 if (rtag7_pre_processing_enable_a) { 624 625 hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2); 626 hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2); 627 hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2); 628 hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2); 629 hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2); 630 hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2); 631 hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2); 632 hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2); 633 hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2); 634 hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2); 635 hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2); 636 hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2); 637 hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2); 638 639 } 640 641 if (((hash_field_bmap_a >> 12) & 0x1) == 0) { 642 hash[12] = 0; 643 } 644 645 if (rtag7_en_bin_12_overlay_a) { 646 hash_word[6] = (rtag7_hash_seed_a & 0xffff0000) | (hash[12] & 0xffff); 647 } else { 648 hash_word[6] = rtag7_hash_seed_a; 649 } 650 651 hash_res->hash_a_valid = TRUE; 652 for (elem = 11; elem >= 0; elem--) { 653 elem_bit = 1 << elem; 654 if (0 != (hash_field_bmap_a & elem_bit)) { 655 if (0 != (hash_element_valid_bits & elem_bit)) { 656 hash_word[elem/2] |= 657 ((hash[elem] & 0xffff) << (16 * (elem % 2))); 658 } else { 659 hash_res->hash_a_valid = FALSE; 660 break; 661 } 662 } 663 } 664 665 /*Calculation*/ 666 xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ 667 hash_word[2] ^ hash_word[1] ^ hash_word[0]; 668 669 hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff); 670 hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff); 671 hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf); 672 hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3); 673 hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1); 674 675 hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28); 676 hash_crc16_ccitt = _shr_crc16_ccitt_array(hash_word, 28); 677 hash_crc32 = _shr_crc32_castagnoli_array(hash_word, 28); 678 679 switch (rtag7_hash_a0_function_select) { 680 case 0: /* reserved */ 681 hash_res->rtag7_hash16_value_a_0 = 0; 682 break; 683 case 1: /* reserved */ 684 hash_res->rtag7_hash16_value_a_0 = 0; 685 break; 686 case 2: /* reserved */ 687 hash_res->rtag7_hash16_value_a_0 = 0; 688 break; 689 case 3: /* CRC16 BISYNC */ 690 hash_res->rtag7_hash16_value_a_0 = hash_crc16_bisync; 691 break; 692 case 4: /* CRC16_XOR1 */ 693 hash_res->rtag7_hash16_value_a_0 = hash_xor1 & 0x1; 694 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 695 break; 696 case 5: /* CRC16_XOR2 */ 697 hash_res->rtag7_hash16_value_a_0 = hash_xor2 & 0x3; 698 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 699 break; 700 case 6: /* CRC16_XOR4 */ 701 hash_res->rtag7_hash16_value_a_0 = hash_xor4 & 0xf; 702 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 703 break; 704 case 7: /* CRC16_XOR8 */ 705 hash_res->rtag7_hash16_value_a_0 = hash_xor8 & 0xff; 706 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 707 break; 708 case 8: /* XOR16 */ 709 hash_res->rtag7_hash16_value_a_0 = hash_xor16; 710 break; 711 case 9: /* CRC16_CCITT */ 712 hash_res->rtag7_hash16_value_a_0 = hash_crc16_ccitt; 713 break; 714 case 10: /* CRC32_LO */ 715 hash_res->rtag7_hash16_value_a_0 = hash_crc32 & 0xffff; 716 break; 717 case 11: /* CRC32_HI */ 718 hash_res->rtag7_hash16_value_a_0 = (hash_crc32 >> 16) & 0xffff; 719 break; 720 default: /* reserved */ 721 hash_res->rtag7_hash16_value_a_0 = 0; 722 break; 723 } 724 725 switch (rtag7_hash_a1_function_select) { 726 case 0: /* reserved */ 727 hash_res->rtag7_hash16_value_a_1 = 0; 728 break; 729 case 1: /* reserved */ 730 hash_res->rtag7_hash16_value_a_1 = 0; 731 break; 732 case 2: /* reserved */ 733 hash_res->rtag7_hash16_value_a_1 = 0; 734 break; 735 case 3: /* CRC16 BISYNC */ 736 hash_res->rtag7_hash16_value_a_1 = hash_crc16_bisync; 737 break; 738 case 4: /* CRC16_XOR1 */ 739 hash_res->rtag7_hash16_value_a_1 = hash_xor1 & 0x1; 740 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 741 break; 742 case 5: /* CRC16_XOR2 */ 743 hash_res->rtag7_hash16_value_a_1 = hash_xor2 & 0x3; 744 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 745 break; 746 case 6: /* CRC16_XOR4 */ 747 hash_res->rtag7_hash16_value_a_1 = hash_xor4 & 0xf; 748 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 749 break; 750 case 7: /* CRC16_XOR8 */ 751 hash_res->rtag7_hash16_value_a_1 = hash_xor8 & 0xff; 752 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 753 break; 754 case 8: /* XOR16 */ 755 hash_res->rtag7_hash16_value_a_1 = hash_xor16; 756 break; 757 case 9: /* CRC16_CCITT */ 758 hash_res->rtag7_hash16_value_a_1 = hash_crc16_ccitt; 759 break; 760 case 10: /* CRC32_LO */ 761 hash_res->rtag7_hash16_value_a_1 = hash_crc32 & 0xffff; 762 break; 763 case 11: /* CRC32_HI */ 764 hash_res->rtag7_hash16_value_a_1 = (hash_crc32 >> 16) & 0xffff; 765 break; 766 default: /* reserved */ 767 hash_res->rtag7_hash16_value_a_1 = 0; 768 break; 769 } 770 771 /* End of option A hash calculation for rtag 7 */ 772 773 /* Generation of Macro Flow Based HASH Select */ 774 /* This is used for Macro flow based Hash function selection for all consumers of RTAG7 HASH */ 775 /* Macro flow based hash function selection improves distribution among members */ 776 /* Refer Each application (ECMP, LAG, HG-TRUNK) on how this is being used */ 777 switch (rtag7_macro_flow_hash_function_select) { 778 case 0: /* reserved */ 779 macro_flow_id = 0; 780 break; 781 case 1: /* reserved */ 782 macro_flow_id = 0; 783 break; 784 case 2: /* reserved */ 785 macro_flow_id = 0; 786 break; 787 case 3: /* CRC16 BISYNC */ 788 macro_flow_id = hash_crc16_bisync; 789 break; 790 case 4: /* CRC16_XOR1 */ 791 macro_flow_id = hash_xor1 & 0x1; 792 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 793 break; 794 case 5: /* CRC16_XOR2 */ 795 macro_flow_id = hash_xor2 & 0x3; 796 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 797 break; 798 case 6: /* CRC16_XOR4 */ 799 macro_flow_id = hash_xor4 & 0xf; 800 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 801 break; 802 case 7: /* CRC16_XOR8 */ 803 macro_flow_id = hash_xor8 & 0xff; 804 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 805 break; 806 case 8: /* XOR16 */ 807 macro_flow_id = hash_xor16; 808 break; 809 case 9: /* CRC16_CCITT */ 810 macro_flow_id = hash_crc16_ccitt; 811 break; 812 case 10: /* CRC32_LO */ 813 macro_flow_id = hash_crc32 & 0xffff; 814 break; 815 case 11: /* CRC32_HI */ 816 macro_flow_id = (hash_crc32 >> 16) & 0xffff; 817 break; 818 default: /* reserved */ 819 macro_flow_id = 0; 820 break; 821 } 822 hash_res->rtag7_macro_flow_id = (rtag7_macro_flow_hash_byte_sel) ? 823 ((macro_flow_id >> 8) & 0xff) : (macro_flow_id & 0xff); 824 825 /* option B hash calculation for rtag 7 */ 826 827 /* initialize the variables */ 828 829 sal_memset(hash,0x0,(sizeof(uint32))*13); 830 sal_memset(hash_word,0x0,(sizeof(uint32))*7); 831 832 hash_crc16_bisync = 0; 833 hash_crc16_ccitt = 0; 834 hash_crc32 = 0; 835 hash_xor16 = 0; 836 hash_xor8 = 0; 837 hash_xor4 = 0; 838 hash_xor2 = 0; 839 hash_xor1 = 0; 840 xor32 = 0; 841 842 hash[12] = 0; 843 hash[3] = hash_src_port; 844 hash[2] = hash_src_modid & 0xff; 845 hash[1] = 0; 846 hash[0] = 0; 847 848 hash_element_valid_bits = 0x1fff; /* Init to valid fields above */ 849 850 /* option B hash calculation for rtag 7 */ 851 852 if ((rtag7_b_sel == RTAG7_IPV6) || (rtag7_b_sel == RTAG7_IPV4)) { 853 if (sip_valid) { 854 hash[11] = (sip_b >> 16) & 0xffff; 855 hash[10] = sip_b & 0xffff; 856 } else { 857 hash_element_valid_bits &= ~0xc00; 858 } 859 if (dip_valid) { 860 hash[9] = (dip_b >> 16) & 0xffff; 861 hash[8] = dip_b & 0xffff; 862 } else { 863 hash_element_valid_bits &= ~0x300; 864 } 865 866 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 867 hash[7] = pkt_info->vid & 0xfff; 868 } else { 869 hash_element_valid_bits &= ~0x80; 870 } 871 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) { 872 hash[6] = pkt_info->src_l4_port; 873 } else { 874 hash_element_valid_bits &= ~0x40; 875 } 876 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) { 877 hash[5] = pkt_info->dst_l4_port; 878 } else { 879 hash_element_valid_bits &= ~0x20; 880 } 881 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) { 882 hash[4] = pkt_info->protocol; 883 } else { 884 hash_element_valid_bits &= ~0x10; 885 } 886 887 if ((rtag7_b_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_b) { 888 LOG_VERBOSE(BSL_LS_BCM_COMMON, 889 (BSL_META_U(unit, 890 "Hash calculation: The system is set to use ipv6 flow label and the code can't get this info\n"))); 891 } 892 893 if (rtag7_b_sel == RTAG7_IPV4) { /* Use IPv4 BITMAPs */ 894 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 895 ((pkt_info->protocol == IP_PROT_TCP) || 896 (pkt_info->protocol == IP_PROT_UDP))) { 897 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 898 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 899 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 900 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r; 901 sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf; 902 LOG_VERBOSE(BSL_LS_BCM_COMMON, 903 (BSL_META_U(unit, 904 "Hash calculation: Bitmap is block B IPv4 TCP=UDP\n"))); 905 } else { 906 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r; 907 sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Bf; 908 LOG_VERBOSE(BSL_LS_BCM_COMMON, 909 (BSL_META_U(unit, 910 "Hash calculation: Bitmap is block B IPv4 L4 tcp/udp\n"))); 911 } 912 } else { 913 sc_reg = RTAG7_HASH_FIELD_BMAP_1r; 914 sc_field = IPV4_FIELD_BITMAP_Bf; 915 LOG_VERBOSE(BSL_LS_BCM_COMMON, 916 (BSL_META_U(unit, 917 "Hash calculation: Bitmap is block B IPv4\n"))); 918 } 919 920 } else { /* Use IPv6 BITMAPs */ 921 922 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 923 ((pkt_info->protocol == IP_PROT_TCP) || 924 (pkt_info->protocol == IP_PROT_UDP))) { 925 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 926 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 927 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 928 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r; 929 sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf; 930 LOG_VERBOSE(BSL_LS_BCM_COMMON, 931 (BSL_META_U(unit, 932 "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n"))); 933 } else { 934 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r; 935 sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Bf; 936 LOG_VERBOSE(BSL_LS_BCM_COMMON, 937 (BSL_META_U(unit, 938 "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n"))); 939 } 940 } else { 941 sc_reg = RTAG7_HASH_FIELD_BMAP_2r; 942 sc_field = IPV6_FIELD_BITMAP_Bf; 943 LOG_VERBOSE(BSL_LS_BCM_COMMON, 944 (BSL_META_U(unit, 945 "Hash calculation: Bitmap is block B IPv6\n"))); 946 } 947 } 948 } else { /* Catch-all for RTAG7_L2_ONLY */ 949 950 /* L2 only hash key */ 951 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) { 952 hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1]; 953 hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3]; 954 hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5]; 955 } else { 956 hash_element_valid_bits &= ~0xe00; 957 } 958 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) { 959 hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1]; 960 hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3]; 961 hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5]; 962 } else { 963 hash_element_valid_bits &= ~0x1c0; 964 } 965 966 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) { 967 hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ? 968 pkt_info->ethertype : 0; 969 } else { 970 hash_element_valid_bits &= ~0x20; 971 } 972 973 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 974 hash[4] = pkt_info->vid & 0xfff; 975 } else { 976 hash_element_valid_bits &= ~0x10; 977 } 978 979 sc_reg = RTAG7_HASH_FIELD_BMAP_3r; 980 sc_field = L2_FIELD_BITMAP_Bf; 981 LOG_VERBOSE(BSL_LS_BCM_COMMON, 982 (BSL_META_U(unit, 983 "Hash calculation: Bitmap is block B L2\n"))); 984 } 985 986 BCM_IF_ERROR_RETURN 987 (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val)); 988 hash_field_bmap_b = soc_reg_field_get(unit, sc_reg, sc_val, sc_field); 989 990 /* Pre-Processing */ 991 992 if (rtag7_pre_processing_enable_b) { 993 994 hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2); 995 hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2); 996 hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2); 997 hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2); 998 hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2); 999 hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2); 1000 hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2); 1001 hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2); 1002 hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2); 1003 hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2); 1004 hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2); 1005 hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2); 1006 hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2); 1007 1008 } 1009 1010 if (((hash_field_bmap_b >> 12) & 0x1) == 0) { 1011 hash[12] = 0; 1012 } 1013 1014 if (rtag7_en_bin_12_overlay_b) { 1015 hash_word[6] = (rtag7_hash_seed_b & 0xffff0000) | (hash[12] & 0xffff); 1016 } else { 1017 hash_word[6] = rtag7_hash_seed_b; 1018 } 1019 1020 hash_res->hash_b_valid = TRUE; 1021 for (elem = 11; elem >= 0; elem--) { 1022 elem_bit = 1 << elem; 1023 if (0 != (hash_field_bmap_b & elem_bit)) { 1024 if (0 != (hash_element_valid_bits & elem_bit)) { 1025 hash_word[elem/2] |= 1026 ((hash[elem] & 0xffff) << (16 * (elem % 2))); 1027 } else { 1028 hash_res->hash_b_valid = FALSE; 1029 break; 1030 } 1031 } 1032 } 1033 1034 xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ hash_word[2] ^ hash_word[1] ^ hash_word[0]; 1035 hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff); 1036 hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff); 1037 hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf); 1038 hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3); 1039 hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1); 1040 1041 hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28); 1042 hash_crc16_ccitt = _shr_crc16_ccitt_array(hash_word, 28); 1043 hash_crc32 = _shr_crc32_castagnoli_array(hash_word, 28); 1044 1045 switch (rtag7_hash_b0_function_select) { 1046 case 0: /* reserved */ 1047 hash_res->rtag7_hash16_value_b_0 = 0; 1048 break; 1049 case 1: /* reserved */ 1050 hash_res->rtag7_hash16_value_b_0 = 0; 1051 break; 1052 case 2: /* reserved */ 1053 hash_res->rtag7_hash16_value_b_0 = 0; 1054 break; 1055 case 3: /* CRC16 BISYNC */ 1056 hash_res->rtag7_hash16_value_b_0 = hash_crc16_bisync; 1057 break; 1058 case 4: /* CRC16_XOR1 */ 1059 hash_res->rtag7_hash16_value_b_0 = hash_xor1 & 0x1; 1060 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1061 break; 1062 case 5: /* CRC16_XOR2 */ 1063 hash_res->rtag7_hash16_value_b_0 = hash_xor2 & 0x3; 1064 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1065 break; 1066 case 6: /* CRC16_XOR4 */ 1067 hash_res->rtag7_hash16_value_b_0 = hash_xor4 & 0xf; 1068 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1069 break; 1070 case 7: /* CRC16_XOR8 */ 1071 hash_res->rtag7_hash16_value_b_0 = hash_xor8 & 0xff; 1072 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1073 break; 1074 case 8: /* XOR16 */ 1075 hash_res->rtag7_hash16_value_b_0 = hash_xor16; 1076 break; 1077 case 9: /* CRC16_CCITT */ 1078 hash_res->rtag7_hash16_value_b_0 = hash_crc16_ccitt; 1079 break; 1080 case 10: /* CRC32_LO */ 1081 hash_res->rtag7_hash16_value_b_0 = hash_crc32 & 0xffff; 1082 break; 1083 case 11: /* CRC32_HI */ 1084 hash_res->rtag7_hash16_value_b_0 = (hash_crc32 >> 16) & 0xffff; 1085 break; 1086 default: /* reserved */ 1087 hash_res->rtag7_hash16_value_b_0 = 0; 1088 break; 1089 } 1090 1091 switch (rtag7_hash_b1_function_select) { 1092 case 0: /* reserved */ 1093 hash_res->rtag7_hash16_value_b_1 = 0; 1094 break; 1095 case 1: /* reserved */ 1096 hash_res->rtag7_hash16_value_b_1 = 0; 1097 break; 1098 case 2: /* reserved */ 1099 hash_res->rtag7_hash16_value_b_1 = 0; 1100 break; 1101 case 3: /* CRC16 BISYNC */ 1102 hash_res->rtag7_hash16_value_b_1 = hash_crc16_bisync; 1103 break; 1104 case 4: /* CRC16_XOR1 */ 1105 hash_res->rtag7_hash16_value_b_1 = hash_xor1 & 0x1; 1106 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1107 break; 1108 case 5: /* CRC16_XOR2 */ 1109 hash_res->rtag7_hash16_value_b_1 = hash_xor2 & 0x3; 1110 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1111 break; 1112 case 6: /* CRC16_XOR4 */ 1113 hash_res->rtag7_hash16_value_b_1 = hash_xor4 & 0xf; 1114 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1115 break; 1116 case 7: /* CRC16_XOR8 */ 1117 hash_res->rtag7_hash16_value_b_1 = hash_xor8 & 0xff; 1118 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1119 break; 1120 case 8: /* XOR16 */ 1121 hash_res->rtag7_hash16_value_b_1 = hash_xor16; 1122 break; 1123 case 9: /* CRC16_CCITT */ 1124 hash_res->rtag7_hash16_value_b_1 = hash_crc16_ccitt; 1125 break; 1126 case 10: /* CRC32_LO */ 1127 hash_res->rtag7_hash16_value_b_1 = hash_crc32 & 0xffff; 1128 break; 1129 case 11: /* CRC32_HI */ 1130 hash_res->rtag7_hash16_value_b_1 = (hash_crc32 >> 16) & 0xffff; 1131 break; 1132 default: /* reserved */ 1133 hash_res->rtag7_hash16_value_b_1 = 0; 1134 break; 1135 } 1136 1137 /* End of option B hash calculation for rtag 7 */ 1138 return BCM_E_NONE; 1139 } 1140 1141 /*----------------------------------------------------------------*/ 1142 1143 1144 1145 STATIC int 1146 select_hash_subfield(int hash_sub_sel, uint32 *selected_subfield, 1147 bcm_rtag7_base_hash_t *hash_Base) 1148 { 1149 int rv = BCM_E_NONE; 1150 *selected_subfield = 0; 1151 1152 switch (hash_sub_sel) { 1153 case 0: /* select pkt hash A */ 1154 *selected_subfield = hash_Base->rtag7_hash16_value_a_0; 1155 if (!hash_Base->hash_a_valid) { 1156 /* Missing paramter in input */ 1157 rv = BCM_E_PARAM; 1158 } 1159 break; 1160 1161 case 1: /* select pkt hash B */ 1162 *selected_subfield = hash_Base->rtag7_hash16_value_b_0; 1163 if (!hash_Base->hash_b_valid) { 1164 /* Missing paramter in input */ 1165 rv = BCM_E_PARAM; 1166 } 1167 break; 1168 1169 case 2: /* select port LBN */ 1170 *selected_subfield = hash_Base->rtag7_port_lbn; 1171 break; 1172 1173 case 3: /* select destination port id or hash A */ 1174 1175 *selected_subfield = hash_Base->rtag7_hash16_value_a_0; 1176 if (!hash_Base->hash_a_valid) { 1177 /* Missing paramter in input */ 1178 rv = BCM_E_PARAM; 1179 } 1180 break; 1181 1182 case 4: /* select LBID from module header or from SW1 stage */ 1183 *selected_subfield = hash_Base->rtag7_lbid_hash; 1184 if (!hash_Base->lbid_hash_valid) { 1185 /* LBID setting isn't RTAG7 */ 1186 rv = BCM_E_CONFIG; 1187 } 1188 break; 1189 1190 case 5: /* select LBID from SW1 stage */ 1191 *selected_subfield = hash_Base->rtag7_lbid_hash; 1192 if (!hash_Base->lbid_hash_valid) { 1193 /* LBID setting isn't RTAG7 */ 1194 rv = BCM_E_CONFIG; 1195 } 1196 break; 1197 1198 case 6: 1199 *selected_subfield = hash_Base->rtag7_hash16_value_a_1; 1200 if (!hash_Base->hash_a_valid) { 1201 /* Missing paramter in input */ 1202 rv = BCM_E_PARAM; 1203 } 1204 break; 1205 1206 case 7: 1207 *selected_subfield = hash_Base->rtag7_hash16_value_b_1; 1208 if (!hash_Base->hash_b_valid) { 1209 /* Missing paramter in input */ 1210 rv = BCM_E_PARAM; 1211 } 1212 break; 1213 } 1214 1215 return rv; 1216 } 1217 1218 1219 STATIC int 1220 main__compute_lbid(int unit, bcm_rtag7_base_hash_t *hash_Base) 1221 { 1222 /*regular var declaration*/ 1223 uint32 lbid_hash_sub_sel; 1224 uint32 lbid_hash_offset; 1225 uint32 lbid_hash_value = 0; 1226 1227 /*register var declaration*/ 1228 int lbid_rtag; 1229 uint8 rtag7_hash_cfg_sel_lbid; 1230 uint32 rtag7_hash_lbid_reg; 1231 int pc_out, sc_val, lbid_idx, rv = BCM_E_NONE; 1232 1233 /*register read*/ 1234 BCM_IF_ERROR_RETURN 1235 (bcm_esw_port_control_get(unit, hash_Base->dev_src_port, 1236 bcmPortControlLoadBalancingNumber, 1237 &pc_out)); 1238 rtag7_hash_cfg_sel_lbid = pc_out; 1239 BCM_IF_ERROR_RETURN 1240 (bcm_esw_switch_control_get(unit, bcmSwitchLoadBalanceHashSelect, 1241 &sc_val)); 1242 lbid_rtag = sc_val; 1243 1244 /* ******************* LBID computation ************************* */ 1245 1246 if (lbid_rtag == 7) { 1247 lbid_idx = (0 != rtag7_hash_cfg_sel_lbid) ? 1 : 0; 1248 SOC_IF_ERROR_RETURN 1249 (READ_RTAG7_HASH_LBIDr(unit, lbid_idx, &rtag7_hash_lbid_reg)); 1250 if (hash_Base->is_nonuc) { 1251 lbid_hash_sub_sel = 1252 soc_reg_field_get(unit, RTAG7_HASH_LBIDr, 1253 rtag7_hash_lbid_reg, SUB_SEL_NONUCf); 1254 lbid_hash_offset = 1255 soc_reg_field_get(unit, RTAG7_HASH_LBIDr, 1256 rtag7_hash_lbid_reg, OFFSET_NONUCf); 1257 } else { 1258 lbid_hash_sub_sel = 1259 soc_reg_field_get(unit, RTAG7_HASH_LBIDr, 1260 rtag7_hash_lbid_reg, SUB_SEL_UCf); 1261 lbid_hash_offset = 1262 soc_reg_field_get(unit, RTAG7_HASH_LBIDr, 1263 rtag7_hash_lbid_reg, OFFSET_UCf); 1264 } 1265 /* Only UC hash selects apply to ECMP */ 1266 switch (lbid_hash_sub_sel) { 1267 1268 case 0: /* use pkt hash A */ 1269 lbid_hash_value = hash_Base->rtag7_hash16_value_a_0; 1270 if (!hash_Base->hash_a_valid) { 1271 /* Missing paramter in input */ 1272 rv = BCM_E_PARAM; 1273 } 1274 break; 1275 1276 case 1: /* use pkt hash B */ 1277 lbid_hash_value = hash_Base->rtag7_hash16_value_b_0; 1278 if (!hash_Base->hash_b_valid) { 1279 /* Missing paramter in input */ 1280 rv = BCM_E_PARAM; 1281 } 1282 break; 1283 1284 case 2: /* Use LBN */ 1285 lbid_hash_value = hash_Base->rtag7_port_lbn; 1286 break; 1287 1288 case 3: /* Use Destination PORTID or hash A */ 1289 lbid_hash_value = hash_Base->rtag7_hash16_value_a_0; 1290 if (!hash_Base->hash_a_valid) { 1291 /* Missing paramter in input */ 1292 rv = BCM_E_PARAM; 1293 } 1294 break; 1295 1296 case 4: /* Use LBID */ 1297 /* Higig lookup use mh_higig2_lbid */ 1298 1299 lbid_hash_value = 0; 1300 break; 1301 1302 case 5: 1303 lbid_hash_value = 0; 1304 break; 1305 1306 case 6: 1307 lbid_hash_value = hash_Base->rtag7_hash16_value_a_1; 1308 if (!hash_Base->hash_a_valid) { 1309 /* Missing paramter in input */ 1310 rv = BCM_E_PARAM; 1311 } 1312 break; 1313 1314 case 7: 1315 lbid_hash_value = hash_Base->rtag7_hash16_value_b_1; 1316 if (!hash_Base->hash_b_valid) { 1317 /* Missing paramter in input */ 1318 rv = BCM_E_PARAM; 1319 } 1320 break; 1321 } 1322 1323 /* 1324 * set up the hash value so that the LSB bits are 1325 * barrel shifted in case offset > 8. 1326 */ 1327 lbid_hash_value |= ((lbid_hash_value & 0xffff) << 16); 1328 1329 /* Only UC hash offsets apply to ECMP */ 1330 lbid_hash_value = (lbid_hash_value >> lbid_hash_offset); 1331 1332 hash_Base->rtag7_lbid_hash = (lbid_hash_value & 0xff); 1333 hash_Base->lbid_hash_valid = TRUE; 1334 1335 } else { /* LBID rtag is 0-6 */ 1336 /* this function not support the rtag 0-6 */ 1337 1338 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1339 (BSL_META_U(unit, 1340 "Hash calculation: This function doesn't support rtag 0 6 pls change register ING_CONFIG.LBID_RTAG to value 7\n"))); 1341 hash_Base->rtag7_lbid_hash = 0; 1342 hash_Base->lbid_hash_valid = FALSE; 1343 } 1344 return rv; 1345 /* ******************* END of LBID computation ************************* */ 1346 } 1347 1348 #ifdef INCLUDE_L3 1349 STATIC int 1350 compute_ecmp_hash(int unit, bcm_rtag7_base_hash_t *hash_Base, 1351 uint32 *hash_val) 1352 { 1353 /*regular var declaration*/ 1354 uint32 hash_sub_sel; 1355 uint32 hash_offset; 1356 uint32 hash_subfield; 1357 uint32 rtag7_ecmp_hash_value; 1358 uint8 rtag7_ecmp_use_macro_flow_hash; 1359 uint8 ecmp_hash_16bits; 1360 uint8 ecmp_hash_use_rtag7; 1361 uint32 rtag7_hash_ecmp; 1362 uint32 ing_config_2, hash_control; 1363 int pc_out, ecmp_idx; 1364 rtag7_flow_based_hash_entry_t rt7_fbh_entry; 1365 1366 /*register read*/ 1367 BCM_IF_ERROR_RETURN 1368 (bcm_esw_port_control_get(unit, hash_Base->dev_src_port, 1369 bcmPortControlECMPHashSet, 1370 &pc_out)); 1371 ecmp_idx = (0 != pc_out) ? 1 : 0; 1372 1373 SOC_IF_ERROR_RETURN 1374 (READ_RTAG7_HASH_ECMPr(unit, ecmp_idx, &rtag7_hash_ecmp)); 1375 if (soc_reg_field_valid(unit, RTAG7_HASH_ECMPr, USE_FLOW_HASHf)) { 1376 rtag7_ecmp_use_macro_flow_hash = 1377 soc_reg_field_get(unit, RTAG7_HASH_ECMPr, 1378 rtag7_hash_ecmp, USE_FLOW_HASHf); 1379 } else { 1380 /* A0 bincomp value */ 1381 rtag7_ecmp_use_macro_flow_hash = 0; 1382 } 1383 1384 if (SOC_REG_IS_VALID(unit, ING_CONFIG_2r)) { 1385 SOC_IF_ERROR_RETURN 1386 (READ_ING_CONFIG_2r(unit, &ing_config_2)); 1387 ecmp_hash_16bits = 1388 soc_reg_field_get(unit, ING_CONFIG_2r, ing_config_2, 1389 ECMP_HASH_16BITSf); 1390 } else { 1391 ecmp_hash_16bits = 0; 1392 } 1393 1394 SOC_IF_ERROR_RETURN 1395 (READ_HASH_CONTROLr(unit, &hash_control)); 1396 ecmp_hash_use_rtag7 = 1397 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 1398 ECMP_HASH_USE_RTAG7f); 1399 1400 /* RTAG7 hash computation */ 1401 1402 if (rtag7_ecmp_use_macro_flow_hash) { 1403 SOC_IF_ERROR_RETURN 1404 (soc_mem_read(unit, RTAG7_FLOW_BASED_HASHm, MEM_BLOCK_ANY, 1405 (hash_Base->rtag7_macro_flow_id & 0xff), 1406 &rt7_fbh_entry)); 1407 1408 /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */ 1409 /* For future designs this logic can be placed in RSEL1 */ 1410 1411 hash_sub_sel = soc_mem_field32_get(unit, RTAG7_FLOW_BASED_HASHm, 1412 &rt7_fbh_entry, SUB_SEL_ECMPf); 1413 hash_offset = soc_mem_field32_get(unit, RTAG7_FLOW_BASED_HASHm, 1414 &rt7_fbh_entry, OFFSET_ECMPf); 1415 1416 } else if (SOC_REG_IS_VALID(unit, RTAG7_HASH_ECMPr)) { 1417 hash_sub_sel = 1418 soc_reg_field_get(unit, RTAG7_HASH_ECMPr, 1419 rtag7_hash_ecmp, SUB_SELf); 1420 hash_offset = 1421 soc_reg_field_get(unit, RTAG7_HASH_ECMPr, 1422 rtag7_hash_ecmp, OFFSETf); 1423 } else { 1424 /* A0 bincomp values */ 1425 hash_sub_sel = 0; 1426 hash_offset = 0; 1427 } 1428 1429 BCM_IF_ERROR_RETURN 1430 (select_hash_subfield(hash_sub_sel, &hash_subfield, hash_Base)); 1431 1432 if (ecmp_hash_16bits) { 1433 /* Barrel shift the hash subfield, then take the LSB 16 bits */ 1434 rtag7_ecmp_hash_value = ((hash_subfield >> hash_offset) | (hash_subfield << (16 - hash_offset))) & 0xffff; 1435 } else { 1436 /* Trident-A0/A1 ECMP mode - SDK restricts to 256 members or less */ 1437 /* Barrel shift the hash subfield, then take the LSB 10 bits */ 1438 rtag7_ecmp_hash_value = ((hash_subfield >> hash_offset) | (hash_subfield << (16 - hash_offset))) & 0x3ff; 1439 } 1440 1441 /* Select between non-RTAG7 hash value and RTAG7 hash value */ 1442 1443 if (ecmp_hash_use_rtag7 == 0) { 1444 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1445 (BSL_META_U(unit, 1446 "Hash calculation: non rtag7 calc not supported\n"))); 1447 *hash_val = 0; 1448 } else { 1449 *hash_val = rtag7_ecmp_hash_value; 1450 } 1451 1452 return BCM_E_NONE; 1453 /* ***************** END of ECMP HASH CALCULATIONS. ************************ */ 1454 } 1455 #endif /* INCLUDE_L3 */ 1456 1457 STATIC int 1458 compute_rtag7_hash_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base, 1459 uint32 *hash_value) 1460 { 1461 uint32 hash_sub_sel; 1462 uint32 hash_offset; 1463 uint32 hash_subfield; 1464 uint32 rtag7_hash_trunk; 1465 uint32 rtag7_hash_trunk_value; 1466 int offset_shift; 1467 int pc_out, trunk_idx; 1468 uint32 hash_control; 1469 uint32 nuc_trunk_hash_use_rtag7; 1470 1471 BCM_IF_ERROR_RETURN 1472 (bcm_esw_port_control_get(unit, hash_Base->dev_src_port, 1473 bcmPortControlTrunkHashSet, 1474 &pc_out)); 1475 trunk_idx = (0 != pc_out) ? 1 : 0; 1476 SOC_IF_ERROR_RETURN 1477 (READ_RTAG7_HASH_TRUNKr(unit, trunk_idx, &rtag7_hash_trunk)); 1478 1479 /* Compute RTAG7 hash for trunking */ 1480 if(hash_Base->is_nonuc) { 1481 hash_sub_sel = 1482 soc_reg_field_get(unit, RTAG7_HASH_TRUNKr, 1483 rtag7_hash_trunk, SUB_SEL_NONUCf); 1484 hash_offset = 1485 soc_reg_field_get(unit, RTAG7_HASH_TRUNKr, 1486 rtag7_hash_trunk, OFFSET_NONUCf); 1487 offset_shift = 0xff; 1488 } else { 1489 hash_sub_sel = 1490 soc_reg_field_get(unit, RTAG7_HASH_TRUNKr, 1491 rtag7_hash_trunk, SUB_SEL_UCf); 1492 hash_offset = 1493 soc_reg_field_get(unit, RTAG7_HASH_TRUNKr, 1494 rtag7_hash_trunk, OFFSET_UCf); 1495 offset_shift = 0x3ff; 1496 } 1497 1498 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1499 (BSL_META_U(unit, 1500 "Trunk hash_seb_sel=%d, hash_offset=%d\n"), 1501 hash_sub_sel, hash_offset)); 1502 BCM_IF_ERROR_RETURN 1503 (select_hash_subfield(hash_sub_sel, &hash_subfield, hash_Base)); 1504 1505 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 1506 rtag7_hash_trunk_value = ((hash_subfield >> hash_offset) | (hash_subfield << (16 - hash_offset))) & offset_shift; 1507 1508 /* Compute the trunk_member_table index 1509 * trunk_index = trunk_hash % (trunk_group_size + 1); 1510 * Irsel2_rsel2__trunk_member_table_index = 1511 * (trunk_base_ptr + trunk_index) & 0x7ff; 1512 */ 1513 1514 *hash_value = rtag7_hash_trunk_value; 1515 1516 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1517 (BSL_META_U(unit, 1518 "Trunk hash_value=%d\n"), 1519 *hash_value)); 1520 1521 BCM_IF_ERROR_RETURN 1522 (READ_HASH_CONTROLr(unit, &hash_control)); 1523 nuc_trunk_hash_use_rtag7 = 1524 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 1525 NON_UC_TRUNK_HASH_USE_RTAG7f); 1526 1527 if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) { 1528 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1529 (BSL_META_U(unit, 1530 "NonUC trunk Hash calculation: non rtag7 calc not supported\n"))); 1531 *hash_value = 0; 1532 } 1533 1534 return BCM_E_NONE; 1535 } 1536 1537 STATIC int 1538 get_hash_trunk(int unit, int tgid, uint32 hash_index, bcm_gport_t *dst_gport) 1539 { 1540 uint32 trunk_base; 1541 uint32 trunk_group_size; 1542 uint32 rtag; 1543 uint32 trunk_index; 1544 uint32 trunk_member_table_index; 1545 bcm_module_t mod_id; 1546 bcm_port_t port_id; 1547 int mod_is_local; 1548 trunk_member_entry_t trunk_member_entry; 1549 trunk_group_entry_t tg_entry; 1550 _bcm_gport_dest_t dest; 1551 1552 BCM_IF_ERROR_RETURN 1553 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &tg_entry)); 1554 1555 trunk_base = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf); 1556 trunk_group_size = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 1557 TG_SIZEf); 1558 rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf); 1559 1560 if (rtag != 7){ 1561 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1562 (BSL_META_U(unit, 1563 "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"), 1564 rtag)); 1565 } 1566 1567 trunk_index = hash_index % (trunk_group_size + 1); 1568 trunk_member_table_index = (trunk_base + trunk_index) & 0x7ff; 1569 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1570 (BSL_META_U(unit, 1571 "\tTrunk HW index 0x%08x\n"), 1572 trunk_index)); 1573 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1574 (BSL_META_U(unit, 1575 "\tTrunk group size 0x%08x\n"), 1576 trunk_group_size)); 1577 1578 1579 BCM_IF_ERROR_RETURN 1580 (READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index, 1581 &trunk_member_entry)); 1582 1583 mod_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry, 1584 MODULE_IDf); 1585 port_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry, 1586 PORT_NUMf); 1587 1588 BCM_IF_ERROR_RETURN 1589 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id, 1590 &(dest.modid), &(dest.port))); 1591 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 1592 1593 BCM_IF_ERROR_RETURN 1594 (_bcm_esw_modid_is_local(unit, dest.modid, 1595 &mod_is_local)); 1596 if (mod_is_local) { 1597 if (IS_ST_PORT(unit, port_id)) { 1598 dest.modid = mod_id; 1599 dest.port = port_id; 1600 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 1601 } 1602 } 1603 1604 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport)); 1605 1606 return BCM_E_NONE; 1607 } 1608 1609 /* 1610 * Function: 1611 * get_hash_trunk_nuc 1612 * Description: 1613 * Compute non-unicast destination trunk member port 1614 * Parameters: 1615 * unit - StrataSwitch PCI device unit number (driver internal). 1616 * tgid - Trunk group id 1617 * fwd_reason - Flow foward reason. unicast, ipmc, l2mc, broadcast, dlf. 1618 * hash_index - Hash value calculated based on RTAG7 1619 * dst_gport - Where egress member port id is stored 1620 * 1621 * Returns: 1622 * BCM_E_xxxx 1623 */ 1624 STATIC int 1625 get_hash_trunk_nuc(int unit, int tgid, 1626 bcm_switch_pkt_hash_info_fwd_reason_t fwd_reason, 1627 uint32 hash_index, bcm_gport_t *dst_gport) 1628 { 1629 int nuc_type, nuc_tbm_index; 1630 int modid, port; 1631 bcm_pbmp_t local_pbmp, block_mask_pbmp; 1632 trunk_bitmap_entry_t trunk_bitmap_entry; 1633 nonucast_trunk_block_mask_entry_t mask_entry; 1634 uint32 disable_flags = BCM_TRUNK_MEMBER_EGRESS_DISABLE; 1635 1636 switch(fwd_reason) { 1637 case bcmSwitchPktHashInfoFwdReasonIpmc: 1638 nuc_type = TRUNK_BLOCK_MASK_TYPE_IPMC; 1639 disable_flags |= BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE; 1640 break; 1641 case bcmSwitchPktHashInfoFwdReasonL2mc: 1642 nuc_type = TRUNK_BLOCK_MASK_TYPE_L2MC; 1643 disable_flags |= BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE; 1644 break; 1645 case bcmSwitchPktHashInfoFwdReasonBcast: 1646 nuc_type = TRUNK_BLOCK_MASK_TYPE_BCAST; 1647 disable_flags |= BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE; 1648 break; 1649 case bcmSwitchPktHashInfoFwdReasonDlf: 1650 nuc_type = TRUNK_BLOCK_MASK_TYPE_DLF; 1651 disable_flags |= BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE; 1652 break; 1653 default: 1654 return BCM_E_PARAM; 1655 } 1656 nuc_tbm_index = (nuc_type << 8) | (hash_index & 0xff); 1657 1658 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1659 (BSL_META_U(unit, 1660 "Nonuc-trunk table index = %d\n"), 1661 nuc_tbm_index)); 1662 1663 BCM_IF_ERROR_RETURN( 1664 READ_NONUCAST_TRUNK_BLOCK_MASKm(unit, MEM_BLOCK_ANY, 1665 nuc_tbm_index, &mask_entry)); 1666 soc_mem_pbmp_field_get(unit, NONUCAST_TRUNK_BLOCK_MASKm, &mask_entry, 1667 BLOCK_MASKf, &block_mask_pbmp); 1668 BCM_IF_ERROR_RETURN( 1669 READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tgid, &trunk_bitmap_entry)); 1670 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 1671 TRUNK_BITMAPf, &local_pbmp); 1672 1673 BCM_PBMP_REMOVE(local_pbmp, block_mask_pbmp); 1674 1675 if (BCM_PBMP_IS_NULL(local_pbmp)) { 1676 /* this means that member is not on local device, try SW prediction */ 1677 bcm_trunk_member_t member_array[BCM_TRUNK_MAX_PORTCNT]; 1678 int member_count; 1679 bcm_gport_t *port_array = NULL; 1680 int port_count, port_index; 1681 int region_size, i, all_local; 1682 1683 BCM_IF_ERROR_RETURN 1684 (bcm_esw_trunk_get(unit, tgid, NULL, BCM_TRUNK_MAX_PORTCNT, 1685 member_array, &member_count)); 1686 1687 port_array = sal_alloc(member_count * sizeof(bcm_gport_t), 1688 "port_array"); 1689 if (port_array == NULL) { 1690 return BCM_E_MEMORY; 1691 } 1692 1693 port_count = 0; 1694 all_local = TRUE; 1695 for (i = 0; i < member_count; i++) { 1696 if (member_array[i].flags & disable_flags) { 1697 continue; 1698 } 1699 port = member_array[i].gport; 1700 port_array[port_count++] = port; 1701 if (all_local) { 1702 if (BCM_FAILURE(bcm_esw_port_local_get(unit, port, &port))) { 1703 all_local = FALSE; 1704 } 1705 } 1706 } 1707 /* All ports are disabled */ 1708 if (port_count == 0) { 1709 *dst_gport = -1; 1710 sal_free(port_array); 1711 return BCM_E_NOT_FOUND; 1712 } 1713 region_size = soc_mem_index_count(unit, NONUCAST_TRUNK_BLOCK_MASKm) / 4; 1714 if (all_local || port_count > BCM_SWITCH_TRUNK_MAX_PORTCNT) { 1715 port_index = (nuc_tbm_index % region_size) % port_count; 1716 } else { 1717 port_index = (nuc_tbm_index % BCM_XGS3_TRUNK_MAX_PORTCNT) % port_count; 1718 } 1719 1720 *dst_gport = port_array[port_index]; 1721 1722 sal_free(port_array); 1723 1724 } else { 1725 _bcm_gport_dest_t dest; 1726 1727 /*Each index only has one egress port */ 1728 BCM_PBMP_ITER(local_pbmp, port) { 1729 break; 1730 } 1731 1732 if (port == BCM_PBMP_PORT_MAX) { 1733 /* If not found in iteration, return not found. It never be here */ 1734 *dst_gport = -1; 1735 return BCM_E_NOT_FOUND; 1736 } 1737 1738 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 1739 1740 BCM_IF_ERROR_RETURN 1741 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 1742 &(dest.modid), &(dest.port))); 1743 if (IS_ST_PORT(unit, port)) { 1744 dest.modid = modid; 1745 dest.port = port; 1746 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 1747 } else { 1748 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 1749 } 1750 1751 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport)); 1752 } 1753 1754 return BCM_E_NONE; 1755 } 1756 1757 #ifdef INCLUDE_L3 1758 STATIC int 1759 get_hash_ecmp(int unit, int ecmp_group, uint32 hash_index, bcm_if_t *nh_id) 1760 { 1761 uint8 ecmp_hash_16bits; 1762 uint32 ecmp_hash_field_upper_bits_count; 1763 1764 ecmp_count_entry_t ecmpc_entry; 1765 ecmp_entry_t ecmp_entry; 1766 uint32 ecmp_ptr = 0; 1767 uint32 ecmp_count = 0; 1768 uint32 ing_config_2, hash_control; 1769 1770 uint32 ecmp_mask; 1771 uint32 ecmp_offset; 1772 uint32 ecmp_index; 1773 1774 /*register read*/ 1775 if (SOC_REG_IS_VALID(unit, ING_CONFIG_2r)) { 1776 SOC_IF_ERROR_RETURN 1777 (READ_ING_CONFIG_2r(unit, &ing_config_2)); 1778 ecmp_hash_16bits = 1779 soc_reg_field_get(unit, ING_CONFIG_2r, ing_config_2, 1780 ECMP_HASH_16BITSf); 1781 } else { 1782 ecmp_hash_16bits = 0; 1783 } 1784 1785 if (SOC_REG_FIELD_VALID(unit, HASH_CONTROLr, 1786 ECMP_HASH_FIELD_UPPER_BITS_COUNTf)) { 1787 SOC_IF_ERROR_RETURN 1788 (READ_HASH_CONTROLr(unit, &hash_control)); 1789 ecmp_hash_field_upper_bits_count = 1790 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 1791 ECMP_HASH_FIELD_UPPER_BITS_COUNTf); 1792 } else { 1793 ecmp_hash_field_upper_bits_count = 0x6; /* A0 bincomp value */ 1794 } 1795 1796 /* pick up the ecmp count and base_ptr */ 1797 /* Trident+ ECMP Mode where ECMP resolution is done in one step using a 16Mod10 */ 1798 BCM_IF_ERROR_RETURN 1799 (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry)); 1800 1801 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1802 * A ECMP_COUNT value of 0 implies 1 entry 1803 * a value of 1 implies 2 entries etc... 1804 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1805 */ 1806 /* ECMP Mask is expected to be set to 0x3ff for TridentA0/A1 mode */ 1807 if (ecmp_hash_16bits == 0) { 1808 /* Trident-A0/A1 ECMP mode - SDK restricts to 256 members or less */ 1809 ecmp_mask = 0x3ff; 1810 ecmp_count = 1811 soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 1812 COUNT_0f); 1813 ecmp_ptr = 1814 soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 1815 BASE_PTR_0f); 1816 } else { 1817 ecmp_ptr = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 1818 BASE_PTRf); 1819 ecmp_count = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 1820 COUNTf); 1821 switch (ecmp_hash_field_upper_bits_count) { 1822 case 0: 1823 ecmp_mask = 0x3ff; 1824 break; 1825 case 1: 1826 ecmp_mask = 0x7ff; 1827 break; 1828 case 2: 1829 ecmp_mask = 0xfff; 1830 break; 1831 case 3: 1832 ecmp_mask = 0x1fff; 1833 break; 1834 case 4: 1835 ecmp_mask = 0x3fff; 1836 break; 1837 case 5: 1838 ecmp_mask = 0x7fff; 1839 break; 1840 case 6: 1841 ecmp_mask = 0xffff; 1842 break; 1843 default: 1844 ecmp_mask = 0xffff; 1845 break; 1846 } 1847 } 1848 1849 ecmp_offset = ((hash_index & ecmp_mask) % (ecmp_count + 1)) & 0x3FF; 1850 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1851 (BSL_META_U(unit, 1852 "\tECMP offset 0x%08x\n"), 1853 ecmp_offset)); 1854 ecmp_index = (ecmp_ptr + ecmp_offset) & 0xfff; 1855 BCM_IF_ERROR_RETURN 1856 (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry)); 1857 1858 *nh_id = 1859 soc_L3_ECMPm_field32_get(unit, &ecmp_entry, 1860 NEXT_HOP_INDEXf) & 0x3fff; 1861 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1862 (BSL_META_U(unit, 1863 "\tECMP next hop HW index 0x%08x\n"), 1864 *nh_id)); 1865 1866 return BCM_E_NONE; 1867 } 1868 #endif /* INCLUDE_L3 */ 1869 1870 int 1871 _bcm_switch_pkt_info_ecmp_hash_get(int unit, 1872 bcm_switch_pkt_info_t *pkt_info, 1873 bcm_gport_t *dst_gport, 1874 bcm_if_t *dst_intf) 1875 { 1876 bcm_rtag7_base_hash_t hash_res; 1877 int pc_out; 1878 bcm_gport_t port; 1879 bcm_trunk_t tid; 1880 int id; 1881 uint32 hash_value; 1882 1883 if (pkt_info == NULL) { 1884 return BCM_E_PARAM; 1885 } 1886 1887 if (!_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_GPORT)) { 1888 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1889 (BSL_META_U(unit, 1890 "Hash calculation: source gport value missing\n"))); 1891 return BCM_E_PARAM; 1892 } 1893 1894 BCM_IF_ERROR_RETURN 1895 (_bcm_esw_gport_resolve(unit, pkt_info->src_gport, 1896 &(hash_res.src_modid), 1897 &(hash_res.src_port), 1898 &tid, &id)); 1899 if ((-1 != id) || (-1 != tid)) { 1900 /* Must be single system port */ 1901 return BCM_E_PORT; 1902 } 1903 1904 /* If dual module mode enable, mod/port should be in PORT32 format */ 1905 BCM_IF_ERROR_RETURN 1906 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 1907 hash_res.src_modid, hash_res.src_port, 1908 &hash_res.src_modid, &hash_res.src_port)); 1909 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1910 (BSL_META_U(unit, 1911 "src_gport=0x%x, src_modid = %d, src_port=%d\n"), 1912 pkt_info->src_gport, hash_res.src_modid, hash_res.src_port)); 1913 1914 /* Load balancing retrieval */ 1915 BCM_IF_ERROR_RETURN 1916 (bcm_esw_port_local_get(unit, pkt_info->src_gport, &port)); 1917 hash_res.dev_src_port = port; 1918 BCM_IF_ERROR_RETURN 1919 (bcm_esw_port_control_get(unit, port, 1920 bcmPortControlLoadBalancingNumber, 1921 &pc_out)); 1922 hash_res.rtag7_port_lbn = pc_out; 1923 1924 /* check if the foward reason of packet is all non-uc packet or bit 40 in the mac DA is one. */ 1925 hash_res.is_nonuc = pkt_info->fwd_reason || BCM_MAC_IS_MCAST(pkt_info->dst_mac); 1926 1927 BCM_IF_ERROR_RETURN 1928 (main__do_rtag7_hashing(unit, pkt_info, &hash_res)); 1929 BCM_IF_ERROR_RETURN 1930 (main__compute_lbid(unit, &hash_res)); 1931 1932 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1933 (BSL_META_U(unit, 1934 "Hash status: \n"))); 1935 if (hash_res.hash_a_valid) { 1936 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1937 (BSL_META_U(unit, 1938 "\tRTAG7 A0 0x%08x\n"), 1939 hash_res.rtag7_hash16_value_a_0)); 1940 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1941 (BSL_META_U(unit, 1942 "\tRTAG7 A1 0x%08x\n"), 1943 hash_res.rtag7_hash16_value_a_1)); 1944 } else { 1945 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1946 (BSL_META_U(unit, 1947 "\tRTAG7 A hashes invalid due to missing packet info\n"))); 1948 } 1949 if (hash_res.hash_b_valid) { 1950 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1951 (BSL_META_U(unit, 1952 "\tRTAG7 B0 0x%08x\n"), 1953 hash_res.rtag7_hash16_value_b_0)); 1954 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1955 (BSL_META_U(unit, 1956 "\tRTAG7 B1 0x%08x\n"), 1957 hash_res.rtag7_hash16_value_b_1)); 1958 } else { 1959 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1960 (BSL_META_U(unit, 1961 "\tRTAG7 B hashes invalid due to missing packet info\n"))); 1962 } 1963 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1964 (BSL_META_U(unit, 1965 "\tRTAG7 LBN 0x%08x\n"), 1966 hash_res.rtag7_port_lbn)); 1967 if (hash_res.lbid_hash_valid){ 1968 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1969 (BSL_META_U(unit, 1970 "\tRTAG7 LBID 0x%08x\n"), 1971 hash_res.rtag7_lbid_hash)); 1972 } else { 1973 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1974 (BSL_META_U(unit, 1975 "\tRTAG7 LBID not valid due to non-RTAG7 configuration\n"))); 1976 } 1977 1978 #ifdef INCLUDE_L3 1979 if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_MULTIPATH)) { 1980 bcm_if_t nh_id; 1981 1982 if (dst_intf == NULL) { 1983 return BCM_E_PARAM; 1984 } 1985 1986 BCM_IF_ERROR_RETURN 1987 (compute_ecmp_hash(unit, &hash_res, &hash_value)); 1988 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1989 (BSL_META_U(unit, 1990 "\tECMP Hash value 0x%08x\n"), 1991 hash_value)); 1992 1993 BCM_IF_ERROR_RETURN 1994 (get_hash_ecmp(unit, 1995 pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 1996 hash_value, &nh_id)); 1997 /* Convert to egress object format */ 1998 *dst_intf = nh_id + BCM_XGS3_EGRESS_IDX_MIN(unit); 1999 } else 2000 #endif /* INCLUDE_L3 */ 2001 if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_TRUNK)) { 2002 bcm_trunk_t trunk = BCM_TRUNK_INVALID; 2003 int member_count; 2004 bcm_trunk_chip_info_t ti; 2005 2006 if (dst_gport == NULL) { 2007 return BCM_E_PARAM; 2008 } 2009 2010 if (!BCM_GPORT_IS_TRUNK(pkt_info->trunk_gport)) { 2011 return BCM_E_PORT; 2012 } 2013 trunk = BCM_GPORT_TRUNK_GET(pkt_info->trunk_gport); 2014 BCM_IF_ERROR_RETURN 2015 (bcm_esw_trunk_get(unit, trunk, NULL, 0, NULL, &member_count)); 2016 if (0 == member_count) { 2017 /* Return failure for no trunk members */ 2018 return BCM_E_FAIL; 2019 } 2020 2021 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &ti)); 2022 2023 if (trunk >= ti.trunk_id_min && trunk <= ti.trunk_id_max) { 2024 BCM_IF_ERROR_RETURN 2025 (compute_rtag7_hash_trunk(unit, &hash_res, &hash_value)); 2026 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2027 (BSL_META_U(unit, 2028 "\tTrunk Hash value 0x%08x\n"), 2029 hash_value)); 2030 2031 if (hash_res.is_nonuc) { 2032 BCM_IF_ERROR_RETURN 2033 (get_hash_trunk_nuc(unit, trunk, pkt_info->fwd_reason, 2034 hash_value, dst_gport)); 2035 } else { 2036 BCM_IF_ERROR_RETURN 2037 (get_hash_trunk(unit, trunk, 2038 hash_value, dst_gport)); 2039 } 2040 } else { 2041 return BCM_E_UNAVAIL; 2042 } 2043 } else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_LBID) { 2044 /* LBID hashing resolution */ 2045 if (dst_intf == NULL || hash_res.lbid_hash_valid == 0) { 2046 return BCM_E_FAIL; 2047 } else { 2048 *dst_intf = hash_res.rtag7_lbid_hash; 2049 } 2050 } else { 2051 return BCM_E_PARAM; 2052 } 2053 2054 return BCM_E_NONE; 2055 }