hash.c (26098B)
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 * HashDestination commands 8 */ 9 10 #include <appl/diag/system.h> 11 #include <appl/diag/parse.h> 12 #include <appl/diag/dport.h> 13 #include <shared/bsl.h> 14 #include <bcm/error.h> 15 #include <bcm/stack.h> 16 #ifdef INCLUDE_L3 17 #include <bcm/l3.h> 18 #ifdef BCM_TOMAHAWK_SUPPORT 19 #include <bcm_int/esw/firebolt.h> 20 #endif 21 #endif 22 #include <bcm/trunk.h> 23 #include <bcm/switch.h> 24 25 #if defined(BCM_ESW_SUPPORT) 26 #include <bcm_int/esw/port.h> 27 #endif 28 29 #define HASH_DESTINATION_ERROR_PRINT(_r) \ 30 do { \ 31 cli_out(\ 32 "HashDestination: %s\n", bcm_errmsg(_r)); \ 33 } while(0) 34 35 36 #define DYNAMIC_ETHERTYPE_ELIGIBLE 0x1 37 #define DYNAMIC_ETHERTYPE_INNER 0x2 38 39 #define ETHERTYPE_ELIGIBILITY_MAP_TABLE_SIZE_MAX 16 /* maximum ELIGIBILITY ethertype size */ 40 41 #define ETHERTYPE_IPV6 0x86dd /* ipv6 ethertype */ 42 #define ETHERTYPE_IPV4 0x0800 /* ipv4 ethertype */ 43 #define ETHERTYPE_MIN 0x0600 /* minimum ethertype for hashing */ 44 45 #define IP_PROT_TCP 0x6 /* TCP protocol number */ 46 #define IP_PROT_UDP 0x11 /* TCP protocol number */ 47 48 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || \ 49 defined(BCM_GREYHOUND2_SUPPORT) 50 /* Packet info flags for HashDestination. */ 51 #define BCM_HD_FLAGS_STR \ 52 "SRC_GPORT", \ 53 "VLAN", \ 54 "ETHERTYPE", \ 55 "SRC_MAC", \ 56 "DST_MAC", \ 57 "SRC_IP", \ 58 "DST_IP", \ 59 "SRC_IPV6", \ 60 "DST_IPV6", \ 61 "PROTOCOL", \ 62 "SRC_L4_PORT", \ 63 "DST_L4_PORT", \ 64 "HASH_TRUNK", \ 65 "HASH_MULTIPATH", \ 66 "UDP_SOURCE_PORT", \ 67 "LBID" 68 69 STATIC char *hd_flags_names[] = { 70 BCM_HD_FLAGS_STR 71 }; 72 73 74 STATIC char *hd_resource_group_names[] = { 75 #ifdef INCLUDE_L3 76 "ECMP", 77 #endif 78 "LAG", 79 "HGT", 80 "ANY", 81 NULL 82 }; 83 84 STATIC char *hd_pkt_forward_reason_names[] = { 85 BCM_SWITCH_PKT_HASH_INFO_FWD_REASON_STRINGS, 86 NULL 87 }; 88 89 STATIC char *hd_calc_info_names[] = { 90 "UDP_SOURCE_PORT", 91 "LBID", 92 NULL 93 }; 94 95 #ifdef BCM_TRIUMPH3_SUPPORT 96 STATIC int (*bcm_hd_ethertype_set[])(int, 97 uint32, int, int*) = { 98 #ifdef INCLUDE_L3 99 bcm_l3_egress_ecmp_ethertype_set, 100 #endif 101 bcm_trunk_ethertype_set, 102 bcm_trunk_ethertype_set, 103 NULL 104 }; 105 106 STATIC int (*bcm_hd_ethertype_get[])(int, 107 uint32*, int, int*, int*) = { 108 #ifdef INCLUDE_L3 109 bcm_l3_egress_ecmp_ethertype_get, 110 #endif 111 bcm_trunk_ethertype_get, 112 bcm_trunk_ethertype_get, 113 NULL 114 }; 115 #endif 116 117 char hash_destination_usage[] = 118 "Usages:\n\t" 119 #ifdef COMPILER_STRING_CONST_LIMIT 120 "hd <option> [args...]\n\t" 121 #else 122 #ifdef BCM_TRIUMPH3_SUPPORT 123 "hd ethertype mode [Group=ECMP|LAG|HGT] [Eligible=T|F] [Inner=T|F]\n\t" 124 "hd ethertype add [Group=ECMP|LAG|HGT] [EtherType=<0xHHHH>]\n\t" 125 "hd ethertype delete [Group=ECMP|LAG|HGT] [EtherType=<0xHHHH>]\n\t" 126 "hd ethertype show [Group=ECMP|LAG|HGT]\n\t" 127 #endif 128 "hd dest get [Group=ECMP|LAG|HGT|ANY] [GID=<id>]\n\t" 129 " [Port=<port#>] [Module=<modid>] [Untagged=T|F]\n\t" 130 " [DestMac=<mac>] [SrcMac=<mac>] [Vlan=<vid>] [EtherType=<0xHHHH>]\n\t" 131 " [SrcIp=<ip4>] [DestIp=<ip4>] [SIp6=<ip6>] [DIp6=<ip6>]\n\t" 132 " [PROTocol=<Pid>] [L4SrcPort=<num>] [L4DstPort=<num>]\n\t" 133 " [FwdReason=Unicast|Ipmc|L2mc|Bcast|Dlf]\n\t" 134 " [CalcInfo=UDP_SOURCE_PORT|LBID]\n\t" 135 #endif 136 "\n" 137 ; 138 139 140 #ifdef BCM_TRIUMPH3_SUPPORT 141 STATIC cmd_result_t 142 _cmd_hd_ethertype(int unit, args_t *a) 143 { 144 char *subcmd = NULL; 145 parse_table_t pt; 146 int r = BCM_E_UNAVAIL; 147 int i, gid, retCode = CMD_OK; 148 int group_all = 0, arg_group = -1, 149 arg_eligible = -1, arg_inner = -1, arg_ethertype = 0xffff; 150 uint32 flags, origin_flags; 151 int ethertype_count = -1, cnt = 0; 152 int ethertype_array[ETHERTYPE_ELIGIBILITY_MAP_TABLE_SIZE_MAX]; 153 154 if ((subcmd = ARG_GET(a)) == NULL) { 155 return CMD_USAGE; 156 } 157 158 if (ARG_CNT(a) == 0) { 159 group_all = 1; 160 } else { 161 parse_table_init(unit, &pt); 162 parse_table_add(&pt, "Group", PQ_DFL|PQ_MULTI, 163 0, &arg_group, hd_resource_group_names); 164 165 if (!sal_strcasecmp(subcmd, "mode")) { 166 /* BCM.0> hd eth mode ... */ 167 parse_table_add(&pt, "Eligible", PQ_DFL|PQ_BOOL, 168 0, &arg_eligible, NULL); 169 parse_table_add(&pt, "Inner", PQ_DFL|PQ_BOOL, 170 0, &arg_inner, NULL); 171 } else 172 if (!sal_strcasecmp(subcmd, "add") || 173 !sal_strcasecmp(subcmd, "delete")) { 174 /* BCM.0> hd eth add/delete ... */ 175 parse_table_add(&pt, "EtherType", PQ_DFL|PQ_HEX, 176 0, &arg_ethertype, NULL); 177 } 178 179 if (!parseEndOk(a, &pt, &retCode)) { 180 return retCode; 181 } 182 183 if (arg_group < 0) { 184 group_all = 1; 185 } 186 } 187 188 for (gid = 0; gid < COUNTOF(hd_resource_group_names) - 1; gid++) { 189 if (group_all == 1 || arg_group == gid) { 190 #ifdef INCLUDE_L3 191 if (!sal_strcasecmp(hd_resource_group_names[gid], "ECMP")) { 192 flags = BCM_L3_ECMP_DYNAMIC_ETHERTYPE_RESILIENT; 193 } else 194 #endif 195 { 196 flags = BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT; 197 if (!sal_strcasecmp(hd_resource_group_names[gid], "LAG")) { 198 flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_TRUNK; 199 } else if (!sal_strcasecmp(hd_resource_group_names[gid], "HGT")) { 200 flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_FABRIC_TRUNK; /*HGT*/ 201 } else { 202 r = BCM_E_PARAM; 203 HASH_DESTINATION_ERROR_PRINT(r); 204 return CMD_FAIL; 205 } 206 } 207 208 ethertype_count = -1; 209 210 r = bcm_hd_ethertype_get[gid](unit, 211 &flags, ethertype_count, ethertype_array, ðertype_count); 212 if (BCM_FAILURE(r)) { 213 HASH_DESTINATION_ERROR_PRINT(r); 214 return CMD_FAIL; 215 } 216 217 origin_flags = flags; 218 219 if (!sal_strcasecmp(subcmd, "mode")) { 220 if (arg_eligible < 0 && arg_inner < 0) { 221 return CMD_USAGE; 222 } 223 224 flags &= ~(DYNAMIC_ETHERTYPE_INNER | DYNAMIC_ETHERTYPE_ELIGIBLE); 225 226 if (arg_eligible) { 227 flags |= DYNAMIC_ETHERTYPE_ELIGIBLE; 228 } 229 230 if (arg_inner) { 231 flags |= DYNAMIC_ETHERTYPE_INNER; 232 } 233 234 if (flags == origin_flags) { 235 continue; 236 } 237 } else 238 if (!sal_strcasecmp(subcmd, "add")) { 239 if (arg_ethertype == 0xffff) { 240 return CMD_USAGE; 241 } 242 243 if (ethertype_count >= ETHERTYPE_ELIGIBILITY_MAP_TABLE_SIZE_MAX) { 244 r = BCM_E_FULL; 245 HASH_DESTINATION_ERROR_PRINT(r); 246 return CMD_FAIL; 247 } 248 for (i = 0; i < ethertype_count; i++) { 249 if (ethertype_array[i] == arg_ethertype) { 250 r = BCM_E_EXISTS; 251 HASH_DESTINATION_ERROR_PRINT(r); 252 return CMD_FAIL; 253 } 254 } 255 ethertype_array[i] = arg_ethertype; 256 ethertype_count++; 257 } else 258 if (!sal_strcasecmp(subcmd, "delete")) { 259 if (arg_ethertype == 0xffff) { 260 return CMD_USAGE; 261 } 262 263 if (ethertype_count <= 0) { 264 r = BCM_E_EMPTY; 265 HASH_DESTINATION_ERROR_PRINT(r); 266 return CMD_FAIL; 267 } 268 269 for (i = 0; i < ethertype_count; i++) { 270 if (ethertype_array[i] == arg_ethertype) { 271 break; 272 } 273 } 274 if (i == ethertype_count) { 275 r = BCM_E_NOT_FOUND; 276 HASH_DESTINATION_ERROR_PRINT(r); 277 return CMD_FAIL; 278 } 279 280 ethertype_array[i] = ethertype_array[ethertype_count - 1]; 281 ethertype_count--; 282 } 283 284 r = bcm_hd_ethertype_set[gid](unit, 285 flags, ethertype_count, ethertype_array); 286 if (BCM_FAILURE(r)) { 287 HASH_DESTINATION_ERROR_PRINT(r); 288 return CMD_FAIL; 289 } 290 291 if (!sal_strcasecmp(subcmd, "show")) { 292 /* BCM.0> hd eth show ... */ 293 cli_out(" %s:\n", hd_resource_group_names[gid]); 294 cli_out(" EtherType: %s %s Cnt:%d\n\t", 295 flags & DYNAMIC_ETHERTYPE_INNER ? "INNER":"OUTER", 296 flags & DYNAMIC_ETHERTYPE_ELIGIBLE ? "Eligible":"Ineligible", 297 ethertype_count); 298 for (i = 0, cnt = 0; i < ethertype_count; i++) { 299 cnt++; 300 cli_out("0x%04x %s", 301 ethertype_array[i], (cnt % 4 == 0) ? "\n\t":""); 302 } 303 cli_out("\n"); 304 } 305 } 306 } 307 308 return CMD_OK; 309 } 310 #endif 311 312 313 STATIC cmd_result_t 314 _cmd_hd_dest_get(int unit, args_t *a) 315 { 316 parse_table_t pt; 317 int r = BCM_E_UNAVAIL; 318 int i, retCode = CMD_OK; 319 int arg_group = -1, arg_gid = -1; 320 int arg_untagged = FALSE; 321 int arg_port = BCM_GPORT_INVALID, arg_modid = BCM_MODID_INVALID, 322 arg_vlan = VLAN_ID_INVALID, arg_ethertype = 0xffff; 323 int arg_fwd_reason = bcmSwitchPktHashInfoFwdReasonUnicast; 324 int arg_calc_info = -1; 325 sal_mac_addr_t default_macaddr = {0, 0, 0, 0, 0, 0x1}; 326 sal_mac_addr_t arg_srcmac = {0, 0, 0, 0, 0, 0x1}; 327 sal_mac_addr_t arg_dstmac = {0, 0, 0, 0, 0, 0x1}; 328 bcm_trunk_t tid; 329 bcm_trunk_chip_info_t ti; 330 bcm_trunk_info_t t_add_info; 331 bcm_trunk_member_t *member_array = NULL; 332 int member_count = 0; 333 #ifdef INCLUDE_L3 334 bcm_ip_t arg_sip_addr = 0, arg_ip_addr = 0; 335 bcm_ip6_t arg_sip6_addr, arg_ip6_addr, default_ip6_addr; 336 int arg_protocol = -1, arg_l4srcport = -1, arg_l4dstport = -1; 337 338 int intf_count = 0; 339 bcm_if_t *mpath_egr = NULL; 340 #endif 341 342 bcm_switch_pkt_info_t pkt_info; 343 bcm_gport_t dst_gport = BCM_GPORT_INVALID; 344 bcm_if_t dst_intf = BCM_IF_INVALID; 345 346 if (ARG_CNT(a) == 0) { 347 return CMD_USAGE; 348 } 349 350 #ifdef INCLUDE_L3 351 sal_memset(arg_sip6_addr, 0, BCM_IP6_ADDRLEN); 352 sal_memset(arg_ip6_addr, 0, BCM_IP6_ADDRLEN); 353 sal_memset(default_ip6_addr, 0, BCM_IP6_ADDRLEN); 354 #endif 355 356 parse_table_init(unit, &pt); 357 parse_table_add(&pt, "Group", PQ_DFL|PQ_MULTI, 358 0, &arg_group, hd_resource_group_names); 359 parse_table_add(&pt, "GID", PQ_DFL|PQ_HEX, 360 0, &arg_gid, NULL); 361 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 362 0, &arg_port, NULL); 363 parse_table_add(&pt, "Modid", PQ_DFL|PQ_INT, 364 0, &arg_modid, NULL); 365 parse_table_add(&pt, "Untagged", PQ_DFL|PQ_BOOL, 366 0, &arg_untagged, NULL); 367 parse_table_add(&pt, "DestMac", PQ_DFL|PQ_MAC, 368 0, &arg_dstmac, NULL); 369 parse_table_add(&pt, "SrcMac", PQ_DFL|PQ_MAC, 370 0, &arg_srcmac, NULL); 371 parse_table_add(&pt, "Vlan", PQ_DFL|PQ_INT, 372 0, &arg_vlan, NULL); 373 parse_table_add(&pt, "EtherType", PQ_DFL|PQ_HEX, 374 0, &arg_ethertype, NULL); 375 #ifdef INCLUDE_L3 376 parse_table_add(&pt, "SrcIp", PQ_DFL|PQ_IP, 377 0, &arg_sip_addr, NULL); 378 parse_table_add(&pt, "DestIp", PQ_DFL|PQ_IP, 379 0, &arg_ip_addr, NULL); 380 parse_table_add(&pt, "SIp6", PQ_DFL|PQ_IP6, 381 0, (void *)&arg_sip6_addr, NULL); 382 parse_table_add(&pt, "DIp6", PQ_DFL|PQ_IP6, 383 0, (void *)&arg_ip6_addr, NULL); 384 parse_table_add(&pt, "PROTocol", PQ_DFL|PQ_INT, 385 0, &arg_protocol, NULL); 386 parse_table_add(&pt, "L4SrcPort", PQ_DFL|PQ_INT, 387 0, &arg_l4srcport, NULL); 388 parse_table_add(&pt, "L4DstPort", PQ_DFL|PQ_INT, 389 0, &arg_l4dstport, NULL); 390 #endif 391 parse_table_add(&pt, "FwdReason", PQ_DFL|PQ_MULTI, 392 0, &arg_fwd_reason, hd_pkt_forward_reason_names); 393 parse_table_add(&pt, "CalcInfo", PQ_DFL|PQ_MULTI, 394 0, &arg_calc_info, hd_calc_info_names); 395 396 if (!parseEndOk(a, &pt, &retCode)) { 397 return retCode; 398 } 399 400 if (arg_group < 0 || 401 arg_group > (COUNTOF(hd_resource_group_names) - 1) || 402 (arg_gid < 0 && sal_strcasecmp(hd_resource_group_names[arg_group], "ANY"))) { 403 return CMD_USAGE; 404 } 405 406 bcm_switch_pkt_info_t_init(&pkt_info); 407 408 #ifdef INCLUDE_L3 409 if (!sal_strcasecmp(hd_resource_group_names[arg_group], "ECMP")) { 410 pkt_info.flags |= BCM_SWITCH_PKT_INFO_HASH_MULTIPATH; 411 412 r = bcm_l3_egress_multipath_get(unit, arg_gid, 0, NULL, 413 &intf_count); 414 mpath_egr = sal_alloc((intf_count * sizeof(int)), 415 "ecmp group"); 416 if (mpath_egr == NULL) { 417 r = BCM_E_MEMORY; 418 HASH_DESTINATION_ERROR_PRINT(r); 419 return CMD_FAIL; 420 } 421 r = bcm_l3_egress_multipath_get(unit, arg_gid, intf_count, 422 mpath_egr, &intf_count); 423 if (BCM_FAILURE(r)) { 424 HASH_DESTINATION_ERROR_PRINT(r); 425 retCode = CMD_FAIL; 426 goto error_cleanup; 427 } 428 429 pkt_info.mpintf = arg_gid; 430 } else 431 #endif 432 if (!sal_strcasecmp(hd_resource_group_names[arg_group], "LAG") || 433 !sal_strcasecmp(hd_resource_group_names[arg_group], "HGT")) { 434 435 pkt_info.flags |= BCM_SWITCH_PKT_INFO_HASH_TRUNK; 436 437 if (BCM_GPORT_IS_TRUNK(arg_gid)) { 438 tid = BCM_GPORT_TRUNK_GET(arg_gid); 439 } else { 440 tid = arg_gid; 441 } 442 443 if ((r = bcm_trunk_chip_info_get(unit, &ti)) < 0) { 444 HASH_DESTINATION_ERROR_PRINT(r); 445 return CMD_FAIL; 446 } 447 448 if ((!sal_strcasecmp(hd_resource_group_names[arg_group], "LAG") && 449 (tid < ti.trunk_id_min || tid > ti.trunk_id_max)) || 450 (!sal_strcasecmp(hd_resource_group_names[arg_group], "HGT") && 451 (tid < ti.trunk_fabric_id_min || tid > ti.trunk_fabric_id_max))) { 452 r = BCM_E_PARAM; 453 HASH_DESTINATION_ERROR_PRINT(r); 454 return CMD_FAIL; 455 } 456 457 member_array = sal_alloc( 458 sizeof(bcm_trunk_member_t) * BCM_TRUNK_MAX_PORTCNT, 459 "member array"); 460 if (NULL == member_array) { 461 r = BCM_E_MEMORY; 462 HASH_DESTINATION_ERROR_PRINT(r); 463 return CMD_FAIL; 464 } 465 466 r = bcm_trunk_get(unit, tid, &t_add_info, BCM_TRUNK_MAX_PORTCNT, 467 member_array, &member_count); 468 if (BCM_FAILURE(r)) { 469 HASH_DESTINATION_ERROR_PRINT(r); 470 retCode = CMD_FAIL; 471 goto error_cleanup; 472 } 473 474 BCM_GPORT_TRUNK_SET(pkt_info.trunk_gport, 475 tid); 476 } else if (!sal_strcasecmp(hd_resource_group_names[arg_group], "ANY")) { 477 if (arg_calc_info < 0 || 478 arg_calc_info > (COUNTOF(hd_calc_info_names) - 1)) { 479 r = BCM_E_PARAM; 480 HASH_DESTINATION_ERROR_PRINT(r); 481 return CMD_FAIL; 482 } 483 if (!sal_strcasecmp(hd_calc_info_names[arg_calc_info], "UDP_SOURCE_PORT")) { 484 pkt_info.flags |= BCM_SWITCH_PKT_INFO_HASH_UDP_SOURCE_PORT; 485 } else if (!sal_strcasecmp(hd_calc_info_names[arg_calc_info], "LBID")) { 486 pkt_info.flags |= BCM_SWITCH_PKT_INFO_HASH_LBID; 487 } else { 488 r = BCM_E_PARAM; 489 HASH_DESTINATION_ERROR_PRINT(r); 490 return CMD_FAIL; 491 } 492 } else { 493 r = BCM_E_PARAM; 494 HASH_DESTINATION_ERROR_PRINT(r); 495 return CMD_FAIL; 496 } 497 498 if (BCM_GPORT_IS_SET(arg_port)) { 499 #if defined(BCM_ESW_SUPPORT) 500 if (SOC_IS_ESW(unit)) { 501 int tgid, id; 502 503 r = _bcm_esw_gport_resolve(unit, arg_port, &arg_modid, 504 &arg_port, &tgid, &id); 505 if ((tgid != BCM_TRUNK_INVALID) || (id != -1)) { 506 r = BCM_E_PORT; 507 HASH_DESTINATION_ERROR_PRINT(r); 508 retCode = CMD_FAIL; 509 goto error_cleanup; 510 } 511 512 pkt_info.src_gport = arg_port; 513 } else 514 #endif 515 { 516 HASH_DESTINATION_ERROR_PRINT(r); 517 retCode = CMD_FAIL; 518 goto error_cleanup; 519 } 520 } else if (arg_modid == BCM_MODID_INVALID) { 521 (void)bcm_stk_my_modid_get(unit, 522 &arg_modid); 523 r = _bcm_esw_port_gport_validate(unit, arg_port, 524 &arg_port); 525 if (BCM_FAILURE(r)) { 526 HASH_DESTINATION_ERROR_PRINT(r); 527 retCode = CMD_FAIL; 528 goto error_cleanup; 529 } 530 531 BCM_GPORT_LOCAL_SET(pkt_info.src_gport, arg_port); 532 } else if (arg_modid >= 0 && arg_port >= 0) { 533 int mod_is_local; 534 535 r = _bcm_esw_modid_is_local(unit, arg_modid, &mod_is_local); 536 if (BCM_FAILURE(r)) { 537 HASH_DESTINATION_ERROR_PRINT(r); 538 retCode = CMD_FAIL; 539 goto error_cleanup; 540 } 541 if (mod_is_local) { 542 BCM_GPORT_MODPORT_SET(pkt_info.src_gport, 543 arg_modid, arg_port); 544 } else { 545 BCM_GPORT_PROXY_SET(pkt_info.src_gport, 546 arg_modid, arg_port); 547 } 548 } else { 549 r = BCM_E_PORT; 550 HASH_DESTINATION_ERROR_PRINT(r); 551 retCode = CMD_FAIL; 552 goto error_cleanup; 553 } 554 555 pkt_info.flags |= BCM_SWITCH_PKT_INFO_SRC_GPORT; 556 557 if (ENET_CMP_MACADDR(arg_dstmac, default_macaddr)) { 558 pkt_info.flags |= BCM_SWITCH_PKT_INFO_DST_MAC; 559 sal_memcpy(pkt_info.dst_mac, 560 arg_dstmac, sizeof(sal_mac_addr_t)); 561 } 562 563 if (ENET_CMP_MACADDR(arg_srcmac, default_macaddr)) { 564 pkt_info.flags |= BCM_SWITCH_PKT_INFO_SRC_MAC; 565 sal_memcpy(pkt_info.src_mac, 566 arg_srcmac, sizeof(sal_mac_addr_t)); 567 } 568 569 if (arg_untagged) { 570 pkt_info.flags |= BCM_SWITCH_PKT_INFO_VLAN; 571 pkt_info.vid = VLAN_ID_NONE; 572 } else { 573 if (VLAN_ID_VALID(arg_vlan)) { 574 pkt_info.flags |= BCM_SWITCH_PKT_INFO_VLAN; 575 pkt_info.vid = arg_vlan; 576 } 577 } 578 579 if ((arg_ethertype < 0xffff) && 580 (arg_ethertype >= ETHERTYPE_MIN)) { 581 pkt_info.flags |= BCM_SWITCH_PKT_INFO_ETHERTYPE; 582 pkt_info.ethertype = arg_ethertype; 583 584 #ifdef INCLUDE_L3 585 if (pkt_info.ethertype == ETHERTYPE_IPV4 || 586 pkt_info.ethertype == ETHERTYPE_IPV6) { 587 588 if (pkt_info.ethertype == ETHERTYPE_IPV4 && 589 arg_sip_addr != 0) { 590 pkt_info.flags |= BCM_SWITCH_PKT_INFO_SRC_IP; 591 pkt_info.sip = arg_sip_addr; 592 } 593 594 if (pkt_info.ethertype == ETHERTYPE_IPV4 && 595 arg_ip_addr != 0) { 596 pkt_info.flags |= BCM_SWITCH_PKT_INFO_DST_IP; 597 pkt_info.dip = arg_ip_addr; 598 } 599 600 if (pkt_info.ethertype == ETHERTYPE_IPV6 && 601 !BCM_IP6_ADDR_EQ(arg_sip6_addr, default_ip6_addr)) { 602 pkt_info.flags |= BCM_SWITCH_PKT_INFO_SRC_IPV6; 603 sal_memcpy(pkt_info.sip6, arg_sip6_addr, BCM_IP6_ADDRLEN); 604 } 605 606 if (pkt_info.ethertype == ETHERTYPE_IPV6 && 607 !BCM_IP6_ADDR_EQ(arg_ip6_addr, default_ip6_addr)) { 608 pkt_info.flags |= BCM_SWITCH_PKT_INFO_DST_IPV6; 609 sal_memcpy(pkt_info.dip6, arg_ip6_addr, BCM_IP6_ADDRLEN); 610 } 611 612 if (arg_protocol >= 0 && arg_protocol <= 0xff) { 613 pkt_info.flags |= BCM_SWITCH_PKT_INFO_PROTOCOL; 614 pkt_info.protocol = arg_protocol & 0xff; 615 616 if (pkt_info.protocol == IP_PROT_TCP || 617 pkt_info.protocol == IP_PROT_UDP) { 618 if (arg_l4srcport != -1) { 619 pkt_info.flags |= BCM_SWITCH_PKT_INFO_SRC_L4_PORT; 620 pkt_info.src_l4_port = arg_l4srcport & 0xffff; 621 } 622 if (arg_l4dstport != -1) { 623 pkt_info.flags |= BCM_SWITCH_PKT_INFO_DST_L4_PORT; 624 pkt_info.dst_l4_port = arg_l4dstport & 0xffff; 625 } 626 } 627 } 628 } 629 #endif 630 } 631 632 pkt_info.fwd_reason = arg_fwd_reason; 633 634 if (LOG_CHECK(BSL_LS_APPL_COMMON | BSL_VERBOSE)) { 635 cli_out("flags: 0x%08x\n", pkt_info.flags); 636 for (i = 0; i < 8 * sizeof(pkt_info.flags); i++) { 637 if (pkt_info.flags & (0x1 << i)) { 638 if (i < COUNTOF(hd_flags_names)) { 639 cli_out("%s ", hd_flags_names[i]); 640 } else { 641 cli_out("%s (%d) ", "UNKNOWN", i); 642 } 643 } 644 } 645 cli_out("\n"); 646 } 647 648 if ((r = bcm_switch_pkt_info_hash_get(unit, &pkt_info, 649 &dst_gport, &dst_intf)) < 0) { 650 HASH_DESTINATION_ERROR_PRINT(r); 651 retCode = CMD_FAIL; 652 goto error_cleanup; 653 } 654 655 #ifdef INCLUDE_L3 656 if (pkt_info.flags & BCM_SWITCH_PKT_INFO_HASH_MULTIPATH) { 657 cli_out("\n%s (%s):\n", 658 "HashDestination", 659 hd_resource_group_names[arg_group]); 660 for (i = 0; i < intf_count; i++) { 661 #ifdef BCM_TOMAHAWK_SUPPORT 662 if (soc_feature(unit, soc_feature_hierarchical_ecmp) && 663 BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, mpath_egr[i])) { 664 bcm_if_t *mpath_egr_l2 = NULL; 665 int intf_count_l2 = 0, j; 666 r = bcm_l3_egress_multipath_get(unit, mpath_egr[i], 0, NULL, 667 &intf_count_l2); 668 mpath_egr_l2 = sal_alloc((intf_count_l2 * sizeof(int)), 669 "ecmp group level2"); 670 if (mpath_egr_l2 == NULL) { 671 r = BCM_E_MEMORY; 672 HASH_DESTINATION_ERROR_PRINT(r); 673 return CMD_FAIL; 674 } 675 r = bcm_l3_egress_multipath_get(unit, mpath_egr[i], intf_count_l2, 676 mpath_egr_l2, &intf_count_l2); 677 if (BCM_FAILURE(r)) { 678 HASH_DESTINATION_ERROR_PRINT(r); 679 sal_free(mpath_egr_l2); 680 retCode = CMD_FAIL; 681 goto error_cleanup; 682 } 683 for (j = 0; j < intf_count_l2; j++) { 684 cli_out(" %d %s\n", mpath_egr_l2[j], 685 mpath_egr_l2[j] == dst_intf ? "destination":""); 686 } 687 sal_free(mpath_egr_l2); 688 } else 689 #endif 690 { 691 cli_out(" %d %s\n", mpath_egr[i], 692 mpath_egr[i] == dst_intf ? "destination":""); 693 } 694 } 695 } else 696 #endif 697 if (pkt_info.flags & BCM_SWITCH_PKT_INFO_HASH_TRUNK) { 698 cli_out("\n%s (%s):\n", 699 "HashDestination", 700 hd_resource_group_names[arg_group]); 701 702 for (i = 0; i < member_count; i++) { 703 bcm_gport_t gport = member_array[i].gport; 704 if (BCM_GPORT_IS_DEVPORT(gport)) { 705 cli_out(" 0x%08x (tp[%d]=%d,tdev[%d]=%d) %s\n", 706 gport, 707 i, BCM_GPORT_DEVPORT_PORT_GET(gport), 708 i, BCM_GPORT_DEVPORT_DEVID_GET(gport), 709 gport == dst_gport ? "destination":""); 710 } else { 711 cli_out(" 0x%08x (tp[%d]=%d,tmod[%d]=%d) %s\n", 712 gport, 713 i, BCM_GPORT_MODPORT_PORT_GET(gport), 714 i, BCM_GPORT_MODPORT_MODID_GET(gport), 715 gport == dst_gport ? "destination":""); 716 } 717 } 718 } else 719 if ((pkt_info.flags & BCM_SWITCH_PKT_INFO_HASH_UDP_SOURCE_PORT) || 720 (pkt_info.flags & BCM_SWITCH_PKT_INFO_HASH_LBID)) { 721 cli_out("\n%s (%s):\n", 722 "HashDestination", 723 hd_resource_group_names[arg_group]); 724 725 cli_out(" CalcInfo (%s): %d(0x%x)\n", 726 hd_calc_info_names[arg_calc_info], dst_intf, dst_intf); 727 } 728 729 error_cleanup: 730 if (member_array != NULL) { 731 sal_free(member_array); 732 } 733 #ifdef INCLUDE_L3 734 if (mpath_egr != NULL) { 735 sal_free(mpath_egr); 736 } 737 #endif 738 739 return retCode; 740 } 741 742 743 STATIC cmd_result_t 744 _cmd_hd_dest(int unit, args_t *a) 745 { 746 char *subcmd = NULL; 747 748 if ((subcmd = ARG_GET(a)) == NULL) { 749 return CMD_USAGE; 750 } 751 /* BCM.0> hd dest get ... */ 752 if (!sal_strcasecmp(subcmd, "get") || 753 !sal_strcasecmp(subcmd, "calc")) { 754 return _cmd_hd_dest_get(unit, a); 755 } 756 757 return CMD_USAGE; 758 } 759 760 761 cmd_result_t 762 cmd_hash_destination(int unit, args_t *a) 763 { 764 char *subcmd = NULL; 765 766 if (!sh_check_attached(ARG_CMD(a), unit)) { 767 return CMD_FAIL; 768 } 769 770 if ((subcmd = ARG_GET(a)) == NULL) { 771 return CMD_USAGE; 772 } 773 774 #ifdef BCM_TRIUMPH3_SUPPORT 775 if (!sal_strcasecmp(subcmd, "eth") || 776 !sal_strcasecmp(subcmd, "ethertype")) { 777 /* BCM.0> hd eth ... */ 778 return _cmd_hd_ethertype(unit, a); 779 } 780 #endif 781 782 if (!sal_strcasecmp(subcmd, "dest") || 783 !sal_strcasecmp(subcmd, "info")) { 784 /* BCM.0> hd dest ... */ 785 return _cmd_hd_dest(unit, a); 786 } 787 788 return CMD_USAGE; 789 } 790 #endif /* BCM_TRIDENT_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 791