DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support
@ 2017-09-22  9:44 Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 1/5] cfgfile: remove EAL dependency Kuba Kozak
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Kuba Kozak @ 2017-09-22  9:44 UTC (permalink / raw)
  To: dev
  Cc: bruce.richardson, deepak.k.jain, michalx.k.jastrzebski,
	jacekx.piasecki, Kuba Kozak

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v6 1/5] cfgfile: remove EAL dependency
  2017-09-22  9:44 [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Kuba Kozak
@ 2017-09-22  9:44 ` Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 2/5] cfgfile: change existing API functions Kuba Kozak
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Kuba Kozak @ 2017-09-22  9:44 UTC (permalink / raw)
  To: dev
  Cc: bruce.richardson, deepak.k.jain, michalx.k.jastrzebski, jacekx.piasecki

From: Jacek Piasecki <jacekx.piasecki@intel.com>

This patch removes the dependency to EAL in cfgfile library.

Signed-off-by: Jacek Piasecki <jacekx.piasecki@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 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 <string.h>
 #include <ctype.h>
 #include <rte_common.h>
-#include <rte_string_fns.h>
 
 #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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v6 2/5] cfgfile: change existing API functions
  2017-09-22  9:44 [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 1/5] cfgfile: remove EAL dependency Kuba Kozak
@ 2017-09-22  9:44 ` Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 3/5] cfgfile: add APIs for cfgfile modification Kuba Kozak
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Kuba Kozak @ 2017-09-22  9:44 UTC (permalink / raw)
  To: dev
  Cc: bruce.richardson, deepak.k.jain, michalx.k.jastrzebski, jacekx.piasecki

From: Jacek Piasecki <jacekx.piasecki@intel.com>

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 <jacekx.piasecki@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 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 <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 #include <rte_common.h>
 
 #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_section *sect = cfg->sections;
 
 			char *split[2] = {NULL};
 			split[0] = buffer;
@@ -292,18 +307,17 @@ rte_cfgfile_load_with_params(const char *filename, int flags,
 					printf("Error - no more memory\n");
 					goto error1;
 				}
-				sect = cfg->sections[curr_section] = n_sect;
+				sect = cfg->sections = n_sect;
 			}
 
