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