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