l2.c (28435B)
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: l2.c 8 * Purpose: 9 * Requires: 10 */ 11 12 #include <sal/types.h> 13 #include <sal/appl/sal.h> 14 #include <sal/appl/io.h> 15 #include <sal/core/libc.h> 16 #include <sal/core/thread.h> 17 #include <shared/bsl.h> 18 #include <bcmx/lplist.h> 19 #include <bcmx/lport.h> 20 #include <bcmx/bcmx.h> 21 #include <bcmx/l2.h> 22 23 #include <bcm/l2.h> 24 #include <bcm/error.h> 25 26 #include <appl/diag/shell.h> 27 #include <appl/diag/system.h> 28 #include <appl/diag/parse.h> 29 30 #if defined(INCLUDE_BCMX) 31 32 #include "bcmx.h" 33 34 static int l2n_report = TRUE; 35 static int l2n_inserts = 0; 36 static int l2n_deletes = 0; 37 static int l2n_insert_calls = 0; 38 static int l2n_delete_calls = 0; 39 static int l2n_native_inserts = 0; 40 static int l2n_native_deletes = 0; 41 static int l2n_insert = FALSE; 42 43 STATIC void 44 bcmxdiag_l2_notify(bcmx_l2_addr_t *addr, int insert, void *cookie) 45 { 46 char flags_str[200]; 47 int flag_str_left; 48 int count = 0; 49 int i; 50 int rv; 51 52 if (insert) { 53 l2n_inserts++; 54 } else { 55 l2n_deletes++; 56 } 57 if (addr->flags & BCM_L2_NATIVE) { 58 if (insert) { 59 l2n_native_inserts++; 60 } else { 61 l2n_native_deletes++; 62 } 63 } 64 65 if (l2n_report) { 66 cli_out("BCMX L2 %s: V=0x%03x MAC=0x%02x%02x%02x" 67 "%02x%02x%02x %s uport %s (0x%x) unit %d\n", 68 insert ? "ADD" : "DEL", 69 addr->vid, 70 addr->mac[0], addr->mac[1], addr->mac[2], 71 addr->mac[3], addr->mac[4], addr->mac[5], 72 insert ? "to" : "from", 73 bcmx_lport_to_uport_str(addr->lport), 74 addr->lport, addr->bcm_unit); 75 76 if (addr->flags != 0) { 77 flags_str[0] = '\0'; 78 flag_str_left = sizeof(flags_str) - 1; 79 for (i = 0; i < bcm_l2_flags_count; i++) { 80 if ((1 << i) & addr->flags) { 81 if (flag_str_left > 0) { 82 strncat(flags_str, bcm_l2_flags_str[i], flag_str_left); 83 flag_str_left -= strlen(bcm_l2_flags_str[i]); 84 } 85 if (flag_str_left > 0) { 86 strncat(flags_str, " ", flag_str_left); 87 flag_str_left -= 1; 88 } 89 if (!(++count % 4)) { 90 if (flag_str_left > 0) { 91 strncat(flags_str, "\n ", 92 flag_str_left); 93 flag_str_left -= 13; 94 } 95 } 96 } 97 } 98 cli_out(" Flags 0x%x: %s\n", addr->flags, flags_str); 99 } 100 } 101 102 if (l2n_insert) { /* Propagate native inserts/deletes */ 103 if (addr->flags & BCM_L2_NATIVE) { 104 if (insert) { 105 ++l2n_insert_calls; 106 rv = bcmx_l2_addr_add(addr, NULL); 107 if (rv < 0) { 108 cli_out("ERROR L2 notify insert %d: %s\n", rv, 109 bcm_errmsg(rv)); 110 } 111 } else { 112 ++l2n_delete_calls; 113 rv = bcmx_l2_addr_delete(addr->mac, addr->vid); 114 if (rv < 0) { 115 cli_out("ERROR L2 notify delete %d: %s\n", rv, 116 bcm_errmsg(rv)); 117 } 118 } 119 } 120 } 121 } 122 123 124 /* 125 * Add an L2 address to the switch, remove an L2 address from the 126 * switch, show addresses, and clear addresses on a per port basis. 127 */ 128 129 char bcmx_cmd_l2_usage[] = 130 "Usages:\n" 131 #ifdef COMPILER_STRING_CONST_LIMIT 132 " l2 add | del | remove | notify | age | lookup\n" 133 #else 134 " l2 add [Ports=<user-port-list>] [MACaddress=<mac>] [Vlanid=<id>]\n" 135 " [Trunk=true|false] [TrunkGroupId=<id>] [STatic=true|false]\n" 136 " [SourceCosPriority=true|false] [DiscardSource=true|false]\n" 137 " [DiscardDest]=true|false] [L3=true|false]\n" 138 " [CPUmirror=true|false]\n" 139 " - Add incrementing L2 addresses associated with port(s)\n" 140 " l2 del [MACaddress=<mac>] [Count=<value>] [Vlanid=<id>]\n" 141 " - Delete incrementing L2 address(s)\n" 142 " l2 remove [Vlanid=<id>] [TrunkGroupId=<id>]\n" 143 " - Remove all L2 addresses with VlanID or TrunkGroupId\n" 144 " l2 notify [start | stop | reg | unreg | [+|-]report [+|-]insert]\n" 145 " - Start, stop, register or unregister L2 change notification\n" 146 " 'report' means report learns as they happen\n" 147 " 'insert' means call bcmx_l2_addr_add on notify callback\n" 148 " l2 age [<seconds>]\n" 149 " - Set L2 aging interval if <seconds> provided,\n" 150 " otherwise return current aging interval.\n" 151 " l2 lookup MACaddress=<mac> Vlanid=<id>\n" 152 " - Lookup an l2 entry\n" 153 #ifdef BCM_XGS3_SWITCH_SUPPORT 154 " l2 cache add CacheIndex=<index>\n" 155 " [MACaddress=<mac>] [MACaddressMask=<mac>]\n" 156 " [Vlanid=<id>] [VlanidMask=<mask>]\n" 157 " [Port=<uport>] [Trunk=true|false] [TrunkGroupId=<id>]\n" 158 " [SetPriority=true|false] [PRIOrity=<prio>]\n" 159 " [DiscardDest]=true|false] [CPUmirror=true|false]\n" 160 " [MIRror=true|false] [BPDU=true|false] [L3=true|false]\n" 161 " - Add L2 cache entry\n" 162 " l2 cache del CacheIndex=<index> [Count=<value>]\n" 163 " - Delete L2 cache entry\n" 164 " l2 cache clear\n" 165 " - Delete all L2 cache entries\n" 166 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 167 #endif 168 ; 169 170 cmd_result_t 171 bcmx_cmd_l2(int unit, args_t *args) 172 { 173 int idx; 174 char *subcmd = NULL; 175 static int initted = 0; 176 static sal_mac_addr_t arg_macaddr; 177 static int arg_static=0, arg_trunk=0, arg_l3if=0, 178 arg_scp=0, arg_ds=0, arg_dd=0, arg_count=0, 179 arg_vlan=VLAN_ID_DEFAULT, arg_tgid=0, arg_cbit=0; 180 int arg_vlan_temp = -1, arg_tgid_temp = -1, 181 arg_age_seconds = 0; 182 char *argage; 183 int rv = CMD_OK; 184 parse_table_t pt; 185 cmd_result_t retCode; 186 bcmx_l2_addr_t l2addr; 187 char *plist_str; 188 static bcmx_lplist_t plist; 189 int count; 190 bcmx_lport_t lport; 191 192 /* 193 * Initialize MAC address field for the user to the first real 194 * address which does not conflict 195 */ 196 if (! initted) { 197 arg_macaddr[0] = 0; 198 arg_macaddr[1] = 0; 199 arg_macaddr[2] = 0; 200 arg_macaddr[3] = 0; 201 arg_macaddr[4] = 0; 202 arg_macaddr[5] = 0x1; 203 204 if (bcmx_lplist_init(&plist, 0, 0) < 0) { 205 cli_out("%s: Error: could not init plist\n", ARG_CMD(args)); 206 return CMD_FAIL; 207 } 208 209 initted = 1; 210 } 211 212 if ((subcmd = ARG_GET(args)) == NULL) { 213 return CMD_USAGE; 214 } 215 216 if (! sal_strcasecmp(subcmd, "add") || ! sal_strcasecmp(subcmd, "+")) { 217 218 parse_table_init(unit, &pt); 219 parse_table_add(&pt, "Ports", PQ_STRING, 220 0, &plist_str, NULL); 221 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 222 0, &arg_macaddr,NULL); 223 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 224 0, &arg_vlan, NULL); 225 parse_table_add(&pt, "Trunk", PQ_DFL|PQ_BOOL, 226 0, &arg_trunk, NULL); 227 parse_table_add(&pt, "TrunkGroupID", PQ_DFL|PQ_INT, 228 0, &arg_tgid, NULL); 229 parse_table_add(&pt, "STatic", PQ_DFL|PQ_BOOL, 230 0, &arg_static, NULL); 231 parse_table_add(&pt, "SourceCosPriority", PQ_DFL|PQ_BOOL, 232 0, &arg_scp, NULL); 233 parse_table_add(&pt, "DiscardSource", PQ_DFL|PQ_BOOL, 234 0, &arg_ds, NULL); 235 parse_table_add(&pt, "DiscardDest",PQ_DFL|PQ_BOOL, 236 0, &arg_dd, NULL); 237 parse_table_add(&pt, "L3", PQ_DFL|PQ_BOOL, 238 0, &arg_l3if, NULL); 239 parse_table_add(&pt, "CPUmirror", PQ_DFL|PQ_BOOL, 240 0, &arg_cbit, NULL); 241 242 243 if (!parse_arg_eq(args, &pt)) { 244 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args)); 245 parse_arg_eq_done(&pt); 246 return CMD_FAIL; 247 } 248 249 bcmx_lplist_clear(&plist); 250 251 if (bcmx_lplist_parse(&plist, plist_str) < 0) { 252 cli_out("%s: Error: could not parse portlist: %s\n", 253 ARG_CMD(args), plist_str); 254 parse_arg_eq_done(&pt); 255 return CMD_FAIL; 256 } 257 parse_arg_eq_done(&pt); 258 259 /* 260 * If we are setting the range, the MAC address is incremented by 261 * 1 for each port. 262 */ 263 BCMX_LPLIST_ITER(plist, lport, count) { 264 bcmx_l2_addr_t_init(&l2addr, arg_macaddr, arg_vlan); 265 266 l2addr.tgid = arg_tgid; 267 268 /* Configure flags for SDK call */ 269 if (arg_static) 270 l2addr.flags |= BCM_L2_STATIC; 271 if (arg_scp) 272 l2addr.flags |= BCM_L2_COS_SRC_PRI; 273 if (arg_dd) 274 l2addr.flags |= BCM_L2_DISCARD_DST; 275 if (arg_ds) 276 l2addr.flags |= BCM_L2_DISCARD_SRC; 277 if (arg_l3if) 278 l2addr.flags |= BCM_L2_L3LOOKUP; 279 if (arg_trunk) 280 l2addr.flags |= BCM_L2_TRUNK_MEMBER; 281 if (arg_cbit) 282 l2addr.flags |= BCM_L2_COPY_TO_CPU; 283 284 l2addr.lport = lport; 285 286 bcmx_dump_l2_addr("ADD: ", &l2addr, NULL); 287 288 if ((rv = bcmx_l2_addr_add(&l2addr, NULL))!= BCM_E_NONE) { 289 cli_out("%s ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 290 return CMD_FAIL; 291 } 292 293 /* Set up for next call */ 294 increment_macaddr(arg_macaddr, 1); 295 } 296 297 return CMD_OK; 298 } 299 300 else if (! sal_strcasecmp(subcmd, "del") || ! sal_strcasecmp(subcmd, "-")) { 301 302 arg_count = 1; /* Default count */ 303 304 parse_table_init(unit, &pt); 305 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 306 0, &arg_macaddr,NULL); 307 parse_table_add(&pt, "Count", PQ_DFL|PQ_INT, 308 0, &arg_count, NULL); 309 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 310 0, &arg_vlan, NULL); 311 312 if (!parseEndOk(args, &pt, &retCode)) 313 return retCode; 314 315 for (idx = 0; idx < arg_count; idx++) { 316 rv = bcmx_l2_addr_get(arg_macaddr, arg_vlan, &l2addr, NULL); 317 318 if (rv < 0) { 319 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 320 return CMD_FAIL; 321 } 322 323 bcmx_dump_l2_addr("DEL: ", &l2addr, NULL); 324 325 if ((rv = bcmx_l2_addr_delete(arg_macaddr, arg_vlan)) < 0) { 326 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 327 return CMD_FAIL; 328 } 329 330 increment_macaddr(arg_macaddr, 1); 331 } 332 333 return CMD_OK; 334 } 335 336 else if (! sal_strcasecmp(subcmd, "remove") || ! sal_strcasecmp(subcmd, "rem")) { 337 parse_table_init(unit, &pt); 338 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 339 (void *) -1, &arg_vlan_temp, NULL); 340 parse_table_add(&pt, "TrunkGroupID", PQ_DFL|PQ_INT, 341 (void *) -1, &arg_tgid_temp, NULL); 342 if (!parseEndOk(args, &pt, &retCode)) 343 return retCode; 344 345 if (arg_vlan_temp > 0) { 346 rv = bcmx_l2_addr_delete_by_vlan(arg_vlan_temp, 0); 347 348 if (rv < 0) { 349 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 350 return CMD_FAIL; 351 } 352 } 353 354 if (arg_tgid_temp > 0) { 355 rv = bcmx_l2_addr_delete_by_trunk(arg_tgid_temp, 0); 356 357 if (rv < 0) { 358 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 359 return CMD_FAIL; 360 } 361 } 362 363 return CMD_OK; 364 } 365 366 else if (! sal_strcasecmp(subcmd, "age")) { 367 368 if ((argage = ARG_GET(args)) == NULL) { 369 rv = bcmx_l2_age_timer_get(&arg_age_seconds); 370 371 if (rv < 0) { 372 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 373 return CMD_FAIL; 374 } else { 375 cli_out("Current age timer setting: %d seconds\n", 376 arg_age_seconds); 377 } 378 } else { 379 arg_age_seconds = sal_ctoi(argage, 0); 380 rv = bcmx_l2_age_timer_set(arg_age_seconds); 381 382 if (rv < 0) { 383 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 384 return CMD_FAIL; 385 } 386 } 387 388 return CMD_OK; 389 } 390 391 else if (! sal_strcasecmp(subcmd, "lookup") || ! sal_strcasecmp(subcmd, "lkup")) { 392 393 /* 394 * Lookup an arl entry 395 */ 396 parse_table_init(unit, &pt); 397 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 398 0, &arg_macaddr,NULL); 399 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 400 0, &arg_vlan, NULL); 401 if (!parseEndOk(args, &pt, &retCode)) 402 return retCode; 403 404 rv = bcmx_l2_addr_get(arg_macaddr, arg_vlan, &l2addr, NULL); 405 406 if (rv < 0) { 407 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 408 return CMD_FAIL; 409 } else { /* Found it. Display. */ 410 lport = l2addr.lport; 411 cli_out("Found on uport %s:", bcmx_lport_to_uport_str(lport)); 412 bcmx_dump_l2_addr("lookup", &l2addr, NULL); 413 return CMD_OK; 414 } 415 } 416 417 else if (! sal_strcasecmp(subcmd, "dump")) { 418 cli_out("L2 dump not yet implemented.\n"); 419 return CMD_OK; 420 } 421 422 else if (! sal_strcasecmp(subcmd, "notify")) { 423 int rv = BCM_E_NONE; 424 425 if ((subcmd = ARG_GET(args)) == NULL) { 426 cli_out("L2 notify: Ins %d (tot %d). " 427 "Del %d (tot %d). Ins calls %d. Del calls %d\n", 428 l2n_native_inserts, l2n_inserts, 429 l2n_native_deletes, l2n_deletes, 430 l2n_insert_calls, l2n_delete_calls); 431 432 return CMD_OK; 433 } else { 434 while (subcmd) { 435 if (!sal_strcasecmp(subcmd, "start")) { 436 rv = bcmx_l2_notify_start(); 437 if (rv < 0) { 438 cli_out("Could not start BCMX L2 notify: %s", 439 bcm_errmsg(rv)); 440 return CMD_FAIL; 441 } 442 } else if (!sal_strcasecmp(subcmd, "stop")) { 443 rv = bcmx_l2_notify_stop(); 444 if (rv < 0) { 445 cli_out("Could not stop BCMX L2 notify: %s", 446 bcm_errmsg(rv)); 447 return CMD_FAIL; 448 } 449 } else if (!sal_strcasecmp(subcmd, "reg")) { 450 rv = bcmx_l2_notify_register(bcmxdiag_l2_notify, NULL); 451 if (rv < 0) { 452 cli_out("Could not register BCMX L2 notify " 453 "handler: %s", bcm_errmsg(rv)); 454 return CMD_FAIL; 455 } 456 } else if (!sal_strcasecmp(subcmd, "unreg")) { 457 rv = bcmx_l2_notify_unregister(bcmxdiag_l2_notify, NULL); 458 if (rv < 0) { 459 cli_out("Could not register BCMX L2 notify " 460 "handler: %s", bcm_errmsg(rv)); 461 return CMD_FAIL; 462 } 463 } else if (!sal_strcasecmp(subcmd, "report")) { 464 l2n_report = !l2n_report; 465 cli_out("L2 notify report is %s\n", l2n_report ? 466 "on" : "off"); 467 } else if (!sal_strcasecmp(subcmd, "+report")) { 468 l2n_report = TRUE; 469 } else if (!sal_strcasecmp(subcmd, "-report")) { 470 l2n_report = FALSE; 471 } else if (!sal_strcasecmp(subcmd, "insert")) { 472 l2n_insert = !l2n_insert; 473 cli_out("L2 notify insert is %s\n", l2n_insert ? 474 "on" : "off"); 475 } else if (!sal_strcasecmp(subcmd, "+insert")) { 476 l2n_insert = TRUE; 477 } else if (!sal_strcasecmp(subcmd, "-insert")) { 478 l2n_insert = FALSE; 479 } else { 480 cli_out("Bad notify subcommand: %s\n", subcmd); 481 return CMD_USAGE; 482 } 483 subcmd = ARG_GET(args); 484 } 485 } 486 487 return CMD_OK; 488 } 489 490 #ifdef BCM_XGS3_SWITCH_SUPPORT 491 else if (!sal_strcasecmp(subcmd, "cache") || 492 !sal_strcasecmp(subcmd, "c") ) { 493 int cidx; 494 char *cachecmd = NULL; 495 char str[16]; 496 static sal_mac_addr_t arg_macaddr, arg_macaddr_mask; 497 static int arg_setpri = 0, arg_bpdu = 0, arg_mirror = 0, arg_prio = -1; 498 static int arg_lport = 0; 499 int arg_vlan_mask, arg_cidx, arg_ccount, idx_max; 500 int arg_lookup_class = 0; 501 bcmx_l2_cache_addr_t l2caddr; 502 char *port_str = NULL; 503 504 if ((cachecmd = ARG_GET(args)) == NULL) { 505 return CMD_USAGE; 506 } 507 508 /* Masks always default to full mask */ 509 arg_vlan_mask = BCM_L2_VID_MASK_ALL; 510 sal_memset(arg_macaddr_mask, 0xff, sizeof (sal_mac_addr_t)); 511 512 arg_cidx = -1; 513 arg_ccount = 1; 514 515 if (!sal_strcasecmp(cachecmd, "add") || 516 !sal_strcasecmp(cachecmd, "+") ) { 517 518 parse_table_init(unit, &pt); 519 parse_table_add(&pt, "LookupClass", PQ_DFL|PQ_INT, 520 0, &arg_lookup_class, NULL); 521 parse_table_add(&pt, "CacheIndex", PQ_DFL|PQ_INT, 522 0, &arg_cidx, NULL); 523 parse_table_add(&pt, "MACaddress", PQ_DFL|PQ_MAC, 524 0, &arg_macaddr, NULL); 525 parse_table_add(&pt, "MACaddressMask", PQ_DFL|PQ_MAC, 526 0, &arg_macaddr_mask, NULL); 527 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 528 0, &arg_vlan, NULL); 529 parse_table_add(&pt, "VlanidMask", PQ_DFL|PQ_HEX, 530 0, &arg_vlan_mask, NULL); 531 parse_table_add(&pt, "Port", PQ_DFL|PQ_STRING, 532 0, &port_str, NULL); 533 parse_table_add(&pt, "Trunk", PQ_DFL|PQ_BOOL, 534 0, &arg_trunk, NULL); 535 parse_table_add(&pt, "TrunkGroupID", PQ_DFL|PQ_INT, 536 0, &arg_tgid, NULL); 537 parse_table_add(&pt, "SetPriority", PQ_DFL|PQ_BOOL, 538 0, &arg_trunk, NULL); 539 parse_table_add(&pt, "PRIOrity", PQ_DFL|PQ_INT, 540 0, &arg_tgid, NULL); 541 parse_table_add(&pt, "DiscardDest", PQ_DFL|PQ_BOOL, 542 0, &arg_dd, NULL); 543 parse_table_add(&pt, "L3", PQ_DFL|PQ_BOOL, 544 0, &arg_l3if, NULL); 545 parse_table_add(&pt, "CPUmirror", PQ_DFL|PQ_BOOL, 546 0, &arg_cbit, NULL); 547 parse_table_add(&pt, "MIRror", PQ_DFL|PQ_BOOL, 548 0, &arg_mirror, NULL); 549 parse_table_add(&pt, "BPDU", PQ_DFL|PQ_BOOL, 550 0, &arg_bpdu, NULL); 551 if (parse_arg_eq(args, &pt) < 0) { 552 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args)); 553 parse_arg_eq_done(&pt); 554 return CMD_FAIL; 555 } 556 557 if (port_str != NULL) { 558 arg_lport = bcmx_uport_to_lport(bcmx_uport_parse(port_str, 559 NULL)); 560 if (arg_lport == BCMX_NO_SUCH_LPORT) { 561 sal_printf("%s: Error: could not parse port: %s\n", 562 ARG_CMD(args), port_str); 563 parse_arg_eq_done(&pt); 564 return CMD_FAIL; 565 } 566 } 567 parse_arg_eq_done(&pt); /* No longer needed */ 568 569 if (arg_cidx == -1) { 570 cli_out("%s ERROR: no cache index specified\n", ARG_CMD(args)); 571 return CMD_FAIL; 572 } 573 if (arg_setpri && arg_prio == -1) { 574 cli_out("%s ERROR: no priority specified\n", ARG_CMD(args)); 575 return CMD_FAIL; 576 } 577 if (!arg_setpri) { 578 arg_prio = -1; 579 } 580 581 bcmx_l2_cache_addr_t_init(&l2caddr); 582 583 l2caddr.vlan = arg_vlan; 584 l2caddr.vlan_mask = arg_vlan_mask; 585 586 ENET_COPY_MACADDR(arg_macaddr, l2caddr.mac); 587 ENET_COPY_MACADDR(arg_macaddr_mask, l2caddr.mac_mask); 588 589 l2caddr.lookup_class = arg_lookup_class; 590 591 l2caddr.dest_lport = arg_lport; 592 593 l2caddr.dest_trunk = arg_tgid; 594 595 /* Configure flags for SDK call */ 596 if (arg_dd || arg_ds) 597 l2caddr.flags |= BCM_L2_CACHE_DISCARD; 598 if (arg_l3if) 599 l2caddr.flags |= BCM_L2_CACHE_L3; 600 if (arg_trunk) 601 l2caddr.flags |= BCM_L2_CACHE_TRUNK; 602 if (arg_cbit) 603 l2caddr.flags |= BCM_L2_CACHE_CPU; 604 if (arg_bpdu) 605 l2caddr.flags |= BCM_L2_CACHE_BPDU; 606 if (arg_mirror) 607 l2caddr.flags |= BCM_L2_CACHE_MIRROR; 608 609 bcmx_dump_l2_cache_addr("ADD CACHE: ", &l2caddr); 610 611 if ((rv = bcmx_l2_cache_set(arg_cidx, &l2caddr, 612 &cidx)) != BCM_E_NONE) { 613 cli_out("%s ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 614 return CMD_FAIL; 615 } 616 617 if (cidx == -1) { 618 cli_out(" => using index %d\n", cidx); 619 } 620 621 /* Set up for next call */ 622 increment_macaddr(arg_macaddr, 1); 623 if (arg_cidx >= 0) { 624 arg_cidx++; 625 } 626 627 return CMD_OK; 628 } 629 630 else if (!sal_strcasecmp(cachecmd, "del") || 631 !sal_strcasecmp(cachecmd, "-")) { 632 633 if (ARG_CNT(args)) { 634 parse_table_init(unit, &pt); 635 parse_table_add(&pt, "CacheIndex", PQ_DFL|PQ_INT, 636 0, &arg_cidx, NULL); 637 parse_table_add(&pt, "Count", PQ_DFL|PQ_INT, 638 0, &arg_ccount, NULL); 639 if (!parseEndOk(args, &pt, &retCode)) { 640 return retCode; 641 } 642 } 643 644 if (arg_cidx == -1) { 645 cli_out("%s ERROR: no index specified\n", ARG_CMD(args)); 646 return CMD_FAIL; 647 } 648 649 for (idx = 0; idx < arg_ccount; idx++) { 650 if ((rv = bcmx_l2_cache_get(arg_cidx, &l2caddr)) < 0) { 651 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 652 return CMD_FAIL; 653 } 654 655 bcmx_dump_l2_cache_addr("DEL CACHE: ", &l2caddr); 656 657 if ((rv = bcmx_l2_cache_delete(arg_cidx)) != BCM_E_NONE) { 658 cli_out("%s ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 659 return CMD_FAIL; 660 } 661 arg_cidx++; 662 } 663 664 return CMD_OK; 665 } 666 667 else if (!sal_strcasecmp(cachecmd, "show") || 668 !sal_strcasecmp(cachecmd, "-d")) { 669 670 if ((rv = bcmx_l2_cache_size_get(&idx_max)) < 0) { 671 cli_out("%s: ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 672 return CMD_FAIL; 673 } 674 675 for (idx = 0; idx <= idx_max; idx++) { 676 if (bcmx_l2_cache_get(idx, &l2caddr) == BCM_E_NONE) { 677 sal_sprintf(str, " %4d : ", idx); 678 bcmx_dump_l2_cache_addr(str, &l2caddr); 679 } 680 } 681 682 return CMD_OK; 683 } 684 685 else if (!sal_strcasecmp(cachecmd, "clear") || 686 !sal_strcasecmp(cachecmd, "clr")) { 687 688 if (ARG_CNT(args)) { 689 return CMD_USAGE; 690 } 691 692 if ((rv = bcmx_l2_cache_delete_all()) != BCM_E_NONE) { 693 cli_out("%s ERROR: %s\n", ARG_CMD(args), bcm_errmsg(rv)); 694 return CMD_FAIL; 695 } 696 697 return CMD_OK; 698 } 699 700 else { 701 return CMD_USAGE; 702 } 703 } 704 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 705 706 return CMD_USAGE; 707 } 708 709 710 void 711 bcmx_dump_l2_addr(char *pfx, bcmx_l2_addr_t *l2addr, bcmx_lplist_t *port_block) 712 { 713 bcmx_lport_t lport; 714 int count; 715 716 717 cli_out("%smac=%02x:%02x:%02x:%02x:%02x:%02x vlan=%d uport=%s", 718 pfx, 719 l2addr->mac[0], l2addr->mac[1], l2addr->mac[2], 720 l2addr->mac[3], l2addr->mac[4], l2addr->mac[5], 721 l2addr->vid, 722 bcmx_lport_to_uport_str(l2addr->lport)); 723 724 725 if (l2addr->flags & BCM_L2_TRUNK_MEMBER) { 726 cli_out(" Trunk=%d Rtag=%d", l2addr->tgid, l2addr->trunk_sel); 727 } 728 729 if (l2addr->flags & BCM_L2_STATIC) { 730 cli_out(" Static"); 731 } 732 733 if (l2addr->flags & BCM_L2_HIT) { 734 cli_out(" Hit"); 735 } 736 737 if (l2addr->cos_src != 0 || l2addr->cos_dst != 0) { 738 cli_out(" COS(src=%d,dst=%d)", l2addr->cos_src, l2addr->cos_dst); 739 } 740 741 if (l2addr->flags & BCM_L2_COS_SRC_PRI) { 742 cli_out(" SCP"); 743 } 744 745 if (l2addr->flags & BCM_L2_COPY_TO_CPU) { 746 cli_out(" CPU"); 747 } 748 749 if (l2addr->flags & BCM_L2_L3LOOKUP) { 750 cli_out(" L3"); 751 } 752 753 if (l2addr->flags & BCM_L2_DISCARD_SRC) { 754 cli_out(" DiscardSrc"); 755 } 756 757 if (l2addr->flags & BCM_L2_DISCARD_DST) { 758 cli_out(" DiscardDest"); 759 } 760 761 if (l2addr->flags & BCM_L2_MCAST) { 762 cli_out(" MCast=%d", l2addr->l2mc_group); 763 } 764 765 if (!BCMX_LPLIST_IS_EMPTY(port_block)) { 766 BCMX_LPLIST_ITER(*(port_block), lport, count) { 767 cli_out(" Uport blocked: %s\n", bcmx_lport_to_uport_str(lport)); 768 cli_out("\n"); 769 } 770 } 771 772 cli_out("\n"); 773 } 774 775 #ifdef BCM_XGS3_SWITCH_SUPPORT 776 void 777 bcmx_dump_l2_cache_addr(char *pfx, bcmx_l2_cache_addr_t *l2caddr) 778 { 779 cli_out("%smac=%02x:%02x:%02x:%02x:%02x:%02x", 780 pfx, 781 l2caddr->mac[0], l2caddr->mac[1], l2caddr->mac[2], 782 l2caddr->mac[3], l2caddr->mac[4], l2caddr->mac[5]); 783 784 if (!ENET_MACADDR_BROADCAST(l2caddr->mac_mask)) { 785 cli_out("/%02x:%02x:%02x:%02x:%02x:%02x", 786 l2caddr->mac_mask[0], l2caddr->mac_mask[1], l2caddr->mac_mask[2], 787 l2caddr->mac_mask[3], l2caddr->mac_mask[4], l2caddr->mac_mask[5]); 788 } 789 790 cli_out(" vlan=%d", l2caddr->vlan); 791 792 if (l2caddr->vlan_mask != BCM_L2_VID_MASK_ALL) { 793 cli_out("/0x%03x", l2caddr->vlan_mask); 794 } 795 796 if (l2caddr->flags & BCM_L2_CACHE_TRUNK) { 797 cli_out(" trunk=%d", l2caddr->dest_trunk); 798 } else { 799 cli_out(" uport=%s", bcmx_lport_to_uport_str(l2caddr->dest_lport)); 800 } 801 802 if (l2caddr->flags & BCM_L2_CACHE_SETPRI) { 803 cli_out(" prio=%d", l2caddr->prio); 804 } 805 806 if (l2caddr->flags & BCM_L2_CACHE_BPDU) { 807 cli_out(" BPDU"); 808 } 809 810 if ((l2caddr->flags & BCM_L2_CACHE_CPU) || 811 (l2caddr->dest_lport == BCMX_LPORT_LOCAL_CPU)) { 812 cli_out(" CPU"); 813 } 814 815 if (l2caddr->flags & BCM_L2_CACHE_L3) { 816 cli_out(" L3"); 817 } 818 819 if (l2caddr->flags & BCM_L2_CACHE_DISCARD) { 820 cli_out(" Discard"); 821 } 822 823 if (l2caddr->flags & BCM_L2_CACHE_MIRROR) { 824 cli_out(" Mirror"); 825 } 826 827 cli_out("\n"); 828 } 829 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 830 831 #endif