Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/134536/?format=api
http://patchwork.dpdk.org/api/patches/134536/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20231122164550.3873633-2-euan.bourke@intel.com/", "project": { "id": 1, "url": "http://patchwork.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": "<20231122164550.3873633-2-euan.bourke@intel.com>", "list_archive_url": "https://inbox.dpdk.org/dev/20231122164550.3873633-2-euan.bourke@intel.com", "date": "2023-11-22T16:45:47", "name": "[24.03,1/4] arg_parser: new library for command line parsing", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "d3979ed77702bf50b207af34de4d9dbe4db8413d", "submitter": { "id": 3231, "url": "http://patchwork.dpdk.org/api/people/3231/?format=api", "name": "Euan Bourke", "email": "euan.bourke@intel.com" }, "delegate": { "id": 1, "url": "http://patchwork.dpdk.org/api/users/1/?format=api", "username": "tmonjalo", "first_name": "Thomas", "last_name": "Monjalon", "email": "thomas@monjalon.net" }, "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20231122164550.3873633-2-euan.bourke@intel.com/mbox/", "series": [ { "id": 30362, "url": "http://patchwork.dpdk.org/api/series/30362/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=30362", "date": "2023-11-22T16:45:46", "name": "add new command line argument parsing library", "version": 1, "mbox": "http://patchwork.dpdk.org/series/30362/mbox/" } ], "comments": "http://patchwork.dpdk.org/api/patches/134536/comments/", "check": "warning", "checks": "http://patchwork.dpdk.org/api/patches/134536/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dev-bounces@dpdk.org>", "X-Original-To": "patchwork@inbox.dpdk.org", "Delivered-To": "patchwork@inbox.dpdk.org", "Received": [ "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id F137643382;\n\tWed, 22 Nov 2023 17:48:04 +0100 (CET)", "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 7067542670;\n\tWed, 22 Nov 2023 17:47:57 +0100 (CET)", "from mgamail.intel.com (mgamail.intel.com [134.134.136.31])\n by mails.dpdk.org (Postfix) with ESMTP id 588DF4028C\n for <dev@dpdk.org>; Wed, 22 Nov 2023 17:45:59 +0100 (CET)", "from fmsmga002.fm.intel.com ([10.253.24.26])\n by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 22 Nov 2023 08:45:57 -0800", "from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151])\n by fmsmga002.fm.intel.com with ESMTP; 22 Nov 2023 08:45:57 -0800" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1700671558; x=1732207558;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=27rllYr0JspWUru9sD+3sf+zwNybuifUPr3djSC/NG4=;\n b=Qk4KTtslfNEVnkYY26gw9EU83YkvVjWcWrgRB5N0PMOqNHw6XA1NLyWh\n ovE4l9NxNqBlu21Hkh6qMcst9hWpfDND6Fq/+uJ9poXDoVSE+e0L49Ftp\n vfscPdt80QoEHXrvi3+QihG/qlWUkuuRXutURoBhc7HyPXUawKPIpBH2f\n YXaQR9PNFc5dWprSCS3Xph/SDgcOaNQECImpw0Xl1AGlY0X8Wd3FnNcDM\n ZLJEcIdxUUG6YwtD5AEkIImlNu1b5PpBYwqXB4vIu1f2eLGoL9qzmFYU/\n pavAhbQVinC2vfFG18XVDXr5DPemmooCcwtKeUYbVFopb0F9pObmn9rJh w==;", "X-IronPort-AV": [ "E=McAfee;i=\"6600,9927,10902\"; a=\"456415986\"", "E=Sophos;i=\"6.04,219,1695711600\"; d=\"scan'208\";a=\"456415986\"", "E=McAfee;i=\"6600,9927,10902\"; a=\"884685089\"", "E=Sophos;i=\"6.04,219,1695711600\"; d=\"scan'208\";a=\"884685089\"" ], "X-ExtLoop1": "1", "From": "Euan Bourke <euan.bourke@intel.com>", "To": "dev@dpdk.org", "Cc": "Euan Bourke <euan.bourke@intel.com>", "Subject": "[PATCH 24.03 1/4] arg_parser: new library for command line parsing", "Date": "Wed, 22 Nov 2023 16:45:47 +0000", "Message-Id": "<20231122164550.3873633-2-euan.bourke@intel.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20231122164550.3873633-1-euan.bourke@intel.com>", "References": "<20231122164550.3873633-1-euan.bourke@intel.com>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-Mailman-Approved-At": "Wed, 22 Nov 2023 17:47:54 +0100", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "DPDK patches and discussions <dev.dpdk.org>", "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <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 <mailto:dev-request@dpdk.org?subject=subscribe>", "Errors-To": "dev-bounces@dpdk.org" }, "content": "Add a new library to make it easier for eal and other libraries to parse\ncommand line arguments.\n\nThe first function in this library is one to parse a corelist string into an\narray of individual core ids. The function will then return the total number\nof cores described in the corelist\n\nSigned-off-by: Euan Bourke <euan.bourke@intel.com>\n---\n .mailmap | 1 +\n MAINTAINERS | 5 ++\n doc/api/doxy-api-index.md | 3 +-\n doc/api/doxy-api.conf.in | 1 +\n lib/arg_parser/arg_parser.c | 113 ++++++++++++++++++++++++++++++++\n lib/arg_parser/meson.build | 7 ++\n lib/arg_parser/rte_arg_parser.h | 66 +++++++++++++++++++\n lib/arg_parser/version.map | 10 +++\n lib/meson.build | 1 +\n 9 files changed, 206 insertions(+), 1 deletion(-)\n create mode 100644 lib/arg_parser/arg_parser.c\n create mode 100644 lib/arg_parser/meson.build\n create mode 100644 lib/arg_parser/rte_arg_parser.h\n create mode 100644 lib/arg_parser/version.map", "diff": "diff --git a/.mailmap b/.mailmap\nindex 72b216df9c..c1a4bf85f6 100644\n--- a/.mailmap\n+++ b/.mailmap\n@@ -379,6 +379,7 @@ Eric Zhang <eric.zhang@windriver.com>\n Erik Gabriel Carrillo <erik.g.carrillo@intel.com>\n Erik Ziegenbalg <eziegenb@brocade.com>\n Erlu Chen <erlu.chen@intel.com>\n+Euan Bourke <euan.bourke@intel.com>\n Eugenio Pérez <eperezma@redhat.com>\n Eugeny Parshutin <eugeny.parshutin@linux.intel.com>\n Evan Swanson <evan.swanson@intel.com>\ndiff --git a/MAINTAINERS b/MAINTAINERS\nindex cf2af0d3a4..ce81877ce0 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1753,6 +1753,11 @@ M: Nithin Dabilpuram <ndabilpuram@marvell.com>\n M: Pavan Nikhilesh <pbhagavatula@marvell.com>\n F: lib/node/\n \n+Argument parsing\n+M: Bruce Richardson <bruce.richardson@intel.com>\n+M: Euan Bourke <euan.bourke@intel.com>\n+F: lib/arg_parser/\n+\n \n Test Applications\n -----------------\ndiff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md\nindex a6a768bd7c..f711010140 100644\n--- a/doc/api/doxy-api-index.md\n+++ b/doc/api/doxy-api-index.md\n@@ -221,7 +221,8 @@ The public API headers are grouped by topics:\n [config file](@ref rte_cfgfile.h),\n [key/value args](@ref rte_kvargs.h),\n [string](@ref rte_string_fns.h),\n- [thread](@ref rte_thread.h)\n+ [thread](@ref rte_thread.h),\n+ [argument parsing](@ref rte_arg_parser.h)\n \n - **debug**:\n [jobstats](@ref rte_jobstats.h),\ndiff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in\nindex e94c9e4e46..05718ba6ed 100644\n--- a/doc/api/doxy-api.conf.in\n+++ b/doc/api/doxy-api.conf.in\n@@ -28,6 +28,7 @@ INPUT = @TOPDIR@/doc/api/doxy-api-index.md \\\n @TOPDIR@/lib/eal/include \\\n @TOPDIR@/lib/eal/include/generic \\\n @TOPDIR@/lib/acl \\\n+ @TOPDIR@/lib/arg_parser \\\n @TOPDIR@/lib/bbdev \\\n @TOPDIR@/lib/bitratestats \\\n @TOPDIR@/lib/bpf \\\ndiff --git a/lib/arg_parser/arg_parser.c b/lib/arg_parser/arg_parser.c\nnew file mode 100644\nindex 0000000000..45acaf5631\n--- /dev/null\n+++ b/lib/arg_parser/arg_parser.c\n@@ -0,0 +1,113 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+\n+#include \"errno.h\"\n+#include \"stdlib.h\"\n+#include \"ctype.h\"\n+#include \"string.h\"\n+#include \"stdbool.h\"\n+\n+#include <rte_arg_parser.h>\n+#include <rte_common.h>\n+\n+\n+struct core_bits {\n+\tuint8_t bits[(UINT16_MAX + 1)/CHAR_BIT];\n+\tuint16_t max_bit_set;\n+\tuint16_t min_bit_set;\n+\tuint32_t total_bits_set;\n+};\n+\n+static inline bool\n+get_core_bit(struct core_bits *mask, uint16_t idx)\n+{\n+\treturn !!(mask->bits[idx/8] & (1 << (idx % 8)));\n+}\n+\n+static inline void\n+set_core_bit(struct core_bits *mask, uint16_t idx)\n+{\n+\tif (get_core_bit(mask, idx) == 0) {\n+\t\tmask->total_bits_set++;\n+\n+\t\t/* If its the first bit, assign min and max that value */\n+\t\tif (mask->total_bits_set == 1) {\n+\t\t\tmask->min_bit_set = idx;\n+\t\t\tmask->max_bit_set = idx;\n+\t\t}\n+\t}\n+\n+\tmask->bits[idx/8] |= 1 << (idx % 8);\n+\n+\tif (idx > mask->max_bit_set)\n+\t\tmask->max_bit_set = idx;\n+\n+\tif (idx < mask->min_bit_set)\n+\t\tmask->min_bit_set = idx;\n+}\n+\n+static inline void\n+corebits_to_array(struct core_bits *mask, uint16_t *cores, size_t max_cores)\n+{\n+\tuint32_t count = 0;\n+\tfor (uint32_t i = mask->min_bit_set; i <= mask->max_bit_set && count < max_cores; i++) {\n+\t\tif (get_core_bit(mask, i))\n+\t\t\tcores[count++] = i;\n+\t}\n+}\n+\n+\n+int\n+rte_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len)\n+{\n+\tint32_t min = -1;\n+\tchar *end = NULL;\n+\n+\tstruct core_bits *mask = malloc(sizeof(struct core_bits));\n+\tmemset(mask, 0, sizeof(struct core_bits));\n+\n+\tmin = -1;\n+\tdo {\n+\t\tuint32_t idx;\n+\t\tint32_t max;\n+\n+\t\twhile (isblank(*corelist))\n+\t\t\tcorelist++;\n+\t\tif (!isdigit(*corelist))\n+\t\t\treturn -1;\n+\t\terrno = 0;\n+\t\tidx = strtol(corelist, &end, 10);\n+\t\tif (errno || end == NULL)\n+\t\t\treturn -1;\n+\t\tif (idx > UINT16_MAX)\n+\t\t\treturn -1;\n+\t\twhile (isblank(*end))\n+\t\t\tend++;\n+\t\tif (*end == '-')\n+\t\t\tmin = idx;\n+\n+\t\telse if (*end == ',' || *end == '\\0') {\n+\t\t\tmax = idx;\n+\t\t\tif (min == -1)\n+\t\t\t\tmin = idx;\n+\n+\t\t\t/* Swap min and max if min is larger than max */\n+\t\t\tif (min > max)\n+\t\t\t\tRTE_SWAP(min, max);\n+\n+\t\t\tfor (; min <= max; min++)\n+\t\t\t\tset_core_bit(mask, min);\n+\n+\t\t\tmin = -1;\n+\t\t} else\n+\t\t\treturn -1;\n+\t\tcorelist = end + 1;\n+\t} while (*end != '\\0');\n+\n+\tcorebits_to_array(mask, cores, cores_len);\n+\tuint32_t total_count = mask->total_bits_set;\n+\tfree(mask);\n+\n+\treturn total_count;\n+}\ndiff --git a/lib/arg_parser/meson.build b/lib/arg_parser/meson.build\nnew file mode 100644\nindex 0000000000..6ee228bd69\n--- /dev/null\n+++ b/lib/arg_parser/meson.build\n@@ -0,0 +1,7 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2023 Intel Corporation\n+\n+sources = files('arg_parser.c')\n+headers = files('rte_arg_parser.h')\n+\n+includes += global_inc\ndiff --git a/lib/arg_parser/rte_arg_parser.h b/lib/arg_parser/rte_arg_parser.h\nnew file mode 100644\nindex 0000000000..1b12bf451f\n--- /dev/null\n+++ b/lib/arg_parser/rte_arg_parser.h\n@@ -0,0 +1,66 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Intel Corporation\n+ */\n+\n+#ifndef _RTE_ARG_PARSER_H_\n+#define _RTE_ARG_PARSER_H_\n+\n+/**\n+ * @file\n+ *\n+ * RTE Argument Parsing API\n+ *\n+ * The argument parsing API is a collection of functions to help parse\n+ * command line arguments. The API takes a string input and will return\n+ * it to the user in a more usable format.\n+ * \n+ */\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <stdint.h>\n+\n+#include <rte_compat.h>\n+\n+\n+/**\n+ * Convert a string describing a list of core ids into an array of core ids.\n+ *\n+ * On success, the passed array is filled with the core ids present in the\n+ * list up to the \"cores_len\", and the length of the array is returned.\n+ * For example, passing a 1-3,6 \"corelist\" results in an array of [1, 2, 3, 6]\n+ * and would return 4.\n+ * \n+ * Like the snprintf function for strings, if the length of the input array is\n+ * insufficient to hold the number of cores in the \"corelist\", the input array is\n+ * filled to capacity and the return value is the number of elements which would\n+ * be returned if the array had been big enough.\n+ * Function can also be called with a NULL array and 0 \"cores_len\" to find out\n+ * the \"cores_len\" required.\n+ *\n+ * @param corelist\n+ * Input string describing a list of core ids.\n+ * @param cores\n+ * An array where to store the core ids.\n+ * Array can be NULL if \"cores_len\" is 0.\n+ * @param cores_len\n+ * The length of the \"cores\" array.\n+ * If the size is smaller than that needed to hold all cores from \"corelist\",\n+ * only \"cores_len\" elements will be written to the array.\n+ * @return\n+ * n: the number of unique cores present in \"corelist\".\n+ * -1 if the string was invalid.\n+ * NOTE: if n > \"cores_len\", then only \"cores_len\" elements in the \"cores\" array are valid.\n+ */\n+__rte_experimental\n+int\n+rte_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len);\n+\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_ARG_PARSER_H_ */\ndiff --git a/lib/arg_parser/version.map b/lib/arg_parser/version.map\nnew file mode 100644\nindex 0000000000..f11699a306\n--- /dev/null\n+++ b/lib/arg_parser/version.map\n@@ -0,0 +1,10 @@\n+DPDK_24 {\n+ local: *;\n+};\n+\n+EXPERIMENTAL {\n+ global:\n+\n+ # added in 24.03\n+ rte_parse_corelist;\n+};\ndiff --git a/lib/meson.build b/lib/meson.build\nindex 6c143ce5a6..1b068fc61f 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -11,6 +11,7 @@\n libraries = [\n 'log',\n 'kvargs', # eal depends on kvargs\n+ 'arg_parser',\n 'telemetry', # basic info querying\n 'eal', # everything depends on eal\n 'ring',\n", "prefixes": [ "24.03", "1/4" ] }{ "id": 134536, "url": "