openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

dispatch.c (29374B)


      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:        dispatch.c
      8  * Purpose:     Dispatch related diagnostic commands
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <appl/diag/shell.h>
     14 #include <appl/diag/system.h>
     15 
     16 #include <bcm/types.h>
     17 #include <bcm/error.h>
     18 #include <bcm/custom.h>
     19 
     20 #ifdef  BCM_ASYNC_SUPPORT
     21 #include <bcm/async.h>
     22 #include <bcm_int/async_server.h>
     23 #ifdef  INCLUDE_BCMX
     24 #include <bcmx/async.h>
     25 #endif  /* INCLUDE_BCMX */
     26 #endif  /* BCM_ASYNC_SUPPORT */
     27 
     28 #ifdef  BCM_RPC_SUPPORT
     29 #include <appl/cpudb/cpudb.h>
     30 #include <bcm_int/rpc/rpc.h>
     31 #include <bcm_int/rpc/rlink.h>
     32 #if defined(BROADCOM_DEBUG)
     33 extern void bcm_rpc_dump(void);
     34 #endif  /* BROADCOM_DEBUG */
     35 #endif  /* BCM_RPC_SUPPORT */
     36 
     37 #include <bcm_int/control.h>
     38 #ifdef  INCLUDE_LIB_STKTASK
     39 #include <appl/stktask/attach.h>
     40 #endif  /* INCLUDE_LIB_STKTASK */
     41 
     42 #include <appl/diag/diag.h>
     43 
     44 #ifdef  BCM_ASYNC_SUPPORT
     45 char cmd_async_usage[] = 
     46     "async start: start the async api task\n"
     47     "async stop: stop the async api task\n"
     48     "async test: submit an async bcm call (vlan create)\n"
     49     "async testx: submit an async bcmx call (vlan create)\n"
     50 ;
     51 
     52 void
     53 cmd_async_cb(void *cookie, int ret)
     54 {
     55     int  n;
     56 
     57     n = PTR_TO_INT(cookie);
     58 
     59     sal_printf("async callback cookie %d ret %d (%s)\n",
     60                n, ret, bcm_errmsg(ret));
     61 }
     62 
     63 static int cmd_async_count;
     64 
     65 cmd_result_t
     66 cmd_async(int unit, args_t *args)
     67 {
     68     char  *cmd, *subcmd;
     69     int   rv;
     70 
     71     cmd = ARG_CMD(args);
     72     subcmd = ARG_GET(args);
     73 
     74     if (subcmd == NULL) {
     75         subcmd = "show";
     76     }
     77     if (sal_strcasecmp(subcmd, "show") == 0) {
     78         /* hmmm.  Nothing to do here */
     79         return CMD_OK;
     80     }
     81     if (sal_strcasecmp(subcmd, "start") == 0) {
     82         rv = bcm_async_start();
     83         if (rv < 0) {
     84             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
     85             return CMD_FAIL;
     86         }
     87         return CMD_OK;
     88     }
     89     if (sal_strcasecmp(subcmd, "stop") == 0) {
     90         rv = bcm_async_stop();
     91         if (rv < 0) {
     92             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
     93             return CMD_FAIL;
     94         }
     95         return CMD_OK;
     96     }
     97     if (sal_strcasecmp(subcmd, "test") == 0) {
     98         ++ cmd_async_count;
     99         sal_printf("[bcm vlan create 0, %d]\n", cmd_async_count);
    100         bcm_vlan_create_async(0, cmd_async_count,
    101                               cmd_async_cb, INT_TO_PTR(cmd_async_count));
    102         return CMD_OK;
    103     }
    104     if (sal_strcasecmp(subcmd, "testx") == 0) {
    105 #ifdef  INCLUDE_BCMX
    106         ++ cmd_async_count;
    107         sal_printf("[bcmx vlan create %d]\n", cmd_async_count);
    108         bcmx_vlan_create_async(cmd_async_count,
    109                                cmd_async_cb, INT_TO_PTR(cmd_async_count));
    110         return CMD_OK;
    111 #else
    112         sal_printf("ERROR: bcmx support not included\n");
    113         return CMD_FAIL;
    114 #endif  /* INCLUDE_BCMX */
    115     }
    116     return CMD_USAGE;
    117 }
    118 #endif  /* BCM_ASYNC_SUPPORT */
    119 
    120 #ifdef  BCM_RPC_SUPPORT
    121 char cmd_rpc_usage[] = 
    122     "rpc start: start the BCM API RPC server task\n"
    123     "rpc stop: stop the BCM API RPC server task\n"
    124     "rpc nexthop: next rpc start will use nexthop transport\n"
    125     "rpc nonexthop: next rpc start will use cpu2cpu transport\n"
    126 #if defined(BROADCOM_DEBUG)
    127     "rpc show: display internal rpc information\n"
    128 #endif  /* BROADCOM_DEBUG */
    129 ;
    130 
    131 extern int _rpc_nexthop;
    132 extern int _rlink_nexthop;
    133 
    134 cmd_result_t
    135 cmd_rpc(int unit, args_t *args)
    136 {
    137     char  *cmd, *subcmd;
    138     int   rv;
    139 
    140     cmd = ARG_CMD(args);
    141     subcmd = ARG_GET(args);
    142 
    143     if (subcmd == NULL) {
    144         return CMD_USAGE;
    145     }
    146 
    147     if (sal_strcasecmp(subcmd, "nexthop") == 0) {
    148         _rpc_nexthop = 1;
    149         _rlink_nexthop = 1;
    150         return CMD_OK;
    151     }
    152     if (sal_strcasecmp(subcmd, "nonexthop") == 0) {
    153         _rpc_nexthop = 0;
    154         _rlink_nexthop = 0;
    155         return CMD_OK;
    156     }
    157     if (sal_strcasecmp(subcmd, "start") == 0) {
    158         rv = bcm_rpc_start();
    159         if (rv < 0) {
    160             sal_printf("ERROR: %s %s: rpc_start: %s\n",
    161                        cmd, subcmd, bcm_errmsg(rv));
    162             return CMD_FAIL;
    163         }
    164         rv = bcm_rlink_start();
    165         if (rv < 0) {
    166             sal_printf("ERROR: %s %s: rlink_start: %s\n",
    167                        cmd, subcmd, bcm_errmsg(rv));
    168             return CMD_FAIL;
    169         }
    170         return CMD_OK;
    171     }
    172     if (sal_strcasecmp(subcmd, "stop") == 0) {
    173         rv = bcm_rpc_stop();
    174         if (rv < 0) {
    175             sal_printf("ERROR: %s %s: rpc_stop: %s\n",
    176                        cmd, subcmd, bcm_errmsg(rv));
    177             return CMD_FAIL;
    178         }
    179         rv = bcm_rlink_stop();
    180         if (rv < 0) {
    181             sal_printf("ERROR: %s %s: rlink_stop: %s\n",
    182                        cmd, subcmd, bcm_errmsg(rv));
    183             return CMD_FAIL;
    184         }
    185         return CMD_OK;
    186     }
    187 
    188 #if defined(BROADCOM_DEBUG)
    189     if (sal_strcasecmp(subcmd, "show") == 0) {
    190         bcm_rpc_dump();
    191         return CMD_OK;
    192     }
    193 #endif  /* BROADCOM_DEBUG */
    194 
    195     return CMD_USAGE;
    196 }
    197 #endif  /* BCM_RPC_SUPPORT */
    198 
    199 void
    200 cmd_dispatch_link_notify(int unit, bcm_port_t port, bcm_port_info_t *info)
    201 {
    202     if (info->linkstatus == BCM_PORT_LINK_STATUS_UP) {
    203         sal_printf(" port %d.%d link up %dMb/s %s\n",
    204                    unit, port, info->speed, info->duplex ? "FD" : "HD");
    205     } else {
    206         sal_printf(" port %d.%d link down\n", unit, port);
    207     }
    208 }
    209 
    210 #ifdef  INCLUDE_LIB_STKTASK
    211 void
    212 cmd_dispatch_attach_notify(int unit, int attached,
    213                            cpudb_entry_t *cpuent, int cpuinit)
    214 {
    215     sal_printf(" unit %d %s\n",
    216                unit, attached ? "attached" : "detached");
    217 }
    218 #endif  /* INCLUDE_LIB_STKTASK */
    219 
    220 void
    221 cmd_dispatch_l2_notify(int unit, bcm_l2_addr_t *l2addr, int insert, void *cookie)
    222 {
    223     sal_printf(" unit %d l2 %s %x:%x:%x:%x:%x:%x modport %d.%d vlan %d\n",
    224                unit, insert ? "insert" : "delete",
    225                l2addr->mac[0], l2addr->mac[1], l2addr->mac[2],
    226                l2addr->mac[3], l2addr->mac[4], l2addr->mac[5],
    227                l2addr->modid, l2addr->port,
    228                l2addr->vid);
    229 }
    230 
    231 int
    232 custom_unit_vlan_vector_get(int unit, int len, uint32 *args, int *actual)
    233 {
    234     int rv = BCM_E_NONE;
    235     int i, vid, idx, maxidx, count = 0;
    236     bcm_vlan_data_t *list = NULL;
    237    
    238     rv = bcm_vlan_list(unit, &list, &count);
    239     if (rv < 0) {
    240         return rv;
    241     }
    242 
    243     sal_memset(args, 0, sizeof(args[0])*len);    
    244     args[0] = count; /* store the number of active VLANS in word0 */
    245     maxidx = 0;
    246     for (i = 0; i < count; i++) {
    247         vid = list[i].vlan_tag;
    248         idx = vid/32 + 1;
    249         if (idx < len) {
    250             args[idx] |=  1 << (vid % 32);
    251             if (idx > maxidx) {
    252                 maxidx = idx;
    253             }
    254         }
    255     }
    256     *actual = maxidx;
    257     rv = bcm_vlan_list_destroy(unit, list, count);
    258     return rv;
    259 }
    260 
    261 /*
    262  * Generic Custom handler
    263  *
    264  * We now have 3 examples using this Custom handler
    265  *
    266  * CUSTOM_HANDLER_VLAN: Gets configured vlans across the system
    267  *                     
    268  * CUSTOM_HANDLER_STAT: Get all of a port's stats in one call.
    269  * 
    270  * CUSTOM_HANDLER_STAT_SYNC: Sync stats counters and then get them
    271  *
    272  * This is the custom handler that runs on the slave devices.
    273  * See companion calling routine custom_unit_vlan_vector_get/
    274  * custom_stat_get() that runs on the master.
    275  */
    276 int
    277 custom_handler(int unit, bcm_port_t port, int setget, int type, int len,
    278                uint32 *args, int *actual, void *user_data)
    279 {
    280     int     rv, argi, s;
    281     uint64  val;
    282 
    283     if (setget != BCM_CUSTOM_GET) {
    284         return BCM_E_PARAM;
    285     }
    286 
    287     switch (type) {
    288     case CUSTOM_HANDLER_VLAN_GET: /* gets vlan vector for a unit */
    289         rv = custom_unit_vlan_vector_get(unit, len, args, actual);
    290         break;
    291         
    292     case CUSTOM_HANDLER_STAT_SYNC_GET:
    293         /* sync stats counters, then get them */
    294         rv = bcm_stat_sync(unit);
    295         if (BCM_FAILURE(rv)) {
    296             break;
    297         }
    298         /* FALLTHROUGH */
    299     case CUSTOM_HANDLER_STAT_GET:    /* just get all stats */
    300         rv = BCM_E_NONE;
    301         argi = 0;
    302         for (s = 0; s < snmpValCount && argi < len; s++) {
    303             COMPILER_64_ZERO(val);
    304             rv = bcm_stat_get(unit, port, s, &val);
    305             if (BCM_FAILURE(rv) && rv != BCM_E_PARAM) {
    306                 /* only break if the error is serious */
    307                 break;
    308             }
    309             args[argi++] = COMPILER_64_HI(val);
    310             args[argi++] = COMPILER_64_LO(val);
    311         }
    312         *actual = argi;
    313         break;
    314     default:
    315         rv = BCM_E_PARAM;
    316         break;
    317     }
    318     return rv;
    319 }
    320 
    321 int
    322 custom_stat_get(int unit, bcm_port_t port,
    323                 int dosync, uint32 num_stats, uint64 stats[])
    324 {
    325     int     rv, argi, actual, op;
    326     uint32  *args = NULL;
    327 
    328     if(num_stats == 0 || num_stats > snmpValCount){
    329         rv = BCM_E_PARAM;
    330         return rv;
    331     }
    332 
    333     args = sal_alloc(num_stats * sizeof(uint32) * 2, "custom_stat_get args Mem");
    334     if (args == NULL) {
    335         return BCM_E_MEMORY;
    336     }
    337 
    338     op = dosync ? CUSTOM_HANDLER_STAT_SYNC_GET : CUSTOM_HANDLER_STAT_GET;
    339     rv = bcm_custom_port_get(unit, port, op, num_stats*2, args, &actual);
    340     if (rv >= 0) {
    341         argi = 0;
    342         for (argi = 0; argi < num_stats; argi++) {
    343             COMPILER_64_SET(stats[argi], args[argi*2], args[argi*2+1]);
    344         }
    345     }
    346     sal_free(args);
    347     return rv;
    348 }
    349 
    350 #if 0  /* the bcmx version */
    351 int
    352 customx_stat_get(bcmx_lport_t port,
    353                  int dosync, uint64 stats[snmpValCount])
    354 {
    355     int     rv, argi, s, op, actual;
    356     uint32  args[snmpValCount*2];
    357 
    358     op = dosync ? 2 : 1;
    359     rv = bcmx_custom_port_get(port, op, snmpValCount*2, args, &actual);
    360     if (rv >= 0) {
    361         argi = 0;
    362         for (s = 0; s < snmpValCount; s++) {
    363             COMPILER_64_SET(stats[s], args[argi], args[argi+1]);
    364             argi += 2;
    365         }
    366     }
    367     return rv;
    368 }
    369 #endif
    370 
    371 char cmd_dispatch_usage[] = 
    372 #ifdef COMPILER_STRING_CONST_LIMIT
    373     "dispatch <option>\n"
    374 #else
    375     "dispatch show: list attached bcm units\n"
    376     "dispatch attach unit type unit: attach bcm unit\n"
    377     "dispatch detach unit: detach bcm unit\n"
    378     "dispatch find type unit [subtype]: find matching bcm unit\n"
    379     "dispatch vcreate unit vid: bcm_vlan_create(unit, vid)\n"
    380     "dispatch vdestroy unit vid: bcm_vlan_destroy(unit, vid)\n"
    381     "dispatch vtime count unit vid: time count calls to vcreate\n"
    382     "dispatch linkreg unit: register for link changes\n"
    383     "dispatch linkunreg unit: unregister for link changes\n"
    384     "dispatch l2reg unit: register for l2 changes\n"
    385     "dispatch l2unreg unit: unregister for l2 changes\n"
    386     "dispatch attreg: register for bcm dispatch attaches\n"
    387     "dispatch attunreg unit: unregister for bcm dispatch attaches\n"
    388     "dispatch cparse key: parse a cpudb key\n"
    389     "dispatch init_check: check if device was initialized\n"
    390 #endif
    391     ;
    392 
    393 cmd_result_t
    394 cmd_dispatch(int unit, args_t *args)
    395 {
    396     char  *cmd, *subcmd;
    397     char  *s, *dtype, *dsub;
    398     int   u, du, rv, vid;
    399 #ifdef BCM_RPC_SUPPORT
    400     cpudb_key_t key;
    401     char keybuf[CPUDB_KEY_STRING_LEN];
    402 #endif /* BCM_RPC_SUPPORT */
    403 
    404     cmd = ARG_CMD(args);
    405     subcmd = ARG_GET(args);
    406 
    407     if (subcmd == NULL) {
    408         subcmd = "show";
    409     }
    410     if (sal_strcasecmp(subcmd, "show") == 0) {
    411         for (u = 0; u < BCM_CONTROL_MAX; u++) {
    412             if (!BCM_UNIT_VALID(u)) {
    413                 continue;
    414             }
    415             sal_printf("unit %d: dispatch %s, %s unit %d chip %x.%x.%x "
    416                        "caps %#x\n",
    417                        u,
    418                        BCM_TYPE_NAME(u),
    419                        BCM_CONTROL(u)->subtype ? BCM_CONTROL(u)->subtype : "-",
    420                        BCM_CONTROL(u)->unit,
    421                        BCM_CONTROL(u)->chip_vendor,
    422                        BCM_CONTROL(u)->chip_device,
    423                        BCM_CONTROL(u)->chip_revision,
    424                        BCM_CONTROL(u)->capability);
    425         }
    426         return CMD_OK;
    427     }
    428 
    429     /* dispatch attach N type N */
    430     if (sal_strcasecmp(subcmd, "attach") == 0) {
    431         s = ARG_GET(args);
    432         if (s == NULL) {
    433             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    434             return CMD_FAIL;
    435         }
    436         u = parse_integer(s);
    437         if (u < -1 || u >= BCM_CONTROL_MAX) {
    438             sal_printf("ERROR: %s %s: unit %d out of range\n", cmd, subcmd, u);
    439             return CMD_FAIL;
    440         }
    441         dtype = ARG_GET(args);
    442         if (dtype == NULL) {
    443             sal_printf("ERROR: %s %s: dispatch type missing\n", cmd, subcmd);
    444             return CMD_FAIL;
    445         }
    446         s = ARG_GET(args);
    447         if (s == NULL) {
    448             sal_printf("ERROR: %s %s: dispatch unit missing\n", cmd, subcmd);
    449             return CMD_FAIL;
    450         }
    451         du = parse_integer(s);
    452         dsub = ARG_GET(args);
    453 #ifdef BCM_RPC_SUPPORT
    454         /* As a convenience to the user, treat client type subtype
    455            strings as cpudb keys, and put into a standard format */
    456         if (sal_strcasecmp(dtype, "client") == 0) {
    457 
    458             rv = cpudb_key_parse(dsub, &key);
    459             if (BCM_SUCCESS(rv)) {
    460                 /* put in standard format */
    461                 rv = cpudb_key_format(key, keybuf, sizeof(keybuf));
    462                 if (BCM_SUCCESS(rv)) {
    463                     dsub = keybuf;
    464                 } else {
    465                     sal_printf("ERROR: %s %s: could not format key %s: %s\n",
    466                                cmd, subcmd, dsub, bcm_errmsg(rv));
    467                     return CMD_FAIL;
    468                 }
    469             } else {
    470                 sal_printf("ERROR: %s %s: could not parse key %s: %s\n",
    471                            cmd, subcmd, dsub, bcm_errmsg(rv));
    472                 return CMD_FAIL;
    473             }
    474         }
    475 #endif
    476         
    477         rv = bcm_attach(u, dtype, dsub, du);
    478         if (rv < 0) {
    479             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    480             return CMD_FAIL;
    481         }
    482         if (u < 0) {
    483             sal_printf("[unit %d attached]\n", rv);
    484         }
    485         return CMD_OK;
    486     }
    487 
    488     /* dispatch detach N */
    489     if (sal_strcasecmp(subcmd, "detach") == 0) {
    490         s = ARG_GET(args);
    491         if (s == NULL) {
    492             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    493             return CMD_FAIL;
    494         }
    495         u = parse_integer(s);
    496         rv = bcm_detach(u);
    497         if (rv < 0) {
    498             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    499             return CMD_FAIL;
    500         }
    501         return CMD_OK;
    502     }
    503 
    504     /* dispatch init_check N*/
    505     if (sal_strcasecmp(subcmd, "init_check") == 0) {
    506         s = ARG_GET(args);
    507         if (s == NULL) {
    508             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    509             return CMD_FAIL;
    510         }
    511         u = parse_integer(s);
    512         rv = bcm_init_check(u);
    513         return CMD_OK;
    514     }
    515 
    516     /* dispatch find type remunit subtype */
    517     if (sal_strcasecmp(subcmd, "find") == 0) {
    518         dtype = ARG_GET(args);
    519         if (dtype == NULL) {
    520             sal_printf("ERROR: %s %s: dispatch type missing\n", cmd, subcmd);
    521             return CMD_FAIL;
    522         }
    523         s = ARG_GET(args);
    524         if (s == NULL) {
    525             sal_printf("ERROR: %s %s: dispatch unit missing\n", cmd, subcmd);
    526             return CMD_FAIL;
    527         }
    528         u = parse_integer(s);
    529         dsub = ARG_GET(args);
    530 
    531         rv = bcm_find(dtype, dsub, u);
    532         if (rv < 0) {
    533             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    534             return CMD_FAIL;
    535         }
    536         sal_printf("[unit %d found]\n", rv);
    537         return CMD_OK;
    538     }
    539 
    540     /* dispatch vcreate N N */
    541     if (sal_strcasecmp(subcmd, "vcreate") == 0) {
    542         s = ARG_GET(args);
    543         if (s == NULL) {
    544             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    545             return CMD_FAIL;
    546         }
    547         u = parse_integer(s);
    548         s = ARG_GET(args);
    549         if (s == NULL) {
    550             sal_printf("ERROR: %s %s: vlanid missing\n", cmd, subcmd);
    551             return CMD_FAIL;
    552         }
    553         vid = parse_integer(s);
    554         rv = bcm_vlan_create(u, vid);
    555         if (rv < 0) {
    556             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    557             return CMD_FAIL;
    558         }
    559         return CMD_OK;
    560     }
    561 
    562     /* dispatch vdestroy N N */
    563     if (sal_strcasecmp(subcmd, "vdestroy") == 0) {
    564         s = ARG_GET(args);
    565         if (s == NULL) {
    566             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    567             return CMD_FAIL;
    568         }
    569         u = parse_integer(s);
    570         s = ARG_GET(args);
    571         if (s == NULL) {
    572             sal_printf("ERROR: %s %s: vlanid missing\n", cmd, subcmd);
    573             return CMD_FAIL;
    574         }
    575         vid = parse_integer(s);
    576         rv = bcm_vlan_destroy(u, vid);
    577         if (rv < 0) {
    578             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    579             return CMD_FAIL;
    580         }
    581         return CMD_OK;
    582     }
    583 
    584     /* dispatch vtime N N N */
    585     if (sal_strcasecmp(subcmd, "vtime") == 0) {
    586         int i, count;
    587         uint32 btime, etime;
    588         
    589         s = ARG_GET(args);
    590         if (s == NULL) {
    591             sal_printf("ERROR: %s %s: count missing\n", cmd, subcmd);
    592             return CMD_FAIL;
    593         }
    594         count = parse_integer(s);
    595         s = ARG_GET(args);
    596         if (s == NULL) {
    597             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    598             return CMD_FAIL;
    599         }
    600         u = parse_integer(s);
    601         s = ARG_GET(args);
    602         if (s == NULL) {
    603             sal_printf("ERROR: %s %s: vlanid missing\n", cmd, subcmd);
    604             return CMD_FAIL;
    605         }
    606         vid = parse_integer(s);
    607         btime = sal_time_usecs();
    608         for (i = 0; i < count; i++) {
    609             (void)bcm_vlan_create(u, vid);
    610         }
    611         etime = sal_time_usecs();
    612         sal_printf("%d api calls in %u usec (%d usec/call)\n",
    613                    count, etime-btime, (etime-btime)/count);
    614         return CMD_OK;
    615     }
    616 
    617     if (sal_strcasecmp(subcmd, "linkreg") == 0) {
    618         s = ARG_GET(args);
    619         if (s == NULL) {
    620             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    621             return CMD_FAIL;
    622         }
    623         u = parse_integer(s);
    624         rv = bcm_linkscan_register(u, cmd_dispatch_link_notify);
    625         if (rv < 0) {
    626             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    627             return CMD_FAIL;
    628         }
    629         return CMD_OK;
    630     }
    631 
    632     if (sal_strcasecmp(subcmd, "linkunreg") == 0) {
    633         s = ARG_GET(args);
    634         if (s == NULL) {
    635             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    636             return CMD_FAIL;
    637         }
    638         u = parse_integer(s);
    639         rv = bcm_linkscan_unregister(u, cmd_dispatch_link_notify);
    640         if (rv < 0) {
    641             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    642             return CMD_FAIL;
    643         }
    644         return CMD_OK;
    645     }
    646 
    647     if (sal_strcasecmp(subcmd, "l2reg") == 0) {
    648         s = ARG_GET(args);
    649         if (s == NULL) {
    650             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    651             return CMD_FAIL;
    652         }
    653         u = parse_integer(s);
    654         rv = bcm_l2_addr_register(u, cmd_dispatch_l2_notify, NULL);
    655         if (rv < 0) {
    656             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    657             return CMD_FAIL;
    658         }
    659         return CMD_OK;
    660     }
    661 
    662     if (sal_strcasecmp(subcmd, "l2unreg") == 0) {
    663         s = ARG_GET(args);
    664         if (s == NULL) {
    665             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    666             return CMD_FAIL;
    667         }
    668         u = parse_integer(s);
    669         rv = bcm_l2_addr_unregister(u, cmd_dispatch_l2_notify, NULL);
    670         if (rv < 0) {
    671             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    672             return CMD_FAIL;
    673         }
    674         return CMD_OK;
    675     }
    676 
    677 #ifdef  INCLUDE_LIB_STKTASK
    678     if (sal_strcasecmp(subcmd, "attreg") == 0) {
    679         rv = bcm_stack_attach_register(cmd_dispatch_attach_notify);
    680         if (rv < 0) {
    681             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    682             return CMD_FAIL;
    683         }
    684         return CMD_OK;
    685     }
    686 
    687     if (sal_strcasecmp(subcmd, "attunreg") == 0) {
    688         rv = bcm_stack_attach_unregister(cmd_dispatch_attach_notify);
    689         if (rv < 0) {
    690             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    691             return CMD_FAIL;
    692         }
    693         return CMD_OK;
    694     }
    695 #endif  /* INCLUDE_LIB_STKTASK */
    696 
    697 #ifdef  INCLUDE_LIB_CPUDB
    698     if (sal_strcasecmp(subcmd, "cparse") == 0) {
    699         char         buf[CPUDB_KEY_STRING_LEN];
    700         cpudb_key_t  key;
    701 
    702         s = ARG_GET(args);
    703         if (s == NULL) {
    704             sal_printf("ERROR: %s %s: key missing\n", cmd, subcmd);
    705             return CMD_FAIL;
    706         }
    707         rv = cpudb_key_parse(s, &key);
    708         if (rv < 0) {
    709             sal_printf("ERROR: %s %s (cpudb_key_parse): %s\n",
    710                        cmd, subcmd, bcm_errmsg(rv));
    711             return CMD_FAIL;
    712         }
    713         rv = cpudb_key_format(key, buf, CPUDB_KEY_STRING_LEN);
    714         if (rv < 0) {
    715             sal_printf("ERROR: %s %s (cpudb_key_format): %s\n",
    716                        cmd, subcmd, bcm_errmsg(rv));
    717             return CMD_FAIL;
    718         }
    719         sal_printf("key %x:%x:%x:%x:%x:%x --> %s (hash %d)\n",
    720                    key.key[0], key.key[1], key.key[2],
    721                    key.key[3], key.key[4], key.key[5],
    722                    buf, CPUDB_KEY_HASH(key));
    723         return CMD_OK;
    724     }
    725 #endif  /* INCLUDE_LIB_CPUDB */
    726 
    727     /* doesn't really belong here... */
    728     /* maxframe unit port [size] */
    729     if (sal_strcasecmp(subcmd, "maxframe") == 0) {
    730         bcm_port_t p;
    731         int size;
    732         s = ARG_GET(args);
    733         if (s == NULL) {
    734             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    735             return CMD_FAIL;
    736         }
    737         u = parse_integer(s);
    738         s = ARG_GET(args);
    739         if (s == NULL) {
    740             sal_printf("ERROR: %s %s: port missing\n", cmd, subcmd);
    741             return CMD_FAIL;
    742         }
    743         p = parse_integer(s);
    744         s = ARG_GET(args);
    745         if (s == NULL) {
    746             rv = bcm_port_frame_max_get(u, p, &size);
    747             if (rv < 0) {
    748                 sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    749                 return CMD_FAIL;
    750             }
    751             sal_printf("%d\n", size);
    752         } else {
    753             size = parse_integer(s);
    754             rv = bcm_port_frame_max_set(u, p, size);
    755             if (rv < 0) {
    756                 sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    757                 return CMD_FAIL;
    758             }
    759         }
    760         return CMD_OK;
    761     }
    762 
    763     /* doesn't really belong here... */
    764     /* jam unit port [enable] */
    765     if (sal_strcasecmp(subcmd, "jam") == 0) {
    766         bcm_port_t p;
    767         int enable;
    768         s = ARG_GET(args);
    769         if (s == NULL) {
    770             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    771             return CMD_FAIL;
    772         }
    773         u = parse_integer(s);
    774         s = ARG_GET(args);
    775         if (s == NULL) {
    776             sal_printf("ERROR: %s %s: port missing\n", cmd, subcmd);
    777             return CMD_FAIL;
    778         }
    779         p = parse_integer(s);
    780         s = ARG_GET(args);
    781         if (s == NULL) {
    782             rv = bcm_port_jam_get(u, p, &enable);
    783             if (rv < 0) {
    784                 sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    785                 return CMD_FAIL;
    786             }
    787             sal_printf("jamming %s\n", enable ? "enabled" : "disabled");
    788         } else {
    789             enable = parse_integer(s);
    790             rv = bcm_port_jam_set(u, p, enable);
    791             if (rv < 0) {
    792                 sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    793                 return CMD_FAIL;
    794             }
    795         }
    796         return CMD_OK;
    797     }
    798 
    799     /* dispatch custom_reg <unit> */
    800     if (sal_strcasecmp(subcmd, "custom_reg") == 0) {
    801         s = ARG_GET(args);
    802         if (s == NULL) {
    803             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    804             return CMD_FAIL;
    805         }
    806         u = parse_integer(s);
    807         rv = bcm_custom_register(u, custom_handler, NULL);
    808         if (rv < 0) {
    809             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    810             return CMD_FAIL;
    811         }
    812         return CMD_OK;
    813     }
    814 
    815     /* dispatch custom_stat <unit> <port> */
    816     if (sal_strcasecmp(subcmd, "custom_stat") == 0) {
    817         int     p, si;
    818         const static char *sname[] = BCM_STAT_NAME_INITIALIZER;
    819         uint64  stats[snmpValCount];
    820 
    821         s = ARG_GET(args);
    822         if (s == NULL) {
    823             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    824             return CMD_FAIL;
    825         }
    826         u = parse_integer(s);
    827 
    828         s = ARG_GET(args);
    829         if (s == NULL) {
    830             sal_printf("ERROR: %s %s: port missing\n", cmd, subcmd);
    831             return CMD_FAIL;
    832         }
    833         p = parse_integer(s);
    834 
    835         rv = custom_stat_get(u, p, 0, snmpValCount, stats);
    836         if (rv < 0) {
    837             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    838             return CMD_FAIL;
    839         }
    840         for (si = 0; si < snmpValCount; si++) {
    841             if (COMPILER_64_IS_ZERO(stats[si])) {
    842                 continue;
    843             }
    844             if (COMPILER_64_HI(stats[si]) == 0) {
    845                 cli_out("\t%18u\t%s (stat %d)\n",
    846                         COMPILER_64_LO(stats[si]), sname[si], si);
    847             } else {
    848                 cli_out("\t0x%08x%08x\t%s (stat %d)\n",
    849                         COMPILER_64_HI(stats[si]),
    850                         COMPILER_64_LO(stats[si]),
    851                         sname[si], si);
    852             }
    853 
    854         }
    855         return CMD_OK;
    856     }
    857 
    858     /* dispatch custom_stattime <count> <unit> <port> */
    859     if (sal_strcasecmp(subcmd, "custom_stattime") == 0) {
    860         int i, count, p;
    861         uint32 btime, etime;
    862         uint64 stats[snmpValCount];
    863 
    864         s = ARG_GET(args);
    865         if (s == NULL) {
    866             sal_printf("ERROR: %s %s: count missing\n", cmd, subcmd);
    867             return CMD_FAIL;
    868         }
    869         count = parse_integer(s);
    870         s = ARG_GET(args);
    871         if (s == NULL) {
    872             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    873             return CMD_FAIL;
    874         }
    875         u = parse_integer(s);
    876         s = ARG_GET(args);
    877         if (s == NULL) {
    878             sal_printf("ERROR: %s %s: port missing\n", cmd, subcmd);
    879             return CMD_FAIL;
    880         }
    881         p = parse_integer(s);
    882         btime = sal_time_usecs();
    883         for (i = 0; i < count; i++) {
    884             (void)custom_stat_get(u, p, 0, snmpValCount, stats);
    885         }
    886         etime = sal_time_usecs();
    887         sal_printf("%d api calls in %u usec (%d usec/call)\n",
    888                    count, etime-btime, (etime-btime)/count);
    889         return CMD_OK;
    890     }
    891 
    892     /* dispatch stattime <count> <unit> <port> */
    893     if (sal_strcasecmp(subcmd, "stattime") == 0) {
    894         int i, count, p, si;
    895         uint32 btime, etime;
    896         uint64 stats[snmpValCount];
    897 
    898         s = ARG_GET(args);
    899         if (s == NULL) {
    900             sal_printf("ERROR: %s %s: count missing\n", cmd, subcmd);
    901             return CMD_FAIL;
    902         }
    903         count = parse_integer(s);
    904         s = ARG_GET(args);
    905         if (s == NULL) {
    906             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    907             return CMD_FAIL;
    908         }
    909         u = parse_integer(s);
    910         s = ARG_GET(args);
    911         if (s == NULL) {
    912             sal_printf("ERROR: %s %s: port missing\n", cmd, subcmd);
    913             return CMD_FAIL;
    914         }
    915         p = parse_integer(s);
    916         btime = sal_time_usecs();
    917         for (i = 0; i < count; i++) {
    918             for (si = 0; si < snmpValCount; si++) {
    919                 (void)bcm_stat_get(u, p, si, &stats[si]);
    920             }
    921         }
    922         etime = sal_time_usecs();
    923         sal_printf("%d api calls in %u usec (%d usec/call)\n",
    924                    count, etime-btime, (etime-btime)/count);
    925         return CMD_OK;
    926     }
    927 
    928     /* dispatch pause_addr <unit> <port> [<mac>] */
    929     if (sal_strcasecmp(subcmd, "pause_addr") == 0) {
    930         int p;
    931         bcm_mac_t mac;
    932         char macstr[SAL_MACADDR_STR_LEN];
    933 
    934         s = ARG_GET(args);
    935         if (s == NULL) {
    936             sal_printf("ERROR: %s %s: unit missing\n", cmd, subcmd);
    937             return CMD_FAIL;
    938         }
    939         u = parse_integer(s);
    940         s = ARG_GET(args);
    941         if (s == NULL) {
    942             sal_printf("ERROR: %s %s: port missing\n", cmd, subcmd);
    943             return CMD_FAIL;
    944         }
    945         p = parse_integer(s);
    946 
    947         s = ARG_GET(args);
    948         if (s == NULL) {
    949             rv = bcm_port_pause_addr_get(u, p, mac);
    950             if (rv >= 0) {
    951                 format_macaddr(macstr, mac);
    952                 sal_printf("port %d.%d: pause mac addr %s\n", u, p, macstr);
    953             }
    954         } else {
    955             if (parse_macaddr(s, mac) < 0) {
    956                 sal_printf("ERROR: %s %s: illegal mac-addr\n", cmd, subcmd);
    957                 return CMD_FAIL;
    958             }
    959             rv = bcm_port_pause_addr_set(u, p, mac);
    960         }
    961         if (rv < 0) {
    962             sal_printf("ERROR: %s %s: %s\n", cmd, subcmd, bcm_errmsg(rv));
    963             return CMD_FAIL;
    964         }
    965         return CMD_OK;
    966     }
    967 
    968     return CMD_USAGE;
    969 }