l2.c (78415B)
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 * L2 CLI 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 <soc/l2x.h> 15 #include <soc/l2u.h> 16 #include <soc/debug.h> 17 #include <soc/hash.h> 18 19 #include <bcm/error.h> 20 #include <bcm/l2.h> 21 #include <bcm/stack.h> 22 #include <bcm/mcast.h> 23 #include <bcm/debug.h> 24 25 #include <bcm_int/esw/trunk.h> 26 #include <bcm_int/esw/mbcm.h> 27 #include <bcm_int/esw/hercules.h> 28 #include <bcm_int/esw/firebolt.h> 29 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT*/ 30 #include <bcm_int/esw/triumph.h> 31 #endif /* !BCM_TRIUMPH_SUPPORT */ 32 #if defined(BCM_TOMAHAWK_SUPPORT) 33 #include <bcm_int/esw/switch.h> 34 #endif 35 #if defined(BCM_TOMAHAWK3_SUPPORT) 36 #include <soc/tomahawk3.h> 37 #endif 38 39 static sal_usecs_t prev_l2x_interval[SOC_MAX_NUM_DEVICES]; 40 #if defined(BCM_TOMAHAWK3_SUPPORT) 41 static sal_usecs_t prev_l2x_lrn_interval[SOC_MAX_NUM_DEVICES]; 42 #endif 43 44 #if defined(BCM_TRIUMPH_SUPPORT) 45 /* 46 * Macro: 47 * L2_CHECK_RETURN 48 * Purpose: 49 * Check the return value from an API call. Output either a failed 50 * message or okay along with the function name. 51 */ 52 #define L2_CHECK_RETURN(unit, rv, func_name) \ 53 do { \ 54 if (BCM_FAILURE(rv)) { \ 55 cli_out("L2(unit %d) Error: %s() failed - %s. \n", \ 56 (unit), (func_name), bcm_errmsg(rv)); \ 57 return (CMD_FAIL); \ 58 } else { \ 59 if (LOG_CHECK(BSL_LS_BCM_L2 | BSL_VERBOSE)) { \ 60 cli_out("L2(unit %d) Info: %s() success. \n", \ 61 (unit), (func_name)); \ 62 } \ 63 } \ 64 } while(0) 65 #endif 66 67 68 #if defined(BCM_TRIDENT2_SUPPORT) 69 #define L2_MAX_BANKS 6 70 #endif 71 72 /* 73 * Used with the 'l2 watch' command below. 74 */ 75 static void 76 _l2_watch_cb(int unit, 77 bcm_l2_addr_t *l2addr, 78 int insert, 79 void *userdata) 80 { 81 int s; 82 sal_thread_t main_thread; 83 84 s = sal_splhi(); 85 86 main_thread = sal_thread_main_get(); 87 sal_thread_main_set(sal_thread_self()); 88 89 if(insert) { 90 dump_l2_addr(unit, "L2 ADD: ", l2addr); 91 } 92 else { 93 dump_l2_addr(unit, "L2 DEL: ", l2addr); 94 } 95 96 sal_thread_main_set(main_thread); 97 98 sal_spl(s); 99 } 100 101 102 /* CB function to print L2 Entry */ 103 int _l2addr_dump(int unit, bcm_l2_addr_t *l2addr, void *user_data) 104 { 105 /* Don't dump individual entries when just the 'count' is desired, the 106 user of this callback will print the counts */ 107 #if defined(BCM_TRIUMPH3_SUPPORT) 108 if (soc_feature(unit, soc_feature_ism_memory)) { 109 if(!(_l2_addr_counts.flags & L2_DUMP_COUNT)) { 110 dump_l2_addr(unit, "", l2addr); 111 } 112 } else { 113 dump_l2_addr(unit, "", l2addr); 114 } 115 #else 116 dump_l2_addr(unit, "", l2addr); 117 #endif 118 119 return BCM_E_NONE; 120 } 121 122 123 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT */ 124 /* 125 * Function: 126 * _l2_station_add 127 * Purpose: 128 * Add L2 station entry. 129 * Parmameters: 130 * unit - (IN) BCM device number 131 * args - (IN) input parameters passed as arguments 132 * Returns: 133 * CMD_XXX 134 */ 135 STATIC int 136 _l2_station_add(int unit, args_t *args) 137 { 138 int rv; 139 int sid = -1; 140 int prio = 0; 141 bcm_mac_t dst_mac; 142 bcm_mac_t dst_mac_mask; 143 int vlan = 0; 144 int vlan_mask = 0; 145 int src_port = 0; 146 int src_port_mask = 0; 147 int ipv4 = 0; 148 int ipv6 = 0; 149 int arp_rarp = 0; 150 int mpls_term = 0; 151 int mim_term = 0; 152 int trill_term = 0; 153 int fcoe_term = 0; 154 int oam_term = 0; 155 int replace = 0; 156 int copy_to_cpu = 0; 157 int discard = 0; 158 parse_table_t pt; 159 bcm_l2_station_t s_ent; 160 int station_id = -1; 161 cmd_result_t retCode = CMD_OK; 162 163 sal_memset(dst_mac, 0x00, sizeof(bcm_mac_t)); 164 sal_memset(dst_mac_mask, 0x00, sizeof(bcm_mac_t)); 165 166 bcm_l2_station_t_init(&s_ent); 167 168 parse_table_init(unit, &pt); 169 170 parse_table_add(&pt, "Priority", PQ_DFL|PQ_INT, 171 0, (void *)&prio, NULL); 172 173 parse_table_add(&pt, "ID", PQ_DFL|PQ_INT, 174 (void *)-1, (void *)&sid, NULL); 175 176 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 177 0, (void *)&dst_mac, NULL); 178 179 parse_table_add(&pt, "MACaddressMask", PQ_DFL|PQ_MAC, 180 0, (void *)&dst_mac_mask, NULL); 181 182 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 183 0, (void *)&vlan, NULL); 184 185 parse_table_add(&pt, "VlanidMask", PQ_DFL|PQ_HEX, 186 0, (void *)&vlan_mask, NULL); 187 188 parse_table_add(&pt, "SourcePort", PQ_DFL|PQ_PORT|PQ_BCM, 189 0, (void *)&src_port, NULL); 190 191 parse_table_add(&pt, "SourcePortMask", PQ_DFL|PQ_HEX, 192 0, (void *)&src_port_mask, NULL); 193 194 parse_table_add(&pt, "IPv4", PQ_DFL|PQ_BOOL, 195 0, (void *)&ipv4, NULL); 196 197 parse_table_add(&pt, "IPv6", PQ_DFL|PQ_BOOL, 198 0, (void *)&ipv6, NULL); 199 200 parse_table_add(&pt, "ArpRarp", PQ_DFL|PQ_BOOL, 201 0, (void *)&arp_rarp, NULL); 202 203 parse_table_add(&pt, "MPLS", PQ_DFL|PQ_BOOL, 204 0, (void *)&mpls_term, NULL); 205 206 parse_table_add(&pt, "MiM", PQ_DFL|PQ_BOOL, 207 0, (void *)&mim_term, NULL); 208 209 parse_table_add(&pt, "TRILL", PQ_DFL|PQ_BOOL, 210 0, (void *)&trill_term, NULL); 211 212 parse_table_add(&pt, "FCoE", PQ_DFL|PQ_BOOL, 213 0, (void *)&fcoe_term, NULL); 214 215 parse_table_add(&pt, "OAM", PQ_DFL|PQ_BOOL, 216 0, (void *)&oam_term, NULL); 217 218 parse_table_add(&pt, "Replace", PQ_DFL|PQ_BOOL, 219 0, (void *)&replace, NULL); 220 221 parse_table_add(&pt, "CPUmirror", PQ_DFL|PQ_BOOL, 222 0, (void *)©_to_cpu, NULL); 223 224 parse_table_add(&pt, "Discard", PQ_DFL|PQ_BOOL, 225 0, (void *)&discard, NULL); 226 227 if (!parseEndOk(args, &pt, &retCode)) { 228 return retCode; 229 } 230 231 s_ent.priority = prio; 232 233 if (-1 != sid) { 234 station_id = sid; 235 s_ent.flags |= BCM_L2_STATION_WITH_ID; 236 } 237 sal_memcpy(s_ent.dst_mac, dst_mac, sizeof(bcm_mac_t)); 238 sal_memcpy(s_ent.dst_mac_mask, dst_mac_mask, sizeof(bcm_mac_t)); 239 240 s_ent.vlan = vlan; 241 s_ent.vlan_mask = vlan_mask; 242 243 s_ent.src_port = src_port; 244 s_ent.src_port_mask = src_port_mask; 245 246 if (1 == ipv4) { 247 s_ent.flags |= BCM_L2_STATION_IPV4; 248 } 249 250 if (1 == ipv6) { 251 s_ent.flags |= BCM_L2_STATION_IPV6; 252 } 253 254 if (1 == arp_rarp) { 255 s_ent.flags |= BCM_L2_STATION_ARP_RARP; 256 } 257 258 if (1 == mpls_term) { 259 s_ent.flags |= BCM_L2_STATION_MPLS; 260 } 261 262 if (1 == mim_term) { 263 s_ent.flags |= BCM_L2_STATION_MIM; 264 } 265 266 if (1 == trill_term) { 267 s_ent.flags |= BCM_L2_STATION_TRILL; 268 } 269 270 if (1 == oam_term) { 271 s_ent.flags |= BCM_L2_STATION_OAM; 272 } 273 274 if (1 == fcoe_term) { 275 s_ent.flags |= BCM_L2_STATION_FCOE; 276 } 277 278 if (1 == replace) { 279 s_ent.flags |= BCM_L2_STATION_REPLACE; 280 } 281 282 if (1 == copy_to_cpu) { 283 s_ent.flags |= BCM_L2_STATION_COPY_TO_CPU; 284 } 285 286 if (1 == discard) { 287 s_ent.flags |= BCM_L2_STATION_DISCARD; 288 } 289 290 rv = bcm_l2_station_add(unit, &station_id, &s_ent); 291 L2_CHECK_RETURN(unit, rv, "bcm_l2_station_add"); 292 293 if (-1 == sid) { 294 cli_out("Created SID=0x%08x\n", station_id); 295 } 296 297 return (retCode); 298 } 299 300 /* 301 * Function: 302 * _l2_station_delete 303 * Purpose: 304 * Delete L2 station entry. 305 * Parmameters: 306 * unit - (IN) BCM device number 307 * args - (IN) input parameters passed as arguments 308 * Returns: 309 * CMD_XXX 310 */ 311 STATIC int 312 _l2_station_delete(int unit, args_t *args) 313 { 314 int rv; 315 parse_table_t pt; 316 int station_id = -1; 317 cmd_result_t retCode = CMD_OK; 318 319 parse_table_init(unit, &pt); 320 321 parse_table_add(&pt, "ID", PQ_DFL|PQ_INT, 322 (void *)-1, (void *)&station_id, NULL); 323 if (!parseEndOk(args, &pt, &retCode)) { 324 return retCode; 325 } 326 327 rv = bcm_l2_station_delete(unit, station_id); 328 329 L2_CHECK_RETURN(unit, rv, "bcm_l2_station_delete"); 330 331 return (retCode); 332 } 333 334 /* 335 * Function: 336 * _l2_station_clear 337 * Purpose: 338 * Delete all L2 station entries. 339 * Parmameters: 340 * unit - (IN) BCM device number 341 * args - (IN) input parameters passed as arguments 342 * Returns: 343 * CMD_XXX 344 */ 345 STATIC int 346 _l2_station_clear(int unit, args_t *args) 347 { 348 cmd_result_t retCode = CMD_OK; 349 int rv; 350 351 rv = bcm_l2_station_delete_all(unit); 352 L2_CHECK_RETURN(unit, rv, "bcm_l2_station_delete_all"); 353 354 return (retCode); 355 } 356 357 /* 358 * Function: 359 * _l2_station_show 360 * Purpose: 361 * Show L2 station entry value. 362 * Parmameters: 363 * unit - (IN) BCM device number 364 * args - (IN) input parameters passed as arguments 365 * Returns: 366 * CMD_XXX 367 */ 368 STATIC int 369 _l2_station_show(int unit, args_t *args) 370 { 371 int rv; 372 parse_table_t pt; 373 int station_id = -1; 374 cmd_result_t retCode = CMD_OK; 375 bcm_l2_station_t s_ent; 376 377 parse_table_init(unit, &pt); 378 379 parse_table_add(&pt, "ID", PQ_DFL|PQ_INT, 380 (void *)-1, (void *)&station_id, NULL); 381 if (!parseEndOk(args, &pt, &retCode)) { 382 return retCode; 383 } 384 385 bcm_l2_station_t_init(&s_ent); 386 387 rv = bcm_l2_station_get(unit, station_id, &s_ent); 388 L2_CHECK_RETURN(unit, rv, "bcm_l2_station_get"); 389 390 cli_out("\tSID=0x%08x, priority=%d\n", station_id, s_ent.priority); 391 cli_out("\tMAC=%x:%x:%x:%x:%x:%x\n", s_ent.dst_mac[0], s_ent.dst_mac[1], 392 s_ent.dst_mac[2], s_ent.dst_mac[3], s_ent.dst_mac[4], 393 s_ent.dst_mac[5]); 394 cli_out("\tMAC MASK=%x:%x:%x:%x:%x:%x\n", s_ent.dst_mac_mask[0], 395 s_ent.dst_mac_mask[1], s_ent.dst_mac_mask[2], s_ent.dst_mac_mask[3], 396 s_ent.dst_mac_mask[4], s_ent.dst_mac_mask[5]); 397 cli_out("\tVLAN=0x%x\n", s_ent.vlan); 398 cli_out("\tVLAN MASK=0x%x\n", s_ent.vlan_mask); 399 cli_out("\tSourcePort=0x%x\n", s_ent.src_port); 400 cli_out("\tSourcePort MASK=0x%x\n", s_ent.src_port_mask); 401 cli_out("\tFlags=0x%x\n", s_ent.flags); 402 403 return (rv); 404 } 405 406 /* 407 * Function: 408 * _l2_station_cmd_process 409 * Purpose: 410 * Add/Delete/Clear/Show L2 station entry values. 411 * Parmameters: 412 * unit - (IN) BCM device number 413 * args - (IN) input parameters passed as arguments 414 * Returns: 415 * CMD_XXX 416 */ 417 STATIC int 418 _l2_station_cmd_process(int unit, args_t *args) 419 { 420 char *subcmd = NULL; 421 422 if ((subcmd = ARG_GET(args)) == NULL) { 423 return CMD_USAGE; 424 } 425 426 /* BCM.0> l2 station add ... */ 427 if (!sal_strcasecmp(subcmd, "add")) { 428 return _l2_station_add(unit, args); 429 } 430 431 /* BCM.0> l2 station delete ... */ 432 if (!sal_strcasecmp(subcmd, "delete")) { 433 return _l2_station_delete(unit, args); 434 } 435 436 /* BCM.0> l2 station clear ... */ 437 if (!sal_strcasecmp(subcmd, "clear")) { 438 return _l2_station_clear(unit, args); 439 } 440 441 /* BCM.0> l2 station show ... */ 442 if (!sal_strcasecmp(subcmd, "show")) { 443 return _l2_station_show(unit, args); 444 } 445 446 return CMD_USAGE; 447 } 448 #endif /* !BCM_TRIUMPH_SUPPORT */ 449 450 /* 451 * Add an L2 address to the switch, remove an L2 address from the 452 * switch, show addresses, and clear addresses on a per port basis. 453 */ 454 cmd_result_t 455 if_esw_l2(int unit, args_t *a) 456 { 457 int idx; 458 char *subcmd = NULL; 459 pbmp_t arg_pbmp, arg_pbmp_mb; 460 int arg_static = 0, arg_trunk = 0, arg_l3if = 0, 461 arg_scp = 0, arg_ds = 0, arg_dd = 0, arg_count = 1, arg_modid = 0, 462 arg_newmodid = 0, arg_vlan = VLAN_ID_DEFAULT, arg_tgid = 0, arg_newtgid = 0, 463 arg_cbit = 0, arg_hit = 0, arg_replace = 0, arg_port = 0, arg_newport = 0, 464 arg_group = 0, arg_pending = 0, arg_limitexempt = 0, arg_mirror = 0; 465 #ifdef BCM_XGS_SWITCH_SUPPORT 466 int arg_hash = XGS_HASH_COUNT; 467 #endif 468 int arg_rpe = TRUE; 469 soc_port_t p, dport; 470 int rv = BCM_E_NONE; 471 parse_table_t pt; 472 cmd_result_t retCode; 473 bcm_l2_addr_t l2addr; 474 uint32 flags; 475 bcm_module_t mymodid; 476 /* 477 * Initialize MAC address field for the user to the first real 478 * address which does not conflict 479 */ 480 481 sal_mac_addr_t default_macaddr = {0, 0, 0, 0, 0, 0X1}; 482 sal_mac_addr_t arg_macaddr = {0, 0, 0, 0, 0, 0X1}; 483 484 BCM_PBMP_CLEAR(arg_pbmp); 485 BCM_PBMP_CLEAR(arg_pbmp_mb); 486 sal_memset(&l2addr, 0, sizeof(bcm_l2_addr_t)); 487 488 UNSUPPORTED_COMMAND(unit, SOC_CHIP_BCM5670, a); 489 490 491 if ((subcmd = ARG_GET(a)) == NULL) { 492 return CMD_USAGE; 493 } 494 495 /* Check valid device to operation on ...*/ 496 if (!sh_check_attached(ARG_CMD(a), unit)) { 497 return CMD_FAIL; 498 } 499 500 if (!sal_strcasecmp(subcmd, "replace")) { 501 uint32 flags = 0; 502 503 arg_modid = arg_port = arg_vlan = arg_tgid = arg_newmodid = arg_newport = arg_newtgid = -1; 504 parse_table_init(unit, &pt); 505 parse_table_add(&pt, "Module", PQ_DFL|PQ_INT, 506 0, &arg_modid, NULL); 507 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 508 0, &arg_port, NULL); 509 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 510 0, &arg_macaddr, NULL); 511 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 512 0, &arg_vlan, NULL); 513 parse_table_add(&pt, "Trunk", PQ_DFL|PQ_BOOL, 514 0, &arg_trunk, NULL); 515 parse_table_add(&pt, "TrunkGroupID", PQ_DFL|PQ_INT, 516 0, &arg_tgid, NULL); 517 parse_table_add(&pt, "STatic", PQ_DFL|PQ_BOOL, 518 0, &arg_static, NULL); 519 parse_table_add(&pt, "PENDing", PQ_DFL|PQ_BOOL, 520 0, &arg_pending, NULL); 521 parse_table_add(&pt, "NewModule", PQ_DFL|PQ_INT, 522 0, &arg_newmodid, NULL); 523 parse_table_add(&pt, "NewPort", PQ_DFL|PQ_PORT, 524 0, &arg_newport, NULL); 525 parse_table_add(&pt, "NewTrunkGroupID", PQ_DFL|PQ_INT, 526 0, &arg_newtgid, NULL); 527 if (!parseEndOk(a, &pt, &retCode)) { 528 return retCode; 529 } 530 531 bcm_l2_addr_t_init(&l2addr, arg_macaddr, arg_vlan); 532 if (arg_static) { 533 flags |= BCM_L2_REPLACE_MATCH_STATIC; 534 } 535 if (arg_pending) { 536 flags |= BCM_L2_REPLACE_PENDING; 537 } 538 if (ENET_CMP_MACADDR(arg_macaddr, default_macaddr)) { 539 flags |= BCM_L2_REPLACE_MATCH_MAC; 540 } 541 if (arg_vlan != -1) { 542 flags |= BCM_L2_REPLACE_MATCH_VLAN; 543 } 544 if (arg_newtgid != - 1) { 545 flags |= BCM_L2_REPLACE_NEW_TRUNK; 546 } 547 if (BCM_GPORT_IS_SET(arg_port)) { 548 flags |= BCM_L2_REPLACE_MATCH_DEST; 549 l2addr.port = arg_port; 550 } else { 551 if ((arg_port != - 1) && (arg_modid != - 1)) { 552 flags |= BCM_L2_REPLACE_MATCH_DEST; 553 l2addr.modid = arg_modid; 554 l2addr.port = arg_port; 555 } 556 if (arg_trunk && (arg_tgid != -1)) { 557 flags |= BCM_L2_REPLACE_MATCH_DEST; 558 l2addr.tgid = arg_tgid; 559 } 560 } 561 562 rv = bcm_l2_replace(unit, flags, &l2addr, arg_newmodid, 563 arg_newport, arg_newtgid); 564 565 if (BCM_FAILURE(rv)) { 566 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 567 return CMD_FAIL; 568 } 569 570 return CMD_OK; 571 } else if (!sal_strcasecmp(subcmd, "add") || 572 !sal_strcasecmp(subcmd, "+")) { 573 574 parse_table_init(unit, &pt); 575 parse_table_add(&pt, "Module", PQ_DFL|PQ_INT, 576 0, &arg_modid, NULL); 577 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 578 0, &arg_port, NULL); 579 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP, 580 (void *)(0), &arg_pbmp, NULL); 581 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC,0, 582 &arg_macaddr, NULL); 583 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 584 0, &arg_vlan, NULL); 585 parse_table_add(&pt, "Trunk", PQ_DFL|PQ_BOOL, 586 0, &arg_trunk, NULL); 587 parse_table_add(&pt, "TrunkGroupID", PQ_DFL|PQ_INT, 588 0, &arg_tgid, NULL); 589 parse_table_add(&pt, "STatic", PQ_DFL|PQ_BOOL, 590 0, &arg_static, NULL); 591 parse_table_add(&pt, "HIT", PQ_DFL|PQ_BOOL, 592 0, &arg_hit, NULL); 593 parse_table_add(&pt, "Replace", PQ_DFL|PQ_BOOL, 594 0, &arg_replace, NULL); 595 parse_table_add(&pt, "SourceCosPriority", PQ_DFL|PQ_BOOL, 596 0, &arg_scp, NULL); 597 parse_table_add(&pt, "DiscardSource", PQ_DFL|PQ_BOOL, 598 0, &arg_ds, NULL); 599 parse_table_add(&pt, "DiscardDest",PQ_DFL|PQ_BOOL, 600 0, &arg_dd, NULL); 601 parse_table_add(&pt, "L3", PQ_DFL|PQ_BOOL, 602 0, &arg_l3if, NULL); 603 parse_table_add(&pt, "CPUmirror", PQ_DFL|PQ_BOOL, 604 0, &arg_cbit, NULL); 605 parse_table_add(&pt, "MIRror", PQ_DFL|PQ_BOOL, 606 0, &arg_mirror, NULL); 607 parse_table_add(&pt, "MacBlockPortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 608 (void *)(0), &arg_pbmp_mb, NULL); 609 parse_table_add(&pt, "Group", PQ_DFL|PQ_INT, 610 0, &arg_group, NULL); 611 parse_table_add(&pt, "PENDing", PQ_DFL|PQ_BOOL, 612 0, &arg_pending, NULL); 613 parse_table_add(&pt, "LearnLimitExempt", PQ_DFL|PQ_BOOL, 614 0, &arg_limitexempt, NULL); 615 616 if (SOC_IS_XGS3_SWITCH(unit)) { 617 parse_table_add(&pt, "ReplacePriority", PQ_DFL|PQ_BOOL, 618 0, &arg_rpe, NULL); 619 } 620 if (!parseEndOk(a, &pt, &retCode)) { 621 return retCode; 622 } 623 624 625 /* Configure flags for SDK call */ 626 flags = 0; 627 if (arg_static) 628 flags |= BCM_L2_STATIC; 629 if (arg_hit) 630 flags |= BCM_L2_HIT; 631 if (arg_replace) 632 flags |= BCM_L2_REPLACE_DYNAMIC; 633 if (arg_scp) 634 flags |= BCM_L2_COS_SRC_PRI; 635 if (arg_dd) 636 flags |= BCM_L2_DISCARD_DST; 637 if (arg_ds) 638 flags |= BCM_L2_DISCARD_SRC; 639 if (arg_l3if) 640 flags |= BCM_L2_L3LOOKUP; 641 if (arg_trunk) 642 flags |= BCM_L2_TRUNK_MEMBER; 643 if (arg_cbit) 644 flags |= BCM_L2_COPY_TO_CPU; 645 if (arg_mirror) 646 flags |= BCM_L2_MIRROR; 647 if (arg_rpe) 648 flags |= BCM_L2_SETPRI; 649 if (arg_pending) 650 flags |= BCM_L2_PENDING; 651 if (arg_limitexempt) 652 flags |= BCM_L2_LEARN_LIMIT_EXEMPT; 653 654 if (SOC_PBMP_IS_NULL(arg_pbmp)) { 655 /* Fill l2addr structure */ 656 bcm_l2_addr_t_init(&l2addr, arg_macaddr, arg_vlan); 657 l2addr.tgid = arg_tgid; 658 l2addr.group = arg_group; 659 l2addr.flags = flags; 660 l2addr.port = arg_port; 661 if (!BCM_GPORT_IS_SET(arg_port)) { 662 l2addr.modid = arg_modid; 663 bcm_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 664 l2addr.modid, l2addr.port, 665 &l2addr.modid, &l2addr.port); 666 } 667 BCM_PBMP_ASSIGN(l2addr.block_bitmap, arg_pbmp_mb); 668 if ((rv = bcm_l2_addr_add(unit, &l2addr))!= BCM_E_NONE) { 669 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 670 return CMD_FAIL; 671 } 672 dump_l2_addr(unit, "ADD: ", &l2addr); 673 } else { 674 /* 675 * If we are setting the range, the MAC address is incremented by 676 * 1 for each port. 677 */ 678 /* coverity[overrun-local : FALSE] */ 679 DPORT_SOC_PBMP_ITER(unit, arg_pbmp, dport, p) { 680 bcm_error_t rv; 681 /* Fill l2addr structure */ 682 bcm_l2_addr_t_init(&l2addr, arg_macaddr, arg_vlan); 683 l2addr.tgid = arg_tgid; 684 l2addr.group = arg_group; 685 l2addr.flags = flags; 686 687 SOC_IF_ERROR_RETURN(bcm_stk_my_modid_get(unit, &mymodid)); 688 689 /* 690 * Handle devices that don't support port stacking by 691 * ignoring BCM_E_UNAVAIL status 692 */ 693 rv = bcm_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mymodid, 694 p, &mymodid, &p); 695 696 if ((BCM_FAILURE(rv)) && (rv != BCM_E_UNAVAIL)) { 697 cli_out("%s ERROR: bcm_stk_modmap_map returned %d(%s)\n", 698 ARG_CMD(a), rv, bcm_errmsg(rv)); 699 return CMD_FAIL; 700 } 701 702 l2addr.port = p; 703 l2addr.modid = mymodid; 704 BCM_PBMP_ASSIGN(l2addr.block_bitmap, arg_pbmp_mb); 705 706 if ((rv = bcm_l2_addr_add(unit, &l2addr))!= BCM_E_NONE) { 707 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 708 return CMD_FAIL; 709 } 710 711 dump_l2_addr(unit, "ADD: ", &l2addr); 712 713 /* Set up for next call */ 714 increment_macaddr(arg_macaddr, 1); 715 } 716 } 717 718 return CMD_OK; 719 } else if (!sal_strcasecmp(subcmd, "del") || 720 !sal_strcasecmp(subcmd, "-")) { 721 722 parse_table_init(unit, &pt); 723 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 724 0, &arg_macaddr,NULL); 725 parse_table_add(&pt, "Count", PQ_DFL|PQ_INT, 726 (void *)(1), &arg_count, NULL); 727 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 728 0, &arg_vlan, NULL); 729 if (!parseEndOk(a, &pt, &retCode)) { 730 return retCode; 731 } 732 733 for (idx = 0; idx < arg_count; idx++) { 734 bcm_l2_addr_t_init(&l2addr, arg_macaddr, arg_vlan); 735 rv = bcm_l2_addr_get(unit, arg_macaddr, arg_vlan, &l2addr); 736 if (rv < 0) { 737 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 738 return CMD_FAIL; 739 } 740 741 if (LOG_CHECK(BSL_LS_BCM_L2 | BSL_VERBOSE)) { 742 dump_l2_addr(unit, "DEL: ", &l2addr); 743 } 744 745 if ((rv = bcm_l2_addr_delete(unit, arg_macaddr, arg_vlan)) < 0) { 746 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 747 return CMD_FAIL; 748 } 749 750 increment_macaddr(arg_macaddr, 1); 751 752 } 753 arg_count = 1; 754 return CMD_OK; 755 } 756 757 else if (!sal_strcasecmp(subcmd, "show") || 758 !sal_strcasecmp(subcmd, "-d") || 759 !sal_strcasecmp(subcmd, "count")) { 760 761 #ifdef BCM_XGS_SWITCH_SUPPORT 762 if (SOC_IS_XGS_SWITCH(unit)) { 763 764 #if defined(BCM_TRIUMPH3_SUPPORT) 765 if (soc_feature(unit, soc_feature_ism_memory)) { 766 sal_memset(&_l2_addr_counts, 0, sizeof(_l2_addr_counts)); 767 if(!sal_strcasecmp(subcmd, "count")) { 768 _l2_addr_counts.flags = L2_DUMP_COUNT; 769 } 770 } else if(!sal_strcasecmp(subcmd, "count")) { 771 cli_out("ERROR: %s %s not implemented on this unit\n", 772 ARG_CMD(a), subcmd); 773 return BCM_E_UNAVAIL; 774 } 775 #else 776 if(!sal_strcasecmp(subcmd, "count")) { 777 cli_out("ERROR: %s %s not implemented on this unit\n", 778 ARG_CMD(a), subcmd); 779 return BCM_E_UNAVAIL; 780 } 781 #endif 782 783 rv = bcm_l2_traverse(unit, _l2addr_dump, NULL); 784 785 if (rv < 0) { 786 cli_out("%s: ERROR: bcm_l2_traverse failed %s\n", 787 ARG_CMD(a), bcm_errmsg(rv)); 788 } 789 790 #if defined(BCM_TRIUMPH3_SUPPORT) 791 if (soc_feature(unit, soc_feature_ism_memory)) { 792 if(_l2_addr_counts.flags & L2_DUMP_COUNT) { 793 cli_out("\n L2 Counts:"); 794 cli_out("\n L2_ENTRY_1: %d", 795 _l2_addr_counts.l2_count.l2_entry_1); 796 cli_out("\n L2_ENTRY_2: %d\n", 797 _l2_addr_counts.l2_count.l2_entry_2); 798 if ((soc_feature(unit, soc_feature_esm_support)) ) { 799 cli_out("\n EXT_L2_ENTRY_1: %d", 800 _l2_addr_counts.l2_count.ext_l2_entry_1); 801 cli_out("\n EXT_L2_ENTRY_1: %d\n\n", 802 _l2_addr_counts.l2_count.ext_l2_entry_2); 803 } 804 } 805 806 /* Reset the L2 counts structure for subsequent runs */ 807 sal_memset(&_l2_addr_counts, 0, sizeof(_l2_addr_counts)); 808 } 809 #endif 810 811 return CMD_OK; 812 813 } 814 815 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 816 817 cli_out("ERROR: %s %s not implemented on this unit\n", 818 ARG_CMD(a), subcmd); 819 return CMD_FAIL; 820 } 821 822 else if (!sal_strcasecmp(subcmd, "check")) { 823 int i, rv, min, max; 824 l2x_entry_t entry; 825 char *sscmd; 826 soc_mem_t mem; 827 soc_field_t fld; 828 829 mem = INVALIDm; 830 fld = INVALIDf; 831 if ((sscmd = ARG_GET(a)) != NULL) { 832 cli_out("Subcommands not supported\n"); 833 return CMD_USAGE; 834 } else { 835 if (SOC_IS_TRIUMPH3(unit)) { 836 mem = L2_ENTRY_1m; 837 }else { 838 mem = L2Xm; 839 } 840 fld = VALIDf; 841 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 842 if(SOC_MEM_FIELD_VALID(unit, mem, BASE_VALIDf)) { 843 fld = BASE_VALIDf; 844 } 845 #endif 846 } 847 if (!SOC_IS_XGS_SWITCH(unit)) { 848 cli_out("Command only valid for XGS switches\n"); 849 return CMD_FAIL; 850 } 851 852 if (!SOC_MEM_IS_VALID(unit, mem)) { 853 cli_out("Error: Memory %s not valid for chip %s.\n", 854 SOC_MEM_UFNAME(unit, mem), SOC_UNIT_NAME(unit)); 855 return CMD_FAIL; 856 } 857 858 min = soc_mem_index_min(unit, mem); 859 max = soc_mem_index_max(unit, mem); 860 861 cli_out("Dumping %s entries. From %d to %d.\n", 862 sscmd, min, max); 863 864 cli_out("Progress . marks 100 memory table entries.\n"); 865 for (i = min; i < max; i++) { 866 if (!((i+1)%100)) { 867 cli_out("."); 868 if (!((i+1)%4000)) { 869 cli_out("\n"); 870 } 871 } 872 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, &entry); 873 if (SOC_SUCCESS(rv)) { 874 if (soc_mem_field32_get(unit, mem, &entry, fld)) { 875 cli_out("Index %d (0x%x) has valid entries (H: %x, E: %d)\n", 876 i, i, i>>3, i&0x3); 877 soc_mem_entry_dump(unit, mem, &entry, BSL_LSS_CLI); 878 cli_out("\n"); 879 } 880 } 881 } 882 cli_out("Done.\n"); 883 } 884 885 else if (!sal_strcasecmp(subcmd, "clear") || 886 !sal_strcasecmp(subcmd, "clr")) { 887 char *static_str; 888 int old_modid, old_port, old_vlan, old_tgid, old_static, old_pending; 889 enum { 890 MAC_PRESENT = 0x00000001, 891 MODID_PRESENT = 0x00000002, 892 PORT_PRESENT = 0x00000004, 893 VLANID_PRESENT = 0x00000008, 894 TGID_PRESENT = 0x00000010 895 } arg_combination; 896 897 /* 898 * Clear the ARL on a per port or per switch basis. Walk ARL 899 * memory finding matching ports such as the user specified, 900 * issue BCM L2 SDK calls for clearing the entries. 901 */ 902 903 /* Save current arguments */ 904 old_modid = arg_modid; 905 old_port = arg_port; 906 old_vlan = arg_vlan; 907 old_tgid = arg_tgid; 908 old_static = arg_static; 909 old_pending = arg_pending; 910 911 arg_modid = -1; 912 arg_port = -1; 913 arg_vlan = -1; 914 arg_tgid = -1; 915 arg_static = TRUE; 916 arg_pending = FALSE; 917 ENET_SET_MACADDR(arg_macaddr, _soc_mac_all_zeroes); 918 arg_combination = 0; 919 920 parse_table_init(unit, &pt); 921 parse_table_add(&pt, "Module", PQ_DFL|PQ_INT, 922 0, &arg_modid, NULL); 923 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 924 0, &arg_port, NULL); 925 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 926 0, &arg_vlan, NULL); 927 parse_table_add(&pt, "TrunkGroupID", PQ_DFL|PQ_INT, 928 0, &arg_tgid, NULL); 929 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 930 0, &arg_macaddr,NULL); 931 parse_table_add(&pt, "STatic", PQ_DFL|PQ_BOOL, 932 0, &arg_static, NULL); 933 parse_table_add(&pt, "PENDing", PQ_DFL|PQ_BOOL, 934 0, &arg_pending, NULL); 935 936 retCode = CMD_OK; 937 938 if (!ARG_CNT(a)) { 939 /* 940 * Restore arguments for parseEndOk below to print 941 * correct settings. 942 */ 943 if (arg_modid == -1) arg_modid = old_modid; 944 if (arg_port == -1) arg_port = old_port; 945 if (arg_vlan == -1) arg_vlan = old_vlan; 946 if (arg_tgid == -1) arg_tgid = old_tgid; 947 if (arg_static == -1) arg_static = old_static; 948 if (arg_pending == -1) arg_pending = old_pending; 949 } 950 951 if (!parseEndOk(a, &pt, &retCode)) { 952 goto done; 953 } 954 955 /* 956 * Notice which arguments were supplied 957 */ 958 if (arg_modid >=0) { 959 arg_combination |= MODID_PRESENT; 960 } 961 962 if (arg_port >= 0) { 963 arg_combination |= PORT_PRESENT; 964 } 965 966 if (ENET_CMP_MACADDR(arg_macaddr, _soc_mac_all_zeroes)) { 967 arg_combination |= MAC_PRESENT; 968 } 969 970 if (arg_tgid >= 0) { 971 arg_combination |= TGID_PRESENT; 972 } 973 974 if (arg_vlan >= 0) { 975 arg_combination |= VLANID_PRESENT; 976 } 977 978 arg_static = arg_static ? BCM_L2_DELETE_STATIC : 0; 979 if (arg_pending == TRUE) { 980 static_str = arg_static ? "static and pending" : "pending"; 981 arg_static |= BCM_L2_DELETE_PENDING; 982 } else { 983 static_str = arg_static ? "static and non-static" : "non-static"; 984 } 985 switch ((int)arg_combination) { 986 case PORT_PRESENT: 987 cli_out("%s: Deleting %s addresses by port, local module ID\n", 988 ARG_CMD(a), static_str); 989 rv = bcm_l2_addr_delete_by_port(unit, 990 -1, arg_port, 991 arg_static); 992 break; 993 994 case PORT_PRESENT | MODID_PRESENT: 995 cli_out("%s: Deleting %s addresses by module/port\n", 996 ARG_CMD(a), static_str); 997 rv = bcm_l2_addr_delete_by_port(unit, 998 arg_modid, arg_port, 999 arg_static); 1000 break; 1001 1002 case VLANID_PRESENT: 1003 cli_out("%s: Deleting %s addresses by VLAN\n", 1004 ARG_CMD(a), static_str); 1005 rv = bcm_l2_addr_delete_by_vlan(unit, 1006 arg_vlan, 1007 arg_static); 1008 break; 1009 1010 case TGID_PRESENT: 1011 cli_out("%s: Deleting %s addresses by trunk ID\n", 1012 ARG_CMD(a), static_str); 1013 rv = bcm_l2_addr_delete_by_trunk(unit, 1014 arg_tgid, 1015 arg_static); 1016 1017 break; 1018 1019 case MAC_PRESENT: 1020 cli_out("%s: Deleting %s addresses by MAC\n", 1021 ARG_CMD(a), static_str); 1022 rv = bcm_l2_addr_delete_by_mac(unit, 1023 arg_macaddr, 1024 arg_static); 1025 break; 1026 1027 case MAC_PRESENT | VLANID_PRESENT: 1028 cli_out("%s: Deleting an address by MAC and VLAN\n", 1029 ARG_CMD(a)); 1030 rv = bcm_l2_addr_delete(unit, 1031 arg_macaddr, 1032 arg_vlan); 1033 1034 break; 1035 1036 case MAC_PRESENT | PORT_PRESENT: 1037 cli_out("%s: Deleting %s addresses by MAC and port\n", 1038 ARG_CMD(a), static_str); 1039 rv = bcm_l2_addr_delete_by_mac_port(unit, 1040 arg_macaddr, 1041 -1, arg_port, 1042 arg_static); 1043 break; 1044 1045 case MAC_PRESENT | PORT_PRESENT | MODID_PRESENT: 1046 cli_out("%s: Deleting %s addresses by MAC and module/port\n", 1047 ARG_CMD(a), static_str); 1048 rv = bcm_l2_addr_delete_by_mac_port(unit, 1049 arg_macaddr, 1050 arg_modid, arg_port, 1051 arg_static); 1052 break; 1053 1054 case VLANID_PRESENT | PORT_PRESENT: 1055 cli_out("%s: Deleting %s addresses by VLAN and port\n", 1056 ARG_CMD(a), static_str); 1057 rv = bcm_l2_addr_delete_by_vlan_port(unit, 1058 arg_vlan, 1059 -1, arg_port, 1060 arg_static); 1061 break; 1062 1063 case VLANID_PRESENT | PORT_PRESENT | MODID_PRESENT: 1064 cli_out("%s: Deleting %s addresses by VLAN and module/port\n", 1065 ARG_CMD(a), static_str); 1066 rv = bcm_l2_addr_delete_by_vlan_port(unit, 1067 arg_vlan, 1068 arg_modid, arg_port, 1069 arg_static); 1070 break; 1071 1072 case VLANID_PRESENT | TGID_PRESENT: 1073 cli_out("%s: Deleting %s addresses by VLAN and trunk ID\n", 1074 ARG_CMD(a), static_str); 1075 rv = bcm_l2_addr_delete_by_vlan_trunk(unit, 1076 arg_vlan, 1077 arg_tgid, 1078 arg_static); 1079 break; 1080 1081 default: 1082 cli_out("%s: Unknown argument combination\n", ARG_CMD(a)); 1083 retCode = CMD_USAGE; 1084 break; 1085 } 1086 1087 done: 1088 /* Restore unused arguments */ 1089 if (arg_modid == -1) arg_modid = old_modid; 1090 if (arg_port == -1) arg_port = old_port; 1091 if (arg_vlan == -1) arg_vlan = old_vlan; 1092 if (arg_tgid == -1) arg_tgid = old_tgid; 1093 if (arg_static == -1) arg_static = old_static; 1094 if (arg_pending == -1) arg_pending = old_pending; 1095 1096 if ((retCode == CMD_OK) && (rv < 0)) { 1097 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 1098 return CMD_FAIL; 1099 } 1100 1101 return retCode; 1102 } 1103 1104 else if (!sal_strcasecmp(subcmd, "watch")) { 1105 static int watch = 0; 1106 char* opt = ARG_GET(a); 1107 if(opt == NULL) { 1108 cli_out("L2 watch is%srunning.\n", 1109 (watch) ? " " : " not "); 1110 return CMD_OK; 1111 } 1112 else if(!sal_strcasecmp(opt, "start")) { 1113 watch = 1; 1114 bcm_l2_addr_register(unit, _l2_watch_cb, NULL); 1115 return CMD_OK; 1116 } 1117 else if(!sal_strcasecmp(opt, "stop")) { 1118 watch = 0; 1119 bcm_l2_addr_unregister(unit, _l2_watch_cb, NULL); 1120 return CMD_OK; 1121 } 1122 else { 1123 return CMD_USAGE; 1124 } 1125 } 1126 1127 #ifdef BCM_XGS_SWITCH_SUPPORT 1128 else if (!sal_strcasecmp(subcmd, "conflict")) { 1129 bcm_l2_addr_t addr; 1130 bcm_l2_addr_t cf[SOC_L2X_BUCKET_SIZE]; 1131 int cf_count, i; 1132 1133 parse_table_init(unit, &pt); 1134 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 1135 0, &arg_macaddr,NULL); 1136 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 1137 0, &arg_vlan, NULL); 1138 if (!parseEndOk(a, &pt, &retCode)) 1139 return retCode; 1140 1141 bcm_l2_addr_t_init(&addr, arg_macaddr, arg_vlan); 1142 1143 if ((rv = bcm_l2_conflict_get(unit, &addr, 1144 cf, sizeof (cf) / sizeof (cf[0]), 1145 &cf_count)) < 0) { 1146 cli_out("%s: bcm_l2_conflict_get failed: %s\n", 1147 ARG_CMD(a), bcm_errmsg(rv)); 1148 return CMD_FAIL; 1149 } 1150 1151 for (i = 0; i < cf_count; i++) { 1152 dump_l2_addr(unit, "conflict: ", &cf[i]); 1153 } 1154 1155 return CMD_OK; 1156 } 1157 1158 else if (!sal_strcasecmp(subcmd, "hash") || 1159 !sal_strcasecmp(subcmd, "-h") ) { 1160 int hash_select; 1161 int hash_bucket = 0; 1162 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) || \ 1163 defined(BCM_TOMAHAWK_SUPPORT) 1164 int num_l2_banks = 0; 1165 int bank = 0; 1166 int l2_index_array[L2_MAX_BANKS] = {0}; 1167 int l2_bucket_array[L2_MAX_BANKS] = {0}; 1168 #endif 1169 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1170 defined(BCM_TRX_SUPPORT) 1171 int hash_select2 = -1; 1172 int hash_bucket2 = -1; 1173 #endif 1174 uint32 regval; 1175 uint8 key[XGS_HASH_KEY_SIZE]; 1176 1177 parse_table_init(unit, &pt); 1178 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 1179 0, &arg_macaddr,NULL); 1180 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 1181 0, &arg_vlan, NULL); 1182 parse_table_add(&pt, "Hash", PQ_DFL|PQ_INT, 1183 (void *)(0), &arg_hash, NULL); 1184 if (!parseEndOk(a, &pt, &retCode)) 1185 return retCode; 1186 1187 hash_select = arg_hash; 1188 #ifdef BCM_XGS3_SWITCH_SUPPORT 1189 if (SOC_IS_XGS3_SWITCH(unit)) { 1190 #ifdef BCM_ISM_SUPPORT 1191 if (soc_feature(unit, soc_feature_ism_memory)) { 1192 int b, rc, index; 1193 l2_entry_1_entry_t entry; 1194 soc_field_t keyflds[MAX_FIELDS], lsbfld; 1195 uint32 bucket, sizes[_SOC_ISM_MAX_BANKS]; 1196 uint8 act_zero_lsb, act_offset, zero_lsb = 0, offset = 48; 1197 uint8 banks[_SOC_ISM_MAX_BANKS], bcount, num_flds; 1198 1199 sal_memset(&entry, 0, sizeof(entry)); 1200 soc_L2_ENTRY_1m_field32_set(unit, &entry, VALIDf, 1); 1201 soc_L2_ENTRY_1m_field32_set(unit, &entry, VLAN_IDf, arg_vlan); 1202 soc_L2_ENTRY_1m_mac_addr_set(unit, &entry, MAC_ADDRf, arg_macaddr); 1203 1204 rc = soc_ism_get_banks_for_mem(unit, L2_ENTRY_1m, banks, sizes, &bcount); 1205 if (rc || !bcount) { 1206 cli_out("Error retreiving bank info: Test aborted.\n"); 1207 return CMD_FAIL; 1208 } 1209 rc = soc_generic_get_hash_key(unit, L2_ENTRY_1m, &entry, keyflds, &lsbfld, 1210 &num_flds); 1211 if (rc) { 1212 cli_out("Error constructing key: Test aborted.\n"); 1213 return CMD_FAIL; 1214 } 1215 sal_memset(key, 0, sizeof(key)); 1216 soc_ism_gen_key_from_keyfields(unit, L2_ENTRY_1m, &entry, keyflds, key, num_flds); 1217 cli_out("Hash[%d] of key " 1218 "0x%02x%02x%02x%02x%02x%02x%02x%02x is \n", hash_select, 1219 key[7], key[6], key[5], key[4], 1220 key[3], key[2], key[1], key[0]); 1221 for (b = 0; b < bcount; b++) { 1222 rc = soc_ism_mem_hash_config_get(unit, L2_ENTRY_1m, &act_zero_lsb); 1223 if (rc) { 1224 cli_out("Error retreiving hash config: Test aborted.\n"); 1225 return CMD_FAIL; 1226 } 1227 rc = soc_ism_hash_offset_config_get(unit, banks[b], &act_offset); 1228 if (rc) { 1229 cli_out("Error retreiving hash offset: Test aborted.\n"); 1230 return CMD_FAIL; 1231 } 1232 switch(hash_select) { 1233 case XGS_HASH_CRC16_UPPER: offset = 48 - soc_ism_get_hash_bits(sizes[b]); 1234 break; 1235 case XGS_HASH_CRC16_LOWER: offset = 32; 1236 break; 1237 case XGS_HASH_LSB: offset = 48; zero_lsb = 1; 1238 break; 1239 case XGS_HASH_ZERO: 1240 break; 1241 case XGS_HASH_CRC32_UPPER: offset = 32 - soc_ism_get_hash_bits(sizes[b]); 1242 break; 1243 case XGS_HASH_CRC32_LOWER: offset = 0; 1244 break; 1245 case XGS_HASH_COUNT: offset = act_offset; zero_lsb = act_zero_lsb; 1246 break; 1247 default: if (hash_select > 63) { 1248 cli_out("Invalid hash offset value !!\n"); 1249 return CMD_FAIL; 1250 } 1251 offset = hash_select; if (hash_select >= 48) { zero_lsb = 1; } 1252 break; 1253 } 1254 /* get config */ 1255 if (zero_lsb != act_zero_lsb) { 1256 rc = soc_ism_mem_hash_config(unit, L2_ENTRY_1m, zero_lsb); 1257 if (rc) { 1258 cli_out("Error setting hash config: Test aborted.\n"); 1259 return CMD_FAIL; 1260 } 1261 } 1262 if (offset != act_offset) { 1263 rc = soc_ism_hash_offset_config(unit, banks[b], offset); 1264 if (rc) { 1265 cli_out("Error setting hash offset: Test aborted.\n"); 1266 return CMD_FAIL; 1267 } 1268 } 1269 rc = soc_generic_hash(unit, L2_ENTRY_1m, &entry, 1 << banks[b], 0, 1270 &index, NULL, &bucket, NULL); 1271 if (rc) { 1272 cli_out("Error calculating hash: Test aborted.\n"); 1273 return CMD_FAIL; 1274 } 1275 cli_out("\tBank[%d] num: %d, bucket: %d, index: %d\n", b, 1276 banks[b], bucket, index); 1277 /* restore config */ 1278 if (zero_lsb != act_zero_lsb) { 1279 rc = soc_ism_mem_hash_config(unit, L2_ENTRY_1m, act_zero_lsb); 1280 if (rc) { 1281 cli_out("Error setting hash config: Test aborted.\n"); 1282 return CMD_FAIL; 1283 } 1284 } 1285 if (offset != act_offset) { 1286 rc = soc_ism_hash_offset_config(unit, banks[b], act_offset); 1287 if (rc) { 1288 cli_out("Error setting hash offset: Test aborted.\n"); 1289 return CMD_FAIL; 1290 } 1291 } 1292 } 1293 return CMD_OK; 1294 } 1295 #endif /* BCM_ISM_SUPPORT */ 1296 if ( 1297 #if defined(BCM_TOMAHAWK3_SUPPORT) 1298 (!SOC_IS_TOMAHAWK3(unit)) && 1299 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1300 (hash_select == XGS_HASH_COUNT)) { 1301 /* Get the hash selection from hardware */ 1302 if ( (rv = READ_HASH_CONTROLr(unit, ®val)) < 0) { 1303 cli_out("%s: ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv)); 1304 return CMD_FAIL; 1305 } 1306 hash_select = soc_reg_field_get(unit, HASH_CONTROLr, regval, 1307 L2_AND_VLAN_MAC_HASH_SELECTf); 1308 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1309 defined(BCM_TRX_SUPPORT) 1310 if (soc_feature(unit, soc_feature_dual_hash)) { 1311 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT) || \ 1312 defined(BCM_TOMAHAWK_SUPPORT) 1313 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 1314 if ( (rv = READ_L2_TABLE_HASH_CONTROLr(unit, 1315 ®val)) < 0) { 1316 cli_out("%s: ERROR: %s\n", ARG_CMD(a), 1317 soc_errmsg(rv)); 1318 return CMD_FAIL; 1319 } 1320 hash_select2 = 1321 soc_reg_field_get(unit, L2_TABLE_HASH_CONTROLr, 1322 regval, HASH_ZERO_OR_LSBf); 1323 if (0 == hash_select2) { 1324 hash_select2 = FB_HASH_ZERO; 1325 } else if (1 == hash_select2) { 1326 hash_select2 = FB_HASH_LSB; 1327 } 1328 } else 1329 #endif 1330 { 1331 if ( (rv = READ_L2_AUX_HASH_CONTROLr(unit, 1332 ®val)) < 0) { 1333 cli_out("%s: ERROR: %s\n", ARG_CMD(a), 1334 soc_errmsg(rv)); 1335 return CMD_FAIL; 1336 } 1337 hash_select2 = 1338 soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr, 1339 regval, HASH_SELECTf); 1340 } 1341 } 1342 #endif 1343 } 1344 1345 #ifdef BCM_TRX_SUPPORT 1346 if (SOC_IS_TRX(unit)) { 1347 int bits; 1348 l2x_entry_t entry; 1349 1350 sal_memset(&entry, 0, sizeof(entry)); 1351 soc_L2Xm_field32_set(unit, &entry, VLAN_IDf, arg_vlan); 1352 soc_L2Xm_mac_addr_set(unit, &entry, MAC_ADDRf, arg_macaddr); 1353 bits = soc_tr_l2x_base_entry_to_key(unit, &entry, key); 1354 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT) || \ 1355 defined(BCM_TRIDENT2_SUPPORT) 1356 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 1357 if ((rv = soc_td2x_th_l2x_hash(unit, (uint32 *)&entry, 1358 &num_l2_banks, l2_bucket_array, 1359 l2_index_array, key)) < 0) { 1360 cli_out("%s ERROR: %s\n", ARG_CMD(a), soc_errmsg(rv)); 1361 return CMD_FAIL; 1362 } 1363 1364 if (num_l2_banks > L2_MAX_BANKS) { 1365 cli_out("%s ERROR: the number of banks overflow\n", 1366 ARG_CMD(a)); 1367 return CMD_FAIL; 1368 } 1369 } else 1370 #endif 1371 { 1372 hash_bucket = soc_tr_l2x_hash(unit, hash_select, bits, &entry, 1373 key); 1374 } 1375 if (hash_select2 >= 0) { 1376 hash_bucket2 = 1377 soc_tr_l2x_hash(unit, hash_select2, bits, &entry, key); 1378 } 1379 } else 1380 #endif 1381 #ifdef BCM_FIREBOLT_SUPPORT 1382 if (SOC_IS_FBX(unit)) { 1383 soc_draco_l2x_param_to_key(arg_macaddr, arg_vlan, key); 1384 hash_bucket = soc_fb_l2_hash(unit, hash_select, key); 1385 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 1386 if (hash_select2 >= 0) { 1387 hash_bucket2 = soc_fb_l2_hash(unit, hash_select2, key); 1388 } 1389 #endif 1390 } else 1391 #endif 1392 { 1393 return CMD_FAIL; 1394 } 1395 } 1396 #endif 1397 1398 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \ 1399 defined(BCM_TOMAHAWK_SUPPORT) 1400 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 1401 cli_out("Hash[%d] of key " 1402 "0x%02x%02x%02x%02x%02x%02x%02x%01x:\n", 1403 hash_select, 1404 key[7], key[6], key[5], key[4], 1405 key[3], key[2], key[1], (key[0] >> 4) & 0xf); 1406 1407 for (bank = 0; bank < num_l2_banks; bank++) { 1408 cli_out("bank%d bucket 0x%06x (%06d) index 0x%06x (%06d)\n", 1409 bank, l2_bucket_array[bank], l2_bucket_array[bank], 1410 l2_index_array[bank], l2_index_array[bank]); 1411 1412 } 1413 1414 } else 1415 #endif 1416 { 1417 cli_out("Hash[%d] of key " 1418 "0x%02x%02x%02x%02x%02x%02x%02x%01x " 1419 "is bucket 0x%03x (%d)\n", hash_select, 1420 key[7], key[6], key[5], key[4], 1421 key[3], key[2], key[1], (key[0] >> 4) & 0xf, 1422 hash_bucket, hash_bucket); 1423 } 1424 1425 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1426 defined(BCM_TRX_SUPPORT) 1427 if (hash_select2 >= 0) { 1428 cli_out("Dual hash[%d] of key " 1429 "0x%02x%02x%02x%02x%02x%02x%02x%01x " 1430 "is bucket 0x%03x (%d)\n", hash_select2, 1431 key[7], key[6], key[5], key[4], 1432 key[3], key[2], key[1], (key[0] >> 4) & 0xf, 1433 hash_bucket2, hash_bucket2); 1434 } 1435 #endif 1436 } 1437 #endif /* BCM_XGS_SWITCH_SUPPORT */ 1438 1439 #ifdef BCM_XGS3_SWITCH_SUPPORT 1440 else if (!sal_strcasecmp(subcmd, "cache") || 1441 !sal_strcasecmp(subcmd, "c") ) { 1442 int cidx; 1443 char *cachecmd = NULL; 1444 char str[16]; 1445 sal_mac_addr_t arg_macaddr, arg_macaddr_mask; 1446 int arg_setpri = 0, arg_bpdu = 0; 1447 int arg_prio = -1, arg_lrndis = FALSE, arg_tunnel = FALSE; 1448 int arg_vlan_mask, arg_cidx, arg_ccount, arg_reinit, idx_max; 1449 int arg_sport = -1, arg_sport_mask; 1450 int arg_lookup_class = 0; 1451 int arg_protocolPkt = 0; 1452 bcm_l2_cache_addr_t l2caddr; 1453 1454 if ((cachecmd = ARG_GET(a)) == NULL) { 1455 return CMD_USAGE; 1456 } 1457 1458 /* Masks always default to full mask */ 1459 arg_vlan_mask = BCM_L2_VID_MASK_ALL; 1460 arg_sport_mask = BCM_L2_SRCPORT_MASK_ALL; 1461 sal_memset(arg_macaddr, 0, sizeof (sal_mac_addr_t)); 1462 sal_memset(arg_macaddr_mask, 0xff, sizeof (sal_mac_addr_t)); 1463 1464 arg_cidx = -1; 1465 arg_ccount = 1; 1466 1467 if (!sal_strcasecmp(cachecmd, "add") || 1468 !sal_strcasecmp(cachecmd, "+") ) { 1469 1470 parse_table_init(unit, &pt); 1471 parse_table_add(&pt, "LookupClass", PQ_DFL|PQ_INT, 1472 0, &arg_lookup_class, NULL); 1473 parse_table_add(&pt, "CacheIndex", PQ_DFL|PQ_INT, 1474 0, &arg_cidx, NULL); 1475 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 1476 0, &arg_macaddr, NULL); 1477 parse_table_add(&pt, "MACaddressMask", PQ_DFL|PQ_MAC, 1478 0, &arg_macaddr_mask, NULL); 1479 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 1480 0, &arg_vlan, NULL); 1481 parse_table_add(&pt, "VlanidMask", PQ_DFL|PQ_HEX, 1482 0, &arg_vlan_mask, NULL); 1483 parse_table_add(&pt, "SourcePort", PQ_DFL|PQ_PORT|PQ_BCM, 1484 0, &arg_sport, NULL); 1485 parse_table_add(&pt, "SourcePortMask", PQ_DFL|PQ_HEX, 1486 0, &arg_sport_mask, NULL); 1487 parse_table_add(&pt, "Module", PQ_DFL|PQ_INT, 1488 0, &arg_modid, NULL); 1489 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT, 1490 (void *)(0), &arg_port, NULL); 1491 parse_table_add(&pt, "Trunk", PQ_DFL|PQ_BOOL, 1492 0, &arg_trunk, NULL); 1493 parse_table_add(&pt, "TrunkGroupID", PQ_DFL|PQ_INT, 1494 0, &arg_tgid, NULL); 1495 parse_table_add(&pt, "SetPriority", PQ_DFL|PQ_BOOL, 1496 0, &arg_setpri, NULL); 1497 parse_table_add(&pt, "PRIOrity", PQ_DFL|PQ_INT, 1498 0, &arg_prio, NULL); 1499 parse_table_add(&pt, "DiscardDest", PQ_DFL|PQ_BOOL, 1500 0, &arg_dd, NULL); 1501 parse_table_add(&pt, "L3", PQ_DFL|PQ_BOOL, 1502 0, &arg_l3if, NULL); 1503 parse_table_add(&pt, "CPUmirror", PQ_DFL|PQ_BOOL, 1504 0, &arg_cbit, NULL); 1505 parse_table_add(&pt, "MIRror", PQ_DFL|PQ_BOOL, 1506 0, &arg_mirror, NULL); 1507 parse_table_add(&pt, "BPDU", PQ_DFL|PQ_BOOL, 1508 0, &arg_bpdu, NULL); 1509 parse_table_add(&pt, "ReplacePriority", PQ_DFL|PQ_BOOL, 1510 0, &arg_rpe, NULL); 1511 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_TRX(unit)) { 1512 parse_table_add(&pt, "LearnDisable", PQ_DFL|PQ_BOOL, 1513 0, &arg_lrndis, NULL); 1514 } 1515 parse_table_add(&pt, "PROTocolPacKeT", PQ_DFL|PQ_BOOL, 1516 0, &arg_protocolPkt, NULL); 1517 if (!parseEndOk(a, &pt, &retCode)) { 1518 return retCode; 1519 } 1520 1521 if (arg_setpri && arg_prio == -1) { 1522 cli_out("%s ERROR: no priority specified\n", ARG_CMD(a)); 1523 return CMD_FAIL; 1524 } 1525 if (!arg_setpri) { 1526 arg_prio = -1; 1527 } 1528 1529 bcm_l2_cache_addr_t_init(&l2caddr); 1530 1531 l2caddr.vlan = arg_vlan_mask ? arg_vlan : 0; 1532 l2caddr.vlan_mask = arg_vlan_mask; 1533 1534 ENET_COPY_MACADDR(arg_macaddr, l2caddr.mac); 1535 ENET_COPY_MACADDR(arg_macaddr_mask, l2caddr.mac_mask); 1536 1537 if (arg_sport >= 0) { 1538 l2caddr.src_port = arg_sport; 1539 l2caddr.src_port_mask = arg_sport_mask; 1540 } 1541 1542 l2caddr.lookup_class = arg_lookup_class; 1543 1544 l2caddr.dest_modid = arg_modid; 1545 l2caddr.dest_port = arg_port; 1546 l2caddr.prio = arg_prio; 1547 l2caddr.dest_trunk = arg_tgid; 1548 1549 /* Configure flags for SDK call */ 1550 if (arg_dd || arg_ds) 1551 l2caddr.flags |= BCM_L2_CACHE_DISCARD; 1552 if (arg_l3if) 1553 l2caddr.flags |= BCM_L2_CACHE_L3; 1554 if (arg_trunk) 1555 l2caddr.flags |= BCM_L2_CACHE_TRUNK; 1556 if (arg_cbit) 1557 l2caddr.flags |= BCM_L2_CACHE_CPU; 1558 if (arg_bpdu) 1559 l2caddr.flags |= BCM_L2_CACHE_BPDU; 1560 if (arg_mirror) 1561 l2caddr.flags |= BCM_L2_CACHE_MIRROR; 1562 if (arg_rpe || arg_setpri) 1563 l2caddr.flags |= BCM_L2_CACHE_SETPRI; 1564 if (arg_lrndis) 1565 l2caddr.flags |= BCM_L2_CACHE_LEARN_DISABLE; 1566 if (arg_tunnel) 1567 l2caddr.flags |= BCM_L2_CACHE_TUNNEL; 1568 if (arg_protocolPkt) 1569 l2caddr.flags |= BCM_L2_CACHE_PROTO_PKT; 1570 1571 dump_l2_cache_addr(unit, "ADD CACHE: ", &l2caddr); 1572 1573 if ((rv = bcm_l2_cache_set(unit, arg_cidx, &l2caddr, 1574 &cidx)) != BCM_E_NONE) { 1575 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1576 return CMD_FAIL; 1577 } 1578 1579 if (arg_cidx == -1) { 1580 cli_out(" => using index %d\n", cidx); 1581 } 1582 1583 /* Set up for next call */ 1584 increment_macaddr(arg_macaddr, 1); 1585 if (arg_cidx >= 0) { 1586 arg_cidx++; 1587 } 1588 1589 return CMD_OK; 1590 } 1591 1592 else if (!sal_strcasecmp(cachecmd, "del") || 1593 !sal_strcasecmp(cachecmd, "-")) { 1594 1595 if (ARG_CNT(a)) { 1596 parse_table_init(unit, &pt); 1597 parse_table_add(&pt, "CacheIndex", PQ_DFL|PQ_INT, 1598 0, &arg_cidx, NULL); 1599 parse_table_add(&pt, "Count", PQ_DFL|PQ_INT, 1600 0, &arg_ccount, NULL); 1601 if (!parseEndOk(a, &pt, &retCode)) { 1602 return retCode; 1603 } 1604 } 1605 1606 if (arg_cidx == -1) { 1607 cli_out("%s ERROR: no index specified\n", ARG_CMD(a)); 1608 return CMD_FAIL; 1609 } 1610 1611 for (idx = 0; idx < arg_ccount; idx++) { 1612 if ((rv = bcm_l2_cache_get(unit, arg_cidx, &l2caddr)) < 0) { 1613 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1614 return CMD_FAIL; 1615 } 1616 1617 if (LOG_CHECK(BSL_LS_BCM_L2 | BSL_VERBOSE)) { 1618 dump_l2_cache_addr(unit, "DEL CACHE: ", &l2caddr); 1619 } 1620 1621 if ((rv = bcm_l2_cache_delete(unit, arg_cidx)) != BCM_E_NONE) { 1622 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1623 return CMD_FAIL; 1624 } 1625 arg_cidx++; 1626 } 1627 1628 return CMD_OK; 1629 } 1630 1631 else if (!sal_strcasecmp(cachecmd, "show") || 1632 !sal_strcasecmp(cachecmd, "-d")) { 1633 1634 if ((rv = bcm_l2_cache_size_get(unit, &idx_max)) < 0) { 1635 cli_out("%s: ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1636 return CMD_FAIL; 1637 } 1638 1639 for (idx = 0; idx < idx_max; idx++) { 1640 if (bcm_l2_cache_get(unit, idx, &l2caddr) == BCM_E_NONE) { 1641 sal_sprintf(str, " %4d : ", idx); 1642 dump_l2_cache_addr(unit, str, &l2caddr); 1643 } 1644 } 1645 1646 return CMD_OK; 1647 } 1648 1649 else if (!sal_strcasecmp(cachecmd, "clear") || 1650 !sal_strcasecmp(cachecmd, "clr")) { 1651 1652 arg_reinit = 0; 1653 1654 if (ARG_CNT(a)) { 1655 parse_table_init(unit, &pt); 1656 parse_table_add(&pt, "ReInit", PQ_DFL|PQ_BOOL, 1657 0, &arg_reinit, NULL); 1658 if (!parseEndOk(a, &pt, &retCode)) { 1659 return retCode; 1660 } 1661 } 1662 1663 if ((rv = bcm_l2_cache_delete_all(unit)) != BCM_E_NONE) { 1664 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1665 return CMD_FAIL; 1666 } 1667 1668 if (arg_reinit && (rv = bcm_l2_cache_init(unit)) != BCM_E_NONE) { 1669 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1670 return CMD_FAIL; 1671 } 1672 1673 return CMD_OK; 1674 } 1675 1676 else { 1677 return CMD_USAGE; 1678 } 1679 } 1680 #if defined(BCM_TRIUMPH_SUPPORT) /* BCM_TRIUMPH_SUPPORT */ 1681 else if (!sal_strcasecmp(subcmd, "station")) { 1682 /* BCM.0> l2 station ... */ 1683 return _l2_station_cmd_process(unit, a); 1684 } 1685 #endif /* !BCM_TRIUMPH_SUPPORT */ 1686 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1687 1688 else { 1689 return CMD_USAGE; 1690 } 1691 1692 return CMD_FAIL; 1693 } 1694 1695 1696 /* 1697 * Add an L2 address to the switch, remove an L2 address from the 1698 * switch, show addresses, and clear addresses on a per port basis. 1699 */ 1700 1701 cmd_result_t 1702 if_esw_bpdu(int unit, args_t *a) 1703 { 1704 int idx, count; 1705 char *subcmd = NULL; 1706 sal_mac_addr_t arg_macaddr, maczero; 1707 bcm_l2_cache_addr_t addr; 1708 int arg_index = 0, idx_used = 0; 1709 cmd_result_t retCode; 1710 int rv; 1711 parse_table_t pt; 1712 char buf[SAL_MACADDR_STR_LEN]; 1713 1714 /* 1715 * Initialize MAC address field for the user to the first real 1716 * address which does not conflict 1717 */ 1718 maczero[0] = arg_macaddr[0] = 0; 1719 maczero[1] = arg_macaddr[1] = 0; 1720 maczero[2] = arg_macaddr[2] = 0; 1721 maczero[3] = arg_macaddr[3] = 0; 1722 maczero[4] = arg_macaddr[4] = 0; 1723 maczero[5] = 0; 1724 arg_macaddr[5] = 0x1; 1725 1726 if ((subcmd = ARG_GET(a)) == NULL) { 1727 return CMD_USAGE; 1728 } 1729 1730 /* Check valid device to operation on ...*/ 1731 if (!sh_check_attached(ARG_CMD(a), unit)) { 1732 return CMD_FAIL; 1733 } 1734 1735 if (!sal_strcasecmp(subcmd, "add") || 1736 !sal_strcasecmp(subcmd, "+")) { 1737 parse_table_init(unit, &pt); 1738 parse_table_add(&pt, "Index", PQ_DFL|PQ_INT, 1739 (void *)(0), &arg_index, NULL); 1740 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 1741 0, &arg_macaddr,NULL); 1742 1743 if (!parseEndOk(a, &pt, &retCode)) { 1744 return retCode; 1745 } 1746 1747 ENET_COPY_MACADDR(arg_macaddr, addr.mac); 1748 addr.flags = BCM_L2_CACHE_BPDU; 1749 rv = bcm_l2_cache_set(unit, arg_index, &addr, &idx_used); 1750 if (rv != BCM_E_NONE) { 1751 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1752 return CMD_FAIL; 1753 } 1754 return CMD_OK; 1755 } 1756 1757 if (!sal_strcasecmp(subcmd, "del") || 1758 !sal_strcasecmp(subcmd, "-")) { 1759 parse_table_init(unit, &pt); 1760 parse_table_add(&pt, "Index", PQ_DFL|PQ_INT, 1761 (void *)(0), &arg_index, NULL); 1762 1763 if (!parseEndOk(a, &pt, &retCode)) { 1764 return retCode; 1765 } 1766 1767 ENET_COPY_MACADDR(maczero, addr.mac); 1768 addr.flags = BCM_L2_CACHE_BPDU; 1769 rv = bcm_l2_cache_set(unit, arg_index, &addr, &idx_used); 1770 if (rv != BCM_E_NONE) { 1771 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1772 return CMD_FAIL; 1773 } 1774 return CMD_OK; 1775 } 1776 1777 if (!sal_strcasecmp(subcmd, "show") || 1778 !sal_strcasecmp(subcmd, "-d")) { 1779 rv = bcm_l2_cache_size_get(unit, &count); 1780 if (rv != BCM_E_NONE) { 1781 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1782 return CMD_FAIL; 1783 } 1784 cli_out("unit %d has %d BPDU entries\n", unit, count); 1785 for (idx = 0; idx < count; idx++) { 1786 rv = bcm_l2_cache_get(unit, idx, &addr); 1787 if (rv == BCM_E_NOT_FOUND) { 1788 continue; 1789 } else if (rv != BCM_E_NONE) { 1790 cli_out("%s ERROR: %s\n", ARG_CMD(a), bcm_errmsg(rv)); 1791 return CMD_FAIL; 1792 } 1793 1794 format_macaddr(buf, addr.mac); 1795 cli_out("\tBPDU %d: %s\n", idx, buf); 1796 } 1797 return CMD_OK ; 1798 } 1799 return CMD_USAGE; 1800 } 1801 1802 /* 1803 * Multicast command 1804 */ 1805 1806 cmd_result_t 1807 if_esw_mcast(int unit, args_t *a) 1808 { 1809 char *subcmd; 1810 int r; 1811 sal_mac_addr_t mac_address; 1812 int vid=1; 1813 int cos_dst=0; 1814 int mcindex = -1; 1815 bcm_pbmp_t pbmp; 1816 bcm_pbmp_t ubmp; 1817 parse_table_t pt; 1818 cmd_result_t retCode; 1819 bcm_mcast_addr_t mcaddr; 1820 pbmp_t rtrpbmp; 1821 int port, dport; 1822 1823 mac_address[0] = 0x1; 1824 mac_address[1] = 0; 1825 mac_address[2] = 0; 1826 mac_address[3] = 0; 1827 mac_address[4] = 0; 1828 mac_address[5] = 0x1; 1829 1830 BCM_PBMP_CLEAR(pbmp); 1831 1832 if (!sh_check_attached(ARG_CMD(a), unit)) { 1833 return CMD_FAIL; 1834 } 1835 1836 if ((subcmd = ARG_GET(a)) == NULL) { 1837 return CMD_USAGE; 1838 } 1839 1840 if (!sal_strcasecmp(subcmd, "init")) { 1841 if ((r = bcm_mcast_init(unit)) < 0) { 1842 cli_out("ERROR: %s\n", bcm_errmsg(r)); 1843 return CMD_FAIL; 1844 } 1845 return CMD_OK; 1846 } 1847 1848 if (sal_strcasecmp(subcmd, "bitmap") == 0) { 1849 if ((subcmd = ARG_GET(a)) == NULL) { 1850 return CMD_USAGE; 1851 } 1852 1853 if (!SOC_IS_XGS_FABRIC(unit)) { 1854 cli_out("Mcast bitmap operations only valid on XGS fabric devices\n"); 1855 return CMD_FAIL; 1856 } 1857 1858 if (sal_strcasecmp(subcmd, "max") == 0) { 1859 if ((r = bcm_mcast_bitmap_max_get(unit, &mcindex)) < 0) { 1860 cli_out("bcm_mcast_bitmap_max_set failed ERROR: %s\n", 1861 bcm_errmsg(r)); 1862 return CMD_FAIL; 1863 } 1864 cli_out("Unit %d: Maximum multicast index of %d\n", 1865 unit, mcindex); 1866 return CMD_OK; 1867 } 1868 1869 if (sal_strcasecmp(subcmd, "set") == 0) { 1870 parse_table_init(unit, &pt); 1871 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT|PQ_BCM, 1872 (void *)(0), &port, NULL); 1873 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 1874 (void *)(0), &pbmp, NULL); 1875 parse_table_add(&pt, "Index", PQ_DFL|PQ_INT, 1876 0, &mcindex, NULL); 1877 if (!parseEndOk(a, &pt, &retCode)) 1878 return retCode; 1879 1880 if ((r = bcm_mcast_bitmap_set(unit, mcindex, port, pbmp)) < 0) { 1881 cli_out("bcm_mcast_bitmap_set failed ERROR: %s\n", 1882 bcm_errmsg(r)); 1883 return CMD_FAIL; 1884 } 1885 return CMD_OK; 1886 } 1887 1888 if (sal_strcasecmp(subcmd, "del") == 0) { 1889 parse_table_init(unit, &pt); 1890 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT|PQ_BCM, 1891 (void *)(0), &port, NULL); 1892 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 1893 (void *)(0), &pbmp, NULL); 1894 parse_table_add(&pt, "Index", PQ_DFL|PQ_INT, 1895 0, &mcindex, NULL); 1896 if (!parseEndOk(a, &pt, &retCode)) 1897 return retCode; 1898 1899 if ((r = bcm_mcast_bitmap_del(unit, mcindex, port, pbmp)) < 0) { 1900 cli_out("bcm_mcast_bitmap_del failed ERROR: %s\n", 1901 bcm_errmsg(r)); 1902 return CMD_FAIL; 1903 } 1904 return CMD_OK; 1905 } 1906 1907 if (sal_strcasecmp(subcmd, "get") == 0) { 1908 char buf[FORMAT_PBMP_MAX]; 1909 parse_table_init(unit, &pt); 1910 parse_table_add(&pt, "Port", PQ_DFL|PQ_PORT|PQ_BCM, 1911 (void *)(0), &port, NULL); 1912 parse_table_add(&pt, "Index", PQ_DFL|PQ_INT, 1913 0, &mcindex, NULL); 1914 if (!parseEndOk(a, &pt, &retCode)) 1915 return retCode; 1916 1917 if ((r = bcm_mcast_bitmap_get(unit, mcindex, port, &pbmp)) < 0) { 1918 cli_out("bcm_mcast_bitmap_get failed ERROR: %s\n", 1919 bcm_errmsg(r)); 1920 return CMD_FAIL; 1921 } 1922 format_pbmp(unit, buf, sizeof (buf), pbmp); 1923 cli_out("Unit %d: MC index=%d, Port=%d, Bitmap=%s\n", 1924 unit, mcindex, port, buf); 1925 return CMD_OK; 1926 } 1927 return CMD_USAGE; 1928 } 1929 1930 if (SOC_IS_XGS_FABRIC(unit)) { 1931 cli_out("Non-bitmap mcast operations only valid on XGS switch devices\n\n"); 1932 return CMD_USAGE; 1933 } 1934 1935 if (sal_strcasecmp(subcmd, "add") == 0) { 1936 parse_table_init(unit, &pt); 1937 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 1938 0, &mac_address,NULL); 1939 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 1940 0, &vid, NULL); 1941 parse_table_add(&pt, "Cos", PQ_DFL|PQ_INT, 1942 0, &cos_dst, NULL); 1943 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 1944 (void *)(0), &pbmp, NULL); 1945 parse_table_add(&pt, "UntagBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 1946 (void *)(0), &ubmp, NULL); 1947 parse_table_add(&pt, "Index", PQ_DFL|PQ_INT, 1948 0, &mcindex, NULL); 1949 if (!parseEndOk(a, &pt, &retCode)) 1950 return retCode; 1951 1952 bcm_mcast_addr_t_init(&mcaddr, mac_address, vid); 1953 mcaddr.cos_dst = cos_dst; 1954 BCM_PBMP_ASSIGN(mcaddr.pbmp, pbmp); 1955 BCM_PBMP_ASSIGN(mcaddr.ubmp, ubmp); 1956 mcaddr.l2mc_index = mcindex; 1957 if (mcindex < 0) { 1958 r = bcm_mcast_addr_add(unit, &mcaddr); 1959 } else { 1960 r = bcm_mcast_addr_add_w_l2mcindex(unit, &mcaddr); 1961 } 1962 if (r < 0) { 1963 cli_out("bcm_mcast_addr_add failed ERROR: %s\n", bcm_errmsg(r)); 1964 return CMD_FAIL; 1965 } 1966 return CMD_OK; 1967 } 1968 1969 if (sal_strncasecmp(subcmd, "del", 3) == 0) { 1970 parse_table_init(unit, &pt); 1971 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 1972 0, &mac_address,NULL); 1973 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 1974 0, &vid, NULL); 1975 if (!parseEndOk(a, &pt, &retCode)) 1976 return retCode; 1977 if ((r = bcm_mcast_addr_remove(unit, mac_address, vid)) < 0) { 1978 cli_out("bcm_mcast_addr_remove failed ERROR: %s\n", 1979 bcm_errmsg(r)); 1980 return CMD_FAIL; 1981 } 1982 return CMD_OK; 1983 } 1984 1985 if (sal_strcasecmp(subcmd, "join") == 0) { 1986 parse_table_init(unit, &pt); 1987 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 1988 0, &mac_address,NULL); 1989 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 1990 0, &vid, NULL); 1991 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 1992 (void *)(0), &pbmp, NULL); 1993 if (!parseEndOk(a, &pt, &retCode)) 1994 return retCode; 1995 /* coverity[overrun-local : FALSE] */ 1996 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 1997 r = bcm_mcast_join(unit, mac_address, vid, port, 1998 &mcaddr, &rtrpbmp); 1999 if (r < 0) { 2000 cli_out("ERROR: %s %s port %s failed: %s\n", 2001 ARG_CMD(a), subcmd, BCM_PORT_NAME(unit, port), 2002 bcm_errmsg(r)); 2003 return CMD_FAIL; 2004 } 2005 switch (r) { 2006 case BCM_MCAST_JOIN_ADDED: 2007 cli_out("port %s added\n", BCM_PORT_NAME(unit, port)); 2008 break; 2009 case BCM_MCAST_JOIN_UPDATED: 2010 cli_out("port %s updated\n", BCM_PORT_NAME(unit, port)); 2011 break; 2012 default: 2013 cli_out("port %s complete, return %d\n", 2014 BCM_PORT_NAME(unit, port), r); 2015 break; 2016 } 2017 } 2018 return CMD_OK; 2019 } 2020 2021 if (sal_strcasecmp(subcmd, "leave") == 0) { 2022 parse_table_init(unit, &pt); 2023 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 2024 0, &mac_address,NULL); 2025 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 2026 0, &vid, NULL); 2027 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 2028 (void *)(0), &pbmp, NULL); 2029 if (!parseEndOk(a, &pt, &retCode)) 2030 return retCode; 2031 DPORT_BCM_PBMP_ITER(unit, pbmp, dport, port) { 2032 r = bcm_mcast_leave(unit, mac_address, vid, port); 2033 if (r < 0) { 2034 cli_out("ERROR: %s %s port %s failed: %s\n", 2035 ARG_CMD(a), subcmd, BCM_PORT_NAME(unit, port), 2036 bcm_errmsg(r)); 2037 return CMD_FAIL; 2038 } 2039 switch (r) { 2040 case BCM_MCAST_LEAVE_NOTFOUND: 2041 cli_out("port %s not found\n", BCM_PORT_NAME(unit, port)); 2042 break; 2043 case BCM_MCAST_LEAVE_DELETED: 2044 cli_out("port %s deleted\n", BCM_PORT_NAME(unit, port)); 2045 break; 2046 case BCM_MCAST_LEAVE_UPDATED: 2047 cli_out("port %s updated\n", BCM_PORT_NAME(unit, port)); 2048 break; 2049 default: 2050 cli_out("port %s complete, return %d\n", 2051 BCM_PORT_NAME(unit, port), r); 2052 break; 2053 } 2054 } 2055 return CMD_OK; 2056 } 2057 2058 if (sal_strcasecmp(subcmd, "padd") == 0) { 2059 parse_table_init(unit, &pt); 2060 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 2061 0, &mac_address, NULL); 2062 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 2063 0, &vid, NULL); 2064 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 2065 (void *)(0), &pbmp, NULL); 2066 parse_table_add(&pt, "UntagBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 2067 (void *)(0), &ubmp, NULL); 2068 if (!parseEndOk(a, &pt, &retCode)) 2069 return retCode; 2070 bcm_mcast_addr_t_init(&mcaddr, mac_address, vid); 2071 BCM_PBMP_ASSIGN(mcaddr.pbmp, pbmp); 2072 BCM_PBMP_ASSIGN(mcaddr.ubmp, ubmp); 2073 r = bcm_mcast_port_add(unit, &mcaddr); 2074 if (r < 0) { 2075 cli_out("ERROR: %s %s ports failed: %s\n", 2076 ARG_CMD(a), subcmd, bcm_errmsg(r)); 2077 return CMD_FAIL; 2078 } 2079 return CMD_OK; 2080 } 2081 2082 if (sal_strcasecmp(subcmd, "premove") == 0) { 2083 parse_table_init(unit, &pt); 2084 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 2085 0, &mac_address, NULL); 2086 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 2087 0, &vid, NULL); 2088 parse_table_add(&pt, "PortBitMap", PQ_DFL|PQ_PBMP|PQ_BCM, 2089 (void *)(0), &pbmp, NULL); 2090 if (!parseEndOk(a, &pt, &retCode)) 2091 return retCode; 2092 bcm_mcast_addr_t_init(&mcaddr, mac_address, vid); 2093 BCM_PBMP_ASSIGN(mcaddr.pbmp, pbmp); 2094 r = bcm_mcast_port_remove(unit, &mcaddr); 2095 if (r < 0) { 2096 cli_out("ERROR: %s %s ports failed: %s\n", 2097 ARG_CMD(a), subcmd, bcm_errmsg(r)); 2098 return CMD_FAIL; 2099 } 2100 return CMD_OK; 2101 } 2102 2103 return CMD_USAGE; 2104 } 2105 2106 /* 2107 * AGE timer 2108 */ 2109 2110 cmd_result_t 2111 cmd_esw_age(int unit, args_t *a) 2112 { 2113 int seconds; 2114 int r; 2115 2116 if (!sh_check_attached(ARG_CMD(a), unit)) { 2117 return CMD_FAIL; 2118 } 2119 2120 UNSUPPORTED_COMMAND(unit, SOC_CHIP_BCM5670, a); 2121 UNSUPPORTED_COMMAND(unit, SOC_CHIP_BCM5675, a); 2122 2123 if (!ARG_CNT(a)) { /* Display settings */ 2124 if ((r = bcm_l2_age_timer_get(unit, &seconds)) != BCM_E_NONE) { 2125 cli_out("%s ERROR: could not get age time: %s\n", 2126 ARG_CMD(a), bcm_errmsg(r)); 2127 return CMD_FAIL; 2128 } 2129 2130 cli_out("Current age timer is %d.\n", seconds); 2131 2132 return CMD_OK; 2133 } 2134 2135 seconds = sal_ctoi(ARG_GET(a), 0); 2136 2137 if ((r = bcm_l2_age_timer_set(unit, seconds)) != BCM_E_NONE) { 2138 cli_out("%s ERROR: could not set age time: %s\n", 2139 ARG_CMD(a), bcm_errmsg(r)); 2140 return CMD_FAIL; 2141 } 2142 2143 cli_out("Set age timer to %d. %s\n", seconds, seconds ? "":"(disabled)"); 2144 2145 return CMD_OK; 2146 } 2147 2148 #ifdef BCM_XGS_SWITCH_SUPPORT 2149 2150 /* 2151 * L2 Mode 2152 */ 2153 2154 char l2mode_usage[] = 2155 "Parameters: [on] [off] [Interval=<interval>]\n\t" 2156 "Starts the L2 shadow table update thread running every <interval>\n\t" 2157 "microseconds. The task reads the entire L2 table and issues updates\n\t" 2158 "to the L2 shadow table and associated callbacks. If <interval> is 0,\n\t" 2159 "stops the task. If <interval> is omitted, prints current setting.\n"; 2160 2161 cmd_result_t 2162 cmd_l2mode(int unit, args_t *a) 2163 { 2164 soc_control_t *soc = SOC_CONTROL(unit); 2165 sal_usecs_t usec; 2166 parse_table_t pt; 2167 int r; 2168 uint32 flags = 0; /* no flags yet */ 2169 2170 if (!sh_check_attached(ARG_CMD(a), unit)) { 2171 return CMD_FAIL; 2172 } 2173 2174 UNSUPPORTED_COMMAND(unit, SOC_CHIP_BCM5670, a); 2175 UNSUPPORTED_COMMAND(unit, SOC_CHIP_BCM5675, a); 2176 2177 if (!soc_feature(unit, soc_feature_arl_hashed)) { 2178 cli_out("%s: No L2X on this chip\n", ARG_CMD(a)); 2179 return CMD_FAIL; 2180 } 2181 2182 if (soc == NULL) { 2183 return CMD_FAIL; 2184 } 2185 usec = soc->l2x_interval; 2186 2187 parse_table_init(unit, &pt); 2188 parse_table_add(&pt, "Interval", PQ_DFL|PQ_INT, 2189 (void *) 0, &usec, NULL); 2190 2191 if (!ARG_CNT(a)) { /* Display settings */ 2192 cli_out("Current settings:\n"); 2193 parse_eq_format(&pt); 2194 parse_arg_eq_done(&pt); 2195 return CMD_OK; 2196 } 2197 2198 if (parse_arg_eq(a, &pt) < 0) { 2199 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 2200 parse_arg_eq_done(&pt); 2201 return CMD_FAIL; 2202 } 2203 parse_arg_eq_done(&pt); 2204 2205 if (ARG_CNT(a) > 0 && !sal_strcasecmp(_ARG_CUR(a), "on")) { 2206 usec = prev_l2x_interval[unit]; 2207 ARG_NEXT(a); 2208 } 2209 if (ARG_CNT(a) > 0 && !sal_strcasecmp(_ARG_CUR(a), "off")) { 2210 ARG_NEXT(a); 2211 usec = 0; 2212 } 2213 2214 if (ARG_CNT(a) > 0) { 2215 return CMD_USAGE; 2216 } 2217 2218 if (usec > 0) { 2219 r = soc_l2x_start(unit, flags, usec); 2220 } else { 2221 sal_usecs_t prev_interval; 2222 2223 r = soc_l2x_running(unit, NULL, &prev_interval); 2224 if (r < 0 || prev_interval <= 0) { 2225 prev_interval = SOC_L2X_INTERVAL_DEFAULT; 2226 } 2227 prev_l2x_interval[unit] = prev_interval; 2228 r = soc_l2x_stop(unit); 2229 } 2230 2231 if (r < 0) { 2232 cli_out("%s: Error: Could not set L2X mode: %s\n", 2233 ARG_CMD(a), soc_errmsg(r)); 2234 return CMD_FAIL; 2235 } 2236 2237 return CMD_OK; 2238 } 2239 2240 #if defined(BCM_TOMAHAWK3_SUPPORT) 2241 char l2learn_usage[] = 2242 "Parameters: [on] [off] [Interval=<interval>]\n\t" 2243 "Starts L2 learning thread running every <interval>\n\t" 2244 "microseconds. If <interval> is 0, stops the task.\n\t" 2245 "If <interval> is omitted, prints current setting.\n\t" 2246 "Note: If this thread is stopped, L2 learning is stopped\n"; 2247 2248 cmd_result_t 2249 cmd_l2learn(int unit, args_t *a) 2250 { 2251 soc_control_t *soc = SOC_CONTROL(unit); 2252 sal_usecs_t usec; 2253 parse_table_t pt; 2254 int r; 2255 2256 if (!(SOC_IS_TOMAHAWK3(unit))) { 2257 cli_out("%s: Command supported on Tomahawk3 chip only\n", ARG_CMD(a)); 2258 return CMD_FAIL; 2259 } 2260 2261 if (!sh_check_attached(ARG_CMD(a), unit)) { 2262 return CMD_FAIL; 2263 } 2264 2265 if (!soc_feature(unit, soc_feature_arl_hashed)) { 2266 cli_out("%s: No L2X on this chip\n", ARG_CMD(a)); 2267 return CMD_FAIL; 2268 } 2269 2270 if (soc == NULL) { 2271 return CMD_FAIL; 2272 } 2273 2274 usec = soc->l2x_learn_interval; 2275 2276 parse_table_init(unit, &pt); 2277 parse_table_add(&pt, "Interval", PQ_DFL|PQ_INT, 2278 (void *) 0, &usec, NULL); 2279 2280 if (!ARG_CNT(a)) { /* Display settings */ 2281 cli_out("Current settings:\n"); 2282 parse_eq_format(&pt); 2283 parse_arg_eq_done(&pt); 2284 cli_out("Note: If this thread is stopped, L2 learning is stopped\n"); 2285 return CMD_OK; 2286 } 2287 2288 if (parse_arg_eq(a, &pt) < 0) { 2289 cli_out("%s: Error: Unknown option: %s\n", ARG_CMD(a), ARG_CUR(a)); 2290 parse_arg_eq_done(&pt); 2291 return CMD_FAIL; 2292 } 2293 2294 parse_arg_eq_done(&pt); 2295 2296 if (ARG_CNT(a) > 0 && !sal_strcasecmp(_ARG_CUR(a), "on")) { 2297 usec = prev_l2x_lrn_interval[unit]; 2298 ARG_NEXT(a); 2299 } 2300 2301 if (ARG_CNT(a) > 0 && !sal_strcasecmp(_ARG_CUR(a), "off")) { 2302 ARG_NEXT(a); 2303 usec = 0; 2304 } 2305 2306 if (ARG_CNT(a) > 0) { 2307 return CMD_USAGE; 2308 } 2309 2310 if (usec > 0) { 2311 r = soc_th3_l2_learn_thread_start(unit, usec); 2312 } else { 2313 sal_usecs_t prev_interval; 2314 2315 cli_out("Stopping L2 Learn thread\n"); 2316 cli_out("Note this command can take longer to complete depending" 2317 " on configured interval\n"); 2318 r = soc_th3_l2_learn_thread_running(unit, &prev_interval); 2319 /* Thread is not running */ 2320 if (r == 0 || prev_interval <= 0) { 2321 /* Set to default value */ 2322 prev_interval = BCMSIM_L2XLRN_INTERVAL; 2323 } 2324 prev_l2x_lrn_interval[unit] = prev_interval; 2325 r = soc_th3_l2_learn_thread_stop(unit); 2326 } 2327 2328 if (r < 0) { 2329 cli_out("%s: Error: Could not set L2X mode: %s\n", 2330 ARG_CMD(a), soc_errmsg(r)); 2331 return CMD_FAIL; 2332 } else { 2333 cli_out("L2 Learn thread %s\n", usec ? "started" : "stopped"); 2334 } 2335 2336 return CMD_OK; 2337 } 2338 #endif /* BCM_TOMAHAWK3_SUPPORT */ 2339 #endif /* BCM_XGS_SWITCH_SUPPORT */ 2340 2341 #if defined(BCM_TOMAHAWK_SUPPORT) 2342 cmd_result_t 2343 if_esw_latency(int unit, args_t *a) 2344 { 2345 int rv = 0, support; 2346 char *arg, **list = NULL; 2347 uint32 resource, count = 0, idx = 0; 2348 char *rstr[3] = {"feature", "memory", "register"}; 2349 char *sstr[2] = {"not ", ""}; 2350 2351 if (!sh_check_attached(ARG_CMD(a), unit)) { 2352 return CMD_FAIL; 2353 } 2354 if ((arg = ARG_GET(a)) == NULL) { 2355 return (CMD_USAGE); 2356 } 2357 2358 /* latency show */ 2359 if (arg && !sal_strcasecmp(arg, "show")) { 2360 rv = bcmi_esw_switch_latency_show(unit); 2361 if ((arg = ARG_GET(a)) == NULL) { 2362 return (CMD_OK); 2363 } 2364 2365 #ifdef SOC_NO_NAMES 2366 return CMD_OK; 2367 #else 2368 if (!sal_strcasecmp(arg, "feature")) { 2369 count = soc_feature_count; 2370 list = soc_feature_name; 2371 idx = 0; 2372 } else if (!sal_strcasecmp(arg, "mem")) { 2373 count = NUM_SOC_MEM; 2374 list = soc_mem_name; 2375 idx = 1; 2376 } else if (!sal_strcasecmp(arg, "reg")) { 2377 count = NUM_SOC_REG; 2378 list = soc_reg_name; 2379 idx = 2; 2380 } 2381 #endif 2382 2383 if ((arg = ARG_GET(a)) == NULL) { 2384 return (CMD_USAGE); 2385 } 2386 2387 /* generic resource iterator */ 2388 for (resource = 0; resource < count; resource++) { 2389 if (!sal_strcasecmp(arg, list[resource])) { 2390 break; 2391 } 2392 } 2393 if (!(resource < count)) { 2394 cli_out("invalid %s: %s\n", rstr[idx], arg); 2395 return CMD_FAIL; 2396 } 2397 2398 switch(idx) 2399 { 2400 case 0: /* latency show feature */ 2401 support = soc_feature(unit, resource) ? 1 : 0; 2402 break; 2403 case 1: /* latency show mem */ 2404 support = bcmi_esw_switch_latency_mem_avail(unit, resource) ? 1 : 0; 2405 break; 2406 case 2: /* latency show reg */ 2407 support = bcmi_esw_switch_latency_reg_avail(unit, resource) ? 1 : 0; 2408 break; 2409 default: 2410 return CMD_USAGE; 2411 } 2412 2413 cli_out("%s '%s' is %savailable in this latency mode\n", 2414 rstr[idx], arg, sstr[support]); 2415 return CMD_OK; 2416 } else if (arg && !sal_strcasecmp(arg, "diag")) { /* latency diag */ 2417 rv = bcmi_esw_switch_latency_diag(unit); 2418 } 2419 else { 2420 cli_out("error: incorrect argument\n"); 2421 return CMD_USAGE; 2422 } 2423 2424 if (BCM_FAILURE(rv)) { 2425 return CMD_FAIL; 2426 } else { 2427 return CMD_OK; 2428 } 2429 } 2430 #endif 2431