From: Bruce Richardson <bruce.richardson@intel.com>
To: Jacek Piasecki <jacekx.piasecki@intel.com>
Cc: dev@dpdk.org, deepak.k.jain@intel.com,
Kuba Kozak <kubax.kozak@intel.com>
Subject: Re: [dpdk-dev] [PATCH v3 1/3] eal: add functions parsing EAL arguments
Date: Fri, 30 Jun 2017 17:04:45 +0100 [thread overview]
Message-ID: <20170630160445.GA17400@bricha3-MOBL3.ger.corp.intel.com> (raw)
In-Reply-To: <1498560760-104196-2-git-send-email-jacekx.piasecki@intel.com>
On Tue, Jun 27, 2017 at 12:52:38PM +0200, Jacek Piasecki wrote:
> From: Kuba Kozak <kubax.kozak@intel.com>
>
> added function rte_eal_configure which configure
> Environment Abstraction Layer (EAL) using
> configuration structure.
>
> Signed-off-by: Kuba Kozak <kubax.kozak@intel.com>
> Suggested-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
Thanks for looking to implement this idea, to see how it would work.
Comments on the implementation inline below.
Regards,
/Bruce
> This patch depends on cfgfile patchset with:
> "cfgfile: remove EAL dependency"
> "cfgfile: add new functions to API"
> "cfgfile: rework of load function"
> "test/cfgfile: add new unit test"
> ---
> config/common_base | 1 +
> lib/Makefile | 6 +-
> lib/librte_eal/bsdapp/eal/Makefile | 4 +
> lib/librte_eal/bsdapp/eal/eal.c | 249 ++++++++++++++---
> lib/librte_eal/bsdapp/eal/rte_eal_version.map | 4 +
> lib/librte_eal/common/eal_common_cpuflags.c | 14 +-
> lib/librte_eal/common/eal_common_lcore.c | 11 +-
> lib/librte_eal/common/eal_common_options.c | 5 +
> lib/librte_eal/common/include/rte_eal.h | 21 ++
> lib/librte_eal/linuxapp/eal/Makefile | 3 +
> lib/librte_eal/linuxapp/eal/eal.c | 353 ++++++++++++++++++------
> lib/librte_eal/linuxapp/eal/rte_eal_version.map | 4 +
> mk/rte.app.mk | 2 +-
> 13 files changed, 543 insertions(+), 134 deletions(-)
>
> diff --git a/config/common_base b/config/common_base
> index f6aafd1..c1d0e69 100644
> --- a/config/common_base
> +++ b/config/common_base
> @@ -569,6 +569,7 @@ CONFIG_RTE_LIBRTE_TIMER_DEBUG=n
> # Compile librte_cfgfile
> #
> CONFIG_RTE_LIBRTE_CFGFILE=y
> +CONFIG_RTE_LIBRTE_CFGFILE_DEBUG=n
This change does not belong in this patchset. In fact, I don't think it
belongs anywhere as there are no debug statements in the cfgfile
library.
>
> #
> # Compile librte_cmdline
> diff --git a/lib/Makefile b/lib/Makefile
> index 07e1fd0..fc5df3a 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -32,7 +32,11 @@
> include $(RTE_SDK)/mk/rte.vars.mk
>
> DIRS-y += librte_compat
> +DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile
> DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal
> +ifeq ($(CONFIG_RTE_LIBRTE_CFGFILE),y)
> +DEPDIRS-librte_eal := librte_cfgfile
> +endif
> DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
> DEPDIRS-librte_ring := librte_eal
> DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool
> @@ -41,8 +45,6 @@ DIRS-$(CONFIG_RTE_LIBRTE_MBUF) += librte_mbuf
> DEPDIRS-librte_mbuf := librte_eal librte_mempool
> DIRS-$(CONFIG_RTE_LIBRTE_TIMER) += librte_timer
> DEPDIRS-librte_timer := librte_eal
> -DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile
> -DEPDIRS-librte_cfgfile := librte_eal
> DIRS-$(CONFIG_RTE_LIBRTE_CMDLINE) += librte_cmdline
> DEPDIRS-librte_cmdline := librte_eal
> DIRS-$(CONFIG_RTE_LIBRTE_ETHER) += librte_ether
I think the parts of this change - the deleteion of the line saying
cfgfile depends on EAL, and the moving of the declaration of the cfgfile
library up in the file, should go in patch 1 of the earlier cfgfile set.
> diff --git a/lib/librte_eal/bsdapp/eal/Makefile b/lib/librte_eal/bsdapp/eal/Makefile
> index a0f9950..d70eefb 100644
> --- a/lib/librte_eal/bsdapp/eal/Makefile
> +++ b/lib/librte_eal/bsdapp/eal/Makefile
> @@ -50,6 +50,10 @@ EXPORT_MAP := rte_eal_version.map
>
> LIBABIVER := 4
>
> +ifeq ($(CONFIG_RTE_LIBRTE_CFGFILE),y)
> +LDLIBS += -lrte_cfgfile
> +endif
> +
This should not be needed here. Other DPDK libs which depend on yet
other libs don't go modifying the LDLIBS like this.
> # specific to bsdapp exec-env
> SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) := eal.c
> SRCS-$(CONFIG_RTE_EXEC_ENV_BSDAPP) += eal_memory.c
> diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
> index 05f0c1f..7baf848 100644
> --- a/lib/librte_eal/bsdapp/eal/eal.c
> +++ b/lib/librte_eal/bsdapp/eal/eal.c
> @@ -73,6 +73,7 @@
> #include <rte_version.h>
> #include <rte_atomic.h>
> #include <malloc_heap.h>
> +#include <rte_cfgfile.h>
>
> #include "eal_private.h"
> #include "eal_thread.h"
> @@ -309,6 +310,18 @@ eal_get_hugepage_mem_size(void)
>
> /* Parse the arguments for --log-level only */
> static void
> +eal_log_level_cfg(struct rte_cfgfile *cfg)
> +{
> + const char *entry;
> +
> + entry = rte_cfgfile_get_entry(cfg, "DPDK", OPT_LOG_LEVEL);
> + if (entry)
> + eal_parse_common_option(OPT_LOG_LEVEL_NUM, entry,
> + &internal_config);
> +}
> +
> +/* Parse the arguments for --log-level only */
> +static void
> eal_log_level_parse(int argc, char **argv)
> {
> int opt;
> @@ -347,6 +360,58 @@ eal_log_level_parse(int argc, char **argv)
> optarg = old_optarg;
> }
>
> +/* Parse single argument */
> +static int
> +eal_parse_option(int opt, char *optarg, int option_index, char *prgname)
> +{
> + int ret;
> +
> + /* getopt is not happy, stop right now */
> + if (opt == '?') {
> + eal_usage(prgname);
> + ret = -1;
> + goto out;
> + }
> +
> + ret = eal_parse_common_option(opt, optarg, &internal_config);
> + /* common parser is not happy */
> + if (ret < 0) {
> + eal_usage(prgname);
> + ret = -1;
> + goto out;
> + }
> + /* common parser handled this option */
> + if (ret == 0)
> + return 0;
> +
> + switch (opt) {
> + case 'h':
> + eal_usage(prgname);
> + exit(EXIT_SUCCESS);
> + break;
> +
> + default:
> + if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
> + RTE_LOG(ERR, EAL, "Option %c is not supported "
> + "on FreeBSD\n", opt);
> + } else if (opt >= OPT_LONG_MIN_NUM &&
> + opt < OPT_LONG_MAX_NUM) {
> + RTE_LOG(ERR, EAL, "Option %s is not supported "
> + "on FreeBSD\n",
> + eal_long_options[option_index].name);
> + } else {
> + RTE_LOG(ERR, EAL, "Option %d is not supported "
> + "on FreeBSD\n", opt);
> + }
> + eal_usage(prgname);
> + ret = -1;
> + goto out;
> + }
> + return 0;
> +out:
> + return ret;
> +}
> +
> /* Parse the argument given in the command line of the application */
> static int
> eal_parse_args(int argc, char **argv)
> @@ -367,45 +432,9 @@ eal_parse_args(int argc, char **argv)
> while ((opt = getopt_long(argc, argvopt, eal_short_options,
> eal_long_options, &option_index)) != EOF) {
>
> - /* getopt is not happy, stop right now */
> - if (opt == '?') {
> - eal_usage(prgname);
> - ret = -1;
> - goto out;
> - }
> -
> - ret = eal_parse_common_option(opt, optarg, &internal_config);
> - /* common parser is not happy */
> - if (ret < 0) {
> - eal_usage(prgname);
> - ret = -1;
> - goto out;
> - }
> - /* common parser handled this option */
> - if (ret == 0)
> - continue;
> -
> - switch (opt) {
> - case 'h':
> - eal_usage(prgname);
> - exit(EXIT_SUCCESS);
> - default:
> - if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
> - RTE_LOG(ERR, EAL, "Option %c is not supported "
> - "on FreeBSD\n", opt);
> - } else if (opt >= OPT_LONG_MIN_NUM &&
> - opt < OPT_LONG_MAX_NUM) {
> - RTE_LOG(ERR, EAL, "Option %s is not supported "
> - "on FreeBSD\n",
> - eal_long_options[option_index].name);
> - } else {
> - RTE_LOG(ERR, EAL, "Option %d is not supported "
> - "on FreeBSD\n", opt);
> - }
> - eal_usage(prgname);
> - ret = -1;
> + ret = eal_parse_option(opt, optarg, option_index, prgname);
> + if (ret < 0)
> goto out;
> - }
> }
>
> if (eal_adjust_config(&internal_config) != 0) {
> @@ -677,3 +706,147 @@ rte_eal_process_type(void)
> {
> return rte_config.process_type;
> }
> +
> +#ifdef RTE_LIBRTE_CFGFILE
> +#define vdev_buff_size 200
> +#define sectionname_size 20
> +static int
> +parse_vdev_devices(struct rte_cfgfile *cfg)
> +{
> + char sectionname[sectionname_size];
> + char buffer1[vdev_buff_size];
> + int vdev_nb = 0;
> + int n_entries;
> + int i;
> +
> + /* ----------- parsing VDEVS */
> + snprintf(sectionname, sectionname_size, "DPDK.vdev%d", vdev_nb);
move this inside the loop to be the first thing done, rather than having
it outside and then the last thing on each iteration.
> +
> + for (vdev_nb = 1; rte_cfgfile_has_section(cfg, sectionname);
> + vdev_nb++) {
> + n_entries = rte_cfgfile_section_num_entries(cfg, sectionname);
> +
> + struct rte_cfgfile_entry entries[n_entries];
> +
> + if (n_entries != rte_cfgfile_section_entries(cfg, sectionname,
> + entries, n_entries)) {
> + rte_eal_init_alert("Unexpected fault.");
> + rte_errno = EFAULT;
> + return -1;
> + }
> +
> + buffer1[0] = 0;
> + for (i = 0; i < n_entries; i++) {
> + if (strlen(entries[i].value)) {
> +
> + if ((strlen(buffer1) +
> + strlen(entries[i].name) +
> + strlen(entries[i].value) + 3)
> + >= vdev_buff_size)
> + goto buff_size_err;
> + strcat(buffer1, entries[i].name);
> + strcat(buffer1, "=");
> + strcat(buffer1, entries[i].value);
> + } else {
> + if ((strlen(buffer1) +
> + strlen(entries[i].name) + 2)
> + >= vdev_buff_size)
> + goto buff_size_err;
> + strcat(buffer1, entries[i].name);
> + }
> +
Doing these strlen calls and calculations that way is horribly
inefficient IMHO, even if this is not in a perf-critical path. Instead,
I would look to start with a buf_len variable which tracks the available
buffer size, and a buf_ptr variable which points to the first available
character. Then do the following each time you want to add something:
ret = snprintf(buf_ptr, buf_len, "%s%s%s", entries[i].name,
entries[i].value[0] != '\0' ? "=" : "",
entries[i].value);
if (ret >= buf_len)
goto buff_size_err;
buf_ptr += ret;
buf_len -= ret;
Shorter and simpler, as well as being more efficient as it does not need
any string length computation calls, using snprintf safely instead.
> + if (i < (n_entries - 1))
> + strcat(buffer1, ",");
You can add this bit into the above snprintf too, in a similar way to
how I optionally added the "=".
> + }
> +
> + /* parsing vdev */
> + if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL,
> + buffer1) < 0) {
> + return -1;
> + }
> + snprintf(sectionname, sectionname_size, "DPDK.vdev%d", vdev_nb);
> + }
> + /* ----------- parsing VDEVS */
> + return 0;
> +
> +buff_size_err:
> + printf("parse_vdev_devices(): buffer size is to small\n");
> + return -1;
If the code is reworked so that there is only one place where this error
occurs, remove the label and goto, and just put the error handling
inline in the code.
> +}
> +
> +static void
> +eal_getopt(const char *str, int *opt, int *option_index)
> +{
> + int i;
> +
> + *opt = '?';
> + *option_index = 0;
> +
> + if (strlen(str) == 1) {
> + *opt = *str;
> + return;
> + }
> +
> + for (i = 0; eal_long_options[i].name != NULL; i++) {
> + if (strcmp(str, eal_long_options[i].name) == 0) {
> + *opt = eal_long_options[i].val;
> + *option_index = i;
> + break;
> + }
> + }
> +}
> +
> +int
> +rte_eal_configure(struct rte_cfgfile *cfg, char *prgname)
> +{
> + int n_entries;
> + int i;
> + int opt;
> + int option_index;
> +
> + if (cfg == NULL) {
> + rte_errno = -EINVAL;
> + return -1;
> + }
> +
> + n_entries = rte_cfgfile_section_num_entries(cfg, "DPDK");
> +
> + if (n_entries < 1) {
> + printf("No DPDK section entries in cfgfile object\n");
> + return 0;
> + }
> +
> + struct rte_cfgfile_entry entries[n_entries];
> +
> + if (n_entries !=
> + rte_cfgfile_section_entries(cfg, "DPDK", entries,
> + n_entries)) {
> + rte_eal_init_alert("Unexpected fault.");
> + rte_errno = EFAULT;
> + return -1;
> + }
> +
> + eal_reset_internal_config(&internal_config);
> +
> + /* set log level as early as possible */
> + eal_log_level_cfg(cfg);
> +
> + for (i = 0; i < n_entries; i++) {
> + eal_getopt(entries[i].name, &opt, &option_index);
> +
> + if (eal_parse_option(opt, entries[i].value,
> + option_index, prgname) != 0) {
> + rte_eal_init_alert("Invalid config file arguments.");
> + rte_errno = EINVAL;
> + return -1;
> + }
> + }
> +
> + if (parse_vdev_devices(cfg) < 0) {
> + rte_eal_init_alert("Couldn't parse vdevs");
> + rte_errno = ENOMEM;
> + return -1;
> + }
> + return 0;
> +}
> +#endif
> diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> index 2e48a73..a939b03 100644
> --- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
> @@ -193,3 +193,7 @@ DPDK_17.05 {
> vfio_get_group_no;
>
> } DPDK_17.02;
> +
> +DPDK_17.08 {
> + rte_eal_configure;
> +} DPDK_17.05;
> diff --git a/lib/librte_eal/common/eal_common_cpuflags.c b/lib/librte_eal/common/eal_common_cpuflags.c
> index 9a2d080..6a365f3 100644
> --- a/lib/librte_eal/common/eal_common_cpuflags.c
> +++ b/lib/librte_eal/common/eal_common_cpuflags.c
> @@ -50,12 +50,18 @@ rte_cpu_check_supported(void)
> int
> rte_cpu_is_supported(void)
> {
> + static int run_once;
> + static int ret;
> /* This is generated at compile-time by the build system */
> static const enum rte_cpu_flag_t compile_time_flags[] = {
> RTE_COMPILE_TIME_CPUFLAGS
> };
> unsigned count = RTE_DIM(compile_time_flags), i;
> - int ret;
> +
> + /* No need to calculate this function again if we know the result */
> + if (run_once)
> + return ret;
> + run_once = 1;
>
> for (i = 0; i < count; i++) {
> ret = rte_cpu_get_flag_enabled(compile_time_flags[i]);
> @@ -64,16 +70,16 @@ rte_cpu_is_supported(void)
> fprintf(stderr,
> "ERROR: CPU feature flag lookup failed with error %d\n",
> ret);
> - return 0;
> + return ret = 0;
> }
> if (!ret) {
> fprintf(stderr,
> "ERROR: This system does not support \"%s\".\n"
> "Please check that RTE_MACHINE is set correctly.\n",
> rte_cpu_get_flag_name(compile_time_flags[i]));
> - return 0;
> + return ret = 0;
> }
> }
>
> - return 1;
> + return ret = 1;
> }
This is not a bad change in and of itself. However, I'm not sure it
belongs in this patchset. With the new configure call, we should still
only be calling these initialization functions once - in eal_init().
> diff --git a/lib/librte_eal/common/eal_common_lcore.c b/lib/librte_eal/common/eal_common_lcore.c
> index 84fa0cb..ce3ef34 100644
> --- a/lib/librte_eal/common/eal_common_lcore.c
> +++ b/lib/librte_eal/common/eal_common_lcore.c
> @@ -53,11 +53,18 @@
> int
> rte_eal_cpu_init(void)
> {
> + static int run_once;
> + static int ret;
> /* pointer to global configuration */
> struct rte_config *config = rte_eal_get_configuration();
> unsigned lcore_id;
> unsigned count = 0;
>
> + /* No need to calculate this function again if we know the result */
> + if (run_once)
> + return ret;
> + run_once = 1;
> +
> /*
> * Parse the maximum set of logical cores, detect the subset of running
> * ones and enable them by default.
> @@ -91,7 +98,7 @@ rte_eal_cpu_init(void)
> "RTE_MAX_NUMA_NODES (%d)\n",
> lcore_config[lcore_id].socket_id,
> RTE_MAX_NUMA_NODES);
> - return -1;
> + return ret = -1;
> #endif
> }
> RTE_LOG(DEBUG, EAL, "Detected lcore %u as "
> @@ -107,5 +114,5 @@ rte_eal_cpu_init(void)
> RTE_MAX_LCORE);
> RTE_LOG(INFO, EAL, "Detected %u lcore(s)\n", config->lcore_count);
>
> - return 0;
> + return ret = 0;
> }
As above, should not be needed.
> diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
> index f470195..138a27f 100644
> --- a/lib/librte_eal/common/eal_common_options.c
> +++ b/lib/librte_eal/common/eal_common_options.c
> @@ -131,8 +131,13 @@ static int core_parsed;
> void
> eal_reset_internal_config(struct internal_config *internal_cfg)
> {
> + static int run_once;
> int i;
>
> + if (run_once)
> + return;
> + run_once = 1;
> +
> internal_cfg->memory = 0;
> internal_cfg->force_nrank = 0;
> internal_cfg->force_nchannel = 0;
I don't think for this function this is the way to do things, given that
the function does one job - resetting the internal config - and the new
flag just disables it. It's different from e.g. the cpu check which is
able to cache a return value.
Instead, this should be tracked at the higher eal level, and not call
the function at all if it is unneeded. This mean that eal_init should
check itself if configure has already called the function and then skip
calling it itself.
> diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
> index abf020b..e0705de 100644
> --- a/lib/librte_eal/common/include/rte_eal.h
> +++ b/lib/librte_eal/common/include/rte_eal.h
> @@ -46,6 +46,8 @@
> #include <rte_per_lcore.h>
> #include <rte_config.h>
>
> +struct rte_cfgfile; /* forward declaration of struct */
> +
> #ifdef __cplusplus
> extern "C" {
> #endif
> @@ -188,6 +190,25 @@ int rte_eal_iopl_init(void);
> */
> int rte_eal_init(int argc, char **argv);
>
> +#ifdef RTE_LIBRTE_CFGFILE
> +/**
> + * Initialize the Environment Abstraction Layer (EAL) using
> + * configuration structure
> + *
> + * @param cfg
> + * pointer to config file structure.
> + * If 0 - function free allocated for **cfg_argv memory
Don't understand this comment.
> + * @param prgname
> + * pointer to string with execution path
> + *
> + * @return
> + * - On success, return 0
> + * - On failure, returns -1.
> + */
> +int
> +rte_eal_configure(struct rte_cfgfile *cfg, char *prgname);
> +#endif
> +
> /**
> * Check if a primary process is currently alive
> *
> diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
> index 640afd0..656033e 100644
> --- a/lib/librte_eal/linuxapp/eal/Makefile
> +++ b/lib/librte_eal/linuxapp/eal/Makefile
> @@ -50,6 +50,9 @@ LDLIBS += -ldl
> LDLIBS += -lpthread
> LDLIBS += -lgcc_s
> LDLIBS += -lrt
> +ifeq ($(CONFIG_RTE_LIBRTE_CFGFILE),y)
> +LDLIBS += -lrte_cfgfile
> +endif
>
> # specific to linuxapp exec-env
> SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) := eal.c
> diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
> index 7c78f2d..f5973f4 100644
> --- a/lib/librte_eal/linuxapp/eal/eal.c
> +++ b/lib/librte_eal/linuxapp/eal/eal.c
> @@ -78,6 +78,9 @@
> #include <rte_version.h>
> #include <rte_atomic.h>
> #include <malloc_heap.h>
> +#ifdef RTE_LIBRTE_CFGFILE
> +#include <rte_cfgfile.h>
> +#endif
>
> #include "eal_private.h"
> #include "eal_thread.h"
> @@ -478,6 +481,20 @@ eal_parse_vfio_intr(const char *mode)
> return -1;
> }
>
> +#ifdef RTE_LIBRTE_CFGFILE
> +/* Parse the arguments for --log-level only */
> +static void
> +eal_log_level_cfg(struct rte_cfgfile *cfg)
> +{
> + const char *entry;
> +
> + entry = rte_cfgfile_get_entry(cfg, "DPDK", OPT_LOG_LEVEL);
> + if (entry)
> + eal_parse_common_option(OPT_LOG_LEVEL_NUM, entry,
> + &internal_config);
> +}
> +#endif
> +
This looks the same as the BSD version. Can it go in a common file?
> /* Parse the arguments for --log-level only */
> static void
> eal_log_level_parse(int argc, char **argv)
> @@ -515,119 +532,135 @@ eal_log_level_parse(int argc, char **argv)
> optarg = old_optarg;
> }
>
> -/* Parse the argument given in the command line of the application */
> +/* Parse single argument */
> static int
> -eal_parse_args(int argc, char **argv)
> +eal_parse_option(int opt, char *optarg, int option_index, char *prgname)
> {
> - int opt, ret;
> - char **argvopt;
> - int option_index;
> - char *prgname = argv[0];
> - const int old_optind = optind;
> - const int old_optopt = optopt;
> - char * const old_optarg = optarg;
> + int ret;
>
> - argvopt = argv;
> - optind = 1;
> + /* getopt is not happy, stop right now */
> + if (opt == '?') {
> + eal_usage(prgname);
> + ret = -1;
> + goto out;
> + }
>
> - while ((opt = getopt_long(argc, argvopt, eal_short_options,
> - eal_long_options, &option_index)) != EOF) {
> + ret = eal_parse_common_option(opt, optarg, &internal_config);
> + /* common parser is not happy */
> + if (ret < 0) {
> + eal_usage(prgname);
> + ret = -1;
> + goto out;
> + }
> + /* common parser handled this option */
> + if (ret == 0)
> + return 0;
>
> - /* getopt is not happy, stop right now */
> - if (opt == '?') {
> + switch (opt) {
> + case 'h':
> + eal_usage(prgname);
> + exit(EXIT_SUCCESS);
> + break;
> +
> + /* long options */
> + case OPT_XEN_DOM0_NUM:
> +#ifdef RTE_LIBRTE_XEN_DOM0
> + internal_config.xen_dom0_support = 1;
> + break;
> +#else
> + RTE_LOG(ERR, EAL, "Can't support DPDK app "
> + "running on Dom0, please configure"
> + " RTE_LIBRTE_XEN_DOM0=y\n");
> + ret = -1;
> + goto out;
> +#endif
> +
> + case OPT_HUGE_DIR_NUM:
> + internal_config.hugepage_dir = optarg;
> + break;
> +
> + case OPT_FILE_PREFIX_NUM:
> + internal_config.hugefile_prefix = optarg;
> + break;
> +
> + case OPT_SOCKET_MEM_NUM:
> + if (eal_parse_socket_mem(optarg) < 0) {
> + RTE_LOG(ERR, EAL, "invalid parameters for --"
> + OPT_SOCKET_MEM "\n");
> eal_usage(prgname);
> ret = -1;
> goto out;
> }
> + break;
>
> - ret = eal_parse_common_option(opt, optarg, &internal_config);
> - /* common parser is not happy */
> - if (ret < 0) {
> + case OPT_BASE_VIRTADDR_NUM:
> + if (eal_parse_base_virtaddr(optarg) < 0) {
> + RTE_LOG(ERR, EAL, "invalid parameter for --"
> + OPT_BASE_VIRTADDR "\n");
> eal_usage(prgname);
> ret = -1;
> goto out;
> }
> - /* common parser handled this option */
> - if (ret == 0)
> - continue;
> + break;
>
> - switch (opt) {
> - case 'h':
> + case OPT_VFIO_INTR_NUM:
> + if (eal_parse_vfio_intr(optarg) < 0) {
> + RTE_LOG(ERR, EAL, "invalid parameters for --"
> + OPT_VFIO_INTR "\n");
> eal_usage(prgname);
> - exit(EXIT_SUCCESS);
> -
> - /* long options */
> - case OPT_XEN_DOM0_NUM:
> -#ifdef RTE_LIBRTE_XEN_DOM0
> - internal_config.xen_dom0_support = 1;
> -#else
> - RTE_LOG(ERR, EAL, "Can't support DPDK app "
> - "running on Dom0, please configure"
> - " RTE_LIBRTE_XEN_DOM0=y\n");
> ret = -1;
> goto out;
> -#endif
> - break;
> + }
> + break;
>
> - case OPT_HUGE_DIR_NUM:
> - internal_config.hugepage_dir = optarg;
> - break;
> + case OPT_CREATE_UIO_DEV_NUM:
> + internal_config.create_uio_dev = 1;
> + break;
>
> - case OPT_FILE_PREFIX_NUM:
> - internal_config.hugefile_prefix = optarg;
> - break;
> + default:
> + if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
> + RTE_LOG(ERR, EAL, "Option %c is not supported "
> + "on Linux\n", opt);
> + } else if (opt >= OPT_LONG_MIN_NUM &&
> + opt < OPT_LONG_MAX_NUM) {
> + RTE_LOG(ERR, EAL, "Option %s is not supported "
> + "on Linux\n",
> + eal_long_options[option_index].name);
> + } else {
> + RTE_LOG(ERR, EAL, "Option %d is not supported "
> + "on Linux\n", opt);
> + }
> + eal_usage(prgname);
> + ret = -1;
> + goto out;
> + }
>
> - case OPT_SOCKET_MEM_NUM:
> - if (eal_parse_socket_mem(optarg) < 0) {
> - RTE_LOG(ERR, EAL, "invalid parameters for --"
> - OPT_SOCKET_MEM "\n");
> - eal_usage(prgname);
> - ret = -1;
> - goto out;
> - }
> - break;
> + return 0;
> +out:
> + return ret;
> +}
>
> - case OPT_BASE_VIRTADDR_NUM:
> - if (eal_parse_base_virtaddr(optarg) < 0) {
> - RTE_LOG(ERR, EAL, "invalid parameter for --"
> - OPT_BASE_VIRTADDR "\n");
> - eal_usage(prgname);
> - ret = -1;
> - goto out;
> - }
> - break;
> +/* Parse the argument given in the command line of the application */
> +static int
> +eal_parse_args(int argc, char **argv)
> +{
> + int opt, ret;
> + char **argvopt;
> + int option_index;
> + char *prgname = argv[0];
> + const int old_optind = optind;
> + const int old_optopt = optopt;
> + char * const old_optarg = optarg;
>
> - case OPT_VFIO_INTR_NUM:
> - if (eal_parse_vfio_intr(optarg) < 0) {
> - RTE_LOG(ERR, EAL, "invalid parameters for --"
> - OPT_VFIO_INTR "\n");
> - eal_usage(prgname);
> - ret = -1;
> - goto out;
> - }
> - break;
> + argvopt = argv;
> + optind = 1;
>
> - case OPT_CREATE_UIO_DEV_NUM:
> - internal_config.create_uio_dev = 1;
> - break;
> + while ((opt = getopt_long(argc, argvopt, eal_short_options,
> + eal_long_options, &option_index)) != EOF) {
>
> - default:
> - if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
> - RTE_LOG(ERR, EAL, "Option %c is not supported "
> - "on Linux\n", opt);
> - } else if (opt >= OPT_LONG_MIN_NUM &&
> - opt < OPT_LONG_MAX_NUM) {
> - RTE_LOG(ERR, EAL, "Option %s is not supported "
> - "on Linux\n",
> - eal_long_options[option_index].name);
> - } else {
> - RTE_LOG(ERR, EAL, "Option %d is not supported "
> - "on Linux\n", opt);
> - }
> - eal_usage(prgname);
> - ret = -1;
> + ret = eal_parse_option(opt, optarg, option_index, prgname);
> + if (ret < 0)
> goto out;
> - }
> }
>
> if (eal_adjust_config(&internal_config) != 0) {
> @@ -995,3 +1028,149 @@ rte_eal_check_module(const char *module_name)
> /* Module has been found */
> return 1;
> }
> +
> +#ifdef RTE_LIBRTE_CFGFILE
> +#define vdev_buff_size 200
> +#define sectionname_size 20
> +static int
> +parse_vdev_devices(struct rte_cfgfile *cfg)
> +{
> + char sectionname[sectionname_size];
> + char buffer1[vdev_buff_size];
> + int vdev_nb = 0;
> + int n_entries;
> +
> + int i;
> +
> + /* ----------- parsing VDEVS */
> + snprintf(sectionname, sectionname_size, "DPDK.vdev%d", vdev_nb);
> +
> + for (vdev_nb = 1; rte_cfgfile_has_section(cfg, sectionname);
> + vdev_nb++) {
> + n_entries = rte_cfgfile_section_num_entries(cfg, sectionname);
> +
> + struct rte_cfgfile_entry entries[n_entries];
> +
> +
> + if (n_entries != rte_cfgfile_section_entries(cfg, sectionname,
> + entries, n_entries)) {
> + rte_eal_init_alert("Unexpected fault.");
> + rte_errno = EFAULT;
> + return -1;
> + }
> +
> + buffer1[0] = 0;
> + for (i = 0; i < n_entries; i++) {
> + if (strlen(entries[i].value)) {
> +
> + if ((strlen(buffer1) +
> + strlen(entries[i].name) +
> + strlen(entries[i].value) + 3)
> + >= vdev_buff_size)
> + goto buff_size_err;
> + strcat(buffer1, entries[i].name);
> + strcat(buffer1, "=");
> + strcat(buffer1, entries[i].value);
> + } else {
> + if ((strlen(buffer1) +
> + strlen(entries[i].name) + 2)
> + >= vdev_buff_size)
> + goto buff_size_err;
> + strcat(buffer1, entries[i].name);
> + }
> +
> + if (i < (n_entries - 1))
> + strcat(buffer1, ",");
> + }
> +
> + /* parsing vdev */
> + if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL,
> + buffer1) < 0) {
> + return -1;
> + }
> + snprintf(sectionname, sectionname_size, "DPDK.vdev%d", vdev_nb);
> + }
> + /* ----------- parsing VDEVS */
> + return 0;
> +
> +buff_size_err:
> + printf("parse_vdev_devices(): buffer size is to small\n");
> + return -1;
> +}
> +
> +static void
> +eal_getopt(const char *str, int *opt, int *option_index)
> +{
> + int i;
> +
> + *opt = '?';
> + *option_index = 0;
> +
> + if (strlen(str) == 1) {
> + *opt = *str;
> + return;
> + }
> +
> + for (i = 0; eal_long_options[i].name != NULL; i++) {
> + if (strcmp(str, eal_long_options[i].name) == 0) {
> + *opt = eal_long_options[i].val;
> + *option_index = i;
> + break;
> + }
> + }
> +}
> +
> +int
> +rte_eal_configure(struct rte_cfgfile *cfg, char *prgname)
> +{
> + int n_entries;
> + int i;
> + int opt;
> + int option_index;
> +
> + if (cfg == NULL) {
> + rte_errno = -EINVAL;
> + return -1;
> + }
> +
> + n_entries = rte_cfgfile_section_num_entries(cfg, "DPDK");
> +
> + if (n_entries < 1) {
> + printf("No DPDK section entries in cfgfile object\n");
> + return 0;
> + }
> +
> + struct rte_cfgfile_entry entries[n_entries];
> +
> + if (n_entries !=
> + rte_cfgfile_section_entries(cfg, "DPDK", entries,
> + n_entries)) {
> + rte_eal_init_alert("Unexpected fault.");
> + rte_errno = EFAULT;
> + return -1;
> + }
> +
> + eal_reset_internal_config(&internal_config);
> +
> + /* set log level as early as possible */
> + eal_log_level_cfg(cfg);
> +
> + for (i = 0; i < n_entries; i++) {
> + eal_getopt(entries[i].name, &opt, &option_index);
> +
> + if (eal_parse_option(opt, entries[i].value,
> + option_index, prgname) != 0) {
> + rte_eal_init_alert("Invalid config file arguments.");
> + rte_errno = EINVAL;
> + return -1;
> + }
> + }
> +
> + if (parse_vdev_devices(cfg) < 0) {
> + rte_eal_init_alert("Couldn't parse vdevs");
> + rte_errno = ENOMEM;
> + return -1;
> + }
> + return 0;
> +}
> +#endif
Can this code in the #ifdef #endif block above go in a common file, as
again it looks very alike the BSD version?
> diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> index 670bab3..c93e6d9 100644
> --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
> @@ -198,3 +198,7 @@ DPDK_17.05 {
> vfio_get_group_no;
>
> } DPDK_17.02;
> +
> +DPDK_17.08 {
> + rte_eal_configure;
> +} DPDK_17.05;
> diff --git a/mk/rte.app.mk b/mk/rte.app.mk
> index bcaf1b3..642af92 100644
> --- a/mk/rte.app.mk
> +++ b/mk/rte.app.mk
> @@ -80,7 +80,6 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_POWER) += -lrte_power
>
> _LDLIBS-$(CONFIG_RTE_LIBRTE_TIMER) += -lrte_timer
> _LDLIBS-$(CONFIG_RTE_LIBRTE_EFD) += -lrte_efd
> -_LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile
>
> _LDLIBS-y += --whole-archive
>
> @@ -96,6 +95,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += -lrte_mempool
> _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING) += -lrte_mempool_ring
> _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring
> _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal
> +_LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile
> _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline
> _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder
>
> --
> 2.7.4
>
next prev parent reply other threads:[~2017-06-30 16:04 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-30 8:30 [dpdk-dev] [PATCH 0/3] Add support for using a config file for DPDK Jacek Piasecki
2017-05-30 8:30 ` [dpdk-dev] [PATCH 1/3] cfgfile: add new API functions Jacek Piasecki
2017-05-31 14:20 ` Bruce Richardson
2017-05-31 14:22 ` Bruce Richardson
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 0/7] Add support for using a config file for DPDK Jacek Piasecki
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 1/7] cfgfile: remove EAL dependency Jacek Piasecki
2017-06-26 13:12 ` Dumitrescu, Cristian
2017-06-27 10:26 ` [dpdk-dev] [PATCH v3 0/4] Rework cfgfile API to enable apps config file support Jacek Piasecki
2017-06-27 10:26 ` [dpdk-dev] [PATCH v3 1/4] cfgfile: remove EAL dependency Jacek Piasecki
2017-06-30 9:44 ` Bruce Richardson
2017-06-30 11:16 ` Bruce Richardson
2017-06-27 10:26 ` [dpdk-dev] [PATCH v3 2/4] cfgfile: add new functions to API Jacek Piasecki
2017-06-30 9:55 ` Bruce Richardson
2017-06-30 10:28 ` Bruce Richardson
2017-06-27 10:26 ` [dpdk-dev] [PATCH v3 3/4] cfgfile: rework of load function Jacek Piasecki
2017-06-30 11:18 ` Bruce Richardson
2017-06-27 10:26 ` [dpdk-dev] [PATCH v3 4/4] test/cfgfile: add new unit test Jacek Piasecki
2017-06-30 11:20 ` [dpdk-dev] [PATCH v3 0/4] Rework cfgfile API to enable apps config file support Bruce Richardson
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 2/7] cfgfile: add new functions to API Jacek Piasecki
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 3/7] cfgfile: rework of load function Jacek Piasecki
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 4/7] test/cfgfile: add new unit test Jacek Piasecki
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 5/7] eal: add functions parsing EAL arguments Jacek Piasecki
2017-06-27 10:52 ` [dpdk-dev] [PATCH v3 0/3] EAL change for using a config file for DPDK Jacek Piasecki
2017-06-27 10:52 ` [dpdk-dev] [PATCH v3 1/3] eal: add functions parsing EAL arguments Jacek Piasecki
2017-06-30 16:04 ` Bruce Richardson [this message]
2017-07-10 12:44 ` [dpdk-dev] [PATCH v4 0/5] Rework cfgfile API to enable apps config file support Jacek Piasecki
2017-07-10 12:44 ` [dpdk-dev] [PATCH v4 1/5] cfgfile: remove EAL dependency Jacek Piasecki
2017-08-30 17:58 ` Bruce Richardson
2017-07-10 12:44 ` [dpdk-dev] [PATCH v4 2/5] cfgfile: change existing API functions Jacek Piasecki
2017-08-30 20:07 ` Bruce Richardson
2017-07-10 12:44 ` [dpdk-dev] [PATCH v4 3/5] cfgfile: add new functions to API Jacek Piasecki
2017-08-30 20:18 ` Bruce Richardson
2017-07-10 12:44 ` [dpdk-dev] [PATCH v4 4/5] cfgfile: rework of load function Jacek Piasecki
2017-08-30 20:24 ` Bruce Richardson
2017-07-10 12:44 ` [dpdk-dev] [PATCH v4 5/5] test/cfgfile: add new unit test Jacek Piasecki
2017-08-30 20:25 ` Bruce Richardson
2017-09-04 9:21 ` Bruce Richardson
2017-09-04 9:30 ` Bruce Richardson
2017-09-15 13:56 ` Thomas Monjalon
2017-09-18 13:49 ` Jastrzebski, MichalX K
2017-07-10 15:13 ` [dpdk-dev] [PATCH v4 0/5] Rework cfgfile API to enable apps config file support Thomas Monjalon
2017-07-20 21:48 ` Thomas Monjalon
2017-07-10 12:51 ` [dpdk-dev] [PATCH v4 0/3] EAL change for using a config file for DPDK Kuba Kozak
2017-07-10 12:51 ` [dpdk-dev] [PATCH v4 1/3] eal: add functions parsing EAL arguments Kuba Kozak
2017-07-13 9:26 ` [dpdk-dev] [PATCH v5 0/3] EAL change for using a config file for DPDK Kuba Kozak
2017-07-13 10:07 ` Kuba Kozak
2017-07-13 10:07 ` [dpdk-dev] [PATCH v5 1/3] eal: add functions parsing EAL arguments Kuba Kozak
2017-07-13 10:07 ` [dpdk-dev] [PATCH v5 2/3] app/testpmd: add parse options from cfg file Kuba Kozak
2017-07-13 10:07 ` [dpdk-dev] [PATCH v5 3/3] app/testpmd: add parse options from JSON " Kuba Kozak
2019-01-23 19:31 ` [dpdk-dev] [PATCH v5 0/3] EAL change for using a config file for DPDK Ferruh Yigit
2019-01-23 20:26 ` Thomas Monjalon
2019-01-24 13:54 ` Ferruh Yigit
2019-01-24 14:32 ` Thomas Monjalon
2019-01-24 14:46 ` Ferruh Yigit
2019-01-24 16:06 ` Thomas Monjalon
2019-01-24 16:18 ` Ferruh Yigit
2019-01-24 17:45 ` Thomas Monjalon
2019-01-28 14:43 ` Ferruh Yigit
2017-07-10 12:51 ` [dpdk-dev] [PATCH v4 2/3] app/testpmd: add parse options from cfg file Kuba Kozak
2017-07-10 12:51 ` [dpdk-dev] [PATCH v4 3/3] app/testpmd: add parse options from JSON " Kuba Kozak
2017-06-27 10:52 ` [dpdk-dev] [PATCH v3 2/3] app/testpmd: changed example to parse options from " Jacek Piasecki
2017-06-27 10:52 ` [dpdk-dev] [PATCH v3 3/3] app/testpmd: add parse arguments from JSON config file Jacek Piasecki
2017-07-05 0:00 ` [dpdk-dev] [PATCH v3 0/3] EAL change for using a config file for DPDK Thomas Monjalon
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 6/7] app/testpmd: changed example to parse options from cfg file Jacek Piasecki
2017-06-26 10:59 ` [dpdk-dev] [PATCH v2 7/7] app/testpmd: add parse arguments from JSON config file Jacek Piasecki
2017-05-30 8:30 ` [dpdk-dev] [PATCH 2/3] eal: add functions parsing EAL arguments Jacek Piasecki
2017-05-31 15:46 ` Bruce Richardson
2017-05-30 8:30 ` [dpdk-dev] [PATCH 3/3] app/testpmd: changed example to parse options from cfg file Jacek Piasecki
2017-06-20 2:13 ` Wu, Jingjing
2017-06-20 10:10 ` Kozak, KubaX
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170630160445.GA17400@bricha3-MOBL3.ger.corp.intel.com \
--to=bruce.richardson@intel.com \
--cc=deepak.k.jain@intel.com \
--cc=dev@dpdk.org \
--cc=jacekx.piasecki@intel.com \
--cc=kubax.kozak@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).