From patchwork Fri Dec 15 17:26:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135233 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id C2BBA43700; Fri, 15 Dec 2023 18:26:48 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 57A6343378; Fri, 15 Dec 2023 18:26:48 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id E23D243377 for ; Fri, 15 Dec 2023 18:26:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661207; x=1734197207; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Jl8Upv9c+THq3E/6rtRbdpy3u7DSwZOWMBllB/HvJfw=; b=h2u00kOxhAfZaqqVf6zVR/N5nUhlmU4cCu1TYvHx0WS4hBYWWxfeimHG Eh/D5AgK3tB3jIUfuVAV3S+8Q/jGlhBM0+GwhaubA3g/TVpYrTQbpddCq 1yuHf7TfXClvT+cVYpj/pFK9QG0D0n4XJWEf+EZicjymmRhPSGTm6KT79 PC47UY2HYz9ww6Nkk/iak+BnZnXOQV+YdQnhfbaCgLxDmiczZqiuuOXy0 C3uAdrAnErI0Jqak76+YwrA0BUQtAnPM0aptoSwQTKY1SMbnTN1XCS4L2 CiHDpSvX5qAkxdmomjsGfJv7JosOK1UT/cwmvwH1++mWekSNGf0ZlAeqV A==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474230" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474230" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:26:46 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914238" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:26:44 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Thomas Monjalon , Bruce Richardson Subject: [PATCH v4 1/8] arg_parser: new library for command line parsing Date: Fri, 15 Dec 2023 17:26:25 +0000 Message-Id: <20231215172632.3102502-2-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add a new library to make it easier for eal and other libraries to parse command line arguments. The first function in this library is one to parse a corelist string into an array of individual core ids. The function will then return the total number of cores described in the corelist. Signed-off-by: Euan Bourke --- .mailmap | 1 + MAINTAINERS | 4 ++ doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf.in | 1 + lib/arg_parser/arg_parser.c | 108 ++++++++++++++++++++++++++++++++ lib/arg_parser/meson.build | 7 +++ lib/arg_parser/rte_arg_parser.h | 66 +++++++++++++++++++ lib/arg_parser/version.map | 10 +++ lib/meson.build | 2 + 9 files changed, 200 insertions(+) create mode 100644 lib/arg_parser/arg_parser.c create mode 100644 lib/arg_parser/meson.build create mode 100644 lib/arg_parser/rte_arg_parser.h create mode 100644 lib/arg_parser/version.map diff --git a/.mailmap b/.mailmap index ab0742a382..528bc68a30 100644 --- a/.mailmap +++ b/.mailmap @@ -379,6 +379,7 @@ Eric Zhang Erik Gabriel Carrillo Erik Ziegenbalg Erlu Chen +Euan Bourke Eugenio PĂ©rez Eugeny Parshutin Evan Swanson diff --git a/MAINTAINERS b/MAINTAINERS index 0d1c8126e3..68ef5ba14b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1756,6 +1756,10 @@ M: Nithin Dabilpuram M: Pavan Nikhilesh F: lib/node/ +Argument parsing +M: Bruce Richardson +F: lib/arg_parser/ + Test Applications ----------------- diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index a6a768bd7c..743d3b6773 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -215,6 +215,7 @@ The public API headers are grouped by topics: [udp4_input_node](@ref rte_node_udp4_input_api.h) - **basic**: + [argument parsing](@ref rte_arg_parser.h), [bitops](@ref rte_bitops.h), [approx fraction](@ref rte_approx.h), [random](@ref rte_random.h), diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in index e94c9e4e46..05718ba6ed 100644 --- a/doc/api/doxy-api.conf.in +++ b/doc/api/doxy-api.conf.in @@ -28,6 +28,7 @@ INPUT = @TOPDIR@/doc/api/doxy-api-index.md \ @TOPDIR@/lib/eal/include \ @TOPDIR@/lib/eal/include/generic \ @TOPDIR@/lib/acl \ + @TOPDIR@/lib/arg_parser \ @TOPDIR@/lib/bbdev \ @TOPDIR@/lib/bitratestats \ @TOPDIR@/lib/bpf \ diff --git a/lib/arg_parser/arg_parser.c b/lib/arg_parser/arg_parser.c new file mode 100644 index 0000000000..d8324a27b1 --- /dev/null +++ b/lib/arg_parser/arg_parser.c @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include + +#include +#include + + +struct core_bits { + uint8_t bits[(UINT16_MAX + 1) / CHAR_BIT]; + uint16_t max_bit_set; + uint16_t min_bit_set; + uint32_t total_bits_set; +}; + +static inline bool +get_core_bit(struct core_bits *mask, uint16_t idx) +{ + return !!(mask->bits[idx / CHAR_BIT] & (1 << (idx % CHAR_BIT))); +} + +static inline void +set_core_bit(struct core_bits *mask, uint16_t idx) +{ + if (get_core_bit(mask, idx)) + return; + + mask->bits[idx / CHAR_BIT] |= 1 << (idx % CHAR_BIT); + /* Update min and max bit if its first time setting a bit */ + if (++(mask->total_bits_set) == 1) { + mask->min_bit_set = idx; + mask->max_bit_set = idx; + return; + } + + if (idx > mask->max_bit_set) + mask->max_bit_set = idx; + + if (idx < mask->min_bit_set) + mask->min_bit_set = idx; +} + +static inline uint32_t +corebits_to_array(struct core_bits *mask, uint16_t *cores, size_t max_cores) +{ + uint32_t count = 0; + for (uint32_t i = mask->min_bit_set; i <= mask->max_bit_set && count < max_cores; i++) { + if (get_core_bit(mask, i)) + cores[count++] = i; + } + return mask->total_bits_set; +} + + +int +rte_arg_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len) +{ + struct core_bits mask = {0}; + int32_t min = -1; + char *end = NULL; + + min = -1; + do { + int64_t idx; + int32_t max; + + while (isblank(*corelist)) + corelist++; + if (!isdigit(*corelist)) + return -EINVAL; + + errno = 0; + idx = strtol(corelist, &end, 10); + if (errno || end == NULL || idx > UINT16_MAX) + return -EINVAL; + while (isblank(*end)) + end++; + if (*end == '-') + min = idx; + + else if (*end == ',' || *end == '\0') { + /* Check for first number in range */ + if (min == -1) + min = max = idx; + /* Swap if min is larger than max */ + else if (min > idx) { + max = min; + min = idx; + } else /* Normal case */ + max = idx; + + for (; min <= max; min++) + set_core_bit(&mask, min); + + min = -1; + } else + return -EINVAL; + corelist = end + 1; + } while (*end != '\0'); + + return corebits_to_array(&mask, cores, cores_len); +} diff --git a/lib/arg_parser/meson.build b/lib/arg_parser/meson.build new file mode 100644 index 0000000000..6ee228bd69 --- /dev/null +++ b/lib/arg_parser/meson.build @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation + +sources = files('arg_parser.c') +headers = files('rte_arg_parser.h') + +includes += global_inc diff --git a/lib/arg_parser/rte_arg_parser.h b/lib/arg_parser/rte_arg_parser.h new file mode 100644 index 0000000000..a1ef428b95 --- /dev/null +++ b/lib/arg_parser/rte_arg_parser.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Intel Corporation + */ + +#ifndef _RTE_ARG_PARSER_H_ +#define _RTE_ARG_PARSER_H_ + +/** + * @file + * + * RTE Argument Parsing API + * + * The argument parsing API is a collection of functions to help parse + * command line arguments. The API takes a string input and will return + * it to the user in a more usable format. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + + +/** + * Convert a string describing a list of core ids into an array of core ids. + * + * On success, the passed array is filled with the core ids present in the list up + * to the "cores_len", and the number of unique cores present in the "corelist" + * is returned. + * For example, passing a 1-3,6 "corelist" results in an array of [1, 2, 3, 6] + * and would return 4. + * + * NOTE: if the length of the input array is insufficient to hold the number of core ids + * in "corelist" the input array is filled to capacity but the return value is the + * number of elements which would have been written to the array, had enough space been + * available. [This is similar to the behaviour of the snprintf function]. Because of + * this, the number of core values in the "corelist" may be determined by calling the + * function with a NULL array pointer and array length given as 0. + * + * @param corelist + * Input string describing a list of core ids. + * @param cores + * An array where to store the core ids. + * Array can be NULL if "cores_len" is 0. + * @param cores_len + * The length of the "cores" array. + * If the size is smaller than that needed to hold all cores from "corelist", + * only "cores_len" elements will be written to the array. + * @return + * n: the number of unique cores present in "corelist". + * -EINVAL if the string was invalid. + * NOTE: if n > "cores_len", then only "cores_len" elements in the "cores" array are valid. + */ +__rte_experimental +int +rte_arg_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_ARG_PARSER_H_ */ diff --git a/lib/arg_parser/version.map b/lib/arg_parser/version.map new file mode 100644 index 0000000000..b0caaac569 --- /dev/null +++ b/lib/arg_parser/version.map @@ -0,0 +1,10 @@ +DPDK_24 { + local: *; +}; + +EXPERIMENTAL { + global: + + # added in 24.03 + rte_arg_parse_corelist; +}; diff --git a/lib/meson.build b/lib/meson.build index 6c143ce5a6..db9e769033 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -11,6 +11,7 @@ libraries = [ 'log', 'kvargs', # eal depends on kvargs + 'arg_parser', 'telemetry', # basic info querying 'eal', # everything depends on eal 'ring', @@ -72,6 +73,7 @@ if is_ms_compiler 'log', 'kvargs', 'telemetry', + 'arg_parser', ] endif From patchwork Fri Dec 15 17:26:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135234 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 1CB3F43700; Fri, 15 Dec 2023 18:26:58 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D3E2B4338F; Fri, 15 Dec 2023 18:26:51 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id CB73C43399 for ; Fri, 15 Dec 2023 18:26:49 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661210; x=1734197210; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=BlKltLXAHkZnuOHB8DzlXHBUilkZroPUNFyag8fVs9w=; b=htl2PlpIzBpbry48TTyZy0GMHajiSg/itGWUIMaaDtjymYIjCUtcFSqS XTcPCC2MFN3aVi1N4IIRdqtCn4sDv8KV0m2qzLb9CJwr9lc2NNIriyE/h 8NFk5IYS7WEW2+zBtt3by4lvx2fIvd2giP0lYee1ymX6+YRf1MV4i0n3L kh3qmhIPH+7qrqwktUSRexH8DrGsrI8vatKJLEvFN6nvxvNfuK7nwp9HB 57kV9em6IxjKcuTDhW+6gw5OQhvreZZ1WPorXl8O0DUH9HexjudSp51MD lBF9mcbf3OWEtvuaPkE8FfPo0X/v8z324PE9XdLbPg2o8ehvo6zAAMINj A==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474237" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474237" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:26:49 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914244" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:26:48 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Bruce Richardson Subject: [PATCH v4 2/8] arg_parser: add new coremask parsing API Date: Fri, 15 Dec 2023 17:26:26 +0000 Message-Id: <20231215172632.3102502-3-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add new coremask parsing API. This API behaves similarly to the corelist parsing API, taking a coremask string, a cores array and a cores_len int. Parsing the coremask string, filling its values into the cores array up to cores_len. The API also returns a 'count' which corresponds to the total number of cores in the coremask string. Signed-off-by: Euan Bourke --- lib/arg_parser/arg_parser.c | 51 +++++++++++++++++++++++++++++++++ lib/arg_parser/rte_arg_parser.h | 34 ++++++++++++++++++++++ lib/arg_parser/version.map | 1 + 3 files changed, 86 insertions(+) diff --git a/lib/arg_parser/arg_parser.c b/lib/arg_parser/arg_parser.c index d8324a27b1..8d86a7b618 100644 --- a/lib/arg_parser/arg_parser.c +++ b/lib/arg_parser/arg_parser.c @@ -11,6 +11,9 @@ #include #include +#define BITS_PER_HEX 4 +#define MAX_COREMASK_SIZE ((UINT16_MAX + 1) / BITS_PER_HEX) + struct core_bits { uint8_t bits[(UINT16_MAX + 1) / CHAR_BIT]; @@ -57,6 +60,15 @@ corebits_to_array(struct core_bits *mask, uint16_t *cores, size_t max_cores) return mask->total_bits_set; } +static int xdigit2val(unsigned char c) +{ + if (isdigit(c)) + return c - '0'; + else if (isupper(c)) + return c - 'A' + 10; + else + return c - 'a' + 10; +} int rte_arg_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len) @@ -106,3 +118,42 @@ rte_arg_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len return corebits_to_array(&mask, cores, cores_len); } + +int +rte_arg_parse_coremask(const char *coremask, uint16_t *cores, uint32_t cores_len) +{ + struct core_bits mask = {0}; + + /* Remove all blank characters ahead and after . + * Remove 0x/0X if exists. + */ + while (isblank(*coremask)) + coremask++; + if (coremask[0] == '0' && ((coremask[1] == 'x') || (coremask[1] == 'X'))) + coremask += 2; + + int32_t i = strlen(coremask); + while ((i > 0) && isblank(coremask[i - 1])) + i--; + if (i == 0 || i > MAX_COREMASK_SIZE) + return -EINVAL; + + uint32_t idx = 0; + + for (i = i - 1; i >= 0; i--) { + int val; + char c = coremask[i]; + + if (isxdigit(c) == 0) + return -EINVAL; + + val = xdigit2val(c); + + for (uint8_t j = 0; j < BITS_PER_HEX; j++, idx++) { + if ((1 << j) & val) + set_core_bit(&mask, idx); + } + } + + return corebits_to_array(&mask, cores, cores_len); +} diff --git a/lib/arg_parser/rte_arg_parser.h b/lib/arg_parser/rte_arg_parser.h index a1ef428b95..49d7daa204 100644 --- a/lib/arg_parser/rte_arg_parser.h +++ b/lib/arg_parser/rte_arg_parser.h @@ -58,6 +58,40 @@ __rte_experimental int rte_arg_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len); +/** + * Convert a string describing a bitmask of core ids into an array of core ids. + * + * On success, the passed array is filled with the core ids present in the + * bitmask up to the "cores_len", and the number of unique cores present in the + * "coremask" is returned. + * For example, passing a 0xA "coremask" results in an array of [1, 3] + * and would return 2. + * + * NOTE: if the length of the input array is insufficient to hold the number of core ids + * in "coremask" the input array is filled to capacity but the return value is the + * number of elements which would have been written to the array, had enough space been + * available. [This is similar to the behaviour of the snprintf function]. Because of + * this, the number of core values in the "coremask" may be determined by calling the + * function with a NULL array pointer and array length given as 0. + * + * @param coremask + * A string containing a bitmask of core ids. + * @param cores + * An array where to store the core ids. + * Array can be NULL if "cores_len" is 0. + * @param cores_len + * The length of the "cores" array. + * If the size is smaller than that needed to hold all cores from "coremask", + * only "cores_len" elements will be written to the array. + * @return + * n: the number of unique cores present in "coremask". + * -EINVAL if the string was invalid. + * NOTE: if n > "cores_len", then only "cores_len" elements in the "cores" array are valid. + */ +__rte_experimental +int +rte_arg_parse_coremask(const char *coremask, uint16_t *cores, uint32_t cores_len); + #ifdef __cplusplus } diff --git a/lib/arg_parser/version.map b/lib/arg_parser/version.map index b0caaac569..b44d4b02b7 100644 --- a/lib/arg_parser/version.map +++ b/lib/arg_parser/version.map @@ -7,4 +7,5 @@ EXPERIMENTAL { # added in 24.03 rte_arg_parse_corelist; + rte_arg_parse_coremask; }; From patchwork Fri Dec 15 17:26:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135235 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id A02FE43700; Fri, 15 Dec 2023 18:27:05 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id F1DA74339E; Fri, 15 Dec 2023 18:26:54 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id C55B24339A for ; Fri, 15 Dec 2023 18:26:52 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661213; x=1734197213; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JeGTeJZFctZd+znjoV2swqZS09T6IyEHBTmac4LtOtQ=; b=OxmYwTT4OD8Bc9iqCf6ttwPa/zTmWGT72RExERbkU2XWxKATInNLJHPd rsSopKED7qxM6lJl7vUJQwyCWLOqXL2IU9hBGnOm53raM3aMAnAXuJ53x azc909BWm8t3eM72rcqugp57n1e9No6W2Lse7PWab2cMAgcvR5/9/0TFU zvrdR+KRT8RsdsYlrL0NYW9VisH7Ggc6Qum7rty7cUfNEUq23GJXo7H44 +aY4TrrzWrrAj9j0Fukcd+iI+T1Nl1Ii8jqEeTFrs8f5X2f2/KATBEz25 zZaImjfMEEQUm/XeFIx26JTXIzEU9pv5No1usChzERCRphadm63OsY9e9 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474246" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474246" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:26:52 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914251" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:26:52 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke Subject: [PATCH v4 3/8] eal: add support for new arg parsing library Date: Fri, 15 Dec 2023 17:26:27 +0000 Message-Id: <20231215172632.3102502-4-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Update to eal functions relating to corelist and coremask parsing to support the new arg parsing library. Functions now call the API instead of implementing their own version. Signed-off-by: Euan Bourke --- lib/eal/common/eal_common_options.c | 114 ++++------------------------ lib/eal/meson.build | 2 +- 2 files changed, 14 insertions(+), 102 deletions(-) diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c index a6d21f1cba..60ba12a368 100644 --- a/lib/eal/common/eal_common_options.c +++ b/lib/eal/common/eal_common_options.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #ifndef RTE_EXEC_ENV_WINDOWS #include @@ -706,7 +707,7 @@ update_lcore_config(int *cores) } static int -check_core_list(int *lcores, unsigned int count) +check_core_list(uint16_t *lcores, unsigned int count) { char lcorestr[RTE_MAX_LCORE * 10]; bool overflow = false; @@ -746,60 +747,18 @@ check_core_list(int *lcores, unsigned int count) int rte_eal_parse_coremask(const char *coremask, int *cores) { - const char *coremask_orig = coremask; - int lcores[RTE_MAX_LCORE]; - unsigned int count = 0; - int i, j, idx; - int val; - char c; + int count; + uint16_t lcores[RTE_MAX_LCORE]; + int idx; for (idx = 0; idx < RTE_MAX_LCORE; idx++) cores[idx] = -1; - idx = 0; - /* Remove all blank characters ahead and after . - * Remove 0x/0X if exists. - */ - while (isblank(*coremask)) - coremask++; - if (coremask[0] == '0' && ((coremask[1] == 'x') - || (coremask[1] == 'X'))) - coremask += 2; - i = strlen(coremask); - while ((i > 0) && isblank(coremask[i - 1])) - i--; - if (i == 0) { - RTE_LOG(ERR, EAL, "No lcores in coremask: [%s]\n", - coremask_orig); - return -1; - } + /* Call public coremask parsing API */ + count = rte_arg_parse_coremask(coremask, lcores, RTE_MAX_LCORE); - for (i = i - 1; i >= 0; i--) { - c = coremask[i]; - if (isxdigit(c) == 0) { - /* invalid characters */ - RTE_LOG(ERR, EAL, "invalid characters in coremask: [%s]\n", - coremask_orig); - return -1; - } - val = xdigit2val(c); - for (j = 0; j < BITS_PER_HEX; j++, idx++) - { - if ((1 << j) & val) { - if (count >= RTE_MAX_LCORE) { - RTE_LOG(ERR, EAL, "Too many lcores provided. Cannot exceed RTE_MAX_LCORE (%d)\n", - RTE_MAX_LCORE); - return -1; - } - lcores[count++] = idx; - } - } - } - if (count == 0) { - RTE_LOG(ERR, EAL, "No lcores in coremask: [%s]\n", - coremask_orig); + if (count <= 0 || count > RTE_MAX_LCORE) return -1; - } if (check_core_list(lcores, count)) return -1; @@ -898,64 +857,17 @@ eal_parse_service_corelist(const char *corelist) static int eal_parse_corelist(const char *corelist, int *cores) { - unsigned int count = 0, i; - int lcores[RTE_MAX_LCORE]; - char *end = NULL; - int min, max; + int count; + uint16_t lcores[RTE_MAX_LCORE]; int idx; for (idx = 0; idx < RTE_MAX_LCORE; idx++) cores[idx] = -1; - /* Remove all blank characters ahead */ - while (isblank(*corelist)) - corelist++; + /* Call public corelist parsing API */ + count = rte_arg_parse_corelist(corelist, lcores, RTE_MAX_LCORE); - /* Get list of cores */ - min = -1; - do { - while (isblank(*corelist)) - corelist++; - if (*corelist == '\0') - return -1; - errno = 0; - idx = strtol(corelist, &end, 10); - if (errno || end == NULL) - return -1; - if (idx < 0) - return -1; - while (isblank(*end)) - end++; - if (*end == '-') { - min = idx; - } else if ((*end == ',') || (*end == '\0')) { - max = idx; - if (min == -1) - min = idx; - for (idx = min; idx <= max; idx++) { - bool dup = false; - - /* Check if this idx is already present */ - for (i = 0; i < count; i++) { - if (lcores[i] == idx) - dup = true; - } - if (dup) - continue; - if (count >= RTE_MAX_LCORE) { - RTE_LOG(ERR, EAL, "Too many lcores provided. Cannot exceed RTE_MAX_LCORE (%d)\n", - RTE_MAX_LCORE); - return -1; - } - lcores[count++] = idx; - } - min = -1; - } else - return -1; - corelist = end + 1; - } while (*end != '\0'); - - if (count == 0) + if (count <= 0 || count > RTE_MAX_LCORE) return -1; if (check_core_list(lcores, count)) diff --git a/lib/eal/meson.build b/lib/eal/meson.build index e1d6c4cf17..52a22e2e66 100644 --- a/lib/eal/meson.build +++ b/lib/eal/meson.build @@ -14,7 +14,7 @@ subdir(exec_env) subdir(arch_subdir) -deps += ['log', 'kvargs'] +deps += ['log', 'kvargs', 'arg_parser'] if not is_windows deps += ['telemetry'] endif From patchwork Fri Dec 15 17:26:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135236 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id CB71A43700; Fri, 15 Dec 2023 18:27:12 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 35B71433A4; Fri, 15 Dec 2023 18:26:57 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id AC8B5433A1 for ; Fri, 15 Dec 2023 18:26:55 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661216; x=1734197216; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LVghYsSuh7gYwi/527BOt+d4xJ7IPnG1RmWH9spLqnc=; b=LGGSi1P9k2RtT3GwbfawI9pWoNqyxhQ/lfDhmdDf/GK9C371UNCI984T PooZIuc92Y1WZnsw9Yd5MKpQEyi1fnJy1bkKPPe6NupQFyQiWTC1BojHq Eoqqh+Eog/w8PaJgd9KCZ+Zj/dq/VPTXMKaLLZzT++JLJAJUYo9FOKHW+ Y1ih2VXh17EuJRKNnikzXA0Yc7pflWBnOTWUzepXR5F0okdx16jARGO6L 6nkGSH5gjpMHcSThRFKLdgFOx5BR+AL00YxRDyY/ULYzSGq8RcqRMl8B6 xb24N+QBZ8/3+STy+zqJUh6k2mrFN8YcrmN6tcRtpNZ+RNENkBVYaxfkI w==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474250" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474250" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:26:55 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914256" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:26:54 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke Subject: [PATCH v4 4/8] eal: update to service core related parsers Date: Fri, 15 Dec 2023 17:26:28 +0000 Message-Id: <20231215172632.3102502-5-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Updates to the parse service cores functions in EAL to call the arg parser API instead of implementing its own versions. Signed-off-by: Euan Bourke --- lib/eal/common/eal_common_options.c | 171 +++++++--------------------- 1 file changed, 41 insertions(+), 130 deletions(-) diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c index 60ba12a368..d44654f621 100644 --- a/lib/eal/common/eal_common_options.c +++ b/lib/eal/common/eal_common_options.c @@ -573,97 +573,49 @@ eal_plugins_init(void) * the global configuration (core role and core count) with the parsed * value. */ -static int xdigit2val(unsigned char c) -{ - int val; - - if (isdigit(c)) - val = c - '0'; - else if (isupper(c)) - val = c - 'A' + 10; - else - val = c - 'a' + 10; - return val; -} - static int eal_parse_service_coremask(const char *coremask) { struct rte_config *cfg = rte_eal_get_configuration(); - int i, j, idx = 0; - unsigned int count = 0; - char c; - int val; + uint16_t cores[RTE_MAX_LCORE]; + int64_t count; uint32_t taken_lcore_count = 0; - if (coremask == NULL) - return -1; - /* Remove all blank characters ahead and after . - * Remove 0x/0X if exists. - */ - while (isblank(*coremask)) - coremask++; - if (coremask[0] == '0' && ((coremask[1] == 'x') - || (coremask[1] == 'X'))) - coremask += 2; - i = strlen(coremask); - while ((i > 0) && isblank(coremask[i - 1])) - i--; - - if (i == 0) + count = rte_arg_parse_coremask(coremask, cores, RTE_DIM(cores)); + + if (count == 0 || count == -1) return -1; - for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) { - c = coremask[i]; - if (isxdigit(c) == 0) { - /* invalid characters */ + for (int i = 0; i < count; i++) { + uint32_t lcore = cores[i]; + if (main_lcore_parsed && + cfg->main_lcore == lcore) { + RTE_LOG(ERR, EAL, + "lcore %u is main lcore, cannot use as service core\n", + cores[i]); return -1; } - val = xdigit2val(c); - for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; - j++, idx++) { - if ((1 << j) & val) { - /* handle main lcore already parsed */ - uint32_t lcore = idx; - if (main_lcore_parsed && - cfg->main_lcore == lcore) { - RTE_LOG(ERR, EAL, - "lcore %u is main lcore, cannot use as service core\n", - idx); - return -1; - } - if (eal_cpu_detected(idx) == 0) { - RTE_LOG(ERR, EAL, - "lcore %u unavailable\n", idx); - return -1; - } - - if (cfg->lcore_role[idx] == ROLE_RTE) - taken_lcore_count++; - - lcore_config[idx].core_role = ROLE_SERVICE; - count++; - } - } - } - - for (; i >= 0; i--) - if (coremask[i] != '0') + if (eal_cpu_detected(cores[i]) == 0) { + RTE_LOG(ERR, EAL, + "lcore %u unavailable\n", cores[i]); return -1; + } - for (; idx < RTE_MAX_LCORE; idx++) - lcore_config[idx].core_index = -1; - - if (count == 0) - return -1; + if (cfg->lcore_role[cores[i]] == ROLE_RTE) + taken_lcore_count++; + lcore_config[cores[i]].core_role = ROLE_SERVICE; + } if (core_parsed && taken_lcore_count != count) { RTE_LOG(WARNING, EAL, - "Not all service cores are in the coremask. " + "Not all service cores were in the coremask. " "Please ensure -c or -l includes service cores\n"); } + for (uint16_t j = count*4; j < RTE_MAX_LCORE; j++) + lcore_config[j].core_index = -1; + cfg->service_lcore_count = count; return 0; } @@ -780,70 +732,29 @@ static int eal_parse_service_corelist(const char *corelist) { struct rte_config *cfg = rte_eal_get_configuration(); - int i; - unsigned count = 0; - char *end = NULL; - uint32_t min, max, idx; + int64_t i, count; + uint16_t cores[RTE_MAX_LCORE]; uint32_t taken_lcore_count = 0; - if (corelist == NULL) - return -1; + count = rte_arg_parse_corelist(corelist, cores, RTE_DIM(cores)); - /* Remove all blank characters ahead and after */ - while (isblank(*corelist)) - corelist++; - i = strlen(corelist); - while ((i > 0) && isblank(corelist[i - 1])) - i--; + if (count == 0 || count == -1) + return -1; - /* Get list of cores */ - min = RTE_MAX_LCORE; - do { - while (isblank(*corelist)) - corelist++; - if (*corelist == '\0') - return -1; - errno = 0; - idx = strtoul(corelist, &end, 10); - if (errno || end == NULL) - return -1; - if (idx >= RTE_MAX_LCORE) - return -1; - while (isblank(*end)) - end++; - if (*end == '-') { - min = idx; - } else if ((*end == ',') || (*end == '\0')) { - max = idx; - if (min == RTE_MAX_LCORE) - min = idx; - for (idx = min; idx <= max; idx++) { - if (cfg->lcore_role[idx] != ROLE_SERVICE) { - /* handle main lcore already parsed */ - uint32_t lcore = idx; - if (cfg->main_lcore == lcore && - main_lcore_parsed) { - RTE_LOG(ERR, EAL, - "Error: lcore %u is main lcore, cannot use as service core\n", - idx); - return -1; - } - if (cfg->lcore_role[idx] == ROLE_RTE) - taken_lcore_count++; - - lcore_config[idx].core_role = - ROLE_SERVICE; - count++; - } - } - min = RTE_MAX_LCORE; - } else + for (i = 0; i < count; i++) { + uint32_t lcore = cores[i]; + if (cfg->main_lcore == lcore && + main_lcore_parsed) { + RTE_LOG(ERR, EAL, + "Error: lcore %u is main lcore, cannot use as service core\n", + cores[i]); return -1; - corelist = end + 1; - } while (*end != '\0'); + } + if (cfg->lcore_role[cores[i]] == ROLE_RTE) + taken_lcore_count++; - if (count == 0) - return -1; + lcore_config[cores[i]].core_role = ROLE_SERVICE; + } if (core_parsed && taken_lcore_count != count) { RTE_LOG(WARNING, EAL, From patchwork Fri Dec 15 17:26:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135237 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 97F9143700; Fri, 15 Dec 2023 18:27:19 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6F0B94339A; Fri, 15 Dec 2023 18:27:00 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id 7B6B4433A8 for ; Fri, 15 Dec 2023 18:26:58 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661218; x=1734197218; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zFQ2rHxu1X0r2TEHDZIX1mt9oK01LWnLJ4/zA2wqdLA=; b=Okktz0HkEiS0u18MJqJqTckbWBm9s/lMoKb7sS9X7+5Qve3HyYUlKDnn l9UKGRCo8csLiij8KBrted1cRrrI3iNbtxIaa7DWTimB+fHHIvun1hT2k JzLkcTAGbadEhvSebLXSvGwFAefDU6NE9g3+397zkUDblRRwmn8qnLFze Qp7QTl9qadxHQo6umd720z1CJGS3H6sn85tUCJfp3YXDGV/o5wo/9Tafj HSF0J+kcP8/fxX9gurGceDSiLR8CX2g8Y0LfcZ3MrHc85V4jCKEW3iCkN NiRDHFtl1dyscOXrr6m6kUEjtNzFVNICGH4BS4uhWIaJu0BQLRBGaaUpk A==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474251" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474251" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:26:58 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914270" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:26:57 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Abdullah Sevincer Subject: [PATCH v4 5/8] event/dlb2: add new arg parsing library API support Date: Fri, 15 Dec 2023 17:26:29 +0000 Message-Id: <20231215172632.3102502-6-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Switched the dlb2 driver to call the new arg parsing library instead of eal for coremask parsing, and updated the resource probe function to support the changed formatting of the API. Signed-off-by: Euan Bourke --- drivers/event/dlb2/dlb2_priv.h | 4 +- drivers/event/dlb2/pf/base/dlb2_resource.c | 51 +++++++++------------- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/drivers/event/dlb2/dlb2_priv.h b/drivers/event/dlb2/dlb2_priv.h index 31a3beeb6c..c14d83da5b 100644 --- a/drivers/event/dlb2/dlb2_priv.h +++ b/drivers/event/dlb2/dlb2_priv.h @@ -10,6 +10,7 @@ #include #include +#include #include "dlb2_user.h" #include "dlb2_log.h" #include "rte_pmd_dlb2.h" @@ -729,9 +730,6 @@ void dlb2_event_build_hcws(struct dlb2_port *qm_port, uint8_t *sched_type, uint8_t *queue_id); -/* Extern functions */ -extern int rte_eal_parse_coremask(const char *coremask, int *cores); - /* Extern globals */ extern struct process_local_port_data dlb2_port[][DLB2_NUM_PORT_TYPES]; diff --git a/drivers/event/dlb2/pf/base/dlb2_resource.c b/drivers/event/dlb2/pf/base/dlb2_resource.c index 7ce3e3531c..b65de9350a 100644 --- a/drivers/event/dlb2/pf/base/dlb2_resource.c +++ b/drivers/event/dlb2/pf/base/dlb2_resource.c @@ -922,49 +922,38 @@ dlb2_resource_probe(struct dlb2_hw *hw, const void *probe_args) { const struct dlb2_devargs *args = (const struct dlb2_devargs *)probe_args; const char *mask = args ? args->producer_coremask : NULL; - int cpu = 0, cnt = 0, cores[RTE_MAX_LCORE], i; + int cpu = 0, i; + uint16_t cores[RTE_MAX_LCORE]; if (args) { mask = (const char *)args->producer_coremask; } - if (mask && rte_eal_parse_coremask(mask, cores)) { + int ret = rte_arg_parse_coremask(mask, cores, RTE_DIM(cores)); + + if (mask && ret == -1) { DLB2_LOG_ERR(": Invalid producer coremask=%s", mask); return -1; } - hw->num_prod_cores = 0; - for (i = 0; i < RTE_MAX_LCORE; i++) { - bool is_pcore = (mask && cores[i] != -1); - - if (rte_lcore_is_enabled(i)) { - if (is_pcore) { - /* - * Populate the producer cores from parsed - * coremask - */ - hw->prod_core_list[cores[i]] = i; - hw->num_prod_cores++; - - } else if ((++cnt == DLB2_EAL_PROBE_CORE || - rte_lcore_count() < DLB2_EAL_PROBE_CORE)) { - /* - * If no producer coremask is provided, use the - * second EAL core to probe - */ - cpu = i; - break; - } - } else if (is_pcore) { + hw->num_prod_cores = ret; + /* Check for no producer cores and then get the second EAL core */ + if (hw->num_prod_cores > 0) + cpu = cores[0]; + else if (rte_lcore_count() < DLB2_EAL_PROBE_CORE) + cpu = rte_get_main_lcore(); + else + cpu = rte_get_next_lcore(-1, 1, 0); + + /* check our producer list is valid and error out if not */ + for (i = 0; i < hw->num_prod_cores; i++) { + if (!rte_lcore_is_enabled(cores[i])) { DLB2_LOG_ERR("Producer coremask(%s) must be a subset of EAL coremask", - mask); + mask); return -1; - } - } - /* Use the first core in producer coremask to probe */ - if (hw->num_prod_cores) - cpu = hw->prod_core_list[0]; + hw->prod_core_list[i] = cores[i]; +} dlb2_get_pp_allocation(hw, cpu, DLB2_LDB_PORT); dlb2_get_pp_allocation(hw, cpu, DLB2_DIR_PORT); From patchwork Fri Dec 15 17:26:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135238 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id CA9BF43700; Fri, 15 Dec 2023 18:27:25 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8EFB1433AC; Fri, 15 Dec 2023 18:27:02 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id 30046433AC for ; Fri, 15 Dec 2023 18:27:01 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661221; x=1734197221; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zfSPueyhYozZXaM0NV4BRRu14E9MVKrTRbt8MBI3Hr4=; b=hq8yXfum/uqGebwQWHGUu/jpsGveUY+OjYHm0pvxCq2dhLuof4nd4Lrq ebtg4YD2nNJ00U5ByMvP9nzd5hFmb9q5EsKZWZUjAbwiP5eXs3YiTpsUE 02gyghsUBTPJjZbeO0lC34bp66yEyYrrhELD9vggcM8BNHgGCge3Pk5JZ NqG/Dvm5e7Y6JXGRI/kdPTdAk/mvUWJekwxub0M3S+jq0a1Tm46X47OPy 4fisUbY3GaVS7FtjqwkreDe6tGe3hIsrxSbVWNjhEUgvfGy+oqYcy2vUX uXyfaThLj4s8QO77WLuYHsl8dg9nEHUZcVEGFNwj8CHdq2dXiy7It3zmn A==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474255" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474255" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:27:01 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914284" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:27:00 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Bruce Richardson Subject: [PATCH v4 6/8] arg_parser: added common core string and heuristic parsers Date: Fri, 15 Dec 2023 17:26:30 +0000 Message-Id: <20231215172632.3102502-7-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Two new functions, the first is a 'heuristic parser' which examines a string describing a set of cores and determines based off heuristics whether its a coremask or a corelist. Second is a 'combined parser' which calls the first function and then based off the returned value will call the relevant core string parser. This function also takes a 'default_type' int which corresponds to which parser should be used in the case of an ambiguous string. Signed-off-by: Euan Bourke --- lib/arg_parser/arg_parser.c | 62 ++++++++++++++++++++++++++++++++ lib/arg_parser/rte_arg_parser.h | 64 +++++++++++++++++++++++++++++++++ lib/arg_parser/version.map | 2 ++ 3 files changed, 128 insertions(+) diff --git a/lib/arg_parser/arg_parser.c b/lib/arg_parser/arg_parser.c index 8d86a7b618..1755ecb3b2 100644 --- a/lib/arg_parser/arg_parser.c +++ b/lib/arg_parser/arg_parser.c @@ -157,3 +157,65 @@ rte_arg_parse_coremask(const char *coremask, uint16_t *cores, uint32_t cores_len return corebits_to_array(&mask, cores, cores_len); } + +int +rte_arg_parse_arg_type(const char *core_string) +{ + /* Remove leading whitespace */ + while (isblank(*core_string)) + core_string++; + + /* Check for 0x prefix */ + if (core_string[0] == '0' && tolower(core_string[1]) == 'x') { + if (core_string[2] != '\0') + return RTE_ARG_PARSE_TYPE_COREMASK; + return -EINVAL; + } + + int i = 0, idx = 0; + /* Check for ',' and '-' and check for A-F */ + do { + while (isblank(core_string[idx])) + idx++; + + if (core_string[idx] == ',' || core_string[idx] == '-') + return RTE_ARG_PARSE_TYPE_CORELIST; + + if (isalpha(core_string[idx])) { + if (isxdigit(core_string[idx])) + return RTE_ARG_PARSE_TYPE_COREMASK; + return -EINVAL; + } + idx++; + i++; + } while (core_string[idx] != '\0'); + + /* Check length of core_string if ambiguous as max length of a uint16_t is 5 digits + * implying its a coremask. + */ + if (i > 5) + return RTE_ARG_PARSE_TYPE_COREMASK; + + return -EINVAL; +} + +int +rte_arg_parse_core_string(const char *core_string, uint16_t *cores, uint32_t cores_len, + int default_type) +{ + if (default_type != RTE_ARG_PARSE_TYPE_COREMASK && + default_type != RTE_ARG_PARSE_TYPE_CORELIST) { + return -EINVAL; + } + switch (rte_arg_parse_arg_type(core_string)) { + case RTE_ARG_PARSE_TYPE_COREMASK: + return rte_arg_parse_coremask(core_string, cores, cores_len); + case RTE_ARG_PARSE_TYPE_CORELIST: + return rte_arg_parse_corelist(core_string, cores, cores_len); + default: + return default_type == RTE_ARG_PARSE_TYPE_COREMASK ? + rte_arg_parse_coremask(core_string, cores, cores_len) : + rte_arg_parse_corelist(core_string, cores, cores_len); + return -EINVAL; + } +} diff --git a/lib/arg_parser/rte_arg_parser.h b/lib/arg_parser/rte_arg_parser.h index 49d7daa204..3b2df74d10 100644 --- a/lib/arg_parser/rte_arg_parser.h +++ b/lib/arg_parser/rte_arg_parser.h @@ -23,6 +23,9 @@ extern "C" { #include +#define RTE_ARG_PARSE_TYPE_COREMASK 0 +#define RTE_ARG_PARSE_TYPE_CORELIST 1 +#define RTE_ARG_PARSE_TYPE_UNKNOWN 2 /** * Convert a string describing a list of core ids into an array of core ids. @@ -92,6 +95,67 @@ __rte_experimental int rte_arg_parse_coremask(const char *coremask, uint16_t *cores, uint32_t cores_len); +/** + * Use heuristics to determine if a string contains a coremask or a corelist. + * + * This function will check a series of conditions and return an int representing which + * core type (mask or list) the string represents or report the type as unknown if the + * string is ambiguous. + * + * @param core_string + * A string describing the intended cores to be parsed + * @return + * int representing the core type + * RTE_ARG_PARSE_TYPE_COREMASK: coremask. + * RTE_ARG_PARSE_TYPE_CORELIST: corelist. + * RTE_ARG_PARSE_TYPE_UNKNOWN: unknown (ambiguous). + * -EINVAL if the string was invalid. + */ +__rte_experimental +int +rte_arg_parse_arg_type(const char *core_string); + +/** + * Convert a string describing either a corelist or coremask into an array of core ids. + * + * This function will fill the "cores" array up to "cores_len" with the core ids described + * in the "core_string". The string can either describe a corelist or a coremask, and + * will be parsed accordingly. The number of unique core ids in the string is then returned. + * For example: + * "1-4" is treated as a corelist and results in an array of [1,2,3,4] with 4 being returned + * "0xA1" is treated as a coremask and results in an array of [0,5,7] with 3 being returned + * + * In the case of an ambiguous string, the function will use the default_type parameter to + * decide. + * + * NOTE: if the length of the input array is insufficient to hold the number of core ids + * in "core_string" the input array is filled to capacity but the return value is the + * number of elements which would have been written to the array, had enough space been + * available. [This is similar to the behaviour of the snprintf function]. Because of + * this, the number of core values in the "core_string" may be determined by calling the + * function with a NULL array pointer and array length given as 0. + * + * @param core_string + * A string describing the intended cores to be parsed. + * @param cores + * An array where to store the core ids. + * Array can be NULL if "cores_len" is 0. + * @param cores_len + * The length of the "cores" array. + * If the size is smaller than that needed to hold all cores from "core_string" + * @param default_type + * How to treat ambiguous cases (e.g. '4' could be mask or list). + * RTE_ARG_PARSE_TYPE_COREMASK: coremask. + * RTE_ARG_PARSE_TYPE_CORELIST: corelist. + * @return + * n: the number of unique cores present in "core_string". + * -EINVAL if the string was invalid. + * NOTE: if n > "cores_len", then only "cores_len" elements in the "cores" array are valid. + */ +__rte_experimental +int +rte_arg_parse_core_string(const char *core_string, uint16_t *cores, uint32_t cores_len, + int default_type); #ifdef __cplusplus } diff --git a/lib/arg_parser/version.map b/lib/arg_parser/version.map index b44d4b02b7..1e54b91dae 100644 --- a/lib/arg_parser/version.map +++ b/lib/arg_parser/version.map @@ -6,6 +6,8 @@ EXPERIMENTAL { global: # added in 24.03 + rte_arg_parse_arg_type; rte_arg_parse_corelist; rte_arg_parse_coremask; + rte_arg_parse_core_string; }; From patchwork Fri Dec 15 17:26:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135239 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 2018443700; Fri, 15 Dec 2023 18:27:35 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E64C3433B5; Fri, 15 Dec 2023 18:27:05 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id 0E71D433BF for ; Fri, 15 Dec 2023 18:27:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661224; x=1734197224; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5l5sU4EugsPauK8Vfoc5qJj20SctflAYnknNS1cEcZ0=; b=SZdtb8EYiKDCIh/GR9AP6K99NdTeL4TnnaUbBYxX6NOWzig92qbsXMHb KqKLExqk1F764SBk/BI6hl5wQKvwtJTLtDkU3E6OKyMRJNCzjOx7TUwoo JA4/093PapUxjDqJGj9lZyOrnaTjygtgTzmfBY3T6VYjJRZljZDzjAm5y poLejAh9+4Xw0UDhulwNzoFsCY6nvZ0F3UKKrP7XNyiXk3C692FsfQHjM qYNXPqhPZA6IyMfyMJIy/zOhUqHZ5kqixPbH1pwsXokCWOCdfvyxCdKfK /RInA6DjbO0tQ9Qs47niXWi52R48LreX3ad5G3L+iFpvy67jYsFNzxg96 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474259" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474259" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:27:03 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914289" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:27:03 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Harry van Haaren Subject: [PATCH v4 7/8] examples/eventdev_pipeline: update to call arg parser API Date: Fri, 15 Dec 2023 17:26:31 +0000 Message-Id: <20231215172632.3102502-8-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Update to the eventdev_pipeline example application to call the arg parser library for its 'combined core string parser' instead of implementing its own coremask parser. The default_type passed into the function call is a coremask. Signed-off-by: Euan Bourke --- examples/eventdev_pipeline/main.c | 66 +++----------------- examples/eventdev_pipeline/pipeline_common.h | 1 + 2 files changed, 11 insertions(+), 56 deletions(-) diff --git a/examples/eventdev_pipeline/main.c b/examples/eventdev_pipeline/main.c index 0c995d1a70..edd0e2c843 100644 --- a/examples/eventdev_pipeline/main.c +++ b/examples/eventdev_pipeline/main.c @@ -56,69 +56,23 @@ core_in_use(unsigned int lcore_id) { fdata->tx_core[lcore_id] || fdata->worker_core[lcore_id]); } -/* - * Parse the coremask given as argument (hexadecimal string) and fill - * the global configuration (core role and core count) with the parsed - * value. - */ -static int xdigit2val(unsigned char c) -{ - int val; - - if (isdigit(c)) - val = c - '0'; - else if (isupper(c)) - val = c - 'A' + 10; - else - val = c - 'a' + 10; - return val; -} - static uint64_t parse_coremask(const char *coremask) { - int i, j, idx = 0; - unsigned int count = 0; - char c; - int val; + int count; + uint16_t i; uint64_t mask = 0; - const int32_t BITS_HEX = 4; + uint16_t cores[RTE_MAX_LCORE]; - if (coremask == NULL) - return -1; - /* Remove all blank characters ahead and after . - * Remove 0x/0X if exists. - */ - while (isblank(*coremask)) - coremask++; - if (coremask[0] == '0' && ((coremask[1] == 'x') - || (coremask[1] == 'X'))) - coremask += 2; - i = strlen(coremask); - while ((i > 0) && isblank(coremask[i - 1])) - i--; - if (i == 0) - return -1; + count = rte_arg_parse_core_string(coremask, cores, RTE_DIM(cores), + RTE_ARG_PARSE_TYPE_COREMASK); - for (i = i - 1; i >= 0 && idx < MAX_NUM_CORE; i--) { - c = coremask[i]; - if (isxdigit(c) == 0) { - /* invalid characters */ - return -1; - } - val = xdigit2val(c); - for (j = 0; j < BITS_HEX && idx < MAX_NUM_CORE; j++, idx++) { - if ((1 << j) & val) { - mask |= (1ULL << idx); - count++; - } - } - } - for (; i >= 0; i--) - if (coremask[i] != '0') - return -1; - if (count == 0) + if (count == 0 || count == -1) return -1; + + for (i = 0; i < count; i++) + mask |= 1ULL << cores[i]; + return mask; } diff --git a/examples/eventdev_pipeline/pipeline_common.h b/examples/eventdev_pipeline/pipeline_common.h index 28b6ab85ff..2b97a29bfc 100644 --- a/examples/eventdev_pipeline/pipeline_common.h +++ b/examples/eventdev_pipeline/pipeline_common.h @@ -6,6 +6,7 @@ #include +#include #include #include #include From patchwork Fri Dec 15 17:26:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 135240 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 1375A43700; Fri, 15 Dec 2023 18:27:42 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 07038433BA; Fri, 15 Dec 2023 18:27:09 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.10]) by mails.dpdk.org (Postfix) with ESMTP id 042F7433BA for ; Fri, 15 Dec 2023 18:27:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1702661227; x=1734197227; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MvgOX7W+CxNxzucGWfoItQH9t6AmZZ75Up9W9eV8szs=; b=S6tB8BxLt9fjUG2ynCVuXZMxyNlQTnJre0BN6t66MIiNujbvt6AQidMy SFrRy+vQcizLy2bHHPMq9ZImCNN4uPIvHebqbQrEg3RWKJjlGsrUuJSj6 pc2+sQUcSDaEmChAVFBOLHLauNOiTA0ywDb4xGB04iZcmLEsSz/H+hTMB sZT7zlqfVO0ckvIEYoYb3xdOuBg+aEVsSz4JQudWJWZb0EvdhPKqqbOLe Grr/VGuI2WDmjzhuhQrs7NyQq28nRYOwb23M/leh09mof9DZ3HQEybm7w +GTXXAPQPMA786RbZHWlw7QBB2AYLptaeJ93Ynm3uRZGTCkWAEmwNYf5o w==; X-IronPort-AV: E=McAfee;i="6600,9927,10925"; a="2474266" X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="2474266" Received: from orviesa001.jf.intel.com ([10.64.159.141]) by fmvoesa104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Dec 2023 09:27:06 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.04,279,1695711600"; d="scan'208";a="22914297" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orviesa001.jf.intel.com with ESMTP; 15 Dec 2023 09:27:05 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , David Hunt , Anatoly Burakov , Sivaprasad Tummala Subject: [PATCH v4 8/8] examples/l3fwd-power: update to call arg parser API Date: Fri, 15 Dec 2023 17:26:32 +0000 Message-Id: <20231215172632.3102502-9-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231215172632.3102502-1-euan.bourke@intel.com> References: <20231215172632.3102502-1-euan.bourke@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Update to the l3fwd-power example application to call the arg parser library for its 'combined core string parser' instead of implementing its own corelist parser. The default_type passed into the function call is a corelist. Signed-off-by: Euan Bourke Acked-by: David Hunt Acked-by: Sivaprasad Tummala --- examples/l3fwd-power/perf_core.c | 52 ++++++-------------------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/examples/l3fwd-power/perf_core.c b/examples/l3fwd-power/perf_core.c index 41ef6d0c9a..e8ed414d40 100644 --- a/examples/l3fwd-power/perf_core.c +++ b/examples/l3fwd-power/perf_core.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "perf_core.h" #include "main.h" @@ -177,56 +178,21 @@ parse_perf_config(const char *q_arg) int parse_perf_core_list(const char *corelist) { - int i, idx = 0; - unsigned int count = 0; - char *end = NULL; - int min, max; + int count; + uint16_t cores[RTE_MAX_LCORE]; if (corelist == NULL) { printf("invalid core list\n"); return -1; } + count = rte_arg_parse_core_string(corelist, cores, RTE_DIM(cores), + RTE_ARG_PARSE_TYPE_CORELIST); - /* Remove all blank characters ahead and after */ - while (isblank(*corelist)) - corelist++; - i = strlen(corelist); - while ((i > 0) && isblank(corelist[i - 1])) - i--; + for (int i = 0; i < count; i++) + hp_lcores[i] = cores[i]; - /* Get list of cores */ - min = RTE_MAX_LCORE; - do { - while (isblank(*corelist)) - corelist++; - if (*corelist == '\0') - return -1; - errno = 0; - idx = strtoul(corelist, &end, 10); - if (errno || end == NULL) - return -1; - while (isblank(*end)) - end++; - if (*end == '-') { - min = idx; - } else if ((*end == ',') || (*end == '\0')) { - max = idx; - if (min == RTE_MAX_LCORE) - min = idx; - for (idx = min; idx <= max; idx++) { - hp_lcores[count] = idx; - count++; - } - min = RTE_MAX_LCORE; - } else { - printf("invalid core list\n"); - return -1; - } - corelist = end + 1; - } while (*end != '\0'); - - if (count == 0) { + if (count == 0 || count == -1) { printf("invalid core list\n"); return -1; } @@ -234,7 +200,7 @@ parse_perf_core_list(const char *corelist) nb_hp_lcores = count; printf("Configured %d high performance cores\n", nb_hp_lcores); - for (i = 0; i < nb_hp_lcores; i++) + for (int i = 0; i < nb_hp_lcores; i++) printf("\tHigh performance core %d %d\n", i, hp_lcores[i]);