hashing.c (103608B)
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: TR3-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 #define HASH_VALUE_64_COMPUTE(subfield,offset,width) do { \ 58 uint64 sf; \ 59 COMPILER_64_ZERO(sf); \ 60 COMPILER_64_ADD_64(sf, subfield); \ 61 COMPILER_64_SHR(subfield, offset); \ 62 COMPILER_64_SHL(sf, (width - offset)); \ 63 COMPILER_64_OR(subfield, sf); \ 64 } while(0) 65 66 #define HASH_VALUE_32_COMPUTE(hash_value_32, hash_value_64) do { \ 67 COMPILER_64_TO_32_LO(hash_value_32, hash_value_64); \ 68 } while(0) 69 70 71 /* 72 * Function: 73 * main_tr3_do_rtag7_hashing 74 * Description: 75 * read hash control register values and 76 * set hash_res' fields 77 * Parameters: 78 * unit - StrataSwitch PCI device unit number (driver internal). 79 * pkt_info - ptr to data that has packet information 80 * hash_res - internal data where hashing informaiton is stored 81 * Returns: 82 * BCM_E_xxxx 83 */ 84 STATIC int 85 main_tr3_do_rtag7_hashing(int unit, 86 bcm_switch_pkt_info_t *pkt_info, 87 bcm_rtag7_base_hash_t *hash_res) 88 { 89 /* regular var declaration */ 90 uint32 hash_src_port; 91 uint32 hash_src_modid; 92 uint32 rtag7_a_sel; 93 bcm_ip_t sip_a; /* Source IPv4 address. */ 94 bcm_ip_t dip_a; /* Destination IPv4 address. */ 95 uint32 rtag7_b_sel; 96 bcm_ip_t sip_b; /* Source IPv4 address. */ 97 bcm_ip_t dip_b; /* Destination IPv4 address. */ 98 uint32 hash_field_bmap_a; /* block A chosen bitmap*/ 99 uint32 hash_field_bmap_b; /* block B chosen bitmap*/ 100 101 uint32 hash_word[7]; 102 uint32 hash[13]; 103 int elem, elem_bit; 104 uint32 hash_element_valid_bits; 105 /* int ip6_addrs = FALSE, ip4_addrs = FALSE; */ 106 int sip_valid = FALSE, dip_valid = FALSE; 107 uint32 macro_flow_id; 108 109 uint32 hash_crc16_bisync; 110 uint32 hash_crc16_ccitt; 111 uint32 hash_crc32; 112 uint32 hash_xor16; 113 uint32 hash_xor8; 114 uint32 hash_xor4; 115 uint32 hash_xor2; 116 uint32 hash_xor1; 117 uint32 xor32; 118 119 /* register var declaration */ 120 uint8 rtag7_disable_hash_ipv4_a; 121 uint8 rtag7_disable_hash_ipv6_a; 122 uint8 rtag7_disable_hash_ipv4_b; 123 uint8 rtag7_disable_hash_ipv6_b; 124 uint8 rtag7_ipv6_addr_use_lsb_a; 125 uint8 rtag7_ipv6_addr_use_lsb_b; 126 uint8 rtag7_pre_processing_enable_a; 127 uint8 rtag7_pre_processing_enable_b; 128 uint8 rtag7_en_flow_label_ipv6_a; 129 uint8 rtag7_en_flow_label_ipv6_b; 130 uint8 rtag7_en_bin_12_overlay_a; 131 uint8 rtag7_en_bin_12_overlay_b; 132 uint32 rtag7_hash_seed_a; 133 uint32 rtag7_hash_seed_b; 134 uint32 rtag7_hash_a0_function_select; 135 uint32 rtag7_hash_a1_function_select; 136 uint32 rtag7_hash_b0_function_select; 137 uint32 rtag7_hash_b1_function_select; 138 uint32 rtag7_macro_flow_hash_function_select; 139 uint8 rtag7_macro_flow_hash_byte_sel; 140 141 uint64 rtag7_hash_control; 142 uint32 rtag7_hash_control_2, rtag7_hash_control_3; 143 uint32 rtag7_hash_seed_a_reg, rtag7_hash_seed_b_reg; 144 soc_reg_t sc_reg; 145 soc_field_t sc_field; 146 uint32 sc_val; 147 int symmetric_hash_control_mask = 0; 148 int symmetric_hash_need_swap_ip6 = 0; 149 int symmetric_hash_need_swap_ip4 = 0; 150 151 SOC_IF_ERROR_RETURN 152 (READ_RTAG7_HASH_CONTROLr(unit, &rtag7_hash_control)); 153 SOC_IF_ERROR_RETURN 154 (READ_RTAG7_HASH_CONTROL_2r(unit, &rtag7_hash_control_2)); 155 156 SOC_IF_ERROR_RETURN 157 (READ_RTAG7_HASH_CONTROL_3r(unit, &rtag7_hash_control_3)); 158 SOC_IF_ERROR_RETURN 159 (READ_RTAG7_HASH_SEED_Ar(unit, &rtag7_hash_seed_a_reg)); 160 SOC_IF_ERROR_RETURN 161 (READ_RTAG7_HASH_SEED_Br(unit, &rtag7_hash_seed_b_reg)); 162 163 /* RTAG7 hash registers */ 164 rtag7_disable_hash_ipv4_a = 165 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 166 DISABLE_HASH_IPV4_Af); 167 rtag7_disable_hash_ipv6_a = 168 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 169 DISABLE_HASH_IPV6_Af); 170 rtag7_disable_hash_ipv4_b = 171 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 172 DISABLE_HASH_IPV4_Bf); 173 rtag7_disable_hash_ipv6_b = 174 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 175 DISABLE_HASH_IPV6_Bf); 176 rtag7_ipv6_addr_use_lsb_a = 177 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 178 IPV6_COLLAPSED_ADDR_SELECT_Af); 179 rtag7_ipv6_addr_use_lsb_b = 180 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 181 IPV6_COLLAPSED_ADDR_SELECT_Bf); 182 183 rtag7_pre_processing_enable_a = 184 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 185 HASH_PRE_PROCESSING_ENABLE_Af); 186 rtag7_pre_processing_enable_b = 187 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 188 HASH_PRE_PROCESSING_ENABLE_Bf); 189 rtag7_hash_a0_function_select = 190 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 191 HASH_A0_FUNCTION_SELECTf); 192 rtag7_hash_a1_function_select = 193 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 194 HASH_A1_FUNCTION_SELECTf); 195 rtag7_hash_b0_function_select = 196 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 197 HASH_B0_FUNCTION_SELECTf); 198 rtag7_hash_b1_function_select = 199 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 200 HASH_B1_FUNCTION_SELECTf); 201 202 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 203 ENABLE_FLOW_LABEL_IPV6_Af)) { 204 rtag7_en_flow_label_ipv6_a = 205 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 206 rtag7_hash_control_2, 207 ENABLE_FLOW_LABEL_IPV6_Af); 208 } else { 209 rtag7_en_flow_label_ipv6_a = 0; /* A0 bincomp value */ 210 } 211 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 212 ENABLE_FLOW_LABEL_IPV6_Bf)) { 213 rtag7_en_flow_label_ipv6_b = 214 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 215 rtag7_hash_control_2, 216 ENABLE_FLOW_LABEL_IPV6_Bf); 217 } else { 218 rtag7_en_flow_label_ipv6_b = 0; /* A0 bincomp value */ 219 } 220 rtag7_en_bin_12_overlay_a = 221 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2, 222 ENABLE_BIN_12_OVERLAY_Af); 223 rtag7_en_bin_12_overlay_b = 224 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, rtag7_hash_control_2, 225 ENABLE_BIN_12_OVERLAY_Bf); 226 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 227 MACRO_FLOW_HASH_FUNC_SELf)) { 228 rtag7_macro_flow_hash_function_select = 229 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 230 rtag7_hash_control_2, 231 MACRO_FLOW_HASH_FUNC_SELf); 232 } else { 233 rtag7_macro_flow_hash_function_select = 0; /* A0 bincomp value */ 234 } 235 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 236 MACRO_FLOW_HASH_BYTE_SELf)) { 237 rtag7_macro_flow_hash_byte_sel = 238 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 239 rtag7_hash_control_2, 240 MACRO_FLOW_HASH_BYTE_SELf); 241 } else { 242 rtag7_macro_flow_hash_byte_sel = 0; /* A0 bincomp value */ 243 } 244 245 rtag7_hash_seed_a = 246 soc_reg_field_get(unit, RTAG7_HASH_SEED_Ar, rtag7_hash_seed_a_reg, 247 HASH_SEED_Af); 248 rtag7_hash_seed_b = 249 soc_reg_field_get(unit, RTAG7_HASH_SEED_Br, rtag7_hash_seed_b_reg, 250 HASH_SEED_Bf); 251 252 #if defined(BCM_TRIUMPH3_SUPPORT) 253 if (BCM_SUCCESS(bcm_esw_switch_control_get(unit, 254 bcmSwitchSymmetricHashControl, &symmetric_hash_control_mask))) { 255 if (symmetric_hash_control_mask & 256 (BCM_SYMMETRIC_HASH_0_IP6_ENABLE | BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) { 257 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6) && 258 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6) && 259 (sal_memcmp(pkt_info->sip6, pkt_info->dip6, BCM_IP6_ADDRLEN) < 0)) { 260 symmetric_hash_need_swap_ip6 = 1; 261 } 262 } 263 if (symmetric_hash_control_mask & 264 (BCM_SYMMETRIC_HASH_0_IP4_ENABLE | BCM_SYMMETRIC_HASH_1_IP4_ENABLE)) { 265 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP) && 266 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP) && 267 (pkt_info->sip < pkt_info->dip)) { 268 symmetric_hash_need_swap_ip4 = 1; 269 } 270 } 271 } 272 #endif /* BCM_TRIUMPH3_SUPPORT */ 273 274 /* RTAG7 tables */ 275 /* the first step is to choose the paket type and to fold the ipv6 276 * addresses in case of IPv6 packet*/ 277 278 /* option A ip folding for rtag 7 */ 279 if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 280 (pkt_info->ethertype == ETHERTYPE_IPV6)) && 281 (rtag7_disable_hash_ipv6_a == 0)) { 282 283 /* ip6_addrs = TRUE; */ 284 rtag7_a_sel = RTAG7_IPV6; 285 286 /* This section will fold the Ipv6 address to single 32 bit address 287 * by using of of the methose LSB or xor */ 288 if (rtag7_ipv6_addr_use_lsb_a) { 289 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 290 sip_a = (pkt_info->sip6[12] << 24) | 291 (pkt_info->sip6[13] << 16) | 292 (pkt_info->sip6[14] << 8) | 293 (pkt_info->sip6[15]); 294 sip_valid = TRUE; 295 } else { 296 sip_a = 0; 297 } 298 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 299 dip_a = (pkt_info->dip6[12] << 24) | 300 (pkt_info->dip6[13] << 16) | 301 (pkt_info->dip6[14] << 8) | 302 (pkt_info->dip6[15]); 303 dip_valid = TRUE; 304 } else { 305 dip_a = 0; 306 } 307 } else { 308 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 309 sip_a = 310 ((pkt_info->sip6[12] << 24) | 311 (pkt_info->sip6[13] << 16) | 312 (pkt_info->sip6[14] << 8) | 313 (pkt_info->sip6[15])) ^ 314 ((pkt_info->sip6[8] << 24) | 315 (pkt_info->sip6[9] << 16) | 316 (pkt_info->sip6[10] << 8) | 317 (pkt_info->sip6[11])) ^ 318 ((pkt_info->sip6[4] << 24) | 319 (pkt_info->sip6[5] << 16) | 320 (pkt_info->sip6[6] << 8) | 321 (pkt_info->sip6[7])) ^ 322 ((pkt_info->sip6[0] << 24) | 323 (pkt_info->sip6[1] << 16) | 324 (pkt_info->sip6[2] << 8) | 325 (pkt_info->sip6[3])); 326 sip_valid = TRUE; 327 } else { 328 sip_a = 0; 329 } 330 331 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 332 dip_a = 333 ((pkt_info->dip6[12] << 24) | 334 (pkt_info->dip6[13] << 16) | 335 (pkt_info->dip6[14] << 8) | 336 (pkt_info->dip6[15])) ^ 337 ((pkt_info->dip6[8] << 24) | 338 (pkt_info->dip6[9] << 16) | 339 (pkt_info->dip6[10] << 8) | 340 (pkt_info->dip6[11])) ^ 341 ((pkt_info->dip6[4] << 24) | 342 (pkt_info->dip6[5] << 16) | 343 (pkt_info->dip6[6] << 8) | 344 (pkt_info->dip6[7])) ^ 345 ((pkt_info->dip6[0] << 24) | 346 (pkt_info->dip6[1] << 16) | 347 (pkt_info->dip6[2] << 8) | 348 (pkt_info->dip6[3])); 349 dip_valid = TRUE; 350 } else { 351 dip_a = 0; 352 } 353 } 354 } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 355 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 356 (rtag7_disable_hash_ipv4_a == 0)) { 357 358 /* ip4_addrs = TRUE; */ 359 rtag7_a_sel = RTAG7_IPV4; 360 361 /* only one IPv4 hdr */ 362 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) { 363 sip_a = pkt_info->sip; 364 sip_valid = TRUE; 365 } else { 366 sip_a = 0; 367 } 368 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) { 369 dip_a = pkt_info->dip; 370 dip_valid = TRUE; 371 } else { 372 dip_a = 0; 373 } 374 } else { 375 rtag7_a_sel = RTAG7_L2_ONLY; 376 sip_a = dip_a = 0; 377 } 378 379 /* End of option A ip folding for rtag 7 */ 380 381 /* option B ip folding for rtag 7 */ 382 if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 383 (pkt_info->ethertype == ETHERTYPE_IPV6)) && 384 (rtag7_disable_hash_ipv6_b == 0)) { 385 386 /* ip6_addrs = TRUE; */ 387 rtag7_b_sel = RTAG7_IPV6; 388 389 /* This section will fold the Ipv6 address to single 32 bit address 390 * by using of of the methose LSB or xor */ 391 if (rtag7_ipv6_addr_use_lsb_b) { 392 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 393 sip_b = (pkt_info->sip6[12] << 24) | 394 (pkt_info->sip6[13] << 16) | 395 (pkt_info->sip6[14] << 8) | 396 (pkt_info->sip6[15]); 397 sip_valid = TRUE; 398 } else { 399 sip_b = 0; 400 } 401 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 402 dip_b = (pkt_info->dip6[12] << 24) | 403 (pkt_info->dip6[13] << 16) | 404 (pkt_info->dip6[14] << 8) | 405 (pkt_info->dip6[15]); 406 dip_valid = TRUE; 407 } else { 408 dip_b = 0; 409 } 410 } else { 411 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 412 sip_b = 413 ((pkt_info->sip6[12] << 24) | 414 (pkt_info->sip6[13] << 16) | 415 (pkt_info->sip6[14] << 8) | 416 (pkt_info->sip6[15])) ^ 417 ((pkt_info->sip6[8] << 24) | 418 (pkt_info->sip6[9] << 16) | 419 (pkt_info->sip6[10] << 8) | 420 (pkt_info->sip6[11])) ^ 421 ((pkt_info->sip6[4] << 24) | 422 (pkt_info->sip6[5] << 16) | 423 (pkt_info->sip6[6] << 8) | 424 (pkt_info->sip6[7])) ^ 425 ((pkt_info->sip6[0] << 24) | 426 (pkt_info->sip6[1] << 16) | 427 (pkt_info->sip6[2] << 8) | 428 (pkt_info->sip6[3])); 429 sip_valid = TRUE; 430 } else { 431 sip_b = 0; 432 } 433 434 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 435 dip_b = 436 ((pkt_info->dip6[12] << 24) | 437 (pkt_info->dip6[13] << 16) | 438 (pkt_info->dip6[14] << 8) | 439 (pkt_info->dip6[15])) ^ 440 ((pkt_info->dip6[8] << 24) | 441 (pkt_info->dip6[9] << 16) | 442 (pkt_info->dip6[10] << 8) | 443 (pkt_info->dip6[11])) ^ 444 ((pkt_info->dip6[4] << 24) | 445 (pkt_info->dip6[5] << 16) | 446 (pkt_info->dip6[6] << 8) | 447 (pkt_info->dip6[7])) ^ 448 ((pkt_info->dip6[0] << 24) | 449 (pkt_info->dip6[1] << 16) | 450 (pkt_info->dip6[2] << 8) | 451 (pkt_info->dip6[3])); 452 dip_valid = TRUE; 453 } else { 454 dip_b = 0; 455 } 456 } 457 } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 458 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 459 (rtag7_disable_hash_ipv4_b == 0)) { 460 461 /* ip4_addrs = TRUE; */ 462 rtag7_b_sel = RTAG7_IPV4; 463 464 /* only one IPv4 hdr */ 465 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) { 466 sip_b = pkt_info->sip; 467 sip_valid = TRUE; 468 } else { 469 sip_b = 0; 470 } 471 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) { 472 dip_b = pkt_info->dip; 473 dip_valid = TRUE; 474 } else { 475 dip_b = 0; 476 } 477 } else { 478 rtag7_b_sel = RTAG7_L2_ONLY; 479 sip_b = dip_b = 0; 480 } 481 /* End of option B ip folding for rtag 7 */ 482 483 484 485 /* 486 * ============= 487 * RTAG7 HASHING 488 * ============= 489 */ 490 491 /* The inputs to the RTAG7 hash function were reduced in the begining 492 * of this function. 493 * This logic takes the hash inputs and computes both A and B RTAG7 494 * hash values. 495 */ 496 497 /* Change source modid/port to PORT32 space for hashing */ 498 hash_src_port = hash_res->src_port; 499 hash_src_modid = hash_res->src_modid; 500 501 /* Only if the packet was sourced by this chip, make sure to use 502 * PORT32 space modid and port if dual modid is enabled 503 * Need to do this because of front panel ports. 504 * 505 * Already handled by API gport resolve */ 506 507 /* initialize the variables */ 508 sal_memset(hash,0x0,(sizeof(uint32))*13); 509 sal_memset(hash_word,0x0,(sizeof(uint32))*7); 510 511 hash_crc16_bisync = 0; 512 hash_crc16_ccitt = 0; 513 hash_crc32 = 0; 514 hash_xor16 = 0; 515 hash_xor8 = 0; 516 hash_xor4 = 0; 517 hash_xor2 = 0; 518 hash_xor1 = 0; 519 xor32 = 0; 520 521 hash[12] = 0; 522 hash[3] = hash_src_port; 523 hash[2] = hash_src_modid & 0xff; 524 hash[1] = 0; 525 hash[0] = 0; 526 527 hash_element_valid_bits = 0x1fff; /* Init to valid fields above */ 528 529 /* option A hash calculation for rtag 7 */ 530 531 if ((rtag7_a_sel == RTAG7_IPV6) || (rtag7_a_sel == RTAG7_IPV4)) { 532 533 if (sip_valid) { 534 hash[11] = (sip_a >> 16) & 0xffff; 535 hash[10] = sip_a & 0xffff; 536 } else { 537 hash_element_valid_bits &= ~0xc00; 538 } 539 if (dip_valid) { 540 hash[9] = (dip_a >> 16) & 0xffff; 541 hash[8] = dip_a & 0xffff; 542 } else { 543 hash_element_valid_bits &= ~0x300; 544 } 545 546 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 547 hash[7] = pkt_info->vid & 0xfff; 548 } else { 549 hash_element_valid_bits &= ~0x80; 550 } 551 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) { 552 hash[6] = pkt_info->src_l4_port; 553 } else { 554 hash_element_valid_bits &= ~0x40; 555 } 556 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) { 557 hash[5] = pkt_info->dst_l4_port; 558 } else { 559 hash_element_valid_bits &= ~0x20; 560 } 561 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) { 562 hash[4] = pkt_info->protocol; 563 } else { 564 hash_element_valid_bits &= ~0x10; 565 } 566 567 /* Symmetric hash swap src/dst ipaddr/l4_port for option A */ 568 if (((rtag7_a_sel == RTAG7_IPV6) && 569 symmetric_hash_need_swap_ip6 && 570 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP6_ENABLE)) 571 || 572 ((rtag7_a_sel == RTAG7_IPV4) && 573 symmetric_hash_need_swap_ip4 && 574 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP4_ENABLE))) { 575 576 uint32 temp; 577 temp = hash[11]; hash[11] = hash[9]; hash[9] = temp; 578 temp = hash[10]; hash[10] = hash[8]; hash[8] = temp; 579 temp = hash[6]; hash[6] = hash[5]; hash[5] = temp; 580 LOG_VERBOSE(BSL_LS_BCM_COMMON, 581 (BSL_META_U(unit, 582 "Symmetric hash swap for hash A calculation.\n"))); 583 } 584 585 if ((rtag7_a_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_a) { 586 LOG_VERBOSE(BSL_LS_BCM_COMMON, 587 (BSL_META_U(unit, 588 "Hash calculation: The system is set to use ipv6 flow label" 589 " and the code can't get this info\n"))); 590 } 591 592 if (rtag7_a_sel == RTAG7_IPV4) { /* Use IPv4 BITMAPs */ 593 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 594 ((pkt_info->protocol == IP_PROT_TCP) || 595 (pkt_info->protocol == IP_PROT_UDP))) { 596 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 597 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 598 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 599 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r; 600 sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af; 601 LOG_VERBOSE(BSL_LS_BCM_COMMON, 602 (BSL_META_U(unit, 603 "Hash calculation: Bitmap is block A IPv4 TCP=UDP\n"))); 604 } else { 605 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r; 606 sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Af; 607 LOG_VERBOSE(BSL_LS_BCM_COMMON, 608 (BSL_META_U(unit, 609 "Hash calculation: Bitmap is block A IPv4 L4 tcp/udp\n"))); 610 } 611 } else { 612 sc_reg = RTAG7_HASH_FIELD_BMAP_1r; 613 sc_field = IPV4_FIELD_BITMAP_Af; 614 LOG_VERBOSE(BSL_LS_BCM_COMMON, 615 (BSL_META_U(unit, 616 "Hash calculation: Bitmap is block A IPv4 \n"))); 617 } 618 619 } else { /* Use IPv6 BITMAPs */ 620 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 621 ((pkt_info->protocol == IP_PROT_TCP) || 622 (pkt_info->protocol == IP_PROT_UDP))) { 623 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 624 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 625 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 626 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r; 627 sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af; 628 LOG_VERBOSE(BSL_LS_BCM_COMMON, 629 (BSL_META_U(unit, 630 "Hash calculation: Bitmap is block A IPv6 TCP=UDP\n"))); 631 } else { 632 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r; 633 sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Af; 634 LOG_VERBOSE(BSL_LS_BCM_COMMON, 635 (BSL_META_U(unit, 636 "Hash calculation: Bitmap is block A IPv6 L4 tcp/udp\n"))); 637 } 638 } else { 639 sc_reg = RTAG7_HASH_FIELD_BMAP_2r; 640 sc_field = IPV6_FIELD_BITMAP_Af; 641 LOG_VERBOSE(BSL_LS_BCM_COMMON, 642 (BSL_META_U(unit, 643 "Hash calculation: Bitmap is block A IPv6 \n"))); 644 } 645 } 646 647 } else { /* Catch-all for RTAG7_L2_ONLY */ 648 649 /* L2 only hash key */ 650 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) { 651 hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1]; 652 hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3]; 653 hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5]; 654 } else { 655 hash_element_valid_bits &= ~0xe00; 656 } 657 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) { 658 hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1]; 659 hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3]; 660 hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5]; 661 } else { 662 hash_element_valid_bits &= ~0x1c0; 663 } 664 665 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) { 666 hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ? 667 pkt_info->ethertype : 0; 668 } else { 669 hash_element_valid_bits &= ~0x20; 670 } 671 672 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 673 hash[4] = pkt_info->vid & 0xfff; 674 } else { 675 hash_element_valid_bits &= ~0x10; 676 } 677 678 sc_reg = RTAG7_HASH_FIELD_BMAP_3r; 679 sc_field = L2_FIELD_BITMAP_Af; 680 LOG_VERBOSE(BSL_LS_BCM_COMMON, 681 (BSL_META_U(unit, 682 "Hash calculation: Bitmap is block A L2\n"))); 683 } 684 685 BCM_IF_ERROR_RETURN 686 (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val)); 687 hash_field_bmap_a = soc_reg_field_get(unit, sc_reg, sc_val, sc_field); 688 689 /* Pre-Processing */ 690 691 if (rtag7_pre_processing_enable_a) { 692 693 hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2); 694 hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2); 695 hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2); 696 hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2); 697 hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2); 698 hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2); 699 hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2); 700 hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2); 701 hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2); 702 hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2); 703 hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2); 704 hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2); 705 hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2); 706 707 } 708 709 if (((hash_field_bmap_a >> 12) & 0x1) == 0) { 710 hash[12] = 0; 711 } 712 713 if (rtag7_en_bin_12_overlay_a) { 714 hash_word[6] = (rtag7_hash_seed_a & 0xffff0000) | (hash[12] & 0xffff); 715 } else { 716 hash_word[6] = rtag7_hash_seed_a; 717 } 718 719 hash_res->hash_a_valid = TRUE; 720 for (elem = 11; elem >= 0; elem--) { 721 elem_bit = 1 << elem; 722 if (0 != (hash_field_bmap_a & elem_bit)) { 723 if (0 != (hash_element_valid_bits & elem_bit)) { 724 hash_word[elem/2] |= 725 ((hash[elem] & 0xffff) << (16 * (elem % 2))); 726 } else { 727 hash_res->hash_a_valid = FALSE; 728 break; 729 } 730 } 731 } 732 733 /*Calculation*/ 734 xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ 735 hash_word[2] ^ hash_word[1] ^ hash_word[0]; 736 737 hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff); 738 hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff); 739 hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf); 740 hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3); 741 hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1); 742 743 hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28); 744 hash_crc16_ccitt = _shr_crc16_ccitt_array(hash_word, 28); 745 hash_crc32 = _shr_crc32_castagnoli_array(hash_word, 28); 746 747 switch (rtag7_hash_a0_function_select) { 748 case 0: /* reserved */ 749 hash_res->rtag7_hash16_value_a_0 = 0; 750 break; 751 case 1: /* reserved */ 752 hash_res->rtag7_hash16_value_a_0 = 0; 753 break; 754 case 2: /* reserved */ 755 hash_res->rtag7_hash16_value_a_0 = 0; 756 break; 757 case 3: /* CRC16 BISYNC */ 758 hash_res->rtag7_hash16_value_a_0 = hash_crc16_bisync; 759 break; 760 case 4: /* CRC16_XOR1 */ 761 hash_res->rtag7_hash16_value_a_0 = hash_xor1 & 0x1; 762 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 763 break; 764 case 5: /* CRC16_XOR2 */ 765 hash_res->rtag7_hash16_value_a_0 = hash_xor2 & 0x3; 766 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 767 break; 768 case 6: /* CRC16_XOR4 */ 769 hash_res->rtag7_hash16_value_a_0 = hash_xor4 & 0xf; 770 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 771 break; 772 case 7: /* CRC16_XOR8 */ 773 hash_res->rtag7_hash16_value_a_0 = hash_xor8 & 0xff; 774 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 775 break; 776 case 8: /* XOR16 */ 777 hash_res->rtag7_hash16_value_a_0 = hash_xor16; 778 break; 779 case 9: /* CRC16_CCITT */ 780 hash_res->rtag7_hash16_value_a_0 = hash_crc16_ccitt; 781 break; 782 case 10: /* CRC32_LO */ 783 hash_res->rtag7_hash16_value_a_0 = hash_crc32 & 0xffff; 784 break; 785 case 11: /* CRC32_HI */ 786 hash_res->rtag7_hash16_value_a_0 = (hash_crc32 >> 16) & 0xffff; 787 break; 788 default: /* reserved */ 789 hash_res->rtag7_hash16_value_a_0 = 0; 790 break; 791 } 792 793 switch (rtag7_hash_a1_function_select) { 794 case 0: /* reserved */ 795 hash_res->rtag7_hash16_value_a_1 = 0; 796 break; 797 case 1: /* reserved */ 798 hash_res->rtag7_hash16_value_a_1 = 0; 799 break; 800 case 2: /* reserved */ 801 hash_res->rtag7_hash16_value_a_1 = 0; 802 break; 803 case 3: /* CRC16 BISYNC */ 804 hash_res->rtag7_hash16_value_a_1 = hash_crc16_bisync; 805 break; 806 case 4: /* CRC16_XOR1 */ 807 hash_res->rtag7_hash16_value_a_1 = hash_xor1 & 0x1; 808 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 809 break; 810 case 5: /* CRC16_XOR2 */ 811 hash_res->rtag7_hash16_value_a_1 = hash_xor2 & 0x3; 812 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 813 break; 814 case 6: /* CRC16_XOR4 */ 815 hash_res->rtag7_hash16_value_a_1 = hash_xor4 & 0xf; 816 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 817 break; 818 case 7: /* CRC16_XOR8 */ 819 hash_res->rtag7_hash16_value_a_1 = hash_xor8 & 0xff; 820 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 821 break; 822 case 8: /* XOR16 */ 823 hash_res->rtag7_hash16_value_a_1 = hash_xor16; 824 break; 825 case 9: /* CRC16_CCITT */ 826 hash_res->rtag7_hash16_value_a_1 = hash_crc16_ccitt; 827 break; 828 case 10: /* CRC32_LO */ 829 hash_res->rtag7_hash16_value_a_1 = hash_crc32 & 0xffff; 830 break; 831 case 11: /* CRC32_HI */ 832 hash_res->rtag7_hash16_value_a_1 = (hash_crc32 >> 16) & 0xffff; 833 break; 834 default: /* reserved */ 835 hash_res->rtag7_hash16_value_a_1 = 0; 836 break; 837 } 838 839 /* End of option A hash calculation for rtag 7 */ 840 841 /* Generation of Macro Flow Based HASH Select */ 842 /* This is used for Macro flow based Hash function selection for all consumers of RTAG7 HASH */ 843 /* Macro flow based hash function selection improves distribution among members */ 844 /* Refer Each application (ECMP, LAG, HG-TRUNK) on how this is being used */ 845 switch (rtag7_macro_flow_hash_function_select) { 846 case 0: /* reserved */ 847 macro_flow_id = 0; 848 break; 849 case 1: /* reserved */ 850 macro_flow_id = 0; 851 break; 852 case 2: /* reserved */ 853 macro_flow_id = 0; 854 break; 855 case 3: /* CRC16 BISYNC */ 856 macro_flow_id = hash_crc16_bisync; 857 break; 858 case 4: /* CRC16_XOR1 */ 859 macro_flow_id = hash_xor1 & 0x1; 860 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 861 break; 862 case 5: /* CRC16_XOR2 */ 863 macro_flow_id = hash_xor2 & 0x3; 864 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 865 break; 866 case 6: /* CRC16_XOR4 */ 867 macro_flow_id = hash_xor4 & 0xf; 868 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 869 break; 870 case 7: /* CRC16_XOR8 */ 871 macro_flow_id = hash_xor8 & 0xff; 872 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 873 break; 874 case 8: /* XOR16 */ 875 macro_flow_id = hash_xor16; 876 break; 877 case 9: /* CRC16_CCITT */ 878 macro_flow_id = hash_crc16_ccitt; 879 break; 880 case 10: /* CRC32_LO */ 881 macro_flow_id = hash_crc32 & 0xffff; 882 break; 883 case 11: /* CRC32_HI */ 884 macro_flow_id = (hash_crc32 >> 16) & 0xffff; 885 break; 886 default: /* reserved */ 887 macro_flow_id = 0; 888 break; 889 } 890 hash_res->rtag7_macro_flow_id = (rtag7_macro_flow_hash_byte_sel) ? 891 ((macro_flow_id >> 8) & 0xff) : (macro_flow_id & 0xff); 892 893 /* option B hash calculation for rtag 7 */ 894 895 /* initialize the variables */ 896 897 sal_memset(hash,0x0,(sizeof(uint32))*13); 898 sal_memset(hash_word,0x0,(sizeof(uint32))*7); 899 900 hash_crc16_bisync = 0; 901 hash_crc16_ccitt = 0; 902 hash_crc32 = 0; 903 hash_xor16 = 0; 904 hash_xor8 = 0; 905 hash_xor4 = 0; 906 hash_xor2 = 0; 907 hash_xor1 = 0; 908 xor32 = 0; 909 910 hash[12] = 0; 911 hash[3] = hash_src_port; 912 hash[2] = hash_src_modid & 0xff; 913 hash[1] = 0; 914 hash[0] = 0; 915 916 hash_element_valid_bits = 0x1fff; /* Init to valid fields above */ 917 918 /* option B hash calculation for rtag 7 */ 919 920 if ((rtag7_b_sel == RTAG7_IPV6) || (rtag7_b_sel == RTAG7_IPV4)) { 921 if (sip_valid) { 922 hash[11] = (sip_b >> 16) & 0xffff; 923 hash[10] = sip_b & 0xffff; 924 } else { 925 hash_element_valid_bits &= ~0xc00; 926 } 927 if (dip_valid) { 928 hash[9] = (dip_b >> 16) & 0xffff; 929 hash[8] = dip_b & 0xffff; 930 } else { 931 hash_element_valid_bits &= ~0x300; 932 } 933 934 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 935 hash[7] = pkt_info->vid & 0xfff; 936 } else { 937 hash_element_valid_bits &= ~0x80; 938 } 939 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) { 940 hash[6] = pkt_info->src_l4_port; 941 } else { 942 hash_element_valid_bits &= ~0x40; 943 } 944 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) { 945 hash[5] = pkt_info->dst_l4_port; 946 } else { 947 hash_element_valid_bits &= ~0x20; 948 } 949 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) { 950 hash[4] = pkt_info->protocol; 951 } else { 952 hash_element_valid_bits &= ~0x10; 953 } 954 955 /* Symmetric hash swap src/dst ipaddr/l4_port for option B */ 956 if (((rtag7_b_sel == RTAG7_IPV6) && 957 symmetric_hash_need_swap_ip6 && 958 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) 959 || 960 ((rtag7_b_sel == RTAG7_IPV4) && 961 symmetric_hash_need_swap_ip4 && 962 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP4_ENABLE))) { 963 964 uint32 temp; 965 temp = hash[11]; hash[11] = hash[9]; hash[9] = temp; 966 temp = hash[10]; hash[10] = hash[8]; hash[8] = temp; 967 temp = hash[6]; hash[6] = hash[5]; hash[5] = temp; 968 LOG_VERBOSE(BSL_LS_BCM_COMMON, 969 (BSL_META_U(unit, 970 "Symmetric hash swap for hash B calculation.\n"))); 971 } 972 973 if ((rtag7_b_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_b) { 974 LOG_VERBOSE(BSL_LS_BCM_COMMON, 975 (BSL_META_U(unit, 976 "Hash calculation: The system is set to use ipv6 flow label" 977 " and the code can't get this info\n"))); 978 } 979 980 if (rtag7_b_sel == RTAG7_IPV4) { /* Use IPv4 BITMAPs */ 981 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 982 ((pkt_info->protocol == IP_PROT_TCP) || 983 (pkt_info->protocol == IP_PROT_UDP))) { 984 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 985 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 986 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 987 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r; 988 sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf; 989 LOG_VERBOSE(BSL_LS_BCM_COMMON, 990 (BSL_META_U(unit, 991 "Hash calculation: Bitmap is block B IPv4 TCP=UDP\n"))); 992 } else { 993 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r; 994 sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Bf; 995 LOG_VERBOSE(BSL_LS_BCM_COMMON, 996 (BSL_META_U(unit, 997 "Hash calculation: Bitmap is block B IPv4 L4 tcp/udp\n"))); 998 } 999 } else { 1000 sc_reg = RTAG7_HASH_FIELD_BMAP_1r; 1001 sc_field = IPV4_FIELD_BITMAP_Bf; 1002 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1003 (BSL_META_U(unit, 1004 "Hash calculation: Bitmap is block B IPv4\n"))); 1005 } 1006 1007 } else { /* Use IPv6 BITMAPs */ 1008 1009 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 1010 ((pkt_info->protocol == IP_PROT_TCP) || 1011 (pkt_info->protocol == IP_PROT_UDP))) { 1012 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 1013 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 1014 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 1015 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r; 1016 sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf; 1017 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1018 (BSL_META_U(unit, 1019 "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n"))); 1020 } else { 1021 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r; 1022 sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Bf; 1023 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1024 (BSL_META_U(unit, 1025 "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n"))); 1026 } 1027 } else { 1028 sc_reg = RTAG7_HASH_FIELD_BMAP_2r; 1029 sc_field = IPV6_FIELD_BITMAP_Bf; 1030 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1031 (BSL_META_U(unit, 1032 "Hash calculation: Bitmap is block B IPv6\n"))); 1033 } 1034 } 1035 } else { /* Catch-all for RTAG7_L2_ONLY */ 1036 1037 /* L2 only hash key */ 1038 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) { 1039 hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1]; 1040 hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3]; 1041 hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5]; 1042 } else { 1043 hash_element_valid_bits &= ~0xe00; 1044 } 1045 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) { 1046 hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1]; 1047 hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3]; 1048 hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5]; 1049 } else { 1050 hash_element_valid_bits &= ~0x1c0; 1051 } 1052 1053 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) { 1054 hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ? 1055 pkt_info->ethertype : 0; 1056 } else { 1057 hash_element_valid_bits &= ~0x20; 1058 } 1059 1060 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 1061 hash[4] = pkt_info->vid & 0xfff; 1062 } else { 1063 hash_element_valid_bits &= ~0x10; 1064 } 1065 1066 sc_reg = RTAG7_HASH_FIELD_BMAP_3r; 1067 sc_field = L2_FIELD_BITMAP_Bf; 1068 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1069 (BSL_META_U(unit, 1070 "Hash calculation: Bitmap is block B L2\n"))); 1071 } 1072 1073 BCM_IF_ERROR_RETURN 1074 (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val)); 1075 hash_field_bmap_b = soc_reg_field_get(unit, sc_reg, sc_val, sc_field); 1076 /* Pre-Processing */ 1077 1078 if (rtag7_pre_processing_enable_b) { 1079 1080 hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2); 1081 hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2); 1082 hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2); 1083 hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2); 1084 hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2); 1085 hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2); 1086 hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2); 1087 hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2); 1088 hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2); 1089 hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2); 1090 hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2); 1091 hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2); 1092 hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2); 1093 1094 } 1095 1096 if (((hash_field_bmap_b >> 12) & 0x1) == 0) { 1097 hash[12] = 0; 1098 } 1099 1100 if (rtag7_en_bin_12_overlay_b) { 1101 hash_word[6] = (rtag7_hash_seed_b & 0xffff0000) | (hash[12] & 0xffff); 1102 } else { 1103 hash_word[6] = rtag7_hash_seed_b; 1104 } 1105 1106 hash_res->hash_b_valid = TRUE; 1107 for (elem = 11; elem >= 0; elem--) { 1108 elem_bit = 1 << elem; 1109 if (0 != (hash_field_bmap_b & elem_bit)) { 1110 if (0 != (hash_element_valid_bits & elem_bit)) { 1111 hash_word[elem/2] |= 1112 ((hash[elem] & 0xffff) << (16 * (elem % 2))); 1113 } else { 1114 hash_res->hash_b_valid = FALSE; 1115 break; 1116 } 1117 } 1118 } 1119 1120 xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ hash_word[2] ^ hash_word[1] ^ hash_word[0]; 1121 hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff); 1122 hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff); 1123 hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf); 1124 hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3); 1125 hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1); 1126 1127 hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28); 1128 hash_crc16_ccitt = _shr_crc16_ccitt_array(hash_word, 28); 1129 hash_crc32 = _shr_crc32_castagnoli_array(hash_word, 28); 1130 1131 switch (rtag7_hash_b0_function_select) { 1132 case 0: /* reserved */ 1133 hash_res->rtag7_hash16_value_b_0 = 0; 1134 break; 1135 case 1: /* reserved */ 1136 hash_res->rtag7_hash16_value_b_0 = 0; 1137 break; 1138 case 2: /* reserved */ 1139 hash_res->rtag7_hash16_value_b_0 = 0; 1140 break; 1141 case 3: /* CRC16 BISYNC */ 1142 hash_res->rtag7_hash16_value_b_0 = hash_crc16_bisync; 1143 break; 1144 case 4: /* CRC16_XOR1 */ 1145 hash_res->rtag7_hash16_value_b_0 = hash_xor1 & 0x1; 1146 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1147 break; 1148 case 5: /* CRC16_XOR2 */ 1149 hash_res->rtag7_hash16_value_b_0 = hash_xor2 & 0x3; 1150 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1151 break; 1152 case 6: /* CRC16_XOR4 */ 1153 hash_res->rtag7_hash16_value_b_0 = hash_xor4 & 0xf; 1154 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1155 break; 1156 case 7: /* CRC16_XOR8 */ 1157 hash_res->rtag7_hash16_value_b_0 = hash_xor8 & 0xff; 1158 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1159 break; 1160 case 8: /* XOR16 */ 1161 hash_res->rtag7_hash16_value_b_0 = hash_xor16; 1162 break; 1163 case 9: /* CRC16_CCITT */ 1164 hash_res->rtag7_hash16_value_b_0 = hash_crc16_ccitt; 1165 break; 1166 case 10: /* CRC32_LO */ 1167 hash_res->rtag7_hash16_value_b_0 = hash_crc32 & 0xffff; 1168 break; 1169 case 11: /* CRC32_HI */ 1170 hash_res->rtag7_hash16_value_b_0 = (hash_crc32 >> 16) & 0xffff; 1171 break; 1172 default: /* reserved */ 1173 hash_res->rtag7_hash16_value_b_0 = 0; 1174 break; 1175 } 1176 1177 switch (rtag7_hash_b1_function_select) { 1178 case 0: /* reserved */ 1179 hash_res->rtag7_hash16_value_b_1 = 0; 1180 break; 1181 case 1: /* reserved */ 1182 hash_res->rtag7_hash16_value_b_1 = 0; 1183 break; 1184 case 2: /* reserved */ 1185 hash_res->rtag7_hash16_value_b_1 = 0; 1186 break; 1187 case 3: /* CRC16 BISYNC */ 1188 hash_res->rtag7_hash16_value_b_1 = hash_crc16_bisync; 1189 break; 1190 case 4: /* CRC16_XOR1 */ 1191 hash_res->rtag7_hash16_value_b_1 = hash_xor1 & 0x1; 1192 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1193 break; 1194 case 5: /* CRC16_XOR2 */ 1195 hash_res->rtag7_hash16_value_b_1 = hash_xor2 & 0x3; 1196 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1197 break; 1198 case 6: /* CRC16_XOR4 */ 1199 hash_res->rtag7_hash16_value_b_1 = hash_xor4 & 0xf; 1200 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1201 break; 1202 case 7: /* CRC16_XOR8 */ 1203 hash_res->rtag7_hash16_value_b_1 = hash_xor8 & 0xff; 1204 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1205 break; 1206 case 8: /* XOR16 */ 1207 hash_res->rtag7_hash16_value_b_1 = hash_xor16; 1208 break; 1209 case 9: /* CRC16_CCITT */ 1210 hash_res->rtag7_hash16_value_b_1 = hash_crc16_ccitt; 1211 break; 1212 case 10: /* CRC32_LO */ 1213 hash_res->rtag7_hash16_value_b_1 = hash_crc32 & 0xffff; 1214 break; 1215 case 11: /* CRC32_HI */ 1216 hash_res->rtag7_hash16_value_b_1 = (hash_crc32 >> 16) & 0xffff; 1217 break; 1218 default: /* reserved */ 1219 hash_res->rtag7_hash16_value_b_1 = 0; 1220 break; 1221 } 1222 1223 /* End of option B hash calculation for rtag 7 */ 1224 return BCM_E_NONE; 1225 } 1226 1227 /* 1228 * Function: 1229 * select_tr3_hash_subfield 1230 * Description: 1231 * read hashing values of hash A0,A1,B0,B1,LBID 1232 * from sub_sel_block pointed by hash_sub_sel 1233 * Parameters: 1234 * concat - tell whether is in concatenated mode or not 1235 * hash_sub_sel - tell which hash sub to choose 1236 * seleted_subfiled - saves subfield value 1237 * hash_Base - internal data where hashing informaiton is stored 1238 * Returns: 1239 * BCM_E_xxxx 1240 * Note: if hash_sub_sel and hash_Base->hash_x_valid mismatches, 1241 * it will return BCM_E_PARAM 1242 */ 1243 STATIC int 1244 select_tr3_hash_subfield(uint32 concat, int hash_sub_sel, uint64 *selected_subfield, 1245 bcm_rtag7_base_hash_t *hash_Base) 1246 { 1247 int rv = BCM_E_NONE; 1248 1249 switch (hash_sub_sel) { 1250 case 0: /* select pkt hash A */ 1251 if (concat) { 1252 COMPILER_64_SET(*selected_subfield, 1253 (hash_Base->rtag7_hash16_value_b_1 << 16 | hash_Base->rtag7_hash16_value_b_0), 1254 (hash_Base->rtag7_hash16_value_a_1 << 16 | hash_Base->rtag7_hash16_value_a_0)); 1255 if (!hash_Base->hash_a_valid || !hash_Base->hash_b_valid) { 1256 /* Missing paramter in input */ 1257 rv = BCM_E_PARAM; 1258 } 1259 } else { 1260 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0); 1261 if (!hash_Base->hash_a_valid) { 1262 /* Missing paramter in input */ 1263 rv = BCM_E_PARAM; 1264 } 1265 } 1266 break; 1267 1268 case 1: /* select pkt hash B */ 1269 if (concat) { 1270 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn); 1271 } else { 1272 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_0); 1273 if (!hash_Base->hash_b_valid) { 1274 /* Missing paramter in input */ 1275 rv = BCM_E_PARAM; 1276 } 1277 } 1278 break; 1279 1280 case 2: /* select port LBN */ 1281 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn); 1282 break; 1283 1284 case 3: /* select destination port id or hash A */ 1285 if (concat) { 1286 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn); 1287 } else { 1288 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0); 1289 if (!hash_Base->hash_a_valid) { 1290 /* Missing paramter in input */ 1291 rv = BCM_E_PARAM; 1292 } 1293 } 1294 break; 1295 1296 case 4: /* select LBID from module header or from SW1 stage */ 1297 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash); 1298 if (!hash_Base->lbid_hash_valid) { 1299 /* LBID setting isn't RTAG7 */ 1300 rv = BCM_E_CONFIG; 1301 } 1302 break; 1303 1304 case 5: /* select LBID from SW1 stage */ 1305 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash); 1306 if (!hash_Base->lbid_hash_valid) { 1307 /* LBID setting isn't RTAG7 */ 1308 rv = BCM_E_CONFIG; 1309 } 1310 break; 1311 1312 case 6: 1313 if (concat) { 1314 COMPILER_64_ZERO(*selected_subfield); 1315 } else { 1316 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_1); 1317 if (!hash_Base->hash_a_valid) { 1318 /* Missing paramter in input */ 1319 rv = BCM_E_PARAM; 1320 } 1321 } 1322 break; 1323 1324 case 7: 1325 if (concat) { 1326 COMPILER_64_ZERO(*selected_subfield); 1327 } else { 1328 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_1); 1329 if (!hash_Base->hash_b_valid) { 1330 /* Missing paramter in input */ 1331 rv = BCM_E_PARAM; 1332 } 1333 } 1334 break; 1335 1336 default: 1337 return BCM_E_PARAM; 1338 } 1339 1340 return rv; 1341 } 1342 1343 /* 1344 * Function: 1345 * main_tr3_compute_lbid 1346 * Description: 1347 * get lbid value that is used in hashing calculation 1348 * if flow hash is used, get SUB_SEL_LBID_OR_ENTROPY_LABELf and 1349 * OFFSET_LBID_OR_ENTROPY_LABELf from RTAG7_FLOW_BASED_HASHm 1350 * if flow hash is not used, get SUB_SEL_LBID_(non)UCf and 1351 * OFFSET_LBID_(non)UCf from RTAG7_PORT_BASED_HASHm 1352 * Parameters: 1353 * unit - StrataSwitch PCI device unit number (driver internal). 1354 * hash_Base - internal data that lbid_hash_value is stored 1355 * Returns: 1356 * BCM_E_xxxx 1357 * Note: bcmSwitchLoadBalanceHashSelect must be set to 7 1358 * and bcmSwitchLoadBalanceHashSet0UnicastOffset must be set properly. 1359 * if lbid_hash_sub_sel and hash_Base->hash_x_valid mismatches, 1360 * then lbid_hash_val saved in hash_Base will be 0 1361 */ 1362 STATIC int 1363 main_tr3_compute_lbid(int unit, bcm_rtag7_base_hash_t *hash_Base) 1364 { 1365 /*regular var declaration*/ 1366 uint32 lbid_hash_sub_sel; 1367 uint32 lbid_hash_offset; 1368 uint32 lbid_hash_value = 0; 1369 1370 /*register var declaration*/ 1371 int lbid_rtag = 0; 1372 uint64 ing_hash_config_reg; 1373 int rv = BCM_E_NONE; 1374 uint32 rtag7_hash_sel; 1375 uint32 port_based_hash_index; 1376 rtag7_port_based_hash_entry_t 1377 port_based_hash_entry; 1378 rtag7_flow_based_hash_entry_t 1379 flow_based_hash_entry; 1380 uint8 loadbalance_use_flow_hash_uc = 0; 1381 uint8 loadbalance_use_flow_hash_nonuc = 0; 1382 1383 /* get the lbid rtag value */ 1384 if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, LBID_RTAGf)) { 1385 rv = READ_ING_CONFIG_64r(unit, &ing_hash_config_reg); 1386 if (BCM_SUCCESS(rv)) { 1387 lbid_rtag = soc_reg64_field32_get(unit, ING_CONFIG_64r, 1388 ing_hash_config_reg, LBID_RTAGf); 1389 } else { 1390 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1391 (BSL_META_U(unit, 1392 "compute_lbid fail, lbid_rtag=0\n"))); 1393 lbid_rtag =0; 1394 } 1395 } else { 1396 rv = (BCM_E_UNAVAIL); 1397 } 1398 1399 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1400 (BSL_META_U(unit, 1401 "lbid_rtag = %d\n"), 1402 lbid_rtag)); 1403 1404 if (lbid_rtag == 7) { 1405 /* check if flow hash is used for UC*/ 1406 SOC_IF_ERROR_RETURN 1407 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1408 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_UCf)) { 1409 loadbalance_use_flow_hash_uc = 1410 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1411 rtag7_hash_sel, USE_FLOW_SEL_LBID_UCf); 1412 } else { 1413 loadbalance_use_flow_hash_uc = 0; 1414 } 1415 1416 /* check if flow hash is used for NONUC*/ 1417 SOC_IF_ERROR_RETURN 1418 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1419 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_NONUCf)) { 1420 loadbalance_use_flow_hash_nonuc = 1421 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1422 rtag7_hash_sel, USE_FLOW_SEL_LBID_NONUCf); 1423 } else { 1424 loadbalance_use_flow_hash_nonuc = 0; 1425 } 1426 1427 /* RTAG7 hash computation */ 1428 if ((loadbalance_use_flow_hash_nonuc&& (hash_Base->is_nonuc == 0)) || 1429 (loadbalance_use_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 1430 SOC_IF_ERROR_RETURN( 1431 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 1432 (hash_Base->rtag7_macro_flow_id & 0xff), 1433 &flow_based_hash_entry)); 1434 1435 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 1436 UC and NONUC */ 1437 lbid_hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1438 &flow_based_hash_entry, SUB_SEL_LBID_OR_ENTROPY_LABELf); 1439 lbid_hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1440 &flow_based_hash_entry, OFFSET_LBID_OR_ENTROPY_LABELf); 1441 1442 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 1443 if (hash_Base->dev_src_port < 0) { 1444 int field_count = 0; 1445 soc_field_t fields[2]; 1446 uint32 values[2]; 1447 bcm_gport_t gport; 1448 1449 BCM_GPORT_PROXY_SET(gport, 1450 hash_Base->src_modid, hash_Base->src_port); 1451 1452 if (hash_Base->is_nonuc) { 1453 fields[0] = SUB_SEL_LBID_NONUCf ; 1454 field_count++; 1455 fields[1] = OFFSET_LBID_NONUCf; 1456 field_count++; 1457 } else { 1458 fields[0] = SUB_SEL_LBID_UCf ; 1459 field_count++; 1460 fields[1] = OFFSET_LBID_UCf; 1461 field_count++; 1462 } 1463 PORT_LOCK(unit); 1464 rv = bcm_esw_port_lport_fields_get(unit, gport, 1465 LPORT_PROFILE_RTAG7_TAB, 1466 field_count, fields, values); 1467 PORT_UNLOCK(unit); 1468 if (BCM_FAILURE(rv)) { 1469 return rv; 1470 } 1471 lbid_hash_sub_sel = values[0]; 1472 lbid_hash_offset = values[1]; 1473 } else { 1474 port_based_hash_index = hash_Base->dev_src_port + 1475 soc_mem_index_count(unit, LPORT_TABm); 1476 SOC_IF_ERROR_RETURN( 1477 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 1478 port_based_hash_index, &port_based_hash_entry)); 1479 if (hash_Base->is_nonuc) { 1480 lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1481 &port_based_hash_entry, SUB_SEL_LBID_NONUCf); 1482 lbid_hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1483 &port_based_hash_entry, OFFSET_LBID_NONUCf); 1484 } else { 1485 lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1486 &port_based_hash_entry, SUB_SEL_LBID_UCf); 1487 lbid_hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1488 &port_based_hash_entry, OFFSET_LBID_UCf); 1489 } 1490 } 1491 } else { 1492 lbid_hash_sub_sel = 0; 1493 lbid_hash_offset = 0; 1494 } 1495 1496 switch (lbid_hash_sub_sel) { 1497 1498 case 0: /* use pkt hash A */ 1499 lbid_hash_value = hash_Base->rtag7_hash16_value_a_0; 1500 if (!hash_Base->hash_a_valid) { 1501 /* Missing paramter in input */ 1502 rv = BCM_E_PARAM; 1503 } 1504 break; 1505 1506 case 1: /* use pkt hash B */ 1507 lbid_hash_value = hash_Base->rtag7_hash16_value_b_0; 1508 if (!hash_Base->hash_b_valid) { 1509 /* Missing paramter in input */ 1510 rv = BCM_E_PARAM; 1511 } 1512 break; 1513 1514 case 2: /* Use LBN */ 1515 lbid_hash_value = hash_Base->rtag7_port_lbn; 1516 break; 1517 1518 case 3: /* Use Destination PORTID or hash A */ 1519 lbid_hash_value = hash_Base->rtag7_hash16_value_a_0; 1520 if (!hash_Base->hash_a_valid) { 1521 /* Missing paramter in input */ 1522 rv = BCM_E_PARAM; 1523 } 1524 break; 1525 1526 case 4: /* Use LBID */ 1527 /* Higig lookup use mh_higig2_lbid */ 1528 1529 lbid_hash_value = 0; 1530 break; 1531 1532 case 5: 1533 lbid_hash_value = 0; 1534 break; 1535 1536 case 6: 1537 lbid_hash_value = hash_Base->rtag7_hash16_value_a_1; 1538 if (!hash_Base->hash_a_valid) { 1539 /* Missing paramter in input */ 1540 rv = BCM_E_PARAM; 1541 } 1542 break; 1543 1544 case 7: 1545 lbid_hash_value = hash_Base->rtag7_hash16_value_b_1; 1546 if (!hash_Base->hash_b_valid) { 1547 /* Missing paramter in input */ 1548 rv = BCM_E_PARAM; 1549 } 1550 break; 1551 } 1552 1553 /* 1554 * set up the hash value so that the LSB bits are 1555 * barrel shifted in case offset > 8. 1556 */ 1557 lbid_hash_value |= ((lbid_hash_value & 0xffff) << 16); 1558 1559 /* Only UC hash offsets apply to ECMP */ 1560 lbid_hash_value = (lbid_hash_value >> lbid_hash_offset); 1561 1562 hash_Base->rtag7_lbid_hash = (lbid_hash_value & 0xff); 1563 hash_Base->lbid_hash_valid = TRUE; 1564 } else { /* LBID rtag is 0-6 */ 1565 /* this function not support the rtag 0-6 */ 1566 1567 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1568 (BSL_META_U(unit, 1569 "Hash calculation: This function doesn't support rtag 0 6" 1570 " pls change register ING_CONFIG.LBID_RTAG to value 7\n"))); 1571 hash_Base->rtag7_lbid_hash = 0; 1572 hash_Base->lbid_hash_valid = FALSE; 1573 } 1574 1575 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1576 (BSL_META_U(unit, 1577 "lbid_hash_val=%d, valid=%d\n"), 1578 hash_Base->rtag7_lbid_hash, hash_Base->lbid_hash_valid)); 1579 1580 return rv; 1581 /* ******************* END of LBID computation ************************* */ 1582 } 1583 1584 #ifdef INCLUDE_L3 1585 /* 1586 * Function: 1587 * compute_tr3_ecmp_hash 1588 * Description: 1589 * get ecmp hash value using SUB_SEL_ECMPf and OFFSET_ECMPf 1590 * if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASHm 1591 * if flow hash is not used, get subsel and offset from RTAG7_PORT_BASED_HASHm 1592 * Parameters: 1593 * unit - StrataSwitch PCI device unit number (driver internal). 1594 * hash_Base - internal data where ecmp hash value is stored 1595 * Returns: 1596 * BCM_E_xxxx 1597 */ 1598 STATIC int 1599 compute_tr3_ecmp_hash(int unit, bcm_rtag7_base_hash_t *hash_Base, 1600 uint32 *hash_value) 1601 { 1602 /*regular var declaration*/ 1603 uint32 hash_sub_sel; 1604 uint32 hash_offset; 1605 uint64 hash_subfield; 1606 uint32 hash_subfield_width; 1607 uint8 rtag7_ecmp_use_macro_flow_hash; 1608 uint8 ecmp_hash_use_rtag7; 1609 uint32 rtag7_hash_sel; 1610 uint32 hash_control; 1611 uint32 concat; 1612 uint32 port_based_hash_index; 1613 rtag7_port_based_hash_entry_t 1614 port_based_hash_entry; 1615 rtag7_flow_based_hash_entry_t 1616 flow_based_hash_entry; 1617 int rv = BCM_E_NONE; 1618 1619 /* Select between non-RTAG7 hash value and RTAG7 hash value */ 1620 SOC_IF_ERROR_RETURN 1621 (READ_HASH_CONTROLr(unit, &hash_control)); 1622 ecmp_hash_use_rtag7 = 1623 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 1624 ECMP_HASH_USE_RTAG7f); 1625 1626 if (ecmp_hash_use_rtag7 == 0) { 1627 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1628 (BSL_META_U(unit, 1629 "ECMP Hash calculation: non rtag7 calc not supported\n"))); 1630 *hash_value = 0; 1631 return BCM_E_NONE; 1632 } 1633 1634 /* check if flow hash is used*/ 1635 SOC_IF_ERROR_RETURN 1636 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1637 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_ECMPf)) { 1638 rtag7_ecmp_use_macro_flow_hash = 1639 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1640 rtag7_hash_sel, USE_FLOW_SEL_ECMPf); 1641 } else { 1642 rtag7_ecmp_use_macro_flow_hash = 0; 1643 } 1644 1645 /* RTAG7 hash computation */ 1646 if (rtag7_ecmp_use_macro_flow_hash) { 1647 SOC_IF_ERROR_RETURN( 1648 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 1649 (hash_Base->rtag7_macro_flow_id & 0xff), 1650 &flow_based_hash_entry)); 1651 1652 /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */ 1653 /* For future designs this logic can be placed in RSEL1 */ 1654 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1655 &flow_based_hash_entry, SUB_SEL_ECMPf); 1656 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1657 &flow_based_hash_entry, OFFSET_ECMPf); 1658 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1659 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_ECMPf); 1660 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 1661 if (hash_Base->dev_src_port < 0) { 1662 int field_count = 0; 1663 soc_field_t fields[3]; 1664 uint32 values[3]; 1665 bcm_gport_t gport; 1666 1667 BCM_GPORT_PROXY_SET(gport, 1668 hash_Base->src_modid, hash_Base->src_port); 1669 1670 fields[0] = SUB_SEL_ECMPf; 1671 field_count++; 1672 fields[1] = OFFSET_ECMPf; 1673 field_count++; 1674 fields[2] = CONCATENATE_HASH_FIELDS_ECMPf; 1675 field_count++; 1676 PORT_LOCK(unit); 1677 rv = bcm_esw_port_lport_fields_get(unit, gport, 1678 LPORT_PROFILE_RTAG7_TAB, 1679 field_count, fields, values); 1680 PORT_UNLOCK(unit); 1681 if (BCM_FAILURE(rv)) { 1682 return rv; 1683 } 1684 hash_sub_sel = values[0]; 1685 hash_offset = values[1]; 1686 concat = values[2]; 1687 } else { 1688 port_based_hash_index = hash_Base->dev_src_port + 1689 soc_mem_index_count(unit, LPORT_TABm); 1690 SOC_IF_ERROR_RETURN( 1691 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 1692 port_based_hash_index, &port_based_hash_entry)); 1693 1694 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1695 &port_based_hash_entry, SUB_SEL_ECMPf); 1696 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1697 &port_based_hash_entry, OFFSET_ECMPf); 1698 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1699 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_ECMPf); 1700 } 1701 } else { 1702 hash_sub_sel = 0; 1703 hash_offset = 0; 1704 concat = 0; 1705 } 1706 1707 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1708 (BSL_META_U(unit, 1709 "ecmp hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 1710 hash_sub_sel, hash_offset, concat)); 1711 BCM_IF_ERROR_RETURN 1712 (select_tr3_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 1713 1714 hash_subfield_width = concat ? 64 : 16; 1715 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 1716 1717 /* Barrel shift the hash subfield, then take the LSB 16 bits */ 1718 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 1719 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 1720 *hash_value &= 0xffff; 1721 1722 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1723 (BSL_META_U(unit, 1724 "ecmp hash val=%d\n"), 1725 *hash_value)); 1726 1727 return BCM_E_NONE; 1728 /* ***************** END of ECMP HASH CALCULATIONS. ************************ */ 1729 } 1730 #endif /* INCLUDE_L3 */ 1731 1732 /* 1733 * Function: 1734 * compute_tr3_rtag7_hash_trunk 1735 * Description: 1736 * get LAG hash value from RTAG7_PORT_BASED_HASHm 1737 * if unicast, SUB_SEL_TRUNK_UCf and OFFSET_TRUNK_UCf are used 1738 * if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_TRUNK_NONUCf 1739 * if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 1740 * Parameters: 1741 * unit - StrataSwitch PCI device unit number (driver internal). 1742 * hash_Base - internal data where trunk hash value is storead 1743 * hash_value- result param 1744 * Returns: 1745 * BCM_E_xxxx 1746 */ 1747 STATIC int 1748 compute_tr3_rtag7_hash_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base, 1749 uint32 *hash_value) 1750 { 1751 uint32 hash_sub_sel; 1752 uint32 hash_offset; 1753 uint32 rtag7_hash_sel; 1754 uint32 port_based_hash_index; 1755 uint64 hash_subfield; 1756 uint32 hash_subfield_width; 1757 uint32 offset_shift = 0; 1758 uint32 concat; 1759 uint8 rtag7_trunk_use_macro_flow_hash_uc = 0; 1760 uint8 rtag7_trunk_use_macro_flow_hash_nonuc = 0; 1761 rtag7_port_based_hash_entry_t 1762 port_based_hash_entry; 1763 rtag7_flow_based_hash_entry_t 1764 flow_based_hash_entry; 1765 uint32 hash_control; 1766 uint32 nuc_trunk_hash_use_rtag7; 1767 int rv = BCM_E_NONE; 1768 1769 /* check if flow hash is used for UC*/ 1770 SOC_IF_ERROR_RETURN 1771 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1772 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_UCf)) { 1773 rtag7_trunk_use_macro_flow_hash_uc = 1774 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1775 rtag7_hash_sel, USE_FLOW_SEL_TRUNK_UCf); 1776 } else { 1777 rtag7_trunk_use_macro_flow_hash_uc = 0; 1778 } 1779 1780 /* check if flow hash is used for NONUC*/ 1781 SOC_IF_ERROR_RETURN 1782 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1783 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_NONUCf)) { 1784 rtag7_trunk_use_macro_flow_hash_nonuc = 1785 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1786 rtag7_hash_sel, USE_FLOW_SEL_TRUNK_NONUCf); 1787 } else { 1788 rtag7_trunk_use_macro_flow_hash_nonuc = 0; 1789 } 1790 1791 /* RTAG7 hash computation */ 1792 if ((rtag7_trunk_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) || 1793 (rtag7_trunk_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 1794 SOC_IF_ERROR_RETURN( 1795 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 1796 (hash_Base->rtag7_macro_flow_id & 0xff), 1797 &flow_based_hash_entry)); 1798 1799 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 1800 UC and NONUC */ 1801 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1802 &flow_based_hash_entry, SUB_SEL_TRUNKf); 1803 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1804 &flow_based_hash_entry, OFFSET_TRUNKf); 1805 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1806 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNKf); 1807 offset_shift = 0xffff; 1808 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 1809 if (hash_Base->dev_src_port < 0) { 1810 int field_count = 0; 1811 soc_field_t fields[3]; 1812 uint32 values[3]; 1813 bcm_gport_t gport; 1814 1815 BCM_GPORT_PROXY_SET(gport, 1816 hash_Base->src_modid, hash_Base->src_port); 1817 1818 if (hash_Base->is_nonuc) { 1819 fields[0] = SUB_SEL_TRUNK_NONUCf ; 1820 field_count++; 1821 fields[1] = OFFSET_TRUNK_NONUCf; 1822 field_count++; 1823 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_NONUCf; 1824 field_count++; 1825 offset_shift = 0xff; 1826 } else { 1827 fields[0] = SUB_SEL_TRUNK_UCf ; 1828 field_count++; 1829 fields[1] = OFFSET_TRUNK_UCf; 1830 field_count++; 1831 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_UCf; 1832 field_count++; 1833 offset_shift = 0x3ff; 1834 } 1835 PORT_LOCK(unit); 1836 rv = bcm_esw_port_lport_fields_get(unit, gport, 1837 LPORT_PROFILE_RTAG7_TAB, 1838 field_count, fields, values); 1839 PORT_UNLOCK(unit); 1840 if (BCM_FAILURE(rv)) { 1841 return rv; 1842 } 1843 hash_sub_sel = values[0]; 1844 hash_offset = values[1]; 1845 concat = values[2]; 1846 } else { 1847 port_based_hash_index = hash_Base->dev_src_port + 1848 soc_mem_index_count(unit, LPORT_TABm); 1849 SOC_IF_ERROR_RETURN( 1850 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 1851 port_based_hash_index, &port_based_hash_entry)); 1852 if (hash_Base->is_nonuc) { 1853 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1854 &port_based_hash_entry, SUB_SEL_TRUNK_NONUCf); 1855 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1856 &port_based_hash_entry, OFFSET_TRUNK_NONUCf); 1857 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1858 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_NONUCf); 1859 offset_shift = 0xff; 1860 } else { 1861 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1862 &port_based_hash_entry, SUB_SEL_TRUNK_UCf); 1863 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1864 &port_based_hash_entry, OFFSET_TRUNK_UCf); 1865 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1866 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_UCf); 1867 offset_shift = 0x3ff; 1868 } 1869 } 1870 } else { 1871 hash_sub_sel = 0; 1872 hash_offset = 0; 1873 concat = 0; 1874 } 1875 1876 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1877 (BSL_META_U(unit, 1878 "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 1879 hash_sub_sel, hash_offset, concat)); 1880 1881 BCM_IF_ERROR_RETURN 1882 (select_tr3_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 1883 1884 hash_subfield_width = concat ? 64 : 16; 1885 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 1886 1887 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 1888 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 1889 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 1890 *hash_value &= offset_shift; 1891 1892 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1893 (BSL_META_U(unit, 1894 "Trunk hash_value=%d\n"), 1895 *hash_value)); 1896 1897 BCM_IF_ERROR_RETURN 1898 (READ_HASH_CONTROLr(unit, &hash_control)); 1899 nuc_trunk_hash_use_rtag7 = 1900 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 1901 NON_UC_TRUNK_HASH_USE_RTAG7f); 1902 1903 if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) { 1904 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1905 (BSL_META_U(unit, 1906 "NonUC trunk Hash calculation: non rtag7 calc not supported\n"))); 1907 *hash_value = 0; 1908 } 1909 1910 return BCM_E_NONE; 1911 } 1912 1913 /* 1914 * Function: 1915 * compute_tr3_rtag7_hash_hg_trunk 1916 * Description: 1917 * get HGT hash value from RTAG7_PORT_BASED_HASHm 1918 * if unicast, SUB_SEL_TRUNK_UCf and OFFSET_TRUNK_UCf are used 1919 * if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_TRUNK_NONUCf 1920 * if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 1921 * Parameters: 1922 * unit - StrataSwitch PCI device unit number (driver internal). 1923 * hash_Base - internal data where trunk hash value is storead 1924 * hash_value- result param 1925 * Returns: 1926 * BCM_E_xxxx 1927 */ 1928 STATIC int 1929 compute_tr3_rtag7_hash_hg_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base, 1930 uint32 *hash_value) 1931 { 1932 uint32 hash_sub_sel; 1933 uint32 hash_offset; 1934 uint32 rtag7_hash_sel; 1935 uint32 port_based_hash_index; 1936 uint64 hash_subfield; 1937 uint32 hash_subfield_width; 1938 uint32 offset_shift = 0; 1939 uint32 concat; 1940 uint8 rtag7_hgt_use_macro_flow_hash_uc = 0; 1941 uint8 rtag7_hgt_use_macro_flow_hash_nonuc = 0; 1942 rtag7_port_based_hash_entry_t 1943 port_based_hash_entry; 1944 rtag7_flow_based_hash_entry_t 1945 flow_based_hash_entry; 1946 int rv = BCM_E_NONE; 1947 1948 /* check if flow hash is used for UC*/ 1949 SOC_IF_ERROR_RETURN 1950 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1951 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_UCf)) { 1952 rtag7_hgt_use_macro_flow_hash_uc = 1953 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1954 rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_UCf); 1955 } else { 1956 rtag7_hgt_use_macro_flow_hash_uc = 0; 1957 } 1958 1959 /* check if flow hash is used for NONUC*/ 1960 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_NONUCf)) { 1961 rtag7_hgt_use_macro_flow_hash_nonuc = 1962 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1963 rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_NONUCf); 1964 } else { 1965 rtag7_hgt_use_macro_flow_hash_nonuc = 0; 1966 } 1967 1968 /* RTAG7 hash computation */ 1969 if ((rtag7_hgt_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) || 1970 (rtag7_hgt_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 1971 SOC_IF_ERROR_RETURN( 1972 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 1973 (hash_Base->rtag7_macro_flow_id & 0xff), 1974 &flow_based_hash_entry)); 1975 1976 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 1977 UC and NONUC */ 1978 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1979 &flow_based_hash_entry, SUB_SEL_HG_TRUNKf); 1980 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1981 &flow_based_hash_entry, OFFSET_HG_TRUNKf); 1982 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1983 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNKf); 1984 offset_shift = 0xffff; 1985 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 1986 if (hash_Base->dev_src_port < 0) { 1987 int field_count = 0; 1988 soc_field_t fields[3]; 1989 uint32 values[3]; 1990 bcm_gport_t gport; 1991 1992 BCM_GPORT_PROXY_SET(gport, 1993 hash_Base->src_modid, hash_Base->src_port); 1994 1995 if (hash_Base->is_nonuc) { 1996 fields[0] = SUB_SEL_HG_TRUNK_NONUCf ; 1997 field_count++; 1998 fields[1] = OFFSET_HG_TRUNK_NONUCf; 1999 field_count++; 2000 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf; 2001 field_count++; 2002 offset_shift = 0xff; 2003 } else { 2004 fields[0] = SUB_SEL_HG_TRUNK_UCf ; 2005 field_count++; 2006 fields[1] = OFFSET_HG_TRUNK_UCf; 2007 field_count++; 2008 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf; 2009 field_count++; 2010 offset_shift = 0x3ff; 2011 } 2012 PORT_LOCK(unit); 2013 rv = bcm_esw_port_lport_fields_get(unit, gport, 2014 LPORT_PROFILE_RTAG7_TAB, 2015 field_count, fields, values); 2016 PORT_UNLOCK(unit); 2017 if (BCM_FAILURE(rv)) { 2018 return rv; 2019 } 2020 hash_sub_sel = values[0]; 2021 hash_offset = values[1]; 2022 concat = values[2]; 2023 } else { 2024 port_based_hash_index = hash_Base->dev_src_port + 2025 soc_mem_index_count(unit, LPORT_TABm); 2026 SOC_IF_ERROR_RETURN( 2027 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 2028 port_based_hash_index, &port_based_hash_entry)); 2029 if (hash_Base->is_nonuc) { 2030 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2031 &port_based_hash_entry, SUB_SEL_HG_TRUNK_NONUCf); 2032 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2033 &port_based_hash_entry, OFFSET_HG_TRUNK_NONUCf); 2034 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2035 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf); 2036 offset_shift = 0xff; 2037 } else { 2038 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2039 &port_based_hash_entry, SUB_SEL_HG_TRUNK_UCf); 2040 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2041 &port_based_hash_entry, OFFSET_HG_TRUNK_UCf); 2042 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2043 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf); 2044 offset_shift = 0x3ff; 2045 } 2046 } 2047 } else { 2048 hash_sub_sel = 0; 2049 hash_offset = 0; 2050 concat = 0; 2051 } 2052 2053 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2054 (BSL_META_U(unit, 2055 "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 2056 hash_sub_sel, hash_offset, concat)); 2057 2058 BCM_IF_ERROR_RETURN 2059 (select_tr3_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 2060 2061 hash_subfield_width = concat ? 64 : 16; 2062 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 2063 2064 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 2065 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 2066 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 2067 *hash_value &= offset_shift; 2068 2069 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2070 (BSL_META_U(unit, 2071 "HG Trunk hash_value=%d\n"), 2072 *hash_value)); 2073 2074 return BCM_E_NONE; 2075 } 2076 2077 /* 2078 * Function: 2079 * get_tr3_hash_trunk 2080 * Description: 2081 * compute destination trunk member port 2082 * Parameters: 2083 * unit - StrataSwitch PCI device unit number (driver internal). 2084 * ecmp_group - multipath id 2085 * tgid - trunk port id 2086 * hash_index - hash value calculated from compute_tr3_rtag7_hash_trunk 2087 * hash_rh_index - hash value calculated from compute_tr3_rtag7_hash_rh_trunk 2088 * dst_tgid - where egress member port id is stored 2089 * lag_rh_hash - flag indicating if rh is enable for this hashing calculation 2090 * ethertype - Ethertype of a packet 2091 * 2092 * Returns: 2093 * BCM_E_xxxx 2094 */ 2095 STATIC int 2096 get_tr3_hash_trunk(int unit, int tgid, uint32 hash_index, bcm_gport_t *dst_gport) 2097 { 2098 uint32 trunk_base; 2099 uint32 trunk_group_size; 2100 uint32 rtag; 2101 uint32 trunk_index; 2102 uint32 trunk_member_table_index; 2103 bcm_module_t mod_id; 2104 bcm_port_t port_id; 2105 int mod_is_local; 2106 trunk_member_entry_t trunk_member_entry; 2107 trunk_group_entry_t tg_entry; 2108 _bcm_gport_dest_t dest; 2109 2110 BCM_IF_ERROR_RETURN 2111 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &tg_entry)); 2112 2113 trunk_base = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf); 2114 trunk_group_size = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf); 2115 rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf); 2116 2117 if (rtag != 7){ 2118 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2119 (BSL_META_U(unit, 2120 "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"), 2121 rtag)); 2122 } 2123 2124 trunk_index = hash_index % (trunk_group_size + 1); 2125 trunk_member_table_index = (trunk_base + trunk_index) & 0x7ff; 2126 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2127 (BSL_META_U(unit, 2128 "\tTrunk HW index 0x%08x\n"), 2129 trunk_index)); 2130 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2131 (BSL_META_U(unit, 2132 "\tTrunk group size 0x%08x\n"), 2133 trunk_group_size)); 2134 2135 2136 BCM_IF_ERROR_RETURN 2137 (READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index, 2138 &trunk_member_entry)); 2139 mod_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry, 2140 MODULE_IDf); 2141 port_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry, 2142 PORT_NUMf); 2143 2144 BCM_IF_ERROR_RETURN 2145 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id, 2146 &(dest.modid), &(dest.port))); 2147 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 2148 2149 BCM_IF_ERROR_RETURN 2150 (_bcm_esw_modid_is_local(unit, dest.modid, 2151 &mod_is_local)); 2152 if (mod_is_local) { 2153 if (IS_ST_PORT(unit, port_id)) { 2154 dest.modid = mod_id; 2155 dest.port = port_id; 2156 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 2157 } 2158 } 2159 2160 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport)); 2161 2162 return BCM_E_NONE; 2163 } 2164 2165 /* 2166 * Function: 2167 * get_tr3_hash_trunk_nuc 2168 * Description: 2169 * Compute non-unicast destination trunk member port 2170 * Parameters: 2171 * unit - StrataSwitch PCI device unit number (driver internal). 2172 * tgid - Trunk group id 2173 * fwd_reason - Flow foward reason. unicast, ipmc, l2mc, broadcast, dlf. 2174 * hash_index - Hash value calculated based on RTAG7 2175 * dst_gport - Where egress member port id is stored 2176 * 2177 * Returns: 2178 * BCM_E_xxxx 2179 */ 2180 STATIC int 2181 get_tr3_hash_trunk_nuc(int unit, int tgid, 2182 bcm_switch_pkt_hash_info_fwd_reason_t fwd_reason, 2183 uint32 hash_index, bcm_gport_t *dst_gport) 2184 { 2185 int nuc_type, nuc_tbm_index; 2186 int modid, port; 2187 bcm_pbmp_t local_pbmp, block_mask_pbmp; 2188 trunk_bitmap_entry_t trunk_bitmap_entry; 2189 nonucast_trunk_block_mask_entry_t mask_entry; 2190 uint32 disable_flags = BCM_TRUNK_MEMBER_EGRESS_DISABLE; 2191 2192 switch(fwd_reason) { 2193 case bcmSwitchPktHashInfoFwdReasonIpmc: 2194 nuc_type = TRUNK_BLOCK_MASK_TYPE_IPMC; 2195 disable_flags |= BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE; 2196 break; 2197 case bcmSwitchPktHashInfoFwdReasonL2mc: 2198 nuc_type = TRUNK_BLOCK_MASK_TYPE_L2MC; 2199 disable_flags |= BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE; 2200 break; 2201 case bcmSwitchPktHashInfoFwdReasonBcast: 2202 nuc_type = TRUNK_BLOCK_MASK_TYPE_BCAST; 2203 disable_flags |= BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE; 2204 break; 2205 case bcmSwitchPktHashInfoFwdReasonDlf: 2206 nuc_type = TRUNK_BLOCK_MASK_TYPE_DLF; 2207 disable_flags |= BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE; 2208 break; 2209 default: 2210 return BCM_E_PARAM; 2211 } 2212 nuc_tbm_index = (nuc_type << 8) | (hash_index & 0xff); 2213 2214 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2215 (BSL_META_U(unit, 2216 "Nonuc-trunk table index = %d\n"), 2217 nuc_tbm_index)); 2218 2219 BCM_IF_ERROR_RETURN( 2220 READ_NONUCAST_TRUNK_BLOCK_MASKm(unit, MEM_BLOCK_ANY, 2221 nuc_tbm_index, &mask_entry)); 2222 soc_mem_pbmp_field_get(unit, NONUCAST_TRUNK_BLOCK_MASKm, &mask_entry, 2223 BLOCK_MASKf, &block_mask_pbmp); 2224 BCM_IF_ERROR_RETURN( 2225 READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tgid, &trunk_bitmap_entry)); 2226 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 2227 TRUNK_BITMAPf, &local_pbmp); 2228 2229 BCM_PBMP_REMOVE(local_pbmp, block_mask_pbmp); 2230 2231 if (BCM_PBMP_IS_NULL(local_pbmp)) { 2232 /* this means that member is not on local device, try SW prediction */ 2233 bcm_trunk_member_t member_array[BCM_TRUNK_MAX_PORTCNT]; 2234 int member_count; 2235 bcm_gport_t *port_array = NULL; 2236 int port_count, port_index; 2237 int region_size, i, all_local; 2238 2239 BCM_IF_ERROR_RETURN 2240 (bcm_esw_trunk_get(unit, tgid, NULL, BCM_TRUNK_MAX_PORTCNT, 2241 member_array, &member_count)); 2242 2243 port_array = sal_alloc(member_count * sizeof(bcm_gport_t), 2244 "port_array"); 2245 if (port_array == NULL) { 2246 return BCM_E_MEMORY; 2247 } 2248 2249 port_count = 0; 2250 all_local = TRUE; 2251 for (i = 0; i < member_count; i++) { 2252 if (member_array[i].flags & disable_flags) { 2253 continue; 2254 } 2255 port = member_array[i].gport; 2256 port_array[port_count++] = port; 2257 if (all_local) { 2258 if (BCM_FAILURE(bcm_esw_port_local_get(unit, port, &port))) { 2259 all_local = FALSE; 2260 } 2261 } 2262 } 2263 /* All ports are disabled */ 2264 if (port_count == 0) { 2265 *dst_gport = -1; 2266 sal_free(port_array); 2267 return BCM_E_NOT_FOUND; 2268 } 2269 region_size = soc_mem_index_count(unit, NONUCAST_TRUNK_BLOCK_MASKm) / 4; 2270 if (all_local || port_count > BCM_SWITCH_TRUNK_MAX_PORTCNT) { 2271 port_index = (nuc_tbm_index % region_size) % port_count; 2272 } else { 2273 port_index = (nuc_tbm_index % BCM_XGS3_TRUNK_MAX_PORTCNT) % port_count; 2274 } 2275 2276 *dst_gport = port_array[port_index]; 2277 2278 sal_free(port_array); 2279 2280 } else { 2281 _bcm_gport_dest_t dest; 2282 2283 /*Each index only has one egress port */ 2284 BCM_PBMP_ITER(local_pbmp, port) { 2285 break; 2286 } 2287 2288 if (port == BCM_PBMP_PORT_MAX) { 2289 /* If not found in iteration, return not found. It never be here */ 2290 *dst_gport = -1; 2291 return BCM_E_NOT_FOUND; 2292 } 2293 2294 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 2295 2296 BCM_IF_ERROR_RETURN 2297 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 2298 &(dest.modid), &(dest.port))); 2299 if (IS_ST_PORT(unit, port)) { 2300 dest.modid = modid; 2301 dest.port = port; 2302 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 2303 } else { 2304 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 2305 } 2306 2307 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport)); 2308 } 2309 2310 return BCM_E_NONE; 2311 } 2312 2313 2314 #ifdef INCLUDE_L3 2315 /* 2316 * Function: 2317 * get_tr3_hash_ecmp 2318 * Description: 2319 * compute ecmp destination among multipath interfaces 2320 * Parameters: 2321 * unit - StrataSwitch PCI device unit number (driver internal). 2322 * ecmp_group - multipath id 2323 * hash_index - hash value calculated from compute_tr3_ecmp_hash 2324 * hash_rh_index - hash value calculated from compute_tr3_ecmp_rh_hash 2325 * nh_id - where egress l3 interface id is stored 2326 * ecmp_rh_enable - flag indicating if rh is enable for this hashing calculation 2327 * ethertype - Ethertype of a packet 2328 * 2329 * Returns: 2330 * BCM_E_xxxx 2331 */ 2332 STATIC int 2333 get_tr3_hash_ecmp(int unit, int ecmp_group, uint32 hash_index, bcm_if_t *nh_id) 2334 { 2335 uint32 ecmp_hash_field_upper_bits_count; 2336 2337 ecmp_count_entry_t ecmpc_entry; 2338 ecmp_entry_t ecmp_entry; 2339 uint32 ecmp_ptr = 0; 2340 uint32 ecmp_count = 0; 2341 uint32 hash_control; 2342 uint32 ecmp_mask; 2343 uint32 ecmp_offset; 2344 uint32 ecmp_index; 2345 2346 2347 if (SOC_REG_FIELD_VALID(unit, HASH_CONTROLr, 2348 ECMP_HASH_FIELD_UPPER_BITS_COUNTf)) { 2349 SOC_IF_ERROR_RETURN 2350 (READ_HASH_CONTROLr(unit, &hash_control)); 2351 ecmp_hash_field_upper_bits_count = 2352 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 2353 ECMP_HASH_FIELD_UPPER_BITS_COUNTf); 2354 } else { 2355 ecmp_hash_field_upper_bits_count = 0x6; /* A0 bincomp value */ 2356 } 2357 2358 /* pick up the ecmp count and base_ptr */ 2359 /* Trident+ ECMP Mode where ECMP resolution is done in one step using a 16Mod10 */ 2360 BCM_IF_ERROR_RETURN 2361 (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry)); 2362 2363 ecmp_ptr = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 2364 BASE_PTRf); 2365 ecmp_count = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 2366 COUNTf); 2367 switch (ecmp_hash_field_upper_bits_count) { 2368 case 0: 2369 ecmp_mask = 0x3ff; 2370 break; 2371 case 1: 2372 ecmp_mask = 0x7ff; 2373 break; 2374 case 2: 2375 ecmp_mask = 0xfff; 2376 break; 2377 case 3: 2378 ecmp_mask = 0x1fff; 2379 break; 2380 case 4: 2381 ecmp_mask = 0x3fff; 2382 break; 2383 case 5: 2384 ecmp_mask = 0x7fff; 2385 break; 2386 case 6: 2387 ecmp_mask = 0xffff; 2388 break; 2389 default: 2390 ecmp_mask = 0xffff; 2391 break; 2392 } 2393 2394 ecmp_offset = ((hash_index & ecmp_mask) % (ecmp_count + 1)) & 0x3FF; 2395 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2396 (BSL_META_U(unit, 2397 "\tECMP offset 0x%08x, ptr 0x%x\n"), 2398 ecmp_offset, ecmp_ptr)); 2399 ecmp_index = (ecmp_ptr + ecmp_offset) & 0xfff; 2400 BCM_IF_ERROR_RETURN 2401 (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry)); 2402 2403 *nh_id = 2404 soc_L3_ECMPm_field32_get(unit, &ecmp_entry, 2405 NEXT_HOP_INDEXf); 2406 *nh_id = *nh_id & 0x3fff; 2407 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2408 (BSL_META_U(unit, 2409 "\tECMP next hop HW index 0x%08x\n"), 2410 *nh_id)); 2411 2412 return BCM_E_NONE; 2413 } 2414 #endif /* INCLUDE_L3 */ 2415 2416 2417 STATIC int 2418 get_tr3_hash_hg_trunk(int unit, int hgtid, uint32 hash_index, bcm_gport_t *dst_gport) 2419 { 2420 uint32 trunk_base; 2421 uint32 trunk_group_size; 2422 uint32 rtag; 2423 uint32 trunk_index; 2424 uint32 trunk_member_table_index; 2425 bcm_module_t mod_id; 2426 bcm_port_t port_id; 2427 hg_trunk_member_entry_t hg_trunk_member_entry; 2428 hg_trunk_group_entry_t hg_tg_entry; 2429 _bcm_gport_dest_t dest; 2430 2431 BCM_IF_ERROR_RETURN 2432 (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, &hg_tg_entry)); 2433 2434 trunk_base = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, BASE_PTRf); 2435 trunk_group_size = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, TG_SIZEf); 2436 rtag = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, RTAGf); 2437 2438 if (rtag != 7) { 2439 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2440 (BSL_META_U(unit, 2441 "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"), 2442 rtag)); 2443 } 2444 2445 trunk_index = hash_index % (trunk_group_size + 1); 2446 trunk_member_table_index = (trunk_base + trunk_index) & 0xff; 2447 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2448 (BSL_META_U(unit, 2449 "\tHG Trunk HW index 0x%08x\n"), 2450 trunk_index)); 2451 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2452 (BSL_META_U(unit, 2453 "\tHG Trunk group size 0x%08x\n"), 2454 trunk_group_size)); 2455 2456 BCM_IF_ERROR_RETURN 2457 (READ_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index, 2458 &hg_trunk_member_entry)); 2459 port_id = soc_HG_TRUNK_MEMBERm_field32_get(unit, &hg_trunk_member_entry, 2460 PORT_NUMf); 2461 2462 if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &mod_id))) { 2463 mod_id = 0; 2464 } 2465 2466 BCM_IF_ERROR_RETURN 2467 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id, 2468 &(dest.modid), &(dest.port))); 2469 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 2470 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport)); 2471 2472 return BCM_E_NONE; 2473 } 2474 2475 /* 2476 * Function: 2477 * _bcm_tr3_switch_pkt_info_hash_get 2478 * Description: 2479 * main tr3 hash get function 2480 * 2481 * Parameters 2482 * unit - StrataSwitch PCI device unit number (driver internal). 2483 * pkt_info - struct that carries packet's l2, l3, and l4 information 2484 * dst_gport - hashing resolved trunk member port as a return val 2485 * dst_intf - hashing resolved ecmp member port as a retrun val 2486 * 2487 * Returns: 2488 * BCM_E_xxxx 2489 */ 2490 int 2491 _bcm_tr3_switch_pkt_info_hash_get (int unit, 2492 bcm_switch_pkt_info_t *pkt_info, 2493 bcm_gport_t *dst_gport, 2494 bcm_if_t *dst_intf) 2495 { 2496 bcm_rtag7_base_hash_t hash_res; 2497 int pc_out, mod_is_local; 2498 bcm_gport_t port; 2499 bcm_trunk_t tid; 2500 int id; 2501 uint32 hash_value; 2502 2503 if (pkt_info == NULL) { 2504 return BCM_E_PARAM; 2505 } 2506 2507 if (!_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_GPORT)) { 2508 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2509 (BSL_META_U(unit, 2510 "Hash calculation: source gport value missing\n"))); 2511 return BCM_E_PARAM; 2512 } 2513 2514 BCM_IF_ERROR_RETURN 2515 (_bcm_esw_gport_resolve(unit, pkt_info->src_gport, 2516 &(hash_res.src_modid), 2517 &(hash_res.src_port), 2518 &tid, &id)); 2519 if ((-1 != id) || (-1 != tid)) { 2520 /* Must be single system port */ 2521 return BCM_E_PORT; 2522 } 2523 2524 /* Load balancing retrieval */ 2525 BCM_IF_ERROR_RETURN( 2526 _bcm_esw_modid_is_local(unit, hash_res.src_modid, &mod_is_local)); 2527 if (mod_is_local) { 2528 BCM_IF_ERROR_RETURN 2529 (bcm_esw_port_local_get(unit, pkt_info->src_gport, &port)); 2530 hash_res.dev_src_port = port; 2531 } else { 2532 hash_res.dev_src_port = -1; 2533 if (BCM_GPORT_IS_PROXY(pkt_info->src_gport)) { 2534 port = pkt_info->src_gport; 2535 } else { 2536 BCM_GPORT_PROXY_SET(port, 2537 hash_res.src_modid, hash_res.src_port); 2538 } 2539 } 2540 BCM_IF_ERROR_RETURN 2541 (bcm_esw_port_control_get(unit, port, 2542 bcmPortControlLoadBalancingNumber, 2543 &pc_out)); 2544 hash_res.rtag7_port_lbn = pc_out; 2545 2546 /* check if the foward reason of packet is all non-uc packet or bit 40 in the mac DA is one. */ 2547 hash_res.is_nonuc = pkt_info->fwd_reason || BCM_MAC_IS_MCAST(pkt_info->dst_mac); 2548 2549 BCM_IF_ERROR_RETURN 2550 (main_tr3_do_rtag7_hashing(unit, pkt_info, &hash_res)); 2551 BCM_IF_ERROR_RETURN 2552 (main_tr3_compute_lbid(unit, &hash_res)); 2553 2554 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2555 (BSL_META_U(unit, 2556 "Hash status: \n"))); 2557 if (hash_res.hash_a_valid) { 2558 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2559 (BSL_META_U(unit, 2560 "\tRTAG7 A0 0x%08x\n"), 2561 hash_res.rtag7_hash16_value_a_0)); 2562 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2563 (BSL_META_U(unit, 2564 "\tRTAG7 A1 0x%08x\n"), 2565 hash_res.rtag7_hash16_value_a_1)); 2566 } else { 2567 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2568 (BSL_META_U(unit, 2569 "\tRTAG7 A hashes invalid due to missing packet info\n"))); 2570 } 2571 if (hash_res.hash_b_valid) { 2572 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2573 (BSL_META_U(unit, 2574 "\tRTAG7 B0 0x%08x\n"), 2575 hash_res.rtag7_hash16_value_b_0)); 2576 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2577 (BSL_META_U(unit, 2578 "\tRTAG7 B1 0x%08x\n"), 2579 hash_res.rtag7_hash16_value_b_1)); 2580 } else { 2581 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2582 (BSL_META_U(unit, 2583 "\tRTAG7 B hashes invalid due to missing packet info\n"))); 2584 } 2585 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2586 (BSL_META_U(unit, 2587 "\tRTAG7 LBN 0x%08x\n"), 2588 hash_res.rtag7_port_lbn)); 2589 if (hash_res.lbid_hash_valid){ 2590 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2591 (BSL_META_U(unit, 2592 "\tRTAG7 LBID 0x%08x\n"), 2593 hash_res.rtag7_lbid_hash)); 2594 } else { 2595 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2596 (BSL_META_U(unit, 2597 "\tRTAG7 LBID not valid due to non-RTAG7 configuration\n"))); 2598 } 2599 2600 #ifdef INCLUDE_L3 2601 if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_MULTIPATH)) { 2602 bcm_if_t nh_id; 2603 2604 if (dst_intf == NULL) { 2605 return BCM_E_PARAM; 2606 } 2607 2608 BCM_IF_ERROR_RETURN 2609 (compute_tr3_ecmp_hash(unit, &hash_res, &hash_value)); 2610 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2611 (BSL_META_U(unit, 2612 "\tECMP Hash value 0x%08x\n"), 2613 hash_value)); 2614 2615 BCM_IF_ERROR_RETURN 2616 (get_tr3_hash_ecmp(unit, 2617 pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 2618 hash_value, &nh_id)); 2619 /* Convert to egress object format */ 2620 *dst_intf = nh_id + BCM_XGS3_EGRESS_IDX_MIN(unit); 2621 } else 2622 #endif /* INCLUDE_L3 */ 2623 if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_TRUNK)) { 2624 bcm_trunk_t trunk = BCM_TRUNK_INVALID; 2625 int member_count; 2626 bcm_trunk_chip_info_t ti; 2627 2628 if (dst_gport == NULL) { 2629 return BCM_E_PARAM; 2630 } 2631 2632 if (!BCM_GPORT_IS_TRUNK(pkt_info->trunk_gport)) { 2633 return BCM_E_PORT; 2634 } 2635 trunk = BCM_GPORT_TRUNK_GET(pkt_info->trunk_gport); 2636 BCM_IF_ERROR_RETURN 2637 (bcm_esw_trunk_get(unit, trunk, NULL, 0, NULL, &member_count)); 2638 if (0 == member_count) { 2639 /* Return failure for no trunk members */ 2640 return BCM_E_FAIL; 2641 } 2642 2643 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &ti)); 2644 2645 if (trunk >= ti.trunk_id_min && trunk <= ti.trunk_id_max) { 2646 BCM_IF_ERROR_RETURN 2647 (compute_tr3_rtag7_hash_trunk(unit, &hash_res, &hash_value)); 2648 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2649 (BSL_META_U(unit, 2650 "\tTrunk Hash value 0x%08x\n"), 2651 hash_value)); 2652 if (hash_res.is_nonuc) { 2653 BCM_IF_ERROR_RETURN 2654 (get_tr3_hash_trunk_nuc(unit, trunk, pkt_info->fwd_reason, 2655 hash_value, dst_gport)); 2656 } else { 2657 BCM_IF_ERROR_RETURN 2658 (get_tr3_hash_trunk(unit, trunk, 2659 hash_value, dst_gport)); 2660 } 2661 } else if (trunk >= ti.trunk_fabric_id_min && trunk <= ti.trunk_fabric_id_max) { 2662 BCM_IF_ERROR_RETURN 2663 (compute_tr3_rtag7_hash_hg_trunk(unit, &hash_res, &hash_value)); 2664 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2665 (BSL_META_U(unit, 2666 "\tHG-Trunk Hash value 0x%08x\n"), 2667 hash_value)); 2668 BCM_IF_ERROR_RETURN 2669 (get_tr3_hash_hg_trunk(unit, trunk - ti.trunk_fabric_id_min, 2670 hash_value, dst_gport)); 2671 } 2672 } else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_LBID) { 2673 /* LBID hashing resolution */ 2674 if (dst_intf == NULL || hash_res.lbid_hash_valid == 0) { 2675 return BCM_E_FAIL; 2676 } else { 2677 *dst_intf = hash_res.rtag7_lbid_hash; 2678 } 2679 } else { 2680 return BCM_E_PARAM; 2681 } 2682 2683 return BCM_E_NONE; 2684 }