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