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

util.c (150606B)


      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  * Diagnostic shell support utilities.
      8  * These routines aren't necessary for the driver itself.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <sal/core/libc.h>
     14 #include <sal/appl/sal.h>
     15 #include <sal/types.h>
     16 #include <shared/bsl.h>
     17 #include <soc/mem.h>
     18 
     19 #include <bcm/pkt.h>
     20 #include <bcm/field.h>
     21 #include <bcm/stack.h>
     22 #include <bcm/error.h>
     23 #include <bcm/l3.h>
     24 #include <bcm/tunnel.h>
     25 #include <bcm/rx.h>
     26 #if defined(BCM_ESW_SUPPORT)
     27 #include <bcm_int/esw/l2.h>
     28 #endif
     29 
     30 #include <appl/diag/system.h>
     31 #include <appl/diag/diag.h>
     32 #include <appl/diag/dport.h>
     33 #include <sal/appl/io.h>
     34 
     35 #ifdef BCM_CMICM_SUPPORT
     36 #include <soc/cmicm.h>
     37 #endif
     38 
     39 #if defined(BCM_ESW_SUPPORT)
     40 #include <bcm_int/esw/port.h>
     41 #endif
     42 
     43 #if defined(BCM_PETRA_SUPPORT)
     44 #include <soc/dpp/drv.h>
     45 #endif
     46 #if defined(BCM_DFE_SUPPORT)
     47 #include <soc/dfe/cmn/dfe_drv.h>
     48 #endif
     49 
     50 #if defined(BCM_ESW_SUPPORT)
     51 #include <bcm_int/esw/field.h>
     52 #endif
     53 
     54 #include <bcm_int/api_xlate_port.h>
     55 
     56 typedef struct _bcm_util_gport_dest_s {
     57     bcm_port_t      port;
     58     bcm_module_t    modid;
     59     bcm_trunk_t     tgid;
     60     int             mpls_id;
     61     int             mim_id;
     62     int             wlan_id;
     63     int             subport_id;
     64     int             subport_group_id;
     65     int             vlan_port_id;
     66     int             vxlan_id;
     67     int             trill_id;
     68     int             niv_id;
     69     int             l2gre_id;
     70     int             extender_id;
     71     int             scheduker_id;
     72     uint32          gport_type;
     73 } _bcm_util_gport_dest_t;
     74 
     75 /*
     76  * strcaseindex: case insensitive substring search
     77  *   Find substring 'sub' within string 's'.
     78  *   Return pointer to substring within 's', NULL if not found.
     79  */
     80 
     81 const char *
     82 strcaseindex(const char *s, const char *sub)
     83 {
     84     int len;
     85 
     86     for (len = sal_strlen(sub); *s; s++) {
     87         if (sal_strncasecmp(s, sub, len) == 0) {
     88             return s;
     89         }
     90     }
     91 
     92     return 0;
     93 }
     94 
     95 /*
     96  * strrepl: string replace
     97  *   Delete 'len' characters from position 'start' in string 's',
     98  *   and insert 'repstr' at the deletion point.
     99  */
    100 
    101 char *
    102 strrepl(char *s, int start, int len, const char *repstr)
    103 {
    104     memmove(s + start + sal_strlen(repstr),
    105             s + start + len,
    106             sal_strlen(s + start + len) + 1);
    107     memmove(s + start, repstr, sal_strlen(repstr));
    108 
    109     return s;
    110 }
    111 
    112 /*
    113  * Convert hex digit to hex character
    114  */
    115 
    116 int
    117 i2xdigit(int digit)
    118 {
    119     digit &= 0xf;
    120 
    121     return (digit > 9) ? digit - 10 + 'a' : digit + '0';
    122 }
    123 
    124 /*
    125  * Convert hex character to digit
    126  */
    127 
    128 int
    129 xdigit2i(int digit)
    130 {
    131     if (digit >= '0' && digit <= '9') return (digit - '0'     );
    132     if (digit >= 'a' && digit <= 'f') return (digit - 'a' + 10);
    133     if (digit >= 'A' && digit <= 'F') return (digit - 'A' + 10);
    134     return 0;
    135 }
    136 
    137 /*
    138  * tabify_line
    139  *
    140  *      Tabifies a string assuming a given tab_width.
    141  *
    142  *      Output buffer should have at least as many characters as input
    143  *      string plus the NUL terminator.
    144  */
    145 
    146 void
    147 tabify_line(char *out, char *in, int tab_width)
    148 {
    149     int         col = 0;
    150 
    151     if (tab_width < 2) {
    152         tab_width = 1;
    153     }
    154 
    155     while (*in) {
    156         int     ts;     /* Spaces to next tab stop */
    157         int     ns;     /* Spaces that can be eaten from input */
    158 
    159         ts = col + tab_width - (col % tab_width) - col;
    160 
    161         for (ns = 0; ns < ts && in[ns] == ' '; ns++)
    162             ;
    163 
    164         if (ts > 1 && ns >= ts) {
    165             *out++ = '\t';
    166             col += ts;
    167             in += ts;
    168         } else {
    169             *out++ = *in++;
    170             col++;
    171         }
    172     }
    173 
    174     *out = 0;
    175 }
    176 
    177 /*
    178  * parse_rand
    179  *
    180  *      Returns non-zero if the string is of the form
    181  *              rand(x)
    182  *      or
    183  *              rand(x,y)
    184  *      and zero otherwise.
    185  *
    186  *      In the case of rand(x), val receives a random value between 0
    187  *      and x-1, inclusive.
    188  *
    189  *      In the case of rand(x,y), val receives a random value between x
    190  *      and y, inclusive.
    191  */
    192 
    193 int
    194 parse_rand(char *str, uint32 *val)
    195 {
    196     uint32              min, max, rnd32;
    197 
    198     if (sal_strncasecmp(str, "rand(", 5) != 0) {
    199         return 0;
    200     }
    201 
    202     min = sal_ctoi(str + 5, &str);
    203 
    204     if (*str == ',') {
    205         max = sal_ctoi(str + 1, &str);
    206     } else {
    207         max = min - 1;
    208         min = 0;
    209     }
    210 
    211     if (*str != ')') {
    212         return 0;
    213     }
    214 
    215     rnd32 = (sal_rand() << 17 ^
    216              sal_rand() << 13 ^
    217              sal_rand() << 5 ^
    218              sal_rand() >> 3);
    219 
    220     if (max - min + 1 == 0) {
    221         *val = 0;
    222     } else {
    223         *val = min + rnd32 % (max - min + 1);
    224     }
    225 
    226     return 1;
    227 }
    228 
    229 /*
    230  * Return true if a constant is a well-formed integer of the type
    231  * supported by parse_integer.
    232  */
    233 
    234 int
    235 isint(char *s)
    236 {
    237     int base;
    238     uint32 dummy;
    239 
    240     if (s == NULL) {
    241         return 0;
    242     }
    243 
    244     if (parse_rand(s, &dummy)) {
    245         return 1;
    246     }
    247 
    248     if (*s == '-') {
    249         s++;
    250     }
    251 
    252     if (*s == '0') {
    253         if (s[1] == 'b' || s[1] == 'B') {
    254             base = 2;
    255             s += 2;
    256         } else if (s[1] == 'x' || s[1] == 'X') {
    257             base = 16;
    258             s += 2;
    259         } else
    260             base = 8;
    261     } else {
    262         base = 10;
    263     }
    264 
    265     do {
    266         if (!isxdigit((unsigned) *s) || xdigit2i(*s) >= base) {
    267             return(0);
    268         }
    269     } while (*++s);
    270 
    271     return(1);
    272 }
    273 
    274 /*
    275  * Read an integer: return unsigned representation.
    276  * Number format explained below.
    277  *
    278  * Expects:
    279  * [-]0x[0-9|A-F|a-f]+   -hexadecimal if the string begins with "0x"
    280  * [-][0-9]+             -decimal integer
    281  * [-]0[0-7]+            -octal integer
    282  * [-]0b[0-1]+           -binary if the string begins with "0b"
    283  */
    284 
    285 uint32
    286 parse_integer(char *str)
    287 {
    288     uint32      rnd;
    289 
    290     if (parse_rand(str, &rnd)) {
    291         return rnd;
    292     }
    293 
    294     if (!isint(str)) {
    295         cli_out("WARNING: truncated malformed integer \"%s\"\n", str);
    296     }
    297 
    298     return _shr_ctoi(str);
    299 }
    300 
    301 /*
    302  * Read string of integer
    303  * argument s is a string with integers smaller than 32, sepereted by some char that is not digit
    304  * the return pbmp is a pbmp of this numbers.
    305  * if one of the numbers on the string is in hex form "0x" its taken as bit map.
    306  * if "-1" set one to all bit map.
    307  * example from: "0xf,7" - it will fill the bit pbmp : 1 1 1 1 0 0 0 1
    308  */
    309 int
    310 parse_small_integers(int unit, char *s, soc_pbmp_t *pbmp)
    311 {
    312     int integer, i;
    313 
    314     BCM_PBMP_CLEAR(*pbmp);
    315 
    316     while (*s != 0) {
    317 
    318         if ((*s <= '9') && (*s >= '0')) {
    319             integer = _shr_ctoi(s);
    320 
    321             /* if the number is in hex form use it as bit map */
    322             if ((*s=='0' && ((*(s+1)=='x') || (*(s+1) == 'X'))) ) {
    323                 for(i=0; i<32; ++i) {
    324 
    325                     if (integer & (1 << i)) {
    326                          BCM_PBMP_PORT_ADD(*pbmp, i);
    327                     }
    328                 }
    329                 s = s+2;
    330 
    331             } /* alse -  block index */
    332              else if ((integer >= 0) && (integer < 32)) {
    333                     BCM_PBMP_PORT_ADD(*pbmp, integer);
    334             }
    335 
    336             while ((*s <= '9') && (*s >= '0')) {
    337                 ++s;
    338             }
    339 
    340         }
    341 
    342         if (*s == '-' && *(s+1) == '1') {
    343             for(i=0; i<32; ++i) {
    344                 BCM_PBMP_PORT_ADD(*pbmp, i);
    345             }
    346 
    347             break;
    348 
    349         }
    350 
    351         if (*s != 0) {
    352             ++s;
    353         }
    354     }
    355 
    356     return 0;
    357 }
    358 
    359 sal_vaddr_t
    360 parse_address(char *str)
    361 {
    362     if (!isint(str)) {
    363         cli_out("WARNING: truncated malformed address \"%s\"\n", str);
    364     }
    365 
    366     return _shr_ctoa(str);
    367 }
    368 
    369 /*
    370  * ---------------------------------------------------------------------------
    371  * Long Integer Support
    372  * ---------------------------------------------------------------------------
    373  *
    374  * Long integers consist of a variable length array of uint32.
    375  *
    376  * Within the array, the least significant word comes first.  This is
    377  * true on all platforms.  However, each word itself is stored in the
    378  * platform native byte order.
    379  */
    380 
    381 /*
    382  * Read a long integer: can read a long hex integer, or a regular
    383  * integer in any base supported by parse_integer.
    384  *
    385  * val[0] receives the least significant word (little-endian).
    386  * nbuf is the number size (count of uint32's).
    387  */
    388 
    389 void
    390 parse_long_integer(uint32 *val, int nval, char *str)
    391 {
    392     char eight[11], *s, *t;
    393     int i, neg;
    394 
    395     if (*str == '-') {
    396         neg = 1;
    397         str++;
    398     } else {
    399         neg = 0;
    400     }
    401 
    402     sal_memset(val, 0, nval * sizeof (*val));
    403 
    404     if (parse_rand(str, &val[0])) {
    405         goto done;
    406     }
    407 
    408     if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
    409         val[0] = parse_integer(str);
    410         goto done;
    411     }
    412 
    413     /* Skip to the last hex digit in the string */
    414 
    415     for (s = str + 1; isxdigit((unsigned) s[1]); s++) {
    416         ;
    417     }
    418 
    419     /* Parse backward in groups of 8 digits */
    420 
    421     i = 0;
    422 
    423     do {
    424         /* Copy 8 digits backward to form a string "0xdddddddd\0" */
    425         t = eight + 11;
    426         *--t = 0;
    427         while (t > eight + 2 && (*s != 'x' && *s != 'X')) {
    428             *--t = *s--;
    429         }
    430         *--t = 'x';
    431         *--t = '0';
    432 
    433         val[i++] = parse_integer(t);
    434     } while ((*s != 'x' && *s != 'X') && i < nval);
    435 
    436  done:
    437     if (neg) {
    438         uint32 cy = 1;
    439         for (i = 0; i < nval; i++) {
    440             if ((val[i] = (~val[i]) + cy) != 0) {
    441                 cy = 0;
    442             }
    443         }
    444     }
    445 }
    446 
    447 /*
    448  * Format a long integer.  If the value is less than 10, generates
    449  * decimal, otherwise generates hex.
    450  *
    451  * val[0] is the least significant word.
    452  * nval is the number of uint32's in the value.
    453  */
    454 
    455 void
    456 format_long_integer(char *buf, uint32 *val, int nval)
    457 {
    458     int i;
    459 
    460     for (i = nval - 1; i > 0; i--) {    /* Skip leading zeroes */
    461         if (val[i]) {
    462             break;
    463         }
    464     }
    465 
    466     if (i == 0 && val[i] < 10) {        /* Only a single word < 10? */
    467         sal_sprintf(buf, "%d", val[i]);
    468     } else {
    469         sal_sprintf(buf, "0x%x", val[i]);   /* Print first word */
    470     }
    471 
    472     while (--i >= 0) {                  /* Print rest of words, if any */
    473         sal_sprintf(buf + sal_strlen(buf), "%08x", val[i]);
    474     }
    475 }
    476 
    477 void
    478 format_spec_long_integer(char *buf, uint32 *val, int nval)
    479 {
    480     int i = nval - 1;
    481 
    482     sal_sprintf(buf, "0x%08X", val[i]);
    483 
    484     while (--i >= 0) {                  /* Print rest of words, if any */
    485         sal_sprintf(buf + sal_strlen(buf), " ");
    486         sal_sprintf(buf + sal_strlen(buf), "0x%08X", val[i]);
    487     }
    488 }
    489 
    490 /*
    491  * Add long integers.
    492  */
    493 
    494 void
    495 add_long_integer(uint32 *dst, uint32 *src, int nval)
    496 {
    497     int         i;
    498     uint32      tmp, new_cy, cy = 0;
    499 
    500     for (i = 0; i < nval; i++, cy = new_cy) {
    501         tmp = dst[i];           /* Add digits, detect overflow */
    502         dst[i] += src[i];
    503         new_cy = (dst[i] < tmp);
    504         tmp = dst[i];           /* Add carry, detect overflow */
    505         dst[i] += cy;
    506         new_cy += (dst[i] < tmp);
    507     }
    508 }
    509 
    510 /*
    511  * Subtract long integers.
    512  */
    513 
    514 void
    515 sub_long_integer(uint32 *dst, uint32 *src, int nval)
    516 {
    517     int         i;
    518     uint32      tmp, new_br, br = 0;
    519 
    520     for (i = 0; i < nval; i++, br = new_br) {
    521         tmp = dst[i];           /* Sub digits, detect underflow */
    522         dst[i] -= src[i];
    523         new_br = (dst[i] > tmp);
    524         tmp = dst[i];           /* Sub carry, detect underflow */
    525         dst[i] -= br;
    526         new_br += (dst[i] > tmp);
    527     }
    528 }
    529 
    530 /*
    531  * Negate long integer.
    532  */
    533 
    534 void
    535 neg_long_integer(uint32 *dst, int nval)
    536 {
    537     int         i;
    538     uint32      tmp, new_br, br = 0;
    539 
    540     for (i = 0; i < nval; i++, br = new_br) {
    541         dst[i] = -dst[i];
    542         new_br = (dst[i] > 0);
    543         tmp = dst[i];           /* Sub carry, detect overflow */
    544         dst[i] -= br;
    545         new_br += (dst[i] > tmp);
    546     }
    547 }
    548 
    549 /*
    550  * Parse uint64
    551  * Endian handling is taken into account.
    552  */
    553 
    554 uint64
    555 parse_uint64(char *str)
    556 {
    557     uint32 tmpval[2];
    558     uint64 rval;
    559 
    560     parse_long_integer(tmpval, 2, str);
    561     COMPILER_64_SET(rval, tmpval[1], tmpval[0]);
    562 
    563     return rval;
    564 }
    565 
    566 /*
    567  * Format uint64
    568  * Endian handling is taken into account.
    569  */
    570 
    571 void
    572 format_uint64(char *buf, uint64 n)
    573 {
    574     uint32              val[2];
    575 
    576     val[0] = COMPILER_64_LO(n);
    577     val[1] = COMPILER_64_HI(n);
    578 
    579     format_long_integer(buf, val, 2);
    580 }
    581 
    582 /*
    583  * Format uint64 as unsigned decimal.
    584  *
    585  * Comma should be one of:
    586  *      ','     to use commas every third digit
    587  *      '.'     to use periods every third digit
    588  *      '\0'    no commas or periods
    589  *
    590  * The buffer must have room for up to 21 bytes (if no commas or
    591  * periods) or 27 bytes (commas or periods).
    592  */
    593 
    594 void
    595 format_uint64_decimal(char *buf, uint64 n, int comma)
    596 {
    597     int                 pw;
    598     char                *obuf;
    599 
    600     static CONST struct pow10_s {
    601         uint32          hi, lo;
    602     } pow10[] = {
    603         { 0U,           1U              },
    604         { 0U,           10U             },
    605         { 0U,           100U            },
    606         { 0U,           1000U           },
    607         { 0U,           10000U          },
    608         { 0U,           100000U         },
    609         { 0U,           1000000U        },
    610         { 0U,           10000000U       },
    611         { 0U,           100000000U      },
    612         { 0U,           1000000000U     },
    613         { 2U,           1410065408U     },
    614         { 23U,          1215752192U     },
    615         { 232U,         3567587328U     },
    616         { 2328U,        1316134912U     },
    617         { 23283U,       276447232U      },
    618         { 232830U,      2764472320U     },
    619         { 2328306U,     1874919424U     },
    620         { 23283064U,    1569325056U     },
    621         { 232830643U,   2808348672U     },
    622         { 2328306436U,  2313682944U     },
    623     };
    624 
    625     obuf = buf;
    626 
    627     for (pw = 19; pw >= 0; pw--) {
    628         uint64          p10;
    629         int             digit;
    630 
    631         COMPILER_64_SET(p10, pow10[pw].hi, pow10[pw].lo);
    632 
    633         for (digit = '0'; COMPILER_64_GE(n, p10); digit++) {
    634             COMPILER_64_SUB_64(n, p10);
    635         }
    636 
    637         if (buf > obuf || digit != '0') {
    638             *buf++ = digit;
    639             if (comma != 0 && (pw % 3) == 0 && pw > 0) {
    640                 *buf++ = comma;
    641             }
    642         }
    643     }
    644 
    645     if (buf == obuf) {
    646         *buf++ = '0';
    647     }
    648 
    649     *buf = 0;
    650 }
    651 
    652 /*
    653  * Parse a mac address that comes from a pure hex number.
    654  * The leading 0x is assumed to have been stripped off.
    655  * String can be up to 12 characters long.
    656  *
    657  * Process string from end.
    658  */
    659 
    660 int
    661 parse_macaddr_hex(char *str, sal_mac_addr_t macaddr)
    662 {
    663     char *s;
    664     int i;
    665 
    666     sal_memset(macaddr, 0, 6);
    667     if ((sal_strlen(str) > 12) || (sal_strlen(str) == 0)) {
    668         return -1;
    669     }
    670     s = str + sal_strlen(str) - 1;
    671     for (i = 0; i < 6; i++) {
    672         if (s < str) {  /* done w/ string; fill w/ 0. */
    673             macaddr[5-i] = 0;
    674         } else {
    675             if (!isxdigit((unsigned) *s)) {  /* bad character */
    676                 return -1;
    677             }
    678             macaddr[5-i] = xdigit2i((unsigned) *(s--));
    679             if (isxdigit((unsigned) *s)) {
    680                 macaddr[5-i] += 16 * xdigit2i((unsigned) *(s--));
    681             }
    682         }
    683     }
    684 
    685     return 0;
    686 }
    687 
    688 /*
    689  * parse_macaddr will take a string of the form H:H:H:H:H:H where each
    690  * H is one or two hex digits, or a string of the form 0xN where N may
    691  * consist of up to 12 hex digits.  The result is returned in a byte
    692  * array to avoid endian confusion.
    693  */
    694 
    695 int
    696 parse_macaddr(char *str, sal_mac_addr_t macaddr)
    697 {
    698     char *s;
    699     int i;
    700 
    701     if (sal_strchr(str, ':')) {             /* Colon format */
    702         s = str;
    703         for (i = 0; i < 6; i++) {
    704             if (!isxdigit((unsigned)*s)) {  /* bad character */
    705                 return -1;
    706             }
    707             macaddr[i] = xdigit2i((unsigned)*(s++));
    708             if (isxdigit((unsigned)*s)) {
    709                 macaddr[i] *= 16;
    710                 macaddr[i] += xdigit2i((unsigned)*(s++));
    711             }
    712             if ((i < 5) && (*(s++) != ':')) {  /* bad character */
    713                 return -1;
    714             }
    715         }
    716         if (*s) {
    717             return -1;
    718         }
    719     } else if (str[0] == '0' && sal_tolower((int)str[1]) == 'x') {
    720         return parse_macaddr_hex(&(str[2]), macaddr);
    721     } else {  /* Handle 0x... format */
    722         return -1;
    723     }
    724 
    725     return 0;
    726 }
    727 
    728 /*
    729  * format_macaddr requires a buffer of 18 bytes minimum.
    730  * It does not use sal_sprintf so it can be called from an interrupt context.
    731  */
    732 
    733 void
    734 format_macaddr(char buf[SAL_MACADDR_STR_LEN], sal_mac_addr_t macaddr)
    735 {
    736     int i;
    737 
    738     for (i = 0; i <= 5; i++) {
    739         *buf++ = i2xdigit(macaddr[i] >> 4);
    740         *buf++ = i2xdigit(macaddr[i]);
    741         *buf++ = ':';
    742     }
    743 
    744     *--buf = 0;
    745 }
    746 
    747 /*
    748  * increment_macaddr
    749  */
    750 
    751 void
    752 increment_macaddr(sal_mac_addr_t macaddr, int amount)
    753 {
    754     int i, v;
    755     for (i = 5; i >= 0; i--) {
    756         v = (int) macaddr[i] + amount;
    757         macaddr[i] = v;
    758         if (v >= 0 && v <= 255)
    759             break;
    760         amount = v >> 8;        /* carry or borrow (signed shift) */
    761     }
    762 }
    763 
    764 int
    765 parse_ipaddr(char *s, ip_addr_t *ipaddr)
    766 {
    767     char *ts;
    768     int i, x;
    769     ip_addr_t ip = 0;
    770 
    771     if (sal_strchr(s, '.')) {               /* dotted notation */
    772         for (i = 0; i < 4; i++) {
    773             x = sal_ctoi(s, &ts);
    774             if ((x > 0xff) || (x < 0)) {
    775                 return(-1);
    776             }
    777             ip = (ip << 8) | x;
    778             if (*ts != '.') {   /* End of string */
    779                 break;
    780             }
    781             s = ts + 1;
    782         }
    783         if (((i != 3) || (*ts != '\0'))) {
    784             return(-1);
    785         } else {
    786             *ipaddr = ip;
    787             return(0);
    788         }
    789     } else if (isint(s)){
    790         *ipaddr = parse_integer(s);
    791         return(0);
    792     } else {
    793         return(-1);
    794     }
    795 }
    796 
    797 static INLINE int
    798 colon_count(char *s)
    799 {
    800     int cc = 0;
    801     char *ts = s;
    802 
    803     while ((ts = sal_strchr(ts, ':')) != NULL) {
    804         ts++;
    805         cc++;
    806     }
    807 
    808     return cc;
    809 }
    810 
    811 int
    812 parse_ip6addr(char *s, ip6_addr_t ipaddr)
    813 {
    814     char *ts;
    815     int i, x;
    816     int has_dcolon = 0; /* double colon */
    817     char *dstr = s;
    818     char str_buf[50];
    819     char *tmps = &str_buf[0];
    820     uint8      *ip = (uint8 *)ipaddr;
    821 
    822     while ((dstr = sal_strstr(dstr, "::")) != NULL) {
    823         dstr += 2;
    824         has_dcolon++;
    825     }
    826     if (has_dcolon > 1) {
    827         return(-1);
    828     } else if (has_dcolon == 1) {
    829         dstr -= 2;
    830     }
    831 
    832     sal_memset(ipaddr, 0, sizeof (ip6_addr_t));
    833     if (sal_strchr(s, ':')) {               /* colon notation */
    834         sal_strncpy(&tmps[2], s, 47);
    835         tmps[49] = '\0';
    836         for (i = 0; i < 8; i++) {
    837             tmps[0] = '0';
    838             tmps[1] = 'x';
    839             x = sal_ctoi(tmps, &ts);
    840             if ((x > 0xffff) || (x < 0)) {
    841                 return(-1);
    842             }
    843 
    844             /* double colon, heading double colon not supported */
    845             if (has_dcolon && *ts == ':' && ts == &tmps[2]) {
    846                 int end;
    847                 int cc = colon_count(ts);
    848                 if (cc > 8) {
    849                     return (-1);
    850                 }
    851                 end = 8 - cc;
    852                 for (;i < end; i++) {
    853                     ip[2 * i] = 0;
    854                     ip[2 * i + 1] = 0;
    855                 }
    856                 i--;
    857                 tmps = ts - 1;
    858                 /* :: will be replaced by 0x */
    859                 continue;
    860             }
    861 
    862             /* double colon, heading double colon not supported */
    863             if (has_dcolon && *ts == ':' && ts == &tmps[2]) {
    864                 int end;
    865                 int cc = colon_count(ts);
    866                 if (cc > 8) {
    867                     return (-1);
    868                 }
    869                 end = 8 - cc;
    870                 for (;i < end; i++) {
    871                     ip[2 * i] = 0;
    872                     ip[2 * i + 1] = 0;
    873                 }
    874                 i--;
    875                 tmps = ts - 1;
    876                 /* :: will be replaced by 0x */
    877                 continue;
    878             }
    879 
    880             ip[2 * i] = (x >> 8) & 0xFF;
    881             ip[2 * i + 1] = x & 0xFF;
    882             if (*ts != ':') {   /* End of string */
    883                 break;
    884             }
    885             tmps = ts - 1;
    886         }
    887         if (((i != 7) || (*ts != '\0'))) {
    888             return(-1);
    889         } else {
    890             return(0);
    891         }
    892     } else {
    893         return(-1);
    894     }
    895 }
    896 
    897 /*
    898  * To be useful the incremnent position should also be specified
    899  */
    900 void
    901 increment_ip6addr(ip6_addr_t ipaddr, uint32 byte_pos, int amount)
    902 {
    903     int i, v;
    904     if (byte_pos >= sizeof(ip6_addr_t)) {
    905         return;
    906     }
    907     for (i = byte_pos; i >= 0; i--) {
    908         v = (int) ipaddr[i] + amount;
    909         ipaddr[i] = v;
    910         if (v >= 0 && v <= 255)
    911             break;
    912         amount = v >> 8;        /* carry or borrow (signed shift) */
    913     }
    914 }
    915 
    916 void
    917 format_ipaddr(char buf[SAL_IPADDR_STR_LEN], ip_addr_t ipaddr)
    918 {
    919     sal_sprintf(buf, "%d.%d.%d.%d",
    920             (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
    921             (ipaddr >> 8) & 0xff, ipaddr & 0xff);
    922 }
    923 
    924 void
    925 format_ipaddr_mask(char *buf, ip_addr_t ipaddr, ip_addr_t mask)
    926 {
    927     int masklen, i;
    928 
    929     /* Convert netmask to number of bits */
    930 
    931     masklen = 0;
    932     for (i = 0; i < 32; i++) {
    933         if (mask & 0x80000000) {
    934             masklen++;
    935             mask = mask << 1;
    936         } else {
    937             break;
    938         }
    939     }
    940     sal_sprintf(buf, "%d.%d.%d.%d/%d",
    941             (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff,
    942             (ipaddr >> 8) & 0xff, ipaddr & 0xff, masklen);
    943 }
    944 
    945 void
    946 format_ip6addr(char buf[IP6ADDR_STR_LEN], ip6_addr_t ipaddr)
    947 {
    948     sal_sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
    949             (((uint16)ipaddr[0] << 8) | ipaddr[1]),
    950             (((uint16)ipaddr[2] << 8) | ipaddr[3]),
    951             (((uint16)ipaddr[4] << 8) | ipaddr[5]),
    952             (((uint16)ipaddr[6] << 8) | ipaddr[7]),
    953             (((uint16)ipaddr[8] << 8) | ipaddr[9]),
    954             (((uint16)ipaddr[10] << 8) | ipaddr[11]),
    955             (((uint16)ipaddr[12] << 8) | ipaddr[13]),
    956             (((uint16)ipaddr[14] << 8) | ipaddr[15]));
    957 }
    958 
    959 /*
    960  * Parse a string containing a list of ports into a bitmap string.
    961  * The input format is:
    962  *
    963  *      PBMP    : '0x' {HEXDIGIT}+      { return BITS_SET($2); }
    964  *              | LIST                  { return $1; }
    965  *              ;
    966  *      LIST    : [LIST ','] RANGE STEP         { return UNION($1, $2, $3); }
    967  *              | [LIST ','] '~' RANGE STEP     { return REMOVE($1, $2, $3); }
    968  *              ;
    969  *      RANGE   : PORT '-' PORT         { return $1 .. $2; }
    970  *              | PORT                  { return $1 .. $1; }
    971  *              | 'FE'                  { return FE ports; }
    972  *              | 'GE'                  { return GE ports; }
    973  *              | 'XE'                  { return XE ports; }
    974  *              | 'HG'                  { return HG ports; }
    975  *              | 'E'                   { return ether ports; }
    976  *              | '*'                   { return ether, HG ports; }
    977  *              | 'ALL'                 { return ether, HG, CPU ports; }
    978  *              ;
    979  *      STEP    : ':' INTEGER           { return $2 };
    980  *              ;
    981  *      PORT    : INTEGER{NUM_PORT}             { return $1 }
    982  *              | 'E' INTEGER{NUM_E_PORT}       { return E port $2 }
    983  *              | 'FE' INTEGER{NUM_FE_PORT}     { return FE port $2 }
    984  *              | 'GE' INTEGER{NUM_GE_PORT}     { return GE port $2 }
    985  *              | 'XE' INTEGER{NUM_GE_PORT}     { return XE port $2 }
    986  *              | 'HG' INTEGER{NUM_HG_PORT}     { return HG port $2 }
    987  *              | 'CPU'                         { return CMIC_PORT }
    988  *              | 'NONE'                        { return NIL }
    989  *
    990  * Returns 0 on success, -1 on syntax error.
    991  */
    992 
    993 int
    994 parse_pbmp(int unit, char *s, soc_pbmp_t *pbmp)
    995 {
    996     soc_pbmp_t  bmall;
    997     int         complement, plast, pfirst, pstep, port, p, tp, i;
    998     int         matched, blk, blktype, is_ci = 0, is_phy = 0;
    999     char        *sn, *se;
   1000     soc_block_name_t *blk_names;
   1001     soc_pbmp_t  pbmp_temp;
   1002 
   1003     if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
   1004         return _shr_pbmp_decode(s, pbmp);
   1005     }
   1006 
   1007     SOC_PBMP_CLEAR(bmall);
   1008     SOC_PBMP_CLEAR(pbmp_temp);
   1009     SOC_PBMP_CLEAR(*pbmp);
   1010 
   1011     blk_names = soc_block_names;
   1012     pfirst = -1;
   1013     pstep = 1;
   1014     complement = 0;
   1015 
   1016     while (*s) {
   1017         if (s[0] == '~' || s[0] == '!') {
   1018             complement = 1;
   1019             s += 1;
   1020         }
   1021 
   1022         /* To cover for Apache XLPORTB0 and CLG2PORT blocks  */
   1023         if ((sal_strncasecmp("XLB0PORT", s, (sizeof("XLB0PORT") - 1)) == 0) ||
   1024             (sal_strncasecmp("CLG2PORT", s, (sizeof("CLG2PORT") - 1)) == 0)) {
   1025             sn = s + 8;
   1026         } else {
   1027 
   1028 
   1029             for (sn = s; *sn && *sn != '-' && *sn != ',' && *sn != ':' &&
   1030                      !isdigit((unsigned)*sn); sn++) {
   1031                 ;
   1032             }
   1033         }
   1034 
   1035 
   1036         se = sn;
   1037         if (isdigit((unsigned)*sn)) {
   1038             port = 0;
   1039             do {
   1040                 port = port * 10 + (*se++ - '0');
   1041             } while (isdigit((unsigned) *se));
   1042         } else {
   1043             port = -1;
   1044         }
   1045         plast = -1;
   1046         BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PORT_ALL(unit));
   1047 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   1048         if (SOC_IS_ENDURO(unit) || SOC_IS_TD_TT(unit)) {
   1049             /* Since the LB port in Enduro is port 1, not the last port.
   1050                  We need to add this to support <reg_name>.number
   1051                  register access method with correct port mapping in AV tests. */
   1052             BCM_PBMP_OR(pbmp_temp, PBMP_LB(unit));
   1053         }
   1054 #endif /* BCM_ENDURO_SUPPORT || BCM_TRIDENT_SUPPORT */
   1055 
   1056         if (soc_feature(unit, soc_feature_ep_redirect_v2)) {
   1057             BCM_PBMP_OR(pbmp_temp, PBMP_RDB_ALL(unit));
   1058         }
   1059         if (SOC_IS_MONTEREY(unit)) {
   1060             BCM_PBMP_OR(pbmp_temp, PBMP_MACSEC_ALL(unit));
   1061         }
   1062 #if defined(BCM_TRIUMPH3_SUPPORT)
   1063         if (SOC_IS_TRIUMPH3(unit)) {
   1064             /* Add AXP ports.
   1065              * We need to add this to support <reg_name>.number
   1066              * register access method with correct port mapping in AV tests.
   1067              */
   1068             BCM_PBMP_OR(pbmp_temp, PBMP_AXP_ALL(unit));
   1069         }
   1070 #endif /* BCM_TRIUMPH3_SUPPORT */
   1071         if (sn == s) {                          /* unprefixed number */
   1072             if (soc_property_get(unit, spn_DPORT_MAP_DIRECT, FALSE)) {
   1073                 /* Treat port as internal port number */
   1074                 plast = DPORT_FROM_PORT(unit, port);
   1075             } else {
   1076                 plast = -1;
   1077 
   1078                 /* Iterate through the dport map and find the corresponding
   1079                  * logical port. If the logical port is valid and is the last
   1080                  * one passed in as the arg, mark it as the last port
   1081                  */
   1082                 for (p = 0; p < SOC_DPORT_MAX; p++) {
   1083                     tp = soc_dport_to_port(unit, p);
   1084 
   1085                     /* If the logical port is valid and mapped, and if it's
   1086                      * the last port from the string passed above, mark it
   1087                      * as the last port and break out of the loop
   1088                      */
   1089                     if (tp >= 0 && SOC_PBMP_MEMBER(pbmp_temp, tp)) {
   1090                         if (p == port) {
   1091                             plast = p;
   1092                             break;
   1093                         }
   1094                     }
   1095                 }
   1096             }
   1097             if (plast < 0) {
   1098                 return -1;                      /* error: port out of range */
   1099             }
   1100         } else {                                /* prefix number */
   1101             tp = *sn;
   1102             *sn = '\0';
   1103             if (sal_strcasecmp(s, "fe") == 0) {
   1104                 bmall = PBMP_FE_ALL(unit);
   1105             } else if (sal_strcasecmp(s, "ge") == 0) {
   1106                 bmall = PBMP_GE_ALL(unit);
   1107             } else if (sal_strcasecmp(s, "xe") == 0) {
   1108                 bmall = PBMP_XE_ALL(unit);
   1109             } else if (sal_strcasecmp(s, "ce") == 0) {
   1110                 bmall = PBMP_CE_ALL(unit);
   1111             } else if (sal_strcasecmp(s, "cd") == 0) {
   1112                 bmall = PBMP_CDE_ALL(unit);
   1113             } else if (sal_strcasecmp(s, "hg") == 0) {
   1114                 bmall = PBMP_HG_ALL(unit);
   1115             } else if (sal_strcasecmp(s, "hl") == 0) {
   1116                 bmall = PBMP_HL_ALL(unit);
   1117             } else if (sal_strcasecmp(s, "hg_s") == 0) {
   1118                 bmall = PBMP_HG_SUBPORT_ALL(unit);
   1119             } else if (sal_strcasecmp(s, "st") == 0) {
   1120                 bmall = PBMP_ST_ALL(unit);
   1121             } else if (sal_strcasecmp(s, "il") == 0) {
   1122                 bmall = PBMP_IL_ALL(unit);
   1123             } else if (SOC_IS_SAND(unit) && (sal_strcasecmp(s, "xl") == 0)) {
   1124                 bmall = PBMP_XL_ALL(unit);
   1125             } else if (sal_strcasecmp(s, "axp") == 0) {
   1126                 bmall = PBMP_AXP_ALL(unit);
   1127             } else if (sal_strcasecmp(s, "sch") == 0) {
   1128                 bmall = PBMP_SCH_ALL(unit);
   1129             } else if (sal_strcasecmp(s, "sci") == 0) {
   1130                 bmall = PBMP_SCI_ALL(unit);
   1131             } else if (sal_strcasecmp(s, "qsgmii") == 0) {
   1132                 bmall = PBMP_QSGMII_ALL(unit);
   1133             } else if ((sal_strcasecmp(s, "sfi") == 0 ||
   1134                         sal_strcasecmp(s, "if") == 0)) {
   1135                 bmall = PBMP_SFI_ALL(unit);
   1136             } else if (sal_strcasecmp(s, "fabric") == 0) {
   1137                 bmall = PBMP_SFI_ALL(unit);
   1138                 port += SOC_INFO(unit).fabric_logical_port_base; /* fabric links starting from
   1139                                                                 configurable logical_port_base */
   1140             } else if (sal_strcasecmp(s, "sci_sfi") == 0) {
   1141                 bmall = PBMP_SCI_ALL(unit);
   1142 		BCM_PBMP_AND(bmall, PBMP_SFI_ALL(unit));
   1143             } else if (sal_strcasecmp(s, "spi") == 0) {
   1144                 bmall = PBMP_SPI_ALL(unit);
   1145             } else if (sal_strcasecmp(s, "spi_s") == 0) {
   1146                 bmall = PBMP_SPI_SUBPORT_ALL(unit);
   1147             } else if (sal_strcasecmp(s, "e") == 0) {
   1148                 bmall = PBMP_E_ALL(unit);
   1149 #ifdef BCM_DNX_SUPPORT
   1150             } else if ((sal_strcasecmp(s, "eth") == 0) && SOC_IS_DNX(unit)) {
   1151                 bmall = PBMP_E_ALL(unit);
   1152 #endif
   1153             } else if (sal_strcasecmp(s, "cpu") == 0) {
   1154                 bmall = PBMP_CMIC(unit);
   1155             } else if (sal_strcasecmp(s, "lb") == 0) {
   1156                 bmall = PBMP_LB(unit);
   1157             } else if (sal_strcasecmp(s, "rdb") == 0) {
   1158                 bmall = PBMP_RDB_ALL(unit);
   1159             } else if (sal_strcasecmp(s, "fae") == 0) {
   1160                 bmall = PBMP_FAE_ALL(unit);
   1161             } else if (sal_strcasecmp(s, "msec") == 0) {
   1162                 bmall = PBMP_MACSEC_ALL(unit);
   1163             } else if (sal_strcasecmp(s, "roe") == 0) {
   1164                 bmall = PBMP_CPRI_ALL(unit);
   1165             } else if (sal_strcasecmp(s, "mmu") == 0) {
   1166                 bmall = PBMP_MMU(unit);
   1167             } else if (sal_strcasecmp(s, "mgmt") == 0) {
   1168                 bmall = PBMP_MANAGEMENT(unit);
   1169             } else if (sal_strcasecmp(s, "all") == 0) {
   1170                 bmall = PBMP_ALL(unit);
   1171                 SOC_PBMP_REMOVE(bmall, PBMP_MACSEC_ALL(unit));
   1172                 SOC_PBMP_REMOVE(bmall, PBMP_LB(unit));
   1173                 SOC_PBMP_REMOVE(bmall, PBMP_RDB_ALL(unit));
   1174                 SOC_PBMP_REMOVE(bmall, PBMP_FAE_ALL(unit));
   1175                 BCM_PBMP_OR(bmall, PBMP_SPI_ALL(unit));
   1176             } else if (sal_strcasecmp(s, "*") == 0) {
   1177                 bmall = PBMP_PORT_ALL(unit);
   1178                 BCM_PBMP_OR(bmall, PBMP_SPI_ALL(unit));
   1179             } else if (sal_strcasecmp(s, "none") == 0) {
   1180                 SOC_PBMP_CLEAR(bmall);
   1181             } else if (sal_strcasecmp(s, "phy") == 0) {
   1182                 SOC_PBMP_ASSIGN(bmall,SOC_INFO(unit).physical_pbm);
   1183                 is_phy = 1;
   1184             } else if (sal_strcasecmp(s, "ci") == 0) {
   1185                 SOC_PBMP_CLEAR(bmall);
   1186                 for (i = 0; blk_names[i].blk != SOC_BLK_NONE; i++) {
   1187                     if (sal_strcasecmp(blk_names[i].name, "ci") == 0) {
   1188                         blktype = blk_names[i].blk;
   1189                         SOC_BLOCK_ITER(unit, blk, blktype) {
   1190                             SOC_PBMP_OR(bmall, SOC_BLOCK_BITMAP(unit, blk));
   1191                             plast = port;
   1192                             is_ci = 1;
   1193                         }
   1194                     }
   1195                 }
   1196             } else {
   1197                 /* parse block names */
   1198                 matched = 0;
   1199                 SOC_PBMP_CLEAR(bmall);
   1200                 for (i = 0; blk_names[i].blk != SOC_BLK_NONE; i++) {
   1201                     if (sal_strcasecmp(blk_names[i].name, s) == 0) {
   1202                         blktype = blk_names[i].blk;
   1203                         matched += 1;
   1204                         SOC_BLOCK_ITER(unit, blk, blktype) {
   1205                             if (port >= 0 &&
   1206                                 SOC_BLOCK_INFO(unit, blk).number != port) {
   1207                                 continue;
   1208                             }
   1209                             SOC_PBMP_OR(bmall, SOC_BLOCK_BITMAP(unit, blk));
   1210                         }
   1211                     }
   1212                 }
   1213                 if (matched == 0) {             /* was not a block name */
   1214                     *sn = tp;                   /* restore parsed string */
   1215                     return -1;                  /* error: unexpected char */
   1216                 }
   1217                 port = -1;                      /* don't use the number */
   1218             }
   1219             *sn = tp;
   1220             if (port >= 0) {
   1221                 i = -1;
   1222                 if(is_phy || is_ci) {
   1223                   SOC_PBMP_ITER(bmall,p){
   1224                     if (p == port) {
   1225             			    plast = p;
   1226             			    break;
   1227                     }
   1228                   }
   1229                 } else {
   1230                   DPORT_SOC_PBMP_ITER(unit, bmall, p, tp) {
   1231                     if (SOC_IS_SAND(unit)) {
   1232                       if (p == port) {
   1233                           plast = p;
   1234                           break;
   1235                       }
   1236                     } else {
   1237                       i += 1;
   1238                       if (DPORT_FROM_DPORT_INDEX(unit, p, i) == port) {
   1239                           plast = p;
   1240                           break;
   1241                       }
   1242                     }
   1243                   }
   1244                 }
   1245                 if (plast < 0) {
   1246                     return -1;                  /* error: index out of range */
   1247                 }
   1248             }
   1249         }
   1250         s = se;
   1251 
   1252         switch (*s) {
   1253         case '-':
   1254             pstep = 1;
   1255             if (plast < 0) {
   1256                 return -1;                      /* error: range without port */
   1257             } else if (pfirst < 0) {
   1258                 pfirst = plast;
   1259             } else {
   1260                 return -1;                      /* error: x-y-z */
   1261             }
   1262             break;
   1263         case ':':
   1264             s++;
   1265             if (!isdigit((unsigned)*s)) {
   1266                 return -1;
   1267             }
   1268             for (pstep = 0; isdigit((unsigned)*s); s++) {
   1269                 pstep = pstep * 10 + (*s - '0');
   1270             }
   1271             if (pstep == 0 || (*s != ',' && *s != '\0')) {
   1272                 return -1;
   1273             }
   1274             /* fall through */
   1275         case ',':
   1276         case '\0':
   1277             if (plast < 0) {                    /* complete bitmap op */
   1278                 pfirst = 999;
   1279                 plast = -1;
   1280                 DPORT_SOC_PBMP_ITER(unit, bmall, p, tp) {
   1281                     if (p < pfirst) {
   1282                         pfirst = p;
   1283                     }
   1284                     if (p > plast) {
   1285                         plast = p;
   1286                     }
   1287                 }
   1288             }
   1289             if (pfirst < 0) {           /* just one port */
   1290                 pfirst = plast;
   1291             }
   1292             for (port = pfirst; port <= plast; port += pstep) {  /* a range */
   1293                 p = is_ci ? port : DPORT_TO_PORT(unit, port);
   1294                 p = is_phy ? port : p;
   1295                 /* coverity[overrun-local] */
   1296                 if ((p >= 0) && SOC_PBMP_NOT_NULL(bmall) && !SOC_PBMP_MEMBER(bmall, p)) {
   1297                     continue;   /* skip gaps in range */
   1298                 }
   1299                 if ((is_ci) || (SOC_PORT_VALID(unit, p)) || is_phy) {
   1300                     if (complement) {
   1301                         SOC_PBMP_PORT_REMOVE(*pbmp, p + is_phy*(SOC_INFO(unit).physical_port_offset-1));
   1302                     } else {
   1303                         SOC_PBMP_PORT_ADD(*pbmp, p + is_phy*(SOC_INFO(unit).physical_port_offset-1));
   1304                     }
   1305                 }
   1306             }
   1307             if (*s == '\0') {
   1308                 return 0;
   1309             }
   1310             pfirst = -1;
   1311             pstep = 1;
   1312             complement = 0;
   1313             SOC_PBMP_CLEAR(bmall);
   1314             is_ci = 0;
   1315             break;
   1316         default:
   1317             return -1;                          /* error: unexpected char */
   1318         }
   1319         s += 1;
   1320     }
   1321     return -1;                                  /* error: unexpected end */
   1322 }
   1323 
   1324 int
   1325 parse_pp_pbmp(int unit, char *s, soc_pbmp_t *pbmp)
   1326     {
   1327         soc_pbmp_t  bmall;
   1328         int         complement, plast, pfirst, pstep, port, p, i;
   1329         char        *sn, *se;
   1330         soc_pbmp_t  pbmp_temp;
   1331 
   1332         if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
   1333             return _shr_pbmp_decode(s, pbmp);
   1334         }
   1335 
   1336         SOC_PBMP_CLEAR(bmall);
   1337         SOC_PBMP_CLEAR(pbmp_temp);
   1338         SOC_PBMP_CLEAR(*pbmp);
   1339 
   1340         pfirst = -1;
   1341         pstep = 1;
   1342         complement = 0;
   1343 
   1344         while (*s) {
   1345             if (s[0] == '~' || s[0] == '!') {
   1346                 complement = 1;
   1347                 s += 1;
   1348             }
   1349 
   1350             for (sn = s; *sn && *sn != '-' && *sn != ',' && *sn != ':' &&
   1351                      !isdigit((unsigned)*sn); sn++) {
   1352                 ;
   1353             }
   1354             se = sn;
   1355             if (isdigit((unsigned)*sn)) {
   1356                 port = 0;
   1357                 do {
   1358                     port = port * 10 + (*se++ - '0');
   1359                 } while (isdigit((unsigned) *se));
   1360             } else {
   1361                 port = -1;
   1362             }
   1363 
   1364             plast = -1;
   1365             BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PP_ALL(unit));
   1366             if (sn == s) {                          /* unprefixed number */
   1367                 i = 0;
   1368                 plast = -1;
   1369                 PBMP_ITER(pbmp_temp, p) {
   1370                     if (i == port) {
   1371                         plast = p;
   1372                         break;
   1373                     }
   1374                     i += 1;
   1375                 }
   1376                 if (plast < 0) {
   1377                     return -1;                      /* error: port out of range */
   1378                 }
   1379             } else {                                /* prefix number */
   1380                 p = *sn;
   1381                 *sn = '\0';
   1382                 if (sal_strcasecmp(s, "pp") == 0) {
   1383                     bmall = PBMP_PP_ALL(unit);
   1384                 } else {
   1385                     /* Not Handled now */
   1386                 }
   1387                 SOC_PBMP_ITER(bmall,p){
   1388                     if (p == port) {
   1389                         plast = p;
   1390                         break;
   1391                     }
   1392                 }
   1393                 if (plast < 0) {
   1394                     return -1;                  /* error: index out of range */
   1395                 }
   1396             }
   1397             s = se;
   1398 
   1399             switch (*s) {
   1400             case '-':
   1401                 pstep = 1;
   1402                 if (pfirst < 0) {
   1403                     pfirst = plast;
   1404                 } else {
   1405                     return -1;                      /* error: x-y-z */
   1406                 }
   1407                 break;
   1408             case ':':
   1409                 s++;
   1410                 if (!isdigit((unsigned)*s)) {
   1411                     return -1;
   1412                 }
   1413                 for (pstep = 0; isdigit((unsigned)*s); s++) {
   1414                     pstep = pstep * 10 + (*s - '0');
   1415                 }
   1416                 if (pstep == 0 || (*s != ',' && *s != '\0')) {
   1417                     return -1;
   1418                 }
   1419                 /* fall through */
   1420             case ',':
   1421             case '\0':
   1422                 if (pfirst < 0) {           /* just one port */
   1423                     pfirst = plast;
   1424                 }
   1425                 for (port = pfirst; port <= plast; port += pstep) {  /* a range */
   1426                     if (SOC_PBMP_NOT_NULL(bmall) && !SOC_PBMP_MEMBER(bmall, port)) {
   1427                         continue;   /* skip gaps in range */
   1428                     }
   1429                     if (1) { 
   1430                         if (complement) {
   1431                             SOC_PBMP_PORT_REMOVE(*pbmp, port);
   1432                         } else {
   1433                             SOC_PBMP_PORT_ADD(*pbmp, port);
   1434                         }
   1435                     }
   1436                 }
   1437                 if (*s == '\0') {
   1438                     return 0;
   1439                 }
   1440                 pfirst = -1;
   1441                 pstep = 1;
   1442                 complement = 0;
   1443                 SOC_PBMP_CLEAR(bmall);
   1444                 break;
   1445             default:
   1446                 return -1;                          /* error: unexpected char */
   1447             }
   1448             s += 1;
   1449         }
   1450         return -1;                                  /* error: unexpected end */
   1451     }
   1452 
   1453 
   1454 int
   1455 parse_bcm_pbmp(int unit, char *s, bcm_pbmp_t *pbmp)
   1456 {
   1457     int rv = parse_pbmp(unit, s, pbmp);
   1458 
   1459     BCM_API_XLATE_PORT_PBMP_P2A(unit, pbmp);
   1460 
   1461     return rv;
   1462 }
   1463 
   1464 int
   1465 parse_pbmp_no_error(int unit, char *s, pbmp_t *pbmp)
   1466 {
   1467     pbmp_t      bmall;
   1468     int         complement, plast, pfirst, pstep, port, p, tp, i;
   1469     int         matched, blk, blktype;
   1470     char        *sn, *se;
   1471     uint16      dev_id;
   1472     uint8       rev_id;
   1473     soc_block_name_t *blk_names;
   1474     pbmp_t      pbmp_temp;
   1475 
   1476     if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
   1477         return _shr_pbmp_decode(s, pbmp);
   1478     }
   1479 
   1480     SOC_PBMP_CLEAR(bmall);
   1481     SOC_PBMP_CLEAR(pbmp_temp);
   1482     SOC_PBMP_CLEAR(*pbmp);
   1483 
   1484     blk_names = soc_block_names;
   1485     soc_cm_get_id(unit, &dev_id, &rev_id);
   1486 
   1487     pfirst = -1;
   1488     pstep = 1;
   1489     complement = 0;
   1490 
   1491     while (*s) {
   1492         if (s[0] == '~' || s[0] == '!') {
   1493             complement = 1;
   1494             s += 1;
   1495         }
   1496 
   1497         for (sn = s; *sn && *sn != '-' && *sn != ',' && *sn != ':' &&
   1498                  !isdigit((unsigned)*sn); sn++) {
   1499             ;
   1500         }
   1501         se = sn;
   1502         if (isdigit((unsigned)*sn)) {
   1503             port = 0;
   1504             do {
   1505                 port = port * 10 + (*se++ - '0');
   1506             } while (isdigit((unsigned) *se));
   1507         } else {
   1508             port = -1;
   1509         }
   1510 
   1511         plast = -1;
   1512         BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PORT_ALL(unit));
   1513 #if defined(BCM_ENDURO_SUPPORT)
   1514         if(SOC_IS_ENDURO(unit)) {
   1515             /* Since the LB port in Enduro is port 1, not the last port.
   1516                  We need to add this to support <reg_name>.number
   1517                  register access method with correct port mapping in AV tests. */
   1518             BCM_PBMP_OR(pbmp_temp, PBMP_LB(unit));
   1519         }
   1520 #endif /* BCM_ENDURO_SUPPORT */
   1521         if (sn == s) {                          /* unprefixed number */
   1522             if (soc_property_get(unit, spn_DPORT_MAP_DIRECT, FALSE)) {
   1523                 /* Treat port as internal port number */
   1524                 plast = DPORT_FROM_PORT(unit, port);
   1525             } else {
   1526                 /* Port number is port index + 1 */
   1527                 i = 0;
   1528                 plast = -1;
   1529                 /* coverity[overrun-local] */
   1530                 DPORT_SOC_PBMP_ITER(unit, pbmp_temp, p, tp) {
   1531                     i += 1;
   1532                     if (i == port) {
   1533                         plast = p;
   1534                         break;
   1535                     }
   1536                 }
   1537             }
   1538             if (plast < 0) {
   1539                 return -1;                      /* error: port out of range */
   1540             }
   1541         } else {                                /* prefix number */
   1542             tp = *sn;
   1543             *sn = '\0';
   1544             if (sal_strcasecmp(s, "fe") == 0) {
   1545                 switch (dev_id) {
   1546                 case 0xb018:
   1547                     SOC_PBMP_WORD_SET(bmall, 0, 0xffffffc0);
   1548                     SOC_PBMP_WORD_SET(bmall, 1, 0x3fffff);
   1549                     break;
   1550                 case 0xb014:
   1551                 case 0xb024:
   1552                 case 0xb025:
   1553                     SOC_PBMP_WORD_SET(bmall, 0, 0x3fffffc0);
   1554                     break;
   1555                 default:
   1556                     break;
   1557                 }
   1558             } else if (sal_strcasecmp(s, "ge") == 0) {
   1559                 switch (dev_id) {
   1560                 case 0xb218:
   1561                     SOC_PBMP_WORD_SET(bmall, 0, 0xfffffffe);
   1562                     SOC_PBMP_WORD_SET(bmall, 1, 0x3fffff);
   1563                     break;
   1564                 case 0xb214:
   1565                 case 0xb215:
   1566                 case 0xb224:
   1567                 case 0xb225:
   1568                     SOC_PBMP_WORD_SET(bmall, 0, 0x3ffffffe);
   1569                     break;
   1570                 case 0xb226:
   1571                 case 0xb227:
   1572                     SOC_PBMP_WORD_SET(bmall, 0, 0x3ffffe);
   1573                     break;
   1574                 case 0xb212:
   1575                 case 0xb213:
   1576                 case 0xb228:
   1577                 case 0xb229:
   1578                     SOC_PBMP_WORD_SET(bmall, 0, 0x3ffe);
   1579                     break;
   1580                 case 0xc71a:
   1581                     SOC_PBMP_WORD_SET(bmall, 0, 0xfffffff8);
   1582                     SOC_PBMP_WORD_SET(bmall, 1, 0x3fffff);
   1583                     break;
   1584                 case 0xc71b:
   1585                 case 0xc724:
   1586                     SOC_PBMP_WORD_SET(bmall, 0, 0x3ffffff8);
   1587                     break;
   1588                 case 0xc716:
   1589                     SOC_PBMP_WORD_SET(bmall, 0, 0x3fffc8);
   1590                     break;
   1591                 case 0xc726:
   1592                     SOC_PBMP_WORD_SET(bmall, 0, 0x3ffff8);
   1593                     break;
   1594                 case 0xb018:
   1595                 case 0xb014:
   1596                 case 0xb024:
   1597                 case 0xb025:
   1598                     SOC_PBMP_WORD_SET(bmall, 0, 0x3e);
   1599                     break;
   1600                 default:
   1601                     break;
   1602                 }
   1603             } else if (sal_strcasecmp(s, "st") == 0) {
   1604                 switch (dev_id) {
   1605                 case 0xb218:
   1606                 case 0xb214:
   1607                 case 0xb215:
   1608                 case 0xb212:
   1609                 case 0xb213:
   1610                 case 0xb018:
   1611                 case 0xb014:
   1612                     SOC_PBMP_WORD_SET(bmall, 0, 0x6);
   1613                     break;
   1614                 case 0xb024:
   1615                 case 0xb025:
   1616                 case 0xb224:
   1617                 case 0xb225:
   1618                 case 0xb226:
   1619                 case 0xb227:
   1620                 case 0xb228:
   1621                 case 0xb229:
   1622                     SOC_PBMP_WORD_SET(bmall, 0, 0x36);
   1623                 default:
   1624                     break;
   1625                 }
   1626             } else if (sal_strcasecmp(s, "e") == 0) {
   1627                 bmall = PBMP_E_ALL(unit);
   1628             } else if (sal_strcasecmp(s, "cpu") == 0) {
   1629                 bmall = PBMP_CMIC(unit);
   1630             } else if (sal_strcasecmp(s, "all") == 0) {
   1631                 bmall = PBMP_ALL(unit);
   1632                 BCM_PBMP_OR(bmall, PBMP_SPI_ALL(unit));
   1633             } else if (sal_strcasecmp(s, "*") == 0) {
   1634                 bmall = PBMP_PORT_ALL(unit);
   1635                 BCM_PBMP_OR(bmall, PBMP_SPI_ALL(unit));
   1636             } else if (sal_strcasecmp(s, "none") == 0) {
   1637                 SOC_PBMP_CLEAR(bmall);
   1638             } else {
   1639                 /* parse block names */
   1640                 matched = 0;
   1641                 SOC_PBMP_CLEAR(bmall);
   1642                 for (i = 0; blk_names[i].blk != SOC_BLK_NONE; i++) {
   1643                     if (sal_strcasecmp(blk_names[i].name, s) == 0) {
   1644                         blktype = blk_names[i].blk;
   1645                         matched += 1;
   1646                         SOC_BLOCK_ITER(unit, blk, blktype) {
   1647                             if (port >= 0 &&
   1648                                 SOC_BLOCK_INFO(unit, blk).number != port) {
   1649                                 continue;
   1650                             }
   1651                             SOC_PBMP_OR(bmall, SOC_BLOCK_BITMAP(unit, blk));
   1652                         }
   1653                     }
   1654                 }
   1655                 if (matched == 0) {             /* was not a block name */
   1656                     *sn = tp;                   /* restore parsed string */
   1657                     return -1;                  /* error: unexpected char */
   1658                 }
   1659                 port = -1;                      /* don't use the number */
   1660             }
   1661             *sn = tp;
   1662             if (port >= 0) {
   1663                 p = -1;
   1664                 SOC_PBMP_ITER(bmall, tp) {      /* map port from bitmap */
   1665                     p += 1;
   1666                     if (p == port) {
   1667                         plast = tp;
   1668                     }
   1669                 }
   1670                 if (plast < 0) {
   1671 /*                    return -1;                   error: index out of range */
   1672                 }
   1673 
   1674             }
   1675         }
   1676         s = se;
   1677 
   1678         switch (*s) {
   1679         case '-':
   1680             pstep = 1;
   1681             if (plast < 0) {
   1682 /*                return -1;                       error: range without port */
   1683             } else if (pfirst < 0) {
   1684                 pfirst = plast;
   1685             } else {
   1686                 return -1;                      /* error: x-y-z */
   1687             }
   1688             break;
   1689         case ':':
   1690             s++;
   1691             if (!isdigit((unsigned)*s)) {
   1692                 return -1;
   1693             }
   1694             for (pstep = 0; isdigit((unsigned)*s); s++) {
   1695                 pstep = pstep * 10 + (*s - '0');
   1696             }
   1697             if (pstep == 0 || (*s != ',' && *s != '\0')) {
   1698                 return -1;
   1699             }
   1700             /* fall through */
   1701         case ',':
   1702         case '\0':
   1703             if (plast < 0) {                    /* complete bitmap op */
   1704                 pfirst = 999;
   1705                 plast = -1;
   1706                 PBMP_ITER(bmall, p) {
   1707                     if (p < pfirst) {
   1708                         pfirst = p;
   1709                     }
   1710                     if (p > plast) {
   1711                         plast = p;
   1712                     }
   1713                 }
   1714             }
   1715             if (pfirst < 0) {           /* just one port */
   1716                 pfirst = plast;
   1717             }
   1718             for (p = pfirst; p <= plast; p += pstep) {  /* a range */
   1719     /*    coverity[overrun-local : FALSE]    */
   1720                 if (SOC_PBMP_NOT_NULL(bmall) && !SOC_PBMP_MEMBER(bmall, p)) {
   1721                     continue;   /* skip gaps in range */
   1722                 }
   1723                 if (SOC_PORT_VALID(unit, p)) {
   1724                     if (complement) {
   1725                         SOC_PBMP_PORT_REMOVE(*pbmp, p);
   1726                     } else {
   1727                         SOC_PBMP_PORT_ADD(*pbmp, p);
   1728                     }
   1729                 }
   1730             }
   1731             if (*s == '\0') {
   1732                 return 0;
   1733             }
   1734             pfirst = -1;
   1735             pstep = 1;
   1736             complement = 0;
   1737             SOC_PBMP_CLEAR(bmall);
   1738             break;
   1739         default:
   1740             return -1;                          /* error: unexpected char */
   1741         }
   1742         s += 1;
   1743     }
   1744     return -1;                                  /* error: unexpected end */
   1745 }
   1746 
   1747 
   1748 STATIC int
   1749 _parse_port(int unit, char *s, soc_port_t *portp)
   1750 {
   1751     int         port, max_port;
   1752     int         i, p, tp;
   1753     soc_pbmp_t  pbmp_temp;
   1754 
   1755     /* Check if only port number was passed. */
   1756     if (isint(s)) {
   1757         port = parse_integer(s);
   1758         *portp = port;
   1759         if (soc_property_get(unit, spn_DPORT_MAP_DIRECT, FALSE) == FALSE) {
   1760             /* Port number is port index + 1 */
   1761             i = 1;
   1762             *portp = -1;
   1763             SOC_PBMP_ASSIGN(pbmp_temp, PBMP_PORT_ALL(unit));
   1764             /* coverity[overrun-local] */
   1765             DPORT_SOC_PBMP_ITER(unit, pbmp_temp, p, tp) {
   1766                 if (i == port) {
   1767                     *portp = tp;
   1768                     break;
   1769                 }
   1770                 i += 1;
   1771             }
   1772         }
   1773         if (*portp < 0) {
   1774             return -1;                          /* error: invalid port */
   1775         }
   1776         return 0;
   1777     }
   1778 
   1779     {
   1780         max_port = SOC_MAX_NUM_PORTS;
   1781     }
   1782 
   1783     for (port = 0; port < max_port; port++) {
   1784         if (!SOC_PORT_VALID(unit, port)) {
   1785             continue;
   1786         }
   1787         if (sal_strcasecmp(s, "any") == 0) {
   1788             *portp = port;
   1789             return 0;
   1790         }
   1791         if (sal_strcasecmp(s, SOC_PORT_NAME(unit, port)) == 0) {
   1792             *portp = port;
   1793             return 0;
   1794         }
   1795     }
   1796 
   1797     return -1;                                  /* error: no matching name */
   1798 }
   1799 
   1800 char *
   1801 format_gport(char *buf, bcm_gport_t gport)
   1802 {
   1803     int gport_type;
   1804 
   1805     assert(buf != NULL);
   1806 
   1807 #define GPORT_TYPE_SPRINTF(_name) \
   1808         sal_sprintf(buf, "0x%x(%s)", gport, _name)
   1809 
   1810     if (BCM_GPORT_IS_SET(gport)) {
   1811         gport_type = (gport >> _SHR_GPORT_TYPE_SHIFT) & _SHR_GPORT_TYPE_MASK;
   1812         switch(gport_type) {
   1813         case _SHR_GPORT_TYPE_LOCAL:
   1814             GPORT_TYPE_SPRINTF("local");
   1815             break;
   1816         case _SHR_GPORT_TYPE_LOCAL_CPU:
   1817             GPORT_TYPE_SPRINTF("local_cpu");
   1818             break;
   1819         case _SHR_GPORT_TYPE_MODPORT:
   1820             GPORT_TYPE_SPRINTF("modport");
   1821             break;
   1822         case _SHR_GPORT_TYPE_TRUNK:
   1823             GPORT_TYPE_SPRINTF("trunk");
   1824             break;
   1825         case _SHR_GPORT_TYPE_DEVPORT:
   1826             GPORT_TYPE_SPRINTF("devport");
   1827             break;
   1828         case _SHR_GPORT_TYPE_BLACK_HOLE:
   1829             GPORT_TYPE_SPRINTF("black_hole");
   1830             break;
   1831         case _SHR_GPORT_TYPE_MPLS_PORT:
   1832             GPORT_TYPE_SPRINTF("mpls");
   1833             break;
   1834         case _SHR_GPORT_TYPE_MIM_PORT:
   1835             GPORT_TYPE_SPRINTF("mim");
   1836             break;
   1837         case _SHR_GPORT_TYPE_WLAN_PORT:
   1838             GPORT_TYPE_SPRINTF("wlan");
   1839             break;
   1840         case _SHR_GPORT_TYPE_TRILL_PORT:
   1841             GPORT_TYPE_SPRINTF("trill");
   1842             break;
   1843         case _SHR_GPORT_TYPE_SUBPORT_GROUP:
   1844             GPORT_TYPE_SPRINTF("subport_group");
   1845             break;
   1846         case _SHR_GPORT_TYPE_SUBPORT_PORT:
   1847             GPORT_TYPE_SPRINTF("subport_port");
   1848             break;
   1849         case _SHR_GPORT_TYPE_VLAN_PORT:
   1850             GPORT_TYPE_SPRINTF("vlan");
   1851             break;
   1852         case _SHR_GPORT_TYPE_VXLAN_PORT:
   1853             GPORT_TYPE_SPRINTF("vxlan");
   1854             break;
   1855         case _SHR_GPORT_TYPE_FLOW_PORT:
   1856             GPORT_TYPE_SPRINTF("flow");
   1857             break;
   1858         case _SHR_GPORT_TYPE_NIV_PORT:
   1859             GPORT_TYPE_SPRINTF("niv");
   1860             break;
   1861         case _SHR_GPORT_TYPE_L2GRE_PORT:
   1862             GPORT_TYPE_SPRINTF("l2gre");
   1863             break;
   1864         case _SHR_GPORT_TYPE_EXTENDER_PORT:
   1865             GPORT_TYPE_SPRINTF("extender");
   1866             break;
   1867         default:
   1868             GPORT_TYPE_SPRINTF("unknown");
   1869             break;
   1870         }
   1871     } else {
   1872         sal_sprintf(buf, "0x%x", gport);
   1873     }
   1874 
   1875 #undef GPORT_TYPE_SPRINTF
   1876 
   1877     return buf;
   1878 }
   1879 
   1880 #if defined(BCM_ESW_SUPPORT)
   1881 STATIC int stack_len = 0;
   1882 
   1883 STATIC int parse_gport_push(void)
   1884 {
   1885     stack_len++;
   1886     return 0;
   1887 }
   1888 
   1889 STATIC int parse_gport_pop(void)
   1890 {
   1891     if (stack_len) {
   1892         stack_len--;
   1893         return 0;
   1894     }
   1895 
   1896     return 1;
   1897 }
   1898 
   1899 /*
   1900  * Function    : _bcm_util_gport_construct
   1901  * Description : Internal function to construct a gport from
   1902  *                given parameters
   1903  * Parameters  : (IN)  unit       - BCM device number
   1904  *               (IN)  gport_dest - Structure that contains destination
   1905  *                                   to encode into a gport
   1906  *               (OUT) gport      - Global port identifier
   1907  * Returns     : BCM_E_XXX
   1908  * Notes       : The modid and port are translated from the
   1909  *               local modid/port space to application space
   1910  */
   1911 static int
   1912 _bcm_util_gport_construct(int unit, _bcm_util_gport_dest_t *gport_dest, bcm_gport_t *gport)
   1913 {
   1914 
   1915     bcm_gport_t     l_gport = 0;
   1916     bcm_module_t    mod_out;
   1917     bcm_port_t      port_out;
   1918 
   1919     if ((NULL == gport_dest) || (NULL == gport) ){
   1920         return BCM_E_PARAM;
   1921     }
   1922 
   1923     switch (gport_dest->gport_type) {
   1924         case _SHR_GPORT_TYPE_TRUNK:
   1925             SOC_GPORT_TRUNK_SET(l_gport, gport_dest->tgid);
   1926             break;
   1927         case _SHR_GPORT_TYPE_LOCAL_CPU:
   1928             l_gport = BCM_GPORT_LOCAL_CPU;
   1929             break;
   1930         case _SHR_GPORT_TYPE_LOCAL:
   1931             SOC_GPORT_LOCAL_SET(l_gport, gport_dest->port);
   1932             break;
   1933         case _SHR_GPORT_TYPE_SUBPORT_GROUP:
   1934             SOC_GPORT_SUBPORT_GROUP_SET(l_gport, gport_dest->subport_id);
   1935             break;
   1936         case _SHR_GPORT_TYPE_MPLS_PORT:
   1937             BCM_GPORT_MPLS_PORT_ID_SET(l_gport, gport_dest->mpls_id);
   1938             break;
   1939         case _SHR_GPORT_TYPE_MIM_PORT:
   1940             BCM_GPORT_MIM_PORT_ID_SET(l_gport, gport_dest->mim_id);
   1941             break;
   1942         case _SHR_GPORT_TYPE_SUBPORT_PORT:
   1943             BCM_GPORT_SUBPORT_PORT_SET(l_gport, gport_dest->subport_id);
   1944             break;
   1945         case _SHR_GPORT_TYPE_WLAN_PORT:
   1946             BCM_GPORT_WLAN_PORT_ID_SET(l_gport, gport_dest->wlan_id);
   1947             break;
   1948         case _SHR_GPORT_TYPE_DEVPORT:
   1949             BCM_GPORT_DEVPORT_SET(l_gport, unit, gport_dest->port);
   1950             break;
   1951         case _SHR_GPORT_TYPE_MODPORT:
   1952             BCM_IF_ERROR_RETURN (
   1953                 _bcm_gport_modport_hw2api_map(unit, gport_dest->modid,
   1954                                               gport_dest->port, &mod_out,
   1955                                               &port_out));
   1956             SOC_GPORT_MODPORT_SET(l_gport, mod_out, port_out);
   1957             break;
   1958         case _SHR_GPORT_TYPE_EGRESS_MODPORT:
   1959             BCM_IF_ERROR_RETURN (
   1960                 _bcm_gport_modport_hw2api_map(unit, gport_dest->modid,
   1961                                               gport_dest->port, &mod_out,
   1962                                               &port_out));
   1963             BCM_GPORT_EGRESS_MODPORT_SET(l_gport, mod_out, port_out);
   1964             break;
   1965         case _SHR_GPORT_TYPE_CHILD:
   1966             BCM_GPORT_CHILD_SET(l_gport,
   1967                                 gport_dest->modid,
   1968                                 gport_dest->port);
   1969             break;
   1970         case _SHR_GPORT_TYPE_EGRESS_CHILD:
   1971             BCM_GPORT_EGRESS_CHILD_SET(l_gport,
   1972                                        gport_dest->modid,
   1973                                        gport_dest->port);
   1974             break;
   1975         case _SHR_GPORT_TYPE_VLAN_PORT:
   1976             SOC_GPORT_VLAN_PORT_ID_SET(l_gport, gport_dest->vlan_port_id);
   1977             break;
   1978         case _SHR_GPORT_TYPE_VXLAN_PORT:
   1979             SOC_GPORT_VXLAN_PORT_ID_SET(l_gport, gport_dest->vxlan_id);
   1980             break;
   1981         case _SHR_GPORT_TYPE_TRILL_PORT:
   1982             SOC_GPORT_TRILL_PORT_ID_SET(l_gport, gport_dest->trill_id);
   1983             break;
   1984         case _SHR_GPORT_TYPE_NIV_PORT:
   1985             SOC_GPORT_NIV_PORT_ID_SET(l_gport, gport_dest->niv_id);
   1986             break;
   1987         case _SHR_GPORT_TYPE_L2GRE_PORT:
   1988             SOC_GPORT_L2GRE_PORT_ID_SET(l_gport, gport_dest->l2gre_id);
   1989             break;
   1990         case _SHR_GPORT_TYPE_EXTENDER_PORT:
   1991             SOC_GPORT_EXTENDER_PORT_ID_SET(l_gport, gport_dest->extender_id);
   1992             break;
   1993         default:
   1994             return BCM_E_PARAM;
   1995     }
   1996 
   1997     *gport = l_gport;
   1998     return BCM_E_NONE;
   1999 }
   2000 
   2001 
   2002 /*
   2003  * Function:
   2004  *      parse_gport
   2005  * Description:
   2006  *     Parses string that identifies a GPORT and constructs an appropriate GPORT
   2007  * Parameters:
   2008  *      unit - Device unit number
   2009  *      s - input string to parse
   2010  *      portp - output port number
   2011  */
   2012 int parse_gport(int unit, char *s, soc_port_t *portp)
   2013 {
   2014     int port_val = -1, mod_val = -1;
   2015     int i = 0, start_pos = 0, str_len, modid_len = 0;
   2016     char *gport_type_str = NULL;
   2017     char *gport_val_str = NULL;
   2018     char *mod_str = NULL;
   2019     char *port_str = NULL;
   2020     char *parse_port_str;
   2021     char *start = s;
   2022     int rv = CMD_OK;
   2023     _bcm_util_gport_dest_t   gport_dest;
   2024 
   2025     if (NULL == s) {
   2026         return CMD_FAIL;
   2027     }
   2028 
   2029     str_len = sal_strlen(s) + 1;
   2030 
   2031     if (!str_len) {
   2032         return CMD_FAIL;
   2033     }
   2034     while (s[i] != '\0') {
   2035         if ((s[i] == '(') || (s[i] == '{') || (s[i] == '[')){
   2036             parse_gport_push();
   2037             /* Allocate only once - defensive check against wrong input */
   2038             if (!gport_type_str) {
   2039             gport_type_str = sal_alloc(str_len, "GPORT type string");
   2040             }
   2041             sal_strncpy(gport_type_str, start, i - start_pos);
   2042             gport_type_str[i] = '\0';
   2043             start = (s + i + 1);
   2044             start_pos = i + 1;
   2045         } else if ((s[i] == ')') || (s[i] == '}') || (s[i] == ']')){
   2046             if (parse_gport_pop()) {
   2047                 rv = CMD_FAIL;
   2048                 goto done;
   2049             }
   2050             /* Allocate only once - defensive check against wrong input */
   2051             if (!gport_val_str) {
   2052             gport_val_str = sal_alloc(str_len, "GPORT val string");
   2053             }
   2054             sal_strncpy(gport_val_str, start, i - start_pos);
   2055             gport_val_str[i - start_pos] = '\0';
   2056         } else if ((s[i] == ',') || (s[i] ==':') || (s[i] == '.') ) {
   2057             /* Allocate only once - defensive check against wrong input */
   2058             if (!mod_str) {
   2059             mod_str = sal_alloc(str_len, "Modid str");
   2060             }
   2061             sal_strncpy(mod_str, start , i - start_pos);
   2062             mod_str[i - start_pos] = '\0';
   2063             modid_len = i - start_pos;
   2064 
   2065             /* Allocate only once - defensive check against wrong input */
   2066             if (!port_str) {
   2067             port_str = sal_alloc(str_len, "Port str");
   2068             }
   2069             start_pos = i + 1;
   2070             if (start_pos >= (str_len - 2)) {
   2071                 rv = CMD_FAIL;
   2072                 goto done;
   2073             }
   2074             sal_strncpy(port_str, start + modid_len + 1, str_len - 2 - start_pos);
   2075             port_str[str_len - 2 - start_pos] = '\0';
   2076         }
   2077         i++;
   2078     }
   2079 
   2080     /* Check for redundant parentheses */
   2081     if (!parse_gport_pop()) {
   2082         rv = CMD_FAIL;
   2083         goto done;
   2084     }
   2085 
   2086     /* if not gport - don't parse */
   2087     if (NULL == gport_type_str) {
   2088         if (isint(s)) {
   2089             port_val = parse_integer(s);
   2090             if (BCM_GPORT_IS_SET(port_val)) {
   2091                 *portp = port_val;
   2092                 rv = CMD_OK;
   2093                 goto done;
   2094             } else {
   2095                 rv = CMD_FAIL;
   2096                 goto done;
   2097             }
   2098         } else {
   2099         rv = CMD_FAIL;
   2100         goto done;
   2101     }
   2102     }
   2103 
   2104     /* Initialized gport_dest structure */
   2105     sal_memset(&gport_dest, 0, sizeof(_bcm_util_gport_dest_t));
   2106 
   2107     /* Take care of GPORTS that do not need input */
   2108     if (!sal_strcasecmp(gport_type_str, "localcpu") ||
   2109         !sal_strcasecmp(gport_type_str, "lc")) {
   2110         gport_dest.gport_type = _SHR_GPORT_TYPE_LOCAL;
   2111         goto gport_done;
   2112     }
   2113     if (!sal_strcasecmp(gport_type_str, "invalid")) {
   2114         *portp = BCM_GPORT_INVALID;
   2115         goto done;
   2116     }
   2117     if (!sal_strcasecmp(gport_type_str, "blackhole") ||
   2118         !sal_strcasecmp(gport_type_str, "bh")) {
   2119         *portp = _SHR_GPORT_BLACK_HOLE;
   2120         goto done;
   2121     }
   2122 
   2123     /* Parse the input */
   2124     if (NULL == port_str) {
   2125         mod_val = -1;
   2126         parse_port_str = gport_val_str;
   2127     } else {
   2128         parse_port_str = port_str;
   2129     }
   2130 
   2131     if (mod_str && isint(mod_str)) {
   2132     mod_val = parse_integer(mod_str);
   2133     }
   2134 
   2135     if (isint(parse_port_str)) {
   2136         port_val = parse_integer(parse_port_str);
   2137     } else {
   2138         if (_parse_port(unit, parse_port_str, &port_val) < 0) {
   2139             rv = CMD_FAIL;
   2140             goto done;
   2141         }
   2142     }
   2143 
   2144     /* Take care of GPORTS that need input */
   2145     if (!sal_strcasecmp(gport_type_str, "modport") ||
   2146         !sal_strcasecmp(gport_type_str, "mp") ||
   2147         !sal_strcasecmp(gport_type_str, "egress_modport") ||
   2148         !sal_strcasecmp(gport_type_str, "emp")) {
   2149         if (mod_val < 0) {
   2150             /* If modid was not specified - use mymodid */
   2151             if (bcm_stk_my_modid_get(unit, &mod_val) < 0) {
   2152                 rv = CMD_FAIL;
   2153                 goto done;
   2154             }
   2155         }
   2156         if (port_val < 0) {
   2157             rv = CMD_FAIL;
   2158             goto done;
   2159         }
   2160         if (('e' == gport_type_str[0]) ||
   2161             ('E' == gport_type_str[0])) {
   2162             gport_dest.gport_type = _SHR_GPORT_TYPE_EGRESS_MODPORT;
   2163         } else {
   2164             gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   2165         }
   2166         gport_dest.modid = mod_val;
   2167         gport_dest.port = port_val;
   2168     }
   2169     if (!sal_strcasecmp(gport_type_str, "child") ||
   2170         !sal_strcasecmp(gport_type_str, "egress_child")) {
   2171         if (mod_val < 0) {
   2172             /* If modid was not specified, use mymodid */
   2173             if (bcm_stk_my_modid_get(unit, &mod_val) < 0) {
   2174                 rv = CMD_FAIL;
   2175                 goto done;
   2176             }
   2177         }
   2178         if (port_val < 0) {
   2179             rv = CMD_FAIL;
   2180             goto done;
   2181         }
   2182         if (('e' == gport_type_str[0]) ||
   2183             ('E' == gport_type_str[0])) {
   2184             gport_dest.gport_type = _SHR_GPORT_TYPE_EGRESS_CHILD;
   2185         } else {
   2186             gport_dest.gport_type = _SHR_GPORT_TYPE_CHILD;
   2187         }
   2188         gport_dest.gport_type = _SHR_GPORT_TYPE_CHILD;
   2189         gport_dest.modid = mod_val;
   2190         gport_dest.port = port_val;
   2191     }
   2192     if (!sal_strcasecmp(gport_type_str, "trunk")) {
   2193         gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
   2194         gport_dest.tgid = port_val;
   2195     }
   2196     if (!sal_strcasecmp(gport_type_str, "local")) {
   2197         gport_dest.gport_type = _SHR_GPORT_TYPE_LOCAL;
   2198         gport_dest.port = port_val;
   2199     }
   2200     if (!sal_strcasecmp(gport_type_str, "devport") ||
   2201         !sal_strcasecmp(gport_type_str, "dp")) {
   2202         gport_dest.gport_type = _SHR_GPORT_TYPE_DEVPORT;
   2203         gport_dest.port = port_val;
   2204     }
   2205     if (!sal_strcasecmp(gport_type_str, "mpls")) {
   2206         gport_dest.gport_type = _SHR_GPORT_TYPE_MPLS_PORT;
   2207         gport_dest.mpls_id = port_val;
   2208     }
   2209     if (!sal_strcasecmp(gport_type_str, "mim")) {
   2210         gport_dest.gport_type = _SHR_GPORT_TYPE_MIM_PORT;
   2211         gport_dest.mim_id = port_val;
   2212     }
   2213     if (!sal_strcasecmp(gport_type_str, "wlan")) {
   2214         gport_dest.gport_type = _SHR_GPORT_TYPE_WLAN_PORT;
   2215         gport_dest.wlan_id = port_val;
   2216     }
   2217     if (!sal_strcasecmp(gport_type_str, "sub")) {
   2218         gport_dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_PORT;
   2219         gport_dest.subport_id = port_val;
   2220     }
   2221     if (!sal_strcasecmp(gport_type_str, "subg")) {
   2222         gport_dest.gport_type = _SHR_GPORT_TYPE_SUBPORT_GROUP;
   2223         gport_dest.subport_group_id = port_val;
   2224     }
   2225     if (!sal_strcasecmp(gport_type_str, "vlan")) {
   2226         gport_dest.gport_type = _SHR_GPORT_TYPE_VLAN_PORT;
   2227         gport_dest.vlan_port_id = port_val;
   2228     }
   2229     if (!sal_strcasecmp(gport_type_str, "vxlan")) {
   2230         gport_dest.gport_type = _SHR_GPORT_TYPE_VXLAN_PORT;
   2231         gport_dest.vxlan_id = port_val;
   2232     }
   2233     if (!sal_strcasecmp(gport_type_str, "trill")) {
   2234         gport_dest.gport_type = _SHR_GPORT_TYPE_TRILL_PORT;
   2235         gport_dest.trill_id = port_val;
   2236     }
   2237     if (!sal_strcasecmp(gport_type_str, "niv")) {
   2238         gport_dest.gport_type = _SHR_GPORT_TYPE_NIV_PORT;
   2239         gport_dest.niv_id = port_val;
   2240     }
   2241     if (!sal_strcasecmp(gport_type_str, "l2gre")) {
   2242         gport_dest.gport_type = _SHR_GPORT_TYPE_L2GRE_PORT;
   2243         gport_dest.l2gre_id = port_val;
   2244     }
   2245     if (!sal_strcasecmp(gport_type_str, "extender")) {
   2246         gport_dest.gport_type = _SHR_GPORT_TYPE_EXTENDER_PORT;
   2247         gport_dest.extender_id = port_val;
   2248     }
   2249 
   2250 gport_done:
   2251     rv = _bcm_util_gport_construct(unit, &gport_dest, portp);
   2252 done:
   2253     if (mod_str) {
   2254         sal_free(mod_str);
   2255     }
   2256     if (port_str) {
   2257         sal_free(port_str);
   2258     }
   2259     if (gport_type_str) {
   2260     sal_free(gport_type_str);
   2261     }
   2262     if (gport_val_str) {
   2263         sal_free(gport_val_str);
   2264     }
   2265 
   2266     return rv;
   2267 }
   2268 #endif
   2269 
   2270 int
   2271 parse_port(int unit, char *s, soc_port_t *portp)
   2272 {
   2273 #if defined(BCM_ESW_SUPPORT)
   2274     /* First try to parse a string as a GPORT identifier */
   2275     if (!parse_gport(unit, s, portp)) {
   2276         /* If Success we done */
   2277         return 0;
   2278     }
   2279 #endif
   2280     /* If parse_gport failed, try to parse the old way */
   2281     return _parse_port(unit, s, portp);
   2282 }
   2283 
   2284 int
   2285 parse_bcm_port(int unit, char *s, bcm_port_t *portp)
   2286 {
   2287     int rv = parse_port(unit, s, (soc_port_t *)portp);
   2288 
   2289     BCM_API_XLATE_PORT_P2A(unit, portp);
   2290 
   2291     return rv;
   2292 }
   2293 
   2294 /* PQ_MOD_PORT parsing:  PQ_MOD_PORT |= <mod>.<port> | PQ_PORT */
   2295 
   2296 int
   2297 parse_mod_port(int unit, char *str, bcm_mod_port_t *mp)
   2298 {
   2299     int mod, port;
   2300     char *cur_ptr = str;
   2301 
   2302     if (isdigit((unsigned)*cur_ptr)) {
   2303         mod = 0;
   2304         do {
   2305             mod = mod * 10 + (*cur_ptr++ - '0');
   2306         } while (isdigit((unsigned) *cur_ptr));
   2307         if (*cur_ptr == '.') {  /* Parse port portion; else call parse_port */
   2308             cur_ptr++;
   2309             if (isdigit((unsigned)*cur_ptr)) {
   2310                 port = 0;
   2311                 do {
   2312                     port = port * 10 + (*cur_ptr++ - '0');
   2313                 } while (isdigit((unsigned) *cur_ptr));
   2314                 if (*cur_ptr == '\0') {
   2315                     mp->mod = mod;
   2316                     mp->port = port;
   2317                     return 0;  /* Looks good */
   2318                 }
   2319             }
   2320         }
   2321     }
   2322 
   2323     /* If we get here, wasn't of form <mod>.<port> */
   2324     mp->mod = -1;
   2325     return parse_port(unit, str, &mp->port);
   2326 }
   2327 
   2328 void
   2329 dump_l2_addr(int unit, char *pfx, bcm_l2_addr_t *l2addr)
   2330 {
   2331     char                pfmt[SOC_PBMP_FMT_LEN];
   2332     char                bmstr[FORMAT_PBMP_MAX];
   2333     bcm_module_t        local_modid;
   2334 #ifdef BCM_ESW_SUPPORT
   2335     _bcm_l2_gport_params_t  gport_params;
   2336     char                gpfmt[FORMAT_GPORT_MAX];
   2337 #endif
   2338     int                 islocal;
   2339 
   2340     if (bcm_stk_my_modid_get(unit, &local_modid) != BCM_E_NONE) {
   2341         local_modid = -1;
   2342     }
   2343 
   2344     cli_out("%smac=%02x:%02x:%02x:%02x:%02x:%02x vlan=%d GPORT=0x%x",
   2345             pfx,
   2346             l2addr->mac[0], l2addr->mac[1], l2addr->mac[2],
   2347             l2addr->mac[3], l2addr->mac[4], l2addr->mac[5],
   2348             l2addr->vid, l2addr->port);
   2349 
   2350 #ifdef BCM_ESW_SUPPORT
   2351     if (!SOC_IS_ARAD(unit) && BCM_GPORT_IS_SET(l2addr->port)) {
   2352         if (BCM_FAILURE(_bcm_esw_l2_gport_parse(unit, l2addr, &gport_params))) {
   2353             cli_out("Unknown GPORT 0x%x \n", l2addr->port);
   2354             return;
   2355         }
   2356 #define L2_ADDR_GPORT_FORMAT_PRINT(_fmt, _gport) \
   2357         cli_out(" port=%s", format_gport(_fmt, _gport))
   2358         switch (gport_params.type) {
   2359         case _SHR_GPORT_TYPE_MPLS_PORT:
   2360         case _SHR_GPORT_TYPE_WLAN_PORT:
   2361         case _SHR_GPORT_TYPE_MIM_PORT:
   2362         case _SHR_GPORT_TYPE_TRILL_PORT:
   2363         case _SHR_GPORT_TYPE_SUBPORT_GROUP:
   2364         case _SHR_GPORT_TYPE_SUBPORT_PORT:
   2365         case _SHR_GPORT_TYPE_VLAN_PORT:
   2366         case _SHR_GPORT_TYPE_NIV_PORT:
   2367         case _SHR_GPORT_TYPE_L2GRE_PORT:
   2368         case _SHR_GPORT_TYPE_VXLAN_PORT:
   2369         case _SHR_GPORT_TYPE_FLOW_PORT:
   2370         case _SHR_GPORT_TYPE_EXTENDER_PORT:
   2371         case _SHR_GPORT_TYPE_BLACK_HOLE:
   2372             L2_ADDR_GPORT_FORMAT_PRINT(gpfmt, l2addr->port);
   2373             break;
   2374         case _SHR_GPORT_TYPE_TRUNK:
   2375             l2addr->tgid = gport_params.param0;
   2376             l2addr->flags |= BCM_L2_TRUNK_MEMBER;
   2377             break;
   2378         case _SHR_GPORT_TYPE_MODPORT:
   2379             l2addr->port = gport_params.param0;
   2380             l2addr->modid = gport_params.param1;
   2381             break;
   2382         case _SHR_GPORT_TYPE_LOCAL_CPU:
   2383             l2addr->port = gport_params.param0;
   2384             l2addr->modid = local_modid;
   2385             break;
   2386         default:
   2387             cli_out("Unknown GPORT format \n");
   2388             return;
   2389         }
   2390 #undef L2_ADDR_GPORT_FORMAT_PRINT
   2391     }
   2392     if (SOC_IS_ESW(unit)) {
   2393         (void)_bcm_esw_modid_is_local(unit, l2addr->modid, &islocal);
   2394     } else
   2395 #endif /* BCM_ESW_SUPPORT */
   2396     {
   2397         islocal = (l2addr->modid == local_modid) ? TRUE : FALSE;
   2398     }
   2399 
   2400     if (l2addr->flags & BCM_L2_TRUNK_MEMBER) {
   2401         cli_out(" Trunk=%d", l2addr->tgid);
   2402     } else if (!BCM_GPORT_IS_SET(l2addr->port)) {
   2403         cli_out(" modid=%d port=%d%s%s", l2addr->modid, l2addr->port,
   2404                 (islocal == TRUE) ? "/" : " ",
   2405                 (islocal == TRUE) ?
   2406                 mod_port_name(unit, l2addr->modid, l2addr->port) : " ");
   2407     }
   2408 
   2409     if (l2addr->flags & BCM_L2_STATIC) {
   2410         cli_out(" Static");
   2411     }
   2412 
   2413     if (l2addr->flags & BCM_L2_HIT) {
   2414         cli_out(" Hit");
   2415     }
   2416 
   2417     if (l2addr->cos_src != 0 || l2addr->cos_dst != 0) {
   2418             cli_out(" COS(src=%d,dst=%d)", l2addr->cos_src, l2addr->cos_dst);
   2419     }
   2420 
   2421     if (l2addr->flags & BCM_L2_COS_SRC_PRI) {
   2422         cli_out(" SCP");
   2423     }
   2424 
   2425     if (l2addr->flags & BCM_L2_COPY_TO_CPU) {
   2426         cli_out(" CPU");
   2427     } else if((l2addr->port == CMIC_PORT(unit)) && islocal) {
   2428         if(!(l2addr->flags & (BCM_L2_L3LOOKUP | BCM_L2_TRUNK_MEMBER))) {
   2429             cli_out(" CPU");
   2430         }
   2431     }
   2432 
   2433     if (l2addr->flags & BCM_L2_MIRROR) {
   2434         cli_out(" Mirror");
   2435     }
   2436 
   2437     if (l2addr->flags & BCM_L2_L3LOOKUP) {
   2438         cli_out(" L3");
   2439     }
   2440 
   2441     if (l2addr->flags & BCM_L2_DISCARD_SRC) {
   2442         cli_out(" DiscardSrc");
   2443     }
   2444 
   2445     if (l2addr->flags & BCM_L2_DISCARD_DST) {
   2446         cli_out(" DiscardDest");
   2447     }
   2448 
   2449     if (l2addr->flags & BCM_L2_PENDING) {
   2450         cli_out(" Pending");
   2451     }
   2452 
   2453     if (SOC_IS_XGS3_SWITCH(unit)) {
   2454         if (l2addr->flags & BCM_L2_SETPRI) {
   2455             cli_out(" ReplacePriority");
   2456         }
   2457     }
   2458 
   2459     if (l2addr->flags & BCM_L2_MCAST) {
   2460         cli_out(" MCast=%d", l2addr->l2mc_group);
   2461     }
   2462 
   2463     if (SOC_PBMP_NOT_NULL(l2addr->block_bitmap)) {
   2464         format_pbmp(unit, bmstr, sizeof (bmstr), l2addr->block_bitmap);
   2465         cli_out(" MAC blocked port bitmap=%s: %s",
   2466                 SOC_PBMP_FMT(l2addr->block_bitmap, pfmt), bmstr);
   2467     }
   2468 
   2469     if (l2addr->group) {
   2470         cli_out(" Group=%d", l2addr->group);
   2471     }
   2472 #ifdef BCM_PETRA_SUPPORT
   2473         if(SOC_IS_ARAD(unit)) {
   2474 			cli_out(" encap_id=0x%x", l2addr->encap_id);
   2475 		}
   2476 #endif
   2477     cli_out("\n");
   2478 }
   2479 
   2480 void
   2481 dump_l2_cache_addr(int unit, char *pfx, bcm_l2_cache_addr_t *l2caddr)
   2482 {
   2483     cli_out("%smac=%02x:%02x:%02x:%02x:%02x:%02x",
   2484             pfx,
   2485             l2caddr->mac[0], l2caddr->mac[1], l2caddr->mac[2],
   2486             l2caddr->mac[3], l2caddr->mac[4], l2caddr->mac[5]);
   2487 
   2488     if (!ENET_MACADDR_BROADCAST(l2caddr->mac_mask)) {
   2489         cli_out("/%02x:%02x:%02x:%02x:%02x:%02x",
   2490                 l2caddr->mac_mask[0], l2caddr->mac_mask[1], l2caddr->mac_mask[2],
   2491                 l2caddr->mac_mask[3], l2caddr->mac_mask[4], l2caddr->mac_mask[5]);
   2492     }
   2493 
   2494     cli_out(" vlan=%d", l2caddr->vlan);
   2495     if (l2caddr->vlan_mask != BCM_L2_VID_MASK_ALL) {
   2496         cli_out("/0x%03x", l2caddr->vlan_mask);
   2497     }
   2498 
   2499     if (l2caddr->src_port_mask != 0) {
   2500         cli_out(" srcport=%d", l2caddr->src_port);
   2501         if (l2caddr->src_port_mask != BCM_L2_SRCPORT_MASK_ALL) {
   2502             cli_out("/0x%02x", l2caddr->src_port_mask);
   2503         }
   2504     }
   2505 
   2506     if (l2caddr->flags & BCM_L2_CACHE_TRUNK) {
   2507         cli_out(" trunk=%d", l2caddr->dest_trunk);
   2508     } else {
   2509         cli_out(" modid=%d port=%d/%s",
   2510                 l2caddr->dest_modid,
   2511                 l2caddr->dest_port,
   2512                 mod_port_name(unit, l2caddr->dest_modid,  l2caddr->dest_port));
   2513     }
   2514 
   2515     if (l2caddr->flags & BCM_L2_CACHE_SETPRI) {
   2516         cli_out(" prio=%d", l2caddr->prio);
   2517     }
   2518 
   2519     if (l2caddr->flags & BCM_L2_CACHE_BPDU) {
   2520         cli_out(" BPDU");
   2521     }
   2522 
   2523     if ((l2caddr->flags & BCM_L2_CACHE_CPU) ||
   2524         (l2caddr->dest_port == CMIC_PORT(unit))) {
   2525         cli_out(" CPU");
   2526     }
   2527 
   2528     if (l2caddr->flags & BCM_L2_CACHE_L3) {
   2529         cli_out(" L3");
   2530     }
   2531 
   2532     if (l2caddr->flags & BCM_L2_CACHE_DISCARD) {
   2533         cli_out(" Discard");
   2534     }
   2535 
   2536     if (l2caddr->flags & BCM_L2_CACHE_MIRROR) {
   2537         cli_out(" Mirror");
   2538     }
   2539 
   2540     if (SOC_IS_XGS3_SWITCH(unit)) {
   2541         if (l2caddr->flags & BCM_L2_CACHE_SETPRI) {
   2542             cli_out(" ReplacePriority");
   2543         }
   2544     }
   2545 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
   2546     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_TRX(unit)) {
   2547         if (l2caddr->flags & BCM_L2_CACHE_LEARN_DISABLE) {
   2548             cli_out(" LearnDisable");
   2549         }
   2550     }
   2551 #endif /* BCM_FIREBOLT2_SUPPORT */
   2552 
   2553 #if defined(BCM_TRX_SUPPORT)
   2554     if (SOC_IS_TRX(unit)) {
   2555         cli_out(" lookup_class =%d", l2caddr->lookup_class);
   2556     }
   2557 #endif /* BCM_TRX_SUPPORT */
   2558     if (l2caddr->flags & BCM_L2_CACHE_PROTO_PKT) {
   2559         cli_out(" ProtocolPkt");
   2560     }
   2561 
   2562      cli_out("\n");
   2563 }
   2564 
   2565 /*
   2566  * Format a pbmp into a string, the opposite of what parse_pbmp does.
   2567  * For example, 0x00ffffff ==> "fe"; 0x0b000007 ==> "cpu,ge,fe0-fe2".
   2568  * For clarity, returns "ge,fe" instead of "e" (or on GSL, just "ge"),
   2569  * and returns "cpu,ge,fe" instead of "all" (or on GSL, just "cpu,ge").
   2570  */
   2571 
   2572 STATIC void
   2573 _format_pbmp_type(int unit,
   2574                   char *dest,
   2575                   int bufsize,
   2576                   soc_pbmp_t pbmp,
   2577                   char *pname,
   2578                   soc_pbmp_t pall)
   2579 {
   2580     soc_pbmp_t  bm;
   2581     soc_port_t  tport, port, dport, pfirst, plast;
   2582     int size = 0;
   2583 
   2584     if (SOC_PBMP_IS_NULL(pall)) {       /* no such ports */
   2585         return;
   2586     }
   2587 
   2588     SOC_PBMP_ASSIGN(bm, pbmp);
   2589     SOC_PBMP_AND(bm, pall);
   2590     if (SOC_PBMP_EQ(bm, pall)) {        /* all ports of this type */
   2591         size = sal_strlen(dest);
   2592         assert((bufsize - size) >= 0);
   2593         sal_snprintf(dest + size,(bufsize - size), ",%s", pname);
   2594         return;
   2595     }
   2596     /*
   2597      * The slightly tricky thing here is handling sparse sets of
   2598      * bits in pall (on Tucana or Herc4 for example).
   2599      */
   2600     pfirst = plast = -1;
   2601     port = -1;
   2602     /* coverity[overrun-local] */
   2603     DPORT_SOC_PBMP_ITER(unit, pall, dport, tport) {        /* a subset of ports */
   2604         port += 1;
   2605         /* coverity[overrun-local] */
   2606         if (SOC_PBMP_MEMBER(pbmp, tport)) {
   2607             if (pfirst < 0) {
   2608                 pfirst = plast = (SOC_IS_DPP(unit)
   2609 #ifdef BCM_DNX_SUPPORT
   2610                                 || SOC_IS_DNX(unit)
   2611 #endif
   2612 #ifdef BCM_DNF_SUPPORT
   2613                                 || SOC_IS_DNXF(unit)
   2614 #endif
   2615                                  )?dport:DPORT_FROM_DPORT_INDEX(unit, dport, port);
   2616             } else {
   2617                 plast = (SOC_IS_DPP(unit)
   2618 #ifdef BCM_DNX_SUPPORT
   2619                         || SOC_IS_DNX(unit)
   2620 #endif
   2621 #ifdef BCM_DNF_SUPPORT
   2622                         || SOC_IS_DNXF(unit)
   2623 #endif
   2624                         )?dport:DPORT_FROM_DPORT_INDEX(unit, dport, port);
   2625             }
   2626             continue;
   2627         }
   2628         if (pfirst >= 0) {
   2629             size = sal_strlen(dest);
   2630             assert((bufsize - size) >= 0);
   2631             sal_snprintf(dest + sal_strlen(dest), (bufsize - size), ",%s%d", pname, pfirst);
   2632             if (pfirst != plast) {
   2633                 size = sal_strlen(dest);
   2634                 assert((bufsize - size) >= 0);
   2635                 sal_snprintf(dest + sal_strlen(dest), (bufsize - size), "-%s%d", pname, plast);
   2636             }
   2637             pfirst = plast = -1;
   2638         }
   2639     }
   2640 
   2641     if (pfirst >= 0) {
   2642         size = sal_strlen(dest);
   2643         assert((bufsize - size) >= 0);
   2644         sal_snprintf(dest + sal_strlen(dest), (bufsize - size), ",%s%d", pname, pfirst);
   2645         if (pfirst != plast) {
   2646             size = sal_strlen(dest);
   2647             assert((bufsize - size) >= 0);
   2648             sal_snprintf(dest + sal_strlen(dest), (bufsize - size), "-%s%d", pname, plast);
   2649         }
   2650     }
   2651 }
   2652 
   2653 char *
   2654 format_pbmp(int unit, char *buf, int bufsize, soc_pbmp_t pbmp)
   2655 {
   2656     char        tmp[FORMAT_PBMP_MAX];
   2657     soc_pbmp_t  tpbm;
   2658 
   2659     SOC_PBMP_ASSIGN(tpbm, pbmp);
   2660     SOC_PBMP_REMOVE(tpbm, PBMP_ALL(unit));
   2661     if (SOC_PBMP_NOT_NULL(tpbm)) {
   2662         sal_strncpy(buf, SOC_PBMP_FMT(pbmp, tmp), bufsize);
   2663     } else if (SOC_PBMP_IS_NULL(pbmp)) {
   2664         /*
   2665          * COVERITY
   2666          *
   2667          * Handled below
   2668          */
   2669         /*    coverity[buffer_size]    */
   2670         sal_strncpy(buf, "none", bufsize);
   2671         if (bufsize < 5) {
   2672             /* Guarantee null termination of buf */
   2673             buf[bufsize - 1] = 0;
   2674         }
   2675     } else {
   2676         if (SOC_PBMP_MEMBER(pbmp, CMIC_PORT(unit)) != 0) {
   2677             /* Coverity[secure_coding] */
   2678             sal_strcpy(tmp, ",cpu");
   2679         } else {
   2680             tmp[0] = tmp[1] = 0;
   2681         }
   2682 
   2683         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "cd", PBMP_CDE_ALL(unit));
   2684 
   2685         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "ce", PBMP_CE_ALL(unit));
   2686         if(SOC_IS_SAND(unit)) {
   2687             _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "xl", PBMP_XL_ALL(unit));
   2688         }
   2689         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "fe", PBMP_FE_ALL(unit));
   2690         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "ge", PBMP_GE_ALL(unit));
   2691         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "xe", PBMP_XE_ALL(unit));
   2692         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "hg", PBMP_HG_ALL(unit));
   2693         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "spi", PBMP_SPI_ALL(unit));
   2694         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "sci", PBMP_SCI_ALL(unit));
   2695         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "sfi", PBMP_SFI_ALL(unit));
   2696         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "spi_s", PBMP_SPI_SUBPORT_ALL(unit));
   2697         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "hg_s", PBMP_HG_SUBPORT_ALL(unit));
   2698         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "il", PBMP_IL_ALL(unit));
   2699         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "qsgmii", PBMP_QSGMII_ALL(unit));
   2700         _format_pbmp_type(unit, tmp, FORMAT_PBMP_MAX, pbmp, "roe", PBMP_CPRI_ALL(unit));
   2701         sal_strncpy(buf, tmp + 1, bufsize);
   2702     }
   2703     return buf;
   2704 }
   2705 
   2706 char *
   2707 format_bcm_pbmp(int unit, char *buf, int bufsize, bcm_pbmp_t pbmp)
   2708 {
   2709     pbmp_t      tpbm;
   2710 
   2711     SOC_PBMP_ASSIGN(tpbm, pbmp);
   2712     BCM_API_XLATE_PORT_PBMP_A2P(unit, &tpbm);
   2713     return format_pbmp(unit, buf, bufsize, tpbm);
   2714 }
   2715 
   2716 char *
   2717 bcm_port_name(int unit, int port)
   2718 {
   2719     char *name = NULL;
   2720 
   2721     BCM_API_XLATE_PORT_A2P(unit, &port);
   2722     if (SOC_PORT_VALID_RANGE(unit, port)) {
   2723         name = SOC_PORT_NAME(unit, port);
   2724     }
   2725     if (name == NULL) {
   2726         name = "<unknown>";
   2727     }
   2728     return name;
   2729 }
   2730 
   2731 char *
   2732 mod_port_name(int unit, int modid, int port)
   2733 {
   2734     bcm_gport_t gport;
   2735     bcm_port_t local_port;
   2736 
   2737     if (BCM_GPORT_IS_SET(port)) {
   2738 	/* If port is already a gport, no conversion necessary */
   2739         gport = port;
   2740     } else {
   2741 	/* else convert modid/port to gport */
   2742         BCM_GPORT_MODPORT_SET(gport, modid, port);
   2743     }
   2744     if (BCM_SUCCESS(bcm_port_local_get(unit, gport, &local_port))) {
   2745         return bcm_port_name(unit, local_port);
   2746     }
   2747     return "";
   2748 }
   2749 
   2750 /*
   2751  * Parse a string containing a range of COS's.
   2752  * The input format is:
   2753  *
   2754  *      COS_RANGE       : COS '-' COS           { return $1 .. $2; }
   2755  *                      | COS                   { return $1 .. $1; }
   2756  *                      | {NULL} | '' | 'ALL'   { return 0 .. NUM_COS - 1; }
   2757  *                      ;
   2758  *              COS     : INTEGER{NUM_COS}      { return $1; }
   2759  *                      ;
   2760  */
   2761 
   2762 int
   2763 parse_num_range(int unit, char *s, int *min, int *max, int legal_min,
   2764                 int legal_max)
   2765 {
   2766     if (s == 0 || *s == 0 || sal_strcasecmp(s, "all") == 0) {
   2767         *min = legal_min;
   2768         *max = legal_max;
   2769         return 0;
   2770     }
   2771 
   2772     if ((*min = *s++ - '0') < legal_min || *min > legal_max) {
   2773         return -1;
   2774     }
   2775 
   2776     if (*s == 0) {
   2777         *max = *min;
   2778         return 0;
   2779     }
   2780 
   2781     if (*s++ != '-') {
   2782         return -1;
   2783     }
   2784 
   2785     if ((*max = *s++ - '0') > legal_max) {
   2786         return -1;
   2787     }
   2788 
   2789     return (*s == 0 && *max >= *min) ? 0 : -1;
   2790 }
   2791 
   2792 int
   2793 diag_parse_range(char *low, char *high,
   2794                  int *min, int *max,
   2795                  int legal_min, int legal_max)
   2796 {
   2797     if (low == 0 || *low == 0 || sal_strcasecmp(low, "all") == 0) {
   2798         *min = legal_min;
   2799         *max = legal_max;
   2800         return 0;
   2801     }
   2802 
   2803     *min = sal_strtoul(low, NULL, 0);
   2804 
   2805     if ((*min < legal_min) || *min > legal_max) {
   2806         return -1;
   2807     }
   2808 
   2809     if (high == 0 || *high == 0) {
   2810         *max = *min;
   2811         return 0;
   2812     }
   2813 
   2814     *max = sal_strtoul(high, NULL, 0);
   2815 
   2816     if (*max < *min || *max > legal_max) {
   2817         return -1;
   2818     }
   2819 
   2820     return 0;
   2821 }
   2822 
   2823 /*
   2824  * Utility routine for parse_block_range
   2825  */
   2826 
   2827 STATIC int
   2828 _parse_block(int unit, soc_block_types_t block_types, char **s, int *nump)
   2829 {
   2830     char        *sblk, *snum;
   2831     int         blk, num;
   2832     int         i, phy_port;
   2833     soc_block_t blktype;
   2834     soc_block_name_t *blk_names;
   2835     int         port_num_blktype;
   2836 
   2837     {
   2838 #if defined(BCM_SAND_SUPPORT)
   2839         if (SOC_IS_SAND(unit)) {
   2840             blk_names = soc_dpp_block_names;
   2841         }
   2842         else
   2843 #endif
   2844         {
   2845             blk_names = soc_block_names;
   2846         }
   2847     }
   2848 
   2849     if (sal_strncasecmp("PORT_GROUP", *s, sizeof("PORT_GROUP") - 1) == 0) {
   2850         switch ((*s)[sizeof("PORT_GROUP") - 1]) {
   2851         case '4':
   2852             blktype = SOC_BLK_PORT_GROUP4;
   2853             break;
   2854         case '5':
   2855             blktype = SOC_BLK_PORT_GROUP5;
   2856             break;
   2857         default:
   2858             return -1;
   2859         }
   2860         switch ((*s)[sizeof("PORT_GROUP*_") - 1]) {
   2861         case 'X':
   2862         case 'x':
   2863             num = 0;
   2864             break;
   2865         case 'Y':
   2866         case 'y':
   2867             num = 1;
   2868             break;
   2869         default:
   2870             return -1;
   2871         }
   2872         SOC_BLOCK_ITER(unit, blk, blktype) {
   2873             if (SOC_BLOCK_INFO(unit, blk).number == num) {
   2874                 *s += sizeof("PORT_GROUP*_*") - 1;
   2875                 return blk;
   2876             }
   2877         }
   2878         return -1;
   2879     }
   2880 
   2881     /* To cover for Apache XLPORTB0 and CLG2PORT blocks  */
   2882     if ((sal_strncasecmp("XLB0PORT", *s, (sizeof("XLB0PORT") - 1)) == 0) ||
   2883         (sal_strncasecmp("CLG2PORT", *s, (sizeof("CLG2PORT") - 1)) == 0)) {
   2884         sblk = *s + 8;
   2885     } else {
   2886         /* find the last "number" during string "s"
   2887            ex. s = "pgw_ge8p2" ==> sblk = "2"
   2888          */
   2889         int index = sal_strlen(*s);
   2890 
   2891         sblk = &((*s)[index]);
   2892         while ((index-1) >= 0 &&
   2893                ((*s)[index-1] >= '0' && (*s)[index-1] <= '9')) {
   2894             sblk--;
   2895             index--;
   2896         }
   2897     }
   2898 
   2899     /* skip past prefix */
   2900     num = 0;
   2901     snum = sblk;
   2902     while (*snum && *snum >= '0' && *snum <= '9') {
   2903         num = (num * 10) + (*snum - '0');
   2904         snum++;
   2905     }
   2906 
   2907     /* try to match a port name before we split the prefix */
   2908     PBMP_ALL_ITER(unit, i) {
   2909         if (sal_strncasecmp(SOC_PORT_NAME(unit, i), *s, snum-*s) == 0) {
   2910             *s = snum;
   2911             if (soc_feature(unit, soc_feature_logical_port_num)) {
   2912                 phy_port = SOC_INFO(unit).port_l2p_mapping[i];
   2913             } else {
   2914                 phy_port = i;
   2915             }
   2916 
   2917             port_num_blktype = SOC_DRIVER(unit)->port_num_blktype > 1 ?
   2918                 SOC_DRIVER(unit)->port_num_blktype : 1;
   2919             if (port_num_blktype > 1) {
   2920                 for (i = 0; i <  port_num_blktype; i++) {
   2921                     blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i);
   2922                     if (blk < 0) {
   2923                         break;
   2924                     }
   2925                     if (SOC_BLOCK_IN_LIST(block_types,
   2926                                           SOC_BLOCK_TYPE(unit, blk))) {
   2927                         return blk;
   2928                     }
   2929                 }
   2930                 return -1;
   2931             } else {
   2932                 return SOC_PORT_BLOCK(unit, phy_port);
   2933             }
   2934         }
   2935     }
   2936 
   2937     *sblk = '\0';
   2938     sblk = *s;
   2939     *s = snum;
   2940 
   2941     if (*sblk == '\0') {        /* just digits */
   2942         if (nump == NULL) {
   2943             return -1;
   2944         }
   2945         *nump = num;
   2946         return 0;
   2947     }
   2948 
   2949     /* try to match a block name */
   2950     for (i = 0; blk_names[i].blk != SOC_BLK_NONE; i++) {
   2951         if (sal_strcasecmp(blk_names[i].name, sblk) == 0) {
   2952             blktype = blk_names[i].blk;
   2953             SOC_BLOCK_ITER(unit, blk, blktype) {
   2954                 if (SOC_BLOCK_INFO(unit, blk).number == num) {
   2955                     return blk;
   2956                 }
   2957             }
   2958             return -1;
   2959         }
   2960     }
   2961 
   2962     return -1;
   2963 }
   2964 
   2965 /*
   2966  * Parse a string containing a range of StrataSwitch internal blocks.
   2967  * The input format is:
   2968  *
   2969  *      BLK_RANGE   : BLOCK '-' BLOCK   { return $1 .. $2; }
   2970  *                  | BLOCK             { return $1 .. $1; }
   2971  *                  | 'E'               { return MIN_EPIC .. MAX_EPIC; }
   2972  *                  | 'G'               { return MIN_GPIC .. MAX_GPIC; }
   2973  *                  | 'H'               { return MIN_HPIC .. MAX_HPIC; }
   2974  *                  | 'ALL'             { return MIN_EPIC .. MAX_GPIC; }
   2975  *                  ;
   2976  *      BLOCK       : INTEGER{NUM_PIC}          { return $1; }
   2977  *                  | 'E' INTEGER{NUM_EPIC}     { return MIN_EPIC + $1; }
   2978  *                  | 'G' INTEGER{NUM_GPIC}     { return MIN_GPIC + $1; }
   2979  *                  | 'H' INTEGER{NUM_GPIC}     { return MIN_HPIC + $1; }
   2980  *                  ;
   2981  */
   2982 
   2983 int
   2984 parse_block_range(int unit,
   2985                   soc_block_types_t regtype,
   2986                   char *s,
   2987                   int *min,
   2988                   int *max,
   2989                   soc_block_types_t mask)
   2990 {
   2991     int i, nummin, nummax;
   2992     int matched, blk, idx = 0;
   2993     soc_block_name_t *blk_port_names;
   2994     soc_block_name_t *blk_names;
   2995 
   2996     {
   2997 #if defined(BCM_SAND_SUPPORT)
   2998         if (SOC_IS_SAND(unit)) {
   2999             blk_names = soc_dpp_block_names;
   3000             blk_port_names = soc_dpp_block_port_names;
   3001         }
   3002         else
   3003 #endif
   3004         {
   3005             blk_names = soc_block_names;
   3006             blk_port_names = soc_block_port_names;
   3007         }
   3008     }
   3009 
   3010     *min = 0;
   3011     *max = SOC_INFO(unit).block_num;
   3012 
   3013     /* empty string: all blocks */
   3014     if (s == NULL || *s == '\0') {
   3015         return 0;
   3016     }
   3017 
   3018     /* all blocks */
   3019     if (sal_strcasecmp(s, "all") == 0 || sal_strcasecmp(s, "*") == 0) {
   3020         return 0;
   3021     }
   3022 
   3023     /* all blocks of a certain type */
   3024     for (i = 0; blk_names[i].blk != SOC_BLK_NONE; i++) {
   3025         if (sal_strcasecmp(blk_names[i].name, s) == 0) {
   3026             mask[0] = blk_names[i].blk;
   3027             return 0;
   3028         }
   3029     }
   3030 
   3031     if (SOC_IS_ESW(unit)) {
   3032         /* all blocks of a certain port type */
   3033         /* (remember, hg matches hpic and ipic) */
   3034         matched = 0;
   3035         for (i = 0; blk_port_names[i].blk != SOC_BLK_NONE; i++) {
   3036             if (sal_strcasecmp(blk_port_names[i].name, s) == 0) {
   3037                 mask[idx] = blk_port_names[i].blk;
   3038                 matched += 1;
   3039                 idx++;
   3040             }
   3041         }
   3042         if (matched) {
   3043             return 0;
   3044         }
   3045     }
   3046 
   3047     nummin = -1;
   3048     if ((*min = _parse_block(unit, regtype, &s, &nummin)) < 0) {
   3049         return -1;
   3050     }
   3051 
   3052     if (*s == '\0') {
   3053         if (nummin < 0) {
   3054             *max = *min;
   3055             return 0;
   3056         }
   3057         /* find the nummin'th port block */
   3058         matched = -1;
   3059         SOC_BLOCK_ITER(unit, blk, SOC_BLK_PORT) {
   3060             matched += 1;
   3061             if (matched == nummin) {
   3062                 *max = *min = blk;
   3063                 return 0;
   3064             }
   3065         }
   3066         return -1;
   3067     }
   3068 
   3069     if (*s++ != '-') {
   3070         return -1;
   3071     }
   3072 
   3073     nummax = -1;
   3074     if ((*max = _parse_block(unit, regtype, &s, &nummax)) < 0) {
   3075         return -1;
   3076     }
   3077     if (*s != '\0') {
   3078         return -1;
   3079     }
   3080     if ((nummin >= 0 && nummax < 0) || (nummin < 0 && nummax >= 0)) {
   3081         return -1;
   3082     }
   3083     if (nummin < 0 && nummax < 0) {
   3084         if (*min > *max) {
   3085             return -1;
   3086         }
   3087         return 0;
   3088     }
   3089     if (nummin > nummax) {
   3090         return -1;
   3091     }
   3092     /* find the nummin'th through nummax'th blocks */
   3093     matched = -1;
   3094     SOC_BLOCK_ITER(unit, blk, SOC_BLK_PORT) {
   3095         matched += 1;
   3096         if (matched == nummin) {
   3097             *min = blk;
   3098         }
   3099         if (matched == nummax) {
   3100             *max = blk;
   3101             return 0;
   3102         }
   3103     }
   3104     return -1;
   3105 }
   3106 
   3107 /*
   3108  * Parse a CMIC register name and return offset.  Matching is
   3109  * case-insensitive and works with or without the "CMIC_" prefix.  Also
   3110  * accepts address offset as an integer in hex or decimal.
   3111  */
   3112 
   3113 int
   3114 parse_cmic_regname(int unit, char *name, uint32 *offset_ptr)
   3115 {
   3116 
   3117 #if defined(BCM_ESW_SUPPORT) || defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT)
   3118     if (isint(name)) {
   3119         *offset_ptr = parse_integer(name);
   3120         return 0;       /* Success */
   3121     }
   3122 #ifdef BCM_CMICM_SUPPORT
   3123     if(soc_feature(unit, soc_feature_cmicm)) {
   3124         char *s;
   3125         int i;
   3126         soc_cmicm_reg_t *creg;
   3127         for (i = 0; i < NUM_CMICM_REGS; i++) {
   3128             creg = soc_cmicm_reg_get(i);
   3129             s = creg->name;
   3130             if (sal_strcasecmp(name, s) == 0 || sal_strcasecmp(name, s + 5) == 0) {
   3131                 *offset_ptr = creg->addr;
   3132                 return 0;
   3133             }
   3134         }
   3135         return -1;
   3136     }
   3137 #endif
   3138 
   3139 #ifdef BCM_CMICX_SUPPORT
   3140     if(soc_feature(unit, soc_feature_cmicx)) {
   3141         return(soc_parse_cmicx_regname(unit, name, offset_ptr));
   3142     }
   3143 #endif
   3144 
   3145     for (*offset_ptr = 0; *offset_ptr <= 0x10000; (*offset_ptr) += 4) {
   3146         char *s = soc_pci_off2name(unit, *offset_ptr);
   3147         if (sal_strcasecmp(name, s) == 0 || sal_strcasecmp(name, s + 5) == 0)
   3148             return 0;   /* Success */
   3149     }
   3150 #endif
   3151     return -1;
   3152 }
   3153 
   3154 /*
   3155  * Look up a table memory by user-friendly name.
   3156  * On success, stores result and returns 0.  On failure, returns -1.
   3157  *
   3158  * A memory array index may be added after the memory name in square brackets like: mem[3].
   3159  * The function will fail for memory arrays for which an array index
   3160  * is not specified when array_index is non-NULL.
   3161  * The function will fail for non array memories for which an array index is specified.
   3162  * For non array memories, array_index may be NULL; If not Null 0 will be returned in it.
   3163  *
   3164  * A table copy number may be appended to the table name following a
   3165  * period, e.g. "mcast.2".  If so, this value is returned in the copyno
   3166  * parameter.  If not, COPYNO_ALL is returned in the copyno parameter.
   3167  * If copyno is NULL, an appended copy number causes a syntax error.
   3168  *
   3169  * Also accepts suffixes .E0-E2 and .G0-G1 for StrataSwitch
   3170  * Also accepts suffixes .G0-.G11 and .H0 for Draco
   3171  * Also accepts suffixes .H0-H7 for Hercules
   3172  */
   3173 
   3174 int
   3175 parse_memory_name(int unit, soc_mem_t *result, char *str, int *copyno, unsigned *array_index)
   3176 {
   3177     soc_mem_t   mem;
   3178     int         blk, numblk, matched;
   3179     char        *cp, *aip, tmp[80];
   3180     uint64      blkbits;
   3181     unsigned    arr_ind;
   3182     int         block_types[2];
   3183 
   3184     if (str == NULL || *str == '\0') {
   3185         return -1;
   3186     }
   3187 
   3188     /* Do not destroy input string */
   3189     sal_strncpy(tmp, str, sizeof (tmp));
   3190     tmp[sizeof (tmp) - 1] = '\0';
   3191 
   3192     blk = COPYNO_ALL;
   3193     numblk = -1;
   3194     if (( ((aip = sal_strchr(tmp, '[')) != NULL) &&
   3195                 ((cp = sal_strchr(aip+1, ']')) != NULL) && (cp-aip > 1) )  ||
   3196             ( ((aip = sal_strchr(tmp, '(')) != NULL) &&
   3197               ((cp = sal_strchr(aip+1, ')')) != NULL) && (cp-aip > 1) ) )   {
   3198         /* handle memory array */
   3199 
   3200 
   3201 
   3202         /* handle initial spaces after '[' */
   3203         for (cp = aip+1; *cp == ' '; ++cp) {
   3204         }
   3205         if (*cp < '0' || *cp >'9') {
   3206             return -1;
   3207         }
   3208         /* read array index */
   3209         arr_ind = 0;
   3210         for (; *cp >= '0' && *cp <='9'; ++cp) {
   3211             arr_ind = arr_ind * 10 + (*cp - '0');
   3212         }
   3213         /* handle trailing spaces before ']' */
   3214         for (; *cp == ' '; ++cp) {
   3215         }
   3216         if ((*cp != ']') && (*cp != ')')) { /* verify closing ']' */
   3217             return -1;
   3218         }
   3219         if (array_index == NULL) {
   3220             return -1;
   3221         } else {
   3222             *array_index = arr_ind;
   3223         }
   3224         cp = sal_strchr(cp+1, '.');
   3225         *aip = '\0';
   3226     } else {
   3227         arr_ind = 0xffffffff;
   3228         cp = sal_strchr(tmp, '.');
   3229         if (array_index != NULL) {
   3230             *array_index = 0;
   3231         }
   3232     }
   3233 
   3234     if (cp != NULL) {
   3235         if (copyno == NULL) {
   3236             return -1;
   3237         }
   3238         *cp++ = '\0';
   3239     }
   3240 
   3241     mem = -1;
   3242 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
   3243 #ifdef BCM_TOMAHAWK3_SUPPORT
   3244     if (SOC_IS_TOMAHAWK3(unit)) {
   3245         if (sal_strcasecmp(tmp, "EXACT_MATCH_ONLY_DOUBLE") == 0) {
   3246             sal_strncpy(tmp, "EXACT_MATCH_2", sizeof (tmp));
   3247         }
   3248         if (sal_strcasecmp(tmp, "EXACT_MATCH_ONLY_QUAD") == 0) {
   3249             sal_strncpy(tmp, "EXACT_MATCH_4", sizeof (tmp));
   3250         }
   3251     }
   3252 #endif
   3253 
   3254     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   3255         if (!SOC_MEM_IS_VALID(unit, mem)) {
   3256             continue;
   3257         }
   3258 
   3259         if (sal_strcasecmp(tmp, SOC_MEM_NAME(unit, mem)) == 0) {
   3260             break;
   3261         }
   3262 
   3263         if (sal_strcasecmp(tmp, SOC_MEM_UFNAME(unit, mem)) == 0) {
   3264             break;
   3265         }
   3266 
   3267         if (SOC_MEM_UFALIAS(unit, mem) != NULL &&
   3268             sal_strcasecmp(tmp, SOC_MEM_UFALIAS(unit, mem)) == 0) {
   3269             break;
   3270         }
   3271     }
   3272     if (mem == NUM_SOC_MEM) {
   3273         return -1;
   3274     }
   3275 #endif
   3276 
   3277     if (cp != NULL) {
   3278 #if  defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
   3279         blk = SOC_MEM_BLOCK_ANY(unit, mem);
   3280         block_types[0] = SOC_BLOCK_TYPE(unit, blk);
   3281 #else
   3282         block_types[0] = SOC_BLOCK_TYPE_INVALID;
   3283 #endif
   3284         block_types[1] = SOC_BLOCK_TYPE_INVALID;
   3285         blk = _parse_block(unit, block_types, &cp, &numblk);
   3286         if (blk < 0 || *cp != '\0') {
   3287             return -1;
   3288         }
   3289     }
   3290 
   3291     /* memory array related validation */
   3292     if (arr_ind != 0xffffffff) {
   3293         /* an array index was specified, verify that this is a memory array and that the index is in range */
   3294         if (!SOC_MEM_IS_ARRAY(unit, mem)) {
   3295             cli_out("ERROR: an array index was specified for a memory which is not an array\n");
   3296             return -1;
   3297         } else if  (arr_ind >= (SOC_MEM_NUMELS(unit, mem) + SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) || arr_ind < SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) {
   3298             cli_out("ERROR: array index %u is out of range, should be under %u and above %u \n ",
   3299                     arr_ind, (SOC_MEM_FIRST_ARRAY_INDEX(unit, mem) + SOC_MEM_NUMELS(unit, mem) - 1), SOC_MEM_FIRST_ARRAY_INDEX(unit, mem));
   3300             return -1;
   3301         }
   3302     } else if (array_index != NULL && SOC_MEM_IS_ARRAY(unit, mem)) {
   3303         /* no array index specified, but this is a memory array */
   3304         cli_out("ERROR: an array index was not specified for a memory array\n");
   3305         return -1;
   3306     }
   3307 
   3308     if (numblk >= 0) {
   3309         if (SOC_IS_XGS12_FABRIC(unit)) {
   3310             /*
   3311              * numblk is the index into a list of SOC_BLK_PORT blocks
   3312              * well, thats intuitive, isn't it?
   3313              * This makes numblk==0 be the cpic in all cases.
   3314              * AAAAAAAARRRRRRRRRRRGGGGGGGGGGGHHHHHHHHHHHH!!!!!!!
   3315              */
   3316             matched = -1;
   3317             SOC_BLOCK_ITER(unit, blk, SOC_BLK_PORT) {
   3318                 matched += 1;
   3319                 if (matched == numblk) {
   3320                     break;
   3321                 }
   3322             }
   3323         } else {
   3324             /*
   3325              * numblk is the index into the list of blocks valid
   3326              * for this memory (ie: it's a copy number)
   3327              */
   3328             COMPILER_64_SET(blkbits, SOC_MEM_INFO(unit, mem).blocks_hi,
   3329                             SOC_MEM_INFO(unit, mem).blocks);
   3330             matched = -1;
   3331             for (blk = 0; !COMPILER_64_IS_ZERO(blkbits);
   3332                  blk++) {
   3333                 if (COMPILER_64_BITTEST(blkbits, 1)) {
   3334                     matched += 1;
   3335                     if (matched == numblk) {
   3336                         break;
   3337                     }
   3338                 }
   3339                 COMPILER_64_SHR(blkbits, 1);
   3340             }
   3341         }
   3342         if (matched != numblk) {
   3343 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
   3344             cli_out("ERROR: memory %s.%d is not valid (not enough blocks)\n",
   3345                     SOC_MEM_UFNAME(unit, mem), numblk);
   3346 #endif
   3347             return -1;
   3348         }
   3349     }
   3350 
   3351     *result = mem;
   3352     if (copyno != NULL) {
   3353         *copyno = blk;
   3354     }
   3355 
   3356     if (blk != COPYNO_ALL && !SOC_MEM_BLOCK_VALID(unit, mem, blk)) {
   3357 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
   3358         cli_out("ERROR: memory %s.%s (block %d) is not valid\n",
   3359                 SOC_MEM_UFNAME(unit, mem),
   3360                 SOC_BLOCK_NAME(unit, blk),
   3361                 blk);
   3362 #endif
   3363         return -1;
   3364     }
   3365     return 0;
   3366 }
   3367 
   3368 #if defined(BCM_ESW_SUPPORT)
   3369 /*
   3370  * parse_format_name
   3371  *
   3372  *   Parses a string containing format name.
   3373  *   and return format ID.
   3374  */
   3375 int
   3376 parse_format_name(int unit, char *str, soc_format_t *format)
   3377 {
   3378 
   3379     int f_idx = 0;
   3380     if (str == NULL || *str == '\0') {
   3381         return -1;
   3382     }
   3383     for (f_idx = 0; f_idx < NUM_SOC_FORMAT; f_idx++) {
   3384         if (!SOC_FORMAT_IS_VALID(unit, f_idx)) {
   3385             continue;
   3386         }
   3387         if (sal_strcmp(str,
   3388             SOC_FORMAT_NAME(unit, f_idx)) == 0) {
   3389             *format = f_idx;
   3390             return 0;
   3391         }
   3392     }
   3393     return -1;
   3394 }
   3395 #endif /* BCM_ESW_SUPPORT */
   3396 /*
   3397  * parse_memory_index
   3398  *
   3399  *   Parses a string containing an integer memory index, allowing
   3400  *   the two special values "min" and "max" to indicate the minimum
   3401  *   and maximum indices.
   3402  */
   3403 
   3404 int
   3405 parse_memory_index(int unit, soc_mem_t mem, char *val_str)
   3406 {
   3407     int index;
   3408 
   3409     index = 0;
   3410 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
   3411     if (!sal_strcasecmp(val_str, "min")) {
   3412         return soc_mem_index_min(unit, mem);
   3413     }
   3414 
   3415     if (!sal_strcasecmp(val_str, "max")) {
   3416         return soc_mem_index_max(unit, mem);
   3417     }
   3418 
   3419     index = parse_integer(val_str);
   3420 
   3421     if (!soc_mem_index_valid(unit, mem, index)) {
   3422         if (!(SOC_DEFIP_HOLE_RANGE_CHECK(unit, mem, index))) {
   3423             cli_out("WARNING: index %d out of range for memory %s\n",
   3424                 index, SOC_MEM_UFNAME(unit, mem));
   3425         }
   3426     }
   3427 #endif
   3428 
   3429     return index;
   3430 }
   3431 
   3432 /*
   3433  * parse_memory_index
   3434  *
   3435  *   Parses a string containing an integer memory array index, allowing
   3436  *   the two special values "min" and "max" to indicate the minimum
   3437  *   and maximum indices.
   3438  */
   3439 
   3440 unsigned
   3441 parse_memory_array_index(int unit, soc_mem_t mem, char *val_str)
   3442 {
   3443     unsigned array_index = 0;
   3444 
   3445 #if defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT)
   3446     if (SOC_MEM_IS_ARRAY(unit, mem)) {
   3447         soc_mem_array_info_t *maip = SOC_MEM_ARRAY_INFOP(unit, mem);
   3448         if (maip) {
   3449             if (!sal_strcasecmp(val_str, "min")) {
   3450                 return maip->first_array_index;
   3451             } else if (!sal_strcasecmp(val_str, "max")) {
   3452                 return (maip->numels - 1 + maip->first_array_index);
   3453             }
   3454             array_index = parse_integer(val_str);
   3455             if (array_index >= maip->numels + maip->first_array_index) {
   3456                 cli_out("WARNING: array index %u out of range for memory %s, changing it to %u\n",
   3457                         array_index, SOC_MEM_UFNAME(unit, mem), maip->numels - 1);
   3458                 array_index = (maip->numels - 1) + maip->first_array_index;
   3459             } else if (array_index < maip->first_array_index) {
   3460                 cli_out("WARNING: array index %u out of range for memory %s, changing it to %u\n",
   3461                         array_index, SOC_MEM_UFNAME(unit, mem), maip->first_array_index);
   3462                 array_index = maip->first_array_index;
   3463             }
   3464         }
   3465     }
   3466 #endif
   3467 
   3468     return array_index;
   3469 }
   3470 
   3471 /*
   3472  * parse_port_mode
   3473  *
   3474  *   Parses a port mode string consisting of a comma-separated
   3475  *   list of modes.  Examples of valid input are:
   3476  *
   3477  *      1000full,100full,100half,10full,10half
   3478  *      1000full,100,10    (equivalent to above)
   3479  *      1000full,100,10,pause
   3480  */
   3481 
   3482 static struct {
   3483     char                *str;
   3484     soc_port_mode_t     pm;
   3485 } pm_map[] = {
   3486     /* Multi-bit masks should come before their comprised 1-bit masks */
   3487     { "full",      SOC_PM_FD },
   3488     { "half",      SOC_PM_HD },
   3489     { "16G",       SOC_PM_16GB },
   3490     { "16Gfull",   SOC_PM_16GB_FD },
   3491     { "16Ghalf",   SOC_PM_16GB_HD },
   3492     { "13G",       SOC_PM_13GB },
   3493     { "13Gfull",   SOC_PM_13GB_FD},
   3494     { "13Ghalf",   SOC_PM_13GB_HD},
   3495     { "12G",       SOC_PM_12GB },
   3496     { "12Gfull",   SOC_PM_12GB_FD},
   3497     { "12Ghalf",   SOC_PM_12GB_HD},
   3498     { "10G",       SOC_PM_10GB },
   3499     { "10Gfull",   SOC_PM_10GB_FD },
   3500     { "10Ghalf",   SOC_PM_10GB_HD },
   3501     { "2500",      SOC_PM_2500MB },
   3502     { "2500full",  SOC_PM_2500MB_FD },
   3503     { "2500half",  SOC_PM_2500MB_HD },
   3504     { "1000",      SOC_PM_1000MB },
   3505     { "1000full",  SOC_PM_1000MB_FD },
   3506     { "1000half",  SOC_PM_1000MB_HD },
   3507     { "100",       SOC_PM_100MB },
   3508     { "100full",   SOC_PM_100MB_FD },
   3509     { "100half",   SOC_PM_100MB_HD },
   3510     { "10",        SOC_PM_10MB },
   3511     { "10full",    SOC_PM_10MB_FD },
   3512     { "10half",    SOC_PM_10MB_HD },
   3513     { "pause",     SOC_PM_PAUSE },
   3514     { "pause_tx",  SOC_PM_PAUSE_TX },
   3515     { "pause_rx",  SOC_PM_PAUSE_RX },
   3516     { "TBI",       SOC_PM_TBI },
   3517     { "MII",       SOC_PM_MII },
   3518     { "GMII",      SOC_PM_GMII },
   3519     { "SGMII",     SOC_PM_SGMII },
   3520     { "XGMII",     SOC_PM_XGMII },
   3521     { "combo",     SOC_PM_COMBO },
   3522     { NULL, 0 },
   3523 };
   3524 
   3525 int
   3526 parse_port_mode(char *str, soc_port_mode_t *mode)
   3527 {
   3528     int                 i;
   3529     char                *s = str;
   3530 
   3531     *mode = 0;
   3532 
   3533     while (*s != 0) {
   3534         for (i = 0; pm_map[i].str != NULL; i++) {
   3535             int len = sal_strlen(pm_map[i].str);
   3536 
   3537             if (sal_strncasecmp(s, pm_map[i].str, len) == 0 &&
   3538                 (s[len] == 0 || s[len] == ',')) {
   3539 
   3540                 *mode |= pm_map[i].pm;
   3541 
   3542                 if (*(s += len) == ',') {
   3543                     s++;
   3544                 }
   3545 
   3546                 break;
   3547             }
   3548         }
   3549 
   3550         if (pm_map[i].str == NULL) {
   3551             return -1;
   3552         }
   3553     }
   3554 
   3555     return 0;
   3556 }
   3557 
   3558 #define TYPE_SP_FD  1
   3559 #define TYPE_SP_HD  2
   3560 #define TYPE_PAUSE  3
   3561 #define TYPE_INTF   4
   3562 #define TYPE_FLAGS  5
   3563 #define TYPE_DPLX   6
   3564 #define TYPE_CHANNEL 7
   3565 #define TYPE_FEC    8
   3566 #define TYPE_IGNORE 0
   3567 #define FULL_DUPLEX 1
   3568 #define HALF_DUPLEX 2
   3569 static struct {
   3570     char *str;
   3571     int  type;
   3572     soc_port_mode_t     pm;
   3573 } pa_map[] = {
   3574     /* Multi-bit masks should come before their comprised 1-bit masks */
   3575     { "full",      TYPE_DPLX,       FULL_DUPLEX },
   3576     { "half",      TYPE_DPLX,       HALF_DUPLEX },
   3577     { "127G",      TYPE_SP_FD,      SOC_PA_SPEED_127GB },
   3578     { "120G",      TYPE_SP_FD,      SOC_PA_SPEED_120GB },
   3579     { "106G",      TYPE_SP_FD,      SOC_PA_SPEED_106GB },
   3580     { "100G",      TYPE_SP_FD,      SOC_PA_SPEED_100GB },
   3581     { "53G",       TYPE_SP_FD,      SOC_PA_SPEED_53GB },
   3582     { "50G",       TYPE_SP_FD,      SOC_PA_SPEED_50GB },
   3583     { "42G",       TYPE_SP_FD,      SOC_PA_SPEED_42GB },
   3584     { "40G",       TYPE_SP_FD,      SOC_PA_SPEED_40GB },
   3585     { "32G",       TYPE_SP_FD,      SOC_PA_SPEED_32GB },
   3586     { "30G",       TYPE_SP_FD,      SOC_PA_SPEED_30GB },
   3587     { "27G",       TYPE_SP_FD,      SOC_PA_SPEED_27GB },
   3588     { "25G",       TYPE_SP_FD,      SOC_PA_SPEED_25GB },
   3589     { "24G",       TYPE_SP_FD,      SOC_PA_SPEED_24GB },
   3590     { "21G",       TYPE_SP_FD,      SOC_PA_SPEED_21GB },
   3591     { "20G",       TYPE_SP_FD,      SOC_PA_SPEED_20GB },
   3592     { "16G",       TYPE_SP_FD,      SOC_PA_SPEED_16GB },
   3593     { "16Gfull",   TYPE_SP_FD,      SOC_PA_SPEED_16GB},
   3594     { "16Ghalf",   TYPE_SP_HD,      SOC_PA_SPEED_16GB},
   3595     { "15G",       TYPE_SP_FD,      SOC_PA_SPEED_15GB},
   3596     { "13G",       TYPE_SP_FD,      SOC_PA_SPEED_13GB},
   3597     { "13Gfull",   TYPE_SP_FD,      SOC_PA_SPEED_13GB},
   3598     { "13Ghalf",   TYPE_SP_HD,      SOC_PA_SPEED_13GB},
   3599     { "12G",       TYPE_SP_FD,      SOC_PA_SPEED_12GB},
   3600     { "12Gfull",   TYPE_SP_FD,      SOC_PA_SPEED_12GB},
   3601     { "12Ghalf",   TYPE_SP_HD,      SOC_PA_SPEED_12GB},
   3602     { "10G",       TYPE_SP_FD,      SOC_PA_SPEED_10GB},
   3603     { "10Gfull",   TYPE_SP_FD,      SOC_PA_SPEED_10GB},
   3604     { "10Ghalf",   TYPE_SP_HD,      SOC_PA_SPEED_10GB},
   3605     { "5000",      TYPE_SP_FD,      SOC_PA_SPEED_5000MB},
   3606     { "5G",        TYPE_SP_FD,      SOC_PA_SPEED_5000MB},
   3607     { "2500",      TYPE_SP_FD,      SOC_PA_SPEED_2500MB},
   3608     { "2500full",  TYPE_SP_FD,      SOC_PA_SPEED_2500MB},
   3609     { "2500half",  TYPE_SP_HD,      SOC_PA_SPEED_2500MB},
   3610     { "1000",      TYPE_SP_FD,      SOC_PA_SPEED_1000MB},
   3611     { "1000full",  TYPE_SP_FD,      SOC_PA_SPEED_1000MB},
   3612     { "1000half",  TYPE_SP_HD,      SOC_PA_SPEED_1000MB},
   3613     { "100",       TYPE_SP_FD,      SOC_PA_SPEED_100MB},
   3614     { "100full",   TYPE_SP_FD,      SOC_PA_SPEED_100MB},
   3615     { "100half",   TYPE_SP_HD,      SOC_PA_SPEED_100MB},
   3616     { "10",        TYPE_SP_FD,      SOC_PA_SPEED_10MB},
   3617     { "10full",    TYPE_SP_FD,      SOC_PA_SPEED_10MB},
   3618     { "10half",    TYPE_SP_HD,      SOC_PA_SPEED_10MB},
   3619     { "pause",     TYPE_PAUSE,      SOC_PA_PAUSE},
   3620     { "pause_tx",  TYPE_PAUSE,      SOC_PA_PAUSE_TX},
   3621     { "pause_rx",  TYPE_PAUSE,      SOC_PA_PAUSE_RX},
   3622     { "TBI",       TYPE_INTF,       SOC_PA_INTF_TBI},
   3623     { "MII",       TYPE_INTF,       SOC_PA_INTF_MII},
   3624     { "GMII",      TYPE_INTF,       SOC_PA_INTF_GMII},
   3625     { "SGMII",     TYPE_INTF,       SOC_PA_INTF_SGMII},
   3626     { "XGMII",     TYPE_INTF,       SOC_PA_INTF_XGMII},
   3627     { "combo",     TYPE_FLAGS,      SOC_PA_COMBO},
   3628     { "short",     TYPE_CHANNEL,    SOC_PA_CHANNEL_SHORT},
   3629     { "long",      TYPE_CHANNEL,    SOC_PA_CHANNEL_LONG},
   3630     { "fec_none",  TYPE_FEC,        SOC_PA_FEC_NONE},
   3631     { "cl74",      TYPE_FEC,        SOC_PA_FEC_CL74},
   3632     { "cl91",      TYPE_FEC,        SOC_PA_FEC_CL91},
   3633     { NULL, 0,0 },
   3634 };
   3635 
   3636 int
   3637 parse_port_ability(char *str, soc_port_ability_t *abil)
   3638 {
   3639     int                 i;
   3640     int dplx = 0;
   3641     char                *s = str;
   3642 
   3643     sal_memset((char *)abil, 0, sizeof(soc_port_ability_t));
   3644     while (*s != 0) {
   3645         for (i = 0; pa_map[i].str != NULL; i++) {
   3646             int len = sal_strlen(pa_map[i].str);
   3647             if (sal_strncasecmp(s, pa_map[i].str, len) == 0 &&
   3648                 (s[len] == 0 || s[len] == ',')) {
   3649                 switch (pa_map[i].type) {
   3650                     case TYPE_DPLX:
   3651                         dplx = pa_map[i].pm;
   3652                         break;
   3653                     case TYPE_SP_FD:
   3654                         if (dplx == HALF_DUPLEX) {
   3655                             abil->speed_half_duplex |= pa_map[i].pm;
   3656                         } else {
   3657                             abil->speed_full_duplex |= pa_map[i].pm;
   3658                         }
   3659                         break;
   3660                     case TYPE_SP_HD:
   3661                         if (dplx == FULL_DUPLEX) {
   3662                             abil->speed_full_duplex |= pa_map[i].pm;
   3663                         } else {
   3664                             abil->speed_half_duplex |= pa_map[i].pm;
   3665                         }
   3666                         break;
   3667                     case TYPE_PAUSE:
   3668                         abil->pause |= pa_map[i].pm;
   3669                         break;
   3670                     case TYPE_INTF:
   3671                         abil->interface |= pa_map[i].pm;
   3672                         break;
   3673                     case TYPE_FLAGS:
   3674                         abil->flags |= pa_map[i].pm;
   3675                         break;
   3676                     case TYPE_CHANNEL:
   3677                         abil->channel |= pa_map[i].pm;
   3678                         break;
   3679                     case TYPE_FEC:
   3680                         abil->fec |= pa_map[i].pm;
   3681                         break;
   3682                     default:
   3683                         break;
   3684                 }
   3685 
   3686                 if (*(s += len) == ',') {
   3687                     s++;
   3688                 }
   3689 
   3690                 break;
   3691             }
   3692         }
   3693 
   3694         if (pa_map[i].str == NULL) {
   3695             return -1;
   3696         }
   3697     }
   3698 
   3699     return 0;
   3700 }
   3701 
   3702 
   3703 /*
   3704  * format_port_mode
   3705  *
   3706  *   Formats a port mode into a comma-separated list of port mode
   3707  *   strings.  This is the reverse of parse_port_mode.
   3708  *
   3709  *   If abbrev is TRUE, then "1000full,1000half" will be abbreviated
   3710  *   as "1000".
   3711  *
   3712  *   Output buffer must be at least 80 characters.
   3713  */
   3714 
   3715 void
   3716 format_port_mode(char *buf, int bufsize, soc_port_mode_t mode, int abbrev)
   3717 {
   3718     int                 i, first = 1;
   3719 
   3720     assert(bufsize >= 80);
   3721 
   3722     buf[0] = 0;
   3723 
   3724     for (i = 0; mode != 0 && pm_map[i].str != NULL; i++) {
   3725         if (!abbrev && _shr_popcount(pm_map[i].pm) != 1) {
   3726             continue;
   3727         }
   3728 
   3729         if ((mode & pm_map[i].pm) == pm_map[i].pm) {
   3730             if (first) {
   3731                 first = 0;
   3732             } else {
   3733                 *buf++ = ',';
   3734             }
   3735 
   3736             /* Coverity[secure_coding] */
   3737             sal_strcpy(buf, pm_map[i].str);
   3738 
   3739             while (*buf != 0) {
   3740                 buf++;
   3741             }
   3742 
   3743             mode &= ~pm_map[i].pm;
   3744         }
   3745     }
   3746 }
   3747 
   3748 
   3749 /* Port Ability structure */
   3750 
   3751 typedef struct {
   3752     char                *str;
   3753     soc_port_mode_t  pa;
   3754 } _port_ability_map_t;
   3755 
   3756 
   3757 /* Port Ability speed mapping */
   3758 _port_ability_map_t pa_speed_map[] = {
   3759     /* Multi-bit masks should come before their comprised 1-bit masks */
   3760     { "10MB",           SOC_PA_SPEED_10MB },
   3761     { "100MB",          SOC_PA_SPEED_100MB },
   3762     { "1000MB",         SOC_PA_SPEED_1000MB },
   3763     { "2500MB",         SOC_PA_SPEED_2500MB },
   3764     { "3000MB",         SOC_PA_SPEED_3000MB },
   3765     { "5000MB",         SOC_PA_SPEED_5000MB },
   3766     { "6000MB",         SOC_PA_SPEED_6000MB },
   3767     { "10GB",           SOC_PA_SPEED_10GB},
   3768     { "11GB",           SOC_PA_SPEED_11GB},
   3769     { "12GB",           SOC_PA_SPEED_12GB},
   3770     { "12GP5",          SOC_PA_SPEED_12P5GB},
   3771     { "13GB",           SOC_PA_SPEED_13GB},
   3772     { "15GB",           SOC_PA_SPEED_15GB},
   3773     { "16GB",           SOC_PA_SPEED_16GB},
   3774     { "20GB",           SOC_PA_SPEED_20GB},
   3775 
   3776     { "21GB",           SOC_PA_SPEED_21GB},
   3777     { "24GB",           SOC_PA_SPEED_24GB},
   3778 
   3779     { "25GB",           SOC_PA_SPEED_25GB},
   3780     { "27GB",           SOC_PA_SPEED_27GB},
   3781 
   3782     { "30GB",           SOC_PA_SPEED_30GB},
   3783     { "32GB",           SOC_PA_SPEED_32GB},
   3784     { "40GB",           SOC_PA_SPEED_40GB},
   3785 
   3786     { "42GB",           SOC_PA_SPEED_42GB},
   3787     { "50GB",           SOC_PA_SPEED_50GB},
   3788     { "53GB",           SOC_PA_SPEED_53GB},
   3789     { "100GB",          SOC_PA_SPEED_100GB},
   3790     { "106GB",          SOC_PA_SPEED_106GB},
   3791     { NULL, 0 },
   3792 };
   3793 
   3794 /* Port Ability interface mapping */
   3795 _port_ability_map_t pa_intf_map[] = {
   3796     /* Multi-bit masks should come before their comprised 1-bit masks */
   3797     { "tbi",            SOC_PA_INTF_TBI},
   3798     { "mii",            SOC_PA_INTF_MII},
   3799     { "gmii",           SOC_PA_INTF_GMII},
   3800     { "rgmii",          SOC_PA_INTF_RGMII},
   3801     { "sgmii",          SOC_PA_INTF_SGMII},
   3802     { "xgmii",          SOC_PA_INTF_XGMII},
   3803     { NULL, 0 },
   3804 };
   3805 
   3806 /* Port Ability pause mapping */
   3807 _port_ability_map_t pa_pause_map[] = {
   3808     /* Multi-bit masks should come before their comprised 1-bit masks */
   3809     { "pause_tx",       SOC_PA_PAUSE_TX},
   3810     { "pause_rx",       SOC_PA_PAUSE_RX},
   3811     { "pause_asymm",    SOC_PA_PAUSE_ASYMM},
   3812     { NULL, 0 },
   3813 };
   3814 
   3815 _port_ability_map_t pa_medium_map[] = {
   3816     /* Multi-bit masks should come before their comprised 1-bit masks */
   3817     { "copper",         SOC_PA_MEDIUM_COPPER},
   3818     { "fiber",          SOC_PA_MEDIUM_FIBER},
   3819     { NULL, 0 },
   3820 };
   3821 
   3822 _port_ability_map_t pa_lb_map[] = {
   3823     /* Multi-bit masks should come before their comprised 1-bit masks */
   3824     { "none",           SOC_PA_LB_NONE},
   3825     { "MAC",            SOC_PA_LB_MAC},
   3826     { "PHY",            SOC_PA_LB_PHY},
   3827     { "LINE",           SOC_PA_LB_LINE},
   3828     { NULL, 0 },
   3829 };
   3830 
   3831 _port_ability_map_t pa_flags_map[] = {
   3832     /* Multi-bit masks should come before their comprised 1-bit masks */
   3833     { "autoneg",        SOC_PA_AUTONEG},
   3834     { "combo",          SOC_PA_COMBO},
   3835     { NULL, 0 },
   3836 };
   3837 
   3838 
   3839 STATIC void
   3840 format_port_ability(char *buf, int bufsize, soc_port_mode_t ability,
   3841                     _port_ability_map_t *pa_map)
   3842 {
   3843     int                 i, first = 1;
   3844 
   3845     assert(bufsize >= 80);
   3846     memset(buf, 0, bufsize);
   3847 
   3848     buf[0] = 0;
   3849 
   3850     for (i = 0; ability != 0 && pa_map[i].str != NULL; i++) {
   3851         if ((ability & pa_map[i].pa) == pa_map[i].pa) {
   3852             /* Account for final termination null byte + plus one extra ',' */
   3853             assert(strlen(buf) + strlen(pa_map[i].str) + 2 <= bufsize);
   3854 
   3855             if (first) {
   3856                 first = 0;
   3857             } else {
   3858                 *buf++ = ',';
   3859             }
   3860 
   3861             /* Coverity[secure_coding] */
   3862             sal_strcpy(buf, pa_map[i].str);
   3863 
   3864             while (*buf != 0) {
   3865                 buf++;
   3866             }
   3867 
   3868             ability &= ~pa_map[i].pa;
   3869         }
   3870     }
   3871 }
   3872 
   3873 /*
   3874  * format_port_speed_ability
   3875  *
   3876  *   Formats a port speed ability into a comma-separated list of port speed
   3877  *   strings.
   3878  *   Output buffer must be at least 80 characters.
   3879  */
   3880 
   3881 void
   3882 format_port_speed_ability(char *buf, int bufsize, soc_port_mode_t ability)
   3883 {
   3884     format_port_ability(buf, bufsize, ability, pa_speed_map);
   3885 }
   3886 
   3887 /*
   3888  * format_port_intf_ability
   3889  *
   3890  *   Formats a port interface ability into a comma-separated list of port
   3891  *   interface strings.
   3892  *   Output buffer must be at least 80 characters.
   3893  */
   3894 void
   3895 format_port_intf_ability(char *buf, int bufsize, soc_port_mode_t ability)
   3896 {
   3897     format_port_ability(buf, bufsize, ability, pa_intf_map);
   3898 }
   3899 
   3900 /*
   3901  * format_port_medium_ability
   3902  *
   3903  *   Formats a port medium ability into a comma-separated list of port
   3904  *   medium strings.
   3905  *   Output buffer must be at least 80 characters.
   3906  */
   3907 void
   3908 format_port_medium_ability(char *buf, int bufsize, soc_port_mode_t ability)
   3909 {
   3910     format_port_ability(buf, bufsize, ability, pa_medium_map);
   3911 }
   3912 
   3913 /*
   3914  * format_port_pause_ability
   3915  *
   3916  *   Formats a port pause ability into a comma-separated list of port
   3917  *   pause strings.
   3918  *   Output buffer must be at least 80 characters.
   3919  */
   3920 void
   3921 format_port_pause_ability(char *buf, int bufsize, soc_port_mode_t ability)
   3922 {
   3923     format_port_ability(buf, bufsize, ability, pa_pause_map);
   3924 }
   3925 /*
   3926  * format_port_lb_ability
   3927  *
   3928  *   Formats a port loopback ability into a comma-separated list of port
   3929  *   loopback strings.
   3930  *   Output buffer must be at least 80 characters.
   3931  */
   3932 void
   3933 format_port_lb_ability(char *buf, int bufsize, soc_port_mode_t ability)
   3934 {
   3935     format_port_ability(buf, bufsize, ability, pa_lb_map);
   3936 }
   3937 /*
   3938  * format_port_flags_ability
   3939  *
   3940  *   Formats a port flags ability into a comma-separated list of port
   3941  *   flags strings.
   3942  *   Output buffer must be at least 80 characters.
   3943  */
   3944 void
   3945 format_port_flags_ability(char *buf, int bufsize, soc_port_mode_t ability)
   3946 {
   3947     format_port_ability(buf, bufsize, ability, pa_flags_map);
   3948 }
   3949 
   3950 /*
   3951  * Function:
   3952  *     parse_field_qualifier
   3953  * Purpose:
   3954  *     Turn text into a bcm_field_qualifier_t for the Field Processor code.
   3955  *
   3956  * Returns:
   3957  *     bcm_field_qualifier_t value that matches the input string
   3958  *        or
   3959  *     BCM_FIELD_ENTRY_INVALID if badly formed string
   3960  */
   3961 bcm_field_qualify_t
   3962 parse_field_qualifier(char *qual_str)
   3963 {
   3964     char                cannonical_str[64];
   3965     char tos1[] = "TOS";
   3966     char tos2[] = "bcmFieldQualifyTos";
   3967     bcm_field_qualify_t qual;
   3968 
   3969     assert(qual_str != NULL);
   3970     if (sal_strlen(qual_str) >=  64 - 1) {
   3971         return BCM_FIELD_ENTRY_INVALID;
   3972     }
   3973 
   3974     if (!sal_strcasecmp(tos1, qual_str) ||
   3975         !sal_strcasecmp(tos2, qual_str)) {
   3976         return bcmFieldQualifyDSCP;
   3977     }
   3978 
   3979     for (qual = 0; qual < bcmFieldQualifyCount; qual++) {
   3980         /* Test for whole name of the qualifier */
   3981         format_field_qualifier(cannonical_str, qual, 0);
   3982         if (!sal_strcasecmp(cannonical_str, qual_str)) {
   3983             break;
   3984         }
   3985         /* Test for the suffix only */
   3986         if(!sal_strcasecmp(cannonical_str + sal_strlen("bcmFieldQualify"),
   3987                            qual_str)) {
   3988             break;
   3989         }
   3990     }
   3991 
   3992     /* If not found, result is BCM_FIELD_ENTRY_INVALID */
   3993     return qual;
   3994 }
   3995 
   3996 /*
   3997  * Function:
   3998  *     format_field_qualifier
   3999  * Purpose:
   4000  *    Format a bcm_field_qualify_t variable for output
   4001  * Parameters:
   4002  *    buf       - character buffer where string is written
   4003  *    qualifier - Field Qualifier value
   4004  *    brief     - if 0, use cannonical form, otherwise use short format
   4005  * Returns:
   4006  *    pointer to buffer for printf-style usage
   4007  */
   4008 char *
   4009 format_field_qualifier(char *buf, bcm_field_qualify_t qualifier, int brief)
   4010 {
   4011     char *qualifier_text[bcmFieldQualifyCount] = BCM_FIELD_QUALIFY_STRINGS;
   4012 
   4013     assert(buf != NULL);
   4014 
   4015     if (0 <= qualifier && qualifier < bcmFieldQualifyCount) {
   4016         if (brief) {
   4017             sal_sprintf(buf, "%s", qualifier_text[qualifier]);
   4018         } else {
   4019             sal_sprintf(buf, "bcmFieldQualify%s", qualifier_text[qualifier]);
   4020         }
   4021     } else {
   4022         sal_sprintf(buf, "invalid qualifier value=%#x", qualifier);
   4023     }
   4024 
   4025     return buf;
   4026 }
   4027 
   4028 /*
   4029  * Function:
   4030  *     parse_field_qset
   4031  * Purpose:
   4032  *     Turn CLI input into a qset for the Field Processor code.
   4033  */
   4034 int
   4035 parse_field_qset(char *str, bcm_field_qset_t *qset) {
   4036     char                 *buf;
   4037     char                 *str_copy;
   4038     int                  input_len;
   4039     bcm_field_qualify_t  qual;
   4040     int                  retval = 0;
   4041     char                 delimiters[] = " \t,\n\0{}";
   4042     int                  nval = _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX);
   4043     int                  idx;
   4044     char                 eight[11], *src_str, *temp_str;
   4045     char                 *tokstr;
   4046 
   4047     assert(str != NULL);
   4048 
   4049     BCM_FIELD_QSET_INIT(*qset);
   4050 
   4051     str_copy = (char *) sal_alloc((BCM_FIELD_QSET_WIDTH_MAX * sizeof(char)),
   4052                                    "qset string");
   4053     if (NULL == str_copy) {
   4054         return (BCM_E_MEMORY);
   4055     }
   4056 
   4057     /* Parse bitmap input in the form of an Integer. */
   4058     if (isint(str)) {
   4059         /* Skip to the last hex digit in the string */
   4060         for (src_str = str + 1; isxdigit((unsigned) src_str[1]); src_str++) {
   4061             ;
   4062         }
   4063 
   4064         /* Parse backward in groups of 8 digits */
   4065         idx = 0;
   4066         do {
   4067             /* Copy 8 digits backward to form a string "0xdddddddd\0" */
   4068             temp_str = eight + 11;
   4069             *--temp_str = 0;
   4070             while (temp_str > eight + 2 && *src_str != 'x') {
   4071                 *--temp_str = *src_str--;
   4072             }
   4073             *--temp_str = 'x';
   4074             *--temp_str = '0';
   4075 
   4076             qset->w[idx++] = parse_integer(temp_str);
   4077         } while (*src_str != 'x' && idx < nval);
   4078         sal_free(str_copy);
   4079         return 1;
   4080     }
   4081 
   4082     /* Parse list of qualifiers. */
   4083     input_len = sal_strlen(str);
   4084     if (input_len >= BCM_FIELD_QSET_WIDTH_MAX) {
   4085         sal_free(str_copy);
   4086         return 0;
   4087     }
   4088     sal_strncpy(str_copy, str, input_len + 1);
   4089 
   4090     buf = sal_strtok_r(str_copy, delimiters, &tokstr);
   4091 
   4092     do {
   4093         qual = parse_field_qualifier(buf);
   4094         if (qual != BCM_FIELD_ENTRY_INVALID) {
   4095             BCM_FIELD_QSET_ADD(*qset, qual);
   4096             retval++;
   4097         }
   4098         buf = sal_strtok_r(NULL, delimiters, &tokstr);
   4099     } while (buf);
   4100 
   4101     sal_free(str_copy);
   4102     return retval;
   4103 }
   4104 
   4105 /*
   4106  * Function:
   4107  *     format_field_qset
   4108  * Purpose:
   4109  *    Format a bcm_field_qset_t for output
   4110  * Parameters:
   4111  *    buf       - character buffer where string is written
   4112  *    qset      - Field Qset value
   4113  * Returns:
   4114  *    pointer to buffer (for printf-style usage)
   4115  */
   4116 char *
   4117 format_field_qset(char *buf, bcm_field_qset_t qset, char *separator)
   4118 {
   4119     bcm_field_qualify_t  qual;
   4120     char                 buf_local[30];
   4121     int                  first_print = 1;
   4122 
   4123     assert(buf != NULL);
   4124 
   4125     buf[0] = '{';
   4126     buf[1] = '\0';
   4127 
   4128     /* Iterate over Qset, looking for bits that are set. */
   4129     for (qual = 0; qual < bcmFieldQualifyCount; qual++) {
   4130         if(BCM_FIELD_QSET_TEST(qset, qual)) {
   4131             if (first_print == 1) {
   4132                 first_print = 0;
   4133             } else {
   4134                 sal_strncat(buf, separator, sal_strlen(separator));
   4135             }
   4136             format_field_qualifier(buf_local, qual, 1);
   4137             sal_strncat(buf, buf_local, sal_strlen(buf_local));
   4138         }
   4139     }
   4140     sal_strncat(buf, "}", sal_strlen("}"));
   4141 
   4142     return buf;
   4143 }
   4144 
   4145 /*
   4146  * Function:
   4147  *     parse_field_group_mode
   4148  * Purpose:
   4149  *     Turn text into a bcm_field_group_mode_t for the Field Processor code.
   4150  *
   4151  * Returns:
   4152  *     bcm_field_group_mode_t value that matches the input string
   4153  *        or
   4154  *     bcmFieldGroupModeCount if badly formed string
   4155  */
   4156 bcm_field_group_mode_t
   4157 parse_field_group_mode(char *act_str)
   4158 {
   4159     char                    cannonical_str[64];
   4160     bcm_field_group_mode_t  mode;
   4161 
   4162     assert(act_str != NULL);
   4163     if (sal_strlen(act_str) >=  64 - 1) {
   4164         return bcmFieldGroupModeCount;
   4165     }
   4166 
   4167     for (mode = 0; mode < bcmFieldGroupModeCount; mode++) {
   4168         /* Test for whole name of the mode */
   4169         format_field_group_mode(cannonical_str, mode, 0);
   4170         if (!sal_strcasecmp(cannonical_str, act_str)) {
   4171             break;
   4172         }
   4173         /* Test for the suffix only */
   4174         if(!sal_strcasecmp(cannonical_str + sal_strlen("bcmFieldGroupMode"),
   4175                            act_str)) {
   4176             break;
   4177         }
   4178     }
   4179 
   4180     /* If not found, result is bcmFieldGroupModeCount */
   4181     return mode;
   4182 }
   4183 
   4184 /*
   4185  * Function:
   4186  *     format_field_group_mode
   4187  * Purpose:
   4188  *    Format a bcm_field_group_mode_t variable for output
   4189  * Parameters:
   4190  *    buf       - character buffer where string is written
   4191  *    mode      - Field group_mode value
   4192  *    brief     - if 0, use cannonical form, otherwise use short format
   4193  * Returns:
   4194  *    pointer to buffer for printf-style usage
   4195  */
   4196 char *
   4197 format_field_group_mode(char *buf, bcm_field_group_mode_t mode, int brief)
   4198 {
   4199     char *mode_text[bcmFieldGroupModeCount] = BCM_FIELD_GROUP_MODE_STRINGS;
   4200 
   4201     assert(buf != NULL);
   4202 
   4203     if (0 <= mode && mode < bcmFieldGroupModeCount) {
   4204         if (brief) {
   4205             sal_sprintf(buf, "%s", mode_text[mode]);
   4206         } else {
   4207             sal_sprintf(buf, "bcmFieldGroupMode%s", mode_text[mode]);
   4208         }
   4209     } else {
   4210         sal_sprintf(buf, "invalid group mode value=%#x", mode);
   4211     }
   4212 
   4213     return buf;
   4214 }
   4215 
   4216 /*
   4217  * Function:
   4218  *     parse_field_action
   4219  * Purpose:
   4220  *     Turn text into a bcm_field_action_t for the Field Processor code.
   4221  *
   4222  * Returns:
   4223  *     bcm_field_action_t value that matches the input string
   4224  *        or
   4225  *     BCM_FIELD_ENTRY_INVALID if badly formed string
   4226  */
   4227 bcm_field_action_t
   4228 parse_field_action(char *act_str)
   4229 {
   4230     char                cannonical_str[64];
   4231     bcm_field_action_t  action;
   4232 
   4233     assert(act_str != NULL);
   4234     if (sal_strlen(act_str) >=  64 - 1) {
   4235         return BCM_FIELD_ENTRY_INVALID;
   4236     }
   4237 
   4238     for (action = 0; action < bcmFieldActionCount; action++) {
   4239         /* Test for whole name of the action */
   4240         format_field_action(cannonical_str, action, 0);
   4241         if (!sal_strcasecmp(cannonical_str, act_str)) {
   4242             break;
   4243         }
   4244         /* Test for the suffix only */
   4245         if(!sal_strcasecmp(cannonical_str + sal_strlen("bcmFieldAction"),
   4246                            act_str)) {
   4247             break;
   4248         }
   4249     }
   4250 
   4251     /* If not found, result is BCM_FIELD_ENTRY_INVALID */
   4252     return action;
   4253 }
   4254 
   4255 /*
   4256  * Function:
   4257  *     format_field_action
   4258  * Purpose:
   4259  *    Format a bcm_field_action_t variable for output
   4260  * Parameters:
   4261  *    buf       - character buffer where string is written
   4262  *    action    - Field action value
   4263  *    brief     - if 0, use cannonical form, otherwise use short format
   4264  * Returns:
   4265  *    pointer to buffer for printf-style usage
   4266  */
   4267 static const char *action_text[bcmFieldActionCount] = BCM_FIELD_ACTION_STRINGS;
   4268 char *
   4269 format_field_action(char *buf, bcm_field_action_t action, int brief)
   4270 {
   4271     assert(buf != NULL);
   4272 
   4273     if (0 <= action && action < bcmFieldActionCount) {
   4274         if (brief) {
   4275             sal_sprintf(buf, "%s", action_text[action]);
   4276         } else {
   4277             sal_sprintf(buf, "bcmFieldAction%s", action_text[action]);
   4278         }
   4279     } else {
   4280         sal_sprintf(buf, "invalid action value=%#x", action);
   4281     }
   4282 
   4283     return buf;
   4284 }
   4285 
   4286 /*
   4287  * Function:
   4288  *     parse_field_aset
   4289  * Purpose:
   4290  *     Turn CLI input into a aset for the Field Processor code.
   4291  */
   4292 int
   4293 parse_field_aset(char *str, bcm_field_aset_t *aset, uint8 add) {
   4294     char                 *buf;
   4295     char                 *str_copy;
   4296     int                  input_len;
   4297     bcm_field_action_t   action;
   4298     int                  retval = 0;
   4299     char                 delimiters[] = " \t,\n\0{}";
   4300     char                 *tokstr;
   4301 
   4302     assert(str != NULL);
   4303 
   4304     str_copy = (char *) sal_alloc((BCM_FIELD_ASET_WIDTH_MAX * sizeof(char)),
   4305                                    "aset string");
   4306     if (NULL == str_copy) {
   4307         return (BCM_E_MEMORY);
   4308     }
   4309 
   4310     /* Parse list of actions. */
   4311     input_len = sal_strlen(str);
   4312     if (input_len >= BCM_FIELD_ASET_WIDTH_MAX) {
   4313         sal_free(str_copy);
   4314         return 0;
   4315     }
   4316     sal_strncpy(str_copy, str, input_len + 1);
   4317 
   4318     buf = sal_strtok_r(str_copy, delimiters, &tokstr);
   4319 
   4320     do {
   4321         action = parse_field_action(buf);
   4322         if (action != BCM_FIELD_ENTRY_INVALID) {
   4323             if (add) {
   4324                 BCM_FIELD_ASET_ADD(*aset, action);
   4325             } else {
   4326                 BCM_FIELD_ASET_REMOVE(*aset, action);
   4327             }
   4328             retval++;
   4329         }
   4330         buf = sal_strtok_r(NULL, delimiters, &tokstr);
   4331     } while (buf);
   4332 
   4333     sal_free(str_copy);
   4334     return retval;
   4335 }
   4336 
   4337 /*
   4338  * Function:
   4339  *     format_field_aset
   4340  * Purpose:
   4341  *    Format a bcm_field_aset_t for output
   4342  * Parameters:
   4343  *    buf       - character buffer where string is written
   4344  *    aset      - Field Aset value
   4345  * Returns:
   4346  *    pointer to buffer (for printf-style usage)
   4347  */
   4348 char *
   4349 format_field_aset(char *buf, bcm_field_aset_t aset, char *separator)
   4350 {
   4351     bcm_field_action_t   action;
   4352     char                 buf_local[30];
   4353     int                  first_print = 1;
   4354 
   4355     assert(buf != NULL);
   4356 
   4357     buf[0] = '{';
   4358     buf[1] = '\0';
   4359 
   4360     /* Iterate over Aset, looking for bits that are set. */
   4361     for (action = 0; action < bcmFieldActionCount; action++) {
   4362         if(BCM_FIELD_ASET_TEST(aset, action)) {
   4363             if (first_print == 1) {
   4364                 first_print = 0;
   4365             } else {
   4366                 sal_strncat(buf, separator, sal_strlen(separator));
   4367             }
   4368             format_field_action(buf_local, action, 1);
   4369             sal_strncat(buf, buf_local, sal_strlen(buf_local));
   4370         }
   4371     }
   4372     sal_strncat(buf, "}", sal_strlen("}"));
   4373 
   4374     return buf;
   4375 }
   4376 
   4377 
   4378 #define FP_OLP_HDR_TYPE_STR_SZ 50
   4379 /*
   4380  * Function:
   4381  *    parse_field_olp_hdr_type
   4382  * Purpose:
   4383  *     Turn CLI input into a bcm_field_oam_type_t for the Field Processor code.
   4384  *
   4385  * Returns:
   4386  *     bcm_field_olp_header_type_t value that matches the input string
   4387  *        or
   4388  *     bcmFieldOlpHeaderTypeCount if badly formed string
   4389  */
   4390 bcm_field_olp_header_type_t parse_field_olp_hdr_type(char *str)
   4391 {
   4392     bcm_field_olp_header_type_t olp_hdr_type;
   4393     char *olp_hdr_type_text[bcmFieldOlpHeaderTypeCount] = BCM_FIELD_OLP_HEADER_TYPE_STRINGS;
   4394     char                tbl_str[FP_OLP_HDR_TYPE_STR_SZ];
   4395     char                lng_str[FP_OLP_HDR_TYPE_STR_SZ];
   4396 
   4397     if (str == NULL) {
   4398         return bcmFieldOlpHeaderTypeCount;
   4399     }
   4400 
   4401     if (isint(str)) {
   4402         return parse_integer(str);
   4403     }
   4404 
   4405     for (olp_hdr_type = 0; olp_hdr_type < bcmFieldOlpHeaderTypeCount; olp_hdr_type++) {
   4406         sal_memset(tbl_str, 0, sizeof(char) * FP_OLP_HDR_TYPE_STR_SZ);
   4407         sal_memset(lng_str, 0, sizeof(char) * FP_OLP_HDR_TYPE_STR_SZ);
   4408         /* Test for the suffix only */
   4409         sal_strncpy(tbl_str, olp_hdr_type_text[olp_hdr_type], FP_OLP_HDR_TYPE_STR_SZ - 1);
   4410         if (!sal_strcasecmp(tbl_str, str)) {
   4411             break;
   4412         }
   4413         /* Test for whole name of the action */
   4414         sal_strncpy(lng_str, "bcmFieldOlpHeaderType", sizeof (lng_str));
   4415         sal_strncat(lng_str, tbl_str,
   4416                 FP_OLP_HDR_TYPE_STR_SZ - 1 - sal_strlen("bcmFieldOlpHeaderType"));
   4417         if (!sal_strcasecmp(lng_str, str)) {
   4418             break;
   4419         }
   4420     }
   4421     return olp_hdr_type;
   4422 }
   4423 
   4424 #define FP_OAMTYPE_STR_SZ 50
   4425 /*
   4426  * Function:
   4427  *    parse_field_oam_type
   4428  * Purpose:
   4429  *     Turn CLI input into a bcm_field_oam_type_t for the Field Processor code.
   4430  *
   4431  * Returns:
   4432  *     bcm_field_oam_type_t value that matches the input string
   4433  *        or
   4434  *     bcmFieldOamTypeCount if badly formed string
   4435  */
   4436 bcm_field_oam_type_t
   4437 parse_field_oam_type(char *str)
   4438 {
   4439     bcm_field_oam_type_t   oamtype;
   4440     char *oamtype_text[bcmFieldOamTypeCount] = BCM_FIELD_OAM_TYPE;
   4441     char                tbl_str[FP_OAMTYPE_STR_SZ];
   4442     char                lng_str[FP_OAMTYPE_STR_SZ];
   4443 
   4444     if (str == NULL) {
   4445         return bcmFieldOamTypeCount;
   4446     }
   4447 
   4448     if (isint(str)) {
   4449         return parse_integer(str);
   4450     }
   4451 
   4452     for (oamtype = 0; oamtype < bcmFieldOamTypeCount; oamtype++) {
   4453         sal_memset(tbl_str, 0, sizeof(char) * FP_OAMTYPE_STR_SZ);
   4454         sal_memset(lng_str, 0, sizeof(char) * FP_OAMTYPE_STR_SZ);
   4455         /* Test for the suffix only */
   4456         sal_strncpy(tbl_str, oamtype_text[oamtype], FP_OAMTYPE_STR_SZ - 1);
   4457         if (!sal_strcasecmp(tbl_str, str)) {
   4458             break;
   4459         }
   4460         /* Test for whole name of the action */
   4461         sal_strncpy(lng_str, "bcmFieldOamType", sizeof (lng_str));
   4462         sal_strncat(lng_str, tbl_str,
   4463                 FP_OAMTYPE_STR_SZ - 1 - sal_strlen("bcmFieldOamType"));
   4464         if (!sal_strcasecmp(lng_str, str)) {
   4465             break;
   4466         }
   4467     }
   4468     return oamtype;
   4469 }
   4470 
   4471 
   4472 #define FP_DECAP_STR_SZ 50
   4473 /*
   4474  * Function:
   4475  *     parse_field_decap
   4476  * Purpose:
   4477  *     Turn CLI input into a bcm_field_decap_t for the Field Processor code.
   4478  *
   4479  * Returns:
   4480  *     bcm_field_decap_t value that matches the input string
   4481  *        or
   4482  *     bcmFieldDecapCount if badly formed string
   4483  */
   4484 bcm_field_decap_t
   4485 parse_field_decap(char *str)
   4486 {
   4487     bcm_field_decap_t   decap;
   4488     char *decap_text[bcmFieldDecapCount] = BCM_FIELD_DECAP_STRINGS;
   4489     char                tbl_str[FP_DECAP_STR_SZ];
   4490     char                lng_str[FP_DECAP_STR_SZ];
   4491 
   4492     if (str == NULL) {
   4493         return bcmFieldDecapCount;
   4494     }
   4495 
   4496     if (isint(str)) {
   4497         return parse_integer(str);
   4498     }
   4499 
   4500     for (decap = 0; decap < bcmFieldDecapCount; decap++) {
   4501         sal_memset(tbl_str, 0, sizeof(char) * FP_DECAP_STR_SZ);
   4502         sal_memset(lng_str, 0, sizeof(char) * FP_DECAP_STR_SZ);
   4503         /* Test for the suffix only */
   4504         sal_strncpy(tbl_str, decap_text[decap], FP_DECAP_STR_SZ - 1);
   4505         if (!sal_strcasecmp(tbl_str, str)) {
   4506             break;
   4507         }
   4508         /* Test for whole name of the action */
   4509         /* Coverity[secure_coding] */
   4510         sal_strcpy(lng_str, "bcmFieldDecap");
   4511         sal_strncat(lng_str, tbl_str,
   4512                 FP_DECAP_STR_SZ - 1 - sal_strlen("bcmFieldDecap"));
   4513         if (!sal_strcasecmp(lng_str, str)) {
   4514             break;
   4515         }
   4516     }
   4517     return decap;
   4518 }
   4519 
   4520 
   4521 #define FP_MPLS_OAM_CTRL_PKT_TYPE_STR_SZ 50
   4522 /*
   4523  * Function:
   4524  *    parse_field_MplsOamCtrlPktType
   4525  * Purpose:
   4526  *     Turn CLI input into a bcm_field_MplsOam_Control_pktType_t
   4527        for the Field Processor code.
   4528  *
   4529  * Returns:
   4530  *     bcm_field_MplsOam_Control_pktType_t value that matches the input string
   4531  *        or
   4532  *      bcmFieldMplsOamControlPktTypeCount if badly formed string
   4533  */
   4534 bcm_field_MplsOam_Control_pktType_t
   4535 parse_field_MplsOamCtrlPktType (char *str)
   4536 {
   4537     bcm_field_MplsOam_Control_pktType_t pktType;
   4538     char *MplsOamCtrlPktType[bcmFieldMplsOamControlPktTypeCount]
   4539                        = BCM_FIELD_MPLS_OAM_CONTROL_PKT_TYPE;
   4540     char                tbl_str[FP_MPLS_OAM_CTRL_PKT_TYPE_STR_SZ];
   4541     char                lng_str[FP_MPLS_OAM_CTRL_PKT_TYPE_STR_SZ];
   4542 
   4543     if (str == NULL) {
   4544         return bcmFieldMplsOamControlPktTypeCount;
   4545     }
   4546 
   4547     if (isint(str)) {
   4548         return parse_integer(str);
   4549     }
   4550 
   4551     for (pktType = 0; pktType < bcmFieldMplsOamControlPktTypeCount; pktType++) {
   4552         sal_memset(tbl_str, 0, sizeof(char) * FP_MPLS_OAM_CTRL_PKT_TYPE_STR_SZ);
   4553         sal_memset(lng_str, 0, sizeof(char) * FP_MPLS_OAM_CTRL_PKT_TYPE_STR_SZ);
   4554         /* Test for the suffix only */
   4555         sal_strncpy(tbl_str, MplsOamCtrlPktType[pktType],
   4556                 FP_MPLS_OAM_CTRL_PKT_TYPE_STR_SZ - 1);
   4557         if (!sal_strcasecmp(tbl_str, str)) {
   4558             break;
   4559         }
   4560         /* Test for whole name of the action */
   4561         sal_strncpy(lng_str, "bcmFieldMplsOamControlPktType", sizeof (lng_str));
   4562         sal_strncat(lng_str, tbl_str,
   4563                 FP_MPLS_OAM_CTRL_PKT_TYPE_STR_SZ - 1 -
   4564                 sal_strlen("bcmFieldMplsOamControlPktType"));
   4565         if (!sal_strcasecmp(lng_str, str)) {
   4566             break;
   4567         }
   4568     }
   4569     return pktType;
   4570 }
   4571 
   4572 #define FP_ROE_FRAME_TYPE_STR_SZ 40
   4573 /*
   4574  * Function:
   4575  *    parse_field_roe_frame_type
   4576  * Purpose:
   4577  *     Turn CLI input into a bcm_field_roe_frame_type_t for the Field Processor code.
   4578  *
   4579  * Returns:
   4580  *     bcm_field_roe_frame_type_t value that matches the input string
   4581  *        or
   4582  *     bcmFieldRoeFrameTypeCount if badly formed string
   4583  */
   4584 bcm_field_roe_frame_type_t parse_field_roe_frame_type(char *str)
   4585 {
   4586     bcm_field_roe_frame_type_t roe_frame_type;
   4587     char *roe_frame_type_text[bcmFieldRoeFrameTypeCount] = BCM_FIELD_ROE_FRAME_TYPE_STRINGS;
   4588     char                tbl_str[FP_ROE_FRAME_TYPE_STR_SZ];
   4589     char                lng_str[FP_ROE_FRAME_TYPE_STR_SZ];
   4590 
   4591     if (str == NULL) {
   4592         return bcmFieldRoeFrameTypeCount;
   4593     }
   4594 
   4595     if (isint(str)) {
   4596         return parse_integer(str);
   4597     }
   4598 
   4599     for (roe_frame_type = 0; roe_frame_type < bcmFieldRoeFrameTypeCount; roe_frame_type++) {
   4600         sal_memset(tbl_str, 0, sizeof(char) * FP_ROE_FRAME_TYPE_STR_SZ);
   4601         sal_memset(lng_str, 0, sizeof(char) * FP_ROE_FRAME_TYPE_STR_SZ);
   4602         /* Test for the suffix only */
   4603         sal_strncpy(tbl_str, roe_frame_type_text[roe_frame_type],
   4604                     FP_ROE_FRAME_TYPE_STR_SZ - 1);
   4605         if (!sal_strcasecmp(tbl_str, str)) {
   4606             break;
   4607         }
   4608         /* Test for whole name of the action */
   4609         sal_strncpy(lng_str, "bcmFieldRoeFrameType", sizeof (lng_str));
   4610         sal_strncat(lng_str, tbl_str,
   4611                     FP_ROE_FRAME_TYPE_STR_SZ - 1 - \
   4612                     sal_strlen("bcmFieldRoeFrameType"));
   4613         if (!sal_strcasecmp(lng_str, str)) {
   4614             break;
   4615         }
   4616     }
   4617     return roe_frame_type;
   4618 }
   4619 
   4620 /*
   4621  * Function:
   4622  *     format_field_decap
   4623  * Purpose:
   4624  *    Format a bcm_field_decap_t variable for output.
   4625  * Parameters:
   4626  *    buf       - character buffer where string is written
   4627  *    decap     - Field decap value
   4628  * Returns:
   4629  *    pointer to buffer for printf-style usage
   4630  */
   4631 char *
   4632 format_field_decap(char *buf, bcm_field_decap_t decap)
   4633 {
   4634     char *decap_text[bcmFieldDecapCount] = BCM_FIELD_DECAP_STRINGS;
   4635 
   4636     assert(buf != NULL);
   4637 
   4638     if (0 <= decap && decap < bcmFieldDecapCount) {
   4639         sal_sprintf(buf, "bcmFieldDecap%s", decap_text[decap]);
   4640     } else {
   4641         sal_sprintf(buf, "invalid decap value=%#x", decap);
   4642     }
   4643 
   4644     return buf;
   4645 }
   4646 
   4647 /*
   4648  * Routine to load a big-endian value from a packet with no alignment
   4649  * restrictions.  Size is the length of the value in bytes (0-4).
   4650  */
   4651 
   4652 uint32
   4653 packet_load(uint8 *addr, int size)
   4654 {
   4655     uint32              val = 0;
   4656 
   4657     switch (size) {
   4658     default:
   4659         val |= (uint32) *addr++ << 24;
   4660         /* Fall through */
   4661     case 3:
   4662         val |= (uint32) *addr++ << 16;
   4663     case 2:
   4664         val |= (uint32) *addr++ << 8;
   4665     case 1:
   4666         val |= (uint32) *addr++ << 0;
   4667     case 0:
   4668         ;
   4669     }
   4670 
   4671     return val;
   4672 }
   4673 /*
   4674  * Random Pattern Packet Filler
   4675  *
   4676  * Fills a buffer of bytes with a random pattern.
   4677  * There are no alignment restrictions on the buffer and length.
   4678  */
   4679 
   4680 void
   4681 packet_random_store(uint8 *buf, int size)
   4682 {
   4683     int                 align_off = ((sal_vaddr_t) buf & 3);
   4684     int                 pat_off = 24;
   4685     uint32              pat;
   4686 
   4687     pat = sal_rand();
   4688 
   4689     if (align_off) {
   4690         /* Store bytes from pat (MSB ==> LSB) until buf is aligned. */
   4691 
   4692         for (; ((sal_vaddr_t) buf & 3) != 0 && size > 0; pat_off -= 8, size--) {
   4693             *buf++ = pat >> pat_off;
   4694         }
   4695     }
   4696 
   4697     /* Store whole words. */
   4698 
   4699     for (; size > 3; buf += 4, size -= 4) {
   4700         pat = sal_rand();
   4701         *(uint32 *) buf = bcm_htonl(pat);
   4702     }
   4703     /* Store up to 3 residual bytes. */
   4704 
   4705     pat = sal_rand();
   4706     for (; size > 0; size--, pat_off -= 8) {
   4707         *buf++ = pat >> pat_off;
   4708         if (pat_off == 0) {
   4709             pat = sal_rand();
   4710             pat_off = 24;
   4711         }
   4712     }
   4713 }
   4714 
   4715 /*
   4716  * Optimized Packet Filler
   4717  *
   4718  * Fills a buffer of bytes with a 32-bit incrementing pattern in
   4719  * big-endian order.  There are no alignment restrictions on the buffer
   4720  * and length.
   4721  *
   4722  * The increment value is added to the pattern each time it is stored
   4723  * (every 4 bytes).  The final value of the pattern is returned (after
   4724  * all the incrementing).
   4725  */
   4726 
   4727 uint32
   4728 packet_store(uint8 *buf, int size, uint32 pat, uint32 inc)
   4729 {
   4730     int                 align_off = ((sal_vaddr_t) buf & 3);
   4731     int                 pat_off = 24;
   4732 
   4733     if (align_off) {
   4734         int             align_shr = align_off * 8;
   4735         int             align_shl = 32 - align_shr;
   4736 
   4737         /* Store bytes from pat (MSB ==> LSB) until buf is aligned. */
   4738 
   4739         for (; ((sal_vaddr_t)buf & 3) != 0 && size > 0; pat_off -= 8, size--) {
   4740             *buf++ = pat >> pat_off;
   4741         }
   4742 
   4743         /* Store whole words, incrementing pat in the middle of words. */
   4744 
   4745         for (; size > 3; buf += 4, size -= 4) {
   4746             uint32 x = pat << align_shl;
   4747             pat += inc;
   4748             x |= pat >> align_shr;
   4749             *(uint32 *)buf = bcm_htonl(x);
   4750         }
   4751     } else {
   4752         for (; size > 3; buf += 4, size -= 4, pat += inc) {
   4753             *(uint32 *)buf = bcm_htonl(pat);
   4754         }
   4755     }
   4756 
   4757     /* Store up to 3 residual bytes. */
   4758 
   4759     for (; size > 0; size--, pat_off -= 8) {
   4760         *buf++ = pat >> pat_off;
   4761         if (pat_off == 0) {
   4762             pat += inc;         /* Add increment and wrap around to MSB */
   4763             pat_off = 32;
   4764         }
   4765     }
   4766 
   4767     return pat;
   4768 }
   4769 
   4770 /*
   4771  * Optimized packet compare
   4772  *
   4773  * Returns byte offset of first mismatch, -1 for compare equal.
   4774  */
   4775 
   4776 int
   4777 packet_compare(uint8 *p1, uint8 *p2, int size)
   4778 {
   4779     int                 i = 0;
   4780 
   4781     if ((((sal_vaddr_t) p1 ^ (sal_vaddr_t) p2) & 3) != 0) {
   4782         goto residual;
   4783     }
   4784 
   4785     for (; ((sal_vaddr_t) p1 & 3) != 0 && i < size; i++) {
   4786         if (p1[i] != p2[i]) {
   4787             return i;
   4788         }
   4789     }
   4790 
   4791     for (; i < size - 3; i += 4) {
   4792         if (*(uint32 *) &p1[i] != *(uint32 *) &p2[i]) {
   4793             break;
   4794         }
   4795     }
   4796 
   4797  residual:
   4798 
   4799     for (; i < size; i++) {
   4800         if (p1[i] != p2[i]) {
   4801             return i;
   4802         }
   4803     }
   4804 
   4805     return -1;
   4806 }
   4807 
   4808 static struct {
   4809     char                *str;
   4810     soc_phy_control_longreach_ability_t     pa;
   4811 } lr_pa_map[] = {
   4812     /* Multi-bit masks should come before their comprised 1-bit masks */
   4813     { "10x1",      SOC_PHY_CONTROL_LONGREACH_ABILITY_10M_1PAIR },
   4814     { "10x2",      SOC_PHY_CONTROL_LONGREACH_ABILITY_10M_2PAIR },
   4815     { "20x1",      SOC_PHY_CONTROL_LONGREACH_ABILITY_20M_1PAIR },
   4816     { "20x2",      SOC_PHY_CONTROL_LONGREACH_ABILITY_20M_2PAIR },
   4817     { "25x1",      SOC_PHY_CONTROL_LONGREACH_ABILITY_25M_1PAIR },
   4818     { "25x2",      SOC_PHY_CONTROL_LONGREACH_ABILITY_25M_2PAIR },
   4819     { "33x1",      SOC_PHY_CONTROL_LONGREACH_ABILITY_33M_1PAIR },
   4820     { "33x2",      SOC_PHY_CONTROL_LONGREACH_ABILITY_33M_2PAIR },
   4821     { "50x1",      SOC_PHY_CONTROL_LONGREACH_ABILITY_50M_1PAIR },
   4822     { "50x2",      SOC_PHY_CONTROL_LONGREACH_ABILITY_50M_2PAIR },
   4823     { "100x1",     SOC_PHY_CONTROL_LONGREACH_ABILITY_100M_1PAIR },
   4824     { "100x2",     SOC_PHY_CONTROL_LONGREACH_ABILITY_100M_2PAIR },
   4825     { "100x4",     SOC_PHY_CONTROL_LONGREACH_ABILITY_100M_4PAIR },
   4826     { "pause_rx",  SOC_PHY_CONTROL_LONGREACH_ABILITY_PAUSE_RX },
   4827     { "pause_tx",  SOC_PHY_CONTROL_LONGREACH_ABILITY_PAUSE_TX },
   4828     { NULL, 0 },
   4829 };
   4830 
   4831 int
   4832 parse_phy_control_longreach_ability(char *str, soc_phy_control_longreach_ability_t *ability)
   4833 {
   4834     int                 i;
   4835     char                *s = str;
   4836 
   4837     *ability = 0;
   4838 
   4839     while (*s != 0) {
   4840         for (i = 0; lr_pa_map[i].str != NULL; i++) {
   4841             int len = sal_strlen(lr_pa_map[i].str);
   4842 
   4843             if (sal_strncasecmp(s, lr_pa_map[i].str, len) == 0 &&
   4844                 (s[len] == 0 || s[len] == ',')) {
   4845 
   4846                 *ability |= lr_pa_map[i].pa;
   4847 
   4848                 if (*(s += len) == ',') {
   4849                     s++;
   4850                 }
   4851 
   4852                 break;
   4853             }
   4854         }
   4855 
   4856         if (lr_pa_map[i].str == NULL) {
   4857             return -1;
   4858         }
   4859     }
   4860 
   4861     return 0;
   4862 }
   4863 
   4864 void
   4865 format_phy_control_longreach_ability(char *buf, int bufsize, soc_phy_control_longreach_ability_t ability)
   4866 {
   4867     int                 i, first = 1;
   4868 
   4869     assert(bufsize >= 80);
   4870 
   4871     buf[0] = 0;
   4872 
   4873     for (i = 0; ability != 0 && lr_pa_map[i].str != NULL; i++) {
   4874         if ((ability & lr_pa_map[i].pa) == lr_pa_map[i].pa) {
   4875             if (first) {
   4876                 first = 0;
   4877             } else {
   4878                 *buf++ = ',';
   4879             }
   4880 
   4881             sal_strncpy(buf, lr_pa_map[i].str, bufsize);
   4882 
   4883             while (*buf != 0) {
   4884                 buf++;
   4885             }
   4886 
   4887             ability &= ~lr_pa_map[i].pa;
   4888         }
   4889     }
   4890 
   4891 }
   4892 
   4893 pbmp_t
   4894 soc_property_get_bcm_pbmp(int unit, const char *name, int defneg)
   4895 {
   4896     pbmp_t pbmp = soc_property_get_pbmp(unit, name, defneg);
   4897 
   4898     BCM_API_XLATE_PORT_PBMP_P2A(unit, &pbmp);
   4899 
   4900     return pbmp;
   4901 }
   4902 
   4903 uint32
   4904 soc_property_bcm_port_get(int unit, bcm_port_t aport,
   4905                           const char *name, uint32 defl)
   4906 {
   4907     soc_port_t port = aport;
   4908 
   4909     BCM_API_XLATE_PORT_A2P(unit, &port);
   4910 
   4911     return soc_property_port_get(unit, port, name, defl);
   4912 }
   4913 
   4914 
   4915 int soc_phy_fw_acquire_default(const char *file_name, uint8 **fw, int *fw_len)
   4916 {
   4917 #ifndef  NO_FILEIO
   4918     FILE *fp;
   4919     uint8 *buffer;
   4920     int buffer_size, offset;
   4921 
   4922     if ((fp = sal_fopen((char *)file_name, "rb")) == NULL) {
   4923         return SOC_E_FAIL;
   4924     }
   4925 
   4926     buffer_size = sal_fsize(fp);
   4927 
   4928     /* some implementations of sal_fsize cannot move the file pointer back to the begining */
   4929     sal_fclose(fp);
   4930     if ((fp = sal_fopen((char *)file_name, "rb")) == NULL) {
   4931         return SOC_E_FAIL;
   4932     }
   4933 
   4934     if (buffer_size == -1) {
   4935     /* cannot determine the f/w file size */
   4936         buffer_size = MAX_FW_BUF_LEN;
   4937     }
   4938 
   4939     buffer = sal_alloc(buffer_size,"firmware_buffer");
   4940     if (buffer == NULL) {
   4941         sal_fclose(fp);
   4942         cli_out("ERROR: Can't allocate enough buffer : 0x%x\n",
   4943                 buffer_size);
   4944         return SOC_E_FAIL;
   4945     }
   4946 
   4947     /* coverity[tainted_data_argument] */
   4948     offset = sal_fread(buffer, 1, buffer_size, fp);
   4949     if (sal_ferror(fp)) {
   4950         cli_out("ERROR: Can't read from file : %s\n", file_name);
   4951         /* coverity[tainted_data] */
   4952         sal_free(buffer);
   4953         sal_fclose(fp);
   4954         return SOC_E_FAIL;
   4955     }
   4956 
   4957     sal_fclose(fp);
   4958 
   4959     *fw = buffer;
   4960     *fw_len = offset;
   4961 
   4962     return SOC_E_NONE;
   4963 #else
   4964     return SOC_E_FAIL;
   4965 #endif
   4966 
   4967 }
   4968 
   4969 int soc_phy_fw_release_default(const char *dev_name, uint8 *fw, int fw_len)
   4970 {
   4971     if (fw) {
   4972         sal_free(fw);
   4973     }
   4974     return SOC_E_NONE;
   4975 }
   4976 
   4977 
   4978 #if defined(BROADCOM_DEBUG)
   4979 
   4980 #define CHK_FLAG(pkt, flag, offset, line, desc) \
   4981     do { \
   4982         if ((pkt)->flags & (flag)) { \
   4983             sal_sprintf(&(line)[offset], desc); \
   4984             (offset) = sal_strlen(line); \
   4985         } \
   4986     } while (0)
   4987 
   4988 STATIC char *_rx_pkt_dump_reason_names[bcmRxReasonCount] =
   4989                                         BCM_RX_REASON_NAMES_INITIALIZER;
   4990 
   4991 void
   4992 bcm_pkt_dump(int unit, bcm_pkt_t *pkt, int dump_data)
   4993 {
   4994     char pbm_str[SOC_PBMP_FMT_LEN],
   4995         upbm_str[SOC_PBMP_FMT_LEN],
   4996         l3pbm_str[SOC_PBMP_FMT_LEN];
   4997     char line[80];
   4998     int i;
   4999     int nl = 1;
   5000     int offset = 0;
   5001 
   5002     COMPILER_REFERENCE(unit);
   5003 
   5004     cli_out("Packet dump:  %p.  Data in %d blocks.\n", (void *)pkt,
   5005             pkt->blk_count);
   5006     for (i = 0; i < pkt->blk_count; i++) {
   5007         sal_sprintf(&line[offset], "%s(0x%p, %d)", nl ? "" : ", ",
   5008                     (void *)pkt->pkt_data[i].data, pkt->pkt_data[i].len);
   5009         offset = sal_strlen(line);
   5010         if (!((i+1) % 4)) {
   5011             cli_out("    %s\n", line);
   5012             nl = 1;
   5013             offset = 0;
   5014         } else {
   5015             nl = 0;
   5016         }
   5017     }
   5018 
   5019     if (!nl) {
   5020         cli_out("    %s\n", line);
   5021     }
   5022     line[0] = '\0';
   5023 
   5024     cli_out("  unit %d. %s %d. sm %d. dp %d. dm %d. cos %d. "
   5025             "prio_int %d.\n",
   5026             pkt->unit,  (pkt->flags & BCM_PKT_F_TRUNK) ? "st" : "sp",
   5027             (pkt->flags & BCM_PKT_F_TRUNK) ? pkt->src_trunk : pkt->src_port,
   5028             pkt->src_mod, pkt->dest_port, pkt->dest_mod, pkt->cos, pkt->prio_int);
   5029     cli_out("  opcode 0x%x. base_len %d. tot_len %d.\n",
   5030             pkt->opcode, pkt->pkt_len, pkt->tot_len);
   5031     cli_out("  tx pbm %s. upbm %s. l3pbm %s\n",
   5032             SOC_PBMP_FMT(pkt->tx_pbmp, pbm_str),
   5033             SOC_PBMP_FMT(pkt->tx_upbmp, upbm_str),
   5034             SOC_PBMP_FMT(pkt->tx_l3pbmp, l3pbm_str));
   5035     cli_out("  rx_reason 0x%x. rx_unit %d."
   5036             " rx_port %d. rx_cpu_cos %d. %s.\n",
   5037             pkt->rx_reason, pkt->rx_unit, pkt->rx_port, pkt->rx_cpu_cos,
   5038             (pkt->rx_untagged & BCM_PKT_OUTER_UNTAGGED) ?
   5039             ((pkt->rx_untagged & BCM_PKT_INNER_UNTAGGED) ?
   5040             "Untagged" : "Inner tagged") :
   5041             ((pkt->rx_untagged & BCM_PKT_INNER_UNTAGGED) ?
   5042             "Outer tagged" : "Double tagged"));
   5043 
   5044     cli_out("  matched %d. classification-tag %d. timestamp %d.\n",
   5045             pkt->rx_matched,
   5046             pkt->rx_classification_tag,
   5047             pkt->rx_timestamp);
   5048     for (i = 0; i < bcmRxReasonCount; i++) {
   5049         if (BCM_RX_REASON_GET(pkt->rx_reasons, i)) {
   5050             cli_out("  reasons: %s\n", _rx_pkt_dump_reason_names[i]);
   5051         }
   5052     }
   5053 
   5054     offset = 0;
   5055     CHK_FLAG(pkt, BCM_PKT_F_HGHDR, offset, line, "hg_hdr ");
   5056     CHK_FLAG(pkt, BCM_PKT_F_SLTAG, offset, line, "sl_tag ");
   5057     CHK_FLAG(pkt, BCM_PKT_F_NO_VTAG, offset, line, "no_vtag ");
   5058     cli_out("  flags-->%s\n", line);
   5059 
   5060     offset = 0;
   5061     CHK_FLAG(pkt, BCM_TX_CRC_ALLOC, offset, line, "crc_alloc ");
   5062     CHK_FLAG(pkt, BCM_TX_CRC_REGEN, offset, line, "crc_regen ");
   5063     CHK_FLAG(pkt, BCM_TX_CRC_FORCE_ERROR, offset, line,
   5064              "crc_force_error ");
   5065     cli_out("  tx flags-->%s\n", line);
   5066 
   5067     offset = 0;
   5068     CHK_FLAG(pkt, BCM_RX_CRC_STRIP, offset, line, "crc_strip ");
   5069     CHK_FLAG(pkt, BCM_PKT_F_NO_VTAG, offset, line, "vtag_strip ");
   5070     cli_out("  rx flags-->%s\n", line);
   5071 
   5072     cli_out("  dma chan %d. adr pkt_data %p. idx %d. dv %p\n",
   5073             pkt->dma_channel, (void *)&pkt->_pkt_data, pkt->_idx, pkt->_dv);
   5074     cli_out("  hghdr: 0x%08x%08x%08x. sltag 0x%x. vtag 0x%x\n",
   5075             ((uint32 *)(pkt->_higig))[0], ((uint32 *)(pkt->_higig))[1],
   5076             ((uint32 *)(pkt->_higig))[2], ((uint32 *)(pkt->_sltag))[0],
   5077             ((uint32 *)(pkt->_vtag))[0]);
   5078 
   5079     if (dump_data) {
   5080         int blk, byte = 0, tot_byte = 0;
   5081 
   5082         offset = 0;
   5083         for (blk = 0; blk < pkt->blk_count; blk++) {
   5084             for (byte = 0; byte < pkt->pkt_data[blk].len; byte++) {
   5085                 ++tot_byte;
   5086                 sal_sprintf(&line[offset], "%02x%s",
   5087                             pkt->pkt_data[blk].data[byte],
   5088                             !(tot_byte % 4) ? " " : "");
   5089                 offset = sal_strlen(line);
   5090                 if (!(tot_byte % 16)) {
   5091                     cli_out("data[%04d]:  %s\n", tot_byte - 16, line);
   5092                     offset = 0;
   5093                 }
   5094                 if (tot_byte >= pkt->pkt_len) { /* Displayed all of packet */
   5095                     goto loop_exit;
   5096                 }
   5097             }
   5098         }
   5099 
   5100     loop_exit:
   5101         if (tot_byte % 16) {
   5102             cli_out("data[%04d]:  %s\n", 16 * (tot_byte / 16), line);
   5103         }
   5104     }
   5105 }
   5106 
   5107 #endif /* BROADCOM_DEBUG */