get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/42550/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 42550,
    "url": "http://patches.dpdk.org/api/patches/42550/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20180706172116.50951-13-jasvinder.singh@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20180706172116.50951-13-jasvinder.singh@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180706172116.50951-13-jasvinder.singh@intel.com",
    "date": "2018-07-06T17:21:05",
    "name": "[v5,12/23] net/softnic: add cli interface",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "21a9dabaa41147a6571a5085f674e7bb8ce20868",
    "submitter": {
        "id": 285,
        "url": "http://patches.dpdk.org/api/people/285/?format=api",
        "name": "Jasvinder Singh",
        "email": "jasvinder.singh@intel.com"
    },
    "delegate": {
        "id": 10018,
        "url": "http://patches.dpdk.org/api/users/10018/?format=api",
        "username": "cristian_dumitrescu",
        "first_name": "Cristian",
        "last_name": "Dumitrescu",
        "email": "cristian.dumitrescu@intel.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20180706172116.50951-13-jasvinder.singh@intel.com/mbox/",
    "series": [
        {
            "id": 460,
            "url": "http://patches.dpdk.org/api/series/460/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=460",
            "date": "2018-07-06T17:20:53",
            "name": "net/softnic: refactoring",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/460/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/42550/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/42550/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id F2D7E1BF68;\n\tFri,  6 Jul 2018 19:21:51 +0200 (CEST)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby dpdk.org (Postfix) with ESMTP id 7AECF1BEE3\n\tfor <dev@dpdk.org>; Fri,  6 Jul 2018 19:21:37 +0200 (CEST)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t06 Jul 2018 10:21:34 -0700",
            "from silpixa00381635.ir.intel.com (HELO\n\tsilpixa00381635.ger.corp.intel.com) ([10.237.222.149])\n\tby orsmga003.jf.intel.com with ESMTP; 06 Jul 2018 10:21:30 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.51,317,1526367600\"; d=\"scan'208\";a=\"64955343\"",
        "From": "Jasvinder Singh <jasvinder.singh@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "cristian.dumitrescu@intel.com",
        "Date": "Fri,  6 Jul 2018 18:21:05 +0100",
        "Message-Id": "<20180706172116.50951-13-jasvinder.singh@intel.com>",
        "X-Mailer": "git-send-email 2.9.3",
        "In-Reply-To": "<20180706172116.50951-1-jasvinder.singh@intel.com>",
        "References": "<20180705154754.147420-2-jasvinder.singh@intel.com>\n\t<20180706172116.50951-1-jasvinder.singh@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v5 12/23] net/softnic: add cli interface",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add interface for softnic cli commands.\n\nSigned-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\nSigned-off-by: Jasvinder Singh <jasvinder.singh@intel.com>\n---\n drivers/net/softnic/Makefile                    |   2 +\n drivers/net/softnic/meson.build                 |   4 +-\n drivers/net/softnic/parser.c                    | 685 ++++++++++++++++++++++++\n drivers/net/softnic/parser.h                    |  66 +++\n drivers/net/softnic/rte_eth_softnic_cli.c       | 119 ++++\n drivers/net/softnic/rte_eth_softnic_internals.h |  15 +\n 6 files changed, 890 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/softnic/parser.c\n create mode 100644 drivers/net/softnic/parser.h\n create mode 100644 drivers/net/softnic/rte_eth_softnic_cli.c",
    "diff": "diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile\nindex d002062..cb95414 100644\n--- a/drivers/net/softnic/Makefile\n+++ b/drivers/net/softnic/Makefile\n@@ -32,6 +32,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_pipeline.c\n SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_thread.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_cli.c\n+SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += parser.c\n \n #\n # Export include files\ndiff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build\nindex 16604fc..8d3b4a0 100644\n--- a/drivers/net/softnic/meson.build\n+++ b/drivers/net/softnic/meson.build\n@@ -11,5 +11,7 @@ sources = files('rte_eth_softnic_tm.c',\n \t'rte_eth_softnic_tap.c',\n \t'rte_eth_softnic_action.c',\n \t'rte_eth_softnic_pipeline.c',\n-\t'rte_eth_softnic_thread.c')\n+\t'rte_eth_softnic_thread.c',\n+\t'rte_eth_softnic_cli.c',\n+\t'parser.c')\n deps += ['pipeline', 'port', 'table', 'sched']\ndiff --git a/drivers/net/softnic/parser.c b/drivers/net/softnic/parser.c\nnew file mode 100644\nindex 0000000..7087b87\n--- /dev/null\n+++ b/drivers/net/softnic/parser.c\n@@ -0,0 +1,685 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2016 Intel Corporation.\n+ * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>\n+ * All rights reserved.\n+ */\n+\n+/* For inet_pton4() and inet_pton6() functions:\n+ *\n+ * Copyright (c) 1996 by Internet Software Consortium.\n+ *\n+ * Permission to use, copy, modify, and distribute this software for any\n+ * purpose with or without fee is hereby granted, provided that the above\n+ * copyright notice and this permission notice appear in all copies.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS\n+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE\n+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\n+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\n+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\n+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\n+ * SOFTWARE.\n+ */\n+\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+#include <ctype.h>\n+#include <getopt.h>\n+#include <errno.h>\n+#include <stdarg.h>\n+#include <string.h>\n+#include <libgen.h>\n+#include <unistd.h>\n+#include <sys/wait.h>\n+\n+#include <rte_errno.h>\n+\n+#include \"parser.h\"\n+\n+static uint32_t\n+get_hex_val(char c)\n+{\n+\tswitch (c) {\n+\tcase '0': case '1': case '2': case '3': case '4': case '5':\n+\tcase '6': case '7': case '8': case '9':\n+\t\treturn c - '0';\n+\tcase 'A': case 'B': case 'C': case 'D': case 'E': case 'F':\n+\t\treturn c - 'A' + 10;\n+\tcase 'a': case 'b': case 'c': case 'd': case 'e': case 'f':\n+\t\treturn c - 'a' + 10;\n+\tdefault:\n+\t\treturn 0;\n+\t}\n+}\n+\n+int\n+softnic_parser_read_arg_bool(const char *p)\n+{\n+\tp = skip_white_spaces(p);\n+\tint result = -EINVAL;\n+\n+\tif (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||\n+\t\t((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {\n+\t\tp += 3;\n+\t\tresult = 1;\n+\t}\n+\n+\tif (((p[0] == 'o') && (p[1] == 'n')) ||\n+\t\t((p[0] == 'O') && (p[1] == 'N'))) {\n+\t\tp += 2;\n+\t\tresult = 1;\n+\t}\n+\n+\tif (((p[0] == 'n') && (p[1] == 'o')) ||\n+\t\t((p[0] == 'N') && (p[1] == 'O'))) {\n+\t\tp += 2;\n+\t\tresult = 0;\n+\t}\n+\n+\tif (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||\n+\t\t((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {\n+\t\tp += 3;\n+\t\tresult = 0;\n+\t}\n+\n+\tp = skip_white_spaces(p);\n+\n+\tif (p[0] != '\\0')\n+\t\treturn -EINVAL;\n+\n+\treturn result;\n+}\n+\n+int\n+softnic_parser_read_uint64(uint64_t *value, const char *p)\n+{\n+\tchar *next;\n+\tuint64_t val;\n+\n+\tp = skip_white_spaces(p);\n+\tif (!isdigit(*p))\n+\t\treturn -EINVAL;\n+\n+\tval = strtoul(p, &next, 10);\n+\tif (p == next)\n+\t\treturn -EINVAL;\n+\n+\tp = next;\n+\tswitch (*p) {\n+\tcase 'T':\n+\t\tval *= 1024ULL;\n+\t\t/* fall through */\n+\tcase 'G':\n+\t\tval *= 1024ULL;\n+\t\t/* fall through */\n+\tcase 'M':\n+\t\tval *= 1024ULL;\n+\t\t/* fall through */\n+\tcase 'k':\n+\tcase 'K':\n+\t\tval *= 1024ULL;\n+\t\tp++;\n+\t\tbreak;\n+\t}\n+\n+\tp = skip_white_spaces(p);\n+\tif (*p != '\\0')\n+\t\treturn -EINVAL;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parser_read_uint64_hex(uint64_t *value, const char *p)\n+{\n+\tchar *next;\n+\tuint64_t val;\n+\n+\tp = skip_white_spaces(p);\n+\n+\tval = strtoul(p, &next, 16);\n+\tif (p == next)\n+\t\treturn -EINVAL;\n+\n+\tp = skip_white_spaces(next);\n+\tif (*p != '\\0')\n+\t\treturn -EINVAL;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parser_read_uint32(uint32_t *value, const char *p)\n+{\n+\tuint64_t val = 0;\n+\tint ret = softnic_parser_read_uint64(&val, p);\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (val > UINT32_MAX)\n+\t\treturn -ERANGE;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parser_read_uint32_hex(uint32_t *value, const char *p)\n+{\n+\tuint64_t val = 0;\n+\tint ret = softnic_parser_read_uint64_hex(&val, p);\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (val > UINT32_MAX)\n+\t\treturn -ERANGE;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parser_read_uint16(uint16_t *value, const char *p)\n+{\n+\tuint64_t val = 0;\n+\tint ret = softnic_parser_read_uint64(&val, p);\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (val > UINT16_MAX)\n+\t\treturn -ERANGE;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parser_read_uint16_hex(uint16_t *value, const char *p)\n+{\n+\tuint64_t val = 0;\n+\tint ret = softnic_parser_read_uint64_hex(&val, p);\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (val > UINT16_MAX)\n+\t\treturn -ERANGE;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parser_read_uint8(uint8_t *value, const char *p)\n+{\n+\tuint64_t val = 0;\n+\tint ret = softnic_parser_read_uint64(&val, p);\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (val > UINT8_MAX)\n+\t\treturn -ERANGE;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parser_read_uint8_hex(uint8_t *value, const char *p)\n+{\n+\tuint64_t val = 0;\n+\tint ret = softnic_parser_read_uint64_hex(&val, p);\n+\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tif (val > UINT8_MAX)\n+\t\treturn -ERANGE;\n+\n+\t*value = val;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)\n+{\n+\tuint32_t i;\n+\n+\tif (string == NULL ||\n+\t\ttokens == NULL ||\n+\t\t(*n_tokens < 1))\n+\t\treturn -EINVAL;\n+\n+\tfor (i = 0; i < *n_tokens; i++) {\n+\t\ttokens[i] = strtok_r(string, PARSE_DELIMITER, &string);\n+\t\tif (tokens[i] == NULL)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (i == *n_tokens &&\n+\t\tstrtok_r(string, PARSE_DELIMITER, &string) != NULL)\n+\t\treturn -E2BIG;\n+\n+\t*n_tokens = i;\n+\treturn 0;\n+}\n+\n+int\n+softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)\n+{\n+\tchar *c;\n+\tuint32_t len, i;\n+\n+\t/* Check input parameters */\n+\tif (src == NULL ||\n+\t\tdst == NULL ||\n+\t\tsize == NULL ||\n+\t\t(*size == 0))\n+\t\treturn -1;\n+\n+\tlen = strlen(src);\n+\tif (((len & 3) != 0) ||\n+\t\t(len > (*size) * 2))\n+\t\treturn -1;\n+\t*size = len / 2;\n+\n+\tfor (c = src; *c != 0; c++) {\n+\t\tif ((((*c) >= '0') && ((*c) <= '9')) ||\n+\t\t\t(((*c) >= 'A') && ((*c) <= 'F')) ||\n+\t\t\t(((*c) >= 'a') && ((*c) <= 'f')))\n+\t\t\tcontinue;\n+\n+\t\treturn -1;\n+\t}\n+\n+\t/* Convert chars to bytes */\n+\tfor (i = 0; i < *size; i++)\n+\t\tdst[i] = get_hex_val(src[2 * i]) * 16 +\n+\t\t\tget_hex_val(src[2 * i + 1]);\n+\n+\treturn 0;\n+}\n+\n+int\n+softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)\n+{\n+\tuint32_t n_max_labels = *n_labels, count = 0;\n+\n+\t/* Check for void list of labels */\n+\tif (strcmp(string, \"<void>\") == 0) {\n+\t\t*n_labels = 0;\n+\t\treturn 0;\n+\t}\n+\n+\t/* At least one label should be present */\n+\tfor ( ; (*string != '\\0'); ) {\n+\t\tchar *next;\n+\t\tint value;\n+\n+\t\tif (count >= n_max_labels)\n+\t\t\treturn -1;\n+\n+\t\tif (count > 0) {\n+\t\t\tif (string[0] != ':')\n+\t\t\t\treturn -1;\n+\n+\t\t\tstring++;\n+\t\t}\n+\n+\t\tvalue = strtol(string, &next, 10);\n+\t\tif (next == string)\n+\t\t\treturn -1;\n+\t\tstring = next;\n+\n+\t\tlabels[count++] = (uint32_t)value;\n+\t}\n+\n+\t*n_labels = count;\n+\treturn 0;\n+}\n+\n+#define INADDRSZ 4\n+#define IN6ADDRSZ 16\n+\n+/* int\n+ * inet_pton4(src, dst)\n+ *      like inet_aton() but without all the hexadecimal and shorthand.\n+ * return:\n+ *      1 if `src' is a valid dotted quad, else 0.\n+ * notice:\n+ *      does not touch `dst' unless it's returning 1.\n+ * author:\n+ *      Paul Vixie, 1996.\n+ */\n+static int\n+inet_pton4(const char *src, unsigned char *dst)\n+{\n+\tstatic const char digits[] = \"0123456789\";\n+\tint saw_digit, octets, ch;\n+\tunsigned char tmp[INADDRSZ], *tp;\n+\n+\tsaw_digit = 0;\n+\toctets = 0;\n+\t*(tp = tmp) = 0;\n+\twhile ((ch = *src++) != '\\0') {\n+\t\tconst char *pch;\n+\n+\t\tpch = strchr(digits, ch);\n+\t\tif (pch != NULL) {\n+\t\t\tunsigned int new = *tp * 10 + (pch - digits);\n+\n+\t\t\tif (new > 255)\n+\t\t\t\treturn 0;\n+\t\t\tif (!saw_digit) {\n+\t\t\t\tif (++octets > 4)\n+\t\t\t\t\treturn 0;\n+\t\t\t\tsaw_digit = 1;\n+\t\t\t}\n+\t\t\t*tp = (unsigned char)new;\n+\t\t} else if (ch == '.' && saw_digit) {\n+\t\t\tif (octets == 4)\n+\t\t\t\treturn 0;\n+\t\t\t*++tp = 0;\n+\t\t\tsaw_digit = 0;\n+\t\t} else\n+\t\t\treturn 0;\n+\t}\n+\tif (octets < 4)\n+\t\treturn 0;\n+\n+\tmemcpy(dst, tmp, INADDRSZ);\n+\treturn 1;\n+}\n+\n+/* int\n+ * inet_pton6(src, dst)\n+ *      convert presentation level address to network order binary form.\n+ * return:\n+ *      1 if `src' is a valid [RFC1884 2.2] address, else 0.\n+ * notice:\n+ *      (1) does not touch `dst' unless it's returning 1.\n+ *      (2) :: in a full address is silently ignored.\n+ * credit:\n+ *      inspired by Mark Andrews.\n+ * author:\n+ *      Paul Vixie, 1996.\n+ */\n+static int\n+inet_pton6(const char *src, unsigned char *dst)\n+{\n+\tstatic const char xdigits_l[] = \"0123456789abcdef\",\n+\t\txdigits_u[] = \"0123456789ABCDEF\";\n+\tunsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;\n+\tconst char *xdigits = 0, *curtok = 0;\n+\tint ch = 0, saw_xdigit = 0, count_xdigit = 0;\n+\tunsigned int val = 0;\n+\tunsigned int dbloct_count = 0;\n+\n+\tmemset((tp = tmp), '\\0', IN6ADDRSZ);\n+\tendp = tp + IN6ADDRSZ;\n+\tcolonp = NULL;\n+\t/* Leading :: requires some special handling. */\n+\tif (*src == ':')\n+\t\tif (*++src != ':')\n+\t\t\treturn 0;\n+\tcurtok = src;\n+\tsaw_xdigit = count_xdigit = 0;\n+\tval = 0;\n+\n+\twhile ((ch = *src++) != '\\0') {\n+\t\tconst char *pch;\n+\n+\t\tpch = strchr((xdigits = xdigits_l), ch);\n+\t\tif (pch == NULL)\n+\t\t\tpch = strchr((xdigits = xdigits_u), ch);\n+\t\tif (pch != NULL) {\n+\t\t\tif (count_xdigit >= 4)\n+\t\t\t\treturn 0;\n+\t\t\tval <<= 4;\n+\t\t\tval |= (pch - xdigits);\n+\t\t\tif (val > 0xffff)\n+\t\t\t\treturn 0;\n+\t\t\tsaw_xdigit = 1;\n+\t\t\tcount_xdigit++;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (ch == ':') {\n+\t\t\tcurtok = src;\n+\t\t\tif (!saw_xdigit) {\n+\t\t\t\tif (colonp)\n+\t\t\t\t\treturn 0;\n+\t\t\t\tcolonp = tp;\n+\t\t\t\tcontinue;\n+\t\t\t} else if (*src == '\\0') {\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t\tif (tp + sizeof(int16_t) > endp)\n+\t\t\t\treturn 0;\n+\t\t\t*tp++ = (unsigned char)((val >> 8) & 0xff);\n+\t\t\t*tp++ = (unsigned char)(val & 0xff);\n+\t\t\tsaw_xdigit = 0;\n+\t\t\tcount_xdigit = 0;\n+\t\t\tval = 0;\n+\t\t\tdbloct_count++;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (ch == '.' && ((tp + INADDRSZ) <= endp) &&\n+\t\t    inet_pton4(curtok, tp) > 0) {\n+\t\t\ttp += INADDRSZ;\n+\t\t\tsaw_xdigit = 0;\n+\t\t\tdbloct_count += 2;\n+\t\t\tbreak;  /* '\\0' was seen by inet_pton4(). */\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\tif (saw_xdigit) {\n+\t\tif (tp + sizeof(int16_t) > endp)\n+\t\t\treturn 0;\n+\t\t*tp++ = (unsigned char)((val >> 8) & 0xff);\n+\t\t*tp++ = (unsigned char)(val & 0xff);\n+\t\tdbloct_count++;\n+\t}\n+\tif (colonp != NULL) {\n+\t\t/* if we already have 8 double octets, having a colon means error */\n+\t\tif (dbloct_count == 8)\n+\t\t\treturn 0;\n+\n+\t\t/* Since some memmove()'s erroneously fail to handle\n+\t\t * overlapping regions, we'll do the shift by hand.\n+\t\t */\n+\t\tconst int n = tp - colonp;\n+\t\tint i;\n+\n+\t\tfor (i = 1; i <= n; i++) {\n+\t\t\tendp[-i] = colonp[n - i];\n+\t\t\tcolonp[n - i] = 0;\n+\t\t}\n+\t\ttp = endp;\n+\t}\n+\tif (tp != endp)\n+\t\treturn 0;\n+\tmemcpy(dst, tmp, IN6ADDRSZ);\n+\treturn 1;\n+}\n+\n+static struct ether_addr *\n+my_ether_aton(const char *a)\n+{\n+\tint i;\n+\tchar *end;\n+\tunsigned long o[ETHER_ADDR_LEN];\n+\tstatic struct ether_addr ether_addr;\n+\n+\ti = 0;\n+\tdo {\n+\t\terrno = 0;\n+\t\to[i] = strtoul(a, &end, 16);\n+\t\tif (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))\n+\t\t\treturn NULL;\n+\t\ta = end + 1;\n+\t} while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);\n+\n+\t/* Junk at the end of line */\n+\tif (end[0] != 0)\n+\t\treturn NULL;\n+\n+\t/* Support the format XX:XX:XX:XX:XX:XX */\n+\tif (i == ETHER_ADDR_LEN) {\n+\t\twhile (i-- != 0) {\n+\t\t\tif (o[i] > UINT8_MAX)\n+\t\t\t\treturn NULL;\n+\t\t\tether_addr.addr_bytes[i] = (uint8_t)o[i];\n+\t\t}\n+\t/* Support the format XXXX:XXXX:XXXX */\n+\t} else if (i == ETHER_ADDR_LEN / 2) {\n+\t\twhile (i-- != 0) {\n+\t\t\tif (o[i] > UINT16_MAX)\n+\t\t\t\treturn NULL;\n+\t\t\tether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);\n+\t\t\tether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);\n+\t\t}\n+\t/* unknown format */\n+\t} else\n+\t\treturn NULL;\n+\n+\treturn (struct ether_addr *)&ether_addr;\n+}\n+\n+int\n+softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)\n+{\n+\tif (strlen(token) >= INET_ADDRSTRLEN)\n+\t\treturn -EINVAL;\n+\n+\tif (inet_pton4(token, (unsigned char *)ipv4) != 1)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+int\n+softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)\n+{\n+\tif (strlen(token) >= INET6_ADDRSTRLEN)\n+\t\treturn -EINVAL;\n+\n+\tif (inet_pton6(token, (unsigned char *)ipv6) != 1)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+int\n+softnic_parse_mac_addr(const char *token, struct ether_addr *addr)\n+{\n+\tstruct ether_addr *tmp;\n+\n+\ttmp = my_ether_aton(token);\n+\tif (tmp == NULL)\n+\t\treturn -1;\n+\n+\tmemcpy(addr, tmp, sizeof(struct ether_addr));\n+\treturn 0;\n+}\n+\n+int\n+softnic_parse_cpu_core(const char *entry,\n+\tstruct softnic_cpu_core_params *p)\n+{\n+\tsize_t num_len;\n+\tchar num[8];\n+\n+\tuint32_t s = 0, c = 0, h = 0, val;\n+\tuint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;\n+\tconst char *next = skip_white_spaces(entry);\n+\tchar type;\n+\n+\tif (p == NULL)\n+\t\treturn -EINVAL;\n+\n+\t/* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */\n+\twhile (*next != '\\0') {\n+\t\t/* If everything parsed nothing should left */\n+\t\tif (s_parsed && c_parsed && h_parsed)\n+\t\t\treturn -EINVAL;\n+\n+\t\ttype = *next;\n+\t\tswitch (type) {\n+\t\tcase 's':\n+\t\tcase 'S':\n+\t\t\tif (s_parsed || c_parsed || h_parsed)\n+\t\t\t\treturn -EINVAL;\n+\t\t\ts_parsed = 1;\n+\t\t\tnext++;\n+\t\t\tbreak;\n+\t\tcase 'c':\n+\t\tcase 'C':\n+\t\t\tif (c_parsed || h_parsed)\n+\t\t\t\treturn -EINVAL;\n+\t\t\tc_parsed = 1;\n+\t\t\tnext++;\n+\t\t\tbreak;\n+\t\tcase 'h':\n+\t\tcase 'H':\n+\t\t\tif (h_parsed)\n+\t\t\t\treturn -EINVAL;\n+\t\t\th_parsed = 1;\n+\t\t\tnext++;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\t/* If it start from digit it must be only core id. */\n+\t\t\tif (!isdigit(*next) || s_parsed || c_parsed || h_parsed)\n+\t\t\t\treturn -EINVAL;\n+\n+\t\t\ttype = 'C';\n+\t\t}\n+\n+\t\tfor (num_len = 0; *next != '\\0'; next++, num_len++) {\n+\t\t\tif (num_len == RTE_DIM(num))\n+\t\t\t\treturn -EINVAL;\n+\n+\t\t\tif (!isdigit(*next))\n+\t\t\t\tbreak;\n+\n+\t\t\tnum[num_len] = *next;\n+\t\t}\n+\n+\t\tif (num_len == 0 && type != 'h' && type != 'H')\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (num_len != 0 && (type == 'h' || type == 'H'))\n+\t\t\treturn -EINVAL;\n+\n+\t\tnum[num_len] = '\\0';\n+\t\tval = strtol(num, NULL, 10);\n+\n+\t\th = 0;\n+\t\tswitch (type) {\n+\t\tcase 's':\n+\t\tcase 'S':\n+\t\t\ts = val;\n+\t\t\tbreak;\n+\t\tcase 'c':\n+\t\tcase 'C':\n+\t\t\tc = val;\n+\t\t\tbreak;\n+\t\tcase 'h':\n+\t\tcase 'H':\n+\t\t\th = 1;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tp->socket_id = s;\n+\tp->core_id = c;\n+\tp->thread_id = h;\n+\treturn 0;\n+}\ndiff --git a/drivers/net/softnic/parser.h b/drivers/net/softnic/parser.h\nnew file mode 100644\nindex 0000000..5ab4763\n--- /dev/null\n+++ b/drivers/net/softnic/parser.h\n@@ -0,0 +1,66 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2010-2016 Intel Corporation\n+ */\n+\n+#ifndef __INCLUDE_SOFTNIC_PARSER_H__\n+#define __INCLUDE_SOFTNIC_PARSER_H__\n+\n+#include <stdint.h>\n+\n+#include <rte_ip.h>\n+#include <rte_ether.h>\n+\n+#define PARSE_DELIMITER\t\t\t\t\" \\f\\n\\r\\t\\v\"\n+\n+#define skip_white_spaces(pos)\t\t\t\\\n+({\t\t\t\t\t\t\\\n+\t__typeof__(pos) _p = (pos);\t\t\\\n+\tfor ( ; isspace(*_p); _p++)\t\t\\\n+\t\t;\t\t\t\t\\\n+\t_p;\t\t\t\t\t\\\n+})\n+\n+static inline size_t\n+skip_digits(const char *src)\n+{\n+\tsize_t i;\n+\n+\tfor (i = 0; isdigit(src[i]); i++)\n+\t\t;\n+\n+\treturn i;\n+}\n+\n+int softnic_parser_read_arg_bool(const char *p);\n+\n+int softnic_parser_read_uint64(uint64_t *value, const char *p);\n+int softnic_parser_read_uint32(uint32_t *value, const char *p);\n+int softnic_parser_read_uint16(uint16_t *value, const char *p);\n+int softnic_parser_read_uint8(uint8_t *value, const char *p);\n+\n+int softnic_parser_read_uint64_hex(uint64_t *value, const char *p);\n+int softnic_parser_read_uint32_hex(uint32_t *value, const char *p);\n+int softnic_parser_read_uint16_hex(uint16_t *value, const char *p);\n+int softnic_parser_read_uint8_hex(uint8_t *value, const char *p);\n+\n+int softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size);\n+\n+int softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4);\n+int softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6);\n+int softnic_parse_mac_addr(const char *token, struct ether_addr *addr);\n+int softnic_parse_mpls_labels(char *string,\n+\t\tuint32_t *labels, uint32_t *n_labels);\n+\n+struct softnic_cpu_core_params {\n+\tuint32_t socket_id;\n+\tuint32_t core_id;\n+\tuint32_t thread_id;\n+};\n+\n+int softnic_parse_cpu_core(const char *entry,\n+\t\tstruct softnic_cpu_core_params *p);\n+\n+int softnic_parse_tokenize_string(char *string,\n+\t\tchar *tokens[], uint32_t *n_tokens);\n+\n+#endif\ndiff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c\nnew file mode 100644\nindex 0000000..446b186\n--- /dev/null\n+++ b/drivers/net/softnic/rte_eth_softnic_cli.c\n@@ -0,0 +1,119 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2010-2018 Intel Corporation\n+ */\n+\n+#include <stdio.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <string.h>\n+\n+#include \"rte_eth_softnic_internals.h\"\n+#include \"parser.h\"\n+\n+#ifndef CMD_MAX_TOKENS\n+#define CMD_MAX_TOKENS     256\n+#endif\n+\n+#define MSG_OUT_OF_MEMORY   \"Not enough memory.\\n\"\n+#define MSG_CMD_UNKNOWN     \"Unknown command \\\"%s\\\".\\n\"\n+#define MSG_CMD_UNIMPLEM    \"Command \\\"%s\\\" not implemented.\\n\"\n+#define MSG_ARG_NOT_ENOUGH  \"Not enough arguments for command \\\"%s\\\".\\n\"\n+#define MSG_ARG_TOO_MANY    \"Too many arguments for command \\\"%s\\\".\\n\"\n+#define MSG_ARG_MISMATCH    \"Wrong number of arguments for command \\\"%s\\\".\\n\"\n+#define MSG_ARG_NOT_FOUND   \"Argument \\\"%s\\\" not found.\\n\"\n+#define MSG_ARG_INVALID     \"Invalid value for argument \\\"%s\\\".\\n\"\n+#define MSG_FILE_ERR        \"Error in file \\\"%s\\\" at line %u.\\n\"\n+#define MSG_FILE_NOT_ENOUGH \"Not enough rules in file \\\"%s\\\".\\n\"\n+#define MSG_CMD_FAIL        \"Command \\\"%s\\\" failed.\\n\"\n+\n+static int\n+is_comment(char *in)\n+{\n+\tif ((strlen(in) && index(\"!#%;\", in[0])) ||\n+\t\t(strncmp(in, \"//\", 2) == 0) ||\n+\t\t(strncmp(in, \"--\", 2) == 0))\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+void\n+softnic_cli_process(char *in, char *out, size_t out_size, void *arg)\n+{\n+\tchar *tokens[CMD_MAX_TOKENS];\n+\tuint32_t n_tokens = RTE_DIM(tokens);\n+\tint status;\n+\n+\targ = arg;\n+\n+\tif (is_comment(in))\n+\t\treturn;\n+\n+\tstatus = softnic_parse_tokenize_string(in, tokens, &n_tokens);\n+\tif (status) {\n+\t\tsnprintf(out, out_size, MSG_ARG_TOO_MANY, \"\");\n+\t\treturn;\n+\t}\n+\n+\tif (n_tokens == 0)\n+\t\treturn;\n+\n+\tsnprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);\n+}\n+\n+int\n+softnic_cli_script_process(struct pmd_internals *softnic,\n+\tconst char *file_name,\n+\tsize_t msg_in_len_max,\n+\tsize_t msg_out_len_max)\n+{\n+\tchar *msg_in = NULL, *msg_out = NULL;\n+\tFILE *f = NULL;\n+\n+\t/* Check input arguments */\n+\tif (file_name == NULL ||\n+\t\tstrlen(file_name) == 0 ||\n+\t\tmsg_in_len_max == 0 ||\n+\t\tmsg_out_len_max == 0)\n+\t\treturn -EINVAL;\n+\n+\tmsg_in = malloc(msg_in_len_max + 1);\n+\tmsg_out = malloc(msg_out_len_max + 1);\n+\tif (msg_in == NULL ||\n+\t\tmsg_out == NULL) {\n+\t\tfree(msg_out);\n+\t\tfree(msg_in);\n+\t\treturn -ENOMEM;\n+\t}\n+\n+\t/* Open input file */\n+\tf = fopen(file_name, \"r\");\n+\tif (f == NULL) {\n+\t\tfree(msg_out);\n+\t\tfree(msg_in);\n+\t\treturn -EIO;\n+\t}\n+\n+\t/* Read file */\n+\tfor ( ; ; ) {\n+\t\tif (fgets(msg_in, msg_in_len_max + 1, f) == NULL)\n+\t\t\tbreak;\n+\n+\t\tprintf(\"%s\", msg_in);\n+\t\tmsg_out[0] = 0;\n+\n+\t\tsoftnic_cli_process(msg_in,\n+\t\t\tmsg_out,\n+\t\t\tmsg_out_len_max,\n+\t\t\tsoftnic);\n+\n+\t\tif (strlen(msg_out))\n+\t\t\tprintf(\"%s\", msg_out);\n+\t}\n+\n+\t/* Close file */\n+\tfclose(f);\n+\tfree(msg_out);\n+\tfree(msg_in);\n+\treturn 0;\n+}\ndiff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h\nindex 1c78942..d459571 100644\n--- a/drivers/net/softnic/rte_eth_softnic_internals.h\n+++ b/drivers/net/softnic/rte_eth_softnic_internals.h\n@@ -695,4 +695,19 @@ softnic_thread_init(struct pmd_internals *p);\n void\n softnic_thread_free(struct pmd_internals *p);\n \n+/**\n+ * CLI\n+ */\n+void\n+softnic_cli_process(char *in,\n+\tchar *out,\n+\tsize_t out_size,\n+\tvoid *arg);\n+\n+int\n+softnic_cli_script_process(struct pmd_internals *softnic,\n+\tconst char *file_name,\n+\tsize_t msg_in_len_max,\n+\tsize_t msg_out_len_max);\n+\n #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */\n",
    "prefixes": [
        "v5",
        "12/23"
    ]
}