dpdk/examples/ip_pipeline/parser.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2016 Intel Corporation.
   3 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
   4 * All rights reserved.
   5 */
   6
   7#include <stdint.h>
   8#include <stdlib.h>
   9#include <stdio.h>
  10#include <ctype.h>
  11#include <getopt.h>
  12#include <errno.h>
  13#include <stdarg.h>
  14#include <string.h>
  15#include <libgen.h>
  16#include <unistd.h>
  17#include <sys/wait.h>
  18#include <arpa/inet.h>
  19#include <sys/socket.h>
  20
  21#include <rte_errno.h>
  22#include <rte_string_fns.h>
  23
  24#include "parser.h"
  25
  26static uint32_t
  27get_hex_val(char c)
  28{
  29        switch (c) {
  30        case '0': case '1': case '2': case '3': case '4': case '5':
  31        case '6': case '7': case '8': case '9':
  32                return c - '0';
  33        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  34                return c - 'A' + 10;
  35        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  36                return c - 'a' + 10;
  37        default:
  38                return 0;
  39        }
  40}
  41
  42int
  43parser_read_arg_bool(const char *p)
  44{
  45        p = skip_white_spaces(p);
  46        int result = -EINVAL;
  47
  48        if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
  49                ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
  50                p += 3;
  51                result = 1;
  52        }
  53
  54        if (((p[0] == 'o') && (p[1] == 'n')) ||
  55                ((p[0] == 'O') && (p[1] == 'N'))) {
  56                p += 2;
  57                result = 1;
  58        }
  59
  60        if (((p[0] == 'n') && (p[1] == 'o')) ||
  61                ((p[0] == 'N') && (p[1] == 'O'))) {
  62                p += 2;
  63                result = 0;
  64        }
  65
  66        if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
  67                ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
  68                p += 3;
  69                result = 0;
  70        }
  71
  72        p = skip_white_spaces(p);
  73
  74        if (p[0] != '\0')
  75                return -EINVAL;
  76
  77        return result;
  78}
  79
  80int
  81parser_read_uint64(uint64_t *value, const char *p)
  82{
  83        char *next;
  84        uint64_t val;
  85
  86        p = skip_white_spaces(p);
  87        if (!isdigit(*p))
  88                return -EINVAL;
  89
  90        val = strtoul(p, &next, 10);
  91        if (p == next)
  92                return -EINVAL;
  93
  94        p = next;
  95        switch (*p) {
  96        case 'T':
  97                val *= 1024ULL;
  98                /* fall through */
  99        case 'G':
 100                val *= 1024ULL;
 101                /* fall through */
 102        case 'M':
 103                val *= 1024ULL;
 104                /* fall through */
 105        case 'k':
 106        case 'K':
 107                val *= 1024ULL;
 108                p++;
 109                break;
 110        }
 111
 112        p = skip_white_spaces(p);
 113        if (*p != '\0')
 114                return -EINVAL;
 115
 116        *value = val;
 117        return 0;
 118}
 119
 120int
 121parser_read_uint64_hex(uint64_t *value, const char *p)
 122{
 123        char *next;
 124        uint64_t val;
 125
 126        p = skip_white_spaces(p);
 127
 128        val = strtoul(p, &next, 16);
 129        if (p == next)
 130                return -EINVAL;
 131
 132        p = skip_white_spaces(next);
 133        if (*p != '\0')
 134                return -EINVAL;
 135
 136        *value = val;
 137        return 0;
 138}
 139
 140int
 141parser_read_uint32(uint32_t *value, const char *p)
 142{
 143        uint64_t val = 0;
 144        int ret = parser_read_uint64(&val, p);
 145
 146        if (ret < 0)
 147                return ret;
 148
 149        if (val > UINT32_MAX)
 150                return -ERANGE;
 151
 152        *value = val;
 153        return 0;
 154}
 155
 156int
 157parser_read_uint32_hex(uint32_t *value, const char *p)
 158{
 159        uint64_t val = 0;
 160        int ret = parser_read_uint64_hex(&val, p);
 161
 162        if (ret < 0)
 163                return ret;
 164
 165        if (val > UINT32_MAX)
 166                return -ERANGE;
 167
 168        *value = val;
 169        return 0;
 170}
 171
 172int
 173parser_read_uint16(uint16_t *value, const char *p)
 174{
 175        uint64_t val = 0;
 176        int ret = parser_read_uint64(&val, p);
 177
 178        if (ret < 0)
 179                return ret;
 180
 181        if (val > UINT16_MAX)
 182                return -ERANGE;
 183
 184        *value = val;
 185        return 0;
 186}
 187
 188int
 189parser_read_uint16_hex(uint16_t *value, const char *p)
 190{
 191        uint64_t val = 0;
 192        int ret = parser_read_uint64_hex(&val, p);
 193
 194        if (ret < 0)
 195                return ret;
 196
 197        if (val > UINT16_MAX)
 198                return -ERANGE;
 199
 200        *value = val;
 201        return 0;
 202}
 203
 204int
 205parser_read_uint8(uint8_t *value, const char *p)
 206{
 207        uint64_t val = 0;
 208        int ret = parser_read_uint64(&val, p);
 209
 210        if (ret < 0)
 211                return ret;
 212
 213        if (val > UINT8_MAX)
 214                return -ERANGE;
 215
 216        *value = val;
 217        return 0;
 218}
 219
 220int
 221parser_read_uint8_hex(uint8_t *value, const char *p)
 222{
 223        uint64_t val = 0;
 224        int ret = parser_read_uint64_hex(&val, p);
 225
 226        if (ret < 0)
 227                return ret;
 228
 229        if (val > UINT8_MAX)
 230                return -ERANGE;
 231
 232        *value = val;
 233        return 0;
 234}
 235
 236int
 237parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
 238{
 239        uint32_t i;
 240
 241        if ((string == NULL) ||
 242                (tokens == NULL) ||
 243                (*n_tokens < 1))
 244                return -EINVAL;
 245
 246        for (i = 0; i < *n_tokens; i++) {
 247                tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
 248                if (tokens[i] == NULL)
 249                        break;
 250        }
 251
 252        if ((i == *n_tokens) &&
 253                (NULL != strtok_r(string, PARSE_DELIMITER, &string)))
 254                return -E2BIG;
 255
 256        *n_tokens = i;
 257        return 0;
 258}
 259
 260int
 261parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
 262{
 263        char *c;
 264        uint32_t len, i;
 265
 266        /* Check input parameters */
 267        if ((src == NULL) ||
 268                (dst == NULL) ||
 269                (size == NULL) ||
 270                (*size == 0))
 271                return -1;
 272
 273        len = strlen(src);
 274        if (((len & 3) != 0) ||
 275                (len > (*size) * 2))
 276                return -1;
 277        *size = len / 2;
 278
 279        for (c = src; *c != 0; c++) {
 280                if ((((*c) >= '0') && ((*c) <= '9')) ||
 281                        (((*c) >= 'A') && ((*c) <= 'F')) ||
 282                        (((*c) >= 'a') && ((*c) <= 'f')))
 283                        continue;
 284
 285                return -1;
 286        }
 287
 288        /* Convert chars to bytes */
 289        for (i = 0; i < *size; i++)
 290                dst[i] = get_hex_val(src[2 * i]) * 16 +
 291                        get_hex_val(src[2 * i + 1]);
 292
 293        return 0;
 294}
 295
 296int
 297parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
 298{
 299        uint32_t n_max_labels = *n_labels, count = 0;
 300
 301        /* Check for void list of labels */
 302        if (strcmp(string, "<void>") == 0) {
 303                *n_labels = 0;
 304                return 0;
 305        }
 306
 307        /* At least one label should be present */
 308        for ( ; (*string != '\0'); ) {
 309                char *next;
 310                int value;
 311
 312                if (count >= n_max_labels)
 313                        return -1;
 314
 315                if (count > 0) {
 316                        if (string[0] != ':')
 317                                return -1;
 318
 319                        string++;
 320                }
 321
 322                value = strtol(string, &next, 10);
 323                if (next == string)
 324                        return -1;
 325                string = next;
 326
 327                labels[count++] = (uint32_t) value;
 328        }
 329
 330        *n_labels = count;
 331        return 0;
 332}
 333
 334static struct rte_ether_addr *
 335my_ether_aton(const char *a)
 336{
 337        int i;
 338        char *end;
 339        unsigned long o[RTE_ETHER_ADDR_LEN];
 340        static struct rte_ether_addr ether_addr;
 341
 342        i = 0;
 343        do {
 344                errno = 0;
 345                o[i] = strtoul(a, &end, 16);
 346                if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
 347                        return NULL;
 348                a = end + 1;
 349        } while (++i != RTE_DIM(o) && end[0] != 0);
 350
 351        /* Junk at the end of line */
 352        if (end[0] != 0)
 353                return NULL;
 354
 355        /* Support the format XX:XX:XX:XX:XX:XX */
 356        if (i == RTE_ETHER_ADDR_LEN) {
 357                while (i-- != 0) {
 358                        if (o[i] > UINT8_MAX)
 359                                return NULL;
 360                        ether_addr.addr_bytes[i] = (uint8_t)o[i];
 361                }
 362        /* Support the format XXXX:XXXX:XXXX */
 363        } else if (i == RTE_ETHER_ADDR_LEN / 2) {
 364                while (i-- != 0) {
 365                        if (o[i] > UINT16_MAX)
 366                                return NULL;
 367                        ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
 368                        ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
 369                }
 370        /* unknown format */
 371        } else
 372                return NULL;
 373
 374        return (struct rte_ether_addr *)&ether_addr;
 375}
 376
 377int
 378parse_ipv4_addr(const char *token, struct in_addr *ipv4)
 379{
 380        if (strlen(token) >= INET_ADDRSTRLEN)
 381                return -EINVAL;
 382
 383        if (inet_pton(AF_INET, token, ipv4) != 1)
 384                return -EINVAL;
 385
 386        return 0;
 387}
 388
 389int
 390parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
 391{
 392        if (strlen(token) >= INET6_ADDRSTRLEN)
 393                return -EINVAL;
 394
 395        if (inet_pton(AF_INET6, token, ipv6) != 1)
 396                return -EINVAL;
 397
 398        return 0;
 399}
 400
 401int
 402parse_mac_addr(const char *token, struct rte_ether_addr *addr)
 403{
 404        struct rte_ether_addr *tmp;
 405
 406        tmp = my_ether_aton(token);
 407        if (tmp == NULL)
 408                return -1;
 409
 410        memcpy(addr, tmp, sizeof(struct rte_ether_addr));
 411        return 0;
 412}
 413
 414int
 415parse_cpu_core(const char *entry,
 416        struct cpu_core_params *p)
 417{
 418        size_t num_len;
 419        char num[8];
 420
 421        uint32_t s = 0, c = 0, h = 0, val;
 422        uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
 423        const char *next = skip_white_spaces(entry);
 424        char type;
 425
 426        if (p == NULL)
 427                return -EINVAL;
 428
 429        /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
 430        while (*next != '\0') {
 431                /* If everything parsed nothing should left */
 432                if (s_parsed && c_parsed && h_parsed)
 433                        return -EINVAL;
 434
 435                type = *next;
 436                switch (type) {
 437                case 's':
 438                case 'S':
 439                        if (s_parsed || c_parsed || h_parsed)
 440                                return -EINVAL;
 441                        s_parsed = 1;
 442                        next++;
 443                        break;
 444                case 'c':
 445                case 'C':
 446                        if (c_parsed || h_parsed)
 447                                return -EINVAL;
 448                        c_parsed = 1;
 449                        next++;
 450                        break;
 451                case 'h':
 452                case 'H':
 453                        if (h_parsed)
 454                                return -EINVAL;
 455                        h_parsed = 1;
 456                        next++;
 457                        break;
 458                default:
 459                        /* If it start from digit it must be only core id. */
 460                        if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
 461                                return -EINVAL;
 462
 463                        type = 'C';
 464                }
 465
 466                for (num_len = 0; *next != '\0'; next++, num_len++) {
 467                        if (num_len == RTE_DIM(num))
 468                                return -EINVAL;
 469
 470                        if (!isdigit(*next))
 471                                break;
 472
 473                        num[num_len] = *next;
 474                }
 475
 476                if (num_len == 0 && type != 'h' && type != 'H')
 477                        return -EINVAL;
 478
 479                if (num_len != 0 && (type == 'h' || type == 'H'))
 480                        return -EINVAL;
 481
 482                num[num_len] = '\0';
 483                val = strtol(num, NULL, 10);
 484
 485                h = 0;
 486                switch (type) {
 487                case 's':
 488                case 'S':
 489                        s = val;
 490                        break;
 491                case 'c':
 492                case 'C':
 493                        c = val;
 494                        break;
 495                case 'h':
 496                case 'H':
 497                        h = 1;
 498                        break;
 499                }
 500        }
 501
 502        p->socket_id = s;
 503        p->core_id = c;
 504        p->thread_id = h;
 505        return 0;
 506}
 507