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