From patchwork Thu Dec 7 16:18:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134929 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 0A44B4369D; Thu, 7 Dec 2023 17:18:47 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2610442F29; Thu, 7 Dec 2023 17:18:39 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 958B042ECC for ; Thu, 7 Dec 2023 17:18:37 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965917; x=1733501917; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WvUR/uHVSDOlQYyveiPgygJebg+yZCJpej0LIdC0uAU=; b=jt1W4CDSk/HB0mhhZ7PtP5595AN9++T/LXGSmK5uGVfHfFcJYq57x/X/ iGyxwQa4JzGA5fVIk3Pl8IjN4ZkKaOdZKHzyXvr5vp482ZmVNnx8kJgHz +xqSkilweurS4OKDN0Oq+7Gwhoq4XI3N+IG0DDL057aZo8s7M47DMZQTd djWIHioag3e0tfpSvwkvwheyrvVRDjVMBZqXLbbuNcdc1afEZ87hbB/Wz QKv2i/pIsyrkjCylpXv7Nz+SWEZUSqUDX6523kP0HiHuTj0A9eKI8uu41 T5CLX18DtosY92YENtus11N31ZPMlP9yewwWEIxXD3IrwvytVdj11Tc2o g==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048605" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048605" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:36 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153958" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153958" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:35 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Thomas Monjalon , Bruce Richardson Subject: [PATCH v3 1/8] arg_parser: new library for command line parsing Date: Thu, 7 Dec 2023 16:18:11 +0000 Message-Id: <20231207161818.2590661-2-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 | 3 +- 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, 201 insertions(+), 1 deletion(-) 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..f711010140 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -221,7 +221,8 @@ The public API headers are grouped by topics: [config file](@ref rte_cfgfile.h), [key/value args](@ref rte_kvargs.h), [string](@ref rte_string_fns.h), - [thread](@ref rte_thread.h) + [thread](@ref rte_thread.h), + [argument parsing](@ref rte_arg_parser.h) - **debug**: [jobstats](@ref rte_jobstats.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..240f63d8e1 --- /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 "errno.h" +#include "stdlib.h" +#include "ctype.h" +#include "string.h" +#include "stdbool.h" + +#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 -1; + + errno = 0; + idx = strtol(corelist, &end, 10); + if (errno || end == NULL || idx > UINT16_MAX) + return -1; + while (isblank(*end)) + end++; + if (*end == '-') + min = idx; + + else if (*end == ',' || *end == '\0') { + if (min == -1) + min = max = idx; + else if (min > idx) { + max = min; + min = idx; + } else + max = idx; + + for (; min <= max; min++) + set_core_bit(&mask, min); + + min = -1; + } else + return -1; + corelist = end + 1; + } while (*end != '\0'); + + uint32_t total_count = corebits_to_array(&mask, cores, cores_len); + + return total_count; +} 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..80579f8cf3 --- /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". + * -1 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 Thu Dec 7 16:18:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134930 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 9BB204369D; Thu, 7 Dec 2023 17:18:54 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5081542F33; Thu, 7 Dec 2023 17:18:40 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 18D3042F1F for ; Thu, 7 Dec 2023 17:18:38 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965919; x=1733501919; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dxvbvF9jp60JhP96ZkOUK0YXNoVxDRFPiXegB9NvhhQ=; b=aXmfoPkeGBrTc2jdjlGD1+aTDoxPII5zgVhZzsXlvOvL2iwRKbcH5Ew+ iQj13CafC14hKBnV4gk6QMmjdN2cfRNXg1lkqPXdDmKmhSZArV1Go/8N/ 0xKhoNILiP0joG5c0waJisp11tWBUida7Qi8ubdkMTWslKaSJlRO7sJVs GsUsoaAIl94Xuzr6jzwSf1VbNdvI7wAPE28rRDtAbsYhUJiFiMFBzvxHe kCZ0OH+mTgHAi23UA+iyYHXXif/I2C4QCLc2AaVKebOtyaFbyyqBQkkYn RE/MJoNnu/zw3l9IbMM4ewuEdp/n/IZZVedxMxqnQucpVSbBksoxkxQW2 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048611" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048611" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:38 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153964" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153964" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:37 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Bruce Richardson Subject: [PATCH v3 2/8] arg_parser: add new coremask parsing API Date: Thu, 7 Dec 2023 16:18:12 +0000 Message-Id: <20231207161818.2590661-3-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 | 53 +++++++++++++++++++++++++++++++++ lib/arg_parser/rte_arg_parser.h | 34 +++++++++++++++++++++ lib/arg_parser/version.map | 1 + 3 files changed, 88 insertions(+) diff --git a/lib/arg_parser/arg_parser.c b/lib/arg_parser/arg_parser.c index 240f63d8e1..cebab9e2f8 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,44 @@ rte_arg_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len return total_count; } + +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 -1; + + uint32_t idx = 0; + + for (i = i - 1; i >= 0; i--) { + int val; + char c = coremask[i]; + + if (isxdigit(c) == 0) + return -1; + + val = xdigit2val(c); + + for (uint8_t j = 0; j < BITS_PER_HEX; j++, idx++) { + if ((1 << j) & val) + set_core_bit(&mask, idx); + } + } + + uint32_t total_count = corebits_to_array(&mask, cores, cores_len); + + return total_count; +} diff --git a/lib/arg_parser/rte_arg_parser.h b/lib/arg_parser/rte_arg_parser.h index 80579f8cf3..359d40e305 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". + * -1 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 Thu Dec 7 16:18:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134931 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 CEE134369D; Thu, 7 Dec 2023 17:19:01 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 73A3542F37; Thu, 7 Dec 2023 17:18:42 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 7F2EE42F37 for ; Thu, 7 Dec 2023 17:18:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965920; x=1733501920; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JeGTeJZFctZd+znjoV2swqZS09T6IyEHBTmac4LtOtQ=; b=n64RwD0pSWPF1P9e2kUw1qLG43QhYnG8qWIGlKGXt0/ZDQfBMK7uyVpT bgiSwcHZrh/rJlfgBo941Zd+IFqtpzJNwPHAd+lpKD0VEftBGkFHdpZKg wohkcTQAab4gKTYTWvm/xdLrsoNqBpWVuFuvguUZUETtvjKESSkFy8qjd 2Aiihz9vofenQJEncjReUWFn9L1uUkJnpxDWZAfw+2D1glyWfXM/Z6P+s Nv876tAA95GqbwYh3WxWQSq5jN2307gJs2lbqAgDlLm1oMnYJmVZZNRdN QfKS9LrduMe/GLhspT4s98etf/MK05Ml1OLFMvRA5oA16Of7sgyu5tqnA g==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048612" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048612" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:40 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153971" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153971" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:38 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke Subject: [PATCH v3 3/8] eal: add support for new arg parsing library Date: Thu, 7 Dec 2023 16:18:13 +0000 Message-Id: <20231207161818.2590661-4-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 Thu Dec 7 16:18:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134932 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 B5BCF4369D; Thu, 7 Dec 2023 17:19:09 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B499642F45; Thu, 7 Dec 2023 17:18:43 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 71B0242F37 for ; Thu, 7 Dec 2023 17:18:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965921; x=1733501921; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LVghYsSuh7gYwi/527BOt+d4xJ7IPnG1RmWH9spLqnc=; b=SnpQVg4RYfj2ZArFWA+/UXOpZuARu7RdmIAfwdQCOMlTaji5Kq86L9WN OncAGmA4i0IHkAeFYSC1yjiW4xYUjTqdnahNRpzl3WIoqY4lE7Dg+l9ee MUd5uvDSTvH0DbzXsFi81vhaBoGVUM375wUZ8kTiJOHQnENNkgHd+DiNf VHK7E2qekrmIbscgJYeNhfWXFBTpvFr9/FkuWQRqlBN+E4+6FkGRhNzUT p1WhFkvZnUT2ZhLUuvTld8H+wG1c4RxhN8ZxXSB21tqmbtH6KLgfzEGMN z98q/ClPGBdjr6bEe/wEQmPREezY9hpx+2hz3yVpF5KFUCjG1pdsyBGpq A==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048617" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048617" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:40 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153974" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153974" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:39 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke Subject: [PATCH v3 4/8] eal: update to service core related parsers Date: Thu, 7 Dec 2023 16:18:14 +0000 Message-Id: <20231207161818.2590661-5-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 Thu Dec 7 16:18:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134933 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 CA7394369D; Thu, 7 Dec 2023 17:19:18 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 460B142F67; Thu, 7 Dec 2023 17:18:46 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 3D38B42F3F for ; Thu, 7 Dec 2023 17:18:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965923; x=1733501923; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zFQ2rHxu1X0r2TEHDZIX1mt9oK01LWnLJ4/zA2wqdLA=; b=kLSQ/QCK6qfUky2XVzakhgib+Ly4ghjN6lHNpGKaWje4OBNmi6kZ8FGb V8uaXPROdAHNATTPD0rKhDO+fYhd7OD/717/y3U/HQwG8IxRhq1lAntf3 /E4AX2Hk5gDOxY1AixQGbSd737GBIdsV+IyIFZm3fJdWb9AQJ7FzRuuWd x+eoHtZUiyiIdvFkiwZp99TXFEqf3XTT8rINwdk0HX7/cJkS861CRAvf7 mWQ3HZkDeRvG0VmoEahJpB/G44bvIsdPKsn/KbDqmC8nMgZ0Vb4AKC22h vTxn9xKWZng0yxfLwZ03OQCh+OuF4l2d8nUwAun1P8WdmQXj8Z83dkbrA w==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048622" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048622" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:42 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153981" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153981" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:41 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Abdullah Sevincer Subject: [PATCH v3 5/8] event/dlb2: add new arg parsing library API support Date: Thu, 7 Dec 2023 16:18:15 +0000 Message-Id: <20231207161818.2590661-6-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 Thu Dec 7 16:18:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134934 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 A0F754369D; Thu, 7 Dec 2023 17:19:25 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4F0C442F6F; Thu, 7 Dec 2023 17:18:47 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 521F442F4F for ; Thu, 7 Dec 2023 17:18:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965924; x=1733501924; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=X+91EEYKdZSCJ5uhR76zNfCqIVvnVsqGw+7rnYFiXhY=; b=D1bCawCiyFaXf8EOqmR1XCQ/nQwcd82bMH/Ffd4LWxo1G9o4kOp1kJ/F 9vUjrjfIE9zOz8nTXEFcFIH/s4mJLEg0B2huwhrkXTlI4yuHsF+YJ9H64 Yx6Td5vywvEf7ZONgn/QIWEx836U74PDw56kjHAg/B+tE474CYUozn6eC rWZ+XjQmjU019UETC3l7khL6fx0+Ezyr/xTw2vOgeRasWZI8MPRM9+qOa sF0L0WzEuQg1artjkJBuKxa8b7BtWxrDvM4BAHTk7wxR/9lzkWbMiI5sS E2pkreybf3KaQKoqDD0KV73enVAGFh7x+R900ZLAI6inxYH8J+3rPN6LD A==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048628" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048628" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:44 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153984" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153984" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:42 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Bruce Richardson Subject: [PATCH v3 6/8] arg_parser: added common core string and heuristic parsers Date: Thu, 7 Dec 2023 16:18:16 +0000 Message-Id: <20231207161818.2590661-7-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 | 68 +++++++++++++++++++++++++++++++++ lib/arg_parser/rte_arg_parser.h | 60 +++++++++++++++++++++++++++++ lib/arg_parser/version.map | 2 + 3 files changed, 130 insertions(+) diff --git a/lib/arg_parser/arg_parser.c b/lib/arg_parser/arg_parser.c index cebab9e2f8..95cbc50c13 100644 --- a/lib/arg_parser/arg_parser.c +++ b/lib/arg_parser/arg_parser.c @@ -7,10 +7,15 @@ #include "ctype.h" #include "string.h" #include "stdbool.h" +#include "stdio.h" #include #include +#define RTE_ARG_PARSE_TYPE_COREMASK 0 +#define RTE_ARG_PARSE_TYPE_CORELIST 1 +#define RTE_ARG_PARSE_TYPE_UNKNOWN 2 + #define BITS_PER_HEX 4 #define MAX_COREMASK_SIZE ((UINT16_MAX + 1) / BITS_PER_HEX) @@ -22,6 +27,7 @@ struct core_bits { uint32_t total_bits_set; }; + static inline bool get_core_bit(struct core_bits *mask, uint16_t idx) { @@ -159,3 +165,65 @@ rte_arg_parse_coremask(const char *coremask, uint16_t *cores, uint32_t cores_len return total_count; } + +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 -1; + } + + 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 -1; + } + 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 -1; +} + +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 -1; + } + 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 -1; + } +} diff --git a/lib/arg_parser/rte_arg_parser.h b/lib/arg_parser/rte_arg_parser.h index 359d40e305..125ca9524c 100644 --- a/lib/arg_parser/rte_arg_parser.h +++ b/lib/arg_parser/rte_arg_parser.h @@ -92,6 +92,66 @@ __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 UNKNOWN if the string is ambiguous. + * + * @param core_string + * A string describing the intended cores to be parsed + * @return + * int representing the core type + * -1: error. + * 0: coremask. + * 1: corelist. + * 2: unknown (ambiguous). + */ +__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). + * 0: mask. + * 1: list. + * @return + * n: the number of unique cores present in "core_string". + * -1 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..383b6bd0e9 100644 --- a/lib/arg_parser/version.map +++ b/lib/arg_parser/version.map @@ -8,4 +8,6 @@ EXPERIMENTAL { # added in 24.03 rte_arg_parse_corelist; rte_arg_parse_coremask; + rte_arg_parse_arg_type; + rte_arg_parse_core_string; }; From patchwork Thu Dec 7 16:18:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134935 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 DDF2E4369D; Thu, 7 Dec 2023 17:19:31 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4962042F73; Thu, 7 Dec 2023 17:18:48 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id CBF2342F4F for ; Thu, 7 Dec 2023 17:18:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965926; x=1733501926; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ntTCL7ZgxcrHmd3eNMTw872VD78V+HYFJAaokwfMgTE=; b=EWBSAqD86LwAxYRJsHXkVZbULV7z+h5qSBhk3A0BXellwFdl5WeZhJ1w FvMjZKIm1I0Xce6rjRxzptF15b+V8DTePypkSfTLsuqM0EHezzvX5GYFn Bngqw5GXrwa9/GiV6GrFe9bWT8y+DxFacwrq8YwEjeYynoOpNvzTDMm8w BE73UxfcfFsLo8oaKMajTfQhuSwXZHSyhNJO4S0IjnPb8ExpzRmhbKosy eNw+4JCuT5rRRaNuxKKcFfHowCtP780d7B0ZDLfwEpTOkmw7W9WIR1UDV UeEVUp8SBILtAeMNObszTR1UzpefU1jP4aYBsd36w7BSev0z9OArC2Dde A==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048630" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048630" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:45 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153987" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153987" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:44 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Harry van Haaren Subject: [PATCH v3 7/8] examples/eventdev_pipeline: update to call arg parser API Date: Thu, 7 Dec 2023 16:18:17 +0000 Message-Id: <20231207161818.2590661-8-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 | 65 +++----------------- examples/eventdev_pipeline/pipeline_common.h | 1 + 2 files changed, 10 insertions(+), 56 deletions(-) diff --git a/examples/eventdev_pipeline/main.c b/examples/eventdev_pipeline/main.c index 0c995d1a70..c59d01e7a5 100644 --- a/examples/eventdev_pipeline/main.c +++ b/examples/eventdev_pipeline/main.c @@ -56,69 +56,22 @@ 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), 0); - 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 Thu Dec 7 16:18:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Euan Bourke X-Patchwork-Id: 134936 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 4A3E54369D; Thu, 7 Dec 2023 17:19:38 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5F8A342F0D; Thu, 7 Dec 2023 17:18:49 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 9293242F73 for ; Thu, 7 Dec 2023 17:18:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1701965927; x=1733501927; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PpOYE0dStoI251F0PbA1DOxL8iUA7tRPyFD/F9z/4CE=; b=XA8VjcgaDJw9igP7IoTolKNahgpnD0btmwPMGPDVcyqx7I2/9TZK/qqV CsxoJiyJ9Uh4V9MJAfTveAklddBlFeCDdaqOGKdFeHS0N+PQhp6m8DCfu C/eHNWtvjTT06FeaX7ehj2cpcl/KFPGyLzYGi5uBa1k+aysGMEU9a/iyh zo+JsOV78Y1+G1jJ0WpoH3v2NJdAgMO4Q4bUOoOwZAVI84DlYTC5plM1t yptNOZKSNrNaeKXi1XjpK5Tk3qYeAu4Efn85wBEXhJl5Zel0i7vpJgsCv N/hmqXTeWoPckcVx5XUNtFL4tCS5t6XNYKBsAzpQVogoQvPPhu5deM7G+ g==; X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="397048631" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="397048631" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2023 08:18:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10917"; a="765153990" X-IronPort-AV: E=Sophos;i="6.04,256,1695711600"; d="scan'208";a="765153990" Received: from unknown (HELO silpixa00400630.ir.intel.com) ([10.237.213.151]) by orsmga007.jf.intel.com with ESMTP; 07 Dec 2023 08:18:45 -0800 From: Euan Bourke To: dev@dpdk.org Cc: Euan Bourke , Anatoly Burakov , David Hunt , Sivaprasad Tummala Subject: [PATCH v3 8/8] examples/l3fwd-power: update to call arg parser API Date: Thu, 7 Dec 2023 16:18:18 +0000 Message-Id: <20231207161818.2590661-9-euan.bourke@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231207161818.2590661-1-euan.bourke@intel.com> References: <20231207161818.2590661-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 --- examples/l3fwd-power/perf_core.c | 51 +++++--------------------------- 1 file changed, 8 insertions(+), 43 deletions(-) diff --git a/examples/l3fwd-power/perf_core.c b/examples/l3fwd-power/perf_core.c index 41ef6d0c9a..f8511e30b3 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,20 @@ 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), 1); - /* 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 +199,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 (uint16_t i = 0; i < nb_hp_lcores; i++) printf("\tHigh performance core %d %d\n", i, hp_lcores[i]);