[dpdk-dev] [PATCH] app/crypto-perf: fix total_ops value validation
Added total_ops value validation in parse_total_ops() function. Coverity issue: 141070 Fixes: f8be1786b1b8 ("app/crypto-perf: introduce performance test application") Signed-off-by: Kuba Kozak --- app/test-crypto-perf/cperf_options_parsing.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/test-crypto-perf/cperf_options_parsing.c b/app/test-crypto-perf/cperf_options_parsing.c index 3b7342d..3a8b898 100644 --- a/app/test-crypto-perf/cperf_options_parsing.c +++ b/app/test-crypto-perf/cperf_options_parsing.c @@ -128,7 +128,13 @@ struct name_id_map { int ret = parse_uint32_t(&opts->total_ops, arg); if (ret) - RTE_LOG(ERR, USER1, "failed to parse total operations count"); + RTE_LOG(ERR, USER1, "failed to parse total operations count\n"); + + if (opts->total_ops == 0) { + RTE_LOG(ERR, USER1, + "invalid total operations count number specified\n"); + return -1; + } return ret; } -- 1.9.1 Intel Technology Poland sp. z o.o. ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN. Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione. This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.
[dpdk-dev] [PATCH v4 1/3] eal: add functions parsing EAL arguments
added function rte_eal_configure which configure Environment Abstraction Layer (EAL) using configuration structure. Signed-off-by: Kuba Kozak Suggested-by: Bruce Richardson --- lib/Makefile| 3 + lib/librte_eal/bsdapp/eal/Makefile | 4 + lib/librte_eal/bsdapp/eal/eal.c | 165 +++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 1 + lib/librte_eal/common/eal_common_lcore.c| 7 + lib/librte_eal/common/eal_common_options.c | 106 ++ lib/librte_eal/common/eal_options.h | 3 + lib/librte_eal/common/include/rte_eal.h | 20 ++ lib/librte_eal/linuxapp/eal/Makefile| 3 + lib/librte_eal/linuxapp/eal/eal.c | 265 lib/librte_eal/linuxapp/eal/rte_eal_version.map | 1 + mk/rte.app.mk | 2 +- 12 files changed, 452 insertions(+), 128 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 1080a95..2c6c380 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -34,6 +34,9 @@ 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 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 + # 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..4a0c221 100644 --- a/lib/librte_eal/bsdapp/eal/eal.c +++ b/lib/librte_eal/bsdapp/eal/eal.c @@ -73,6 +73,7 @@ #include #include #include +#include #include "eal_private.h" #include "eal_thread.h" @@ -99,6 +100,8 @@ static struct flock wr_lock = { .l_len = sizeof(early_mem_config.memseg), }; +static int run_once_reset_internal_config; + /* Address of global and public configuration */ static struct rte_config rte_config = { .mem_config = &early_mem_config, @@ -347,6 +350,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 +422,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
[dpdk-dev] [PATCH v4 0/3] EAL change for using a config file for DPDK
This patchset introduce a mechanism for running dpdk application with parameters provided by configuration file. A new API for EAL takes a config file data type - either loaded from file, or built up programmatically in the application - and extracts DPDK parameters from it to be used when eal init is called. This allows apps to have an alternative method to configure EAL, other than via command-line parameters. Reworked applications are used to demonstrate the new eal API. If a --cfgfile-path option is passed into command line non EAL section, then the file is loaded and used by app. If a file called config.ini is present in current working directory, and no --cfgfile-path option is passed in, config.ini file will be loaded and used by app. Patch "app/testpmd: add parse options from JSON cfg file" demonstrates the usage of JSON instead of INI file format. JSON file can be called the same way as above, through --cfgfile-path argument. --- this patch depends on: "Rework cfgfile API to enable apps config file support" v4: Code optimalisation in parse_vdev_devices() function. Moved some functions from librte_eal/bsdapp and librte_eal/linuxapp to the librte_eal/common. Bug fixes. v3: split one patchset into two distinct patchsets: 1. cfgfile library and TEST app changes 2. EAL changes and examples (this patchset depends on cfgfile) v2: lib eal: Rework of rte_eal_configure(struct rte_cfgfile *cfg, char *prgname). Now this function load data from cfg structure and did initial initialization of EAL arguments. Vdev argument are stored in different subsections eg. DPDK.vdev0, DPDK.vdev1 etc. After execution of this function it is necessary to call rte_eal_init to complete EAL initialization. There is no more merging arguments from different sources (cfg file and command line). Added non_eal_configure to testpmd application. Function maintain the same functionality as rte_eal_configure but for non-eal arguments. Added config JSON feature to testpmd last patch from patchset contain example showing use of .json configuration files. lib cfgfile: Rework of add_section(), add_entry() new implementation New members allocated_entries/sections, free_entries/sections in rte_cfgfile structure, change in array of pointers **sections, **entries instead of *sections[], *entries[] Add set_entry() to update/overwrite already existing entry in cfgfile struct Add save() function to save on disc cfgfile structure in INI format Rework of existing load() function simplifying the code Add unit test realloc_sections() in TEST app for testing realloc/malloc of new API functions, add test for save() function Kuba Kozak (3): eal: add functions parsing EAL arguments app/testpmd: add parse options from cfg file app/testpmd: add parse options from JSON cfg file app/test-pmd/Makefile |6 + app/test-pmd/config.ini | 24 + app/test-pmd/config.json| 33 + app/test-pmd/parameters.c | 1181 +-- app/test-pmd/testpmd.c | 159 ++- app/test-pmd/testpmd.h |3 +- config/common_base |5 + lib/Makefile|3 + lib/librte_eal/bsdapp/eal/Makefile |4 + lib/librte_eal/bsdapp/eal/eal.c | 165 +++- lib/librte_eal/bsdapp/eal/rte_eal_version.map |1 + lib/librte_eal/common/eal_common_lcore.c|7 + lib/librte_eal/common/eal_common_options.c | 106 ++ lib/librte_eal/common/eal_options.h |3 + lib/librte_eal/common/include/rte_eal.h | 20 + lib/librte_eal/linuxapp/eal/Makefile|3 + lib/librte_eal/linuxapp/eal/eal.c | 265 +++-- lib/librte_eal/linuxapp/eal/rte_eal_version.map |1 + mk/rte.app.mk |2 +- 19 files changed, 1349 insertions(+), 642 deletions(-) create mode 100644 app/test-pmd/config.ini create mode 100644 app/test-pmd/config.json -- 2.7.4
[dpdk-dev] [PATCH v4 2/3] app/testpmd: add parse options from cfg file
This patch shows how to pass arguments to application using config.ini file. If a --cfgfile-path option is passed into commandline non EAL section, then the file is loaded and used by app. If a config.ini file is present in current working directory, and no --cfgfile-path option is passed in, config.ini file will be loaded and used by app as default configuration. Signed-off-by: Kuba Kozak Suggested-by: Bruce Richardson --- app/test-pmd/config.ini | 24 + app/test-pmd/parameters.c | 1181 + app/test-pmd/testpmd.c| 67 ++- app/test-pmd/testpmd.h|3 +- 4 files changed, 761 insertions(+), 514 deletions(-) create mode 100644 app/test-pmd/config.ini diff --git a/app/test-pmd/config.ini b/app/test-pmd/config.ini new file mode 100644 index 000..54c83a2 --- /dev/null +++ b/app/test-pmd/config.ini @@ -0,0 +1,24 @@ +[DPDK] +v = +l = 0-4 +n = 4 +master-lcore = 0 +proc-type = primary + +[TEST-PMD] +i = +portmask = 0xff +nb-cores = 4 +port-topology = paired + +[DPDK.vdev0] +net_ring0 = + +[DPDK.vdev1] +net_ring1 = + +[DPDK.vdev2] +net_ring2 = + +[DPDK.vdev3] +net_ring3 = \ No newline at end of file diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 958b3d0..d32861a 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -77,9 +77,98 @@ #include #endif #include +#ifdef RTE_LIBRTE_CFGFILE +#include +#endif #include "testpmd.h" +enum { TX, RX }; + +static struct option lgopts[] = { + { "cfgfile-path", 1, 0, 1 }, + { "help", 0, 0, 0 }, +#ifdef RTE_LIBRTE_CMDLINE + { "interactive",0, 0, 0 }, + { "cmdline-file", 1, 0, 0 }, + { "auto-start", 0, 0, 0 }, + { "eth-peers-configfile", 1, 0, 0 }, + { "eth-peer", 1, 0, 0 }, +#endif + { "tx-first", 0, 0, 0 }, + { "stats-period", 1, 0, 0 }, + { "ports", 1, 0, 0 }, + { "nb-cores", 1, 0, 0 }, + { "nb-ports", 1, 0, 0 }, + { "coremask", 1, 0, 0 }, + { "portmask", 1, 0, 0 }, + { "numa", 0, 0, 0 }, + { "no-numa",0, 0, 0 }, + { "mp-anon",0, 0, 0 }, + { "port-numa-config", 1, 0, 0 }, + { "ring-numa-config", 1, 0, 0 }, + { "socket-num", 1, 0, 0 }, + { "mbuf-size", 1, 0, 0 }, + { "total-num-mbufs",1, 0, 0 }, + { "max-pkt-len",1, 0, 0 }, + { "pkt-filter-mode",1, 0, 0 }, + { "pkt-filter-report-hash", 1, 0, 0 }, + { "pkt-filter-size",1, 0, 0 }, + { "pkt-filter-drop-queue", 1, 0, 0 }, +#ifdef RTE_LIBRTE_LATENCY_STATS + { "latencystats", 1, 0, 0 }, +#endif +#ifdef RTE_LIBRTE_BITRATE + { "bitrate-stats", 1, 0, 0 }, +#endif + { "disable-crc-strip", 0, 0, 0 }, + { "enable-lro", 0, 0, 0 }, + { "enable-rx-cksum",0, 0, 0 }, + { "enable-scatter", 0, 0, 0 }, + { "disable-hw-vlan",0, 0, 0 }, + { "disable-hw-vlan-filter", 0, 0, 0 }, + { "disable-hw-vlan-strip", 0, 0, 0 }, + { "disable-hw-vlan-extend", 0, 0, 0 }, + { "enable-drop-en",0, 0, 0 }, + { "disable-rss",0, 0, 0 }, + { "port-topology", 1, 0, 0 }, + { "forward-mode", 1, 0, 0 }, + { "rss-ip", 0, 0, 0 }, + { "rss-udp",0, 0, 0 }, + { "rxq",1, 0, 0 }, + { "txq",1, 0, 0 }, + { "rxd",1, 0, 0 }, + { "txd",1, 0, 0 }, + { "burst", 1, 0, 0 }, + { "mbcache",1, 0, 0 }, + { "txpt", 1, 0, 0 }, + { "txht", 1, 0, 0 }, + { "txwt", 1, 0, 0 }, + { "txfreet",1, 0, 0 }, + { "txrst", 1, 0, 0 }, + { "txqflags",
[dpdk-dev] [PATCH v4 3/3] app/testpmd: add parse options from JSON cfg file
This patch shows usage of Jansson library to parse application arguments from JSON config file. https://github.com/akheron/jansson If a --cfgfile-path option is passed into commandline non EAL section, then the disired JSON file is loaded and used by app. In case when JSON doesn't exist an INI file is loaded. The INI file can be passed also from --cfgfile-path option. If a file called config.ini is present in current working directory, and no --cfgfile-path option is passed in, config.ini file will be loaded and used by app. Signed-off-by: Kuba Kozak Suggested-by: Bruce Richardson --- app/test-pmd/Makefile| 6 app/test-pmd/config.json | 33 + app/test-pmd/testpmd.c | 94 +++- config/common_base | 5 +++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/config.json diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index c36be19..a1c84cc 100644 --- a/app/test-pmd/Makefile +++ b/app/test-pmd/Makefile @@ -83,6 +83,12 @@ endif endif +ifeq ($(CONFIG_RTE_JSON_SUPPORT),y) +ifeq ($(CONFIG_RTE_LIBRTE_CFGFILE),y) +LDLIBS += -ljansson +endif +endif + CFLAGS_cmdline.o := -D_GNU_SOURCE include $(RTE_SDK)/mk/rte.app.mk diff --git a/app/test-pmd/config.json b/app/test-pmd/config.json new file mode 100644 index 000..4589dbc --- /dev/null +++ b/app/test-pmd/config.json @@ -0,0 +1,33 @@ +{ + "DPDK": + { + "v": "", + "l": "0-4", + "n": "4", + "master-lcore": "0", + "proc-type": "primary" + }, + "TEST-PMD": + { + "i": "", + "portmask": "0xff", + "nb-cores": "4", + "port-topology": "paired" + }, + "DPDK.vdev0": + { + "net_ring0": "" + }, + "DPDK.vdev1": + { + "net_ring1": "" + }, + "DPDK.vdev2": + { + "net_ring2": "" + }, + "DPDK.vdev3": + { + "net_ring3": "" + } +} diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 7b82976..014bb46 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -46,6 +46,10 @@ #include #include + +#ifdef RTE_JSON_SUPPORT +#include +#endif #include #include @@ -2290,6 +2294,87 @@ cfgfile_load_path(int argc, char **argv) } return NULL; } + +#ifdef RTE_JSON_SUPPORT +/* + * Decoding JSON structure to rte_cfgfile structure. + * Returns handler to cfgfile object, NULL if error. + */ +static struct +rte_cfgfile *l3fwd_json_to_cfg(json_t *json, int flags) +{ + if (!json) { + printf("Error: JSON structure is NULL, nothing to parse\n"); + return NULL; + } + /* create an empty instance of cfgfile structure */ + struct rte_cfgfile *cfgfile = rte_cfgfile_create(flags); + + if (!cfgfile) + return NULL; + + const char *section; + json_t *entry; + + /* set pointer to first section */ + void *iter_section = json_object_iter(json); + + while (iter_section) { + + section = json_object_iter_key(iter_section); + entry = json_object_iter_value(iter_section); + + /* add parsed section name of current section to cfgfile */ + rte_cfgfile_add_section(cfgfile, section); + + /* set pointer to first entry */ + void *iter_entry = json_object_iter(entry); + + while (iter_entry) { + + const char *key; + const char *value; + + key = json_object_iter_key(iter_entry); + value = json_string_value( + json_object_iter_value(iter_entry)); + + /* add parsed key and value of current entry */ + /* to cfgfile */ + rte_cfgfile_add_entry(cfgfile, section, key, value); + + /* pointer to next entry */ + iter_entry = json_object_iter_next(entry, iter_entry); + } + /* pointer to next section */ + iter_section = json_object_iter_next(json, iter_section); + } + return cfgfile; +} + +/* + * Check presence and load JSON file to rte_cfgfile structure. + * Returns handler to cfgfile object, NULL if error. + */ +static struct +rte_cfgfile *l3fwd_load_json_to_cfg(const char *path) +{ + struct rte_cfgfile *cfgfile = NULL; + /* check if config file e
[dpdk-dev] [PATCH v5 0/3] EAL change for using a config file for DPDK
This patchset introduce a mechanism for running dpdk application with parameters provided by configuration file. A new API for EAL takes a config file data type - either loaded from file, or built up programmatically in the application - and extracts DPDK parameters from it to be used when eal init is called. This allows apps to have an alternative method to configure EAL, other than via command-line parameters. Reworked applications are used to demonstrate the new eal API. If a --cfgfile-path option is passed into command line non EAL section, then the file is loaded and used by app. If a file called config.ini is present in current working directory, and no --cfgfile-path option is passed in, config.ini file will be loaded and used by app. Patch "app/testpmd: add parse options from JSON cfg file" demonstrates the usage of JSON instead of INI file format. JSON file can be called the same way as above, through --cfgfile-path argument. --- this patch depends on: "Rework cfgfile API to enable apps config file support" v5: changed define "RTE_DEVTYPE_VIRTUAL" to "RTE_DEVTYPE_UNDEFINED" due to compilation errors (changes on current master). v4: Code optimalisation in parse_vdev_devices() function. Moved some functions from librte_eal/bsdapp and librte_eal/linuxapp to the librte_eal/common. Bug fixes. v3: split one patchset into two distinct patchsets: 1. cfgfile library and TEST app changes 2. EAL changes and examples (this patchset depends on cfgfile) v2: lib eal: Rework of rte_eal_configure(struct rte_cfgfile *cfg, char *prgname). Now this function load data from cfg structure and did initial initialization of EAL arguments. Vdev argument are stored in different subsections eg. DPDK.vdev0, DPDK.vdev1 etc. After execution of this function it is necessary to call rte_eal_init to complete EAL initialization. There is no more merging arguments from different sources (cfg file and command line). Added non_eal_configure to testpmd application. Function maintain the same functionality as rte_eal_configure but for non-eal arguments. Added config JSON feature to testpmd last patch from patchset contain example showing use of .json configuration files. lib cfgfile: Rework of add_section(), add_entry() new implementation New members allocated_entries/sections, free_entries/sections in rte_cfgfile structure, change in array of pointers **sections, **entries instead of *sections[], *entries[] Add set_entry() to update/overwrite already existing entry in cfgfile struct Add save() function to save on disc cfgfile structure in INI format Rework of existing load() function simplifying the code Add unit test realloc_sections() in TEST app for testing realloc/malloc of new API functions, add test for save() function Kuba Kozak (3): eal: add functions parsing EAL arguments app/testpmd: add parse options from cfg file app/testpmd: add parse options from JSON cfg file app/test-pmd/Makefile |6 + app/test-pmd/config.ini | 24 + app/test-pmd/config.json| 33 + app/test-pmd/parameters.c | 1181 +-- app/test-pmd/testpmd.c | 159 ++- app/test-pmd/testpmd.h |3 +- config/common_base |5 + lib/Makefile|3 + lib/librte_eal/bsdapp/eal/Makefile |4 + lib/librte_eal/bsdapp/eal/eal.c | 165 +++- lib/librte_eal/bsdapp/eal/rte_eal_version.map |1 + lib/librte_eal/common/eal_common_lcore.c|7 + lib/librte_eal/common/eal_common_options.c | 106 ++ lib/librte_eal/common/eal_options.h |3 + lib/librte_eal/common/include/rte_eal.h | 20 + lib/librte_eal/linuxapp/eal/Makefile|3 + lib/librte_eal/linuxapp/eal/eal.c | 265 +++-- lib/librte_eal/linuxapp/eal/rte_eal_version.map |1 + mk/rte.app.mk |2 +- 19 files changed, 1349 insertions(+), 642 deletions(-) create mode 100644 app/test-pmd/config.ini create mode 100644 app/test-pmd/config.json -- 2.7.4
[dpdk-dev] [PATCH v5 0/3] EAL change for using a config file for DPDK
This patchset introduce a mechanism for running dpdk application with parameters provided by configuration file. A new API for EAL takes a config file data type - either loaded from file, or built up programmatically in the application - and extracts DPDK parameters from it to be used when eal init is called. This allows apps to have an alternative method to configure EAL, other than via command-line parameters. Reworked applications are used to demonstrate the new eal API. If a --cfgfile-path option is passed into command line non EAL section, then the file is loaded and used by app. If a file called config.ini is present in current working directory, and no --cfgfile-path option is passed in, config.ini file will be loaded and used by app. Patch "app/testpmd: add parse options from JSON cfg file" demonstrates the usage of JSON instead of INI file format. JSON file can be called the same way as above, through --cfgfile-path argument. --- this patch depends on: "Rework cfgfile API to enable apps config file support" v5: changed define "RTE_DEVTYPE_VIRTUAL" to "RTE_DEVTYPE_UNDEFINED" due to compilation errors (changes on current master). v4: Code optimalisation in parse_vdev_devices() function. Moved some functions from librte_eal/bsdapp and librte_eal/linuxapp to the librte_eal/common. Bug fixes. v3: split one patchset into two distinct patchsets: 1. cfgfile library and TEST app changes 2. EAL changes and examples (this patchset depends on cfgfile) v2: lib eal: Rework of rte_eal_configure(struct rte_cfgfile *cfg, char *prgname). Now this function load data from cfg structure and did initial initialization of EAL arguments. Vdev argument are stored in different subsections eg. DPDK.vdev0, DPDK.vdev1 etc. After execution of this function it is necessary to call rte_eal_init to complete EAL initialization. There is no more merging arguments from different sources (cfg file and command line). Added non_eal_configure to testpmd application. Function maintain the same functionality as rte_eal_configure but for non-eal arguments. Added config JSON feature to testpmd last patch from patchset contain example showing use of .json configuration files. lib cfgfile: Rework of add_section(), add_entry() new implementation New members allocated_entries/sections, free_entries/sections in rte_cfgfile structure, change in array of pointers **sections, **entries instead of *sections[], *entries[] Add set_entry() to update/overwrite already existing entry in cfgfile struct Add save() function to save on disc cfgfile structure in INI format Rework of existing load() function simplifying the code Add unit test realloc_sections() in TEST app for testing realloc/malloc of new API functions, add test for save() function Kuba Kozak (3): eal: add functions parsing EAL arguments app/testpmd: add parse options from cfg file app/testpmd: add parse options from JSON cfg file app/test-pmd/Makefile |6 + app/test-pmd/config.ini | 24 + app/test-pmd/config.json| 33 + app/test-pmd/parameters.c | 1181 +-- app/test-pmd/testpmd.c | 159 ++- app/test-pmd/testpmd.h |3 +- config/common_base |5 + lib/Makefile|3 + lib/librte_eal/bsdapp/eal/Makefile |4 + lib/librte_eal/bsdapp/eal/eal.c | 165 +++- lib/librte_eal/bsdapp/eal/rte_eal_version.map |1 + lib/librte_eal/common/eal_common_lcore.c|7 + lib/librte_eal/common/eal_common_options.c | 106 ++ lib/librte_eal/common/eal_options.h |3 + lib/librte_eal/common/include/rte_eal.h | 20 + lib/librte_eal/linuxapp/eal/Makefile|3 + lib/librte_eal/linuxapp/eal/eal.c | 265 +++-- lib/librte_eal/linuxapp/eal/rte_eal_version.map |1 + mk/rte.app.mk |2 +- 19 files changed, 1349 insertions(+), 642 deletions(-) create mode 100644 app/test-pmd/config.ini create mode 100644 app/test-pmd/config.json -- 2.7.4
[dpdk-dev] [PATCH v5 1/3] eal: add functions parsing EAL arguments
added function rte_eal_configure which configure Environment Abstraction Layer (EAL) using configuration structure. Signed-off-by: Kuba Kozak Suggested-by: Bruce Richardson --- lib/Makefile| 3 + lib/librte_eal/bsdapp/eal/Makefile | 4 + lib/librte_eal/bsdapp/eal/eal.c | 165 +++ lib/librte_eal/bsdapp/eal/rte_eal_version.map | 1 + lib/librte_eal/common/eal_common_lcore.c| 7 + lib/librte_eal/common/eal_common_options.c | 106 ++ lib/librte_eal/common/eal_options.h | 3 + lib/librte_eal/common/include/rte_eal.h | 20 ++ lib/librte_eal/linuxapp/eal/Makefile| 3 + lib/librte_eal/linuxapp/eal/eal.c | 265 lib/librte_eal/linuxapp/eal/rte_eal_version.map | 1 + mk/rte.app.mk | 2 +- 12 files changed, 452 insertions(+), 128 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 1080a95..2c6c380 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -34,6 +34,9 @@ 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 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 + # 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..4a0c221 100644 --- a/lib/librte_eal/bsdapp/eal/eal.c +++ b/lib/librte_eal/bsdapp/eal/eal.c @@ -73,6 +73,7 @@ #include #include #include +#include #include "eal_private.h" #include "eal_thread.h" @@ -99,6 +100,8 @@ static struct flock wr_lock = { .l_len = sizeof(early_mem_config.memseg), }; +static int run_once_reset_internal_config; + /* Address of global and public configuration */ static struct rte_config rte_config = { .mem_config = &early_mem_config, @@ -347,6 +350,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 +422,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
[dpdk-dev] [PATCH v5 3/3] app/testpmd: add parse options from JSON cfg file
This patch shows usage of Jansson library to parse application arguments from JSON config file. https://github.com/akheron/jansson If a --cfgfile-path option is passed into commandline non EAL section, then the disired JSON file is loaded and used by app. In case when JSON doesn't exist an INI file is loaded. The INI file can be passed also from --cfgfile-path option. If a file called config.ini is present in current working directory, and no --cfgfile-path option is passed in, config.ini file will be loaded and used by app. Signed-off-by: Kuba Kozak Suggested-by: Bruce Richardson --- app/test-pmd/Makefile| 6 app/test-pmd/config.json | 33 + app/test-pmd/testpmd.c | 94 +++- config/common_base | 5 +++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 app/test-pmd/config.json diff --git a/app/test-pmd/Makefile b/app/test-pmd/Makefile index c36be19..a1c84cc 100644 --- a/app/test-pmd/Makefile +++ b/app/test-pmd/Makefile @@ -83,6 +83,12 @@ endif endif +ifeq ($(CONFIG_RTE_JSON_SUPPORT),y) +ifeq ($(CONFIG_RTE_LIBRTE_CFGFILE),y) +LDLIBS += -ljansson +endif +endif + CFLAGS_cmdline.o := -D_GNU_SOURCE include $(RTE_SDK)/mk/rte.app.mk diff --git a/app/test-pmd/config.json b/app/test-pmd/config.json new file mode 100644 index 000..4589dbc --- /dev/null +++ b/app/test-pmd/config.json @@ -0,0 +1,33 @@ +{ + "DPDK": + { + "v": "", + "l": "0-4", + "n": "4", + "master-lcore": "0", + "proc-type": "primary" + }, + "TEST-PMD": + { + "i": "", + "portmask": "0xff", + "nb-cores": "4", + "port-topology": "paired" + }, + "DPDK.vdev0": + { + "net_ring0": "" + }, + "DPDK.vdev1": + { + "net_ring1": "" + }, + "DPDK.vdev2": + { + "net_ring2": "" + }, + "DPDK.vdev3": + { + "net_ring3": "" + } +} diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 7b82976..014bb46 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -46,6 +46,10 @@ #include #include + +#ifdef RTE_JSON_SUPPORT +#include +#endif #include #include @@ -2290,6 +2294,87 @@ cfgfile_load_path(int argc, char **argv) } return NULL; } + +#ifdef RTE_JSON_SUPPORT +/* + * Decoding JSON structure to rte_cfgfile structure. + * Returns handler to cfgfile object, NULL if error. + */ +static struct +rte_cfgfile *l3fwd_json_to_cfg(json_t *json, int flags) +{ + if (!json) { + printf("Error: JSON structure is NULL, nothing to parse\n"); + return NULL; + } + /* create an empty instance of cfgfile structure */ + struct rte_cfgfile *cfgfile = rte_cfgfile_create(flags); + + if (!cfgfile) + return NULL; + + const char *section; + json_t *entry; + + /* set pointer to first section */ + void *iter_section = json_object_iter(json); + + while (iter_section) { + + section = json_object_iter_key(iter_section); + entry = json_object_iter_value(iter_section); + + /* add parsed section name of current section to cfgfile */ + rte_cfgfile_add_section(cfgfile, section); + + /* set pointer to first entry */ + void *iter_entry = json_object_iter(entry); + + while (iter_entry) { + + const char *key; + const char *value; + + key = json_object_iter_key(iter_entry); + value = json_string_value( + json_object_iter_value(iter_entry)); + + /* add parsed key and value of current entry */ + /* to cfgfile */ + rte_cfgfile_add_entry(cfgfile, section, key, value); + + /* pointer to next entry */ + iter_entry = json_object_iter_next(entry, iter_entry); + } + /* pointer to next section */ + iter_section = json_object_iter_next(json, iter_section); + } + return cfgfile; +} + +/* + * Check presence and load JSON file to rte_cfgfile structure. + * Returns handler to cfgfile object, NULL if error. + */ +static struct +rte_cfgfile *l3fwd_load_json_to_cfg(const char *path) +{ + struct rte_cfgfile *cfgfile = NULL; + /* check if config file e
[dpdk-dev] [PATCH v5 2/3] app/testpmd: add parse options from cfg file
This patch shows how to pass arguments to application using config.ini file. If a --cfgfile-path option is passed into commandline non EAL section, then the file is loaded and used by app. If a config.ini file is present in current working directory, and no --cfgfile-path option is passed in, config.ini file will be loaded and used by app as default configuration. Signed-off-by: Kuba Kozak Suggested-by: Bruce Richardson --- app/test-pmd/config.ini | 24 + app/test-pmd/parameters.c | 1181 + app/test-pmd/testpmd.c| 67 ++- app/test-pmd/testpmd.h|3 +- 4 files changed, 761 insertions(+), 514 deletions(-) create mode 100644 app/test-pmd/config.ini diff --git a/app/test-pmd/config.ini b/app/test-pmd/config.ini new file mode 100644 index 000..54c83a2 --- /dev/null +++ b/app/test-pmd/config.ini @@ -0,0 +1,24 @@ +[DPDK] +v = +l = 0-4 +n = 4 +master-lcore = 0 +proc-type = primary + +[TEST-PMD] +i = +portmask = 0xff +nb-cores = 4 +port-topology = paired + +[DPDK.vdev0] +net_ring0 = + +[DPDK.vdev1] +net_ring1 = + +[DPDK.vdev2] +net_ring2 = + +[DPDK.vdev3] +net_ring3 = \ No newline at end of file diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 958b3d0..d32861a 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -77,9 +77,98 @@ #include #endif #include +#ifdef RTE_LIBRTE_CFGFILE +#include +#endif #include "testpmd.h" +enum { TX, RX }; + +static struct option lgopts[] = { + { "cfgfile-path", 1, 0, 1 }, + { "help", 0, 0, 0 }, +#ifdef RTE_LIBRTE_CMDLINE + { "interactive",0, 0, 0 }, + { "cmdline-file", 1, 0, 0 }, + { "auto-start", 0, 0, 0 }, + { "eth-peers-configfile", 1, 0, 0 }, + { "eth-peer", 1, 0, 0 }, +#endif + { "tx-first", 0, 0, 0 }, + { "stats-period", 1, 0, 0 }, + { "ports", 1, 0, 0 }, + { "nb-cores", 1, 0, 0 }, + { "nb-ports", 1, 0, 0 }, + { "coremask", 1, 0, 0 }, + { "portmask", 1, 0, 0 }, + { "numa", 0, 0, 0 }, + { "no-numa",0, 0, 0 }, + { "mp-anon",0, 0, 0 }, + { "port-numa-config", 1, 0, 0 }, + { "ring-numa-config", 1, 0, 0 }, + { "socket-num", 1, 0, 0 }, + { "mbuf-size", 1, 0, 0 }, + { "total-num-mbufs",1, 0, 0 }, + { "max-pkt-len",1, 0, 0 }, + { "pkt-filter-mode",1, 0, 0 }, + { "pkt-filter-report-hash", 1, 0, 0 }, + { "pkt-filter-size",1, 0, 0 }, + { "pkt-filter-drop-queue", 1, 0, 0 }, +#ifdef RTE_LIBRTE_LATENCY_STATS + { "latencystats", 1, 0, 0 }, +#endif +#ifdef RTE_LIBRTE_BITRATE + { "bitrate-stats", 1, 0, 0 }, +#endif + { "disable-crc-strip", 0, 0, 0 }, + { "enable-lro", 0, 0, 0 }, + { "enable-rx-cksum",0, 0, 0 }, + { "enable-scatter", 0, 0, 0 }, + { "disable-hw-vlan",0, 0, 0 }, + { "disable-hw-vlan-filter", 0, 0, 0 }, + { "disable-hw-vlan-strip", 0, 0, 0 }, + { "disable-hw-vlan-extend", 0, 0, 0 }, + { "enable-drop-en",0, 0, 0 }, + { "disable-rss",0, 0, 0 }, + { "port-topology", 1, 0, 0 }, + { "forward-mode", 1, 0, 0 }, + { "rss-ip", 0, 0, 0 }, + { "rss-udp",0, 0, 0 }, + { "rxq",1, 0, 0 }, + { "txq",1, 0, 0 }, + { "rxd",1, 0, 0 }, + { "txd",1, 0, 0 }, + { "burst", 1, 0, 0 }, + { "mbcache",1, 0, 0 }, + { "txpt", 1, 0, 0 }, + { "txht", 1, 0, 0 }, + { "txwt", 1, 0, 0 }, + { "txfreet",1, 0, 0 }, + { "txrst", 1, 0, 0 }, + { "txqflags",
[dpdk-dev] [PATCH] examples/l2fwd-crypto: add option --[no-]mac-updating
This patch adds a new option to enable/disable the MAC addresses updating done at forwarding time: --[no-]mac-updating By default, MAC address updating remains enabled, to keep consistency with previous usage. Signed-off-by: Kuba Kozak --- doc/guides/sample_app_ug/l2_forward_crypto.rst | 7 ++-- examples/l2fwd-crypto/main.c | 50 ++ 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/doc/guides/sample_app_ug/l2_forward_crypto.rst b/doc/guides/sample_app_ug/l2_forward_crypto.rst index 2a61af7..91ce278 100644 --- a/doc/guides/sample_app_ug/l2_forward_crypto.rst +++ b/doc/guides/sample_app_ug/l2_forward_crypto.rst @@ -46,7 +46,7 @@ for each packet that is received on a RX_PORT and performs L2 forwarding. The destination port is the adjacent port from the enabled portmask, that is, if the first four ports are enabled (portmask 0xf), ports 0 and 1 forward into each other, and ports 2 and 3 forward into each other. -Also, the MAC addresses are affected as follows: +Also, if MAC addresses updating is enabled, the MAC addresses are affected as follows: * The source MAC address is replaced by the TX_PORT MAC address @@ -90,7 +90,8 @@ The application requires a number of command line options: [--auth_algo ALGO] [--auth_op GENERATE/VERIFY] [--auth_key KEY] / [--auth_key_random_size SIZE] [--auth_iv IV] [--auth_iv_random_size SIZE] / [--aad AAD] [--aad_random_size SIZE] / -[--digest size SIZE] [--sessionless] [--cryptodev_mask MASK] +[--digest size SIZE] [--sessionless] [--cryptodev_mask MASK] / +[--mac-updating] [--no-mac-updating] where, @@ -191,6 +192,8 @@ where, (default is all cryptodevs). +* [no-]mac-updating: Enable or disable MAC addresses updating (enabled by default). + The application requires that crypto devices capable of performing the specified crypto operation are available on application initialization. diff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c index 71cb133..a347ad6 100644 --- a/examples/l2fwd-crypto/main.c +++ b/examples/l2fwd-crypto/main.c @@ -193,6 +193,8 @@ struct l2fwd_crypto_options { char string_type[MAX_STR_LEN]; uint64_t cryptodev_mask; + + unsigned int mac_updating; }; /** l2fwd crypto lcore params */ @@ -608,21 +610,31 @@ l2fwd_send_packet(struct rte_mbuf *m, uint8_t port) } static void -l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) +l2fwd_mac_updating(struct rte_mbuf *m, unsigned int dest_portid) { struct ether_hdr *eth; void *tmp; - unsigned dst_port; - dst_port = l2fwd_dst_ports[portid]; eth = rte_pktmbuf_mtod(m, struct ether_hdr *); /* 02:00:00:00:00:xx */ tmp = ð->d_addr.addr_bytes[0]; - *((uint64_t *)tmp) = 0x0002 + ((uint64_t)dst_port << 40); + *((uint64_t *)tmp) = 0x0002 + ((uint64_t)dest_portid << 40); /* src addr */ - ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); + ether_addr_copy(&l2fwd_ports_eth_addr[dest_portid], ð->s_addr); +} + +static void +l2fwd_simple_forward(struct rte_mbuf *m, unsigned int portid, + struct l2fwd_crypto_options *options) +{ + unsigned int dst_port; + + dst_port = l2fwd_dst_ports[portid]; + + if (options->mac_updating) + l2fwd_mac_updating(m, dst_port); l2fwd_send_packet(m, (uint8_t) dst_port); } @@ -920,7 +932,8 @@ l2fwd_main_loop(struct l2fwd_crypto_options *options) m = ops_burst[j]->sym->m_src; rte_crypto_op_free(ops_burst[j]); - l2fwd_simple_forward(m, portid); + l2fwd_simple_forward(m, portid, + options); } } while (nb_rx == MAX_PKT_BURST); } @@ -975,7 +988,12 @@ l2fwd_crypto_usage(const char *prgname) " --digest_size SIZE: size of digest to be generated/verified\n" " --sessionless\n" - " --cryptodev_mask MASK: hexadecimal bitmask of crypto devices to configure\n", + " --cryptodev_mask MASK: hexadecimal bitmask of crypto devices to configure\n" + + " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n" + " When enabled:\n" + " - The source MAC address is replaced by the TX port MAC address\n" + " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n", prgname); } @@ -1322,6 +1340,16 @@ l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
[dpdk-dev] [PATCH] net/e1000: fix out of bounds access
Fix wrong structure type used as argument in memset() call. Coverity issue: 147223 Coverity issue: 147227 Fixes: a8600af43738 ("net/igb: parse flow API ethertype filter") Fixes: 22bb13410cb2 ("net/igb: create consistent filter") Cc: sta...@dpdk.org Signed-off-by: Kuba Kozak --- drivers/net/e1000/igb_flow.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000/igb_flow.c b/drivers/net/e1000/igb_flow.c index db73b18..ed2ecc4 100644 --- a/drivers/net/e1000/igb_flow.c +++ b/drivers/net/e1000/igb_flow.c @@ -694,7 +694,8 @@ igb_parse_ethertype_filter(struct rte_eth_dev *dev, if (hw->mac.type == e1000_82576) { if (filter->queue >= IGB_MAX_RX_QUEUE_NUM_82576) { - memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); + memset(filter, 0, sizeof( + struct rte_eth_ethertype_filter)); rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL, "queue number not supported " @@ -703,7 +704,8 @@ igb_parse_ethertype_filter(struct rte_eth_dev *dev, } } else { if (filter->queue >= IGB_MAX_RX_QUEUE_NUM) { - memset(filter, 0, sizeof(struct rte_eth_ntuple_filter)); + memset(filter, 0, sizeof( + struct rte_eth_ethertype_filter)); rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL, "queue number not supported " -- 2.7.4
[dpdk-dev] [PATCH] net/i40e: fix dereferencing null pointer
Add check if o_vlan_mask and i_vlan_mask are not a NULL pointer. Coverity issue: 143448 Coverity issue: 143449 Fixes: d37705068ee8 ("net/i40e: parse QinQ pattern") Cc: sta...@dpdk.org Signed-off-by: Kuba Kozak --- drivers/net/i40e/i40e_flow.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index 95af701..b92719a 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -3719,8 +3719,10 @@ i40e_flow_parse_qinq_pattern(__rte_unused struct rte_eth_dev *dev, } /* Get filter specification */ - if ((o_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK)) && - (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) { + if ((o_vlan_mask != NULL) && (o_vlan_mask->tci == + rte_cpu_to_be_16(I40E_TCI_MASK)) && + (i_vlan_mask != NULL) && + (i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) { filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci) & I40E_TCI_MASK; filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci) -- 2.7.4
[dpdk-dev] [PATCH 0/4] extend API to retriving xstats by group and xstats by name
Added three new functions to API: rte_eth_xstats_get_by_name(), rte_eth_xstats_get_by_group(), rte_eth_xstats_get_names_by_group(). Extension of the 'rte_igb_xstats_name_off' structure with additional field 'group_mask'. For each xstats there is now specified group (e.g. TX_GROUP), one xstatistic can be in several groups. To implement new functionality of retriving xstats by group on e1000 driver level, there are two functions added: eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group(), on ixgbe driver level, there are new functions added: ixgbe_dev_xstats_get_by_group() and ixgbe_dev_xstats_get_names_by_group() Extended functionality of proc_info application: --xstats-name NAME: to display single xstat value by NAME --xstats-group GROUPNAME: to display group of xstats by GROUPNAME Jacek Piasecki (4): ethdev: add retrieving xstats by group and xstats by name net/e1000: add grouping of xstats for e1000 driver net/ixgbe: add grouping of xstats for ixgbe driver app/proc_info: add support for xstats-name and xstats-group app/proc_info/main.c | 112 +++- drivers/net/e1000/igb_ethdev.c | 268 +- drivers/net/ixgbe/ixgbe_ethdev.c | 586 +++ lib/librte_ether/rte_ethdev.c| 310 - lib/librte_ether/rte_ethdev.h| 105 ++- 5 files changed, 1193 insertions(+), 188 deletions(-) -- 1.9.1
[dpdk-dev] [PATCH 1/4] ethdev: add retrieving xstats by group and xstats by name
From: Jacek Piasecki This patch extends library for retriving xstats by specified groups and single xstat by given name. Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- lib/librte_ether/rte_ethdev.c | 310 -- lib/librte_ether/rte_ethdev.h | 105 +- 2 files changed, 401 insertions(+), 14 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index eb0a94a..e18ca1d 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -87,33 +87,37 @@ struct rte_eth_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; + uint64_t group_mask; }; static const struct rte_eth_xstats_name_off rte_stats_strings[] = { - {"rx_good_packets", offsetof(struct rte_eth_stats, ipackets)}, - {"tx_good_packets", offsetof(struct rte_eth_stats, opackets)}, - {"rx_good_bytes", offsetof(struct rte_eth_stats, ibytes)}, - {"tx_good_bytes", offsetof(struct rte_eth_stats, obytes)}, - {"rx_errors", offsetof(struct rte_eth_stats, ierrors)}, - {"tx_errors", offsetof(struct rte_eth_stats, oerrors)}, + {"rx_good_packets", offsetof(struct rte_eth_stats, ipackets), RX_GROUP}, + {"tx_good_packets", offsetof(struct rte_eth_stats, opackets), TX_GROUP}, + {"rx_good_bytes", offsetof(struct rte_eth_stats, ibytes), RX_GROUP}, + {"tx_good_bytes", offsetof(struct rte_eth_stats, obytes), TX_GROUP}, + {"rx_errors", offsetof(struct rte_eth_stats, ierrors), + RX_GROUP | ERR_GROUP}, + {"tx_errors", offsetof(struct rte_eth_stats, oerrors), + TX_GROUP | ERR_GROUP}, {"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats, - rx_nombuf)}, + rx_nombuf), RX_GROUP | ERR_GROUP}, }; #define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0])) static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = { - {"packets", offsetof(struct rte_eth_stats, q_ipackets)}, - {"bytes", offsetof(struct rte_eth_stats, q_ibytes)}, - {"errors", offsetof(struct rte_eth_stats, q_errors)}, + {"packets", offsetof(struct rte_eth_stats, q_ipackets), RXQ_GROUP}, + {"bytes", offsetof(struct rte_eth_stats, q_ibytes), RXQ_GROUP}, + {"errors", offsetof(struct rte_eth_stats, q_errors), + RXQ_GROUP | ERR_GROUP}, }; #define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) / \ sizeof(rte_rxq_stats_strings[0])) static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = { - {"packets", offsetof(struct rte_eth_stats, q_opackets)}, - {"bytes", offsetof(struct rte_eth_stats, q_obytes)}, + {"packets", offsetof(struct rte_eth_stats, q_opackets), TXQ_GROUP}, + {"bytes", offsetof(struct rte_eth_stats, q_obytes), TXQ_GROUP}, }; #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \ sizeof(rte_txq_stats_strings[0])) @@ -1448,6 +1452,110 @@ struct rte_eth_dev * return count; } +static int +get_xstats_count_by_group(uint8_t port_id, uint64_t group_mask) +{ + struct rte_eth_dev *dev; + int count = 0; + int dcount = 0; + unsigned i; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + dev = &rte_eth_devices[port_id]; + if (dev->dev_ops->xstats_get_names_by_group != NULL) { + dcount = (*dev->dev_ops->xstats_get_names_by_group) + (dev, NULL, 0, group_mask); + if (dcount < 0) + return dcount; + } + + + + + for (i = 0; i < RTE_NB_STATS; i++) { + if (rte_stats_strings[i].group_mask & group_mask) + count++; + } + for (i = 0; i < RTE_NB_RXQ_STATS; i++) { + if (rte_rxq_stats_strings[i].group_mask & group_mask) + count += RTE_MIN(dev->data->nb_rx_queues, + RTE_ETHDEV_QUEUE_STAT_CNTRS); + } + for (i = 0; i < RTE_NB_TXQ_STATS; i++) { + if (rte_txq_stats_strings[i].group_mask & group_mask) + count += RTE_MIN(dev->data->nb_tx_queues, + RTE_ETHDEV_QUEUE_STAT_CNTRS); + } + return count+dcount; +} + +int +rte_eth_xstats_get_by_name(uint8_t port_id, struct rte_eth_xstat *xstat, + const char *name) +{ + struct rte_eth_xstat *xstats; + int cnt_xstats, idx_xstat; + struct rte_eth_xstat_name *xstats_names; + + + + /* Get count */ + cnt_xstats = rte_eth_xs
[dpdk-dev] [PATCH 3/4] net/ixgbe: add grouping of xstats for ixgbe driver
From: Jacek Piasecki This patch extends the 'rte_ixgbe_xstats_name_off' structure with additional field 'group_mask'. For each xstats there is now specified group (e.g. MAC_GROUP), one xstatistic can be in several groups. To implement new functionality of retriving xstats by group on driver level, there are two functions added: ixgbe_dev_xstats_get_by_group() and ixgbe_dev_xstats_get_names_by_group() Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- drivers/net/ixgbe/ixgbe_ethdev.c | 586 +++ 1 file changed, 475 insertions(+), 111 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 7169007..31aa4e2 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -124,7 +124,8 @@ #define IXGBEVF_PMD_NAME "rte_ixgbevf_pmd" /* PMD name */ -#define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) / sizeof(hw_stats->qprc[0])) +#define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) \ + / sizeof(hw_stats->qprc[0])) #define IXGBE_HKEY_MAX_INDEX 10 @@ -187,12 +188,25 @@ static void ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); +static int ixgbe_dev_xstats_get_by_group(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, + unsigned n, uint64_t group_mask); static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev); static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev); +static int ixgbe_xstats_get_by_name(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + struct rte_eth_xstat *xstat, + const char *name); static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit); +static +int ixgbe_dev_xstats_get_names_by_group(__rte_unused + struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + unsigned limit, + uint64_t group_mask); static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit); static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev, @@ -532,10 +546,13 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, .link_update = ixgbe_dev_link_update, .stats_get= ixgbe_dev_stats_get, .xstats_get = ixgbe_dev_xstats_get, + .xstats_get_by_name = ixgbe_xstats_get_by_name, + .xstats_get_by_group = ixgbe_dev_xstats_get_by_group, .stats_reset = ixgbe_dev_stats_reset, .xstats_reset = ixgbe_dev_xstats_reset, .xstats_get_names = ixgbe_dev_xstats_get_names, .queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set, + .xstats_get_names_by_group = ixgbe_dev_xstats_get_names_by_group, .fw_version_get = ixgbe_fw_version_get, .dev_infos_get= ixgbe_dev_info_get, .dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get, @@ -653,87 +670,125 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, struct rte_ixgbe_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; + uint64_t group_mask; }; static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = { - {"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)}, - {"rx_illegal_byte_errors", offsetof(struct ixgbe_hw_stats, illerrc)}, - {"rx_error_bytes", offsetof(struct ixgbe_hw_stats, errbc)}, - {"mac_local_errors", offsetof(struct ixgbe_hw_stats, mlfc)}, - {"mac_remote_errors", offsetof(struct ixgbe_hw_stats, mrfc)}, - {"rx_length_errors", offsetof(struct ixgbe_hw_stats, rlec)}, - {"tx_xon_packets", offsetof(struct ixgbe_hw_stats, lxontxc)}, - {"rx_xon_packets", offsetof(struct ixgbe_hw_stats, lxonrxc)}, - {"tx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxofftxc)}, - {"rx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxoffrxc)}, - {"rx_size_64_packets", offsetof(struct ixgbe_hw_stats, prc64)}, - {"rx_size_65_to_127_packets", offsetof(struct ixgbe_hw_stats, prc127)}, - {"rx_size_128_to_255_packets", offsetof(struct ixgbe_hw_stats, prc255)}, - {"rx_size_256_to_511_packets", offsetof(struct ixgbe_hw_stats, prc511)},
[dpdk-dev] [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver
From: Jacek Piasecki This patch extends the 'rte_igb_xstats_name_off' structure with additional field 'group_mask'. For each xstats there is now specified group (e.g. TX_GROUP), one xstatistic can be in several groups. To implement new functionality of retriving xstats by group on driver level, there are two functions added: eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group() Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- drivers/net/e1000/igb_ethdev.c | 268 +++-- 1 file changed, 206 insertions(+), 62 deletions(-) diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index a112b38..8057b6f 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -115,9 +115,18 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static int eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); +static +int eth_igb_xstats_get_by_group(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, + unsigned n, uint64_t group_mask); static int eth_igb_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); +static int +eth_igb_xstats_get_names_by_group(__rte_unused struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + __rte_unused unsigned limit, + uint64_t group_mask); static void eth_igb_stats_reset(struct rte_eth_dev *dev); static void eth_igb_xstats_reset(struct rte_eth_dev *dev); static int eth_igb_fw_version_get(struct rte_eth_dev *dev, @@ -390,7 +399,9 @@ static void eth_igbvf_interrupt_handler(struct rte_intr_handle *handle, .link_update = eth_igb_link_update, .stats_get= eth_igb_stats_get, .xstats_get = eth_igb_xstats_get, + .xstats_get_by_group = eth_igb_xstats_get_by_group, .xstats_get_names = eth_igb_xstats_get_names, + .xstats_get_names_by_group = eth_igb_xstats_get_names_by_group, .stats_reset = eth_igb_stats_reset, .xstats_reset = eth_igb_xstats_reset, .fw_version_get = eth_igb_fw_version_get, @@ -473,78 +484,128 @@ static void eth_igbvf_interrupt_handler(struct rte_intr_handle *handle, struct rte_igb_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; + uint64_t group_mask; }; static const struct rte_igb_xstats_name_off rte_igb_stats_strings[] = { - {"rx_crc_errors", offsetof(struct e1000_hw_stats, crcerrs)}, - {"rx_align_errors", offsetof(struct e1000_hw_stats, algnerrc)}, - {"rx_symbol_errors", offsetof(struct e1000_hw_stats, symerrs)}, - {"rx_missed_packets", offsetof(struct e1000_hw_stats, mpc)}, - {"tx_single_collision_packets", offsetof(struct e1000_hw_stats, scc)}, - {"tx_multiple_collision_packets", offsetof(struct e1000_hw_stats, mcc)}, + {"rx_crc_errors", offsetof(struct e1000_hw_stats, crcerrs), + RX_GROUP | ERR_GROUP}, + {"rx_align_errors", offsetof(struct e1000_hw_stats, algnerrc), + RX_GROUP | ERR_GROUP}, + {"rx_symbol_errors", offsetof(struct e1000_hw_stats, symerrs), + RX_GROUP | ERR_GROUP}, + {"rx_missed_packets", offsetof(struct e1000_hw_stats, mpc), + RX_GROUP}, + {"tx_single_collision_packets", offsetof(struct e1000_hw_stats, scc), + TX_GROUP}, + {"tx_multiple_collision_packets", offsetof(struct e1000_hw_stats, mcc), + TX_GROUP}, {"tx_excessive_collision_packets", offsetof(struct e1000_hw_stats, - ecol)}, - {"tx_late_collisions", offsetof(struct e1000_hw_stats, latecol)}, - {"tx_total_collisions", offsetof(struct e1000_hw_stats, colc)}, - {"tx_deferred_packets", offsetof(struct e1000_hw_stats, dc)}, - {"tx_no_carrier_sense_packets", offsetof(struct e1000_hw_stats, tncrs)}, - {"rx_carrier_ext_errors", offsetof(struct e1000_hw_stats, cexterr)}, - {"rx_length_errors", offsetof(struct e1000_hw_stats, rlec)}, - {"rx_xon_packets", offsetof(struct e1000_hw_stats, xonrxc)}, - {"tx_xon_packets", offsetof(struct e1000_hw_stats, xontxc)}, - {"rx_xoff_packets", offsetof(struct e1000_hw_stats, xoffrxc)}, - {"tx_xoff_packets", offsetof(struct e1000_hw_stats, xofftxc)}, + ecol), TX_GROUP}, + {"tx_late_collisions", offsetof(struct e1000_hw
[dpdk-dev] [PATCH 0/4] extend API to retriving xstats by group and xstats by name
Added three new functions to API: rte_eth_xstats_get_by_name(), rte_eth_xstats_get_by_group(), rte_eth_xstats_get_names_by_group(). Extension of the 'rte_igb_xstats_name_off' structure with additional field 'group_mask'. For each xstats there is now specified group (e.g. TX_GROUP), one xstatistic can be in several groups. To implement new functionality of retriving xstats by group on e1000 driver level, there are two functions added: eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group(), on ixgbe driver level, there are new functions added: ixgbe_dev_xstats_get_by_group() and ixgbe_dev_xstats_get_names_by_group() Extended functionality of proc_info application: --xstats-name NAME: to display single xstat value by NAME --xstats-group GROUPNAME: to display group of xstats by GROUPNAME Jacek Piasecki (4): ethdev: add retrieving xstats by group and xstats by name net/e1000: add grouping of xstats for e1000 driver net/ixgbe: add grouping of xstats for ixgbe driver app/proc_info: add support for xstats-name and xstats-group app/proc_info/main.c | 112 - drivers/net/e1000/igb_ethdev.c | 261 +++- drivers/net/ixgbe/ixgbe_ethdev.c | 496 +++ lib/librte_ether/rte_ethdev.c| 310 +++- lib/librte_ether/rte_ethdev.h| 105 - 5 files changed, 1114 insertions(+), 170 deletions(-) -- 1.9.1
[dpdk-dev] [PATCH 1/4] ethdev: add retrieving xstats by group and xstats by name
From: Jacek Piasecki This patch extends library for retriving xstats by specified groups and single xstat by given name. Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- lib/librte_ether/rte_ethdev.c | 310 -- lib/librte_ether/rte_ethdev.h | 105 +- 2 files changed, 401 insertions(+), 14 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index eb0a94a..aad8913 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -87,33 +87,37 @@ struct rte_eth_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; + uint64_t group_mask; }; static const struct rte_eth_xstats_name_off rte_stats_strings[] = { - {"rx_good_packets", offsetof(struct rte_eth_stats, ipackets)}, - {"tx_good_packets", offsetof(struct rte_eth_stats, opackets)}, - {"rx_good_bytes", offsetof(struct rte_eth_stats, ibytes)}, - {"tx_good_bytes", offsetof(struct rte_eth_stats, obytes)}, - {"rx_errors", offsetof(struct rte_eth_stats, ierrors)}, - {"tx_errors", offsetof(struct rte_eth_stats, oerrors)}, + {"rx_good_packets", offsetof(struct rte_eth_stats, ipackets), RX_GROUP}, + {"tx_good_packets", offsetof(struct rte_eth_stats, opackets), TX_GROUP}, + {"rx_good_bytes", offsetof(struct rte_eth_stats, ibytes), RX_GROUP}, + {"tx_good_bytes", offsetof(struct rte_eth_stats, obytes), TX_GROUP}, + {"rx_errors", offsetof(struct rte_eth_stats, ierrors), + RX_GROUP | ERR_GROUP}, + {"tx_errors", offsetof(struct rte_eth_stats, oerrors), + TX_GROUP | ERR_GROUP}, {"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats, - rx_nombuf)}, + rx_nombuf), RX_GROUP | ERR_GROUP}, }; #define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0])) static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = { - {"packets", offsetof(struct rte_eth_stats, q_ipackets)}, - {"bytes", offsetof(struct rte_eth_stats, q_ibytes)}, - {"errors", offsetof(struct rte_eth_stats, q_errors)}, + {"packets", offsetof(struct rte_eth_stats, q_ipackets), RXQ_GROUP}, + {"bytes", offsetof(struct rte_eth_stats, q_ibytes), RXQ_GROUP}, + {"errors", offsetof(struct rte_eth_stats, q_errors), + RXQ_GROUP | ERR_GROUP}, }; #define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) / \ sizeof(rte_rxq_stats_strings[0])) static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = { - {"packets", offsetof(struct rte_eth_stats, q_opackets)}, - {"bytes", offsetof(struct rte_eth_stats, q_obytes)}, + {"packets", offsetof(struct rte_eth_stats, q_opackets), TXQ_GROUP}, + {"bytes", offsetof(struct rte_eth_stats, q_obytes), TXQ_GROUP}, }; #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \ sizeof(rte_txq_stats_strings[0])) @@ -1448,6 +1452,110 @@ struct rte_eth_dev * return count; } +static int +get_xstats_count_by_group(uint8_t port_id, uint64_t group_mask) +{ + struct rte_eth_dev *dev; + int count = 0; + int dcount = 0; + unsigned int i; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + dev = &rte_eth_devices[port_id]; + if (dev->dev_ops->xstats_get_names_by_group != NULL) { + dcount = (*dev->dev_ops->xstats_get_names_by_group) + (dev, NULL, 0, group_mask); + if (dcount < 0) + return dcount; + } + + + + + for (i = 0; i < RTE_NB_STATS; i++) { + if (rte_stats_strings[i].group_mask & group_mask) + count++; + } + for (i = 0; i < RTE_NB_RXQ_STATS; i++) { + if (rte_rxq_stats_strings[i].group_mask & group_mask) + count += RTE_MIN(dev->data->nb_rx_queues, + RTE_ETHDEV_QUEUE_STAT_CNTRS); + } + for (i = 0; i < RTE_NB_TXQ_STATS; i++) { + if (rte_txq_stats_strings[i].group_mask & group_mask) + count += RTE_MIN(dev->data->nb_tx_queues, + RTE_ETHDEV_QUEUE_STAT_CNTRS); + } + return count+dcount; +} + +int +rte_eth_xstats_get_by_name(uint8_t port_id, struct rte_eth_xstat *xstat, + const char *name) +{ + struct rte_eth_xstat *xstats; + int cnt_xstats, idx_xstat; + struct rte_eth_xstat_name *xstats_names; + + + + /* Get count */ + cnt_xstat
[dpdk-dev] [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver
From: Jacek Piasecki This patch extends the 'rte_igb_xstats_name_off' structure with additional field 'group_mask'. For each xstats there is now specified group (e.g. TX_GROUP), one xstatistic can be in several groups. To implement new functionality of retriving xstats by group on driver level, there are two functions added: eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group() Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- drivers/net/e1000/igb_ethdev.c | 261 +++-- 1 file changed, 199 insertions(+), 62 deletions(-) diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index a112b38..28eced6 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -115,9 +115,18 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static int eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); +static +int eth_igb_xstats_get_by_group(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, + unsigned int n, uint64_t group_mask); static int eth_igb_xstats_get_names(struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, unsigned limit); +static int +eth_igb_xstats_get_names_by_group(__rte_unused struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + __rte_unused unsigned int limit, + uint64_t group_mask); static void eth_igb_stats_reset(struct rte_eth_dev *dev); static void eth_igb_xstats_reset(struct rte_eth_dev *dev); static int eth_igb_fw_version_get(struct rte_eth_dev *dev, @@ -390,7 +399,9 @@ static void eth_igbvf_interrupt_handler(struct rte_intr_handle *handle, .link_update = eth_igb_link_update, .stats_get= eth_igb_stats_get, .xstats_get = eth_igb_xstats_get, + .xstats_get_by_group = eth_igb_xstats_get_by_group, .xstats_get_names = eth_igb_xstats_get_names, + .xstats_get_names_by_group = eth_igb_xstats_get_names_by_group, .stats_reset = eth_igb_stats_reset, .xstats_reset = eth_igb_xstats_reset, .fw_version_get = eth_igb_fw_version_get, @@ -473,78 +484,128 @@ static void eth_igbvf_interrupt_handler(struct rte_intr_handle *handle, struct rte_igb_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; + uint64_t group_mask; }; static const struct rte_igb_xstats_name_off rte_igb_stats_strings[] = { - {"rx_crc_errors", offsetof(struct e1000_hw_stats, crcerrs)}, - {"rx_align_errors", offsetof(struct e1000_hw_stats, algnerrc)}, - {"rx_symbol_errors", offsetof(struct e1000_hw_stats, symerrs)}, - {"rx_missed_packets", offsetof(struct e1000_hw_stats, mpc)}, - {"tx_single_collision_packets", offsetof(struct e1000_hw_stats, scc)}, - {"tx_multiple_collision_packets", offsetof(struct e1000_hw_stats, mcc)}, + {"rx_crc_errors", offsetof(struct e1000_hw_stats, crcerrs), + RX_GROUP | ERR_GROUP}, + {"rx_align_errors", offsetof(struct e1000_hw_stats, algnerrc), + RX_GROUP | ERR_GROUP}, + {"rx_symbol_errors", offsetof(struct e1000_hw_stats, symerrs), + RX_GROUP | ERR_GROUP}, + {"rx_missed_packets", offsetof(struct e1000_hw_stats, mpc), + RX_GROUP}, + {"tx_single_collision_packets", offsetof(struct e1000_hw_stats, scc), + TX_GROUP}, + {"tx_multiple_collision_packets", offsetof(struct e1000_hw_stats, mcc), + TX_GROUP}, {"tx_excessive_collision_packets", offsetof(struct e1000_hw_stats, - ecol)}, - {"tx_late_collisions", offsetof(struct e1000_hw_stats, latecol)}, - {"tx_total_collisions", offsetof(struct e1000_hw_stats, colc)}, - {"tx_deferred_packets", offsetof(struct e1000_hw_stats, dc)}, - {"tx_no_carrier_sense_packets", offsetof(struct e1000_hw_stats, tncrs)}, - {"rx_carrier_ext_errors", offsetof(struct e1000_hw_stats, cexterr)}, - {"rx_length_errors", offsetof(struct e1000_hw_stats, rlec)}, - {"rx_xon_packets", offsetof(struct e1000_hw_stats, xonrxc)}, - {"tx_xon_packets", offsetof(struct e1000_hw_stats, xontxc)}, - {"rx_xoff_packets", offsetof(struct e1000_hw_stats, xoffrxc)}, - {"tx_xoff_packets", offsetof(struct e1000_hw_stats, xofftxc)}, + ecol), TX_GROUP}, + {"tx_late_collisions", offsetof(struct e1000_hw
[dpdk-dev] [PATCH 3/4] net/ixgbe: add grouping of xstats for ixgbe driver
From: Jacek Piasecki This patch extends the 'rte_ixgbe_xstats_name_off' structure with additional field 'group_mask'. For each xstats there is now specified group (e.g. MAC_GROUP), one xstatistic can be in several groups. To implement new functionality of retriving xstats by group on driver level, there are two functions added: ixgbe_dev_xstats_get_by_group() and ixgbe_dev_xstats_get_names_by_group() Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- drivers/net/ixgbe/ixgbe_ethdev.c | 496 +++ 1 file changed, 403 insertions(+), 93 deletions(-) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 7169007..69731ce 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -124,7 +124,8 @@ #define IXGBEVF_PMD_NAME "rte_ixgbevf_pmd" /* PMD name */ -#define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) / sizeof(hw_stats->qprc[0])) +#define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) \ + / sizeof(hw_stats->qprc[0])) #define IXGBE_HKEY_MAX_INDEX 10 @@ -187,12 +188,25 @@ static void ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats); static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); +static int ixgbe_dev_xstats_get_by_group(struct rte_eth_dev *dev, + struct rte_eth_xstat *xstats, + unsigned int n, uint64_t group_mask); static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev); static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev); +static int ixgbe_xstats_get_by_name(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + struct rte_eth_xstat *xstat, + const char *name); static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit); +static +int ixgbe_dev_xstats_get_names_by_group(__rte_unused + struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + unsigned int limit, + uint64_t group_mask); static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit); static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev, @@ -532,10 +546,13 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, .link_update = ixgbe_dev_link_update, .stats_get= ixgbe_dev_stats_get, .xstats_get = ixgbe_dev_xstats_get, + .xstats_get_by_name = ixgbe_xstats_get_by_name, + .xstats_get_by_group = ixgbe_dev_xstats_get_by_group, .stats_reset = ixgbe_dev_stats_reset, .xstats_reset = ixgbe_dev_xstats_reset, .xstats_get_names = ixgbe_dev_xstats_get_names, .queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set, + .xstats_get_names_by_group = ixgbe_dev_xstats_get_names_by_group, .fw_version_get = ixgbe_fw_version_get, .dev_infos_get= ixgbe_dev_info_get, .dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get, @@ -653,87 +670,118 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, struct rte_ixgbe_xstats_name_off { char name[RTE_ETH_XSTATS_NAME_SIZE]; unsigned offset; + uint64_t group_mask; }; static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = { - {"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)}, - {"rx_illegal_byte_errors", offsetof(struct ixgbe_hw_stats, illerrc)}, - {"rx_error_bytes", offsetof(struct ixgbe_hw_stats, errbc)}, - {"mac_local_errors", offsetof(struct ixgbe_hw_stats, mlfc)}, - {"mac_remote_errors", offsetof(struct ixgbe_hw_stats, mrfc)}, - {"rx_length_errors", offsetof(struct ixgbe_hw_stats, rlec)}, - {"tx_xon_packets", offsetof(struct ixgbe_hw_stats, lxontxc)}, - {"rx_xon_packets", offsetof(struct ixgbe_hw_stats, lxonrxc)}, - {"tx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxofftxc)}, - {"rx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxoffrxc)}, - {"rx_size_64_packets", offsetof(struct ixgbe_hw_stats, prc64)}, - {"rx_size_65_to_127_packets", offsetof(struct ixgbe_hw_stats, prc127)}, - {"rx_size_128_to_255_packets", offsetof(struct ixgbe_hw_stats, prc255)}, - {"rx_size_256_to_511_packets", offseto
[dpdk-dev] [PATCH 4/4] app/proc_info: add support for xstats-name and xstats-group
From: Jacek Piasecki This patch provides support for proc_info application to allow printing single xstat value specified by its name and printing xstats values specified by its group name. New proc_info arguments: --xstats-name NAME: to display single xstat value by NAME --xstats-group GROUPNAME: to display group of xstats by GROUPNAME Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- app/proc_info/main.c | 112 ++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..8826090 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -74,6 +74,11 @@ static uint32_t reset_xstats; /**< Enable memory info. */ static uint32_t mem_info; +/**< Enable displaying xstat name. */ +static uint32_t enable_xstats_name; +static char *xstats_name; +/**< Enable displaying xstat group name. */ +static uint64_t enable_xstats_group; /**< display usage */ static void @@ -85,6 +90,8 @@ " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --xstats-name NAME: to display single xstat value by NAME\n" + " --xstats-group GROUPNAME: to display group of xstats by GROUPNAME\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -128,6 +135,8 @@ {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, + {"xstats-name", required_argument, NULL, 1}, + {"xstats-group", required_argument, NULL, 1}, {NULL, 0, 0, 0} }; @@ -168,7 +177,27 @@ MAX_LONG_OPT_SZ)) reset_xstats = 1; break; - + case 1: + /* Print xstat single value given by name*/ + if (!strncmp(long_option[option_index].name, + "xstats-name", + MAX_LONG_OPT_SZ)) { + enable_xstats_name = 1; + xstats_name = optarg; + printf("name:%s:%s\n", + long_option[option_index].name, + optarg); + } + /* Print xstat group values given by group name*/ + else if (!strncmp(long_option[option_index].name, + "xstats-group", + MAX_LONG_OPT_SZ)) { + enable_xstats_group = atoi(optarg); + printf("name:%s:%s\n", + long_option[option_index].name, + optarg); + } + break; default: proc_info_usage(prgname); return -1; @@ -241,6 +270,82 @@ } static void +nic_xstats_by_name_display(__rte_unused uint8_t port_id, + __rte_unused char *name) +{ + struct rte_eth_xstat xstat; + + printf("## NIC statistics for port %-2d, statistic name '%s':\n", + port_id, name); + + if (rte_eth_xstats_get_by_name(port_id, &xstat, name) == 0) + printf("%s: %"PRIu64"\n", name, xstat.value); + else + printf("Statistic not found...\n"); + +} + +static void +nic_xstats_by_group_display(__rte_unused uint8_t port_id, + __rte_unused uint64_t group_mask) +{ + struct rte_eth_xstat *xstats; + int cnt_xstats, idx_xstat; + struct rte_eth_xstat_name *xstats_names; + + printf("## NIC extended statistics for port %-2d," + " group %-2lu #\n", + port_id, group_mask); + + /* Get count */ + cnt_xstats = rte_eth_xstats_get_names_by_group(port_id, NULL, 0, + group_mask); + if (cnt_xstats < 0) { + printf("Error: Cannot get count of xstats\n"); + return; + } + + /* Get id-name lookup table */ + xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats); + if (xstats_names == NULL) { + printf("Cannot allocate memory for xstats
[dpdk-dev] [PATCH v6 0/5] Extended xstats API in ethdev library to allow grouping of stats
Extended xstats API in ethdev library to allow grouping of stats logically so they can be retrieved per logical grouping managed by the application. Changed existing functions rte_eth_xstats_get_names and rte_eth_xstats_get to use a new list of arguments: array of ids and array of values. ABI versioning mechanism was used to support backward compatibility. Introduced two new functions rte_eth_xstats_get_all and rte_eth_xstats_get_names_all which keeps functionality of the previous ones (respectively rte_eth_xstats_get and rte_eth_xstats_get_names) but use new API inside. Both functions marked as deprecated. Introduced new function: rte_eth_xstats_get_id_by_name to retrieve xstats ids by its names. Extended functionality of proc_info application: --xstats-name NAME: to display single xstat value by NAME Updated test-pmd application to use new API. v6 changes: * patches arrangement in patchset * fixes spelling bugs * release notes v5 changes: * fix clang shared build compilation * remove wrong versioning macros * Makefile LIBABIVER 6 change v4 changes: * documentation change after API modification * fix xstats display for PMD without _by_ids() functions * fix ABI validator errors v3 changes: * checkpatch fixes * removed malloc bug in ethdev * add new command to proc_info and IDs parsing * merged testpmd and proc_info patch with library patch Jacek Piasecki (3): ethdev: new xstats API add retrieving by ID net/e1000: new xstats API add ID support for e1000 net/ixgbe: new xstats API add ID support for ixgbe Kuba Kozak (2): ethdev: added new function for xstats ID proc-info: add support for new xstats API app/proc_info/main.c| 148 ++- app/test-pmd/config.c | 19 +- doc/guides/prog_guide/poll_mode_drv.rst | 173 +++-- doc/guides/rel_notes/release_17_05.rst | 8 + drivers/net/e1000/igb_ethdev.c | 92 ++- drivers/net/ixgbe/ixgbe_ethdev.c| 179 + lib/librte_ether/rte_ethdev.c | 430 lib/librte_ether/rte_ethdev.h | 167 - lib/librte_ether/rte_ether_version.map | 5 + 9 files changed, 1070 insertions(+), 151 deletions(-) -- 1.9.1
[dpdk-dev] [PATCH v6 1/5] ethdev: new xstats API add retrieving by ID
From: Jacek Piasecki Extended xstats API in ethdev library to allow grouping of stats logically so they can be retrieved per logical grouping managed by the application. Changed existing functions rte_eth_xstats_get_names and rte_eth_xstats_get to use a new list of arguments: array of ids and array of values. ABI versioning mechanism was used to support backward compatibility. Introduced two new functions rte_eth_xstats_get_all and rte_eth_xstats_get_names_all which keeps functionality of the previous ones (respectively rte_eth_xstats_get and rte_eth_xstats_get_names) but use new API inside. test-pmd: add support for new xstats API retrieving by id in testpmd application: xstats_get() and xstats_get_names() call with modified parameters. doc: add description for modified xstats API Documentation change for modified extended statistics API functions. The old API only allows retrieval of *all* of the NIC statistics at once. Given this requires a MMIO read PCI transaction per statistic it is an inefficient way of retrieving just a few key statistics. Often a monitoring agent only has an interest in a few key statistics, and the old API forces wasting CPU time and PCIe bandwidth in retrieving *all* statistics; even those that the application didn't explicitly show an interest in. The new, more flexible API allow retrieval of statistics per ID. If a PMD wishes, it can be implemented to read just the required NIC registers. As a result, the monitoring application no longer wastes PCIe bandwidth and CPU time. Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak Signed-off-by: Tomasz Kulasek --- app/proc_info/main.c| 6 +- app/test-pmd/config.c | 19 +- doc/guides/prog_guide/poll_mode_drv.rst | 173 -- doc/guides/rel_notes/release_17_05.rst | 6 + lib/librte_ether/rte_ethdev.c | 386 +++- lib/librte_ether/rte_ethdev.h | 144 +++- lib/librte_ether/rte_ether_version.map | 4 + 7 files changed, 596 insertions(+), 142 deletions(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index d576b42..9f5e219 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -358,7 +358,7 @@ static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len, int len, ret, i; static const char *nic_stats_border = ""; - len = rte_eth_xstats_get_names(port_id, NULL, 0); + len = rte_eth_xstats_get_names_all(port_id, NULL, 0); if (len < 0) { printf("Cannot get xstats count\n"); return; @@ -375,7 +375,7 @@ static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len, free(xstats); return; } - if (len != rte_eth_xstats_get_names( + if (len != rte_eth_xstats_get_names_all( port_id, xstats_names, len)) { printf("Cannot get xstat names\n"); goto err; @@ -385,7 +385,7 @@ static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len, port_id); printf("%s\n", nic_stats_border); - ret = rte_eth_xstats_get(port_id, xstats, len); + ret = rte_eth_xstats_get_all(port_id, xstats, len); if (ret < 0 || ret > len) { printf("Cannot get xstats\n"); goto err; diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index 4d873cd..ef07925 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -264,9 +264,9 @@ struct rss_type_info { void nic_xstats_display(portid_t port_id) { - struct rte_eth_xstat *xstats; int cnt_xstats, idx_xstat; struct rte_eth_xstat_name *xstats_names; + uint64_t *values; printf("## NIC extended statistics for port %-2d\n", port_id); if (!rte_eth_dev_is_valid_port(port_id)) { @@ -275,7 +275,7 @@ struct rss_type_info { } /* Get count */ - cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0); + cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0, NULL); if (cnt_xstats < 0) { printf("Error: Cannot get count of xstats\n"); return; @@ -288,23 +288,24 @@ struct rss_type_info { return; } if (cnt_xstats != rte_eth_xstats_get_names( - port_id, xstats_names, cnt_xstats)) { + port_id, xstats_names, cnt_xstats, NULL)) { printf("Error: Cannot get xstats lookup\n"); free(xstats_names); return; } /* Get stats themselves */ - xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats); - if (xstats == NULL) { + values = malloc(sizeof(values) * cnt_x
[dpdk-dev] [PATCH v6 2/5] ethdev: added new function for xstats ID
Introduced new function: rte_eth_xstats_get_id_by_name to retrieve xstats ids by its names. doc: added release note Signed-off-by: Kuba Kozak --- doc/guides/rel_notes/release_17_05.rst | 2 ++ lib/librte_ether/rte_ethdev.c | 44 ++ lib/librte_ether/rte_ethdev.h | 21 lib/librte_ether/rte_ether_version.map | 1 + 4 files changed, 68 insertions(+) diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst index 5b77226..dae4261 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -423,6 +423,8 @@ API Changes * Added new functions ``rte_eth_xstats_get_all`` and ``rte_eth_xstats_get_names_all to provide backward compatibility for ``rte_eth_xstats_get`` and ``rte_eth_xstats_get_names`` + * Added new function ``rte_eth_xstats_get_id_by_name`` + ABI Changes --- diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 0adc1d0..ef30883 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1476,6 +1476,50 @@ struct rte_eth_dev * } int +rte_eth_xstats_get_id_by_name(uint8_t port_id, const char *xstat_name, + uint64_t *id) +{ + int cnt_xstats, idx_xstat; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + + if (!id) { + RTE_PMD_DEBUG_TRACE("Error: id pointer is NULL\n"); + return -1; + } + + if (!xstat_name) { + RTE_PMD_DEBUG_TRACE("Error: xstat_name pointer is NULL\n"); + return -1; + } + + /* Get count */ + cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0, NULL); + if (cnt_xstats < 0) { + RTE_PMD_DEBUG_TRACE("Error: Cannot get count of xstats\n"); + return -1; + } + + /* Get id-name lookup table */ + struct rte_eth_xstat_name xstats_names[cnt_xstats]; + + if (cnt_xstats != rte_eth_xstats_get_names( + port_id, xstats_names, cnt_xstats, NULL)) { + RTE_PMD_DEBUG_TRACE("Error: Cannot get xstats lookup\n"); + return -1; + } + + for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) { + if (!strcmp(xstats_names[idx_xstat].name, xstat_name)) { + *id = idx_xstat; + return 0; + }; + } + + return -EINVAL; +} + +int rte_eth_xstats_get_names_v1607(uint8_t port_id, struct rte_eth_xstat_name *xstats_names, unsigned int size) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 8c94b88..058c435 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -2346,6 +2346,27 @@ int rte_eth_tx_queue_setup(uint8_t port_id, uint16_t tx_queue_id, */ void rte_eth_stats_reset(uint8_t port_id); + +/** + * Gets the ID of a statistic from its name. + * + * This function searches for the statistics using string compares, and + * as such should not be used on the fast-path. For fast-path retrieval of + * specific statistics, store the ID as provided in *id* from this function, + * and pass the ID to rte_eth_xstats_get() + * + * @param port_id The port to look up statistics from + * @param xstat_name The name of the statistic to return + * @param[out] id A pointer to an app-supplied uint64_t which should be + *set to the ID of the stat if the stat exists. + * @return + *0 on success + *-ENODEV for invalid port_id, + *-EINVAL if the xstat_name doesn't exist in port_id + */ +int rte_eth_xstats_get_id_by_name(uint8_t port_id, const char *xstat_name, + uint64_t *id); + /** * Retrieve all extended statistics of an Ethernet device. * diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map index a404434..7c41617 100644 --- a/lib/librte_ether/rte_ether_version.map +++ b/lib/librte_ether/rte_ether_version.map @@ -161,6 +161,7 @@ DPDK_17.05 { rte_eth_find_next; rte_eth_xstats_get; rte_eth_xstats_get_all; + rte_eth_xstats_get_id_by_name; rte_eth_xstats_get_names; rte_eth_xstats_get_names_all; -- 1.9.1
[dpdk-dev] [PATCH v6 3/5] proc-info: add support for new xstats API
There is a new argument --xstats-ids and --xstats-name in proc_info command line to retrieve statistics given by ids and by name. E.g. --xstats-ids="1,3,5,7,8" E.g. --xstats-name rx_errors ethdev: mark functions as deprecated Functions rte_eth_xstats_get_all and rte_eth_xstats_get_names_all are marked as deprecated Signed-off-by: Kuba Kozak --- app/proc_info/main.c | 150 ++ lib/librte_ether/rte_ethdev.c | 4 +- lib/librte_ether/rte_ethdev.h | 2 + 3 files changed, 143 insertions(+), 13 deletions(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 9f5e219..9c9b2b5 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -86,6 +86,14 @@ static uint32_t reset_xstats; /**< Enable memory info. */ static uint32_t mem_info; +/**< Enable displaying xstat name. */ +static uint32_t enable_xstats_name; +static char *xstats_name; + +/**< Enable xstats by ids. */ +#define MAX_NB_XSTATS_IDS 1024 +static uint32_t nb_xstats_ids; +static uint64_t xstats_ids[MAX_NB_XSTATS_IDS]; /**< display usage */ static void @@ -99,6 +107,9 @@ "default\n" " --metrics: to display derived metrics of the ports, disabled by " "default\n" + " --xstats-name NAME: to display single xstat value by NAME\n" + " --xstats-ids IDLIST: to display xstat values by id. " + "The argument is comma-separated list of xstat ids to print out.\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n" " --collectd-format: to print statistics to STDOUT in expected by collectd format\n" @@ -132,6 +143,33 @@ } +/* + * Parse ids value list into array + */ +static int +parse_xstats_ids(char *list, uint64_t *ids, int limit) { + int length; + char *token; + char *ctx = NULL; + char *endptr; + + length = 0; + token = strtok_r(list, ",", &ctx); + while (token != NULL) { + ids[length] = strtoull(token, &endptr, 10); + if (*endptr != '\0') + return -EINVAL; + + length++; + if (length >= limit) + return -E2BIG; + + token = strtok_r(NULL, ",", &ctx); + } + + return length; +} + static int proc_info_preparse_args(int argc, char **argv) { @@ -178,7 +216,9 @@ {"xstats", 0, NULL, 0}, {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, + {"xstats-name", required_argument, NULL, 1}, {"collectd-format", 0, NULL, 0}, + {"xstats-ids", 1, NULL, 1}, {"host-id", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -224,7 +264,28 @@ MAX_LONG_OPT_SZ)) reset_xstats = 1; break; + case 1: + /* Print xstat single value given by name*/ + if (!strncmp(long_option[option_index].name, + "xstats-name", MAX_LONG_OPT_SZ)) { + enable_xstats_name = 1; + xstats_name = optarg; + printf("name:%s:%s\n", + long_option[option_index].name, + optarg); + } else if (!strncmp(long_option[option_index].name, + "xstats-ids", + MAX_LONG_OPT_SZ)) { + nb_xstats_ids = parse_xstats_ids(optarg, + xstats_ids, MAX_NB_XSTATS_IDS); + + if (nb_xstats_ids <= 0) { + printf("xstats-id list parse error.\n"); + return -1; + } + } + break; default: proc_info_usage(prgname); return -1; @@ -351,20 +412,82 @@ static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len, } static void +nic_xstats_by_name_display(uint8_t port_id, char *name) +{ + uint64_t id; + + printf("## NIC statistics for port %-2d, statistic name '%s':\n", + port_id, name); + + if (rte_eth_xstats_get_id_by_name(port_id, name, &id) == 0) +
[dpdk-dev] [PATCH v6 4/5] net/e1000: new xstats API add ID support for e1000
From: Jacek Piasecki To achieve functionality of retrieving only specific statistics given by application there are two new functions added: eth_igb_xstats_get_by_ids() which retrieve values of statistics specified by ids array and eth_igb_xstats_get_names_by_ids() which retrieve names of statistics specified by ids array. Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- drivers/net/e1000/igb_ethdev.c | 92 +- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index cc2c244..8fed210 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -115,9 +115,13 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats); static int eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); +static int eth_igb_xstats_get_by_ids(struct rte_eth_dev *dev, uint64_t *ids, + uint64_t *values, unsigned int n); static int eth_igb_xstats_get_names(struct rte_eth_dev *dev, - struct rte_eth_xstat_name *xstats_names, - unsigned limit); + struct rte_eth_xstat_name *xstats_names, unsigned int limit); +static int eth_igb_xstats_get_names_by_ids(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, uint64_t *ids, + unsigned int limit); static void eth_igb_stats_reset(struct rte_eth_dev *dev); static void eth_igb_xstats_reset(struct rte_eth_dev *dev); static int eth_igb_fw_version_get(struct rte_eth_dev *dev, @@ -388,6 +392,8 @@ static void eth_igb_write_ivar(struct e1000_hw *hw, uint8_t msix_vector, .link_update = eth_igb_link_update, .stats_get= eth_igb_stats_get, .xstats_get = eth_igb_xstats_get, + .xstats_get_by_ids= eth_igb_xstats_get_by_ids, + .xstats_get_names_by_ids = eth_igb_xstats_get_names_by_ids, .xstats_get_names = eth_igb_xstats_get_names, .stats_reset = eth_igb_stats_reset, .xstats_reset = eth_igb_xstats_reset, @@ -1846,6 +1852,41 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev, return IGB_NB_XSTATS; } +static int eth_igb_xstats_get_names_by_ids(struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, uint64_t *ids, + unsigned int limit) +{ + unsigned int i; + + if (!ids) { + if (xstats_names == NULL) + return IGB_NB_XSTATS; + + for (i = 0; i < IGB_NB_XSTATS; i++) + snprintf(xstats_names[i].name, + sizeof(xstats_names[i].name), + "%s", rte_igb_stats_strings[i].name); + + return IGB_NB_XSTATS; + + } else { + struct rte_eth_xstat_name xstats_names_copy[IGB_NB_XSTATS]; + + eth_igb_xstats_get_names_by_ids(dev, xstats_names_copy, NULL, + IGB_NB_XSTATS); + + for (i = 0; i < limit; i++) { + if (ids[i] >= IGB_NB_XSTATS) { + PMD_INIT_LOG(ERR, "id value isn't valid"); + return -1; + } + strcpy(xstats_names[i].name, + xstats_names_copy[ids[i]].name); + } + return limit; + } +} + static int eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n) @@ -1876,6 +1917,53 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev, return IGB_NB_XSTATS; } +static int +eth_igb_xstats_get_by_ids(struct rte_eth_dev *dev, uint64_t *ids, + uint64_t *values, unsigned int n) +{ + unsigned int i; + + if (!ids) { + struct e1000_hw *hw = + E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_hw_stats *hw_stats = + E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private); + + if (n < IGB_NB_XSTATS) + return IGB_NB_XSTATS; + + igb_read_stats_registers(hw, hw_stats); + + /* If this is a reset xstats is NULL, and we have cleared the +* registers by reading them. +*/ + if (!values) + return 0; + + /* Extended stats */ + for (i = 0; i < IGB_NB_XSTATS; i++) + values[i] = *(uint64_t *)(((char *)hw_stats) + + rte_igb_stats_strings[i].offset); + +
[dpdk-dev] [PATCH v6 5/5] net/ixgbe: new xstats API add ID support for ixgbe
From: Jacek Piasecki To achieve functionality of retrieving only specific statistics given by application there are two new functions added: ixgbe_dev_xstats_get_by_ids() which retrieve values of statistics specified by ids array and ixgbe_dev_xstats_get_names_by_ids() which retrieve names of statistics specified by ids array. Signed-off-by: Jacek Piasecki Signed-off-by: Kuba Kozak --- drivers/net/ixgbe/ixgbe_ethdev.c | 179 +++ 1 file changed, 179 insertions(+) diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c index 1462324..76a5499 100644 --- a/drivers/net/ixgbe/ixgbe_ethdev.c +++ b/drivers/net/ixgbe/ixgbe_ethdev.c @@ -183,12 +183,20 @@ static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned n); +static int +ixgbe_dev_xstats_get_by_ids(struct rte_eth_dev *dev, uint64_t *ids, + uint64_t *values, unsigned int n); static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev); static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev); static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit); static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit); +static int ixgbe_dev_xstats_get_names_by_ids( + __rte_unused struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + uint64_t *ids, + unsigned int limit); static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev, uint16_t queue_id, uint8_t stat_idx, @@ -524,9 +532,11 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev, .link_update = ixgbe_dev_link_update, .stats_get= ixgbe_dev_stats_get, .xstats_get = ixgbe_dev_xstats_get, + .xstats_get_by_ids= ixgbe_dev_xstats_get_by_ids, .stats_reset = ixgbe_dev_stats_reset, .xstats_reset = ixgbe_dev_xstats_reset, .xstats_get_names = ixgbe_dev_xstats_get_names, + .xstats_get_names_by_ids = ixgbe_dev_xstats_get_names_by_ids, .queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set, .fw_version_get = ixgbe_fw_version_get, .dev_infos_get= ixgbe_dev_info_get, @@ -3095,6 +3105,84 @@ static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev, return cnt_stats; } +static int ixgbe_dev_xstats_get_names_by_ids( + __rte_unused struct rte_eth_dev *dev, + struct rte_eth_xstat_name *xstats_names, + uint64_t *ids, + unsigned int limit) +{ + if (!ids) { + const unsigned int cnt_stats = ixgbe_xstats_calc_num(); + unsigned int stat, i, count; + + if (xstats_names != NULL) { + count = 0; + + /* Note: limit >= cnt_stats checked upstream +* in rte_eth_xstats_names() +*/ + + /* Extended stats from ixgbe_hw_stats */ + for (i = 0; i < IXGBE_NB_HW_STATS; i++) { + snprintf(xstats_names[count].name, + sizeof(xstats_names[count].name), + "%s", + rte_ixgbe_stats_strings[i].name); + count++; + } + + /* MACsec Stats */ + for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) { + snprintf(xstats_names[count].name, + sizeof(xstats_names[count].name), + "%s", + rte_ixgbe_macsec_strings[i].name); + count++; + } + + /* RX Priority Stats */ + for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) { + for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) { + snprintf(xstats_names[count].name, + sizeof(xstats_names[count].name), + "rx_priority%u_%s", i, + rte_ixgbe_rxq_strings[stat].name); + count++; + } + } + + /* TX Priority Stats *
[dpdk-dev] [PATCH] ethdev: fix wrong sizeof argument in malloc function
From: Michal Jastrzebski Coverity reported that an argument for sizeof was used improperly. We should allocate memory for value size that pointer points to, instead of pointer size itself. Coverity issue: 144522 Fixes: 79c913a42f0e ("ethdev: retrieve xstats by ID") Signed-off-by: Michal Jastrzebski --- lib/librte_ether/rte_ethdev.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 8cf8b65..83898a8 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -1714,7 +1714,7 @@ struct rte_eth_dev * size = rte_eth_xstats_get_by_id(port_id, NULL, NULL, 0); - values_copy = malloc(sizeof(values_copy) * size); + values_copy = malloc(sizeof(*values_copy) * size); if (!values_copy) { RTE_PMD_DEBUG_TRACE( "ERROR: can't allocate memory for values_copy\n"); -- 1.7.9.5
[dpdk-dev] [PATCH] proc-info: wrong sizeof argument in malloc function
From: Michal Jastrzebski Coverity reported that an argument for sizeof was used improperly. We should allocate memory for value size that pointer points to, instead of pointer size itself. Coverity issue: 144523, 144521 Fixes: 7ac16a3660c0 ("app/proc-info: support xstats by ID and by name") Signed-off-by: Michal Jastrzebski --- app/proc_info/main.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 17a1c87..d4f6a82 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -434,7 +434,7 @@ static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len, int ret, i; static const char *nic_stats_border = ""; - values = malloc(sizeof(values) * len); + values = malloc(sizeof(*values) * len); if (values == NULL) { printf("Cannot allocate memory for xstats\n"); return; @@ -486,7 +486,7 @@ static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len, printf("Cannot get xstats count\n"); return; } - values = malloc(sizeof(values) * len); + values = malloc(sizeof(*values) * len); if (values == NULL) { printf("Cannot allocate memory for xstats\n"); return; -- 1.7.9.5
[dpdk-dev] [PATCH v5 0/5] Rework cfgfile API to enable apps config file support
New API for cfgfile library allows to create a cfgfile at runtime, add new section, add entry in a section, update existing entry and save cfgfile structure to INI file - opens up the possibility to have applications dynamically build up a proper DPDK configuration, rather than having to have a pre-existing one. Due the new API functions, simplification of load() function was made. One new unit test to TEST app was added. It contains an example of a large INI file whose parsing requires multiple reallocation of memory. --- v5: Some commit message reword test_cfgfile.c - remove *.ini file created during realloc test Add #ifdef RTE_NEXT_ABI for return value change in - rte_cfgfile_section_num_entries(), - rte_cfgfile_section_entries(), - rte_cfgfile_section_entries_by_index() v4: Change members of structure cfgfile: - struct *sections[] to *sections - struct *entries[] to *entries - remove free_sections and free_entries Rework of existing cfgfile API functions to work with modified rte_cfgfile struct. Rework of malloc/realloc implementation due rte_cfgfile struct change, reducing mulitiple mallocs. Change return error codes for all library functions (errno.h) Checkpatch fixes v3: split one patchset into two distinct patchsets: 1. cfgfile library and TEST app changes 2. EAL changes and examples (this patchset depends on cfgfile) v2: lib eal: Rework of rte_eal_configure(struct rte_cfgfile *cfg, char *prgname). Now this function load data from cfg structure and did initial initialization of EAL arguments. Vdev argument are stored in different subsections eg. DPDK.vdev0, DPDK.vdev1 etc. After execution of this function it is necessary to call rte_eal_init to complete EAL initialization. There is no more merging arguments from different sources (cfg file and command line). Added non_eal_configure to testpmd application. Function maintain the same functionality as rte_eal_configure but for non-eal arguments. Added config JSON feature to testpmd last patch from patchset contain example showing use of .json configuration files. lib cfgfile: Rework of add_section(), add_entry() new implementation New members allocated_entries/sections, free_entries/sections in rte_cfgfile structure, change in array of pointers **sections, **entries instead of *sections[], *entries[] Add set_entry() to update/overwrite already existing entry in cfgfile struct Add save() function to save on disc cfgfile structure in INI format Rework of existing load() function simplifying the code Add unit test realloc_sections() in TEST app for testing realloc/malloc of new API functions, add test for save() function Jacek Piasecki (5): cfgfile: remove EAL dependency cfgfile: change existing API functions cfgfile: add APIs for cfgfile modification cfgfile: rework of load function test/cfgfile: add new unit test doc/guides/rel_notes/deprecation.rst | 5 + lib/Makefile | 3 +- lib/librte_cfgfile/Makefile | 1 + lib/librte_cfgfile/rte_cfgfile.c | 431 ++- lib/librte_cfgfile/rte_cfgfile.h | 82 - lib/librte_cfgfile/rte_cfgfile_version.map | 11 + test/test/test_cfgfile.c | 41 +++ test/test/test_cfgfiles/etc/realloc_sections.ini | 128 +++ 8 files changed, 532 insertions(+), 170 deletions(-) create mode 100644 test/test/test_cfgfiles/etc/realloc_sections.ini -- 2.7.4
[dpdk-dev] [PATCH v5 1/5] cfgfile: remove EAL dependency
From: Jacek Piasecki This patch removes the dependency to EAL in cfgfile library. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- lib/Makefile | 3 +-- lib/librte_cfgfile/Makefile | 1 + lib/librte_cfgfile/rte_cfgfile.c | 29 + 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 86caba1..1080a95 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -32,6 +32,7 @@ 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 DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring DEPDIRS-librte_ring := librte_eal @@ -41,8 +42,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 diff --git a/lib/librte_cfgfile/Makefile b/lib/librte_cfgfile/Makefile index 755ef11..0bee43e 100644 --- a/lib/librte_cfgfile/Makefile +++ b/lib/librte_cfgfile/Makefile @@ -38,6 +38,7 @@ LIB = librte_cfgfile.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +CFLAGS += -I$(SRCDIR)/../librte_eal/common/include EXPORT_MAP := rte_cfgfile_version.map diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index 2588093..9dc25cc 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "rte_cfgfile.h" @@ -258,19 +257,25 @@ rte_cfgfile_load_with_params(const char *filename, int flags, struct rte_cfgfile_section *sect = cfg->sections[curr_section]; - int n; + char *split[2] = {NULL}; - n = rte_strsplit(buffer, sizeof(buffer), split, 2, '='); - if (flags & CFG_FLAG_EMPTY_VALUES) { - if ((n < 1) || (n > 2)) { - printf("Error at line %d - cannot split string, n=%d\n", - lineno, n); - goto error1; - } + split[0] = buffer; + split[1] = memchr(buffer, '=', len); + + /* when delimeter not found */ + if (split[1] == NULL) { + printf("Error at line %d - cannot " + "split string\n", lineno); + goto error1; } else { - if (n != 2) { - printf("Error at line %d - cannot split string, n=%d\n", - lineno, n); + /* when delimeter found */ + *split[1] = '\0'; + split[1]++; + + if (!(flags & CFG_FLAG_EMPTY_VALUES) && + (*split[1] == '\0')) { + printf("Error at line %d - cannot " + "split string\n", lineno); goto error1; } } -- 2.7.4
[dpdk-dev] [PATCH v5 3/5] cfgfile: add APIs for cfgfile modification
From: Jacek Piasecki Extend existing cfgfile library with providing new API functions: rte_cfgfile_create() - create new cfgfile object rte_cfgfile_add_section() - add new section to existing cfgfile object rte_cfgfile_add_entry() - add new entry to existing cfgfile object in specified section rte_cfgfile_set_entry() - update existing entry in cfgfile object rte_cfgfile_save() - save existing cfgfile object to INI file This modification allows to create a cfgfile on runtime and opens up the possibility to have applications dynamically build up a proper DPDK configuration, rather than having to have a pre-existing one. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- lib/librte_cfgfile/rte_cfgfile.c | 186 + lib/librte_cfgfile/rte_cfgfile.h | 76 lib/librte_cfgfile/rte_cfgfile_version.map | 11 ++ 3 files changed, 273 insertions(+) diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index d7b3ff6..dd51268 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -121,6 +121,36 @@ _get_section(struct rte_cfgfile *cfg, const char *sectionname) } static int +_add_entry(struct rte_cfgfile_section *section, const char *entryname, + const char *entryvalue) +{ + /* resize entry structure if we don't have room for more entries */ + if (section->num_entries == section->allocated_entries) { + struct rte_cfgfile_entry *n_entries = realloc( + section->entries, + sizeof(struct rte_cfgfile_entry) * + ((section->allocated_entries) + + CFG_ALLOC_ENTRY_BATCH)); + + if (n_entries == NULL) + return -ENOMEM; + + section->entries = n_entries; + section->allocated_entries += CFG_ALLOC_ENTRY_BATCH; + } + /* fill up entry fields with key name and value */ + struct rte_cfgfile_entry *curr_entry = + §ion->entries[section->num_entries]; + + snprintf(curr_entry->name, sizeof(curr_entry->name), "%s", entryname); + snprintf(curr_entry->value, + sizeof(curr_entry->value), "%s", entryvalue); + section->num_entries++; + + return 0; +} + +static int rte_cfgfile_check_params(const struct rte_cfgfile_parameters *params) { unsigned int valid_comment; @@ -346,6 +376,162 @@ rte_cfgfile_load_with_params(const char *filename, int flags, return NULL; } +struct rte_cfgfile * +rte_cfgfile_create(int flags) +{ + int i; + struct rte_cfgfile *cfg = NULL; + + cfg = malloc(sizeof(*cfg)); + + if (cfg == NULL) + return NULL; + + cfg->flags = flags; + cfg->num_sections = 0; + + /* allocate first batch of sections and entries */ + cfg->sections = malloc(sizeof(struct rte_cfgfile_section) * + CFG_ALLOC_SECTION_BATCH); + + if (cfg->sections == NULL) + return NULL; + + cfg->allocated_sections = CFG_ALLOC_SECTION_BATCH; + + for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) { + cfg->sections[i].entries = malloc(sizeof( + struct rte_cfgfile_entry) * CFG_ALLOC_ENTRY_BATCH); + + if (cfg->sections[i].entries == NULL) + return NULL; + + cfg->sections[i].num_entries = 0; + cfg->sections[i].allocated_entries = CFG_ALLOC_ENTRY_BATCH; + } + + if (flags & CFG_FLAG_GLOBAL_SECTION) + rte_cfgfile_add_section(cfg, "GLOBAL"); + return cfg; +} + +int +rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname) +{ + int i; + + if (cfg == NULL) + return -EINVAL; + + if (sectionname == NULL) + return -EINVAL; + + /* resize overall struct if we don't have room for more sections */ + if (cfg->num_sections == cfg->allocated_sections) { + + struct rte_cfgfile_section *n_sections = + realloc(cfg->sections, + sizeof(struct rte_cfgfile_section) * + ((cfg->allocated_sections) + + CFG_ALLOC_SECTION_BATCH)); + + if (n_sections == NULL) + return -ENOMEM; + + for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) { + n_sections[i + cfg->allocated_sections].num_entries = 0; + n_sections[i + +cfg->allocated_sections].allocated_entries = 0; + n_sections[i + cfg->allocated_sections].entries = NULL; + } + cfg->sections = n_sections; + cfg->allocated_sections += CFG_ALLOC
[dpdk-dev] [PATCH v5 5/5] test/cfgfile: add new unit test
From: Jacek Piasecki Load huge realloc_sections.ini file to check malloc/realloc ability of cfgfile library. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- test/test/test_cfgfile.c | 41 test/test/test_cfgfiles/etc/realloc_sections.ini | 128 +++ 2 files changed, 169 insertions(+) create mode 100644 test/test/test_cfgfiles/etc/realloc_sections.ini diff --git a/test/test/test_cfgfile.c b/test/test/test_cfgfile.c index 4cc9b14..25e8539 100644 --- a/test/test/test_cfgfile.c +++ b/test/test/test_cfgfile.c @@ -111,6 +111,7 @@ _test_cfgfile_sample(struct rte_cfgfile *cfgfile) return 0; } + static int test_cfgfile_sample1(void) { @@ -154,6 +155,43 @@ test_cfgfile_sample2(void) } static int +test_cfgfile_realloc_sections(void) +{ + struct rte_cfgfile *cfgfile; + int ret; + const char *value; + + cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0); + TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file"); + + ret = rte_cfgfile_num_sections(cfgfile, NULL, 0); + TEST_ASSERT(ret == 9, "Unexpected number of sections: %d", ret); + + ret = rte_cfgfile_has_section(cfgfile, "section9"); + TEST_ASSERT(ret, "section9 missing"); + + ret = rte_cfgfile_section_num_entries(cfgfile, "section3"); + TEST_ASSERT(ret == 21, + "section3 unexpected number of entries: %d", ret); + + ret = rte_cfgfile_section_num_entries(cfgfile, "section9"); + TEST_ASSERT(ret == 8, "section9 unexpected number of entries: %d", ret); + + value = rte_cfgfile_get_entry(cfgfile, "section9", "key8"); + TEST_ASSERT(strcmp("value8_section9", value) == 0, + "key unexpected value: %s", value); + + ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini"); + TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file"); + remove("/tmp/cfgfile_save.ini"); + + ret = rte_cfgfile_close(cfgfile); + TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); + + return 0; +} + +static int test_cfgfile_invalid_section_header(void) { struct rte_cfgfile *cfgfile; @@ -292,6 +330,9 @@ test_cfgfile(void) if (test_cfgfile_sample2()) return -1; + if (test_cfgfile_realloc_sections()) + return -1; + if (test_cfgfile_invalid_section_header()) return -1; diff --git a/test/test/test_cfgfiles/etc/realloc_sections.ini b/test/test/test_cfgfiles/etc/realloc_sections.ini new file mode 100644 index 000..e653e40 --- /dev/null +++ b/test/test/test_cfgfiles/etc/realloc_sections.ini @@ -0,0 +1,128 @@ +[section1] +key1=value1_section1 +key2=value2_section1 +key3=value3_section1 +key4=value4_section1 +key5=value5_section1 +key6=value6_section1 +key7=value7_section1 +key8=value8_section1 +key9=value9_section1 +key10=value10_section1 +key11=value11_section1 +key12=value12_section1 +key13=value13_section1 +key14=value14_section1 +key15=value15_section1 +key16=value16_section1 +key17=value17_section1 +key18=value18_section1 +key19=value19_section1 +key20=value20_section1 +key21=value21_section1 + +[section2] +key1=value1_section2 +key2=value2_section2 +key3=value3_section2 +key4=value4_section2 +key5=value5_section2 +key6=value6_section2 +key7=value7_section2 +key8=value8_section2 +key9=value9_section2 +key10=value10_section2 +key11=value11_section2 +key12=value12_section2 +key13=value13_section2 +key14=value14_section2 +key15=value15_section2 +key16=value16_section2 +key17=value17_section2 +key18=value18_section2 +key19=value19_section2 +key20=value20_section2 +key21=value21_section2 + +[section3] +key1=value1_section3 +key2=value2_section3 +key3=value3_section3 +key4=value4_section3 +key5=value5_section3 +key6=value6_section3 +key7=value7_section3 +key8=value8_section3 +key9=value9_section3 +key10=value10_section3 +key11=value11_section3 +key12=value12_section3 +key13=value13_section3 +key14=value14_section3 +key15=value15_section3 +key16=value16_section3 +key17=value17_section3 +key18=value18_section3 +key19=value19_section3 +key20=value20_section3 +key21=value21_section3 + +[section4] +key1=value1_section4 +key2=value2_section4 +key3=value3_section4 +key4=value4_section4 +key5=value5_section4 +key6=value6_section4 +key7=value7_section4 +key8=value8_section4 + +[section5] +key1=value1_section5 +key2=value2_section5 +key3=value3_section5 +key4=value4_section5 +key5=value5_section5 +key6=value6_section5 +key7=value7_section5 +key8=value8_section5 + +[section6] +key1=value1_section6 +key2=value2_section6 +key3=value3_section6 +key4=value4_section6 +key5=value5_section6 +key6=value6_section6 +key7=value7_section6 +key8=value8_section6 + +[section7] +key1=value1_section7 +key2=value2_section7 +key3=value3_section7 +key4=value4_section7 +key5=value5_section7 +key6=value6_section7 +key7=value7_section7 +key8=value8_section7 + +[section8] +key1=value1_secti
[dpdk-dev] [PATCH v5 4/5] cfgfile: rework of load function
From: Jacek Piasecki New functions added to cfgfile library make it possible to significantly simplify the code of rte_cfgfile_load_with_params() This patch shows the new body of this function. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- lib/librte_cfgfile/rte_cfgfile.c | 157 --- 1 file changed, 30 insertions(+), 127 deletions(-) diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index dd51268..40954c5 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -189,10 +189,6 @@ struct rte_cfgfile * rte_cfgfile_load_with_params(const char *filename, int flags, const struct rte_cfgfile_parameters *params) { - int allocated_sections = CFG_ALLOC_SECTION_BATCH; - int allocated_entries = 0; - int curr_section = -1; - int curr_entry = -1; char buffer[CFG_NAME_LEN + CFG_VALUE_LEN + 4] = {0}; int lineno = 0; struct rte_cfgfile *cfg = NULL; @@ -204,28 +200,7 @@ rte_cfgfile_load_with_params(const char *filename, int flags, if (f == NULL) return NULL; - cfg = malloc(sizeof(*cfg) + sizeof(cfg->sections[0]) * - allocated_sections); - if (cfg == NULL) - goto error2; - - memset(cfg->sections, 0, sizeof(cfg->sections[0]) * allocated_sections); - - if (flags & CFG_FLAG_GLOBAL_SECTION) { - curr_section = 0; - allocated_entries = CFG_ALLOC_ENTRY_BATCH; - cfg->sections = malloc( - sizeof(cfg->sections[0]) + - sizeof(cfg->sections[0].entries) * - allocated_entries); - if (cfg->sections == NULL) { - printf("Error - no memory for global section\n"); - goto error1; - } - - snprintf(cfg->sections[curr_section].name, -sizeof(cfg->sections[0].name), "GLOBAL"); - } + cfg = rte_cfgfile_create(flags); while (fgets(buffer, sizeof(buffer), f) != NULL) { char *pos = NULL; @@ -236,13 +211,15 @@ rte_cfgfile_load_with_params(const char *filename, int flags, "Check if line too long\n", lineno); goto error1; } + /* skip parsing if comment character found */ pos = memchr(buffer, params->comment_character, len); - if (pos != NULL) { + if (pos != NULL && (*(pos-1) != '\\')) { *pos = '\0'; len = pos - buffer; } len = _strip(buffer, len); + /* skip lines without useful content */ if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL) continue; @@ -250,128 +227,54 @@ rte_cfgfile_load_with_params(const char *filename, int flags, /* section heading line */ char *end = memchr(buffer, ']', len); if (end == NULL) { - printf("Error line %d - no terminating '['" + printf("Error line %d - no terminating ']'" "character found\n", lineno); goto error1; } *end = '\0'; _strip(&buffer[1], end - &buffer[1]); - /* close off old section and add start new one */ - if (curr_section >= 0) - cfg->sections[curr_section].num_entries = - curr_entry + 1; - curr_section++; - - /* resize overall struct if we don't have room for more - sections */ - if (curr_section == allocated_sections) { - allocated_sections += CFG_ALLOC_SECTION_BATCH; - struct rte_cfgfile *n_cfg = realloc(cfg, - sizeof(*cfg) + sizeof(cfg->sections[0]) - * allocated_sections); - if (n_cfg == NULL) { - curr_section--; - printf("Error - no more memory\n"); - goto error1; - } - cfg = n_cfg; - } - - /* allocate space for new section */ - allocated_entries = CFG_ALLOC_ENTRY_BATCH; - curr_entry = -1; - cfg->sections = malloc( - sizeof(cfg->sections[0]) + -
[dpdk-dev] [PATCH v5 2/5] cfgfile: change existing API functions
From: Jacek Piasecki Change to flat arrays in cfgfile struct force slightly diffrent data access for most of cfgfile functions. This patch provides necessary changes in existing API. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- doc/guides/rel_notes/deprecation.rst | 5 ++ lib/librte_cfgfile/rte_cfgfile.c | 133 ++- lib/librte_cfgfile/rte_cfgfile.h | 6 +- 3 files changed, 78 insertions(+), 66 deletions(-) diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index 3362f33..4f67646 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -120,3 +120,8 @@ Deprecation Notices The non-"do-sig" versions of the hash tables will be removed (including the ``signature_offset`` parameter) and the "do-sig" versions renamed accordingly. + +* cfgfile: Return value in ``rte_cfgfile_section_num_entries``, + ``rte_cfgfile_section_entries`` and ``rte_cfgfile_section_entries_by_index`` + will change from ``-1`` to ``-EINVAL`` to get a consistent error + handling in whole cfgfile library. diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index 9dc25cc..d7b3ff6 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "rte_cfgfile.h" @@ -42,13 +43,15 @@ struct rte_cfgfile_section { char name[CFG_NAME_LEN]; int num_entries; - struct rte_cfgfile_entry *entries[0]; + int allocated_entries; + struct rte_cfgfile_entry *entries; }; struct rte_cfgfile { int flags; int num_sections; - struct rte_cfgfile_section *sections[0]; + int allocated_sections; + struct rte_cfgfile_section *sections; }; /** when we resize a file structure, how many extra entries @@ -104,6 +107,19 @@ _strip(char *str, unsigned len) return newlen; } +static struct rte_cfgfile_section * +_get_section(struct rte_cfgfile *cfg, const char *sectionname) +{ + int i; + + for (i = 0; i < cfg->num_sections; i++) { + if (strncmp(cfg->sections[i].name, sectionname, + sizeof(cfg->sections[0].name)) == 0) + return &cfg->sections[i]; + } + return NULL; +} + static int rte_cfgfile_check_params(const struct rte_cfgfile_parameters *params) { @@ -168,17 +184,17 @@ rte_cfgfile_load_with_params(const char *filename, int flags, if (flags & CFG_FLAG_GLOBAL_SECTION) { curr_section = 0; allocated_entries = CFG_ALLOC_ENTRY_BATCH; - cfg->sections[curr_section] = malloc( - sizeof(*cfg->sections[0]) + - sizeof(cfg->sections[0]->entries[0]) * + cfg->sections = malloc( + sizeof(cfg->sections[0]) + + sizeof(cfg->sections[0].entries) * allocated_entries); - if (cfg->sections[curr_section] == NULL) { + if (cfg->sections == NULL) { printf("Error - no memory for global section\n"); goto error1; } - snprintf(cfg->sections[curr_section]->name, -sizeof(cfg->sections[0]->name), "GLOBAL"); + snprintf(cfg->sections[curr_section].name, +sizeof(cfg->sections[0].name), "GLOBAL"); } while (fgets(buffer, sizeof(buffer), f) != NULL) { @@ -213,7 +229,7 @@ rte_cfgfile_load_with_params(const char *filename, int flags, /* close off old section and add start new one */ if (curr_section >= 0) - cfg->sections[curr_section]->num_entries = + cfg->sections[curr_section].num_entries = curr_entry + 1; curr_section++; @@ -235,17 +251,17 @@ rte_cfgfile_load_with_params(const char *filename, int flags, /* allocate space for new section */ allocated_entries = CFG_ALLOC_ENTRY_BATCH; curr_entry = -1; - cfg->sections[curr_section] = malloc( - sizeof(*cfg->sections[0]) + - sizeof(cfg->sections[0]->entries[0]) * + cfg->sections = malloc( + sizeof(cfg->sections[0]) + + sizeof(cfg->sections[0].entries) * allocated_entries); - if (cfg->sections[curr_section] == NULL) { + if (cfg->sections == NULL) { printf("Error - no more memory\n"); goto err
[dpdk-dev] [PATCH] vfio: fix close unchecked file descriptor
Add file descriptor value check before calling close() function. Coverity issue: 141297 Fixes: 811b6b25060f ("vfio: fix file descriptor leak in multi-process") Cc: patr...@patrickmacarthur.net Cc: sta...@dpdk.org Signed-off-by: Kuba Kozak --- lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c b/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c index 7e8095c..c04f548 100644 --- a/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c +++ b/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c @@ -301,7 +301,8 @@ vfio_mp_sync_thread(void __rte_unused * arg) vfio_mp_sync_send_request(conn_sock, SOCKET_ERR); else vfio_mp_sync_send_fd(conn_sock, fd); - close(fd); + if (fd != -1) + close(fd); break; case SOCKET_REQ_GROUP: /* wait for group number */ -- 2.7.4
[dpdk-dev] [PATCH] acl: fix unchecked return value
Add return value check and error handling for fseek call. Coverity issue: 143435 Fixes: 361b2e9559fc ("acl: new sample l3fwd-acl") Cc: konstantin.anan...@intel.com Cc: sta...@dpdk.org Signed-off-by: Kuba Kozak --- examples/l3fwd-acl/main.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c index 8eff4de..708e9eb 100644 --- a/examples/l3fwd-acl/main.c +++ b/examples/l3fwd-acl/main.c @@ -1026,6 +1026,7 @@ add_rules(const char *rule_path, char buff[LINE_MAX]; FILE *fh = fopen(rule_path, "rb"); unsigned int i = 0; + int val; if (fh == NULL) rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__, @@ -1042,7 +1043,11 @@ add_rules(const char *rule_path, rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n", rule_path); - fseek(fh, 0, SEEK_SET); + val = fseek(fh, 0, SEEK_SET); + if (val < 0) { + rte_exit(EXIT_FAILURE, "%s: File seek operation failed\n", + __func__); + } acl_rules = calloc(acl_num, rule_size); -- 2.7.4
[dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support
New API for cfgfile library allows to create a cfgfile at runtime, add new section, add entry in a section, update existing entry and save cfgfile structure to INI file - opens up the possibility to have applications dynamically build up a proper DPDK configuration, rather than having to have a pre-existing one. Due the new API functions, simplification of load() function was made. One new unit test to TEST app was added. It contains an example of a large INI file whose parsing requires multiple reallocation of memory. --- v6: Drop changes from v5 for return value in - rte_cfgfile_section_num_entries(), - rte_cfgfile_section_entries(), - rte_cfgfile_section_entries_by_index() v5: Some commit message reword test_cfgfile.c - remove *.ini file created during realloc test Add #ifdef RTE_NEXT_ABI for return value change in - rte_cfgfile_section_num_entries(), - rte_cfgfile_section_entries(), - rte_cfgfile_section_entries_by_index() v4: Change members of structure cfgfile: - struct *sections[] to *sections - struct *entries[] to *entries - remove free_sections and free_entries Rework of existing cfgfile API functions to work with modified rte_cfgfile struct. Rework of malloc/realloc implementation due rte_cfgfile struct change, reducing mulitiple mallocs. Change return error codes for all library functions (errno.h) Checkpatch fixes v3: split one patchset into two distinct patchsets: 1. cfgfile library and TEST app changes 2. EAL changes and examples (this patchset depends on cfgfile) v2: lib eal: Rework of rte_eal_configure(struct rte_cfgfile *cfg, char *prgname). Now this function load data from cfg structure and did initial initialization of EAL arguments. Vdev argument are stored in different subsections eg. DPDK.vdev0, DPDK.vdev1 etc. After execution of this function it is necessary to call rte_eal_init to complete EAL initialization. There is no more merging arguments from different sources (cfg file and command line). Added non_eal_configure to testpmd application. Function maintain the same functionality as rte_eal_configure but for non-eal arguments. Added config JSON feature to testpmd last patch from patchset contain example showing use of .json configuration files. lib cfgfile: Rework of add_section(), add_entry() new implementation New members allocated_entries/sections, free_entries/sections in rte_cfgfile structure, change in array of pointers **sections, **entries instead of *sections[], *entries[] Add set_entry() to update/overwrite already existing entry in cfgfile struct Add save() function to save on disc cfgfile structure in INI format Rework of existing load() function simplifying the code Add unit test realloc_sections() in TEST app for testing realloc/malloc of new API functions, add test for save() function Jacek Piasecki (5): cfgfile: remove EAL dependency cfgfile: change existing API functions cfgfile: add APIs for cfgfile modification cfgfile: rework of load function test/cfgfile: add new unit test lib/Makefile | 3 +- lib/librte_cfgfile/Makefile | 1 + lib/librte_cfgfile/rte_cfgfile.c | 419 ++- lib/librte_cfgfile/rte_cfgfile.h | 76 lib/librte_cfgfile/rte_cfgfile_version.map | 11 + test/test/test_cfgfile.c | 41 +++ test/test/test_cfgfiles/etc/realloc_sections.ini | 128 +++ 7 files changed, 512 insertions(+), 167 deletions(-) create mode 100644 test/test/test_cfgfiles/etc/realloc_sections.ini -- 2.7.4
[dpdk-dev] [PATCH v6 1/5] cfgfile: remove EAL dependency
From: Jacek Piasecki This patch removes the dependency to EAL in cfgfile library. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- lib/Makefile | 3 +-- lib/librte_cfgfile/Makefile | 1 + lib/librte_cfgfile/rte_cfgfile.c | 29 + 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 86caba1..1080a95 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -32,6 +32,7 @@ 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 DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring DEPDIRS-librte_ring := librte_eal @@ -41,8 +42,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 diff --git a/lib/librte_cfgfile/Makefile b/lib/librte_cfgfile/Makefile index 755ef11..0bee43e 100644 --- a/lib/librte_cfgfile/Makefile +++ b/lib/librte_cfgfile/Makefile @@ -38,6 +38,7 @@ LIB = librte_cfgfile.a CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +CFLAGS += -I$(SRCDIR)/../librte_eal/common/include EXPORT_MAP := rte_cfgfile_version.map diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index 2588093..9dc25cc 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "rte_cfgfile.h" @@ -258,19 +257,25 @@ rte_cfgfile_load_with_params(const char *filename, int flags, struct rte_cfgfile_section *sect = cfg->sections[curr_section]; - int n; + char *split[2] = {NULL}; - n = rte_strsplit(buffer, sizeof(buffer), split, 2, '='); - if (flags & CFG_FLAG_EMPTY_VALUES) { - if ((n < 1) || (n > 2)) { - printf("Error at line %d - cannot split string, n=%d\n", - lineno, n); - goto error1; - } + split[0] = buffer; + split[1] = memchr(buffer, '=', len); + + /* when delimeter not found */ + if (split[1] == NULL) { + printf("Error at line %d - cannot " + "split string\n", lineno); + goto error1; } else { - if (n != 2) { - printf("Error at line %d - cannot split string, n=%d\n", - lineno, n); + /* when delimeter found */ + *split[1] = '\0'; + split[1]++; + + if (!(flags & CFG_FLAG_EMPTY_VALUES) && + (*split[1] == '\0')) { + printf("Error at line %d - cannot " + "split string\n", lineno); goto error1; } } -- 2.7.4
[dpdk-dev] [PATCH v6 3/5] cfgfile: add APIs for cfgfile modification
From: Jacek Piasecki Extend existing cfgfile library with providing new API functions: rte_cfgfile_create() - create new cfgfile object rte_cfgfile_add_section() - add new section to existing cfgfile object rte_cfgfile_add_entry() - add new entry to existing cfgfile object in specified section rte_cfgfile_set_entry() - update existing entry in cfgfile object rte_cfgfile_save() - save existing cfgfile object to INI file This modification allows to create a cfgfile on runtime and opens up the possibility to have applications dynamically build up a proper DPDK configuration, rather than having to have a pre-existing one. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- lib/librte_cfgfile/rte_cfgfile.c | 186 + lib/librte_cfgfile/rte_cfgfile.h | 76 lib/librte_cfgfile/rte_cfgfile_version.map | 11 ++ 3 files changed, 273 insertions(+) diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index 39f61e5..ad9bb2e 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -121,6 +121,36 @@ _get_section(struct rte_cfgfile *cfg, const char *sectionname) } static int +_add_entry(struct rte_cfgfile_section *section, const char *entryname, + const char *entryvalue) +{ + /* resize entry structure if we don't have room for more entries */ + if (section->num_entries == section->allocated_entries) { + struct rte_cfgfile_entry *n_entries = realloc( + section->entries, + sizeof(struct rte_cfgfile_entry) * + ((section->allocated_entries) + + CFG_ALLOC_ENTRY_BATCH)); + + if (n_entries == NULL) + return -ENOMEM; + + section->entries = n_entries; + section->allocated_entries += CFG_ALLOC_ENTRY_BATCH; + } + /* fill up entry fields with key name and value */ + struct rte_cfgfile_entry *curr_entry = + §ion->entries[section->num_entries]; + + snprintf(curr_entry->name, sizeof(curr_entry->name), "%s", entryname); + snprintf(curr_entry->value, + sizeof(curr_entry->value), "%s", entryvalue); + section->num_entries++; + + return 0; +} + +static int rte_cfgfile_check_params(const struct rte_cfgfile_parameters *params) { unsigned int valid_comment; @@ -346,6 +376,162 @@ rte_cfgfile_load_with_params(const char *filename, int flags, return NULL; } +struct rte_cfgfile * +rte_cfgfile_create(int flags) +{ + int i; + struct rte_cfgfile *cfg = NULL; + + cfg = malloc(sizeof(*cfg)); + + if (cfg == NULL) + return NULL; + + cfg->flags = flags; + cfg->num_sections = 0; + + /* allocate first batch of sections and entries */ + cfg->sections = malloc(sizeof(struct rte_cfgfile_section) * + CFG_ALLOC_SECTION_BATCH); + + if (cfg->sections == NULL) + return NULL; + + cfg->allocated_sections = CFG_ALLOC_SECTION_BATCH; + + for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) { + cfg->sections[i].entries = malloc(sizeof( + struct rte_cfgfile_entry) * CFG_ALLOC_ENTRY_BATCH); + + if (cfg->sections[i].entries == NULL) + return NULL; + + cfg->sections[i].num_entries = 0; + cfg->sections[i].allocated_entries = CFG_ALLOC_ENTRY_BATCH; + } + + if (flags & CFG_FLAG_GLOBAL_SECTION) + rte_cfgfile_add_section(cfg, "GLOBAL"); + return cfg; +} + +int +rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname) +{ + int i; + + if (cfg == NULL) + return -EINVAL; + + if (sectionname == NULL) + return -EINVAL; + + /* resize overall struct if we don't have room for more sections */ + if (cfg->num_sections == cfg->allocated_sections) { + + struct rte_cfgfile_section *n_sections = + realloc(cfg->sections, + sizeof(struct rte_cfgfile_section) * + ((cfg->allocated_sections) + + CFG_ALLOC_SECTION_BATCH)); + + if (n_sections == NULL) + return -ENOMEM; + + for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) { + n_sections[i + cfg->allocated_sections].num_entries = 0; + n_sections[i + +cfg->allocated_sections].allocated_entries = 0; + n_sections[i + cfg->allocated_sections].entries = NULL; + } + cfg->sections = n_sections; + cfg->allocated_sections += CFG_ALLOC
[dpdk-dev] [PATCH v6 2/5] cfgfile: change existing API functions
From: Jacek Piasecki Change to flat arrays in cfgfile struct force slightly diffrent data access for most of cfgfile functions. This patch provides necessary changes in existing API. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- lib/librte_cfgfile/rte_cfgfile.c | 121 +++ 1 file changed, 58 insertions(+), 63 deletions(-) diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index 9dc25cc..39f61e5 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "rte_cfgfile.h" @@ -42,13 +43,15 @@ struct rte_cfgfile_section { char name[CFG_NAME_LEN]; int num_entries; - struct rte_cfgfile_entry *entries[0]; + int allocated_entries; + struct rte_cfgfile_entry *entries; }; struct rte_cfgfile { int flags; int num_sections; - struct rte_cfgfile_section *sections[0]; + int allocated_sections; + struct rte_cfgfile_section *sections; }; /** when we resize a file structure, how many extra entries @@ -104,6 +107,19 @@ _strip(char *str, unsigned len) return newlen; } +static struct rte_cfgfile_section * +_get_section(struct rte_cfgfile *cfg, const char *sectionname) +{ + int i; + + for (i = 0; i < cfg->num_sections; i++) { + if (strncmp(cfg->sections[i].name, sectionname, + sizeof(cfg->sections[0].name)) == 0) + return &cfg->sections[i]; + } + return NULL; +} + static int rte_cfgfile_check_params(const struct rte_cfgfile_parameters *params) { @@ -168,17 +184,17 @@ rte_cfgfile_load_with_params(const char *filename, int flags, if (flags & CFG_FLAG_GLOBAL_SECTION) { curr_section = 0; allocated_entries = CFG_ALLOC_ENTRY_BATCH; - cfg->sections[curr_section] = malloc( - sizeof(*cfg->sections[0]) + - sizeof(cfg->sections[0]->entries[0]) * + cfg->sections = malloc( + sizeof(cfg->sections[0]) + + sizeof(cfg->sections[0].entries) * allocated_entries); - if (cfg->sections[curr_section] == NULL) { + if (cfg->sections == NULL) { printf("Error - no memory for global section\n"); goto error1; } - snprintf(cfg->sections[curr_section]->name, -sizeof(cfg->sections[0]->name), "GLOBAL"); + snprintf(cfg->sections[curr_section].name, +sizeof(cfg->sections[0].name), "GLOBAL"); } while (fgets(buffer, sizeof(buffer), f) != NULL) { @@ -213,7 +229,7 @@ rte_cfgfile_load_with_params(const char *filename, int flags, /* close off old section and add start new one */ if (curr_section >= 0) - cfg->sections[curr_section]->num_entries = + cfg->sections[curr_section].num_entries = curr_entry + 1; curr_section++; @@ -235,17 +251,17 @@ rte_cfgfile_load_with_params(const char *filename, int flags, /* allocate space for new section */ allocated_entries = CFG_ALLOC_ENTRY_BATCH; curr_entry = -1; - cfg->sections[curr_section] = malloc( - sizeof(*cfg->sections[0]) + - sizeof(cfg->sections[0]->entries[0]) * + cfg->sections = malloc( + sizeof(cfg->sections[0]) + + sizeof(cfg->sections[0].entries) * allocated_entries); - if (cfg->sections[curr_section] == NULL) { + if (cfg->sections == NULL) { printf("Error - no more memory\n"); goto error1; } - snprintf(cfg->sections[curr_section]->name, - sizeof(cfg->sections[0]->name), + snprintf(cfg->sections[curr_section].name, + sizeof(cfg->sections[0].name), "%s", &buffer[1]); } else { /* value line */ @@ -255,8 +271,7 @@ rte_cfgfile_load_with_params(const char *filename, int flags, goto error1; } - struct rte_cfgfile_section *sect = - cfg->sections[curr_section]; + struct rte_cfgfile_sec
[dpdk-dev] [PATCH v6 4/5] cfgfile: rework of load function
From: Jacek Piasecki New functions added to cfgfile library make it possible to significantly simplify the code of rte_cfgfile_load_with_params() This patch shows the new body of this function. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- lib/librte_cfgfile/rte_cfgfile.c | 157 --- 1 file changed, 30 insertions(+), 127 deletions(-) diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c index ad9bb2e..124aef5 100644 --- a/lib/librte_cfgfile/rte_cfgfile.c +++ b/lib/librte_cfgfile/rte_cfgfile.c @@ -189,10 +189,6 @@ struct rte_cfgfile * rte_cfgfile_load_with_params(const char *filename, int flags, const struct rte_cfgfile_parameters *params) { - int allocated_sections = CFG_ALLOC_SECTION_BATCH; - int allocated_entries = 0; - int curr_section = -1; - int curr_entry = -1; char buffer[CFG_NAME_LEN + CFG_VALUE_LEN + 4] = {0}; int lineno = 0; struct rte_cfgfile *cfg = NULL; @@ -204,28 +200,7 @@ rte_cfgfile_load_with_params(const char *filename, int flags, if (f == NULL) return NULL; - cfg = malloc(sizeof(*cfg) + sizeof(cfg->sections[0]) * - allocated_sections); - if (cfg == NULL) - goto error2; - - memset(cfg->sections, 0, sizeof(cfg->sections[0]) * allocated_sections); - - if (flags & CFG_FLAG_GLOBAL_SECTION) { - curr_section = 0; - allocated_entries = CFG_ALLOC_ENTRY_BATCH; - cfg->sections = malloc( - sizeof(cfg->sections[0]) + - sizeof(cfg->sections[0].entries) * - allocated_entries); - if (cfg->sections == NULL) { - printf("Error - no memory for global section\n"); - goto error1; - } - - snprintf(cfg->sections[curr_section].name, -sizeof(cfg->sections[0].name), "GLOBAL"); - } + cfg = rte_cfgfile_create(flags); while (fgets(buffer, sizeof(buffer), f) != NULL) { char *pos = NULL; @@ -236,13 +211,15 @@ rte_cfgfile_load_with_params(const char *filename, int flags, "Check if line too long\n", lineno); goto error1; } + /* skip parsing if comment character found */ pos = memchr(buffer, params->comment_character, len); - if (pos != NULL) { + if (pos != NULL && (*(pos-1) != '\\')) { *pos = '\0'; len = pos - buffer; } len = _strip(buffer, len); + /* skip lines without useful content */ if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL) continue; @@ -250,128 +227,54 @@ rte_cfgfile_load_with_params(const char *filename, int flags, /* section heading line */ char *end = memchr(buffer, ']', len); if (end == NULL) { - printf("Error line %d - no terminating '['" + printf("Error line %d - no terminating ']'" "character found\n", lineno); goto error1; } *end = '\0'; _strip(&buffer[1], end - &buffer[1]); - /* close off old section and add start new one */ - if (curr_section >= 0) - cfg->sections[curr_section].num_entries = - curr_entry + 1; - curr_section++; - - /* resize overall struct if we don't have room for more - sections */ - if (curr_section == allocated_sections) { - allocated_sections += CFG_ALLOC_SECTION_BATCH; - struct rte_cfgfile *n_cfg = realloc(cfg, - sizeof(*cfg) + sizeof(cfg->sections[0]) - * allocated_sections); - if (n_cfg == NULL) { - curr_section--; - printf("Error - no more memory\n"); - goto error1; - } - cfg = n_cfg; - } - - /* allocate space for new section */ - allocated_entries = CFG_ALLOC_ENTRY_BATCH; - curr_entry = -1; - cfg->sections = malloc( - sizeof(cfg->sections[0]) + -
[dpdk-dev] [PATCH v6 5/5] test/cfgfile: add new unit test
From: Jacek Piasecki Load huge realloc_sections.ini file to check malloc/realloc ability of cfgfile library. Signed-off-by: Jacek Piasecki Acked-by: Bruce Richardson --- test/test/test_cfgfile.c | 41 test/test/test_cfgfiles/etc/realloc_sections.ini | 128 +++ 2 files changed, 169 insertions(+) create mode 100644 test/test/test_cfgfiles/etc/realloc_sections.ini diff --git a/test/test/test_cfgfile.c b/test/test/test_cfgfile.c index 4cc9b14..25e8539 100644 --- a/test/test/test_cfgfile.c +++ b/test/test/test_cfgfile.c @@ -111,6 +111,7 @@ _test_cfgfile_sample(struct rte_cfgfile *cfgfile) return 0; } + static int test_cfgfile_sample1(void) { @@ -154,6 +155,43 @@ test_cfgfile_sample2(void) } static int +test_cfgfile_realloc_sections(void) +{ + struct rte_cfgfile *cfgfile; + int ret; + const char *value; + + cfgfile = rte_cfgfile_load(CFG_FILES_ETC "/realloc_sections.ini", 0); + TEST_ASSERT_NOT_NULL(cfgfile, "Failed to load config file"); + + ret = rte_cfgfile_num_sections(cfgfile, NULL, 0); + TEST_ASSERT(ret == 9, "Unexpected number of sections: %d", ret); + + ret = rte_cfgfile_has_section(cfgfile, "section9"); + TEST_ASSERT(ret, "section9 missing"); + + ret = rte_cfgfile_section_num_entries(cfgfile, "section3"); + TEST_ASSERT(ret == 21, + "section3 unexpected number of entries: %d", ret); + + ret = rte_cfgfile_section_num_entries(cfgfile, "section9"); + TEST_ASSERT(ret == 8, "section9 unexpected number of entries: %d", ret); + + value = rte_cfgfile_get_entry(cfgfile, "section9", "key8"); + TEST_ASSERT(strcmp("value8_section9", value) == 0, + "key unexpected value: %s", value); + + ret = rte_cfgfile_save(cfgfile, "/tmp/cfgfile_save.ini"); + TEST_ASSERT_SUCCESS(ret, "Failed to save *.ini file"); + remove("/tmp/cfgfile_save.ini"); + + ret = rte_cfgfile_close(cfgfile); + TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); + + return 0; +} + +static int test_cfgfile_invalid_section_header(void) { struct rte_cfgfile *cfgfile; @@ -292,6 +330,9 @@ test_cfgfile(void) if (test_cfgfile_sample2()) return -1; + if (test_cfgfile_realloc_sections()) + return -1; + if (test_cfgfile_invalid_section_header()) return -1; diff --git a/test/test/test_cfgfiles/etc/realloc_sections.ini b/test/test/test_cfgfiles/etc/realloc_sections.ini new file mode 100644 index 000..e653e40 --- /dev/null +++ b/test/test/test_cfgfiles/etc/realloc_sections.ini @@ -0,0 +1,128 @@ +[section1] +key1=value1_section1 +key2=value2_section1 +key3=value3_section1 +key4=value4_section1 +key5=value5_section1 +key6=value6_section1 +key7=value7_section1 +key8=value8_section1 +key9=value9_section1 +key10=value10_section1 +key11=value11_section1 +key12=value12_section1 +key13=value13_section1 +key14=value14_section1 +key15=value15_section1 +key16=value16_section1 +key17=value17_section1 +key18=value18_section1 +key19=value19_section1 +key20=value20_section1 +key21=value21_section1 + +[section2] +key1=value1_section2 +key2=value2_section2 +key3=value3_section2 +key4=value4_section2 +key5=value5_section2 +key6=value6_section2 +key7=value7_section2 +key8=value8_section2 +key9=value9_section2 +key10=value10_section2 +key11=value11_section2 +key12=value12_section2 +key13=value13_section2 +key14=value14_section2 +key15=value15_section2 +key16=value16_section2 +key17=value17_section2 +key18=value18_section2 +key19=value19_section2 +key20=value20_section2 +key21=value21_section2 + +[section3] +key1=value1_section3 +key2=value2_section3 +key3=value3_section3 +key4=value4_section3 +key5=value5_section3 +key6=value6_section3 +key7=value7_section3 +key8=value8_section3 +key9=value9_section3 +key10=value10_section3 +key11=value11_section3 +key12=value12_section3 +key13=value13_section3 +key14=value14_section3 +key15=value15_section3 +key16=value16_section3 +key17=value17_section3 +key18=value18_section3 +key19=value19_section3 +key20=value20_section3 +key21=value21_section3 + +[section4] +key1=value1_section4 +key2=value2_section4 +key3=value3_section4 +key4=value4_section4 +key5=value5_section4 +key6=value6_section4 +key7=value7_section4 +key8=value8_section4 + +[section5] +key1=value1_section5 +key2=value2_section5 +key3=value3_section5 +key4=value4_section5 +key5=value5_section5 +key6=value6_section5 +key7=value7_section5 +key8=value8_section5 + +[section6] +key1=value1_section6 +key2=value2_section6 +key3=value3_section6 +key4=value4_section6 +key5=value5_section6 +key6=value6_section6 +key7=value7_section6 +key8=value8_section6 + +[section7] +key1=value1_section7 +key2=value2_section7 +key3=value3_section7 +key4=value4_section7 +key5=value5_section7 +key6=value6_section7 +key7=value7_section7 +key8=value8_section7 + +[section8] +key1=value1_secti
[dpdk-dev] [PATCH] vhost: fix unchecked return value
Add return value check for poll() call. Coverity issue: 140740 Fixes: 59317cef249c ("vhost: allow many vhost-user ports") Cc: jan.wick...@ericsson.com Cc: sta...@dpdk.org Signed-off-by: Kuba Kozak --- lib/librte_vhost/fd_man.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c index 2ceacc9..4c6fed4 100644 --- a/lib/librte_vhost/fd_man.c +++ b/lib/librte_vhost/fd_man.c @@ -222,6 +222,7 @@ fdset_event_dispatch(void *arg) int remove1, remove2; int need_shrink; struct fdset *pfdset = arg; + int val; if (pfdset == NULL) return NULL; @@ -239,7 +240,9 @@ fdset_event_dispatch(void *arg) numfds = pfdset->num; pthread_mutex_unlock(&pfdset->fd_mutex); - poll(pfdset->rwfds, numfds, 1000 /* millisecs */); + val = poll(pfdset->rwfds, numfds, 1000 /* millisecs */); + if (val < 0) + continue; need_shrink = 0; for (i = 0; i < numfds; i++) { -- 2.7.4
[dpdk-dev] [PATCH] l3fwd-acl: fix unchecked return value
Add return value check and error handling for fseek call. Coverity issue: 143435 Fixes: 361b2e9559fc ("acl: new sample l3fwd-acl") Cc: konstantin.anan...@intel.com Cc: sta...@dpdk.org Signed-off-by: Kuba Kozak Acked-by: Konstantin Ananyev --- examples/l3fwd-acl/main.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c index 8eff4de..708e9eb 100644 --- a/examples/l3fwd-acl/main.c +++ b/examples/l3fwd-acl/main.c @@ -1026,6 +1026,7 @@ add_rules(const char *rule_path, char buff[LINE_MAX]; FILE *fh = fopen(rule_path, "rb"); unsigned int i = 0; + int val; if (fh == NULL) rte_exit(EXIT_FAILURE, "%s: Open %s failed\n", __func__, @@ -1042,7 +1043,11 @@ add_rules(const char *rule_path, rte_exit(EXIT_FAILURE, "Not find any route entries in %s!\n", rule_path); - fseek(fh, 0, SEEK_SET); + val = fseek(fh, 0, SEEK_SET); + if (val < 0) { + rte_exit(EXIT_FAILURE, "%s: File seek operation failed\n", + __func__); + } acl_rules = calloc(acl_num, rule_size); -- 2.7.4