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

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 */