[RFC] kvargs: add match count inside processing
diff mbox series

Message ID 20181130003938.27964-1-thomas@monjalon.net
State New
Delegated to: Thomas Monjalon
Headers show
Series
  • [RFC] kvargs: add match count inside processing
Related show

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch success coding style OK

Commit Message

Thomas Monjalon Nov. 30, 2018, 12:39 a.m. UTC
After processing a kvlist in rte_kvargs_process(),
it may be needed to loop again over kvlist, in order to know
whether the key is matched or not, as done with rte_kvargs_count().

In order to simplify implementation of kvargs checks,
a new pointer parameter is added to get the match count from
the function rte_kvargs_process().

This count could have been returned as a positive value of the function,
but it would change also the meaning of "return 0".
It looks simpler to keep return code as 0 or negative,
and add a dedicated output parameter for counting purpose.

Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
---

This RFC is not complete: the calls to rte_kvargs_process()
in the drivers must be updated with the new parameter,
and simplified if rte_kvargs_count() is used.

---
 app/pdump/main.c                              | 20 ++++-----
 doc/guides/rel_notes/deprecation.rst          |  3 --
 doc/guides/rel_notes/release_19_02.rst        |  5 ++-
 drivers/baseband/null/bbdev_null.c            |  6 ++-
 .../baseband/turbo_sw/bbdev_turbo_software.c  |  6 ++-
 drivers/bus/ifpga/ifpga_bus.c                 | 44 +++++++++----------
 drivers/bus/pci/pci_params.c                  |  1 +
 drivers/bus/vdev/vdev_params.c                |  2 +-
 lib/librte_compressdev/rte_compressdev_pmd.c  |  4 +-
 lib/librte_cryptodev/rte_cryptodev_pmd.c      |  6 +--
 lib/librte_ethdev/rte_class_eth.c             | 20 +++------
 lib/librte_kvargs/Makefile                    |  2 +-
 lib/librte_kvargs/meson.build                 |  2 +-
 lib/librte_kvargs/rte_kvargs.c                | 18 ++++++--
 lib/librte_kvargs/rte_kvargs.h                | 14 +++---
 test/test/test_kvargs.c                       | 31 +++++++++++--
 16 files changed, 107 insertions(+), 77 deletions(-)

Patch
diff mbox series

diff --git a/app/pdump/main.c b/app/pdump/main.c
index 9e86bf623..255ff61fe 100644
--- a/app/pdump/main.c
+++ b/app/pdump/main.c
@@ -262,14 +262,14 @@  parse_pdump(const char *optarg)
 	} else if (cnt1 == 1) {
 		v.min = 0;
 		v.max = RTE_MAX_ETHPORTS-1;
-		ret = rte_kvargs_process(kvlist, PDUMP_PORT_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_PORT_ARG, NULL,
 				&parse_uint_value, &v);
 		if (ret < 0)
 			goto free_kvlist;
 		pt->port = (uint16_t) v.val;
 		pt->dump_by_type = PORT_ID;
 	} else if (cnt2 == 1) {
-		ret = rte_kvargs_process(kvlist, PDUMP_PCI_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_PCI_ARG, NULL,
 				&parse_device_id, pt);
 		if (ret < 0)
 			goto free_kvlist;
@@ -282,7 +282,7 @@  parse_pdump(const char *optarg)
 		ret = -1;
 		goto free_kvlist;
 	}
-	ret = rte_kvargs_process(kvlist, PDUMP_QUEUE_ARG, &parse_queue, pt);
+	ret = rte_kvargs_process(kvlist, PDUMP_QUEUE_ARG, NULL, &parse_queue, pt);
 	if (ret < 0)
 		goto free_kvlist;
 
@@ -295,11 +295,11 @@  parse_pdump(const char *optarg)
 		ret = -1;
 		goto free_kvlist;
 	} else if (cnt1 == 1 && cnt2 == 1) {
-		ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG, NULL,
 					&parse_rxtxdev, pt);
 		if (ret < 0)
 			goto free_kvlist;
-		ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG, NULL,
 					&parse_rxtxdev, pt);
 		if (ret < 0)
 			goto free_kvlist;
@@ -308,13 +308,13 @@  parse_pdump(const char *optarg)
 			pt->single_pdump_dev = true;
 		pt->dir = RTE_PDUMP_FLAG_RXTX;
 	} else if (cnt1 == 1) {
-		ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_RX_DEV_ARG, NULL,
 					&parse_rxtxdev, pt);
 		if (ret < 0)
 			goto free_kvlist;
 		pt->dir = RTE_PDUMP_FLAG_RX;
 	} else if (cnt2 == 1) {
-		ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_TX_DEV_ARG, NULL,
 					&parse_rxtxdev, pt);
 		if (ret < 0)
 			goto free_kvlist;