-			sect->entries[curr_entry] = malloc(
-				sizeof(*sect->entries[0]));
-			if (sect->entries[curr_entry] == NULL) {
+			sect->entries = malloc(
+				sizeof(sect->entries[0]));
+			if (sect->entries == NULL) {
 				printf("Error - no more memory\n");
 				goto error1;
 			}
 
-			struct rte_cfgfile_entry *entry = sect->entries[
-				curr_entry];
+			struct rte_cfgfile_entry *entry = sect->entries;
 			snprintf(entry->name, sizeof(entry->name), "%s",
 				split[0]);
 			snprintf(entry->value, sizeof(entry->value), "%s",
@@ -319,42 +333,38 @@ rte_cfgfile_load_with_params(const char *filename, int flags,
 	cfg->num_sections = curr_section + 1;
 	/* curr_section will still be -1 if we have an empty file */
 	if (curr_section >= 0)
-		cfg->sections[curr_section]->num_entries = curr_entry + 1;
+		cfg->sections[curr_section].num_entries = curr_entry + 1;
 	return cfg;
 
 error1:
 	cfg->num_sections = curr_section + 1;
 	if (curr_section >= 0)
-		cfg->sections[curr_section]->num_entries = curr_entry + 1;
+		cfg->sections[curr_section].num_entries = curr_entry + 1;
 	rte_cfgfile_close(cfg);
 error2:
 	fclose(f);
 	return NULL;
 }
 
-
 int rte_cfgfile_close(struct rte_cfgfile *cfg)
 {
-	int i, j;
+	int i;
 
 	if (cfg == NULL)
 		return -1;
 
-	for (i = 0; i < cfg->num_sections; i++) {
-		if (cfg->sections[i] != NULL) {
-			if (cfg->sections[i]->num_entries) {
-				for (j = 0; j < cfg->sections[i]->num_entries;
-					j++) {
-					if (cfg->sections[i]->entries[j] !=
-						NULL)
-						free(cfg->sections[i]->
-							entries[j]);
-				}
+	if (cfg->sections != NULL) {
+		for (i = 0; i < cfg->allocated_sections; i++) {
+			if (cfg->sections[i].entries != NULL) {
+				free(cfg->sections[i].entries);
+				cfg->sections[i].entries = NULL;
 			}
-			free(cfg->sections[i]);
 		}
+		free(cfg->sections);
+		cfg->sections = NULL;
 	}
 	free(cfg);
+	cfg = NULL;
 
 	return 0;
 }
@@ -366,7 +376,7 @@ size_t length)
 	int i;
 	int num_sections = 0;
 	for (i = 0; i < cfg->num_sections; i++) {
-		if (strncmp(cfg->sections[i]->name, sectionname, length) == 0)
+		if (strncmp(cfg->sections[i].name, sectionname, length) == 0)
 			num_sections++;
 	}
 	return num_sections;
@@ -380,23 +390,11 @@ rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
 
 	for (i = 0; i < cfg->num_sections && i < max_sections; i++)
 		snprintf(sections[i], CFG_NAME_LEN, "%s",
-		cfg->sections[i]->name);
+		cfg->sections[i].name);
 
 	return i;
 }
 
-static const 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;
-}
-
 int
 rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname)
 {
@@ -417,14 +415,12 @@ int
 rte_cfgfile_section_num_entries_by_index(struct rte_cfgfile *cfg,
 	char *sectionname, int index)
 {
-	const struct rte_cfgfile_section *sect;
-
 	if (index < 0 || index >= cfg->num_sections)
 		return -1;
 
-	sect = cfg->sections[index];
-	snprintf(sectionname, CFG_NAME_LEN, "%s", sect->name);
+	const struct rte_cfgfile_section *sect = &(cfg->sections[index]);
 
+	snprintf(sectionname, CFG_NAME_LEN, "%s", sect->name);
 	return sect->num_entries;
 }
 int
@@ -436,7 +432,7 @@ rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
 	if (sect == NULL)
 		return -1;
 	for (i = 0; i < max_entries && i < sect->num_entries; i++)
-		entries[i] = *sect->entries[i];
+		entries[i] = sect->entries[i];
 	return i;
 }
 
@@ -450,11 +446,10 @@ rte_cfgfile_section_entries_by_index(struct rte_cfgfile *cfg, int index,
 
 	if (index < 0 || index >= cfg->num_sections)
 		return -1;
-
-	sect = cfg->sections[index];
+	sect = &cfg->sections[index];
 	snprintf(sectionname, CFG_NAME_LEN, "%s", sect->name);
 	for (i = 0; i < max_entries && i < sect->num_entries; i++)
-		entries[i] = *sect->entries[i];
+		entries[i] = sect->entries[i];
 	return i;
 }
 
@@ -467,9 +462,9 @@ rte_cfgfile_get_entry(struct rte_cfgfile *cfg, const char *sectionname,
 	if (sect == NULL)
 		return NULL;
 	for (i = 0; i < sect->num_entries; i++)
-		if (strncmp(sect->entries[i]->name, entryname, CFG_NAME_LEN)
-			== 0)
-			return sect->entries[i]->value;
+		if (strncmp(sect->entries[i].name, entryname, CFG_NAME_LEN)
+									== 0)
+			return sect->entries[i].value;
 	return NULL;
 }
 
-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v6 3/5] cfgfile: add APIs for cfgfile modification
  2017-09-22  9:44 [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 1/5] cfgfile: remove EAL dependency Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 2/5] cfgfile: change existing API functions Kuba Kozak
