hashing.c (158639B)
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: TD2-Hash calcualtions for trunk and ECMP packets. 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/drv.h> 14 #include <soc/hash.h> 15 #include <bcm/switch.h> 16 #include <bcm/error.h> 17 18 #include <bcm_int/esw_dispatch.h> 19 #include <bcm_int/esw/firebolt.h> 20 #include <bcm_int/esw/port.h> 21 #include <bcm_int/esw/stack.h> 22 #include <bcm_int/esw/switch.h> 23 24 typedef struct bcm_rtag7_base_hash_s { 25 uint32 rtag7_hash16_value_a_0; /* hash a0 result */ 26 uint32 rtag7_hash16_value_a_1; /* hash a1 result */ 27 uint32 rtag7_hash16_value_b_0; /* hash b0 result */ 28 uint32 rtag7_hash16_value_b_1; /* hash b1 result */ 29 uint32 rtag7_macro_flow_id; /* hash micro flow result */ 30 uint32 rtag7_port_lbn; /* port LBN value from the port table*/ 31 uint32 rtag7_lbid_hash; /* LBID hash calculation*/ 32 bcm_port_t dev_src_port; /* Local source port */ 33 bcm_port_t src_port; /* System source port */ 34 bcm_module_t src_modid; /* System source modid */ 35 uint8 is_nonuc; /* Non-unicast */ 36 uint8 hash_a_valid; /* Hash A result use valid input */ 37 uint8 hash_b_valid; /* Hash B result use valid input */ 38 uint8 lbid_hash_valid; /* LBID Hash value is valid */ 39 } bcm_rtag7_base_hash_t; 40 41 #define ETHERTYPE_IPV6 0x86dd /* ipv6 ethertype */ 42 #define ETHERTYPE_IPV4 0x0800 /* ipv4 ethertype */ 43 #define ETHERTYPE_MIN 0x0600 /* minimum ethertype for hashing */ 44 45 #define IP_PROT_TCP 0x6 /* TCP protocol number */ 46 #define IP_PROT_UDP 0x11 /* TCP protocol number */ 47 48 #define RTAG7_RH_MODE_ECMP 0 49 #define RTAG7_RH_MODE_LAG 1 50 #define RTAG7_RH_MODE_HGT 2 51 52 #define RTAG7_L2_ONLY 0x0 53 #define RTAG7_UNKNOWN_HIGIG 0x1 54 #define RTAG7_MPLS 0x2 55 #define RTAG7_MIM 0x3 56 #define RTAG7_IPV4 0x4 57 #define RTAG7_IPV6 0x5 58 #define RTAG7_FCOE 0x6 59 #define RTAG7_TRILL 0x7 60 61 #define ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF 0 62 #define ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_ECMP 1 63 #define ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_LAG 2 64 65 #define RH_LAG_FLOWSET_MOD_ID_SHIFT_VAL 7 66 67 #define HASH_VALUE_64_COMPUTE(subfield,offset,width) do { \ 68 uint64 sf; \ 69 COMPILER_64_ZERO(sf); \ 70 COMPILER_64_ADD_64(sf, subfield); \ 71 COMPILER_64_SHR(subfield, offset); \ 72 COMPILER_64_SHL(sf, (width - offset)); \ 73 COMPILER_64_OR(subfield, sf); \ 74 } while(0) 75 76 #define HASH_VALUE_32_COMPUTE(hash_value_32, hash_value_64) do { \ 77 COMPILER_64_TO_32_LO(hash_value_32, hash_value_64); \ 78 } while(0) 79 80 81 /* 82 * Function: 83 * main_td2_do_rtag7_hashing 84 * Description: 85 * read hash control register values and 86 * set hash_res' fields 87 * Parameters: 88 * unit - StrataSwitch PCI device unit number (driver internal). 89 * pkt_info - ptr to data that has packet information 90 * hash_res - internal data where hashing informaiton is stored 91 * Returns: 92 * BCM_E_xxxx 93 */ 94 STATIC int 95 main_td2_do_rtag7_hashing(int unit, 96 bcm_switch_pkt_info_t *pkt_info, 97 bcm_rtag7_base_hash_t *hash_res) 98 { 99 /* regular var declaration */ 100 uint32 hash_src_port; 101 uint32 hash_src_modid; 102 uint32 rtag7_a_sel; 103 bcm_ip_t sip_a; /* Source IPv4 address. */ 104 bcm_ip_t dip_a; /* Destination IPv4 address. */ 105 uint32 rtag7_b_sel; 106 bcm_ip_t sip_b; /* Source IPv4 address. */ 107 bcm_ip_t dip_b; /* Destination IPv4 address. */ 108 uint32 hash_field_bmap_a; /* block A chosen bitmap*/ 109 uint32 hash_field_bmap_b; /* block B chosen bitmap*/ 110 111 uint32 hash_word[7]; 112 uint32 hash[13]; 113 int elem, elem_bit; 114 uint32 hash_element_valid_bits; 115 int sip_valid = FALSE, dip_valid = FALSE; 116 uint32 macro_flow_id; 117 118 uint32 hash_crc16_bisync; 119 uint32 hash_crc16_ccitt; 120 uint32 hash_crc32; 121 uint32 hash_xor16; 122 uint32 hash_xor8; 123 uint32 hash_xor4; 124 uint32 hash_xor2; 125 uint32 hash_xor1; 126 uint32 xor32; 127 128 /* register var declaration */ 129 uint8 rtag7_disable_hash_ipv4_a; 130 uint8 rtag7_disable_hash_ipv6_a; 131 uint8 rtag7_disable_hash_ipv4_b; 132 uint8 rtag7_disable_hash_ipv6_b; 133 uint8 rtag7_ipv6_addr_use_lsb_a; 134 uint8 rtag7_ipv6_addr_use_lsb_b; 135 uint8 rtag7_pre_processing_enable_a; 136 uint8 rtag7_pre_processing_enable_b; 137 uint8 rtag7_en_flow_label_ipv6_a; 138 uint8 rtag7_en_flow_label_ipv6_b; 139 uint8 rtag7_en_bin_12_overlay_a; 140 uint8 rtag7_en_bin_12_overlay_b; 141 uint32 rtag7_hash_seed_a; 142 uint32 rtag7_hash_seed_b; 143 uint32 rtag7_hash_a0_function_select; 144 uint32 rtag7_hash_a1_function_select; 145 uint32 rtag7_hash_b0_function_select; 146 uint32 rtag7_hash_b1_function_select; 147 uint32 rtag7_macro_flow_hash_function_select; 148 uint8 rtag7_macro_flow_hash_byte_sel; 149 150 uint64 rtag7_hash_control, rtag7_hash_control_2_64; 151 uint32 rtag7_hash_control_2, rtag7_hash_control_3; 152 uint32 rtag7_hash_seed_a_reg, rtag7_hash_seed_b_reg; 153 soc_reg_t sc_reg; 154 soc_field_t sc_field; 155 uint32 sc_val; 156 int symmetric_hash_control_mask = 0; 157 int symmetric_hash_need_swap_ip6 = 0; 158 int symmetric_hash_need_swap_ip4 = 0; 159 160 /* read RTAG7 hash control register values */ 161 SOC_IF_ERROR_RETURN 162 (READ_RTAG7_HASH_CONTROLr(unit, &rtag7_hash_control)); 163 if (SOC_REG_IS_VALID(unit, RTAG7_HASH_CONTROL_2_64r)) { 164 SOC_IF_ERROR_RETURN 165 (READ_RTAG7_HASH_CONTROL_2_64r(unit, &rtag7_hash_control_2_64)); 166 } else if (SOC_REG_IS_VALID(unit, RTAG7_HASH_CONTROL_2r)) { 167 SOC_IF_ERROR_RETURN 168 (READ_RTAG7_HASH_CONTROL_2r(unit, &rtag7_hash_control_2)); 169 } 170 SOC_IF_ERROR_RETURN 171 (READ_RTAG7_HASH_CONTROL_3r(unit, &rtag7_hash_control_3)); 172 SOC_IF_ERROR_RETURN 173 (READ_RTAG7_HASH_SEED_Ar(unit, &rtag7_hash_seed_a_reg)); 174 SOC_IF_ERROR_RETURN 175 (READ_RTAG7_HASH_SEED_Br(unit, &rtag7_hash_seed_b_reg)); 176 177 /* read RTAG7 fields from hash control registers */ 178 rtag7_disable_hash_ipv4_a = 179 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 180 DISABLE_HASH_IPV4_Af); 181 rtag7_disable_hash_ipv6_a = 182 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 183 DISABLE_HASH_IPV6_Af); 184 rtag7_disable_hash_ipv4_b = 185 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 186 DISABLE_HASH_IPV4_Bf); 187 rtag7_disable_hash_ipv6_b = 188 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 189 DISABLE_HASH_IPV6_Bf); 190 rtag7_ipv6_addr_use_lsb_a = 191 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 192 IPV6_COLLAPSED_ADDR_SELECT_Af); 193 rtag7_ipv6_addr_use_lsb_b = 194 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROLr, rtag7_hash_control, 195 IPV6_COLLAPSED_ADDR_SELECT_Bf); 196 197 /* read RTAG7 fields from hash control3 registers */ 198 rtag7_pre_processing_enable_a = 199 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 200 HASH_PRE_PROCESSING_ENABLE_Af); 201 rtag7_pre_processing_enable_b = 202 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 203 HASH_PRE_PROCESSING_ENABLE_Bf); 204 rtag7_hash_a0_function_select = 205 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 206 HASH_A0_FUNCTION_SELECTf); 207 rtag7_hash_a1_function_select = 208 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 209 HASH_A1_FUNCTION_SELECTf); 210 rtag7_hash_b0_function_select = 211 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 212 HASH_B0_FUNCTION_SELECTf); 213 rtag7_hash_b1_function_select = 214 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_3r, rtag7_hash_control_3, 215 HASH_B1_FUNCTION_SELECTf); 216 217 /* read RTAG7 fields from hash control2 registers */ 218 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 219 ENABLE_FLOW_LABEL_IPV6_Af)) { 220 rtag7_en_flow_label_ipv6_a = 221 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 222 rtag7_hash_control_2, 223 ENABLE_FLOW_LABEL_IPV6_Af); 224 } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r, 225 ENABLE_FLOW_LABEL_IPV6_Af)) { 226 rtag7_en_flow_label_ipv6_a = 227 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r, 228 rtag7_hash_control_2_64, 229 ENABLE_FLOW_LABEL_IPV6_Af); 230 } else { 231 rtag7_en_flow_label_ipv6_a = 0; 232 } 233 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 234 ENABLE_FLOW_LABEL_IPV6_Bf)) { 235 rtag7_en_flow_label_ipv6_b = 236 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 237 rtag7_hash_control_2, 238 ENABLE_FLOW_LABEL_IPV6_Bf); 239 } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r, 240 ENABLE_FLOW_LABEL_IPV6_Bf)) { 241 rtag7_en_flow_label_ipv6_b = 242 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r, 243 rtag7_hash_control_2_64, 244 ENABLE_FLOW_LABEL_IPV6_Bf); 245 } else { 246 rtag7_en_flow_label_ipv6_b = 0; 247 } 248 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 249 ENABLE_BIN_12_OVERLAY_Af)) { 250 rtag7_en_bin_12_overlay_a = 251 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 252 rtag7_hash_control_2, 253 ENABLE_BIN_12_OVERLAY_Af); 254 } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r, 255 ENABLE_BIN_12_OVERLAY_Af)) { 256 rtag7_en_bin_12_overlay_a = 257 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r, 258 rtag7_hash_control_2_64, 259 ENABLE_BIN_12_OVERLAY_Af); 260 } else { 261 rtag7_en_bin_12_overlay_a = 0; 262 } 263 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 264 ENABLE_BIN_12_OVERLAY_Bf)) { 265 rtag7_en_bin_12_overlay_b = 266 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 267 rtag7_hash_control_2, 268 ENABLE_BIN_12_OVERLAY_Bf); 269 } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r, 270 ENABLE_BIN_12_OVERLAY_Bf)) { 271 rtag7_en_bin_12_overlay_b = 272 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r, 273 rtag7_hash_control_2_64, 274 ENABLE_BIN_12_OVERLAY_Bf); 275 } else { 276 rtag7_en_bin_12_overlay_b = 0; 277 } 278 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 279 MACRO_FLOW_HASH_FUNC_SELf)) { 280 rtag7_macro_flow_hash_function_select = 281 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 282 rtag7_hash_control_2, 283 MACRO_FLOW_HASH_FUNC_SELf); 284 } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r, 285 MACRO_FLOW_HASH_FUNC_SELf)) { 286 rtag7_macro_flow_hash_function_select = 287 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r, 288 rtag7_hash_control_2_64, 289 MACRO_FLOW_HASH_FUNC_SELf); 290 } else { 291 rtag7_macro_flow_hash_function_select = 0; 292 } 293 if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2r, 294 MACRO_FLOW_HASH_BYTE_SELf)) { 295 rtag7_macro_flow_hash_byte_sel = 296 soc_reg_field_get(unit, RTAG7_HASH_CONTROL_2r, 297 rtag7_hash_control_2, 298 MACRO_FLOW_HASH_BYTE_SELf); 299 } else if (SOC_REG_FIELD_VALID(unit, RTAG7_HASH_CONTROL_2_64r, 300 MACRO_FLOW_HASH_BYTE_SELf)) { 301 rtag7_macro_flow_hash_byte_sel = 302 soc_reg64_field32_get(unit, RTAG7_HASH_CONTROL_2_64r, 303 rtag7_hash_control_2_64, 304 MACRO_FLOW_HASH_BYTE_SELf); 305 } else { 306 rtag7_macro_flow_hash_byte_sel = 0; 307 } 308 309 /* read RTAG7 fields from hash seed registers */ 310 rtag7_hash_seed_a = 311 soc_reg_field_get(unit, RTAG7_HASH_SEED_Ar, rtag7_hash_seed_a_reg, 312 HASH_SEED_Af); 313 rtag7_hash_seed_b = 314 soc_reg_field_get(unit, RTAG7_HASH_SEED_Br, rtag7_hash_seed_b_reg, 315 HASH_SEED_Bf); 316 317 #if defined(BCM_TRIUMPH3_SUPPORT) 318 if (BCM_SUCCESS(bcm_esw_switch_control_get(unit, 319 bcmSwitchSymmetricHashControl, &symmetric_hash_control_mask))) { 320 if (symmetric_hash_control_mask & 321 (BCM_SYMMETRIC_HASH_0_IP6_ENABLE | BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) { 322 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6) && 323 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6) && 324 (sal_memcmp(pkt_info->sip6, pkt_info->dip6, BCM_IP6_ADDRLEN) < 0)) { 325 symmetric_hash_need_swap_ip6 = 1; 326 } 327 } 328 if (symmetric_hash_control_mask & 329 (BCM_SYMMETRIC_HASH_0_IP4_ENABLE | BCM_SYMMETRIC_HASH_1_IP4_ENABLE)) { 330 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP) && 331 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP) && 332 (pkt_info->sip < pkt_info->dip)) { 333 symmetric_hash_need_swap_ip4 = 1; 334 } 335 } 336 } 337 #endif /* BCM_TRIUMPH3_SUPPORT */ 338 339 /* RTAG7 tables */ 340 /* the first step is to choose the paket type and to fold the ipv6 341 * addresses in case of IPv6 packet*/ 342 343 /* option A ip folding for rtag 7 */ 344 if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 345 (pkt_info->ethertype == ETHERTYPE_IPV6)) && 346 (rtag7_disable_hash_ipv6_a == 0)) { 347 348 rtag7_a_sel = RTAG7_IPV6; 349 350 /* This section will fold the Ipv6 address to single 32 bit address 351 * by using of of the methose LSB or xor */ 352 if (rtag7_ipv6_addr_use_lsb_a) { 353 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 354 sip_a = (pkt_info->sip6[12] << 24) | 355 (pkt_info->sip6[13] << 16) | 356 (pkt_info->sip6[14] << 8) | 357 (pkt_info->sip6[15]); 358 sip_valid = TRUE; 359 } else { 360 sip_a = 0; 361 } 362 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 363 dip_a = (pkt_info->dip6[12] << 24) | 364 (pkt_info->dip6[13] << 16) | 365 (pkt_info->dip6[14] << 8) | 366 (pkt_info->dip6[15]); 367 dip_valid = TRUE; 368 } else { 369 dip_a = 0; 370 } 371 } else { 372 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 373 sip_a = 374 ((pkt_info->sip6[12] << 24) | 375 (pkt_info->sip6[13] << 16) | 376 (pkt_info->sip6[14] << 8) | 377 (pkt_info->sip6[15])) ^ 378 ((pkt_info->sip6[8] << 24) | 379 (pkt_info->sip6[9] << 16) | 380 (pkt_info->sip6[10] << 8) | 381 (pkt_info->sip6[11])) ^ 382 ((pkt_info->sip6[4] << 24) | 383 (pkt_info->sip6[5] << 16) | 384 (pkt_info->sip6[6] << 8) | 385 (pkt_info->sip6[7])) ^ 386 ((pkt_info->sip6[0] << 24) | 387 (pkt_info->sip6[1] << 16) | 388 (pkt_info->sip6[2] << 8) | 389 (pkt_info->sip6[3])); 390 sip_valid = TRUE; 391 } else { 392 sip_a = 0; 393 } 394 395 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 396 dip_a = 397 ((pkt_info->dip6[12] << 24) | 398 (pkt_info->dip6[13] << 16) | 399 (pkt_info->dip6[14] << 8) | 400 (pkt_info->dip6[15])) ^ 401 ((pkt_info->dip6[8] << 24) | 402 (pkt_info->dip6[9] << 16) | 403 (pkt_info->dip6[10] << 8) | 404 (pkt_info->dip6[11])) ^ 405 ((pkt_info->dip6[4] << 24) | 406 (pkt_info->dip6[5] << 16) | 407 (pkt_info->dip6[6] << 8) | 408 (pkt_info->dip6[7])) ^ 409 ((pkt_info->dip6[0] << 24) | 410 (pkt_info->dip6[1] << 16) | 411 (pkt_info->dip6[2] << 8) | 412 (pkt_info->dip6[3])); 413 dip_valid = TRUE; 414 } else { 415 dip_a = 0; 416 } 417 } 418 } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 419 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 420 (rtag7_disable_hash_ipv4_a == 0)) { 421 422 rtag7_a_sel = RTAG7_IPV4; 423 424 /* only one IPv4 hdr */ 425 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) { 426 sip_a = pkt_info->sip; 427 sip_valid = TRUE; 428 } else { 429 sip_a = 0; 430 } 431 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) { 432 dip_a = pkt_info->dip; 433 dip_valid = TRUE; 434 } else { 435 dip_a = 0; 436 } 437 } else { 438 rtag7_a_sel = RTAG7_L2_ONLY; 439 sip_a = dip_a = 0; 440 } 441 442 /* End of option A ip folding for rtag 7 */ 443 444 /* option B ip folding for rtag 7 */ 445 if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 446 (pkt_info->ethertype == ETHERTYPE_IPV6)) && 447 (rtag7_disable_hash_ipv6_b == 0)) { 448 449 rtag7_b_sel = RTAG7_IPV6; 450 451 /* This section will fold the Ipv6 address to single 32 bit address 452 * by using of of the methose LSB or xor */ 453 if (rtag7_ipv6_addr_use_lsb_b) { 454 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 455 sip_b = (pkt_info->sip6[12] << 24) | 456 (pkt_info->sip6[13] << 16) | 457 (pkt_info->sip6[14] << 8) | 458 (pkt_info->sip6[15]); 459 sip_valid = TRUE; 460 } else { 461 sip_b = 0; 462 } 463 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 464 dip_b = (pkt_info->dip6[12] << 24) | 465 (pkt_info->dip6[13] << 16) | 466 (pkt_info->dip6[14] << 8) | 467 (pkt_info->dip6[15]); 468 dip_valid = TRUE; 469 } else { 470 dip_b = 0; 471 } 472 } else { 473 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IPV6)) { 474 sip_b = 475 ((pkt_info->sip6[12] << 24) | 476 (pkt_info->sip6[13] << 16) | 477 (pkt_info->sip6[14] << 8) | 478 (pkt_info->sip6[15])) ^ 479 ((pkt_info->sip6[8] << 24) | 480 (pkt_info->sip6[9] << 16) | 481 (pkt_info->sip6[10] << 8) | 482 (pkt_info->sip6[11])) ^ 483 ((pkt_info->sip6[4] << 24) | 484 (pkt_info->sip6[5] << 16) | 485 (pkt_info->sip6[6] << 8) | 486 (pkt_info->sip6[7])) ^ 487 ((pkt_info->sip6[0] << 24) | 488 (pkt_info->sip6[1] << 16) | 489 (pkt_info->sip6[2] << 8) | 490 (pkt_info->sip6[3])); 491 sip_valid = TRUE; 492 } else { 493 sip_b = 0; 494 } 495 496 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IPV6)) { 497 dip_b = 498 ((pkt_info->dip6[12] << 24) | 499 (pkt_info->dip6[13] << 16) | 500 (pkt_info->dip6[14] << 8) | 501 (pkt_info->dip6[15])) ^ 502 ((pkt_info->dip6[8] << 24) | 503 (pkt_info->dip6[9] << 16) | 504 (pkt_info->dip6[10] << 8) | 505 (pkt_info->dip6[11])) ^ 506 ((pkt_info->dip6[4] << 24) | 507 (pkt_info->dip6[5] << 16) | 508 (pkt_info->dip6[6] << 8) | 509 (pkt_info->dip6[7])) ^ 510 ((pkt_info->dip6[0] << 24) | 511 (pkt_info->dip6[1] << 16) | 512 (pkt_info->dip6[2] << 8) | 513 (pkt_info->dip6[3])); 514 dip_valid = TRUE; 515 } else { 516 dip_b = 0; 517 } 518 } 519 } else if ((_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE) && 520 (pkt_info->ethertype == ETHERTYPE_IPV4)) && 521 (rtag7_disable_hash_ipv4_b == 0)) { 522 523 rtag7_b_sel = RTAG7_IPV4; 524 525 /* only one IPv4 hdr */ 526 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_IP)) { 527 sip_b = pkt_info->sip; 528 sip_valid = TRUE; 529 } else { 530 sip_b = 0; 531 } 532 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_IP)) { 533 dip_b = pkt_info->dip; 534 dip_valid = TRUE; 535 } else { 536 dip_b = 0; 537 } 538 } else { 539 rtag7_b_sel = RTAG7_L2_ONLY; 540 sip_b = dip_b = 0; 541 } 542 /* End of option B ip folding for rtag 7 */ 543 544 545 546 /* 547 * ============= 548 * RTAG7 HASHING 549 * ============= 550 */ 551 552 /* The inputs to the RTAG7 hash function were reduced in the begining 553 * of this function. 554 * This logic takes the hash inputs and computes both A and B RTAG7 555 * hash values. 556 */ 557 558 /* Change source modid/port to PORT32 space for hashing */ 559 hash_src_port = hash_res->src_port; 560 hash_src_modid = hash_res->src_modid; 561 562 /* Only if the packet was sourced by this chip, make sure to use 563 * PORT32 space modid and port if dual modid is enabled 564 * Need to do this because of front panel ports. 565 * 566 * Already handled by API gport resolve */ 567 568 /* initialize the variables */ 569 sal_memset(hash,0x0,(sizeof(uint32))*13); 570 sal_memset(hash_word,0x0,(sizeof(uint32))*7); 571 572 hash_crc16_bisync = 0; 573 hash_crc16_ccitt = 0; 574 hash_crc32 = 0; 575 hash_xor16 = 0; 576 hash_xor8 = 0; 577 hash_xor4 = 0; 578 hash_xor2 = 0; 579 hash_xor1 = 0; 580 xor32 = 0; 581 582 hash[12] = 0; 583 hash[3] = hash_src_port; 584 hash[2] = hash_src_modid & 0xff; 585 hash[1] = 0; 586 hash[0] = 0; 587 588 hash_element_valid_bits = 0x1fff; /* Init to valid fields above */ 589 590 /* option A hash calculation for rtag 7 */ 591 592 if ((rtag7_a_sel == RTAG7_IPV6) || (rtag7_a_sel == RTAG7_IPV4)) { 593 594 if (sip_valid) { 595 hash[11] = (sip_a >> 16) & 0xffff; 596 hash[10] = sip_a & 0xffff; 597 } else { 598 hash_element_valid_bits &= ~0xc00; 599 } 600 if (dip_valid) { 601 hash[9] = (dip_a >> 16) & 0xffff; 602 hash[8] = dip_a & 0xffff; 603 } else { 604 hash_element_valid_bits &= ~0x300; 605 } 606 607 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 608 hash[7] = pkt_info->vid & 0xfff; 609 } else { 610 hash_element_valid_bits &= ~0x80; 611 } 612 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) { 613 hash[6] = pkt_info->src_l4_port; 614 } else { 615 hash_element_valid_bits &= ~0x40; 616 } 617 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) { 618 hash[5] = pkt_info->dst_l4_port; 619 } else { 620 hash_element_valid_bits &= ~0x20; 621 } 622 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) { 623 hash[4] = pkt_info->protocol; 624 } else { 625 hash_element_valid_bits &= ~0x10; 626 } 627 628 /* Symmetric hash swap src/dst ipaddr/l4_port for option A */ 629 if (((rtag7_a_sel == RTAG7_IPV6) && 630 symmetric_hash_need_swap_ip6 && 631 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP6_ENABLE)) 632 || 633 ((rtag7_a_sel == RTAG7_IPV4) && 634 symmetric_hash_need_swap_ip4 && 635 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_0_IP4_ENABLE))) { 636 637 uint32 temp; 638 temp = hash[11]; hash[11] = hash[9]; hash[9] = temp; 639 temp = hash[10]; hash[10] = hash[8]; hash[8] = temp; 640 temp = hash[6]; hash[6] = hash[5]; hash[5] = temp; 641 LOG_VERBOSE(BSL_LS_BCM_COMMON, 642 (BSL_META_U(unit, 643 "Symmetric hash swap for hash A calculation.\n"))); 644 } 645 646 if ((rtag7_a_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_a) { 647 LOG_VERBOSE(BSL_LS_BCM_COMMON, 648 (BSL_META_U(unit, 649 "Hash calculation: The system is set to use ipv6 flow label" 650 " and the code can't get this info\n"))); 651 } 652 653 if (rtag7_a_sel == RTAG7_IPV4) { /* Use IPv4 BITMAPs */ 654 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 655 ((pkt_info->protocol == IP_PROT_TCP) || 656 (pkt_info->protocol == IP_PROT_UDP))) { 657 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 658 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 659 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 660 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r; 661 sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af; 662 LOG_VERBOSE(BSL_LS_BCM_COMMON, 663 (BSL_META_U(unit, 664 "Hash calculation: Bitmap is block A IPv4 TCP=UDP\n"))); 665 } else { 666 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r; 667 sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Af; 668 LOG_VERBOSE(BSL_LS_BCM_COMMON, 669 (BSL_META_U(unit, 670 "Hash calculation: Bitmap is block A IPv4 L4 tcp/udp\n"))); 671 } 672 } else { 673 sc_reg = RTAG7_HASH_FIELD_BMAP_1r; 674 sc_field = IPV4_FIELD_BITMAP_Af; 675 LOG_VERBOSE(BSL_LS_BCM_COMMON, 676 (BSL_META_U(unit, 677 "Hash calculation: Bitmap is block A IPv4 \n"))); 678 } 679 680 } else { /* Use IPv6 BITMAPs */ 681 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 682 ((pkt_info->protocol == IP_PROT_TCP) || 683 (pkt_info->protocol == IP_PROT_UDP))) { 684 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 685 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 686 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 687 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r; 688 sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Af; 689 LOG_VERBOSE(BSL_LS_BCM_COMMON, 690 (BSL_META_U(unit, 691 "Hash calculation: Bitmap is block A IPv6 TCP=UDP\n"))); 692 } else { 693 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r; 694 sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Af; 695 LOG_VERBOSE(BSL_LS_BCM_COMMON, 696 (BSL_META_U(unit, 697 "Hash calculation: Bitmap is block A IPv6 L4 tcp/udp\n"))); 698 } 699 } else { 700 sc_reg = RTAG7_HASH_FIELD_BMAP_2r; 701 sc_field = IPV6_FIELD_BITMAP_Af; 702 LOG_VERBOSE(BSL_LS_BCM_COMMON, 703 (BSL_META_U(unit, 704 "Hash calculation: Bitmap is block A IPv6 \n"))); 705 } 706 } 707 708 } else { /* Catch-all for RTAG7_L2_ONLY */ 709 710 /* L2 only hash key */ 711 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) { 712 hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1]; 713 hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3]; 714 hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5]; 715 } else { 716 hash_element_valid_bits &= ~0xe00; 717 } 718 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) { 719 hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1]; 720 hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3]; 721 hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5]; 722 } else { 723 hash_element_valid_bits &= ~0x1c0; 724 } 725 726 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) { 727 hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ? 728 pkt_info->ethertype : 0; 729 } else { 730 hash_element_valid_bits &= ~0x20; 731 } 732 733 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 734 hash[4] = pkt_info->vid & 0xfff; 735 } else { 736 hash_element_valid_bits &= ~0x10; 737 } 738 739 sc_reg = RTAG7_HASH_FIELD_BMAP_3r; 740 sc_field = L2_FIELD_BITMAP_Af; 741 LOG_VERBOSE(BSL_LS_BCM_COMMON, 742 (BSL_META_U(unit, 743 "Hash calculation: Bitmap is block A L2\n"))); 744 } 745 746 BCM_IF_ERROR_RETURN 747 (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val)); 748 hash_field_bmap_a = soc_reg_field_get(unit, sc_reg, sc_val, sc_field); 749 750 /* Pre-Processing */ 751 752 if (rtag7_pre_processing_enable_a) { 753 754 hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2); 755 hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2); 756 hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2); 757 hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2); 758 hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2); 759 hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2); 760 hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2); 761 hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2); 762 hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2); 763 hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2); 764 hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2); 765 hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2); 766 hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2); 767 768 } 769 770 if (((hash_field_bmap_a >> 12) & 0x1) == 0) { 771 hash[12] = 0; 772 } 773 774 if (rtag7_en_bin_12_overlay_a) { 775 hash_word[6] = (rtag7_hash_seed_a & 0xffff0000) | (hash[12] & 0xffff); 776 } else { 777 hash_word[6] = rtag7_hash_seed_a; 778 } 779 780 hash_res->hash_a_valid = TRUE; 781 for (elem = 11; elem >= 0; elem--) { 782 elem_bit = 1 << elem; 783 if (0 != (hash_field_bmap_a & elem_bit)) { 784 if (0 != (hash_element_valid_bits & elem_bit)) { 785 hash_word[elem/2] |= 786 ((hash[elem] & 0xffff) << (16 * (elem % 2))); 787 } else { 788 hash_res->hash_a_valid = FALSE; 789 break; 790 } 791 } 792 } 793 794 /*Calculation*/ 795 xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ 796 hash_word[2] ^ hash_word[1] ^ hash_word[0]; 797 798 hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff); 799 hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff); 800 hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf); 801 hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3); 802 hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1); 803 804 hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28); 805 hash_crc16_ccitt = _shr_crc16_ccitt_array(hash_word, 28); 806 hash_crc32 = _shr_crc32_castagnoli_array(hash_word, 28); 807 808 switch (rtag7_hash_a0_function_select) { 809 case 0: /* reserved */ 810 hash_res->rtag7_hash16_value_a_0 = 0; 811 break; 812 case 1: /* reserved */ 813 hash_res->rtag7_hash16_value_a_0 = 0; 814 break; 815 case 2: /* reserved */ 816 hash_res->rtag7_hash16_value_a_0 = 0; 817 break; 818 case 3: /* CRC16 BISYNC */ 819 hash_res->rtag7_hash16_value_a_0 = hash_crc16_bisync; 820 break; 821 case 4: /* CRC16_XOR1 */ 822 hash_res->rtag7_hash16_value_a_0 = hash_xor1 & 0x1; 823 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 824 break; 825 case 5: /* CRC16_XOR2 */ 826 hash_res->rtag7_hash16_value_a_0 = hash_xor2 & 0x3; 827 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 828 break; 829 case 6: /* CRC16_XOR4 */ 830 hash_res->rtag7_hash16_value_a_0 = hash_xor4 & 0xf; 831 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 832 break; 833 case 7: /* CRC16_XOR8 */ 834 hash_res->rtag7_hash16_value_a_0 = hash_xor8 & 0xff; 835 hash_res->rtag7_hash16_value_a_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 836 break; 837 case 8: /* XOR16 */ 838 hash_res->rtag7_hash16_value_a_0 = hash_xor16; 839 break; 840 case 9: /* CRC16_CCITT */ 841 hash_res->rtag7_hash16_value_a_0 = hash_crc16_ccitt; 842 break; 843 case 10: /* CRC32_LO */ 844 hash_res->rtag7_hash16_value_a_0 = hash_crc32 & 0xffff; 845 break; 846 case 11: /* CRC32_HI */ 847 hash_res->rtag7_hash16_value_a_0 = (hash_crc32 >> 16) & 0xffff; 848 break; 849 default: /* reserved */ 850 hash_res->rtag7_hash16_value_a_0 = 0; 851 break; 852 } 853 854 switch (rtag7_hash_a1_function_select) { 855 case 0: /* reserved */ 856 hash_res->rtag7_hash16_value_a_1 = 0; 857 break; 858 case 1: /* reserved */ 859 hash_res->rtag7_hash16_value_a_1 = 0; 860 break; 861 case 2: /* reserved */ 862 hash_res->rtag7_hash16_value_a_1 = 0; 863 break; 864 case 3: /* CRC16 BISYNC */ 865 hash_res->rtag7_hash16_value_a_1 = hash_crc16_bisync; 866 break; 867 case 4: /* CRC16_XOR1 */ 868 hash_res->rtag7_hash16_value_a_1 = hash_xor1 & 0x1; 869 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 870 break; 871 case 5: /* CRC16_XOR2 */ 872 hash_res->rtag7_hash16_value_a_1 = hash_xor2 & 0x3; 873 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 874 break; 875 case 6: /* CRC16_XOR4 */ 876 hash_res->rtag7_hash16_value_a_1 = hash_xor4 & 0xf; 877 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 878 break; 879 case 7: /* CRC16_XOR8 */ 880 hash_res->rtag7_hash16_value_a_1 = hash_xor8 & 0xff; 881 hash_res->rtag7_hash16_value_a_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 882 break; 883 case 8: /* XOR16 */ 884 hash_res->rtag7_hash16_value_a_1 = hash_xor16; 885 break; 886 case 9: /* CRC16_CCITT */ 887 hash_res->rtag7_hash16_value_a_1 = hash_crc16_ccitt; 888 break; 889 case 10: /* CRC32_LO */ 890 hash_res->rtag7_hash16_value_a_1 = hash_crc32 & 0xffff; 891 break; 892 case 11: /* CRC32_HI */ 893 hash_res->rtag7_hash16_value_a_1 = (hash_crc32 >> 16) & 0xffff; 894 break; 895 default: /* reserved */ 896 hash_res->rtag7_hash16_value_a_1 = 0; 897 break; 898 } 899 900 /* End of option A hash calculation for rtag 7 */ 901 902 /* Generation of Macro Flow Based HASH Select */ 903 /* This is used for Macro flow based Hash function selection for all consumers of RTAG7 HASH */ 904 /* Macro flow based hash function selection improves distribution among members */ 905 /* Refer Each application (ECMP, LAG, HG-TRUNK) on how this is being used */ 906 switch (rtag7_macro_flow_hash_function_select) { 907 case 0: /* reserved */ 908 macro_flow_id = 0; 909 break; 910 case 1: /* reserved */ 911 macro_flow_id = 0; 912 break; 913 case 2: /* reserved */ 914 macro_flow_id = 0; 915 break; 916 case 3: /* CRC16 BISYNC */ 917 macro_flow_id = hash_crc16_bisync; 918 break; 919 case 4: /* CRC16_XOR1 */ 920 macro_flow_id = hash_xor1 & 0x1; 921 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 922 break; 923 case 5: /* CRC16_XOR2 */ 924 macro_flow_id = hash_xor2 & 0x3; 925 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 926 break; 927 case 6: /* CRC16_XOR4 */ 928 macro_flow_id = hash_xor4 & 0xf; 929 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 930 break; 931 case 7: /* CRC16_XOR8 */ 932 macro_flow_id = hash_xor8 & 0xff; 933 macro_flow_id |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 934 break; 935 case 8: /* XOR16 */ 936 macro_flow_id = hash_xor16; 937 break; 938 case 9: /* CRC16_CCITT */ 939 macro_flow_id = hash_crc16_ccitt; 940 break; 941 case 10: /* CRC32_LO */ 942 macro_flow_id = hash_crc32 & 0xffff; 943 break; 944 case 11: /* CRC32_HI */ 945 macro_flow_id = (hash_crc32 >> 16) & 0xffff; 946 break; 947 default: /* reserved */ 948 macro_flow_id = 0; 949 break; 950 } 951 hash_res->rtag7_macro_flow_id = (rtag7_macro_flow_hash_byte_sel) ? 952 ((macro_flow_id >> 8) & 0xff) : (macro_flow_id & 0xff); 953 954 /* option B hash calculation for rtag 7 */ 955 956 /* initialize the variables */ 957 958 sal_memset(hash,0x0,(sizeof(uint32))*13); 959 sal_memset(hash_word,0x0,(sizeof(uint32))*7); 960 961 hash_crc16_bisync = 0; 962 hash_crc16_ccitt = 0; 963 hash_crc32 = 0; 964 hash_xor16 = 0; 965 hash_xor8 = 0; 966 hash_xor4 = 0; 967 hash_xor2 = 0; 968 hash_xor1 = 0; 969 xor32 = 0; 970 971 hash[12] = 0; 972 hash[3] = hash_src_port; 973 hash[2] = hash_src_modid & 0xff; 974 hash[1] = 0; 975 hash[0] = 0; 976 977 hash_element_valid_bits = 0x1fff; /* Init to valid fields above */ 978 979 /* option B hash calculation for rtag 7 */ 980 981 if ((rtag7_b_sel == RTAG7_IPV6) || (rtag7_b_sel == RTAG7_IPV4)) { 982 if (sip_valid) { 983 hash[11] = (sip_b >> 16) & 0xffff; 984 hash[10] = sip_b & 0xffff; 985 } else { 986 hash_element_valid_bits &= ~0xc00; 987 } 988 if (dip_valid) { 989 hash[9] = (dip_b >> 16) & 0xffff; 990 hash[8] = dip_b & 0xffff; 991 } else { 992 hash_element_valid_bits &= ~0x300; 993 } 994 995 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 996 hash[7] = pkt_info->vid & 0xfff; 997 } else { 998 hash_element_valid_bits &= ~0x80; 999 } 1000 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT)) { 1001 hash[6] = pkt_info->src_l4_port; 1002 } else { 1003 hash_element_valid_bits &= ~0x40; 1004 } 1005 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT)) { 1006 hash[5] = pkt_info->dst_l4_port; 1007 } else { 1008 hash_element_valid_bits &= ~0x20; 1009 } 1010 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL)) { 1011 hash[4] = pkt_info->protocol; 1012 } else { 1013 hash_element_valid_bits &= ~0x10; 1014 } 1015 1016 /* Symmetric hash swap src/dst ipaddr/l4_port for option B */ 1017 if (((rtag7_b_sel == RTAG7_IPV6) && 1018 symmetric_hash_need_swap_ip6 && 1019 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP6_ENABLE)) 1020 || 1021 ((rtag7_b_sel == RTAG7_IPV4) && 1022 symmetric_hash_need_swap_ip4 && 1023 (symmetric_hash_control_mask & BCM_SYMMETRIC_HASH_1_IP4_ENABLE))) { 1024 1025 uint32 temp; 1026 temp = hash[11]; hash[11] = hash[9]; hash[9] = temp; 1027 temp = hash[10]; hash[10] = hash[8]; hash[8] = temp; 1028 temp = hash[6]; hash[6] = hash[5]; hash[5] = temp; 1029 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1030 (BSL_META_U(unit, 1031 "Symmetric hash swap for hash B calculation.\n"))); 1032 } 1033 1034 if ((rtag7_b_sel == RTAG7_IPV6) && rtag7_en_flow_label_ipv6_b) { 1035 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1036 (BSL_META_U(unit, 1037 "Hash calculation: The system is set to use ipv6 flow label" 1038 " and the code can't get this info\n"))); 1039 } 1040 1041 if (rtag7_b_sel == RTAG7_IPV4) { /* Use IPv4 BITMAPs */ 1042 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 1043 ((pkt_info->protocol == IP_PROT_TCP) || 1044 (pkt_info->protocol == IP_PROT_UDP))) { 1045 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 1046 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 1047 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 1048 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_1r; 1049 sc_field = IPV4_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf; 1050 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1051 (BSL_META_U(unit, 1052 "Hash calculation: Bitmap is block B IPv4 TCP=UDP\n"))); 1053 } else { 1054 sc_reg = RTAG7_IPV4_TCP_UDP_HASH_FIELD_BMAP_2r; 1055 sc_field = IPV4_TCP_UDP_FIELD_BITMAP_Bf; 1056 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1057 (BSL_META_U(unit, 1058 "Hash calculation: Bitmap is block B IPv4 L4 tcp/udp\n"))); 1059 } 1060 } else { 1061 sc_reg = RTAG7_HASH_FIELD_BMAP_1r; 1062 sc_field = IPV4_FIELD_BITMAP_Bf; 1063 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1064 (BSL_META_U(unit, 1065 "Hash calculation: Bitmap is block B IPv4\n"))); 1066 } 1067 1068 } else { /* Use IPv6 BITMAPs */ 1069 1070 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, PROTOCOL) && 1071 ((pkt_info->protocol == IP_PROT_TCP) || 1072 (pkt_info->protocol == IP_PROT_UDP))) { 1073 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_L4_PORT) && 1074 _BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_L4_PORT) && 1075 (pkt_info->src_l4_port == pkt_info->dst_l4_port)) { 1076 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_1r; 1077 sc_field = IPV6_TCP_UDP_SRC_EQ_DST_FIELD_BITMAP_Bf; 1078 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1079 (BSL_META_U(unit, 1080 "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n"))); 1081 } else { 1082 sc_reg = RTAG7_IPV6_TCP_UDP_HASH_FIELD_BMAP_2r; 1083 sc_field = IPV6_TCP_UDP_FIELD_BITMAP_Bf; 1084 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1085 (BSL_META_U(unit, 1086 "Hash calculation: Bitmap is block B IPv6 TCP=UDP\n"))); 1087 } 1088 } else { 1089 sc_reg = RTAG7_HASH_FIELD_BMAP_2r; 1090 sc_field = IPV6_FIELD_BITMAP_Bf; 1091 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1092 (BSL_META_U(unit, 1093 "Hash calculation: Bitmap is block B IPv6\n"))); 1094 } 1095 } 1096 } else { /* Catch-all for RTAG7_L2_ONLY */ 1097 1098 /* L2 only hash key */ 1099 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_MAC)) { 1100 hash[11] = (pkt_info->src_mac[0] << 8) | pkt_info->src_mac[1]; 1101 hash[10] = (pkt_info->src_mac[2] << 8) | pkt_info->src_mac[3]; 1102 hash[9] = (pkt_info->src_mac[4] << 8) | pkt_info->src_mac[5]; 1103 } else { 1104 hash_element_valid_bits &= ~0xe00; 1105 } 1106 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, DST_MAC)) { 1107 hash[8] = (pkt_info->dst_mac[0] << 8) | pkt_info->dst_mac[1]; 1108 hash[7] = (pkt_info->dst_mac[2] << 8) | pkt_info->dst_mac[3]; 1109 hash[6] = (pkt_info->dst_mac[4] << 8) | pkt_info->dst_mac[5]; 1110 } else { 1111 hash_element_valid_bits &= ~0x1c0; 1112 } 1113 1114 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, ETHERTYPE)) { 1115 hash[5] = (pkt_info->ethertype >= ETHERTYPE_MIN) ? 1116 pkt_info->ethertype : 0; 1117 } else { 1118 hash_element_valid_bits &= ~0x20; 1119 } 1120 1121 if (_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, VLAN)) { 1122 hash[4] = pkt_info->vid & 0xfff; 1123 } else { 1124 hash_element_valid_bits &= ~0x10; 1125 } 1126 1127 sc_reg = RTAG7_HASH_FIELD_BMAP_3r; 1128 sc_field = L2_FIELD_BITMAP_Bf; 1129 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1130 (BSL_META_U(unit, 1131 "Hash calculation: Bitmap is block B L2\n"))); 1132 } 1133 1134 BCM_IF_ERROR_RETURN 1135 (soc_reg32_get(unit, sc_reg, REG_PORT_ANY, 0, &sc_val)); 1136 hash_field_bmap_b = soc_reg_field_get(unit, sc_reg, sc_val, sc_field); 1137 /* Pre-Processing */ 1138 1139 if (rtag7_pre_processing_enable_b) { 1140 1141 hash[12] = hash[12] ^ (hash[12] >> 3) ^ (hash[12] << 2); 1142 hash[11] = hash[11] ^ (hash[11] >> 3) ^ (hash[11] << 2); 1143 hash[10] = hash[10] ^ (hash[10] >> 3) ^ (hash[10] << 2); 1144 hash[9] = hash[9] ^ (hash[9] >> 3) ^ (hash[9] << 2); 1145 hash[8] = hash[8] ^ (hash[8] >> 3) ^ (hash[8] << 2); 1146 hash[7] = hash[7] ^ (hash[7] >> 3) ^ (hash[7] << 2); 1147 hash[6] = hash[6] ^ (hash[6] >> 3) ^ (hash[6] << 2); 1148 hash[5] = hash[5] ^ (hash[5] >> 3) ^ (hash[5] << 2); 1149 hash[4] = hash[4] ^ (hash[4] >> 3) ^ (hash[4] << 2); 1150 hash[3] = hash[3] ^ (hash[3] >> 3) ^ (hash[3] << 2); 1151 hash[2] = hash[2] ^ (hash[2] >> 3) ^ (hash[2] << 2); 1152 hash[1] = hash[1] ^ (hash[1] >> 3) ^ (hash[1] << 2); 1153 hash[0] = hash[0] ^ (hash[0] >> 3) ^ (hash[0] << 2); 1154 1155 } 1156 1157 if (((hash_field_bmap_b >> 12) & 0x1) == 0) { 1158 hash[12] = 0; 1159 } 1160 1161 if (rtag7_en_bin_12_overlay_b) { 1162 hash_word[6] = (rtag7_hash_seed_b & 0xffff0000) | (hash[12] & 0xffff); 1163 } else { 1164 hash_word[6] = rtag7_hash_seed_b; 1165 } 1166 1167 hash_res->hash_b_valid = TRUE; 1168 for (elem = 11; elem >= 0; elem--) { 1169 elem_bit = 1 << elem; 1170 if (0 != (hash_field_bmap_b & elem_bit)) { 1171 if (0 != (hash_element_valid_bits & elem_bit)) { 1172 hash_word[elem/2] |= 1173 ((hash[elem] & 0xffff) << (16 * (elem % 2))); 1174 } else { 1175 hash_res->hash_b_valid = FALSE; 1176 break; 1177 } 1178 } 1179 } 1180 1181 xor32 = hash_word[6] ^ hash_word[5] ^ hash_word[4] ^ hash_word[3] ^ hash_word[2] ^ hash_word[1] ^ hash_word[0]; 1182 hash_xor16 = (xor32 & 0xffff) ^ ((xor32 >> 16) & 0xffff); 1183 hash_xor8 = (hash_xor16 & 0xff) ^ ((hash_xor16 >> 8) & 0xff); 1184 hash_xor4 = (hash_xor8 & 0xf) ^ ((hash_xor8 >> 4) & 0xf); 1185 hash_xor2 = (hash_xor4 & 0x3) ^ ((hash_xor4 >> 2) & 0x3); 1186 hash_xor1 = (hash_xor2 & 0x1) ^ ((hash_xor2 >> 1) & 0x1); 1187 1188 hash_crc16_bisync = _shr_crc16_draco_array(hash_word, 28); 1189 hash_crc16_ccitt = _shr_crc16_ccitt_array(hash_word, 28); 1190 hash_crc32 = _shr_crc32_castagnoli_array(hash_word, 28); 1191 1192 switch (rtag7_hash_b0_function_select) { 1193 case 0: /* reserved */ 1194 hash_res->rtag7_hash16_value_b_0 = 0; 1195 break; 1196 case 1: /* reserved */ 1197 hash_res->rtag7_hash16_value_b_0 = 0; 1198 break; 1199 case 2: /* reserved */ 1200 hash_res->rtag7_hash16_value_b_0 = 0; 1201 break; 1202 case 3: /* CRC16 BISYNC */ 1203 hash_res->rtag7_hash16_value_b_0 = hash_crc16_bisync; 1204 break; 1205 case 4: /* CRC16_XOR1 */ 1206 hash_res->rtag7_hash16_value_b_0 = hash_xor1 & 0x1; 1207 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1208 break; 1209 case 5: /* CRC16_XOR2 */ 1210 hash_res->rtag7_hash16_value_b_0 = hash_xor2 & 0x3; 1211 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1212 break; 1213 case 6: /* CRC16_XOR4 */ 1214 hash_res->rtag7_hash16_value_b_0 = hash_xor4 & 0xf; 1215 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1216 break; 1217 case 7: /* CRC16_XOR8 */ 1218 hash_res->rtag7_hash16_value_b_0 = hash_xor8 & 0xff; 1219 hash_res->rtag7_hash16_value_b_0 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1220 break; 1221 case 8: /* XOR16 */ 1222 hash_res->rtag7_hash16_value_b_0 = hash_xor16; 1223 break; 1224 case 9: /* CRC16_CCITT */ 1225 hash_res->rtag7_hash16_value_b_0 = hash_crc16_ccitt; 1226 break; 1227 case 10: /* CRC32_LO */ 1228 hash_res->rtag7_hash16_value_b_0 = hash_crc32 & 0xffff; 1229 break; 1230 case 11: /* CRC32_HI */ 1231 hash_res->rtag7_hash16_value_b_0 = (hash_crc32 >> 16) & 0xffff; 1232 break; 1233 default: /* reserved */ 1234 hash_res->rtag7_hash16_value_b_0 = 0; 1235 break; 1236 } 1237 1238 switch (rtag7_hash_b1_function_select) { 1239 case 0: /* reserved */ 1240 hash_res->rtag7_hash16_value_b_1 = 0; 1241 break; 1242 case 1: /* reserved */ 1243 hash_res->rtag7_hash16_value_b_1 = 0; 1244 break; 1245 case 2: /* reserved */ 1246 hash_res->rtag7_hash16_value_b_1 = 0; 1247 break; 1248 case 3: /* CRC16 BISYNC */ 1249 hash_res->rtag7_hash16_value_b_1 = hash_crc16_bisync; 1250 break; 1251 case 4: /* CRC16_XOR1 */ 1252 hash_res->rtag7_hash16_value_b_1 = hash_xor1 & 0x1; 1253 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1254 break; 1255 case 5: /* CRC16_XOR2 */ 1256 hash_res->rtag7_hash16_value_b_1 = hash_xor2 & 0x3; 1257 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1258 break; 1259 case 6: /* CRC16_XOR4 */ 1260 hash_res->rtag7_hash16_value_b_1 = hash_xor4 & 0xf; 1261 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1262 break; 1263 case 7: /* CRC16_XOR8 */ 1264 hash_res->rtag7_hash16_value_b_1 = hash_xor8 & 0xff; 1265 hash_res->rtag7_hash16_value_b_1 |= (((hash_crc16_bisync >> 8) & 0xff) << 8); 1266 break; 1267 case 8: /* XOR16 */ 1268 hash_res->rtag7_hash16_value_b_1 = hash_xor16; 1269 break; 1270 case 9: /* CRC16_CCITT */ 1271 hash_res->rtag7_hash16_value_b_1 = hash_crc16_ccitt; 1272 break; 1273 case 10: /* CRC32_LO */ 1274 hash_res->rtag7_hash16_value_b_1 = hash_crc32 & 0xffff; 1275 break; 1276 case 11: /* CRC32_HI */ 1277 hash_res->rtag7_hash16_value_b_1 = (hash_crc32 >> 16) & 0xffff; 1278 break; 1279 default: /* reserved */ 1280 hash_res->rtag7_hash16_value_b_1 = 0; 1281 break; 1282 } 1283 1284 /* End of option B hash calculation for rtag 7 */ 1285 return BCM_E_NONE; 1286 } 1287 1288 /* 1289 * Function: 1290 * select_td2_hash_subfield 1291 * Description: 1292 * read hashing values of hash A0,A1,B0,B1,LBID 1293 * from sub_sel_block pointed by hash_sub_sel 1294 * Parameters: 1295 * concat - tell whether is in concatenated mode or not 1296 * hash_sub_sel - tell which hash sub to choose 1297 * seleted_subfiled - saves subfield value 1298 * hash_Base - internal data where hashing informaiton is stored 1299 * Returns: 1300 * BCM_E_xxxx 1301 * Note: if hash_sub_sel and hash_Base->hash_x_valid mismatches, 1302 * it will return BCM_E_PARAM 1303 */ 1304 STATIC int 1305 select_td2_hash_subfield(uint32 concat, int hash_sub_sel, uint64 *selected_subfield, 1306 bcm_rtag7_base_hash_t *hash_Base) 1307 { 1308 int rv = BCM_E_NONE; 1309 1310 switch (hash_sub_sel) { 1311 case 0: /* select pkt hash A */ 1312 if (concat) { 1313 COMPILER_64_SET(*selected_subfield, 1314 (hash_Base->rtag7_hash16_value_b_1 << 16 | hash_Base->rtag7_hash16_value_b_0), 1315 (hash_Base->rtag7_hash16_value_a_1 << 16 | hash_Base->rtag7_hash16_value_a_0)); 1316 if (!hash_Base->hash_a_valid || !hash_Base->hash_b_valid) { 1317 /* Missing paramter in input */ 1318 rv = BCM_E_PARAM; 1319 } 1320 } else { 1321 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0); 1322 if (!hash_Base->hash_a_valid) { 1323 /* Missing paramter in input */ 1324 rv = BCM_E_PARAM; 1325 } 1326 } 1327 break; 1328 1329 case 1: /* select pkt hash B */ 1330 if (concat) { 1331 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn); 1332 } else { 1333 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_0); 1334 if (!hash_Base->hash_b_valid) { 1335 /* Missing paramter in input */ 1336 rv = BCM_E_PARAM; 1337 } 1338 } 1339 break; 1340 1341 case 2: /* select port LBN */ 1342 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn); 1343 break; 1344 1345 case 3: /* select destination port id or hash A */ 1346 if (concat) { 1347 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_port_lbn); 1348 } else { 1349 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_0); 1350 if (!hash_Base->hash_a_valid) { 1351 /* Missing paramter in input */ 1352 rv = BCM_E_PARAM; 1353 } 1354 } 1355 break; 1356 1357 case 4: /* select LBID from module header or from SW1 stage */ 1358 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash); 1359 if (!hash_Base->lbid_hash_valid) { 1360 /* LBID setting isn't RTAG7 */ 1361 rv = BCM_E_CONFIG; 1362 } 1363 break; 1364 1365 case 5: /* select LBID from SW1 stage */ 1366 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_lbid_hash); 1367 if (!hash_Base->lbid_hash_valid) { 1368 /* LBID setting isn't RTAG7 */ 1369 rv = BCM_E_CONFIG; 1370 } 1371 break; 1372 1373 case 6: 1374 if (concat) { 1375 COMPILER_64_ZERO(*selected_subfield); 1376 } else { 1377 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_a_1); 1378 if (!hash_Base->hash_a_valid) { 1379 /* Missing paramter in input */ 1380 rv = BCM_E_PARAM; 1381 } 1382 } 1383 break; 1384 1385 case 7: 1386 if (concat) { 1387 COMPILER_64_ZERO(*selected_subfield); 1388 } else { 1389 COMPILER_64_SET(*selected_subfield, 0, hash_Base->rtag7_hash16_value_b_1); 1390 if (!hash_Base->hash_b_valid) { 1391 /* Missing paramter in input */ 1392 rv = BCM_E_PARAM; 1393 } 1394 } 1395 break; 1396 1397 default: 1398 return BCM_E_PARAM; 1399 } 1400 1401 return rv; 1402 } 1403 1404 /* 1405 * Function: 1406 * main_td2_compute_lbid 1407 * Description: 1408 * get lbid value that is used in hashing calculation 1409 * if flow hash is used, get SUB_SEL_LBID_OR_ENTROPY_LABELf and 1410 * OFFSET_LBID_OR_ENTROPY_LABELf from RTAG7_FLOW_BASED_HASHm 1411 * if flow hash is not used, get SUB_SEL_LBID_(non)UCf and 1412 * OFFSET_LBID_(non)UCf from RTAG7_PORT_BASED_HASHm 1413 * Parameters: 1414 * unit - StrataSwitch PCI device unit number (driver internal). 1415 * hash_Base - internal data that lbid_hash_value is stored 1416 * Returns: 1417 * BCM_E_xxxx 1418 * Note: bcmSwitchLoadBalanceHashSelect must be set to 7 1419 * and bcmSwitchLoadBalanceHashSet0UnicastOffset must be set properly. 1420 * if lbid_hash_sub_sel and hash_Base->hash_x_valid mismatches, 1421 * then lbid_hash_val saved in hash_Base will be 0 1422 */ 1423 STATIC int 1424 main_td2_compute_lbid(int unit, bcm_rtag7_base_hash_t *hash_Base) 1425 { 1426 /*regular var declaration*/ 1427 uint32 lbid_hash_sub_sel; 1428 uint32 lbid_hash_offset; 1429 uint32 lbid_hash_value = 0; 1430 1431 /*register var declaration*/ 1432 int lbid_rtag = 0; 1433 uint64 ing_hash_config_reg; 1434 int rv = BCM_E_NONE; 1435 uint32 rtag7_hash_sel; 1436 uint32 port_based_hash_index; 1437 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1438 int hash_index = 0; 1439 #endif 1440 rtag7_port_based_hash_entry_t 1441 port_based_hash_entry; 1442 rtag7_flow_based_hash_entry_t 1443 flow_based_hash_entry; 1444 uint8 loadbalance_use_flow_hash_uc = 0; 1445 uint8 loadbalance_use_flow_hash_nonuc = 0; 1446 1447 /* get the lbid rtag value */ 1448 if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, LBID_RTAGf)) { 1449 rv = READ_ING_CONFIG_64r(unit, &ing_hash_config_reg); 1450 if (BCM_SUCCESS(rv)) { 1451 lbid_rtag = soc_reg64_field32_get(unit, ING_CONFIG_64r, 1452 ing_hash_config_reg, LBID_RTAGf); 1453 } else { 1454 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1455 (BSL_META_U(unit, 1456 "compute_lbid fail, lbid_rtag=0\n"))); 1457 lbid_rtag =0; 1458 } 1459 } else { 1460 rv = (BCM_E_UNAVAIL); 1461 } 1462 1463 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1464 (BSL_META_U(unit, 1465 "lbid_rtag = %d\n"), 1466 lbid_rtag)); 1467 /* ******************* LBID computation ************************* */ 1468 1469 if (lbid_rtag == 7) { 1470 /* check if flow hash is used for UC*/ 1471 SOC_IF_ERROR_RETURN 1472 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1473 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_UCf)) { 1474 loadbalance_use_flow_hash_uc = 1475 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1476 rtag7_hash_sel, USE_FLOW_SEL_LBID_UCf); 1477 } else { 1478 loadbalance_use_flow_hash_uc = 0; 1479 } 1480 1481 /* check if flow hash is used for NONUC*/ 1482 SOC_IF_ERROR_RETURN 1483 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1484 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_LBID_NONUCf)) { 1485 loadbalance_use_flow_hash_nonuc = 1486 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1487 rtag7_hash_sel, USE_FLOW_SEL_LBID_NONUCf); 1488 } else { 1489 loadbalance_use_flow_hash_nonuc = 0; 1490 } 1491 1492 /* RTAG7 hash computation */ 1493 if ((loadbalance_use_flow_hash_nonuc&& (hash_Base->is_nonuc == 0)) || 1494 (loadbalance_use_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 1495 SOC_IF_ERROR_RETURN( 1496 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 1497 (hash_Base->rtag7_macro_flow_id & 0xff), 1498 &flow_based_hash_entry)); 1499 1500 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 1501 UC and NONUC */ 1502 lbid_hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1503 &flow_based_hash_entry, SUB_SEL_LBID_OR_ENTROPY_LABELf); 1504 lbid_hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1505 &flow_based_hash_entry, OFFSET_LBID_OR_ENTROPY_LABELf); 1506 1507 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 1508 if (hash_Base->dev_src_port < 0) { 1509 int field_count = 0; 1510 soc_field_t fields[2]; 1511 uint32 values[2]; 1512 bcm_gport_t gport; 1513 1514 BCM_GPORT_PROXY_SET(gport, 1515 hash_Base->src_modid, hash_Base->src_port); 1516 1517 if (hash_Base->is_nonuc) { 1518 fields[0] = SUB_SEL_LBID_NONUCf ; 1519 field_count++; 1520 fields[1] = OFFSET_LBID_NONUCf; 1521 field_count++; 1522 } else { 1523 fields[0] = SUB_SEL_LBID_UCf ; 1524 field_count++; 1525 fields[1] = OFFSET_LBID_UCf; 1526 field_count++; 1527 } 1528 PORT_LOCK(unit); 1529 rv = bcm_esw_port_lport_fields_get(unit, gport, 1530 LPORT_PROFILE_RTAG7_TAB, 1531 field_count, fields, values); 1532 PORT_UNLOCK(unit); 1533 if (BCM_FAILURE(rv)) { 1534 return rv; 1535 } 1536 lbid_hash_sub_sel = values[0]; 1537 lbid_hash_offset = values[1]; 1538 } else { 1539 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1540 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 1541 BCM_IF_ERROR_RETURN 1542 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 1543 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 1544 port_based_hash_index = (uint32) hash_index; 1545 } else 1546 #endif 1547 { 1548 port_based_hash_index = hash_Base->dev_src_port + 1549 soc_mem_index_count(unit, LPORT_TABm); 1550 } 1551 SOC_IF_ERROR_RETURN( 1552 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 1553 port_based_hash_index, &port_based_hash_entry)); 1554 if (hash_Base->is_nonuc) { 1555 lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1556 &port_based_hash_entry, SUB_SEL_LBID_NONUCf); 1557 lbid_hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1558 &port_based_hash_entry, OFFSET_LBID_NONUCf); 1559 } else { 1560 lbid_hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1561 &port_based_hash_entry, SUB_SEL_LBID_UCf); 1562 lbid_hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1563 &port_based_hash_entry, OFFSET_LBID_UCf); 1564 } 1565 } 1566 } else { 1567 lbid_hash_sub_sel = 0; 1568 lbid_hash_offset = 0; 1569 } 1570 1571 switch (lbid_hash_sub_sel) { 1572 1573 case 0: /* use pkt hash A */ 1574 lbid_hash_value = hash_Base->rtag7_hash16_value_a_0; 1575 if (!hash_Base->hash_a_valid) { 1576 /* Missing paramter in input */ 1577 rv = BCM_E_PARAM; 1578 } 1579 break; 1580 1581 case 1: /* use pkt hash B */ 1582 lbid_hash_value = hash_Base->rtag7_hash16_value_b_0; 1583 if (!hash_Base->hash_b_valid) { 1584 /* Missing paramter in input */ 1585 rv = BCM_E_PARAM; 1586 } 1587 break; 1588 1589 case 2: /* Use LBN */ 1590 lbid_hash_value = hash_Base->rtag7_port_lbn; 1591 break; 1592 1593 case 3: /* Use Destination PORTID or hash A */ 1594 lbid_hash_value = hash_Base->rtag7_hash16_value_a_0; 1595 if (!hash_Base->hash_a_valid) { 1596 /* Missing paramter in input */ 1597 rv = BCM_E_PARAM; 1598 } 1599 break; 1600 1601 case 4: /* Use LBID */ 1602 /* Higig lookup use mh_higig2_lbid */ 1603 1604 lbid_hash_value = 0; 1605 break; 1606 1607 case 5: 1608 lbid_hash_value = 0; 1609 break; 1610 1611 case 6: 1612 lbid_hash_value = hash_Base->rtag7_hash16_value_a_1; 1613 if (!hash_Base->hash_a_valid) { 1614 /* Missing paramter in input */ 1615 rv = BCM_E_PARAM; 1616 } 1617 break; 1618 1619 case 7: 1620 lbid_hash_value = hash_Base->rtag7_hash16_value_b_1; 1621 if (!hash_Base->hash_b_valid) { 1622 /* Missing paramter in input */ 1623 rv = BCM_E_PARAM; 1624 } 1625 break; 1626 } 1627 1628 /* 1629 * set up the hash value so that the LSB bits are 1630 * barrel shifted in case offset > 8. 1631 */ 1632 lbid_hash_value |= ((lbid_hash_value & 0xffff) << 16); 1633 1634 /* Only UC hash offsets apply to ECMP */ 1635 lbid_hash_value = (lbid_hash_value >> lbid_hash_offset); 1636 1637 hash_Base->rtag7_lbid_hash = (lbid_hash_value & 0xff); 1638 hash_Base->lbid_hash_valid = TRUE; 1639 } else { /* LBID rtag is 0-6 */ 1640 /* this function not support the rtag 0-6 */ 1641 1642 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1643 (BSL_META_U(unit, 1644 "Hash calculation: This function doesn't support rtag 0 6" 1645 " pls change register ING_CONFIG.LBID_RTAG to value 7\n"))); 1646 hash_Base->rtag7_lbid_hash = 0; 1647 hash_Base->lbid_hash_valid = FALSE; 1648 } 1649 1650 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1651 (BSL_META_U(unit, 1652 "lbid_hash_val=%d, valid=%d\n"), 1653 hash_Base->rtag7_lbid_hash, hash_Base->lbid_hash_valid)); 1654 1655 return rv; 1656 /* ******************* END of LBID computation ************************* */ 1657 } 1658 1659 #ifdef INCLUDE_L3 1660 /* 1661 * Function: 1662 * compute_td2_ecmp_hash 1663 * Description: 1664 * get ecmp hash value using SUB_SEL_ECMPf and OFFSET_ECMPf 1665 * if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASHm 1666 * if flow hash is not used, get subsel and offset from RTAG7_PORT_BASED_HASHm 1667 * Parameters: 1668 * unit - StrataSwitch PCI device unit number (driver internal). 1669 * hash_Base - internal data where ecmp hash value is stored 1670 * Returns: 1671 * BCM_E_xxxx 1672 */ 1673 STATIC int 1674 compute_td2_ecmp_hash(int unit, uint32 flags, bcm_rtag7_base_hash_t *hash_Base, 1675 uint32 *hash_value) 1676 { 1677 /*regular var declaration*/ 1678 uint32 hash_sub_sel; 1679 uint32 hash_offset; 1680 uint64 hash_subfield; 1681 uint32 hash_subfield_width; 1682 uint8 rtag7_ecmp_use_macro_flow_hash; 1683 uint8 ecmp_hash_use_rtag7; 1684 uint32 rtag7_hash_sel; 1685 uint32 hash_control; 1686 uint32 concat; 1687 uint32 port_based_hash_index; 1688 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1689 int hash_index = 0; 1690 #endif 1691 int sub_sel_f = SUB_SEL_ECMPf; 1692 int ecmp_offset_f = OFFSET_ECMPf ; 1693 int concat_f = CONCATENATE_HASH_FIELDS_ECMPf ; 1694 int ecmp_hash_control_f = ECMP_HASH_USE_RTAG7f; 1695 int rtag7_ecmp_hash_sel_f = USE_FLOW_SEL_ECMPf; 1696 rtag7_port_based_hash_entry_t 1697 port_based_hash_entry; 1698 rtag7_flow_based_hash_entry_t 1699 flow_based_hash_entry; 1700 int rv = BCM_E_NONE; 1701 1702 #if defined(BCM_RIOT_SUPPORT) || defined (BCM_MULTI_LEVEL_ECMP_SUPPORT) 1703 if (((soc_feature(unit, soc_feature_riot) || 1704 soc_feature(unit, soc_feature_multi_level_ecmp)) && 1705 flags & BCM_SWITCH_PKT_INFO_HASH_OVERLAY)) { 1706 1707 sub_sel_f = SUB_SEL_ECMP_LEVEL1f; 1708 ecmp_offset_f = OFFSET_ECMP_LEVEL1f ; 1709 concat_f = CONCATENATE_HASH_FIELDS_ECMP_LEVEL1f ; 1710 ecmp_hash_control_f = ECMP1_HASH_USE_RTAG7f; 1711 rtag7_ecmp_hash_sel_f = USE_FLOW_SEL_ECMP1f; 1712 } 1713 #endif 1714 /* Select between non-RTAG7 hash value and RTAG7 hash value */ 1715 SOC_IF_ERROR_RETURN 1716 (READ_HASH_CONTROLr(unit, &hash_control)); 1717 ecmp_hash_use_rtag7 = 1718 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 1719 ecmp_hash_control_f); 1720 1721 if (ecmp_hash_use_rtag7 == 0) { 1722 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1723 (BSL_META_U(unit, 1724 "ECMP Hash calculation: non rtag7 calc not supported\n"))); 1725 *hash_value = 0; 1726 return BCM_E_NONE; 1727 } 1728 1729 /* check if flow hash is used*/ 1730 SOC_IF_ERROR_RETURN 1731 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1732 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, rtag7_ecmp_hash_sel_f)) { 1733 rtag7_ecmp_use_macro_flow_hash = 1734 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1735 rtag7_hash_sel, rtag7_ecmp_hash_sel_f); 1736 } else { 1737 rtag7_ecmp_use_macro_flow_hash = 0; 1738 } 1739 1740 /* RTAG7 hash computation */ 1741 if (rtag7_ecmp_use_macro_flow_hash) { 1742 SOC_IF_ERROR_RETURN( 1743 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 1744 (hash_Base->rtag7_macro_flow_id & 0xff), 1745 &flow_based_hash_entry)); 1746 1747 /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */ 1748 /* For future designs this logic can be placed in RSEL1 */ 1749 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1750 &flow_based_hash_entry, sub_sel_f); 1751 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1752 &flow_based_hash_entry, ecmp_offset_f); 1753 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1754 &flow_based_hash_entry, concat_f); 1755 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 1756 if (hash_Base->dev_src_port < 0) { 1757 int field_count = 0; 1758 soc_field_t fields[3]; 1759 uint32 values[3]; 1760 bcm_gport_t gport; 1761 1762 BCM_GPORT_PROXY_SET(gport, 1763 hash_Base->src_modid, hash_Base->src_port); 1764 1765 fields[0] = sub_sel_f; 1766 field_count++; 1767 fields[1] = ecmp_offset_f; 1768 field_count++; 1769 fields[2] = concat_f; 1770 field_count++; 1771 PORT_LOCK(unit); 1772 rv = bcm_esw_port_lport_fields_get(unit, gport, 1773 LPORT_PROFILE_RTAG7_TAB, 1774 field_count, fields, values); 1775 PORT_UNLOCK(unit); 1776 if (BCM_FAILURE(rv)) { 1777 return rv; 1778 } 1779 hash_sub_sel = values[0]; 1780 hash_offset = values[1]; 1781 concat = values[2]; 1782 } else { 1783 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1784 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 1785 BCM_IF_ERROR_RETURN 1786 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 1787 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 1788 port_based_hash_index = (uint32) hash_index; 1789 } else 1790 #endif 1791 { 1792 port_based_hash_index = hash_Base->dev_src_port + 1793 soc_mem_index_count(unit, LPORT_TABm); 1794 } 1795 SOC_IF_ERROR_RETURN( 1796 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 1797 port_based_hash_index, &port_based_hash_entry)); 1798 1799 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1800 &port_based_hash_entry, sub_sel_f); 1801 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1802 &port_based_hash_entry, ecmp_offset_f); 1803 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1804 &port_based_hash_entry, concat_f); 1805 } 1806 } else { 1807 hash_sub_sel = 0; 1808 hash_offset = 0; 1809 concat = 0; 1810 } 1811 1812 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1813 (BSL_META_U(unit, 1814 "ecmp hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 1815 hash_sub_sel, hash_offset, concat)); 1816 BCM_IF_ERROR_RETURN 1817 (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 1818 1819 hash_subfield_width = concat ? 64 : 16; 1820 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 1821 1822 /* Barrel shift the hash subfield, then take the LSB 16 bits */ 1823 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 1824 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 1825 *hash_value &= 0xffff; 1826 1827 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1828 (BSL_META_U(unit, 1829 "ecmp hash val=%d\n"), 1830 *hash_value)); 1831 1832 return BCM_E_NONE; 1833 /* ***************** END of ECMP HASH CALCULATIONS. ************************ */ 1834 } 1835 1836 /* 1837 * Function: 1838 * compute_td2_ecmp_rh_hash 1839 * Description: 1840 * get ecmp rh hash value using SUB_SEL_RH_ECMPf and OFFSET_RH_ECMPf 1841 * if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASHm 1842 * if flow hash is not used, get subsel and offset from RTAG7_PORT_BASED_HASHm 1843 * Parameters: 1844 * unit - StrataSwitch PCI device unit number (driver internal). 1845 * hash_Base - internal data where rh ecmp hash value is stored 1846 * Returns: 1847 * BCM_E_xxxx 1848 */ 1849 STATIC int 1850 compute_td2_ecmp_rh_hash(int unit, bcm_rtag7_base_hash_t *hash_Base, 1851 uint32 *hash_value) 1852 { 1853 /*regular var declaration*/ 1854 uint32 hash_sub_sel; 1855 uint32 hash_offset; 1856 uint64 hash_subfield; 1857 uint32 hash_subfield_width; 1858 uint8 rtag7_ecmp_use_macro_flow_hash; 1859 uint8 ecmp_hash_use_rtag7; 1860 uint32 rtag7_hash_sel; 1861 uint32 hash_control; 1862 uint32 concat; 1863 rtag7_flow_based_hash_entry_t 1864 flow_based_hash_entry; 1865 rtag7_port_based_hash_entry_t 1866 port_based_hash_entry; 1867 uint32 port_based_hash_index; 1868 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1869 int hash_index = 0; 1870 #endif 1871 int rv = BCM_E_NONE; 1872 1873 /* Select between non-RTAG7 hash value and RTAG7 hash value */ 1874 SOC_IF_ERROR_RETURN 1875 (READ_HASH_CONTROLr(unit, &hash_control)); 1876 ecmp_hash_use_rtag7 = 1877 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 1878 ECMP_HASH_USE_RTAG7f); 1879 1880 if (ecmp_hash_use_rtag7 == 0) { 1881 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1882 (BSL_META_U(unit, 1883 "ECMP RH Hash calculation: non rtag7 calc not supported\n"))); 1884 *hash_value = 0; 1885 return BCM_E_NONE; 1886 } 1887 1888 /* check if is uses flow hash */ 1889 SOC_IF_ERROR_RETURN 1890 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 1891 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_RH_ECMPf)) { 1892 rtag7_ecmp_use_macro_flow_hash = 1893 soc_reg_field_get(unit, RTAG7_HASH_SELr, 1894 rtag7_hash_sel, USE_FLOW_SEL_RH_ECMPf); 1895 } else { 1896 /* A0 bincomp value */ 1897 rtag7_ecmp_use_macro_flow_hash = 0; 1898 } 1899 1900 1901 /* RTAG7 hash computation */ 1902 if (rtag7_ecmp_use_macro_flow_hash) { 1903 SOC_IF_ERROR_RETURN( 1904 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 1905 (hash_Base->rtag7_macro_flow_id & 0xff), 1906 &flow_based_hash_entry)); 1907 1908 /* Generating RTAG7 Macro Flow Based Hash Subsel and Offset for use in RSEL1 Stage */ 1909 /* For future designs this logic can be placed in RSEL1 */ 1910 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1911 &flow_based_hash_entry, SUB_SEL_ECMPf); 1912 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1913 &flow_based_hash_entry, OFFSET_ECMPf); 1914 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 1915 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_ECMPf); 1916 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 1917 if (hash_Base->dev_src_port < 0) { 1918 int field_count = 0; 1919 soc_field_t fields[3]; 1920 uint32 values[3]; 1921 bcm_gport_t gport; 1922 1923 BCM_GPORT_PROXY_SET(gport, 1924 hash_Base->src_modid, hash_Base->src_port); 1925 1926 fields[0] = SUB_SEL_RH_ECMPf; 1927 field_count++; 1928 fields[1] = OFFSET_RH_ECMPf; 1929 field_count++; 1930 fields[2] = CONCATENATE_HASH_FIELDS_RH_ECMPf; 1931 field_count++; 1932 PORT_LOCK(unit); 1933 rv = bcm_esw_port_lport_fields_get(unit, gport, 1934 LPORT_PROFILE_RTAG7_TAB, 1935 field_count, fields, values); 1936 PORT_UNLOCK(unit); 1937 if (BCM_FAILURE(rv)) { 1938 return rv; 1939 } 1940 hash_sub_sel = values[0]; 1941 hash_offset = values[1]; 1942 concat = values[2]; 1943 } else { 1944 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1945 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 1946 BCM_IF_ERROR_RETURN 1947 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 1948 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 1949 port_based_hash_index = (uint32) hash_index; 1950 } else 1951 #endif 1952 { 1953 port_based_hash_index = hash_Base->dev_src_port + 1954 soc_mem_index_count(unit, LPORT_TABm); 1955 } 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_RH_ECMPf); 1962 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1963 &port_based_hash_entry, OFFSET_RH_ECMPf); 1964 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 1965 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_RH_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 rh hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 1976 hash_sub_sel, hash_offset, concat)); 1977 1978 BCM_IF_ERROR_RETURN 1979 (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 1980 1981 hash_subfield_width = concat ? 64 : 16; 1982 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 1983 1984 /* Barrel shift the hash subfield, then take the LSB 16 bits */ 1985 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 1986 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 1987 *hash_value &= 0xffff; 1988 1989 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1990 (BSL_META_U(unit, 1991 "ecmp rh hash val=%d\n"), 1992 *hash_value)); 1993 1994 return BCM_E_NONE; 1995 /* ***************** END of ECMP RH HASH CALCULATIONS. ************************ */ 1996 } 1997 #endif /* INCLUDE_L3 */ 1998 1999 /* 2000 * Function: 2001 * compute_td2_rtag7_hash_trunk 2002 * Description: 2003 * get LAG hash value from RTAG7_PORT_BASED_HASHm 2004 * if unicast, SUB_SEL_TRUNK_UCf and OFFSET_TRUNK_UCf are used 2005 * if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_TRUNK_NONUCf 2006 * if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 2007 * Parameters: 2008 * unit - StrataSwitch PCI device unit number (driver internal). 2009 * hash_Base - internal data where trunk hash value is storead 2010 * hash_value- result param 2011 * Returns: 2012 * BCM_E_xxxx 2013 */ 2014 STATIC int 2015 compute_td2_rtag7_hash_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base, 2016 uint32 *hash_value) 2017 { 2018 uint32 hash_sub_sel; 2019 uint32 hash_offset; 2020 uint32 rtag7_hash_sel; 2021 uint32 port_based_hash_index; 2022 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2023 int hash_index = 0; 2024 #endif 2025 uint64 hash_subfield; 2026 uint32 hash_subfield_width; 2027 uint32 offset_shift = 0; 2028 uint32 concat; 2029 uint8 rtag7_trunk_use_macro_flow_hash_uc = 0; 2030 uint8 rtag7_trunk_use_macro_flow_hash_nonuc = 0; 2031 rtag7_port_based_hash_entry_t 2032 port_based_hash_entry; 2033 rtag7_flow_based_hash_entry_t 2034 flow_based_hash_entry; 2035 uint32 hash_control; 2036 uint32 nuc_trunk_hash_use_rtag7; 2037 int rv = BCM_E_NONE; 2038 2039 /* check if flow hash is used for UC*/ 2040 SOC_IF_ERROR_RETURN 2041 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 2042 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_UCf)) { 2043 rtag7_trunk_use_macro_flow_hash_uc = 2044 soc_reg_field_get(unit, RTAG7_HASH_SELr, 2045 rtag7_hash_sel, USE_FLOW_SEL_TRUNK_UCf); 2046 } else { 2047 rtag7_trunk_use_macro_flow_hash_uc = 0; 2048 } 2049 2050 /* check if flow hash is used for NONUC*/ 2051 SOC_IF_ERROR_RETURN 2052 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 2053 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_TRUNK_NONUCf)) { 2054 rtag7_trunk_use_macro_flow_hash_nonuc = 2055 soc_reg_field_get(unit, RTAG7_HASH_SELr, 2056 rtag7_hash_sel, USE_FLOW_SEL_TRUNK_NONUCf); 2057 } else { 2058 rtag7_trunk_use_macro_flow_hash_nonuc = 0; 2059 } 2060 2061 /* RTAG7 hash computation */ 2062 if ((rtag7_trunk_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) || 2063 (rtag7_trunk_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 2064 SOC_IF_ERROR_RETURN( 2065 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 2066 (hash_Base->rtag7_macro_flow_id & 0xff), 2067 &flow_based_hash_entry)); 2068 2069 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 2070 UC and NONUC */ 2071 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2072 &flow_based_hash_entry, SUB_SEL_TRUNKf); 2073 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2074 &flow_based_hash_entry, OFFSET_TRUNKf); 2075 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2076 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNKf); 2077 offset_shift = 0xffff; 2078 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 2079 if (hash_Base->dev_src_port < 0) { 2080 int field_count = 0; 2081 soc_field_t fields[3]; 2082 uint32 values[3]; 2083 bcm_gport_t gport; 2084 2085 BCM_GPORT_PROXY_SET(gport, 2086 hash_Base->src_modid, hash_Base->src_port); 2087 2088 if (hash_Base->is_nonuc) { 2089 fields[0] = SUB_SEL_TRUNK_NONUCf ; 2090 field_count++; 2091 fields[1] = OFFSET_TRUNK_NONUCf; 2092 field_count++; 2093 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_NONUCf; 2094 field_count++; 2095 offset_shift = 0xff; 2096 } else { 2097 fields[0] = SUB_SEL_TRUNK_UCf ; 2098 field_count++; 2099 fields[1] = OFFSET_TRUNK_UCf; 2100 field_count++; 2101 fields[2] = CONCATENATE_HASH_FIELDS_TRUNK_UCf; 2102 field_count++; 2103 offset_shift = 0x3ff; 2104 } 2105 PORT_LOCK(unit); 2106 rv = bcm_esw_port_lport_fields_get(unit, gport, 2107 LPORT_PROFILE_RTAG7_TAB, 2108 field_count, fields, values); 2109 PORT_UNLOCK(unit); 2110 if (BCM_FAILURE(rv)) { 2111 return rv; 2112 } 2113 hash_sub_sel = values[0]; 2114 hash_offset = values[1]; 2115 concat = values[2]; 2116 } else { 2117 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2118 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 2119 BCM_IF_ERROR_RETURN 2120 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 2121 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 2122 port_based_hash_index = (uint32) hash_index; 2123 } else 2124 #endif 2125 { 2126 port_based_hash_index = hash_Base->dev_src_port + 2127 soc_mem_index_count(unit, LPORT_TABm); 2128 } 2129 SOC_IF_ERROR_RETURN( 2130 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 2131 port_based_hash_index, &port_based_hash_entry)); 2132 if (hash_Base->is_nonuc) { 2133 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2134 &port_based_hash_entry, SUB_SEL_TRUNK_NONUCf); 2135 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2136 &port_based_hash_entry, OFFSET_TRUNK_NONUCf); 2137 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2138 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_NONUCf); 2139 offset_shift = 0xff; 2140 } else { 2141 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2142 &port_based_hash_entry, SUB_SEL_TRUNK_UCf); 2143 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2144 &port_based_hash_entry, OFFSET_TRUNK_UCf); 2145 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2146 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNK_UCf); 2147 offset_shift = 0x3ff; 2148 } 2149 } 2150 } else { 2151 hash_sub_sel = 0; 2152 hash_offset = 0; 2153 concat = 0; 2154 } 2155 2156 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2157 (BSL_META_U(unit, 2158 "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 2159 hash_sub_sel, hash_offset, concat)); 2160 2161 BCM_IF_ERROR_RETURN 2162 (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 2163 2164 hash_subfield_width = concat ? 64 : 16; 2165 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 2166 2167 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 2168 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 2169 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 2170 *hash_value &= offset_shift; 2171 2172 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2173 (BSL_META_U(unit, 2174 "Trunk hash_value=%d\n"), 2175 *hash_value)); 2176 2177 BCM_IF_ERROR_RETURN 2178 (READ_HASH_CONTROLr(unit, &hash_control)); 2179 nuc_trunk_hash_use_rtag7 = 2180 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 2181 NON_UC_TRUNK_HASH_USE_RTAG7f); 2182 2183 if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) { 2184 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2185 (BSL_META_U(unit, 2186 "NonUC trunk Hash calculation: non rtag7 calc not supported\n"))); 2187 *hash_value = 0; 2188 } 2189 2190 return BCM_E_NONE; 2191 } 2192 2193 /* 2194 * Function: 2195 * compute_td2_rtag7_hash_hg_trunk 2196 * Description: 2197 * get HGT hash value from RTAG7_PORT_BASED_HASHm 2198 * if unicast, SUB_SEL_TRUNK_UCf and OFFSET_TRUNK_UCf are used 2199 * if not unicast, SUB_SEL_TRUNK_NONUCf and OFFSET_TRUNK_NONUCf 2200 * if flow hash is used, get subsel and offset from RTAG7_FLOW_BASED_HASH 2201 * Parameters: 2202 * unit - StrataSwitch PCI device unit number (driver internal). 2203 * hash_Base - internal data where trunk hash value is storead 2204 * hash_value- result param 2205 * Returns: 2206 * BCM_E_xxxx 2207 */ 2208 STATIC int 2209 compute_td2_rtag7_hash_hg_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base, 2210 uint32 *hash_value) 2211 { 2212 uint32 hash_sub_sel; 2213 uint32 hash_offset; 2214 uint32 rtag7_hash_sel; 2215 uint32 port_based_hash_index; 2216 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2217 int hash_index = 0; 2218 #endif 2219 uint64 hash_subfield; 2220 uint32 hash_subfield_width; 2221 uint32 offset_shift = 0; 2222 uint32 concat; 2223 uint8 rtag7_hgt_use_macro_flow_hash_uc = 0; 2224 uint8 rtag7_hgt_use_macro_flow_hash_nonuc = 0; 2225 rtag7_port_based_hash_entry_t 2226 port_based_hash_entry; 2227 rtag7_flow_based_hash_entry_t 2228 flow_based_hash_entry; 2229 int rv = BCM_E_NONE; 2230 2231 /* check if flow hash is used for UC*/ 2232 SOC_IF_ERROR_RETURN 2233 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 2234 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_UCf)) { 2235 rtag7_hgt_use_macro_flow_hash_uc = 2236 soc_reg_field_get(unit, RTAG7_HASH_SELr, 2237 rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_UCf); 2238 } else { 2239 rtag7_hgt_use_macro_flow_hash_uc = 0; 2240 } 2241 2242 /* check if flow hash is used for NONUC*/ 2243 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_HG_TRUNK_NONUCf)) { 2244 rtag7_hgt_use_macro_flow_hash_nonuc = 2245 soc_reg_field_get(unit, RTAG7_HASH_SELr, 2246 rtag7_hash_sel, USE_FLOW_SEL_HG_TRUNK_NONUCf); 2247 } else { 2248 rtag7_hgt_use_macro_flow_hash_nonuc = 0; 2249 } 2250 2251 /* RTAG7 hash computation */ 2252 if ((rtag7_hgt_use_macro_flow_hash_nonuc && (hash_Base->is_nonuc == 0)) || 2253 (rtag7_hgt_use_macro_flow_hash_uc && (hash_Base->is_nonuc != 0))) { 2254 SOC_IF_ERROR_RETURN( 2255 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 2256 (hash_Base->rtag7_macro_flow_id & 0xff), 2257 &flow_based_hash_entry)); 2258 2259 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 2260 UC and NONUC */ 2261 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2262 &flow_based_hash_entry, SUB_SEL_HG_TRUNKf); 2263 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2264 &flow_based_hash_entry, OFFSET_HG_TRUNKf); 2265 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2266 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNKf); 2267 offset_shift = 0xffff; 2268 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 2269 if (hash_Base->dev_src_port < 0) { 2270 int field_count = 0; 2271 soc_field_t fields[3]; 2272 uint32 values[3]; 2273 bcm_gport_t gport; 2274 2275 BCM_GPORT_PROXY_SET(gport, 2276 hash_Base->src_modid, hash_Base->src_port); 2277 2278 if (hash_Base->is_nonuc) { 2279 fields[0] = SUB_SEL_HG_TRUNK_NONUCf ; 2280 field_count++; 2281 fields[1] = OFFSET_HG_TRUNK_NONUCf; 2282 field_count++; 2283 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf; 2284 field_count++; 2285 offset_shift = 0xff; 2286 } else { 2287 fields[0] = SUB_SEL_HG_TRUNK_UCf ; 2288 field_count++; 2289 fields[1] = OFFSET_HG_TRUNK_UCf; 2290 field_count++; 2291 fields[2] = CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf; 2292 field_count++; 2293 offset_shift = 0x3ff; 2294 } 2295 PORT_LOCK(unit); 2296 rv = bcm_esw_port_lport_fields_get(unit, gport, 2297 LPORT_PROFILE_RTAG7_TAB, 2298 field_count, fields, values); 2299 PORT_UNLOCK(unit); 2300 if (BCM_FAILURE(rv)) { 2301 return rv; 2302 } 2303 hash_sub_sel = values[0]; 2304 hash_offset = values[1]; 2305 concat = values[2]; 2306 } else { 2307 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2308 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 2309 BCM_IF_ERROR_RETURN 2310 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 2311 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 2312 port_based_hash_index = (uint32) hash_index; 2313 } else 2314 #endif 2315 { 2316 port_based_hash_index = hash_Base->dev_src_port + 2317 soc_mem_index_count(unit, LPORT_TABm); 2318 } 2319 SOC_IF_ERROR_RETURN( 2320 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 2321 port_based_hash_index, &port_based_hash_entry)); 2322 if (hash_Base->is_nonuc) { 2323 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2324 &port_based_hash_entry, SUB_SEL_HG_TRUNK_NONUCf); 2325 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2326 &port_based_hash_entry, OFFSET_HG_TRUNK_NONUCf); 2327 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2328 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_NONUCf); 2329 offset_shift = 0xff; 2330 } else { 2331 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2332 &port_based_hash_entry, SUB_SEL_HG_TRUNK_UCf); 2333 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2334 &port_based_hash_entry, OFFSET_HG_TRUNK_UCf); 2335 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2336 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNK_UCf); 2337 offset_shift = 0x3ff; 2338 } 2339 } 2340 } else { 2341 hash_sub_sel = 0; 2342 hash_offset = 0; 2343 concat = 0; 2344 } 2345 2346 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2347 (BSL_META_U(unit, 2348 "Trunk hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 2349 hash_sub_sel, hash_offset, concat)); 2350 2351 BCM_IF_ERROR_RETURN 2352 (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 2353 2354 hash_subfield_width = concat ? 64 : 16; 2355 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 2356 2357 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 2358 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 2359 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 2360 *hash_value &= offset_shift; 2361 2362 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2363 (BSL_META_U(unit, 2364 "HG Trunk hash_value=%d\n"), 2365 *hash_value)); 2366 2367 return BCM_E_NONE; 2368 } 2369 2370 /* 2371 * Function: 2372 * compute_td2_rtag7_hash_rh_trunk 2373 * Description: 2374 * get LAG RH hash value using SUB_SEL_RH_LAGf and OFFSET_RH_LAGf 2375 * from RTAG7_PORT_BASED_HASHm 2376 * Parameters: 2377 * unit - StrataSwitch PCI device unit number (driver internal). 2378 * hash_Base - internal data where rh hash value is stored 2379 * hash_value- result param 2380 * Returns: 2381 * BCM_E_xxxx 2382 */ 2383 STATIC int 2384 compute_td2_rtag7_hash_rh_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base, 2385 uint32 *hash_value) 2386 { 2387 uint32 hash_sub_sel; 2388 uint32 hash_offset; 2389 uint32 rtag7_hash_sel; 2390 uint32 port_based_hash_index; 2391 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2392 int hash_index = 0; 2393 #endif 2394 uint64 hash_subfield; 2395 uint32 hash_subfield_width; 2396 uint32 concat; 2397 uint32 offset_shift = 0; 2398 rtag7_port_based_hash_entry_t 2399 port_based_hash_entry; 2400 rtag7_flow_based_hash_entry_t 2401 flow_based_hash_entry; 2402 uint32 hash_control; 2403 uint32 nuc_trunk_hash_use_rtag7; 2404 int rv = BCM_E_NONE; 2405 2406 2407 /* check if flow hash is used for UC*/ 2408 SOC_IF_ERROR_RETURN 2409 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 2410 /* RTAG7 hash computation */ 2411 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_RH_LAGf) && 2412 soc_reg_field_get(unit, RTAG7_HASH_SELr, 2413 rtag7_hash_sel, USE_FLOW_SEL_RH_LAGf)) { 2414 SOC_IF_ERROR_RETURN( 2415 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 2416 (hash_Base->rtag7_macro_flow_id & 0xff), 2417 &flow_based_hash_entry)); 2418 2419 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 2420 UC and NONUC */ 2421 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2422 &flow_based_hash_entry, SUB_SEL_TRUNKf); 2423 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2424 &flow_based_hash_entry, OFFSET_TRUNKf); 2425 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2426 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_TRUNKf); 2427 offset_shift = 0xffff; 2428 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 2429 if (hash_Base->dev_src_port < 0) { 2430 int field_count = 0; 2431 soc_field_t fields[3]; 2432 uint32 values[3]; 2433 bcm_gport_t gport; 2434 2435 BCM_GPORT_PROXY_SET(gport, 2436 hash_Base->src_modid, hash_Base->src_port); 2437 2438 fields[0] = SUB_SEL_RH_LAGf ; 2439 field_count++; 2440 fields[1] = OFFSET_RH_LAGf; 2441 field_count++; 2442 fields[2] = CONCATENATE_HASH_FIELDS_RH_LAGf; 2443 field_count++; 2444 2445 PORT_LOCK(unit); 2446 rv = bcm_esw_port_lport_fields_get(unit, gport, 2447 LPORT_PROFILE_RTAG7_TAB, 2448 field_count, fields, values); 2449 PORT_UNLOCK(unit); 2450 if (BCM_FAILURE(rv)) { 2451 return rv; 2452 } 2453 hash_sub_sel = values[0]; 2454 hash_offset = values[1]; 2455 concat = values[2]; 2456 offset_shift = 0x3ff; 2457 } else { 2458 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2459 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 2460 BCM_IF_ERROR_RETURN 2461 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 2462 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 2463 port_based_hash_index = (uint32) hash_index; 2464 } else 2465 #endif 2466 { 2467 port_based_hash_index = hash_Base->dev_src_port + 2468 soc_mem_index_count(unit, LPORT_TABm); 2469 } 2470 BCM_IF_ERROR_RETURN ( 2471 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 2472 port_based_hash_index, &port_based_hash_entry)); 2473 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2474 &port_based_hash_entry, SUB_SEL_RH_LAGf); 2475 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2476 &port_based_hash_entry, OFFSET_RH_LAGf); 2477 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2478 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_RH_LAGf); 2479 offset_shift = 0x3ff; 2480 } 2481 } else { 2482 hash_sub_sel = 0; 2483 hash_offset = 0; 2484 concat = 0; 2485 } 2486 2487 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2488 (BSL_META_U(unit, 2489 "Trunk RH hash_sub_sel=%d, hash_offset=%d, concat=%d\n"), 2490 hash_sub_sel, hash_offset, concat)); 2491 2492 BCM_IF_ERROR_RETURN 2493 (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 2494 2495 hash_subfield_width = concat ? 64 : 16; 2496 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 2497 2498 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 2499 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 2500 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 2501 *hash_value &= offset_shift; 2502 2503 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2504 (BSL_META_U(unit, 2505 "Trunk RH hash_value=%d\n"), 2506 *hash_value)); 2507 2508 BCM_IF_ERROR_RETURN 2509 (READ_HASH_CONTROLr(unit, &hash_control)); 2510 nuc_trunk_hash_use_rtag7 = 2511 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 2512 NON_UC_TRUNK_HASH_USE_RTAG7f); 2513 2514 if (hash_Base->is_nonuc && nuc_trunk_hash_use_rtag7 == 0) { 2515 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2516 (BSL_META_U(unit, 2517 "NonUC trunk Hash calculation: non rtag7 calc not supported\n"))); 2518 *hash_value = 0; 2519 } 2520 2521 return BCM_E_NONE; 2522 } 2523 2524 /* 2525 * Function: 2526 * compute_td2_rtag7_hash_rh_hg_trunk 2527 * Description: 2528 * get HGT RH hash value using SUB_SEL_RH_LAGf and OFFSET_RH_LAGf 2529 * from RTAG7_PORT_BASED_HASHm 2530 * Parameters: 2531 * unit - StrataSwitch PCI device unit number (driver internal). 2532 * hash_Base - internal data where rh hash value is stored 2533 * hash_value- result param 2534 * Returns: 2535 * BCM_E_xxxx 2536 */ 2537 STATIC int 2538 compute_td2_rtag7_hash_rh_hg_trunk(int unit , bcm_rtag7_base_hash_t *hash_Base, 2539 uint32 *hash_value) 2540 { 2541 uint32 hash_sub_sel; 2542 uint32 hash_offset; 2543 uint32 rtag7_hash_sel; 2544 uint32 port_based_hash_index; 2545 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2546 int hash_index = 0; 2547 #endif 2548 uint64 hash_subfield; 2549 uint32 hash_subfield_width; 2550 uint32 offset_shift = 0; 2551 uint32 concat; 2552 rtag7_port_based_hash_entry_t 2553 port_based_hash_entry; 2554 rtag7_flow_based_hash_entry_t 2555 flow_based_hash_entry; 2556 int rv = BCM_E_NONE; 2557 2558 /* check if flow hash is used for UC*/ 2559 SOC_IF_ERROR_RETURN 2560 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 2561 /* RTAG7 hash computation */ 2562 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_RH_HGTf) && 2563 soc_reg_field_get(unit, RTAG7_HASH_SELr, 2564 rtag7_hash_sel, USE_FLOW_SEL_RH_HGTf)) { 2565 SOC_IF_ERROR_RETURN( 2566 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 2567 (hash_Base->rtag7_macro_flow_id & 0xff), 2568 &flow_based_hash_entry)); 2569 2570 /* in RTAG7_FLOW_BASED_HASHm, using same selection for 2571 UC and NONUC */ 2572 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2573 &flow_based_hash_entry, SUB_SEL_HG_TRUNKf); 2574 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2575 &flow_based_hash_entry, OFFSET_HG_TRUNKf); 2576 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2577 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_HG_TRUNKf); 2578 offset_shift = 0xffff; 2579 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 2580 if (hash_Base->dev_src_port < 0) { 2581 int field_count = 0; 2582 soc_field_t fields[3]; 2583 uint32 values[3]; 2584 bcm_gport_t gport; 2585 2586 BCM_GPORT_PROXY_SET(gport, 2587 hash_Base->src_modid, hash_Base->src_port); 2588 2589 fields[0] = SUB_SEL_RH_HGTf ; 2590 field_count++; 2591 fields[1] = OFFSET_RH_HGTf; 2592 field_count++; 2593 fields[2] = CONCATENATE_HASH_FIELDS_RH_HGTf; 2594 field_count++; 2595 2596 PORT_LOCK(unit); 2597 rv = bcm_esw_port_lport_fields_get(unit, gport, 2598 LPORT_PROFILE_RTAG7_TAB, 2599 field_count, fields, values); 2600 PORT_UNLOCK(unit); 2601 if (BCM_FAILURE(rv)) { 2602 return rv; 2603 } 2604 hash_sub_sel = values[0]; 2605 hash_offset = values[1]; 2606 concat = values[2]; 2607 offset_shift = 0x3ff; 2608 } else { 2609 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2610 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 2611 BCM_IF_ERROR_RETURN 2612 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 2613 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 2614 port_based_hash_index = (uint32) hash_index; 2615 } else 2616 #endif 2617 { 2618 port_based_hash_index = hash_Base->dev_src_port + 2619 soc_mem_index_count(unit, LPORT_TABm); 2620 } 2621 SOC_IF_ERROR_RETURN( 2622 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 2623 port_based_hash_index, &port_based_hash_entry)); 2624 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2625 &port_based_hash_entry, SUB_SEL_RH_HGTf); 2626 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2627 &port_based_hash_entry, OFFSET_RH_HGTf); 2628 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2629 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_RH_HGTf); 2630 offset_shift = 0x3ff; 2631 } 2632 } else { 2633 hash_sub_sel = 0; 2634 hash_offset = 0; 2635 concat = 0; 2636 } 2637 2638 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2639 (BSL_META_U(unit, 2640 "HGT RH hash_sub_sel=%d, hash_offset=%d, concat=%d\n"), 2641 hash_sub_sel, hash_offset, concat)); 2642 2643 BCM_IF_ERROR_RETURN 2644 (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 2645 2646 hash_subfield_width = concat ? 64 : 16; 2647 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 2648 2649 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 2650 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 2651 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 2652 *hash_value &= offset_shift; 2653 2654 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2655 (BSL_META_U(unit, 2656 "HGT RH hash_value=%d\n"), 2657 *hash_value)); 2658 2659 return BCM_E_NONE; 2660 } 2661 2662 /* 2663 * Function: 2664 * compute_td2_rtag7_vxlan 2665 * Description: compute entropy value of vxlan packet 2666 * Parameters: 2667 * unit - StrataSwitch PCI device unit number (driver internal). 2668 * hash_Base - internal data where trunk hash value is storead 2669 * hash_value- result param 2670 * Returns: 2671 * BCM_E_xxxx 2672 */ 2673 STATIC int 2674 compute_td2_rtag7_vxlan(int unit , bcm_rtag7_base_hash_t *hash_Base, 2675 uint32 *hash_value) 2676 { 2677 uint32 hash_sub_sel; 2678 uint32 hash_offset; 2679 uint32 rtag7_hash_sel; 2680 uint32 port_based_hash_index; 2681 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2682 int hash_index = 0; 2683 #endif 2684 uint64 hash_subfield; 2685 uint32 hash_subfield_width; 2686 uint32 offset_shift = 0xffff; 2687 uint32 concat; 2688 uint8 rtag7_vxlan_use_flow_sel_entropy_label = 0; 2689 rtag7_port_based_hash_entry_t 2690 port_based_hash_entry; 2691 rtag7_flow_based_hash_entry_t 2692 flow_based_hash_entry; 2693 2694 /* check if vxlan use RTAG7_FLOW_BASED_HASH 2695 else use RTAG7_PORT_BASED_HASH selection for ENTROPY_LABEL*/ 2696 SOC_IF_ERROR_RETURN 2697 (READ_RTAG7_HASH_SELr(unit, &rtag7_hash_sel)); 2698 if (soc_reg_field_valid(unit, RTAG7_HASH_SELr, USE_FLOW_SEL_ENTROPY_LABELf)) { 2699 rtag7_vxlan_use_flow_sel_entropy_label = 2700 soc_reg_field_get(unit, RTAG7_HASH_SELr, 2701 rtag7_hash_sel, USE_FLOW_SEL_ENTROPY_LABELf); 2702 } else { 2703 rtag7_vxlan_use_flow_sel_entropy_label = 0; 2704 } 2705 2706 /* RTAG7 hash computation */ 2707 if (rtag7_vxlan_use_flow_sel_entropy_label) { 2708 /* read flow_based_hash table and set hash_sub_sel, offset, and concat value */ 2709 SOC_IF_ERROR_RETURN( 2710 READ_RTAG7_FLOW_BASED_HASHm(unit, MEM_BLOCK_ANY, 2711 (hash_Base->rtag7_macro_flow_id & 0xff), 2712 &flow_based_hash_entry)); 2713 2714 2715 hash_sub_sel = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2716 &flow_based_hash_entry, SUB_SEL_LBID_OR_ENTROPY_LABELf); 2717 hash_offset = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2718 &flow_based_hash_entry, OFFSET_LBID_OR_ENTROPY_LABELf); 2719 concat = soc_RTAG7_FLOW_BASED_HASHm_field32_get(unit, 2720 &flow_based_hash_entry, CONCATENATE_HASH_FIELDS_LBID_OR_ENTROPY_LABELf); 2721 } else if (SOC_MEM_IS_VALID(unit, RTAG7_PORT_BASED_HASHm)) { 2722 /* read port_based_hash table and set hash_sub_sel, offset, and concat value */ 2723 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 2724 if (soc_feature(unit, soc_feature_rtag7_port_profile)) { 2725 BCM_IF_ERROR_RETURN 2726 (_bcm_esw_port_tab_get(unit, hash_Base->dev_src_port, 2727 RTAG7_PORT_PROFILE_INDEXf, &hash_index)); 2728 port_based_hash_index = (uint32) hash_index; 2729 } else 2730 #endif 2731 { 2732 port_based_hash_index = hash_Base->dev_src_port + 2733 soc_mem_index_count(unit, LPORT_TABm); 2734 } 2735 SOC_IF_ERROR_RETURN( 2736 READ_RTAG7_PORT_BASED_HASHm(unit, MEM_BLOCK_ANY, 2737 port_based_hash_index, &port_based_hash_entry)); 2738 hash_sub_sel = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2739 &port_based_hash_entry, SUB_SEL_ENTROPY_LABELf); 2740 hash_offset = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2741 &port_based_hash_entry, OFFSET_ENTROPY_LABELf); 2742 concat = soc_RTAG7_PORT_BASED_HASHm_field32_get(unit, 2743 &port_based_hash_entry, CONCATENATE_HASH_FIELDS_ENTROPY_LABELf); 2744 } else { 2745 hash_sub_sel = 0; 2746 hash_offset = 0; 2747 concat = 0; 2748 } 2749 2750 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2751 (BSL_META_U(unit, 2752 "vxlan hash_seb_sel=%d, hash_offset=%d, concat=%d\n"), 2753 hash_sub_sel, hash_offset, concat)); 2754 BCM_IF_ERROR_RETURN 2755 (select_td2_hash_subfield(concat, hash_sub_sel, &hash_subfield, hash_Base)); 2756 2757 hash_subfield_width = concat ? 64 : 16; 2758 hash_offset = concat ? hash_offset : (hash_offset & 0xf); 2759 2760 /* Barrel shift the hash subfield, then take the LSB 10 bits for UC and 8 bits for nonUC */ 2761 HASH_VALUE_64_COMPUTE(hash_subfield, hash_offset, hash_subfield_width); 2762 HASH_VALUE_32_COMPUTE(*hash_value, hash_subfield); 2763 *hash_value &= offset_shift; 2764 2765 LOG_VERBOSE(BSL_LS_BCM_COMMON, 2766 (BSL_META_U(unit, 2767 "vxlan hash_value=%d\n"), 2768 *hash_value)); 2769 2770 return BCM_E_NONE; 2771 } 2772 2773 2774 /* check ethertype eligibility for resilient hashing */ 2775 uint8 check_td2_ether_type_eligibility_for_rh(int unit, uint8 rh_mode, uint32 rh_ethertype) 2776 { 2777 uint8 ethertype_enable = 0; 2778 uint8 ethertype_eligibility_config = 0; 2779 uint32 ethertype_control; 2780 uint32 ethercount; 2781 int ethertype; 2782 rh_ecmp_ethertype_eligibility_map_entry_t ethertype_entry; 2783 2784 if (rh_mode == RTAG7_RH_MODE_ECMP) { 2785 SOC_IF_ERROR_RETURN 2786 (READ_RH_ECMP_ETHERTYPE_ELIGIBILITY_CONTROLr(unit, ðertype_control)); 2787 2788 ethertype_eligibility_config = soc_reg_field_get(unit, 2789 RH_ECMP_ETHERTYPE_ELIGIBILITY_CONTROLr, 2790 ethertype_control, 2791 ETHERTYPE_ELIGIBILITY_CONFIGf); 2792 } else if (rh_mode == RTAG7_RH_MODE_LAG) { 2793 SOC_IF_ERROR_RETURN 2794 (READ_RH_LAG_ETHERTYPE_ELIGIBILITY_CONTROLr(unit, ðertype_control)); 2795 2796 ethertype_eligibility_config = soc_reg_field_get(unit, 2797 RH_LAG_ETHERTYPE_ELIGIBILITY_CONTROLr, 2798 ethertype_control, 2799 ETHERTYPE_ELIGIBILITY_CONFIGf); 2800 } else if (rh_mode == RTAG7_RH_MODE_HGT) { 2801 SOC_IF_ERROR_RETURN 2802 (READ_RH_HGT_ETHERTYPE_ELIGIBILITY_CONTROLr(unit, ðertype_control)); 2803 2804 ethertype_eligibility_config = soc_reg_field_get(unit, 2805 RH_HGT_ETHERTYPE_ELIGIBILITY_CONTROLr, 2806 ethertype_control, 2807 ETHERTYPE_ELIGIBILITY_CONFIGf); 2808 } 2809 2810 /* Check for 16 Ethertypes supported based on operating in the "exclude mode" or "include mode"*/ 2811 if (ethertype_eligibility_config) { 2812 ethertype_enable = 0; 2813 for (ethercount = 0; 2814 ethercount < soc_mem_index_count(unit,RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm); 2815 ethercount++) { 2816 2817 if (rh_mode == RTAG7_RH_MODE_ECMP) { 2818 SOC_IF_ERROR_RETURN(READ_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2819 MEM_BLOCK_ANY, ethercount, ðertype_entry)); 2820 if (soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2821 ðertype_entry, VALIDf)) { 2822 ethertype = soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2823 ðertype_entry, ETHERTYPEf); 2824 ethertype_enable |= (rh_ethertype == ethertype); 2825 } 2826 } else if (rh_mode == RTAG7_RH_MODE_LAG) { 2827 SOC_IF_ERROR_RETURN(READ_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2828 MEM_BLOCK_ANY, ethercount, ðertype_entry)); 2829 if (soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2830 ðertype_entry, VALIDf)) { 2831 ethertype = soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2832 ðertype_entry, ETHERTYPEf); 2833 ethertype_enable |= (rh_ethertype == ethertype); 2834 } 2835 } else if (rh_mode == RTAG7_RH_MODE_HGT) { 2836 SOC_IF_ERROR_RETURN(READ_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2837 MEM_BLOCK_ANY, ethercount, ðertype_entry)); 2838 if (soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2839 ðertype_entry, VALIDf)) { 2840 ethertype = soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2841 ðertype_entry, ETHERTYPEf); 2842 ethertype_enable |= (rh_ethertype == ethertype); 2843 } 2844 } 2845 } /* end of forloop */ 2846 } else { 2847 ethertype_enable = 1; 2848 for (ethercount = 0; 2849 ethercount < soc_mem_index_count(unit,RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm); 2850 ethercount++) { 2851 2852 if (rh_mode == RTAG7_RH_MODE_ECMP) { 2853 SOC_IF_ERROR_RETURN(READ_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2854 MEM_BLOCK_ANY, ethercount, ðertype_entry)); 2855 if (soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2856 ðertype_entry, VALIDf)) { 2857 ethertype = soc_RH_ECMP_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2858 ðertype_entry, ETHERTYPEf); 2859 ethertype_enable &= !(rh_ethertype == ethertype); 2860 } 2861 } else if (rh_mode == RTAG7_RH_MODE_LAG) { 2862 SOC_IF_ERROR_RETURN(READ_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2863 MEM_BLOCK_ANY, ethercount, ðertype_entry)); 2864 if (soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2865 ðertype_entry, VALIDf)) { 2866 ethertype = soc_RH_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2867 ðertype_entry, ETHERTYPEf); 2868 ethertype_enable &= !(rh_ethertype == ethertype); 2869 } 2870 } else if (rh_mode == RTAG7_RH_MODE_HGT) { 2871 SOC_IF_ERROR_RETURN(READ_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2872 MEM_BLOCK_ANY, ethercount, ðertype_entry)); 2873 if (soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2874 ðertype_entry, VALIDf)) { 2875 ethertype = soc_RH_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2876 ðertype_entry, ETHERTYPEf); 2877 ethertype_enable &= !(rh_ethertype == ethertype); 2878 } 2879 } 2880 } /* end of forloop */ 2881 } 2882 2883 return ethertype_enable; 2884 } 2885 2886 /* calcualte resilient hashing value */ 2887 int perform_td2_rh(int unit,uint32 flow_set_base, uint8 flow_set_size, uint8 rh_mode, 2888 uint32 ecmp_hash,uint32 trunk_hash, 2889 uint32* resolved_member, uint8* resolved_member_is_valid) 2890 { 2891 uint32 rtag7_hash = 0; 2892 uint32 flow_set_index = 0; 2893 uint32 rh_flowset_table_config; 2894 uint32 port_id; 2895 uint32 mod_id; 2896 rh_ecmp_flowset_entry_t ecmp_flow_entry; 2897 rh_lag_flowset_entry_t lag_flow_entry; 2898 rh_hgt_flowset_entry_t hgt_flow_entry; 2899 soc_field_t port_fld = EGRESS_PORTf; 2900 2901 if (!soc_mem_field_valid(unit, RH_HGT_FLOWSETm, port_fld)) { 2902 port_fld = PORT_NUMf; 2903 } 2904 2905 2906 if (rh_mode == RTAG7_RH_MODE_ECMP) { 2907 rtag7_hash = ecmp_hash; 2908 } else if (rh_mode == RTAG7_RH_MODE_LAG) { 2909 rtag7_hash = trunk_hash; 2910 } else if (rh_mode == RTAG7_RH_MODE_HGT) { 2911 rtag7_hash = trunk_hash; 2912 } 2913 2914 /* Compute flow set index */ 2915 2916 switch (flow_set_size) { 2917 case 0: /* 0 - Flow Index is 0 */ 2918 flow_set_index = 0; 2919 break; 2920 case 1: /* 64 - take 6 hash bits*/ 2921 flow_set_index = flow_set_base + (rtag7_hash & 0x3f); 2922 break; 2923 case 2: /* 128 - take 7 hash bits*/ 2924 flow_set_index = flow_set_base + (rtag7_hash & 0x7f); 2925 break; 2926 case 3: /* 256 - take 8 hash bits*/ 2927 flow_set_index = flow_set_base + (rtag7_hash & 0xff); 2928 break; 2929 case 4: /* 512 - take 9 hash bits*/ 2930 flow_set_index = flow_set_base + (rtag7_hash & 0x1ff); 2931 break; 2932 case 5: /* 1024 - take 10 hash bits*/ 2933 flow_set_index = flow_set_base + (rtag7_hash & 0x3ff); 2934 break; 2935 case 6: /* 2048 - take 11 hash bits*/ 2936 flow_set_index = flow_set_base + (rtag7_hash & 0x7ff); 2937 break; 2938 case 7: /* 4096 - take 12 hash bits*/ 2939 flow_set_index = flow_set_base + (rtag7_hash & 0xfff); 2940 break; 2941 case 8: /* 8192 - take 13 hash bits*/ 2942 flow_set_index = flow_set_base + (rtag7_hash & 0x1fff); 2943 break; 2944 case 9: /* 16384 - take 14 hash bits*/ 2945 flow_set_index = flow_set_base + (rtag7_hash & 0x3fff); 2946 break; 2947 case 10: /* 32768 - take 15 hash bits*/ 2948 flow_set_index = flow_set_base + (rtag7_hash & 0x7fff); 2949 break; 2950 case 11: /* 65536 - take 16 hash bits*/ 2951 flow_set_index = flow_set_base + (rtag7_hash & 0xffff); 2952 break; 2953 } 2954 2955 if (rh_mode == RTAG7_RH_MODE_ECMP || rh_mode == RTAG7_RH_MODE_LAG) { 2956 uint32 enhanced_hash_control; 2957 SOC_IF_ERROR_RETURN( 2958 READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control)); 2959 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 2960 rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, 2961 enhanced_hash_control, ECMP_FLOWSET_TABLE_CONFIGf); 2962 } else { 2963 rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, 2964 enhanced_hash_control, RH_FLOWSET_TABLE_CONFIG_ENCODINGf); 2965 } 2966 if (rh_flowset_table_config == 2967 ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF) { 2968 2969 /* 32K flow sets are allocated to each ECMP and LAG */ 2970 flow_set_index = flow_set_index & 0x7fff; 2971 2972 } else if (rh_flowset_table_config == 2973 ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_ECMP) { 2974 2975 flow_set_index = flow_set_index & 0xffff; 2976 2977 } else if (rh_flowset_table_config == 2978 ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_LAG) { 2979 2980 flow_set_index = flow_set_index & 0xffff; 2981 } 2982 } else if (rh_mode == RTAG7_RH_MODE_HGT) { 2983 flow_set_index = flow_set_index & 0xffff; 2984 } 2985 2986 if (rh_mode == RTAG7_RH_MODE_ECMP) { 2987 /* Read RH_ECMP_FLOWSET TABLE */ 2988 SOC_IF_ERROR_RETURN(READ_RH_ECMP_FLOWSETm(unit, 2989 MEM_BLOCK_ANY, flow_set_index, &ecmp_flow_entry)); 2990 *resolved_member_is_valid = soc_RH_ECMP_FLOWSETm_field32_get( 2991 unit, &ecmp_flow_entry, VALIDf); 2992 *resolved_member = soc_RH_ECMP_FLOWSETm_field32_get(unit, 2993 &ecmp_flow_entry, NEXT_HOP_INDEXf); 2994 } else if (rh_mode == RTAG7_RH_MODE_LAG) { 2995 /* Read RH_LAG_FLOWSET TABLE */ 2996 SOC_IF_ERROR_RETURN(READ_RH_LAG_FLOWSETm(unit, 2997 MEM_BLOCK_ANY, flow_set_index, &lag_flow_entry)); 2998 *resolved_member_is_valid = soc_RH_LAG_FLOWSETm_field32_get( 2999 unit, &lag_flow_entry, VALIDf); 3000 port_id = soc_RH_LAG_FLOWSETm_field32_get(unit, 3001 &lag_flow_entry, PORT_NUMf); 3002 3003 mod_id = soc_RH_LAG_FLOWSETm_field32_get(unit, 3004 &lag_flow_entry, MODULE_IDf); 3005 3006 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3007 (BSL_META_U(unit, 3008 "RH_LAG_FLOWSET.PORT_NUMf=%d\n"), 3009 port_id)); 3010 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3011 (BSL_META_U(unit, 3012 "RH_LAG_FLOWSET.MODULE_IDF=%d\n"), 3013 mod_id)); 3014 3015 *resolved_member = port_id | (mod_id << RH_LAG_FLOWSET_MOD_ID_SHIFT_VAL); 3016 } else if (rh_mode == RTAG7_RH_MODE_HGT) { 3017 /* Read RH_HGT_FLOWSET TABLE */ 3018 SOC_IF_ERROR_RETURN(READ_RH_HGT_FLOWSETm(unit, 3019 MEM_BLOCK_ANY, flow_set_index, &hgt_flow_entry)); 3020 *resolved_member_is_valid = soc_RH_HGT_FLOWSETm_field32_get( 3021 unit, &hgt_flow_entry, VALIDf); 3022 port_id = soc_RH_HGT_FLOWSETm_field32_get(unit, 3023 &hgt_flow_entry, port_fld); 3024 3025 *resolved_member = port_id; 3026 } 3027 3028 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3029 (BSL_META_U(unit, 3030 "rh flowset *resolved_member=%d\n"), 3031 *resolved_member)); 3032 3033 return BCM_E_NONE; 3034 } 3035 3036 #ifdef INCLUDE_L3 3037 /* helper function check if resilient hashing is enabled on an ecmp group */ 3038 STATIC uint8 3039 check_td2_ecmp_rh_enable (int unit, int ecmp_group, uint32 ethertype) 3040 { 3041 ecmp_count_entry_t ecmpc_entry; 3042 uint8 rh_ecmp_ethertype_enable, rh_ecmp_enable=0; 3043 uint32 rh_flowset_table_config, enhanced_hash_control; 3044 3045 SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control)); 3046 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 3047 rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control, 3048 ECMP_FLOWSET_TABLE_CONFIGf); 3049 } else { 3050 rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control, 3051 RH_FLOWSET_TABLE_CONFIG_ENCODINGf); 3052 } 3053 3054 BCM_IF_ERROR_RETURN 3055 (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry)); 3056 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 3057 rh_ecmp_enable = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, LB_MODEf); 3058 } else { 3059 rh_ecmp_enable = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, ENHANCED_HASHING_ENABLEf); 3060 } 3061 rh_ecmp_ethertype_enable = check_td2_ether_type_eligibility_for_rh(unit, RTAG7_RH_MODE_ECMP, ethertype); 3062 3063 if ((rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF) || 3064 (rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_ECMP)) { 3065 rh_ecmp_enable = (rh_ecmp_enable && rh_ecmp_ethertype_enable); 3066 } 3067 return rh_ecmp_enable; 3068 } 3069 3070 3071 /* 3072 * Function: 3073 * get_td2_hash_ecmp 3074 * Description: 3075 * compute ecmp destination among multipath interfaces 3076 * Parameters: 3077 * unit - StrataSwitch PCI device unit number (driver internal). 3078 * ecmp_group - multipath id 3079 * hash_index - hash value calculated from compute_td2_ecmp_hash 3080 * hash_rh_index - hash value calculated from compute_td2_ecmp_rh_hash 3081 * nh_id - where egress l3 interface id is stored 3082 * ecmp_rh_enable - flag indicating if rh is enable for this hashing calculation 3083 * ethertype - Ethertype of a packet 3084 * 3085 * Returns: 3086 * BCM_E_xxxx 3087 */ 3088 STATIC int 3089 get_td2_hash_ecmp(int unit, int ecmp_group, uint32 hash_index,uint32 hash_rh_index, bcm_if_t *nh_id, 3090 uint8 ecmp_rh_enable, uint32 ethertype) 3091 { 3092 uint32 ecmp_hash_field_upper_bits_count; 3093 3094 ecmp_count_entry_t ecmpc_entry; 3095 ecmp_entry_t ecmp_entry; 3096 initial_l3_ecmp_group_entry_t 3097 ecmp_group_entry; 3098 3099 uint32 ecmp_ptr = 0; 3100 uint32 ecmp_count = 0; 3101 uint32 hash_control; 3102 3103 uint32 ecmp_mask; 3104 uint32 ecmp_offset; 3105 uint32 ecmp_index; 3106 3107 uint32 ecmp_rh_flow_set_base; 3108 uint8 ecmp_rh_flow_set_size; 3109 uint32 resolved_member; 3110 uint8 resolved_member_valid; 3111 3112 /*register read*/ 3113 if (SOC_REG_FIELD_VALID(unit, HASH_CONTROLr, 3114 ECMP_HASH_FIELD_UPPER_BITS_COUNTf)) { 3115 SOC_IF_ERROR_RETURN 3116 (READ_HASH_CONTROLr(unit, &hash_control)); 3117 ecmp_hash_field_upper_bits_count = 3118 soc_reg_field_get(unit, HASH_CONTROLr, hash_control, 3119 ECMP_HASH_FIELD_UPPER_BITS_COUNTf); 3120 } else { 3121 ecmp_hash_field_upper_bits_count = 0x6; /* A0 bincomp value */ 3122 } 3123 3124 if (ecmp_rh_enable) { 3125 SOC_IF_ERROR_RETURN 3126 (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmp_group_entry)); 3127 ecmp_rh_flow_set_base = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmp_group_entry, RH_FLOW_SET_BASEf); 3128 ecmp_rh_flow_set_size = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmp_group_entry, RH_FLOW_SET_SIZEf); 3129 3130 perform_td2_rh(unit, ecmp_rh_flow_set_base, ecmp_rh_flow_set_size, RTAG7_RH_MODE_ECMP, hash_rh_index, 0, 3131 &resolved_member, &resolved_member_valid); 3132 3133 if (resolved_member_valid) { 3134 *nh_id = resolved_member & 0xffff; 3135 } else { 3136 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3137 (BSL_META_U(unit, 3138 "Hash calculation: Such Configuration is not supported: resolved_lag_member_valid==FALSE\n"))); 3139 return BCM_E_PARAM; 3140 } 3141 } else { 3142 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3143 * A ECMP_COUNT value of 0 implies 1 entry 3144 * a value of 1 implies 2 entries etc... 3145 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3146 */ 3147 SOC_IF_ERROR_RETURN 3148 (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_group, &ecmpc_entry)); 3149 3150 ecmp_ptr = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 3151 BASE_PTRf); 3152 ecmp_count = soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, 3153 COUNTf); 3154 switch (ecmp_hash_field_upper_bits_count) { 3155 case 0: 3156 ecmp_mask = 0x3ff; 3157 break; 3158 case 1: 3159 ecmp_mask = 0x7ff; 3160 break; 3161 case 2: 3162 ecmp_mask = 0xfff; 3163 break; 3164 case 3: 3165 ecmp_mask = 0x1fff; 3166 break; 3167 case 4: 3168 ecmp_mask = 0x3fff; 3169 break; 3170 case 5: 3171 ecmp_mask = 0x7fff; 3172 break; 3173 case 6: 3174 ecmp_mask = 0xffff; 3175 break; 3176 default: 3177 ecmp_mask = 0xffff; 3178 break; 3179 } 3180 3181 ecmp_offset = ((hash_index & ecmp_mask) % (ecmp_count + 1)) & 0x3FF; 3182 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3183 (BSL_META_U(unit, 3184 "\tECMP offset 0x%08x, ptr 0x%x\n"), 3185 ecmp_offset, ecmp_ptr)); 3186 ecmp_index = (ecmp_ptr + ecmp_offset) & 0x3fff; 3187 SOC_IF_ERROR_RETURN 3188 (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry)); 3189 3190 *nh_id = 3191 soc_L3_ECMPm_field32_get(unit, &ecmp_entry, 3192 NEXT_HOP_INDEXf); 3193 *nh_id = *nh_id & 0xffff; 3194 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3195 (BSL_META_U(unit, 3196 "\tECMP next hop HW index 0x%08x\n"), 3197 *nh_id)); 3198 } 3199 3200 return BCM_E_NONE; 3201 } 3202 #endif /* INCLUDE_L3 */ 3203 3204 /* helper function check if resilient hashing is enabled on a lag */ 3205 uint8 3206 check_td2_lag_rh_enable (int unit, int tgid, uint32 ethertype) 3207 { 3208 trunk_group_entry_t dst_tg_entry; 3209 uint8 rh_lag_group_enable = 0, rh_lag_ethertype_enable, lag_rh_enable=0; 3210 uint32 rh_flowset_table_config, enhanced_hash_control; 3211 3212 if(!soc_feature(unit, soc_feature_lag_resilient_hash)){ 3213 return lag_rh_enable; 3214 } 3215 3216 BCM_IF_ERROR_RETURN 3217 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &dst_tg_entry)); 3218 3219 SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control)); 3220 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 3221 rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, enhanced_hash_control, 3222 HGT_LAG_FLOWSET_TABLE_CONFIGf); 3223 rh_lag_group_enable = (soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry, 3224 TRUNK_MODEf)) == 3 ? 1 : 0; 3225 } else { 3226 rh_flowset_table_config = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control, 3227 RH_FLOWSET_TABLE_CONFIG_ENCODINGf); 3228 rh_lag_group_enable = soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry, ENHANCED_HASHING_ENABLEf); 3229 } 3230 3231 3232 rh_lag_ethertype_enable = check_td2_ether_type_eligibility_for_rh(unit, RTAG7_RH_MODE_LAG, ethertype); 3233 3234 if ((rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_HALF_AND_HALF) || 3235 (rh_flowset_table_config == ENHANCED_HASHING_CONTROLRH_FLOWSET_TABLE_CONFIG_ENCODING_ALL_LAG)) { 3236 lag_rh_enable = (rh_lag_group_enable && rh_lag_ethertype_enable); 3237 } 3238 return lag_rh_enable; 3239 } 3240 3241 /* helper function check if resilient hashing is enabled on a lag */ 3242 uint8 3243 check_td2_hgt_rh_enable (int unit, int hgtid, uint32 ethertype) 3244 { 3245 hg_trunk_group_entry_t hg_tg_entry; 3246 uint8 rh_hgt_group_enable = 0, rh_hgt_ethertype_enable, hgt_rh_enable = 0; 3247 uint32 rh_hgt_enable = 0, enhanced_hash_control; 3248 hg_trunk_mode_entry_t hg_trunk_mode_entry; 3249 3250 if(!soc_feature(unit, soc_feature_hg_resilient_hash)){ 3251 return hgt_rh_enable; 3252 } 3253 3254 SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control)); 3255 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 3256 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_MODEm(unit, MEM_BLOCK_ANY, hgtid, 3257 &hg_trunk_mode_entry)); 3258 rh_hgt_group_enable = soc_HG_TRUNK_MODEm_field32_get(unit, &hg_trunk_mode_entry, 3259 HG_TRUNK_LB_MODEf); 3260 SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROL_2r(unit, &enhanced_hash_control)); 3261 rh_hgt_enable = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, enhanced_hash_control, 3262 RH_DLB_SELECTIONf); 3263 3264 } else { 3265 BCM_IF_ERROR_RETURN 3266 (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, &hg_tg_entry)); 3267 rh_hgt_group_enable = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, ENHANCED_HASHING_ENABLEf); 3268 SOC_IF_ERROR_RETURN(READ_ENHANCED_HASHING_CONTROLr(unit, &enhanced_hash_control)); 3269 rh_hgt_enable = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, enhanced_hash_control, 3270 RH_HGT_ENABLEf); 3271 } 3272 3273 rh_hgt_ethertype_enable = check_td2_ether_type_eligibility_for_rh(unit, RTAG7_RH_MODE_HGT, ethertype); 3274 3275 hgt_rh_enable = (rh_hgt_enable && rh_hgt_group_enable && rh_hgt_ethertype_enable); 3276 3277 return hgt_rh_enable; 3278 } 3279 3280 /* 3281 * Function: 3282 * get_td2_hash_trunk 3283 * Description: 3284 * compute destination trunk member port 3285 * Parameters: 3286 * unit - StrataSwitch PCI device unit number (driver internal). 3287 * ecmp_group - multipath id 3288 * tgid - trunk port id 3289 * hash_index - hash value calculated from compute_td2_rtag7_hash_trunk 3290 * hash_rh_index - hash value calculated from compute_td2_rtag7_hash_rh_trunk 3291 * dst_tgid - where egress member port id is stored 3292 * hash_rh_value - flag indicating if rh is enable for this hashing calculation 3293 * ethertype - Ethertype of a packet 3294 * 3295 * Returns: 3296 * BCM_E_xxxx 3297 */ 3298 STATIC int 3299 get_td2_hash_trunk(int unit, int tgid, uint32 hash_index, 3300 bcm_gport_t *dst_tgid, uint32 hash_rh_value, 3301 uint8 lag_rh_enable, uint32 ethertype) 3302 { 3303 uint32 trunk_base; 3304 uint32 trunk_group_size; 3305 uint32 rtag; 3306 uint32 trunk_index; 3307 uint32 trunk_member_table_index; 3308 bcm_module_t mod_id; 3309 bcm_port_t port_id; 3310 int mod_is_local; 3311 trunk_member_entry_t trunk_member_entry; 3312 trunk_group_entry_t tg_entry, dst_tg_entry; 3313 _bcm_gport_dest_t dest; 3314 3315 uint32 lag_rh_flow_set_base; 3316 uint32 lag_rh_flow_set_size; 3317 3318 uint32 resolved_member; 3319 uint8 resolved_member_valid; 3320 3321 BCM_IF_ERROR_RETURN 3322 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &tg_entry)); 3323 3324 trunk_base = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf); 3325 trunk_group_size = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf); 3326 rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf); 3327 3328 if (rtag != 7){ 3329 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3330 (BSL_META_U(unit, 3331 "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"), 3332 rtag)); 3333 } 3334 3335 trunk_index = hash_index % (trunk_group_size + 1); 3336 trunk_member_table_index = (trunk_base + trunk_index) & 0x7ff; 3337 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3338 (BSL_META_U(unit, 3339 "\tTrunk HW index 0x%08x\n"), 3340 trunk_index)); 3341 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3342 (BSL_META_U(unit, 3343 "\tTrunk group size 0x%08x\n"), 3344 trunk_group_size)); 3345 3346 if (lag_rh_enable) { 3347 BCM_IF_ERROR_RETURN 3348 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tgid, &dst_tg_entry)); 3349 lag_rh_flow_set_base = soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry, RH_FLOW_SET_BASEf); 3350 lag_rh_flow_set_size = soc_TRUNK_GROUPm_field32_get(unit, &dst_tg_entry, RH_FLOW_SET_SIZEf); 3351 3352 perform_td2_rh(unit, lag_rh_flow_set_base, lag_rh_flow_set_size, RTAG7_RH_MODE_LAG, 0, hash_rh_value, 3353 &resolved_member, &resolved_member_valid); 3354 3355 if (resolved_member_valid) { 3356 port_id = resolved_member & 0x7f; 3357 mod_id = (resolved_member >> RH_LAG_FLOWSET_MOD_ID_SHIFT_VAL) & 0xff; 3358 } else { 3359 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3360 (BSL_META_U(unit, 3361 "Hash calculation: Such Configuration is not supported: \n"))); 3362 return BCM_E_PARAM; 3363 } 3364 } else { 3365 BCM_IF_ERROR_RETURN 3366 (READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index, 3367 &trunk_member_entry)); 3368 mod_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry, 3369 MODULE_IDf); 3370 port_id = soc_TRUNK_MEMBERm_field32_get(unit, &trunk_member_entry, 3371 PORT_NUMf); 3372 } 3373 3374 BCM_IF_ERROR_RETURN 3375 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id, 3376 &(dest.modid), &(dest.port))); 3377 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 3378 3379 BCM_IF_ERROR_RETURN 3380 (_bcm_esw_modid_is_local(unit, dest.modid, 3381 &mod_is_local)); 3382 if (mod_is_local) { 3383 if (IS_ST_PORT(unit, port_id)) { 3384 dest.modid = mod_id; 3385 dest.port = port_id; 3386 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 3387 } 3388 } 3389 3390 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_tgid)); 3391 3392 return BCM_E_NONE; 3393 } 3394 3395 /* 3396 * Function: 3397 * get_td2_hash_trunk_nuc 3398 * Description: 3399 * Compute non-unicast destination trunk member port 3400 * Parameters: 3401 * unit - StrataSwitch PCI device unit number (driver internal). 3402 * tgid - Trunk group id 3403 * fwd_reason - Flow foward reason. unicast, ipmc, l2mc, broadcast, dlf. 3404 * hash_index - Hash value calculated based on RTAG7 3405 * dst_gport - Where egress member port id is stored 3406 * 3407 * Returns: 3408 * BCM_E_xxxx 3409 */ 3410 STATIC int 3411 get_td2_hash_trunk_nuc(int unit, int tgid, 3412 bcm_switch_pkt_hash_info_fwd_reason_t fwd_reason, 3413 uint32 hash_index, bcm_gport_t *dst_gport) 3414 { 3415 int nuc_type, nuc_tbm_index; 3416 int modid, port; 3417 bcm_pbmp_t local_pbmp, block_mask_pbmp; 3418 trunk_bitmap_entry_t trunk_bitmap_entry; 3419 nonucast_trunk_block_mask_entry_t mask_entry; 3420 uint32 disable_flags = BCM_TRUNK_MEMBER_EGRESS_DISABLE; 3421 3422 switch(fwd_reason) { 3423 case bcmSwitchPktHashInfoFwdReasonIpmc: 3424 nuc_type = TRUNK_BLOCK_MASK_TYPE_IPMC; 3425 disable_flags |= BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE; 3426 break; 3427 case bcmSwitchPktHashInfoFwdReasonL2mc: 3428 nuc_type = TRUNK_BLOCK_MASK_TYPE_L2MC; 3429 disable_flags |= BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE; 3430 break; 3431 case bcmSwitchPktHashInfoFwdReasonBcast: 3432 nuc_type = TRUNK_BLOCK_MASK_TYPE_BCAST; 3433 disable_flags |= BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE; 3434 break; 3435 case bcmSwitchPktHashInfoFwdReasonDlf: 3436 nuc_type = TRUNK_BLOCK_MASK_TYPE_DLF; 3437 disable_flags |= BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE; 3438 break; 3439 default: 3440 return BCM_E_PARAM; 3441 } 3442 nuc_tbm_index = (nuc_type << 8) | (hash_index & 0xff); 3443 3444 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3445 (BSL_META_U(unit, 3446 "Nonuc-trunk table index = %d\n"), 3447 nuc_tbm_index)); 3448 3449 BCM_IF_ERROR_RETURN( 3450 READ_NONUCAST_TRUNK_BLOCK_MASKm(unit, MEM_BLOCK_ANY, 3451 nuc_tbm_index, &mask_entry)); 3452 soc_mem_pbmp_field_get(unit, NONUCAST_TRUNK_BLOCK_MASKm, &mask_entry, 3453 BLOCK_MASKf, &block_mask_pbmp); 3454 BCM_IF_ERROR_RETURN( 3455 READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tgid, &trunk_bitmap_entry)); 3456 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 3457 TRUNK_BITMAPf, &local_pbmp); 3458 3459 BCM_PBMP_REMOVE(local_pbmp, block_mask_pbmp); 3460 3461 if (BCM_PBMP_IS_NULL(local_pbmp)) { 3462 /* this means that member is not on local device, try SW prediction */ 3463 bcm_trunk_member_t member_array[BCM_TRUNK_MAX_PORTCNT]; 3464 int member_count; 3465 bcm_gport_t *port_array = NULL; 3466 int port_count, port_index = BCM_TRUNK_UNSPEC_INDEX; 3467 int region_size, i, all_local; 3468 bcm_trunk_info_t trunk_info; 3469 3470 bcm_trunk_info_t_init(&trunk_info); 3471 3472 BCM_IF_ERROR_RETURN 3473 (bcm_esw_trunk_get(unit, tgid, &trunk_info, BCM_TRUNK_MAX_PORTCNT, 3474 member_array, &member_count)); 3475 3476 /* coverity[dead_error_condition] */ 3477 switch(fwd_reason) { 3478 case bcmSwitchPktHashInfoFwdReasonIpmc: 3479 port_index = trunk_info.ipmc_index; 3480 break; 3481 case bcmSwitchPktHashInfoFwdReasonL2mc: 3482 port_index = trunk_info.mc_index; 3483 break; 3484 case bcmSwitchPktHashInfoFwdReasonBcast: 3485 case bcmSwitchPktHashInfoFwdReasonDlf: 3486 port_index = trunk_info.dlf_index; 3487 break; 3488 default: 3489 return BCM_E_PARAM; 3490 } 3491 3492 if (port_index != BCM_TRUNK_UNSPEC_INDEX) { 3493 if (port_index >= member_count) { 3494 *dst_gport = -1; 3495 return BCM_E_NOT_FOUND; 3496 } 3497 3498 *dst_gport = member_array[port_index].gport; 3499 3500 } else { 3501 port_array = sal_alloc(member_count * sizeof(bcm_gport_t), 3502 "port_array"); 3503 if (port_array == NULL) { 3504 return BCM_E_MEMORY; 3505 } 3506 3507 port_count = 0; 3508 all_local = TRUE; 3509 for (i = 0; i < member_count; i++) { 3510 if (member_array[i].flags & disable_flags) { 3511 continue; 3512 } 3513 port = member_array[i].gport; 3514 port_array[port_count++] = port; 3515 if (all_local) { 3516 if (BCM_FAILURE(bcm_esw_port_local_get(unit, port, 3517 &port))) { 3518 all_local = FALSE; 3519 } 3520 } 3521 } 3522 /* All ports are disabled */ 3523 if (port_count == 0) { 3524 *dst_gport = -1; 3525 sal_free(port_array); 3526 return BCM_E_NOT_FOUND; 3527 } 3528 if (all_local || port_count > BCM_SWITCH_TRUNK_MAX_PORTCNT) { 3529 region_size = soc_mem_index_count(unit, NONUCAST_TRUNK_BLOCK_MASKm) / 4; 3530 } else { 3531 region_size = BCM_XGS3_TRUNK_MAX_PORTCNT; 3532 } 3533 port_index = (nuc_tbm_index % region_size) % port_count; 3534 3535 *dst_gport = port_array[port_index]; 3536 3537 sal_free(port_array); 3538 3539 } 3540 } else { 3541 _bcm_gport_dest_t dest; 3542 3543 /*Each index only has one egress port */ 3544 BCM_PBMP_ITER(local_pbmp, port) { 3545 break; 3546 } 3547 3548 if (port == BCM_PBMP_PORT_MAX) { 3549 /* If not found in iteration, return not found. It never be here */ 3550 *dst_gport = -1; 3551 return BCM_E_NOT_FOUND; 3552 } 3553 3554 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 3555 3556 BCM_IF_ERROR_RETURN 3557 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, modid, port, 3558 &(dest.modid), &(dest.port))); 3559 if (IS_ST_PORT(unit, port)) { 3560 dest.modid = modid; 3561 dest.port = port; 3562 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 3563 } else { 3564 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 3565 } 3566 3567 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_gport)); 3568 } 3569 3570 return BCM_E_NONE; 3571 } 3572 3573 STATIC int 3574 get_td2_hash_hg_trunk(int unit, int hgtid, uint32 hash_index, 3575 bcm_gport_t *dst_tgid, uint32 hash_rh_value, 3576 uint8 lag_rh_enable, uint32 ethertype) 3577 { 3578 uint32 trunk_base; 3579 uint32 trunk_group_size; 3580 uint32 rtag; 3581 uint32 trunk_index; 3582 uint32 trunk_member_table_index; 3583 bcm_module_t mod_id; 3584 bcm_port_t port_id; 3585 hg_trunk_member_entry_t hg_trunk_member_entry; 3586 hg_trunk_group_entry_t hg_tg_entry; 3587 rh_hgt_group_control_entry_t rh_hgt_group_control_entry; 3588 _bcm_gport_dest_t dest; 3589 3590 uint32 hgt_rh_flow_set_base; 3591 uint32 hgt_rh_flow_set_size; 3592 3593 uint32 resolved_member; 3594 uint8 resolved_member_valid; 3595 3596 BCM_IF_ERROR_RETURN 3597 (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, &hg_tg_entry)); 3598 3599 trunk_base = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, BASE_PTRf); 3600 trunk_group_size = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, TG_SIZEf); 3601 rtag = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, RTAGf); 3602 3603 if (rtag != 7) { 3604 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3605 (BSL_META_U(unit, 3606 "Hash calculation: uport only RTAG7 calc no support for rtag %d\n"), 3607 rtag)); 3608 } 3609 3610 trunk_index = hash_index % (trunk_group_size + 1); 3611 trunk_member_table_index = (trunk_base + trunk_index) & 0xff; 3612 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3613 (BSL_META_U(unit, 3614 "\tHG Trunk HW index 0x%08x\n"), 3615 trunk_index)); 3616 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3617 (BSL_META_U(unit, 3618 "\tHG Trunk group size 0x%08x\n"), 3619 trunk_group_size)); 3620 3621 if (lag_rh_enable) { 3622 #ifdef BCM_TRIDENT3_SUPPORT 3623 if (soc_feature(unit, soc_feature_td3_style_dlb_rh)){ 3624 hgt_rh_flow_set_base = soc_HG_TRUNK_GROUPm_field32_get(unit, 3625 &hg_tg_entry, RH_FLOW_SET_BASEf); 3626 hgt_rh_flow_set_size = soc_HG_TRUNK_GROUPm_field32_get(unit, 3627 &hg_tg_entry, RH_FLOW_SET_SIZEf); 3628 } else 3629 #endif 3630 { 3631 BCM_IF_ERROR_RETURN 3632 (READ_RH_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, hgtid, 3633 &rh_hgt_group_control_entry)); 3634 hgt_rh_flow_set_base = soc_RH_HGT_GROUP_CONTROLm_field32_get(unit, 3635 &rh_hgt_group_control_entry, FLOW_SET_BASEf); 3636 hgt_rh_flow_set_size = soc_RH_HGT_GROUP_CONTROLm_field32_get(unit, 3637 &rh_hgt_group_control_entry, FLOW_SET_SIZEf); 3638 } 3639 3640 perform_td2_rh(unit, hgt_rh_flow_set_base, hgt_rh_flow_set_size, RTAG7_RH_MODE_HGT, 0, hash_rh_value, 3641 &resolved_member, &resolved_member_valid); 3642 3643 if (resolved_member_valid) { 3644 port_id = resolved_member & 0x7f; 3645 } else { 3646 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3647 (BSL_META_U(unit, 3648 "Hash calculation: Such Configuration is not supported: \n"))); 3649 return BCM_E_PARAM; 3650 } 3651 } else { 3652 BCM_IF_ERROR_RETURN 3653 (READ_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, trunk_member_table_index, 3654 &hg_trunk_member_entry)); 3655 port_id = soc_HG_TRUNK_MEMBERm_field32_get(unit, &hg_trunk_member_entry, 3656 PORT_NUMf); 3657 } 3658 3659 if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &mod_id))) { 3660 mod_id = 0; 3661 } 3662 3663 BCM_IF_ERROR_RETURN 3664 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod_id, port_id, 3665 &(dest.modid), &(dest.port))); 3666 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 3667 BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, dst_tgid)); 3668 3669 return BCM_E_NONE; 3670 } 3671 3672 /* 3673 * Function: 3674 * _bcm_td2_switch_pkt_info_hash_get 3675 * Description: 3676 * main td2 hash get function 3677 * 3678 * Parameters 3679 * unit - StrataSwitch PCI device unit number (driver internal). 3680 * pkt_info - struct that carries packet's l2, l3, and l4 information 3681 * dst_gport - hashing resolved trunk member port as a return val 3682 * dst_intf - hashing resolved ecmp member port as a return val 3683 * or entropy label of vxlan as a return val 3684 * Returns: 3685 * BCM_E_xxxx 3686 */ 3687 int 3688 _bcm_td2_switch_pkt_info_hash_get(int unit, 3689 bcm_switch_pkt_info_t *pkt_info, 3690 bcm_gport_t *dst_gport, 3691 bcm_if_t *dst_intf) 3692 { 3693 bcm_rtag7_base_hash_t hash_res; 3694 int pc_out, mod_is_local; 3695 bcm_gport_t port; 3696 bcm_trunk_t tid; 3697 int id; 3698 uint32 hash_value; 3699 uint32 hash_rh_value; 3700 bcm_ethertype_t ethertype; 3701 int rc; 3702 3703 if (pkt_info == NULL) { 3704 return BCM_E_PARAM; 3705 } 3706 3707 if (!_BCM_SWITCH_PKT_INFO_FLAG_TEST(pkt_info, SRC_GPORT)) { 3708 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3709 (BSL_META_U(unit, 3710 "Hash calculation: source gport value missing\n"))); 3711 return BCM_E_PARAM; 3712 } 3713 3714 rc = _bcm_esw_gport_resolve(unit, pkt_info->src_gport, 3715 &(hash_res.src_modid), 3716 &(hash_res.src_port), 3717 &tid, &id); 3718 if (rc != BCM_E_NONE) { 3719 return rc; 3720 } 3721 3722 if ((-1 != id) || (-1 != tid)) { 3723 /* Must be single system port */ 3724 return BCM_E_PORT; 3725 } 3726 3727 /* Load balancing retrieval */ 3728 BCM_IF_ERROR_RETURN( 3729 _bcm_esw_modid_is_local(unit, hash_res.src_modid, &mod_is_local)); 3730 if (mod_is_local) { 3731 BCM_IF_ERROR_RETURN 3732 (bcm_esw_port_local_get(unit, pkt_info->src_gport, &port)); 3733 hash_res.dev_src_port = port; 3734 } else { 3735 hash_res.dev_src_port = -1; 3736 if (BCM_GPORT_IS_PROXY(pkt_info->src_gport)) { 3737 port = pkt_info->src_gport; 3738 } else { 3739 BCM_GPORT_PROXY_SET(port, 3740 hash_res.src_modid, hash_res.src_port); 3741 } 3742 } 3743 BCM_IF_ERROR_RETURN 3744 (bcm_esw_port_control_get(unit, port, 3745 bcmPortControlLoadBalancingNumber, 3746 &pc_out)); 3747 hash_res.rtag7_port_lbn = pc_out; 3748 3749 /* check if the foward reason of packet is all non-uc packet or bit 40 in the mac DA is one. */ 3750 hash_res.is_nonuc = pkt_info->fwd_reason || BCM_MAC_IS_MCAST(pkt_info->dst_mac); 3751 3752 BCM_IF_ERROR_RETURN 3753 (main_td2_do_rtag7_hashing(unit, pkt_info, &hash_res)); 3754 BCM_IF_ERROR_RETURN 3755 (main_td2_compute_lbid(unit, &hash_res)); 3756 3757 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3758 (BSL_META_U(unit, 3759 "Hash status: \n"))); 3760 if (hash_res.hash_a_valid) { 3761 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3762 (BSL_META_U(unit, 3763 "\tRTAG7 A0 0x%08x\n"), 3764 hash_res.rtag7_hash16_value_a_0)); 3765 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3766 (BSL_META_U(unit, 3767 "\tRTAG7 A1 0x%08x\n"), 3768 hash_res.rtag7_hash16_value_a_1)); 3769 } else { 3770 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3771 (BSL_META_U(unit, 3772 "\tRTAG7 A hashes invalid due to missing packet info\n"))); 3773 } 3774 if (hash_res.hash_b_valid) { 3775 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3776 (BSL_META_U(unit, 3777 "\tRTAG7 B0 0x%08x\n"), 3778 hash_res.rtag7_hash16_value_b_0)); 3779 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3780 (BSL_META_U(unit, 3781 "\tRTAG7 B1 0x%08x\n"), 3782 hash_res.rtag7_hash16_value_b_1)); 3783 } else { 3784 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3785 (BSL_META_U(unit, 3786 "\tRTAG7 B hashes invalid due to missing packet info\n"))); 3787 } 3788 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3789 (BSL_META_U(unit, 3790 "\tRTAG7 LBN 0x%08x\n"), 3791 hash_res.rtag7_port_lbn)); 3792 if (hash_res.lbid_hash_valid){ 3793 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3794 (BSL_META_U(unit, 3795 "\tRTAG7 LBID 0x%08x\n"), 3796 hash_res.rtag7_lbid_hash)); 3797 } else { 3798 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3799 (BSL_META_U(unit, 3800 "\tRTAG7 LBID not valid due to non-RTAG7 configuration\n"))); 3801 } 3802 3803 ethertype = pkt_info->ethertype; 3804 3805 #ifdef INCLUDE_L3 3806 if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_MULTIPATH)) { 3807 bcm_if_t nh_id; 3808 uint8 ecmp_rh_enable; 3809 nh_id = 0; 3810 3811 if (dst_intf == NULL) { 3812 return BCM_E_PARAM; 3813 } 3814 3815 if (0 != (check_td2_ecmp_rh_enable(unit, 3816 pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), ethertype ))) { 3817 ecmp_rh_enable = TRUE; 3818 hash_value = 0; 3819 rc = compute_td2_ecmp_rh_hash(unit, &hash_res, &hash_rh_value); 3820 if (rc != BCM_E_NONE) { 3821 return rc; 3822 } 3823 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3824 (BSL_META_U(unit, 3825 "\tECMP Hash rh value 0x%08x\n"), 3826 hash_rh_value)); 3827 } else { 3828 ecmp_rh_enable = FALSE; 3829 hash_rh_value = 0; 3830 rc = compute_td2_ecmp_hash(unit, pkt_info->flags, &hash_res, &hash_value); 3831 if (rc != BCM_E_NONE) { 3832 return rc; 3833 } 3834 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3835 (BSL_META_U(unit, 3836 "\tECMP Hash value 0x%08x\n"), 3837 hash_value)); 3838 } 3839 3840 rc = get_td2_hash_ecmp(unit, 3841 pkt_info->mpintf - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), 3842 hash_value, hash_rh_value,&nh_id, 3843 ecmp_rh_enable, ethertype); 3844 /* Convert to egress object format */ 3845 *dst_intf = nh_id + BCM_XGS3_EGRESS_IDX_MIN(unit); 3846 } else 3847 #endif /* INCLUDE_L3 */ 3848 if (0 != (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_TRUNK)) { 3849 int member_count; 3850 bcm_trunk_t trunk; 3851 uint8 lag_rh_enable = FALSE; 3852 uint8 hgt_rh_enable = FALSE; 3853 bcm_trunk_chip_info_t ti; 3854 3855 if (dst_gport == NULL) { 3856 return BCM_E_PARAM; 3857 } 3858 3859 trunk = BCM_TRUNK_INVALID; 3860 if (!BCM_GPORT_IS_TRUNK(pkt_info->trunk_gport)) { 3861 return BCM_E_PORT; 3862 } 3863 trunk = BCM_GPORT_TRUNK_GET(pkt_info->trunk_gport); 3864 BCM_IF_ERROR_RETURN 3865 (bcm_esw_trunk_get(unit, trunk, NULL, 0, NULL, &member_count)); 3866 if (0 == member_count) { 3867 /* Return failure for no trunk members */ 3868 return BCM_E_FAIL; 3869 } 3870 3871 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &ti)); 3872 3873 if (trunk >= ti.trunk_id_min && trunk <= ti.trunk_id_max) { 3874 rc = compute_td2_rtag7_hash_trunk(unit, &hash_res, &hash_value); 3875 3876 if (rc != BCM_E_NONE) { 3877 return rc; 3878 } 3879 3880 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3881 (BSL_META_U(unit, 3882 "\tTrunk Hash value 0x%08x\n"), 3883 hash_value)); 3884 3885 if (0 != (check_td2_lag_rh_enable(unit, trunk, 3886 ethertype))) { 3887 lag_rh_enable = TRUE; 3888 rc = 3889 compute_td2_rtag7_hash_rh_trunk(unit, &hash_res, &hash_rh_value); 3890 3891 if (rc != BCM_E_NONE) { 3892 return rc; 3893 } 3894 } else { 3895 lag_rh_enable = FALSE; 3896 hash_rh_value = 0; 3897 } 3898 3899 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3900 (BSL_META_U(unit, 3901 "\tTrunk RH Hash value 0x%08x\n"), 3902 hash_rh_value)); 3903 3904 if (hash_res.is_nonuc) { 3905 BCM_IF_ERROR_RETURN 3906 (get_td2_hash_trunk_nuc(unit, trunk, pkt_info->fwd_reason, 3907 hash_value, dst_gport)); 3908 } else { 3909 BCM_IF_ERROR_RETURN 3910 (get_td2_hash_trunk(unit, trunk, 3911 hash_value, dst_gport, hash_rh_value, 3912 lag_rh_enable, ethertype)); 3913 } 3914 } else if (trunk >= ti.trunk_fabric_id_min && trunk <= ti.trunk_fabric_id_max) { 3915 3916 rc = compute_td2_rtag7_hash_hg_trunk(unit, &hash_res, &hash_value); 3917 if (rc != BCM_E_NONE) { 3918 return rc; 3919 } 3920 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3921 (BSL_META_U(unit, 3922 "\tHG-Trunk Hash value 0x%08x\n"), 3923 hash_value)); 3924 3925 if (0 != (check_td2_hgt_rh_enable(unit, trunk - ti.trunk_fabric_id_min, 3926 ethertype))) { 3927 hgt_rh_enable = TRUE; 3928 rc = compute_td2_rtag7_hash_rh_hg_trunk(unit, &hash_res, &hash_rh_value); 3929 3930 if (rc != BCM_E_NONE) { 3931 return rc; 3932 } 3933 } else { 3934 hgt_rh_enable = FALSE; 3935 hash_rh_value = 0; 3936 } 3937 3938 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3939 (BSL_META_U(unit, 3940 "\tHG-Trunk RH Hash value 0x%08x\n"), 3941 hash_rh_value)); 3942 BCM_IF_ERROR_RETURN 3943 (get_td2_hash_hg_trunk(unit, trunk - ti.trunk_fabric_id_min, 3944 hash_value, dst_gport, hash_rh_value, 3945 hgt_rh_enable, ethertype)); 3946 3947 } 3948 } 3949 /* vxlan hashing resolution */ 3950 else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_UDP_SOURCE_PORT) { 3951 /* coverity[negative_returns : FALSE] */ 3952 rc = compute_td2_rtag7_vxlan(unit, &hash_res, &hash_value); 3953 if (rc != BCM_E_NONE) { 3954 return rc; 3955 } 3956 LOG_VERBOSE(BSL_LS_BCM_COMMON, 3957 (BSL_META_U(unit, 3958 "\tVXlan Hash value 0x%08x\n"), 3959 hash_value)); 3960 *dst_intf = hash_value; 3961 } else if (pkt_info->flags & BCM_SWITCH_PKT_INFO_HASH_LBID) { 3962 /* LBID hashing resolution */ 3963 if (dst_intf == NULL || hash_res.lbid_hash_valid == 0) { 3964 return BCM_E_FAIL; 3965 } else { 3966 *dst_intf = hash_res.rtag7_lbid_hash; 3967 } 3968 } else { 3969 return BCM_E_PARAM; 3970 } 3971 3972 return BCM_E_NONE; 3973 } 3974