@@ -327,7 +327,7 @@  parse_pdump(const char *optarg)
 	if (cnt1 == 1) {
 		v.min = 2;
 		v.max = RTE_RING_SZ_MASK-1;
-		ret = rte_kvargs_process(kvlist, PDUMP_RING_SIZE_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_RING_SIZE_ARG, NULL,
 						&parse_uint_value, &v);
 		if (ret < 0)
 			goto free_kvlist;
@@ -340,7 +340,7 @@  parse_pdump(const char *optarg)
 	if (cnt1 == 1) {
 		v.min = 1;
 		v.max = UINT16_MAX;
-		ret = rte_kvargs_process(kvlist, PDUMP_MSIZE_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_MSIZE_ARG, NULL,
 						&parse_uint_value, &v);
 		if (ret < 0)
 			goto free_kvlist;
@@ -353,7 +353,7 @@  parse_pdump(const char *optarg)
 	if (cnt1 == 1) {
 		v.min = 1025;
 		v.max = UINT16_MAX;
-		ret = rte_kvargs_process(kvlist, PDUMP_NUM_MBUFS_ARG,
+		ret = rte_kvargs_process(kvlist, PDUMP_NUM_MBUFS_ARG, NULL,
 						&parse_uint_value, &v);
 		if (ret < 0)
 			goto free_kvlist;
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index b48486d36..4ff96c5ec 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -17,9 +17,6 @@  Deprecation Notices
   Long Term Stable (LTS) version which is 3.16, but compatibility for
   recent distribution kernels will be kept.
 
-* kvargs: The function ``rte_kvargs_process`` will get a new parameter
-  for returning key match count. It will ease handling of no-match case.
-
 * eal: function ``rte_bsf64`` in ``rte_bitmap.h`` has been renamed to
   ``rte_bsf64_safe`` and moved to ``rte_common.h``. A new ``rte_bsf64`` function
   will be added in the next release in ``rte_common.h`` that follows convention
diff --git a/doc/guides/rel_notes/release_19_02.rst b/doc/guides/rel_notes/release_19_02.rst
index a94fa86a7..c5dfff5f8 100644
--- a/doc/guides/rel_notes/release_19_02.rst
+++ b/doc/guides/rel_notes/release_19_02.rst
@@ -83,6 +83,9 @@  API Changes
    Also, make sure to start the actual text at the margin.
    =========================================================
 
+kvargs: A parameter is added to ``rte_kvargs_process()`` in order to get
+the match count in one pass (without calling ``rte_kvargs_count()``).
+
 
 ABI Changes
 -----------
@@ -143,7 +146,7 @@  The libraries prepended with a plus sign were incremented in this version.
      librte_ip_frag.so.1
      librte_jobstats.so.1
      librte_kni.so.2
-     librte_kvargs.so.1
+   + librte_kvargs.so.2
      librte_latencystats.so.1
      librte_lpm.so.2
      librte_mbuf.so.4
diff --git a/drivers/baseband/null/bbdev_null.c b/drivers/baseband/null/bbdev_null.c
index 2f2515101..eeae9962d 100644
--- a/drivers/baseband/null/bbdev_null.c
+++ b/drivers/baseband/null/bbdev_null.c
@@ -228,12 +228,14 @@  parse_bbdev_null_params(struct bbdev_null_params *params,
 		if (kvlist == NULL)
 			return -EFAULT;
 
-		ret = rte_kvargs_process(kvlist, bbdev_null_valid_params[0],
+		ret = rte_kvargs_process(kvlist,
+					bbdev_null_valid_params[0], NULL,
 					&parse_u16_arg, &params->queues_num);
 		if (ret < 0)
 			goto exit;
 
-		ret = rte_kvargs_process(kvlist, bbdev_null_valid_params[1],
+		ret = rte_kvargs_process(kvlist,
+					bbdev_null_valid_params[1], NULL,
 					&parse_u16_arg, &params->socket_id);
 		if (ret < 0)
 			goto exit;
diff --git a/drivers/baseband/turbo_sw/bbdev_turbo_software.c b/drivers/baseband/turbo_sw/bbdev_turbo_software.c
index 8ceb2769f..9cc01d164 100644
--- a/drivers/baseband/turbo_sw/bbdev_turbo_software.c
+++ b/drivers/baseband/turbo_sw/bbdev_turbo_software.c
@@ -1179,12 +1179,14 @@  parse_turbo_sw_params(struct turbo_sw_params *params, const char *input_args)
 		if (kvlist == NULL)
 			return -EFAULT;
 
-		ret = rte_kvargs_process(kvlist, turbo_sw_valid_params[0],
+		ret = rte_kvargs_process(kvlist,
+					turbo_sw_valid_params[0], NULL,
 					&parse_u16_arg, &params->queues_num);
 		if (ret < 0)
 			goto exit;
 
-		ret = rte_kvargs_process(kvlist, turbo_sw_valid_params[1],
+		ret = rte_kvargs_process(kvlist,
+					turbo_sw_valid_params[1], NULL,
 					&parse_u16_arg, &params->socket_id);
 		if (ret < 0)
 			goto exit;
diff --git a/drivers/bus/ifpga/ifpga_bus.c b/drivers/bus/ifpga/ifpga_bus.c
index 5f23ed8b4..05ff9771f 100644
--- a/drivers/bus/ifpga/ifpga_bus.c
+++ b/drivers/bus/ifpga/ifpga_bus.c
@@ -94,6 +94,7 @@  ifpga_scan_one(struct rte_rawdev *rawdev,
 	struct rte_kvargs *kvlist = NULL;
 	struct rte_afu_device *afu_dev = NULL;
 	struct rte_afu_pr_conf afu_pr_conf;
+	unsigned int key_count;
 	int ret = 0;
 	char *path = NULL;
 
@@ -105,27 +106,24 @@  ifpga_scan_one(struct rte_rawdev *rawdev,
 		goto end;
 	}
 
-	if (rte_kvargs_count(kvlist, IFPGA_ARG_PORT) == 1) {
-		if (rte_kvargs_process(kvlist, IFPGA_ARG_PORT,
-		&rte_ifpga_get_integer32_arg, &afu_pr_conf.afu_id.port) < 0) {
-			IFPGA_BUS_ERR("error to parse %s",
-				     IFPGA_ARG_PORT);
-			goto end;
-		}
-	} else {
+	if (rte_kvargs_process(kvlist, IFPGA_ARG_PORT, &key_count,
+			&rte_ifpga_get_integer32_arg,
+			&afu_pr_conf.afu_id.port) < 0) {
+		IFPGA_BUS_ERR("error to parse %s", IFPGA_ARG_PORT);
+		goto end;
+	}
+	if (key_count == 0) {
 		IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus",
 			  IFPGA_ARG_PORT);
 		goto end;
 	}
 
-	if (rte_kvargs_count(kvlist, IFPGA_AFU_BTS) == 1) {
-		if (rte_kvargs_process(kvlist, IFPGA_AFU_BTS,
-				       &rte_ifpga_get_string_arg, &path) < 0) {
-			IFPGA_BUS_ERR("Failed to parse %s",
-				     IFPGA_AFU_BTS);
-			goto end;
-		}
-	} else {
+	if (rte_kvargs_process(kvlist, IFPGA_AFU_BTS, &key_count,
+			&rte_ifpga_get_string_arg, &path) < 0) {
+		IFPGA_BUS_ERR("Failed to parse %s", IFPGA_AFU_BTS);
+		goto end;
+	}
+	if (key_count == 0) {
 		IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus",
 			  IFPGA_AFU_BTS);
 		goto end;
@@ -195,6 +193,7 @@  ifpga_scan(void)
 	struct rte_devargs *devargs;
 	struct rte_kvargs *kvlist = NULL;
 	struct rte_rawdev *rawdev = NULL;
+	unsigned int key_count;
 	char *name = NULL;
 	char name1[RTE_RAWDEV_NAME_MAX_LEN];
 	struct rte_afu_device *afu_dev = NULL;
@@ -210,14 +209,11 @@  ifpga_scan(void)
 			goto end;
 		}
 
-		if (rte_kvargs_count(kvlist, IFPGA_ARG_NAME) == 1) {
-			if (rte_kvargs_process(kvlist, IFPGA_ARG_NAME,
-				       &rte_ifpga_get_string_arg, &name) < 0) {
-				IFPGA_BUS_ERR("error to parse %s",
-				     IFPGA_ARG_NAME);
-				goto end;
-			}
-		} else {
+		if (rte_kvargs_process(kvlist, IFPGA_ARG_NAME, &key_count,
+				&rte_ifpga_get_string_arg, &name) < 0) {
+			IFPGA_BUS_ERR("error to parse %s", IFPGA_ARG_NAME);
+			goto end;
+		if (key_count == 0) {
 			IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus",
 			  IFPGA_ARG_NAME);
 			goto end;
diff --git a/drivers/bus/pci/pci_params.c b/drivers/bus/pci/pci_params.c
index 3192e9c96..215ffef70 100644
--- a/drivers/bus/pci/pci_params.c
+++ b/drivers/bus/pci/pci_params.c
@@ -48,6 +48,7 @@  pci_dev_match(const struct rte_device *dev,
 	pdev = RTE_DEV_TO_PCI_CONST(dev);
 	/* if any field does not match. */
 	if (rte_kvargs_process(kvlist, pci_params_keys[RTE_PCI_PARAM_ADDR],
+			       NULL,
 			       &pci_addr_kv_cmp,
 			       (void *)(intptr_t)&pdev->addr))
 		return 1;
diff --git a/drivers/bus/vdev/vdev_params.c b/drivers/bus/vdev/vdev_params.c
index 6f74704d1..9c00ed44f 100644
--- a/drivers/bus/vdev/vdev_params.c
+++ b/drivers/bus/vdev/vdev_params.c
@@ -35,7 +35,7 @@  vdev_dev_match(const struct rte_device *dev,
 	if (name == NULL)
 		return -1;
 	ret = rte_kvargs_process(kvlist,
-		vdev_params_keys[RTE_VDEV_PARAM_NAME],
+		vdev_params_keys[RTE_VDEV_PARAM_NAME], NULL,
 		rte_kvargs_strcmp, name);
 	free(name);
 	if (ret != 0)
diff --git a/lib/librte_compressdev/rte_compressdev_pmd.c b/lib/librte_compressdev/rte_compressdev_pmd.c
index 95beb26ab..43e79fcbc 100644
--- a/lib/librte_compressdev/rte_compressdev_pmd.c
+++ b/lib/librte_compressdev/rte_compressdev_pmd.c
@@ -64,14 +64,14 @@  rte_compressdev_pmd_parse_input_args(
 			return -EINVAL;
 
 		ret = rte_kvargs_process(kvlist,
-				RTE_COMPRESSDEV_PMD_SOCKET_ID_ARG,
+				RTE_COMPRESSDEV_PMD_SOCKET_ID_ARG, NULL,
 				&rte_compressdev_pmd_parse_uint_arg,
 				&params->socket_id);
 		if (ret < 0)
 			goto free_kvlist;
 
 		ret = rte_kvargs_process(kvlist,
-				RTE_COMPRESSDEV_PMD_NAME_ARG,
+				RTE_COMPRESSDEV_PMD_NAME_ARG, NULL,
 				&rte_compressdev_pmd_parse_name_arg,
 				params);
 		if (ret < 0)
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.c b/lib/librte_cryptodev/rte_cryptodev_pmd.c
index f03bdbd5e..04b064346 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.c
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.c
@@ -59,21 +59,21 @@  rte_cryptodev_pmd_parse_input_args(
 			return -EINVAL;
 
 		ret = rte_kvargs_process(kvlist,
-				RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG,
+				RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG, NULL,
 				&rte_cryptodev_pmd_parse_uint_arg,
 				&params->max_nb_queue_pairs);
 		if (ret < 0)
 			goto free_kvlist;
 
 		ret = rte_kvargs_process(kvlist,
-				RTE_CRYPTODEV_PMD_SOCKET_ID_ARG,
+				RTE_CRYPTODEV_PMD_SOCKET_ID_ARG, NULL,
 				&rte_cryptodev_pmd_parse_uint_arg,
 				&params->socket_id);
 		if (ret < 0)
 			goto free_kvlist;
 
 		ret = rte_kvargs_process(kvlist,
-				RTE_CRYPTODEV_PMD_NAME_ARG,
+				RTE_CRYPTODEV_PMD_NAME_ARG, NULL,
 				&rte_cryptodev_pmd_parse_name_arg,
 				params);
 		if (ret < 0)
diff --git a/lib/librte_ethdev/rte_class_eth.c b/lib/librte_ethdev/rte_class_eth.c
index cb99c92ec..bf6a5f2cf 100644
--- a/lib/librte_ethdev/rte_class_eth.c
+++ b/lib/librte_ethdev/rte_class_eth.c
@@ -106,7 +106,7 @@  eth_dev_match(const struct rte_eth_dev *edev,
 	int ret;
 	const struct eth_dev_match_arg *arg = _arg;
 	const struct rte_kvargs *kvlist = arg->kvlist;
-	unsigned int pair;
+	unsigned int match_count;
 
 	if (edev->state == RTE_ETH_DEV_UNUSED)
 		return -1;
@@ -114,27 +114,19 @@  eth_dev_match(const struct rte_eth_dev *edev,
 		return -1;
 
 	ret = rte_kvargs_process(kvlist,
-			eth_params_keys[RTE_ETH_PARAM_MAC],
+			eth_params_keys[RTE_ETH_PARAM_MAC], NULL,
 			eth_mac_cmp, edev->data);
 	if (ret != 0)
 		return -1;
 
 	ret = rte_kvargs_process(kvlist,
-			eth_params_keys[RTE_ETH_PARAM_REPRESENTOR],
+			eth_params_keys[RTE_ETH_PARAM_REPRESENTOR], &match_count,
 			eth_representor_cmp, edev->data);
 	if (ret != 0)
 		return -1;
-	/* search for representor key */
-	for (pair = 0; pair < kvlist->count; pair++) {
-		ret = strcmp(kvlist->pairs[pair].key,
-				eth_params_keys[RTE_ETH_PARAM_REPRESENTOR]);
-		if (ret == 0)
-			break; /* there is a representor key */
-	}
-	/* if no representor key, default is to not match representor ports */
-	if (ret != 0)
-		if ((edev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0)
-			return -1; /* do not match any representor */
+	if (match_count == 0  /* if no representor key */  &&
+			(edev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0)
+		return -1; /* do not match any representor */
 
 	return 0;
 }
diff --git a/lib/librte_kvargs/Makefile b/lib/librte_kvargs/Makefile
index 875939547..11f013739 100644
--- a/lib/librte_kvargs/Makefile
+++ b/lib/librte_kvargs/Makefile
@@ -11,7 +11,7 @@  CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include
 
 EXPORT_MAP := rte_kvargs_version.map
 
-LIBABIVER := 1
+LIBABIVER := 2
 
 # all source are stored in SRCS-y
 SRCS-$(CONFIG_RTE_LIBRTE_KVARGS) := rte_kvargs.c
diff --git a/lib/librte_kvargs/meson.build b/lib/librte_kvargs/meson.build
index acd3e5432..a00d198ed 100644
--- a/lib/librte_kvargs/meson.build
+++ b/lib/librte_kvargs/meson.build
@@ -4,7 +4,7 @@ 
 includes = [global_inc]
 includes += include_directories('../librte_eal/common/include')
 
-version = 1
+version = 2
 sources = files('rte_kvargs.c')
 headers = files('rte_kvargs.h')
 
diff --git a/lib/librte_kvargs/rte_kvargs.c b/lib/librte_kvargs/rte_kvargs.c
index f7030c63b..02c7ec1a8 100644
--- a/lib/librte_kvargs/rte_kvargs.c
+++ b/lib/librte_kvargs/rte_kvargs.c
@@ -128,20 +128,30 @@  rte_kvargs_count(const struct rte_kvargs *kvlist, const char *key_match)
 int
 rte_kvargs_process(const struct rte_kvargs *kvlist,
 		const char *key_match,
-		arg_handler_t handler,
-		void *opaque_arg)
+		unsigned int *match_count,
+		arg_handler_t match_handler,
+		void *opaque)
 {
+	int ret;
 	const struct rte_kvargs_pair *pair;
 	unsigned i;
 
+	if (match_count != NULL)
+		*match_count = 0;
+
 	if (kvlist == NULL)
 		return 0;
 
 	for (i = 0; i < kvlist->count; i++) {
 		pair = &kvlist->pairs[i];
 		if (key_match == NULL || strcmp(pair->key, key_match) == 0) {
-			if ((*handler)(pair->key, pair->value, opaque_arg) < 0)
-				return -1;
+			if (match_count != NULL)
+				(*match_count)++;
+			if (match_handler == NULL)
+				continue;
+			ret = (*match_handler)(pair->key, pair->value, opaque);
+			if (ret < 0)
+				return ret;
 		}
 	}
 	return 0;
diff --git a/lib/librte_kvargs/rte_kvargs.h b/lib/librte_kvargs/rte_kvargs.h
index 1946195de..e9f47ae65 100644
--- a/lib/librte_kvargs/rte_kvargs.h
+++ b/lib/librte_kvargs/rte_kvargs.h
@@ -118,17 +118,18 @@  void rte_kvargs_free(struct rte_kvargs *kvlist);
  * Call a handler function for each key/value matching the key
  *
  * For each key/value association that matches the given key, calls the
- * handler function with the for a given arg_name passing the value on the
- * dictionary for that key and a given extra argument.
+ * handler function and count the matches.
  *
  * @param kvlist
  *   The rte_kvargs structure. No error if NULL.
  * @param key_match
  *   The key on which the handler should be called, or NULL to process handler
  *   on all associations
- * @param handler
- *   The function to call for each matching key
- * @param opaque_arg
+ * @param match_count
+ *   The number of times the key matches in kvlist (can be NULL).
+ * @param match_handler
+ *   The function to call for each matching key (can be NULL).
+ * @param opaque
  *   A pointer passed unchanged to the handler
  *
  * @return
@@ -136,7 +137,8 @@  void rte_kvargs_free(struct rte_kvargs *kvlist);
  *   - Negative on error
  */
 int rte_kvargs_process(const struct rte_kvargs *kvlist,
-	const char *key_match, arg_handler_t handler, void *opaque_arg);
+	const char *key_match, unsigned int *match_count,
+	arg_handler_t match_handler, void *opaque);
 
 /**
  * Count the number of associations matching the given key
diff --git a/test/test/test_kvargs.c b/test/test/test_kvargs.c
index a42056f36..648f40e8e 100644
--- a/test/test/test_kvargs.c
+++ b/test/test/test_kvargs.c
@@ -42,6 +42,7 @@  static int test_valid_kvargs(void)
 	const char *args;
 	const char *valid_keys_list[] = { "foo", "check", NULL };
 	const char **valid_keys;
+	unsigned int match_count;
 
 	/* empty args is valid */
 	args = "";
@@ -63,11 +64,19 @@  static int test_valid_kvargs(void)
 	}
 	/* call check_handler() for all entries with key="check" */
 	count = 0;
-	if (rte_kvargs_process(kvlist, "check", check_handler, NULL) < 0) {
+	if (rte_kvargs_process(kvlist, "check", &match_count,
+			check_handler, NULL) < 0) {
 		printf("rte_kvargs_process() error\n");
 		rte_kvargs_free(kvlist);
 		goto fail;
 	}
+	if (match_count != 2) {
+		printf("invalid match_count value %d"
+			" after rte_kvargs_process(check)\n",
+			count);
+		rte_kvargs_free(kvlist);
+		goto fail;
+	}
 	if (count != 2) {
 		printf("invalid count value %d after rte_kvargs_process(check)\n",
 			count);
@@ -76,11 +85,19 @@  static int test_valid_kvargs(void)
 	}
 	count = 0;
 	/* call check_handler() for all entries with key="unexistant_key" */
-	if (rte_kvargs_process(kvlist, "unexistant_key", check_handler, NULL) < 0) {
+	if (rte_kvargs_process(kvlist, "unexistant_key", &match_count,
+			check_handler, NULL) < 0) {
 		printf("rte_kvargs_process() error\n");
 		rte_kvargs_free(kvlist);
 		goto fail;
 	}
+	if (match_count != 0) {
+		printf("invalid match_count value %d"
+			" after rte_kvargs_process(unexistant_key)\n",
+			count);
+		rte_kvargs_free(kvlist);
+		goto fail;
+	}
 	if (count != 0) {
 		printf("invalid count value %d after rte_kvargs_process(unexistant_key)\n",
 			count);
@@ -123,11 +140,19 @@  static int test_valid_kvargs(void)
 	}
 	/* call check_handler() on all entries with key="check", it
 	 * should fail as the value is not recognized by the handler */
-	if (rte_kvargs_process(kvlist, "check", check_handler, NULL) == 0) {
+	if (rte_kvargs_process(kvlist, "check", &match_count,
+			check_handler, NULL) == 0) {
 		printf("rte_kvargs_process() is success bu should not\n");
 		rte_kvargs_free(kvlist);
 		goto fail;
 	}
+	if (match_count != 3) {
+		printf("invalid match_count value %d"
+			" after rte_kvargs_process(check)\n",
+			count);
+		rte_kvargs_free(kvlist);
+		goto fail;
+	}
 	count = rte_kvargs_count(kvlist, "check");
 	if (count != 3) {
 		printf("invalid count value %d after rte_kvargs_count(check)\n",