bcmx.c (14530B)
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: bcmx.c 8 * Purpose: First cut at some bcmx commands 9 * Requires: 10 */ 11 12 /* Keep dependencies calculated properly by putting this before ifdef. */ 13 14 #include <sal/core/libc.h> 15 16 #include <appl/diag/shell.h> 17 #include <appl/diag/cmdlist.h> 18 #include <appl/diag/system.h> 19 20 #include <appl/diag/diag.h> 21 22 #if defined(INCLUDE_BCMX) 23 24 #include <bcm/init.h> 25 26 #include <bcmx/bcmx.h> 27 #include <bcmx/lport.h> 28 #include <bcmx/lplist.h> 29 30 #include "bcmx.h" 31 32 #define _PLURAL(x) (((x) == 1) ? "" : "s") 33 34 35 STATIC int 36 _bcmx_sys_info_lport_display(bcmx_lport_t lport, int lp_cnt) 37 { 38 int bcm_unit, modid; 39 bcm_port_t bcm_port, modport; 40 uint32 flags; 41 int rv; 42 43 rv = bcmx_lport_to_unit_port(lport, &bcm_unit, &bcm_port); 44 if (BCM_SUCCESS(rv)) { 45 rv = bcmx_lport_to_modid_port(lport, &modid, &modport); 46 } 47 48 if (lp_cnt == 0) { 49 sal_printf("%6s%8s%-10s%10s.%4s%10s.%4s%8s%s\n", 50 "Uport", "", "Lport", "Unit", "Port", 51 "ModID","Port", "", "Flags"); 52 } 53 54 if (BCM_SUCCESS(rv)) { 55 flags = BCMX_LPORT_FLAGS(lport); 56 57 sal_printf("%6s%8s0x%8.8x%10d.%-4d%10d.%-4d%8s%s%s%s%s%s%s%s\n", 58 bcmx_lport_to_uport_str(lport), "", 59 lport, 60 bcm_unit, bcm_port, 61 modid, modport, "", 62 flags & BCMX_PORT_F_STACK_INT ? "Int-Stk " : "", 63 flags & BCMX_PORT_F_STACK_EXT ? "Ext-Stk " : "", 64 flags & BCMX_PORT_F_CPU ? "CPU " : "", 65 flags & BCMX_PORT_F_HG ? "HG " : "", 66 flags & BCMX_PORT_F_FE ? "FE " : "", 67 flags & BCMX_PORT_F_GE ? "GE " : "", 68 flags & BCMX_PORT_F_XE ? "XE " : ""); 69 } else { 70 /* Error obtaining information */ 71 sal_printf("%6s%8s0x%8.8x (%s)\n", 72 bcmx_lport_to_uport_str(lport), "", 73 lport, 74 bcm_errmsg(rv)); 75 } 76 77 return rv; 78 } 79 80 /* Local functions */ 81 STATIC cmd_result_t bcmx_lp_parse(int unit, args_t *args); 82 STATIC cmd_result_t bcmx_cmd_sys_info(int unit, args_t *args); 83 STATIC cmd_result_t bcmx_attach_unit(int unit, args_t *args); 84 STATIC cmd_result_t bcmx_detach_unit(int unit, args_t *args); 85 86 extern char bcmx_test_pkt_usage[]; 87 88 static char bcmx_cmd_sys_info_usage[] = 89 "Usage:\n\t" 90 " sysinfo\n" 91 " - Show information about system\n"; 92 93 STATIC cmd_result_t 94 bcmx_cmd_sys_info(int unit, args_t *args) 95 { 96 int lp_cnt; 97 bcmx_lport_t lport; 98 99 lp_cnt = 0; 100 101 /* Iterate over 'lport' */ 102 BCMX_FOREACH_LPORT(lport) { 103 _bcmx_sys_info_lport_display(lport, lp_cnt++); 104 } 105 106 if (bcmx_unit_count != 0 || lp_cnt != 0) { 107 sal_printf("BCMX has %d unit%s registered with %d valid lports\n", 108 bcmx_unit_count, bcmx_unit_count == 1 ? "" : "s", lp_cnt); 109 } 110 111 return CMD_OK; 112 } 113 114 static char bcmx_lp_parse_usage[] = "Parameters: <port list>\n" 115 " Parse a user port list and report\n" 116 " Syntax of port list is a comma separated list of:\n" 117 " [N[-M] | FE | GE | XE | ALL | *]\n"; 118 119 STATIC cmd_result_t 120 bcmx_lp_parse(int unit, args_t *args) 121 { 122 bcmx_lplist_t list; 123 char *c; 124 bcmx_lport_t lport; 125 int count; 126 cmd_result_t cmd_rv = CMD_OK; 127 int lp_cnt; 128 129 if ((c = ARG_GET(args)) == NULL) { 130 return CMD_USAGE; 131 } 132 133 bcmx_lplist_init(&list, 0, 0); 134 135 if (bcmx_lplist_parse(&list, c)) { 136 cmd_rv = CMD_FAIL; 137 } else { 138 139 sal_printf("List contains %d port%s; allocated %d\n", 140 list.lp_last + 1, (list.lp_last == 0) ? "" : "s", 141 list.lp_alloc); 142 lp_cnt = 0; 143 144 BCMX_LPLIST_ITER(list, lport, count) { 145 _bcmx_sys_info_lport_display(lport, lp_cnt++); 146 } 147 148 if (lp_cnt != list.lp_last + 1) { 149 sal_printf("WARNING: Port count mismatch\n"); 150 } 151 sal_printf("\n"); 152 } 153 154 bcmx_lplist_free(&list); 155 156 return cmd_rv; 157 } 158 159 /**************************************************************** 160 * 161 * Mapping provided by application to get strings for user ports 162 */ 163 164 165 STATIC void 166 bcmx_uport_to_str_default(bcmx_uport_t uport, char *buf, int len) 167 { 168 if (len < BCMX_UPORT_STR_LENGTH_MIN) { 169 return; 170 } 171 172 sal_sprintf(buf, "%d", PTR_TO_INT(uport)); 173 } 174 175 STATIC bcmx_uport_t 176 bcmx_uport_parse_default(char *buf, char **end) 177 { 178 int port; 179 180 port = strtoul(buf, end, 0); 181 182 return (bcmx_uport_t) INT_TO_PTR(port); 183 } 184 185 bcmx_uport_to_str_f bcmx_uport_to_str = bcmx_uport_to_str_default; 186 bcmx_uport_parse_f bcmx_uport_parse = bcmx_uport_parse_default; 187 188 189 /* 190 * Function: 191 * bcmx_lport_to_uport_str 192 * Purpose: 193 * Returns the uport value in char string format for given lport. 194 * Parameters: 195 * lport - BCMX logical port 196 * Returns: 197 * String uport 198 * Notes: 199 * This routine MUST be called one at a time because of the static 200 * buffer (no re-entrant). 201 */ 202 char * 203 bcmx_lport_to_uport_str(bcmx_lport_t lport) 204 { 205 bcmx_uport_t uport; 206 static char _uport_str[BCMX_UPORT_STR_LENGTH_DEFAULT]; 207 208 if ((uport = BCMX_LPORT_TO_UPORT(lport)) != BCMX_UPORT_INVALID_DEFAULT) { 209 bcmx_uport_to_str(uport, _uport_str, BCMX_UPORT_STR_LENGTH_DEFAULT); 210 } else { 211 sal_sprintf(_uport_str, "-1"); 212 } 213 214 return _uport_str; 215 } 216 217 218 /* 219 * Function: 220 * cmp_case_prefix 221 * Purpose: 222 * Check if buf begins with pref, case-independent. 223 * Returns: 224 * TRUE - yes, FALSE - no 225 */ 226 227 STATIC int 228 cmp_case_prefix(char *buf, char *pref) 229 { 230 int i; 231 232 for (i = 0; pref[i] != 0; i++) { 233 if (buf[i] != pref[i] && buf[i] != pref[i] - 32) { 234 return FALSE; 235 } 236 } 237 238 return TRUE; 239 } 240 241 /* 242 * Function: 243 * bcmx_lplist_parse 244 * Purpose: 245 * Parse a buffer specifying user ports 246 * Parameters: 247 * list - Pointer to list to store result 248 * buf - Pointer to buffer holding string desc. 249 * Returns: 250 * 0 on success; -1 on error 251 * Notes: 252 * list must be initialized already. 253 * 254 * This uses local translation function and 255 * assumes 1 - N ports. 256 * Syntax of port list: 257 * A TERM is defined as: [UP1[-UP2] | FE | GE | XE | ALL | *] 258 * UP1 and UP2 are user port refs. Everything else above is literal. 259 * A PORTLIST is multiple terms separated by commas. 260 * No negation. 261 * A NULL buf is treated as an empty port list 262 */ 263 264 int 265 bcmx_lplist_parse(bcmx_lplist_t *list, char *buf) 266 { 267 bcmx_lport_t sport, eport; 268 bcmx_uport_t uport; 269 270 if (list == NULL) { 271 return -1; 272 } 273 274 if (buf == NULL) { 275 return 0; 276 } 277 278 while (*buf) { 279 if (cmp_case_prefix(buf, "fe")) { 280 buf += 2; 281 BCMX_FOREACH_LPORT(sport) { 282 if (BCMX_LPORT_FLAGS(sport) & BCMX_PORT_F_FE) { 283 bcmx_lplist_add(list, sport); 284 } 285 } 286 } else if (cmp_case_prefix(buf, "ge")) { 287 buf += 2; 288 BCMX_FOREACH_LPORT(sport) { 289 if (BCMX_LPORT_FLAGS(sport) & BCMX_PORT_F_GE) { 290 bcmx_lplist_add(list, sport); 291 } 292 } 293 } else if (cmp_case_prefix(buf, "xe")) { 294 buf += 2; 295 BCMX_FOREACH_LPORT(sport) { 296 if (BCMX_LPORT_FLAGS(sport) & BCMX_PORT_F_XE) { 297 bcmx_lplist_add(list, sport); 298 } 299 } 300 } else if (cmp_case_prefix(buf, "hg")) { 301 buf += 2; 302 BCMX_FOREACH_LPORT(sport) { 303 if (BCMX_LPORT_FLAGS(sport) & BCMX_PORT_F_HG) { 304 bcmx_lplist_add(list, sport); 305 } 306 } 307 } else if (cmp_case_prefix(buf, "cpu")) { 308 buf += 3; 309 BCMX_FOREACH_LPORT(sport) { 310 if (BCMX_LPORT_FLAGS(sport) & BCMX_PORT_F_CPU) { 311 bcmx_lplist_add(list, sport); 312 } 313 } 314 } else if (cmp_case_prefix(buf, "all") || cmp_case_prefix(buf, "*")) { 315 if (*buf == '*') { 316 buf += 1; 317 } else { 318 buf += 3; 319 } 320 BCMX_FOREACH_LPORT(sport) { 321 bcmx_lplist_add(list, sport); 322 } 323 } else { /* Try to parse as user port */ 324 uport = bcmx_uport_parse(buf, &buf); 325 sport = BCMX_UPORT_TO_LPORT(uport); 326 if (sport == BCMX_NO_SUCH_LPORT) { 327 return -1; 328 } 329 if (*buf == '-') { /* uport range */ 330 buf += 1; 331 uport = bcmx_uport_parse(buf, &buf); 332 eport = BCMX_UPORT_TO_LPORT(uport); 333 if (eport == BCMX_NO_SUCH_LPORT) { 334 return -1; 335 } 336 if (bcmx_lplist_range(list, sport, eport) < 0) { 337 return -1; 338 } 339 } else { /* single uport */ 340 bcmx_lplist_add(list, sport); 341 } 342 } 343 344 switch (*buf) { 345 case ',': 346 buf += 1; 347 break; 348 case 0: /* end of string */ 349 return 0; 350 default: /* unexpected character */ 351 return -1; 352 } 353 } 354 355 return 0; 356 } 357 358 static char bcmx_attach_unit_usage[] = 359 "Usage: attach [<unit> | * ]\n" 360 " Call the BCMX attach routine. <unit> is the BCM (dispatch) unit\n" 361 " number; * means attach all connected BCM units\n"; 362 363 STATIC cmd_result_t 364 bcmx_attach_unit(int unit, args_t *args) 365 { 366 int rv; 367 int bcm_unit; 368 char *ch; 369 370 if ((ch = ARG_GET(args)) == NULL) { 371 sal_printf("Attach requires BCM unit number\n"); 372 return CMD_USAGE; 373 } 374 375 /* attach *: attach all local units */ 376 if (ch[0] == '*' && ch[1] == '\0') { 377 int max_unit; 378 bcm_attach_max(&max_unit); 379 for (bcm_unit = 0; bcm_unit <= max_unit; bcm_unit++) { 380 if (bcm_attach_check(bcm_unit) < 0) { 381 continue; 382 } 383 rv = bcmx_device_attach(bcm_unit); 384 if (rv < 0) { 385 sal_printf("Error returned by BCMX attach %d: %s\n", rv, 386 bcm_errmsg(rv)); 387 return CMD_FAIL; 388 } 389 } 390 return CMD_OK; 391 } 392 393 bcm_unit = parse_integer(ch); 394 395 rv = bcmx_device_attach(bcm_unit); 396 if (rv < 0) { 397 sal_printf("Error returned by BCMX attach %d: %s\n", rv, 398 bcm_errmsg(rv)); 399 return CMD_FAIL; 400 } 401 402 return CMD_OK; 403 } 404 405 406 static char bcmx_detach_unit_usage[] = 407 "Usage: detach <unit>\n" 408 " Call the BCMX detach routine. <unit> is the BCM (dispatch) unit\n" 409 " number.\n"; 410 411 412 STATIC cmd_result_t 413 bcmx_detach_unit(int unit, args_t *args) 414 { 415 int rv; 416 int bcm_unit; 417 char *ch; 418 419 if ((ch = ARG_GET(args)) == NULL) { 420 sal_printf("Attach requires BCM unit number\n"); 421 return CMD_USAGE; 422 } 423 bcm_unit = parse_integer(ch); 424 425 rv = bcmx_device_detach(bcm_unit); 426 if (rv < 0) { 427 sal_printf("Error returned by BCMX detach %d: %s\n", rv, 428 bcm_errmsg(rv)); 429 return CMD_FAIL; 430 } 431 432 return CMD_OK; 433 } 434 435 cmd_t bcmx_cmd_list[] = { 436 /* Command | Function | Usage String */ 437 /* ---------------+--------------------+----------------------*/ 438 /* | Short Description */ 439 440 {"?", sh_help_short, sh_help_short_usage, 441 "Display list of commands"}, 442 {"??", sh_help, sh_help_usage, 443 "@help" }, 444 #if defined(INCLUDE_ACL) 445 {"ACL", bcmx_cmd_acl, bcmx_cmd_acl_usage, 446 "AccessControlLists"}, 447 #endif /* INCLUDE_ACL */ 448 {"Attach", bcmx_attach_unit, bcmx_attach_unit_usage, 449 "Attach BCMX unit."}, 450 {"BCM", cmd_mode, shell_mode_usage, 451 "Set shell mode."}, 452 {"DETach", bcmx_detach_unit, bcmx_detach_unit_usage, 453 "Detach BCMX unit."}, 454 #ifdef BCM_FIELD_SUPPORT 455 {"FIELD", bcmx_cmd_field, bcmx_cmd_field_usage, 456 "Manage the Field Processor"}, 457 #endif /* BCM_FIELD_SUPPORT */ 458 #ifdef INCLUDE_L3 459 {"IPMC", bcmx_cmd_ipmc, bcmx_cmd_ipmc_usage, 460 "Add/Delete IP Multicast Addresses"}, 461 #endif /* INCLUDE_L3 */ 462 {"L2", bcmx_cmd_l2, bcmx_cmd_l2_usage, 463 "Display or change L2 table information"}, 464 #ifdef INCLUDE_L3 465 {"L3", bcmx_cmd_l3, bcmx_cmd_l3_usage, 466 "Display or change L3 configuration"}, 467 #endif /* INCLUDE_L3 */ 468 {"LINKscan", bcmx_cmd_link, bcmx_cmd_link_usage, 469 "Enable BCMX linkscan callback"}, 470 {"LPort", bcmx_lp_parse, bcmx_lp_parse_usage, 471 "Parse a user port or port list"}, 472 {"MCAST", bcmx_cmd_mcast, bcmx_cmd_mcast_usage, 473 "Add/Delete L2 Multicast Addresses"}, 474 {"MIRROR", bcmx_cmd_mirror, bcmx_cmd_mirror_usage, 475 "Display or set port mirroring properties"}, 476 {"PORT", bcmx_cmd_port, bcmx_cmd_port_usage, 477 "Display or set port properties"}, 478 {"RATE", bcmx_cmd_rate, bcmx_cmd_rate_usage, 479 "Rate limiting"}, 480 {"RX", bcmx_cmd_rx, bcmx_cmd_rx_usage, 481 "Start/stop simple RX."}, 482 {"STAT", bcmx_cmd_stat, bcmx_cmd_stat_usage, 483 "Display or clear snmp statistics"}, 484 {"STG", bcmx_cmd_stg, bcmx_cmd_stg_usage, 485 "Spanning Tree Group"}, 486 {"SysInfo", bcmx_cmd_sys_info, bcmx_cmd_sys_info_usage, 487 "Report system level information"}, 488 {"TRUNK", bcmx_cmd_trunk, bcmx_cmd_trunk_usage, 489 "Display or set trunking properties"}, 490 {"TX", bcmx_cmd_tx, bcmx_cmd_tx_usage, 491 "Send a packet (simple)."}, 492 {"VLAN", bcmx_cmd_vlan, bcmx_cmd_vlan_usage, 493 "Display or set VLAN membership"}, 494 }; 495 496 int bcmx_cmd_cnt = COUNTOF(bcmx_cmd_list); 497 498 #endif /* INCLUDE_BCMX */