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