@ 2017-09-22  9:44 ` Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 4/5] cfgfile: rework of load function Kuba Kozak
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Kuba Kozak @ 2017-09-22  9:44 UTC (permalink / raw)
  To: dev
  Cc: bruce.richardson, deepak.k.jain, michalx.k.jastrzebski, jacekx.piasecki

From: Jacek Piasecki <jacekx.piasecki@intel.com>

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 <jacekx.piasecki@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 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 =
+					&section->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_SECTION_BATCH;
+	}
+
+	snprintf(cfg->sections[cfg->num_sections].name,
+			sizeof(cfg->sections[0].name), "%s", sectionname);
+	cfg->sections[cfg->num_sections].num_entries = 0;
+	cfg->num_sections++;
+
+	return 0;
+}
+
+int rte_cfgfile_add_entry(struct rte_cfgfile *cfg,
+		const char *sectionname, const char *entryname,
+		const char *entryvalue)
+{
+	int ret;
+
+	if ((cfg == NULL) || (sectionname == NULL) || (entryname == NULL)
+			|| (entryvalue == NULL))
+		return -EINVAL;
+
+	if (rte_cfgfile_has_entry(cfg, sectionname, entryname) != 0)
+		return -EEXIST;
+
+	/* search for section pointer by sectionname */
+	struct rte_cfgfile_section *curr_section = _get_section(cfg,
+								sectionname);
+	if (curr_section == NULL)
+		return -EINVAL;
+
+	ret = _add_entry(curr_section, entryname, entryvalue);
+
+	return ret;
+}
+
+int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
+		const char *entryname, const char *entryvalue)
+{
+	int i;
+
+	if ((cfg == NULL) || (sectionname == NULL) || (entryname == NULL))
+		return -EINVAL;
+
+	/* search for section pointer by sectionname */
+	struct rte_cfgfile_section *curr_section = _get_section(cfg,
+								sectionname);
+	if (curr_section == NULL)
+		return -EINVAL;
+
+	if (entryvalue == NULL)
+		entryvalue = "";
+
+	for (i = 0; i < curr_section->num_entries; i++)
+		if (!strcmp(curr_section->entries[i].name, entryname)) {
+			snprintf(curr_section->entries[i].value,
+					sizeof(curr_section->entries[i].value),
+							"%s", entryvalue);
+			return 0;
+		}
+	printf("Error - entry name doesn't exist\n");
+	return -EINVAL;
+}
+
+int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
+{
+	int i, j;
+
+	if ((cfg == NULL) || (filename == NULL))
+		return -EINVAL;
+
+	FILE *f = fopen(filename, "w");
+
+	if (f == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < cfg->num_sections; i++) {
+		fprintf(f, "[%s]\n", cfg->sections[i].name);
+
+		for (j = 0; j < cfg->sections[i].num_entries; j++) {
+			fprintf(f, "%s=%s\n",
+					cfg->sections[i].entries[j].name,
+					cfg->sections[i].entries[j].value);
+		}
+	}
+	return fclose(f);
+}
+
 int rte_cfgfile_close(struct rte_cfgfile *cfg)
 {
 	int i;
diff --git a/lib/librte_cfgfile/rte_cfgfile.h b/lib/librte_cfgfile/rte_cfgfile.h
index 35dc419..17f7275 100644
--- a/lib/librte_cfgfile/rte_cfgfile.h
+++ b/lib/librte_cfgfile/rte_cfgfile.h
@@ -121,6 +121,82 @@ struct rte_cfgfile *rte_cfgfile_load_with_params(const char *filename,
 	int flags, const struct rte_cfgfile_parameters *params);
 
 /**
+ * Create new cfgfile instance with empty sections and entries
+ *
+ * @param flags
+ *   - CFG_FLAG_GLOBAL_SECTION
+ *     Indicates that the file supports key value entries before the first
+ *     defined section.  These entries can be accessed in the "GLOBAL"
+ *     section.
+ *   - CFG_FLAG_EMPTY_VALUES
+ *     Indicates that file supports key value entries where the value can
+ *     be zero length (e.g., "key=").
+ * @return
+ *   Handle to cfgfile instance on success, NULL otherwise
+ */
+struct rte_cfgfile *rte_cfgfile_create(int flags);
+
+/**
+ * Add section in cfgfile instance.
+ *
+ * @param cfg
+ *   Pointer to the cfgfile structure.
+ * @param sectionname
+ *   Section name which will be add to cfgfile.
+ * @return
+ *   0 on success, -ENOMEM if can't add section
+ */
+int
+rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname);
+
+/**
+ * Add entry to specified section in cfgfile instance.
+ *
+ * @param cfg
+ *   Pointer to the cfgfile structure.
+ * @param sectionname
+ *   Given section name to add an entry.
+ * @param entryname
+ *   Entry name to add.
+ * @param entryvalue
+ *   Entry value to add.
+ * @return
+ *   0 on success, -EEXIST if entry already exist, -EINVAL if bad argument
+ */
+int rte_cfgfile_add_entry(struct rte_cfgfile *cfg,
+		const char *sectionname, const char *entryname,
+		const char *entryvalue);
+
+/**
+ * Update value of specified entry name in given section in config file
+ *
+ * @param cfg
+ *   Config file
+ * @param sectionname
+ *   Section name
+ * @param entryname
+ *   Entry name to look for the value change
+ * @param entryvalue
+ *   New entry value. Can be also an empty string if CFG_FLAG_EMPTY_VALUES = 1
+ * @return
+ *   0 on success, -EINVAL if bad argument
+ */
+int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
+		const char *entryname, const char *entryvalue);
+
+/**
+ * Save object cfgfile to file on disc
+ *
+ * @param cfg
+ *   Config file structure
+ * @param filename
+ *   File name to save data
+ * @return
+ *   0 on success, errno otherwise
+ */
+int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename);
+
+/**
 * Get number of sections in config file
 *
 * @param cfg
diff --git a/lib/librte_cfgfile/rte_cfgfile_version.map b/lib/librte_cfgfile/rte_cfgfile_version.map
index 5fe60f7..de68ff6 100644
--- a/lib/librte_cfgfile/rte_cfgfile_version.map
+++ b/lib/librte_cfgfile/rte_cfgfile_version.map
@@ -27,3 +27,14 @@ DPDK_17.05 {
     rte_cfgfile_load_with_params;
 
 } DPDK_16.04;
+
+DPDK_17.08 {
+	global:
+
+	rte_cfgfile_add_entry;
+	rte_cfgfile_add_section;
+	rte_cfgfile_create;
+	rte_cfgfile_save;
+	rte_cfgfile_set_entry;
+
+} DPDK_17.05;
\ No newline at end of file
-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v6 4/5] cfgfile: rework of load function
  2017-09-22  9:44 [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Kuba Kozak
                   ` (2 preceding siblings ...)
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 3/5] cfgfile: add APIs for cfgfile modification Kuba Kozak
@ 2017-09-22  9:44 ` Kuba Kozak
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 5/5] test/cfgfile: add new unit test Kuba Kozak
  2017-10-08 22:55 ` [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Kuba Kozak @ 2017-09-22  9:44 UTC (permalink / raw)
  To: dev
  Cc: bruce.richardson, deepak.k.jain, michalx.k.jastrzebski, jacekx.piasecki

From: Jacek Piasecki <jacekx.piasecki@intel.com>

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 <jacekx.piasecki@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 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]) +
-				sizeof(cfg->sections[0].entries) *
-				allocated_entries);
-			if (cfg->sections == NULL) {
-				printf("Error - no more memory\n");
-				goto error1;
-			}
-
-			snprintf(cfg->sections[curr_section].name,
-					sizeof(cfg->sections[0].name),
-					"%s", &buffer[1]);
+			rte_cfgfile_add_section(cfg, &buffer[1]);
 		} else {
-			/* value line */
-			if (curr_section < 0) {
-				printf("Error line %d - value outside of"
-					"section\n", lineno);
-				goto error1;
-			}
-
-			struct rte_cfgfile_section *sect = cfg->sections;
-
+			/* key and value line */
 			char *split[2] = {NULL};
+
 			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 {
-				/* 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;
-				}
+			*split[1] = '\0';
+			split[1]++;
+
+			_strip(split[0], strlen(split[0]));
+			_strip(split[1], strlen(split[1]));
+			char *end = memchr(split[1], '\\', strlen(split[1]));
+
+			while (end != NULL) {
+				if (*(end+1) == params->comment_character) {
+					*end = '\0';
+					strcat(split[1], end+1);
+				} else
+					end++;
+				end = memchr(end, '\\', strlen(end));
 			}
 
-			curr_entry++;
-			if (curr_entry == allocated_entries) {
-				allocated_entries += CFG_ALLOC_ENTRY_BATCH;
-				struct rte_cfgfile_section *n_sect = realloc(
-					sect, sizeof(*sect) +
-					sizeof(sect->entries[0]) *
-					allocated_entries);
-				if (n_sect == NULL) {
-					curr_entry--;
-					printf("Error - no more memory\n");
-					goto error1;
-				}
-				sect = cfg->sections = n_sect;
+			if (!(flags & CFG_FLAG_EMPTY_VALUES) &&
+					(*split[1] == '\0')) {
+				printf("Error at line %d - cannot use empty "
+							"values\n", lineno);
+				goto error1;
 			}
 
-			sect->entries = malloc(
-				sizeof(sect->entries[0]));
-			if (sect->entries == NULL) {
-				printf("Error - no more memory\n");
+			if (cfg->num_sections == 0)
 				goto error1;
-			}
 
-			struct rte_cfgfile_entry *entry = sect->entries;
-			snprintf(entry->name, sizeof(entry->name), "%s",
-				split[0]);
-			snprintf(entry->value, sizeof(entry->value), "%s",
-				 split[1] ? split[1] : "");
-			_strip(entry->name, strnlen(entry->name,
-				sizeof(entry->name)));
-			_strip(entry->value, strnlen(entry->value,
-				sizeof(entry->value)));
+			_add_entry(&cfg->sections[cfg->num_sections - 1],
+					split[0], (split[1] ? split[1] : ""));
 		}
 	}
 	fclose(f);
-	cfg->flags = flags;
-	cfg->num_sections = curr_section + 1;
-	/* curr_section will still be -1 if we have an empty file */
-	if (curr_section >= 0)
-		cfg->sections[curr_section].num_entries = curr_entry + 1;
 	return cfg;
-
 error1:
-	cfg->num_sections = curr_section + 1;
-	if (curr_section >= 0)
-		cfg->sections[curr_section].num_entries = curr_entry + 1;
 	rte_cfgfile_close(cfg);
-error2:
 	fclose(f);
 	return NULL;
 }
-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [dpdk-dev] [PATCH v6 5/5] test/cfgfile: add new unit test
  2017-09-22  9:44 [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Kuba Kozak
                   ` (3 preceding siblings ...)
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 4/5] cfgfile: rework of load function Kuba Kozak
@ 2017-09-22  9:44 ` Kuba Kozak
  2017-10-08 22:55 ` [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Kuba Kozak @ 2017-09-22  9:44 UTC (permalink / raw)
  To: dev
  Cc: bruce.richardson, deepak.k.jain, michalx.k.jastrzebski, jacekx.piasecki

From: Jacek Piasecki <jacekx.piasecki@intel.com>

Load huge realloc_sections.ini file to check malloc/realloc
ability of cfgfile library.

Signed-off-by: Jacek Piasecki <jacekx.piasecki@intel.com>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 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 0000000..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_section8
+key2=value2_section8
+key3=value3_section8
+key4=value4_section8
+key5=value5_section8
+key6=value6_section8
+key7=value7_section8
+key8=value8_section8
+
+[section9]
+key1=value1_section9
+key2=value2_section9
+key3=value3_section9
+key4=value4_section9
+key5=value5_section9
+key6=value6_section9
+key7=value7_section9
+key8=value8_section9
-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support
  2017-09-22  9:44 [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Kuba Kozak
                   ` (4 preceding siblings ...)
  2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 5/5] test/cfgfile: add new unit test Kuba Kozak
@ 2017-10-08 22:55 ` Thomas Monjalon
  5 siblings, 0 replies; 7+ messages in thread
From: Thomas Monjalon @ 2017-10-08 22:55 UTC (permalink / raw)
  To: Kuba Kozak, jacekx.piasecki
  Cc: dev, bruce.richardson, deepak.k.jain, michalx.k.jastrzebski

22/09/2017 11:44, Kuba Kozak:
> 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.

I have fixed the map file (switched to 17.11) and
applied, thanks.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-10-08 22:55 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-22  9:44 [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Kuba Kozak
2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 1/5] cfgfile: remove EAL dependency Kuba Kozak
2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 2/5] cfgfile: change existing API functions Kuba Kozak
2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 3/5] cfgfile: add APIs for cfgfile modification Kuba Kozak
2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 4/5] cfgfile: rework of load function Kuba Kozak
2017-09-22  9:44 ` [dpdk-dev] [PATCH v6 5/5] test/cfgfile: add new unit test Kuba Kozak
2017-10-08 22:55 ` [dpdk-dev] [PATCH v6 0/5] Rework cfgfile API to enable apps config file support Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).