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

pbmp.c (8058B)


      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  * Port Bitmap helper functions
      8  * Only used if _SHR_DEFINE_PBMP_FUNCTIONS is set in <shared/pbmp.h>
      9  * (everything is done inline in <shared/pbmp.h> otherwise)
     10  *
     11  * Well, actually _shr_pbmp_format() is always available
     12  */
     13 
     14 #include <sal/types.h>
     15 #include <sal/core/libc.h>
     16 #include <shared/util.h>
     17 #include <shared/pbmp.h>
     18 #include <sal/appl/sal.h>
     19 
     20 
     21 
     22 /*
     23  * Size of a single range buffer in shr_pbmp_range_format()
     24  */
     25 #define SHR_PBMP_SINGLE_RANGR_FMT_LEN (20)
     26 #ifdef _SHR_DEFINE_PBMP_FUNCTIONS
     27 
     28 
     29 
     30 /* returns 1 is the bitmap is empty */
     31 int
     32 _shr_pbmp_bmnull(_shr_pbmp_t *bmp)
     33 {
     34     int	i;
     35 
     36     for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) {
     37 	if (_SHR_PBMP_WORD_GET(*bmp, i) != 0) {
     38 	    return 0;
     39 	}
     40     }
     41     return 1;
     42 }
     43 
     44 /* returns 1 is the two bitmaps are equal */
     45 int
     46 _shr_pbmp_bmeq(_shr_pbmp_t *bmp1, _shr_pbmp_t *bmp2)
     47 {
     48     int	i;
     49 
     50     for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) {
     51 	if (_SHR_PBMP_WORD_GET(*bmp1, i) != _SHR_PBMP_WORD_GET(*bmp2, i)) {
     52 	    return 0;
     53 	}
     54     }
     55     return 1;
     56 }
     57 
     58 #endif /* _SHR_DEFINE_PBMP_FUNCTIONS */
     59 
     60 /* format a bitmap into a static buffer suitable for printing */
     61 char *
     62 _shr_pbmp_format(_shr_pbmp_t bmp, char *buf)
     63 {
     64     int		i;
     65     char	*bp;
     66 
     67     if (buf == NULL) {
     68 	return buf;
     69     }
     70     buf[0] = '0';
     71     buf[1] = 'x';
     72     bp = &buf[2];
     73     for (i = _SHR_PBMP_WORD_MAX-1; i >= 0; i--) {
     74 	_shr_format_integer(bp, _SHR_PBMP_WORD_GET(bmp, i), 8, 16);
     75 	bp += 8;
     76     }
     77     return buf;
     78 }
     79 
     80 /*
     81  * Parse a string containing a list of ports into a bitmap string.
     82  * The input format is:
     83  *
     84  *      PBMP    : '0x' {HEXDIGIT}+      { return BITS_SET($2); }
     85  *              | LIST                  { return $1; }
     86  *              ;
     87  *      LIST    : [LIST ','] RANGE STEP         { return UNION($1, $2, $3); }
     88  *              | [LIST ','] '~' RANGE STEP     { return REMOVE($1, $2, $3); }
     89  *              ;
     90  *              ;
     91  *      STEP    : ':' INTEGER           { return $2 };
     92  *              ;
     93 
     94  *
     95  * Returns 0 on success, -1 on syntax error.
     96  */
     97 
     98 int
     99 _shr_pbmp_parse(char *s, _shr_pbmp_t *pbmp, uint32 *arr, uint8 *is_hex)
    100 {
    101     _shr_pbmp_t  bmall;
    102     int          plast, pfirst, pstep, port, p = 0, i =0 ,rv = 0;
    103     char        *sn, *se;
    104 
    105     if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
    106 
    107         * is_hex = TRUE;
    108         rv = _shr_pbmp_decode(s, pbmp);
    109         if (rv == 0)
    110         {
    111             _SHR_PBMP_ITER(*pbmp, p)
    112             {
    113                arr[i++] = p;
    114             }
    115         }
    116         return rv;
    117     }
    118 
    119     _SHR_PBMP_CLEAR(bmall);
    120     _SHR_PBMP_CLEAR(*pbmp);
    121 
    122     pfirst = -1;
    123     pstep = 1;
    124 
    125 
    126     while (*s) {
    127 
    128 
    129         for (sn = s; *sn && *sn != '-' && *sn != ','  &&
    130                  !isdigit((unsigned)*sn); sn++) {
    131             ;
    132         }
    133         se = sn;
    134         if (isdigit((unsigned)*sn)) {
    135             port = 0;
    136             do {
    137                 port = port * 10 + (*se++ - '0');
    138             } while (isdigit((unsigned) *se));
    139         } else {
    140             port = -1;
    141         }
    142         plast = -1;
    143 
    144         if (sn == s) {                          /* unprefixed number */
    145             plast = port;
    146         }
    147         s = se;
    148         switch (*s) {
    149         case '-':
    150             pstep = 1;
    151             if (plast < 0) {
    152                 return -1;                      /* error: range without port */
    153             } else if (pfirst < 0) {
    154                 pfirst = plast;
    155             } else {
    156                 return -1;                      /* error: x-y-z */
    157             }
    158             break;
    159             /* fall through */
    160         case ',':
    161         case '\0':
    162             if (plast < 0) {                    /* complete bitmap op */
    163                 pfirst = 999;
    164                 plast = -1;
    165                _SHR_PBMP_ITER(bmall, p) {
    166                     if (p < pfirst) {
    167                         pfirst = p;
    168                     }
    169                     if (p > plast) {
    170                         plast = p;
    171                     }
    172                 }
    173             }
    174             if (pfirst < 0) {           /* just one port */
    175                 pfirst = plast;
    176             }
    177             for (port = pfirst; port <= plast; port += pstep) {  /* a range */
    178                 p =  port ;
    179                 /* coverity[overrun-local] */
    180                 if ((p >= 0) && _SHR_PBMP_NOT_NULL(bmall) && !_SHR_PBMP_MEMBER(bmall, p)) {
    181                     continue;   /* skip gaps in range */
    182                 }
    183                 _SHR_PBMP_PORT_ADD(*pbmp, p );
    184                 arr[i++] = p;
    185                 }
    186             if (*s == '\0') {
    187                 return 0;
    188             }
    189             pfirst = -1;
    190             pstep = 1;
    191             _SHR_PBMP_CLEAR(bmall);
    192             break;
    193         default:
    194             return -1;                          /* error: unexpected char */
    195         }
    196         s += 1;
    197     }
    198     return -1;                                  /* error: unexpected end */
    199 }
    200 
    201 /*
    202  * decode a string in hex format into a bitmap
    203  * returns 0 on success, -1 on error
    204  */
    205 int
    206 _shr_pbmp_decode(char *s, _shr_pbmp_t *bmp)
    207 {
    208     char	*e;
    209     uint32	v;
    210     int		p;
    211 
    212     _SHR_PBMP_CLEAR(*bmp);
    213 
    214     if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
    215 	/* get end of string */
    216 	s += 2;
    217 	for (e = s; *e; e++)
    218 	    ;
    219 	e -= 1;
    220 	/* back up to beginning of string, setting ports as we go */
    221 	p = 0;
    222 	while (e >= s) {
    223 	    if (*e >= '0' && *e <= '9') {
    224 		v = *e - '0';
    225 	    } else if (*e >= 'a' && *e <= 'f') {
    226 		v = *e - 'a' + 10;
    227 	    } else if (*e >= 'A' && *e <= 'F') {
    228 		v = *e - 'A' + 10;
    229 	    } else {
    230 		return -1;		/* error: invalid hex digits */
    231 	    }
    232 	    e -= 1;
    233 	    /* now set a nibble's worth of ports */
    234 	    if ((v & 1) && p < _SHR_PBMP_PORT_MAX) {
    235 		_SHR_PBMP_PORT_ADD(*bmp, p);
    236 	    }
    237 	    p += 1;
    238 	    if ((v & 2) && p < _SHR_PBMP_PORT_MAX) {
    239 		_SHR_PBMP_PORT_ADD(*bmp, p);
    240 	    }
    241 	    p += 1;
    242 	    if ((v & 4) && p < _SHR_PBMP_PORT_MAX) {
    243 		_SHR_PBMP_PORT_ADD(*bmp, p);
    244 	    }
    245 	    p += 1;
    246 	    if ((v & 8) && p < _SHR_PBMP_PORT_MAX) {
    247 		_SHR_PBMP_PORT_ADD(*bmp, p);
    248 	    }
    249 	    p += 1;
    250 	}
    251     } else {
    252 	v = 0;
    253 	while (*s >= '0' && *s <= '9') {
    254 	    v = v * 10 + (*s++ - '0');
    255 	}
    256 	if (*s != '\0') {
    257 	    return -1;			/* error: invalid decimal digits */
    258 	}
    259 	p = 0;
    260 	while (v) {
    261 	    if ((v & 1) && p < _SHR_PBMP_PORT_MAX) {
    262 		_SHR_PBMP_PORT_ADD(*bmp, p);
    263 	    }
    264 	    v >>= 1;
    265 	    p += 1;
    266 	}
    267     }
    268     return 0;
    269 }
    270 
    271 /* 
    272  * format a bitmap into a static buffer suitable for printing - range format 
    273  * If the the string is too long - fallback to printing bitmap 
    274  */
    275 char *
    276 shr_pbmp_range_format(_shr_pbmp_t bmp, char *buf, int buf_size)
    277 {
    278     int port;
    279     int cur_buf_size = 0;
    280     int temp_buf_size = 0;
    281     char temp_buffer[SHR_PBMP_SINGLE_RANGR_FMT_LEN];
    282     int range_start, range_end;
    283     int first_range = 1;
    284 
    285     *buf = 0;
    286 
    287     _SHR_PBMP_ITER(bmp, port)
    288     {
    289         range_start = port;
    290         range_end = port;
    291 
    292         /* iterate until the end of the range */ 
    293         while (port + 1 < _SHR_PBMP_PORT_MAX && _SHR_PBMP_MEMBER(bmp, port + 1))
    294         {
    295             port++;
    296             range_end++;
    297         }
    298 
    299         /* print to temp buffer */
    300         if (range_start == range_end)
    301         {
    302             sal_snprintf(temp_buffer, SHR_PBMP_SINGLE_RANGR_FMT_LEN, "%s%d", first_range ? "" : ", ", range_start);
    303         }
    304         else
    305         {
    306             sal_snprintf(temp_buffer, SHR_PBMP_SINGLE_RANGR_FMT_LEN, "%s%d-%d", first_range ? "" : ", ", range_start, range_end);
    307         } 
    308 
    309         /* check buffer size */
    310         temp_buf_size = sal_strlen(temp_buffer);
    311         cur_buf_size += temp_buf_size;
    312 
    313         /* print to buffer */
    314         if ( cur_buf_size < buf_size - 1)
    315         {
    316             sal_snprintf(buf, buf_size, "%s%s", buf, temp_buffer);
    317         }
    318         else
    319         {
    320             /* fallback to print bitmap */
    321             return _shr_pbmp_format(bmp, buf);
    322         }
    323 
    324         /* unmark first range */
    325         first_range = 0;
    326         /* continue to next range*/
    327     }
    328 
    329     return buf;
    330 }
    331