1*2bfe3f2eSlogwang /*- 2*2bfe3f2eSlogwang * BSD LICENSE 3*2bfe3f2eSlogwang * 4*2bfe3f2eSlogwang * Copyright(c) 2016 Intel Corporation. All rights reserved. 5*2bfe3f2eSlogwang * Copyright(c) 2017 Cavium, Inc. All rights reserved. 6*2bfe3f2eSlogwang * All rights reserved. 7*2bfe3f2eSlogwang * 8*2bfe3f2eSlogwang * Redistribution and use in source and binary forms, with or without 9*2bfe3f2eSlogwang * modification, are permitted provided that the following conditions 10*2bfe3f2eSlogwang * are met: 11*2bfe3f2eSlogwang * 12*2bfe3f2eSlogwang * * Redistributions of source code must retain the above copyright 13*2bfe3f2eSlogwang * notice, this list of conditions and the following disclaimer. 14*2bfe3f2eSlogwang * * Redistributions in binary form must reproduce the above copyright 15*2bfe3f2eSlogwang * notice, this list of conditions and the following disclaimer in 16*2bfe3f2eSlogwang * the documentation and/or other materials provided with the 17*2bfe3f2eSlogwang * distribution. 18*2bfe3f2eSlogwang * * Neither the name of Intel Corporation nor the names of its 19*2bfe3f2eSlogwang * contributors may be used to endorse or promote products derived 20*2bfe3f2eSlogwang * from this software without specific prior written permission. 21*2bfe3f2eSlogwang * 22*2bfe3f2eSlogwang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23*2bfe3f2eSlogwang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24*2bfe3f2eSlogwang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25*2bfe3f2eSlogwang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26*2bfe3f2eSlogwang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27*2bfe3f2eSlogwang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28*2bfe3f2eSlogwang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29*2bfe3f2eSlogwang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30*2bfe3f2eSlogwang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31*2bfe3f2eSlogwang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32*2bfe3f2eSlogwang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33*2bfe3f2eSlogwang */ 34*2bfe3f2eSlogwang 35*2bfe3f2eSlogwang #include <stdint.h> 36*2bfe3f2eSlogwang #include <stdlib.h> 37*2bfe3f2eSlogwang #include <stdio.h> 38*2bfe3f2eSlogwang #include <ctype.h> 39*2bfe3f2eSlogwang #include <getopt.h> 40*2bfe3f2eSlogwang #include <errno.h> 41*2bfe3f2eSlogwang #include <stdarg.h> 42*2bfe3f2eSlogwang #include <string.h> 43*2bfe3f2eSlogwang #include <libgen.h> 44*2bfe3f2eSlogwang #include <unistd.h> 45*2bfe3f2eSlogwang #include <sys/wait.h> 46*2bfe3f2eSlogwang #include <stdbool.h> 47*2bfe3f2eSlogwang 48*2bfe3f2eSlogwang #include <rte_errno.h> 49*2bfe3f2eSlogwang #include <rte_string_fns.h> 50*2bfe3f2eSlogwang 51*2bfe3f2eSlogwang #include "parser.h" 52*2bfe3f2eSlogwang 53*2bfe3f2eSlogwang static uint32_t 54*2bfe3f2eSlogwang get_hex_val(char c) 55*2bfe3f2eSlogwang { 56*2bfe3f2eSlogwang switch (c) { 57*2bfe3f2eSlogwang case '0': case '1': case '2': case '3': case '4': case '5': 58*2bfe3f2eSlogwang case '6': case '7': case '8': case '9': 59*2bfe3f2eSlogwang return c - '0'; 60*2bfe3f2eSlogwang case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 61*2bfe3f2eSlogwang return c - 'A' + 10; 62*2bfe3f2eSlogwang case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 63*2bfe3f2eSlogwang return c - 'a' + 10; 64*2bfe3f2eSlogwang default: 65*2bfe3f2eSlogwang return 0; 66*2bfe3f2eSlogwang } 67*2bfe3f2eSlogwang } 68*2bfe3f2eSlogwang 69*2bfe3f2eSlogwang int 70*2bfe3f2eSlogwang parser_read_arg_bool(const char *p) 71*2bfe3f2eSlogwang { 72*2bfe3f2eSlogwang p = skip_white_spaces(p); 73*2bfe3f2eSlogwang int result = -EINVAL; 74*2bfe3f2eSlogwang 75*2bfe3f2eSlogwang if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || 76*2bfe3f2eSlogwang ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { 77*2bfe3f2eSlogwang p += 3; 78*2bfe3f2eSlogwang result = 1; 79*2bfe3f2eSlogwang } 80*2bfe3f2eSlogwang 81*2bfe3f2eSlogwang if (((p[0] == 'o') && (p[1] == 'n')) || 82*2bfe3f2eSlogwang ((p[0] == 'O') && (p[1] == 'N'))) { 83*2bfe3f2eSlogwang p += 2; 84*2bfe3f2eSlogwang result = 1; 85*2bfe3f2eSlogwang } 86*2bfe3f2eSlogwang 87*2bfe3f2eSlogwang if (((p[0] == 'n') && (p[1] == 'o')) || 88*2bfe3f2eSlogwang ((p[0] == 'N') && (p[1] == 'O'))) { 89*2bfe3f2eSlogwang p += 2; 90*2bfe3f2eSlogwang result = 0; 91*2bfe3f2eSlogwang } 92*2bfe3f2eSlogwang 93*2bfe3f2eSlogwang if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || 94*2bfe3f2eSlogwang ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { 95*2bfe3f2eSlogwang p += 3; 96*2bfe3f2eSlogwang result = 0; 97*2bfe3f2eSlogwang } 98*2bfe3f2eSlogwang 99*2bfe3f2eSlogwang p = skip_white_spaces(p); 100*2bfe3f2eSlogwang 101*2bfe3f2eSlogwang if (p[0] != '\0') 102*2bfe3f2eSlogwang return -EINVAL; 103*2bfe3f2eSlogwang 104*2bfe3f2eSlogwang return result; 105*2bfe3f2eSlogwang } 106*2bfe3f2eSlogwang 107*2bfe3f2eSlogwang int 108*2bfe3f2eSlogwang parser_read_uint64(uint64_t *value, const char *p) 109*2bfe3f2eSlogwang { 110*2bfe3f2eSlogwang char *next; 111*2bfe3f2eSlogwang uint64_t val; 112*2bfe3f2eSlogwang 113*2bfe3f2eSlogwang p = skip_white_spaces(p); 114*2bfe3f2eSlogwang if (!isdigit(*p)) 115*2bfe3f2eSlogwang return -EINVAL; 116*2bfe3f2eSlogwang 117*2bfe3f2eSlogwang val = strtoul(p, &next, 10); 118*2bfe3f2eSlogwang if (p == next) 119*2bfe3f2eSlogwang return -EINVAL; 120*2bfe3f2eSlogwang 121*2bfe3f2eSlogwang p = next; 122*2bfe3f2eSlogwang switch (*p) { 123*2bfe3f2eSlogwang case 'T': 124*2bfe3f2eSlogwang val *= 1024ULL; 125*2bfe3f2eSlogwang /* fall through */ 126*2bfe3f2eSlogwang case 'G': 127*2bfe3f2eSlogwang val *= 1024ULL; 128*2bfe3f2eSlogwang /* fall through */ 129*2bfe3f2eSlogwang case 'M': 130*2bfe3f2eSlogwang val *= 1024ULL; 131*2bfe3f2eSlogwang /* fall through */ 132*2bfe3f2eSlogwang case 'k': 133*2bfe3f2eSlogwang case 'K': 134*2bfe3f2eSlogwang val *= 1024ULL; 135*2bfe3f2eSlogwang p++; 136*2bfe3f2eSlogwang break; 137*2bfe3f2eSlogwang } 138*2bfe3f2eSlogwang 139*2bfe3f2eSlogwang p = skip_white_spaces(p); 140*2bfe3f2eSlogwang if (*p != '\0') 141*2bfe3f2eSlogwang return -EINVAL; 142*2bfe3f2eSlogwang 143*2bfe3f2eSlogwang *value = val; 144*2bfe3f2eSlogwang return 0; 145*2bfe3f2eSlogwang } 146*2bfe3f2eSlogwang 147*2bfe3f2eSlogwang int 148*2bfe3f2eSlogwang parser_read_int32(int32_t *value, const char *p) 149*2bfe3f2eSlogwang { 150*2bfe3f2eSlogwang char *next; 151*2bfe3f2eSlogwang int32_t val; 152*2bfe3f2eSlogwang 153*2bfe3f2eSlogwang p = skip_white_spaces(p); 154*2bfe3f2eSlogwang if (!isdigit(*p)) 155*2bfe3f2eSlogwang return -EINVAL; 156*2bfe3f2eSlogwang 157*2bfe3f2eSlogwang val = strtol(p, &next, 10); 158*2bfe3f2eSlogwang if (p == next) 159*2bfe3f2eSlogwang return -EINVAL; 160*2bfe3f2eSlogwang 161*2bfe3f2eSlogwang *value = val; 162*2bfe3f2eSlogwang return 0; 163*2bfe3f2eSlogwang } 164*2bfe3f2eSlogwang 165*2bfe3f2eSlogwang int 166*2bfe3f2eSlogwang parser_read_uint64_hex(uint64_t *value, const char *p) 167*2bfe3f2eSlogwang { 168*2bfe3f2eSlogwang char *next; 169*2bfe3f2eSlogwang uint64_t val; 170*2bfe3f2eSlogwang 171*2bfe3f2eSlogwang p = skip_white_spaces(p); 172*2bfe3f2eSlogwang 173*2bfe3f2eSlogwang val = strtoul(p, &next, 16); 174*2bfe3f2eSlogwang if (p == next) 175*2bfe3f2eSlogwang return -EINVAL; 176*2bfe3f2eSlogwang 177*2bfe3f2eSlogwang p = skip_white_spaces(next); 178*2bfe3f2eSlogwang if (*p != '\0') 179*2bfe3f2eSlogwang return -EINVAL; 180*2bfe3f2eSlogwang 181*2bfe3f2eSlogwang *value = val; 182*2bfe3f2eSlogwang return 0; 183*2bfe3f2eSlogwang } 184*2bfe3f2eSlogwang 185*2bfe3f2eSlogwang int 186*2bfe3f2eSlogwang parser_read_uint32(uint32_t *value, const char *p) 187*2bfe3f2eSlogwang { 188*2bfe3f2eSlogwang uint64_t val = 0; 189*2bfe3f2eSlogwang int ret = parser_read_uint64(&val, p); 190*2bfe3f2eSlogwang 191*2bfe3f2eSlogwang if (ret < 0) 192*2bfe3f2eSlogwang return ret; 193*2bfe3f2eSlogwang 194*2bfe3f2eSlogwang if (val > UINT32_MAX) 195*2bfe3f2eSlogwang return -ERANGE; 196*2bfe3f2eSlogwang 197*2bfe3f2eSlogwang *value = val; 198*2bfe3f2eSlogwang return 0; 199*2bfe3f2eSlogwang } 200*2bfe3f2eSlogwang 201*2bfe3f2eSlogwang int 202*2bfe3f2eSlogwang parser_read_uint32_hex(uint32_t *value, const char *p) 203*2bfe3f2eSlogwang { 204*2bfe3f2eSlogwang uint64_t val = 0; 205*2bfe3f2eSlogwang int ret = parser_read_uint64_hex(&val, p); 206*2bfe3f2eSlogwang 207*2bfe3f2eSlogwang if (ret < 0) 208*2bfe3f2eSlogwang return ret; 209*2bfe3f2eSlogwang 210*2bfe3f2eSlogwang if (val > UINT32_MAX) 211*2bfe3f2eSlogwang return -ERANGE; 212*2bfe3f2eSlogwang 213*2bfe3f2eSlogwang *value = val; 214*2bfe3f2eSlogwang return 0; 215*2bfe3f2eSlogwang } 216*2bfe3f2eSlogwang 217*2bfe3f2eSlogwang int 218*2bfe3f2eSlogwang parser_read_uint16(uint16_t *value, const char *p) 219*2bfe3f2eSlogwang { 220*2bfe3f2eSlogwang uint64_t val = 0; 221*2bfe3f2eSlogwang int ret = parser_read_uint64(&val, p); 222*2bfe3f2eSlogwang 223*2bfe3f2eSlogwang if (ret < 0) 224*2bfe3f2eSlogwang return ret; 225*2bfe3f2eSlogwang 226*2bfe3f2eSlogwang if (val > UINT16_MAX) 227*2bfe3f2eSlogwang return -ERANGE; 228*2bfe3f2eSlogwang 229*2bfe3f2eSlogwang *value = val; 230*2bfe3f2eSlogwang return 0; 231*2bfe3f2eSlogwang } 232*2bfe3f2eSlogwang 233*2bfe3f2eSlogwang int 234*2bfe3f2eSlogwang parser_read_uint16_hex(uint16_t *value, const char *p) 235*2bfe3f2eSlogwang { 236*2bfe3f2eSlogwang uint64_t val = 0; 237*2bfe3f2eSlogwang int ret = parser_read_uint64_hex(&val, p); 238*2bfe3f2eSlogwang 239*2bfe3f2eSlogwang if (ret < 0) 240*2bfe3f2eSlogwang return ret; 241*2bfe3f2eSlogwang 242*2bfe3f2eSlogwang if (val > UINT16_MAX) 243*2bfe3f2eSlogwang return -ERANGE; 244*2bfe3f2eSlogwang 245*2bfe3f2eSlogwang *value = val; 246*2bfe3f2eSlogwang return 0; 247*2bfe3f2eSlogwang } 248*2bfe3f2eSlogwang 249*2bfe3f2eSlogwang int 250*2bfe3f2eSlogwang parser_read_uint8(uint8_t *value, const char *p) 251*2bfe3f2eSlogwang { 252*2bfe3f2eSlogwang uint64_t val = 0; 253*2bfe3f2eSlogwang int ret = parser_read_uint64(&val, p); 254*2bfe3f2eSlogwang 255*2bfe3f2eSlogwang if (ret < 0) 256*2bfe3f2eSlogwang return ret; 257*2bfe3f2eSlogwang 258*2bfe3f2eSlogwang if (val > UINT8_MAX) 259*2bfe3f2eSlogwang return -ERANGE; 260*2bfe3f2eSlogwang 261*2bfe3f2eSlogwang *value = val; 262*2bfe3f2eSlogwang return 0; 263*2bfe3f2eSlogwang } 264*2bfe3f2eSlogwang 265*2bfe3f2eSlogwang int 266*2bfe3f2eSlogwang parser_read_uint8_hex(uint8_t *value, const char *p) 267*2bfe3f2eSlogwang { 268*2bfe3f2eSlogwang uint64_t val = 0; 269*2bfe3f2eSlogwang int ret = parser_read_uint64_hex(&val, p); 270*2bfe3f2eSlogwang 271*2bfe3f2eSlogwang if (ret < 0) 272*2bfe3f2eSlogwang return ret; 273*2bfe3f2eSlogwang 274*2bfe3f2eSlogwang if (val > UINT8_MAX) 275*2bfe3f2eSlogwang return -ERANGE; 276*2bfe3f2eSlogwang 277*2bfe3f2eSlogwang *value = val; 278*2bfe3f2eSlogwang return 0; 279*2bfe3f2eSlogwang } 280*2bfe3f2eSlogwang 281*2bfe3f2eSlogwang int 282*2bfe3f2eSlogwang parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) 283*2bfe3f2eSlogwang { 284*2bfe3f2eSlogwang uint32_t i; 285*2bfe3f2eSlogwang 286*2bfe3f2eSlogwang if ((string == NULL) || 287*2bfe3f2eSlogwang (tokens == NULL) || 288*2bfe3f2eSlogwang (*n_tokens < 1)) 289*2bfe3f2eSlogwang return -EINVAL; 290*2bfe3f2eSlogwang 291*2bfe3f2eSlogwang for (i = 0; i < *n_tokens; i++) { 292*2bfe3f2eSlogwang tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); 293*2bfe3f2eSlogwang if (tokens[i] == NULL) 294*2bfe3f2eSlogwang break; 295*2bfe3f2eSlogwang } 296*2bfe3f2eSlogwang 297*2bfe3f2eSlogwang if ((i == *n_tokens) && 298*2bfe3f2eSlogwang (strtok_r(string, PARSE_DELIMITER, &string) != NULL)) 299*2bfe3f2eSlogwang return -E2BIG; 300*2bfe3f2eSlogwang 301*2bfe3f2eSlogwang *n_tokens = i; 302*2bfe3f2eSlogwang return 0; 303*2bfe3f2eSlogwang } 304*2bfe3f2eSlogwang 305*2bfe3f2eSlogwang int 306*2bfe3f2eSlogwang parse_hex_string(char *src, uint8_t *dst, uint32_t *size) 307*2bfe3f2eSlogwang { 308*2bfe3f2eSlogwang char *c; 309*2bfe3f2eSlogwang uint32_t len, i; 310*2bfe3f2eSlogwang 311*2bfe3f2eSlogwang /* Check input parameters */ 312*2bfe3f2eSlogwang if ((src == NULL) || 313*2bfe3f2eSlogwang (dst == NULL) || 314*2bfe3f2eSlogwang (size == NULL) || 315*2bfe3f2eSlogwang (*size == 0)) 316*2bfe3f2eSlogwang return -1; 317*2bfe3f2eSlogwang 318*2bfe3f2eSlogwang len = strlen(src); 319*2bfe3f2eSlogwang if (((len & 3) != 0) || 320*2bfe3f2eSlogwang (len > (*size) * 2)) 321*2bfe3f2eSlogwang return -1; 322*2bfe3f2eSlogwang *size = len / 2; 323*2bfe3f2eSlogwang 324*2bfe3f2eSlogwang for (c = src; *c != 0; c++) { 325*2bfe3f2eSlogwang if ((((*c) >= '0') && ((*c) <= '9')) || 326*2bfe3f2eSlogwang (((*c) >= 'A') && ((*c) <= 'F')) || 327*2bfe3f2eSlogwang (((*c) >= 'a') && ((*c) <= 'f'))) 328*2bfe3f2eSlogwang continue; 329*2bfe3f2eSlogwang 330*2bfe3f2eSlogwang return -1; 331*2bfe3f2eSlogwang } 332*2bfe3f2eSlogwang 333*2bfe3f2eSlogwang /* Convert chars to bytes */ 334*2bfe3f2eSlogwang for (i = 0; i < *size; i++) 335*2bfe3f2eSlogwang dst[i] = get_hex_val(src[2 * i]) * 16 + 336*2bfe3f2eSlogwang get_hex_val(src[2 * i + 1]); 337*2bfe3f2eSlogwang 338*2bfe3f2eSlogwang return 0; 339*2bfe3f2eSlogwang } 340*2bfe3f2eSlogwang 341*2bfe3f2eSlogwang int 342*2bfe3f2eSlogwang parse_lcores_list(bool lcores[], const char *corelist) 343*2bfe3f2eSlogwang { 344*2bfe3f2eSlogwang int i, idx = 0; 345*2bfe3f2eSlogwang int min, max; 346*2bfe3f2eSlogwang char *end = NULL; 347*2bfe3f2eSlogwang 348*2bfe3f2eSlogwang if (corelist == NULL) 349*2bfe3f2eSlogwang return -1; 350*2bfe3f2eSlogwang while (isblank(*corelist)) 351*2bfe3f2eSlogwang corelist++; 352*2bfe3f2eSlogwang i = strlen(corelist); 353*2bfe3f2eSlogwang while ((i > 0) && isblank(corelist[i - 1])) 354*2bfe3f2eSlogwang i--; 355*2bfe3f2eSlogwang 356*2bfe3f2eSlogwang /* Get list of lcores */ 357*2bfe3f2eSlogwang min = RTE_MAX_LCORE; 358*2bfe3f2eSlogwang do { 359*2bfe3f2eSlogwang while (isblank(*corelist)) 360*2bfe3f2eSlogwang corelist++; 361*2bfe3f2eSlogwang if (*corelist == '\0') 362*2bfe3f2eSlogwang return -1; 363*2bfe3f2eSlogwang idx = strtoul(corelist, &end, 10); 364*2bfe3f2eSlogwang 365*2bfe3f2eSlogwang if (end == NULL) 366*2bfe3f2eSlogwang return -1; 367*2bfe3f2eSlogwang while (isblank(*end)) 368*2bfe3f2eSlogwang end++; 369*2bfe3f2eSlogwang if (*end == '-') { 370*2bfe3f2eSlogwang min = idx; 371*2bfe3f2eSlogwang } else if ((*end == ',') || (*end == '\0')) { 372*2bfe3f2eSlogwang max = idx; 373*2bfe3f2eSlogwang if (min == RTE_MAX_LCORE) 374*2bfe3f2eSlogwang min = idx; 375*2bfe3f2eSlogwang for (idx = min; idx <= max; idx++) { 376*2bfe3f2eSlogwang if (lcores[idx] == 1) 377*2bfe3f2eSlogwang return -E2BIG; 378*2bfe3f2eSlogwang lcores[idx] = 1; 379*2bfe3f2eSlogwang } 380*2bfe3f2eSlogwang 381*2bfe3f2eSlogwang min = RTE_MAX_LCORE; 382*2bfe3f2eSlogwang } else 383*2bfe3f2eSlogwang return -1; 384*2bfe3f2eSlogwang corelist = end + 1; 385*2bfe3f2eSlogwang } while (*end != '\0'); 386*2bfe3f2eSlogwang 387*2bfe3f2eSlogwang return 0; 388*2bfe3f2eSlogwang } 389