DPDK patches and discussions
 help / color / mirror / Atom feed
From: Srikanth Yalavarthi <syalavarthi@marvell.com>
To: Thomas Monjalon <thomas@monjalon.net>,
	Srikanth Yalavarthi <syalavarthi@marvell.com>
Cc: <dev@dpdk.org>, <sshankarnara@marvell.com>, <jerinj@marvell.com>
Subject: [PATCH v2 01/12] app/mldev: implement test framework for mldev
Date: Tue, 29 Nov 2022 00:20:58 -0800	[thread overview]
Message-ID: <20221129082109.6809-1-syalavarthi@marvell.com> (raw)
In-Reply-To: <20221129070746.20396-2-syalavarthi@marvell.com>

Implemented framework for mldev test application. New test cases
can be added using the framework. Support is also enabled to add
options specific to the test cases. User can launch the tests by
specifying the name of test as part of launch arguments.

Code to parse command line arguments is imported from
test-eventdev, with support to parse additional data types.

Common arguments supported include:

test        : name of the test application to run
dev_id      : device id of the ML device
socket_id   : socket_id of application resources
debug       : enable debugging
help        : print help

Sample launch command:
./dpdk-test-mldev -- --test <testname> --dev_id <dev_id> \
--socket_id <socket_id>

Signed-off-by: Srikanth Yalavarthi <syalavarthi@marvell.com>
---
Depends-on: series-25753 ("mldev: introduce machine learning device library")

 MAINTAINERS                 |   1 +
 app/meson.build             |   1 +
 app/test-mldev/meson.build  |  17 ++
 app/test-mldev/ml_common.h  |  29 +++
 app/test-mldev/ml_main.c    | 118 +++++++++++
 app/test-mldev/ml_options.c | 160 +++++++++++++++
 app/test-mldev/ml_options.h |  31 +++
 app/test-mldev/ml_test.c    |  45 +++++
 app/test-mldev/ml_test.h    |  75 +++++++
 app/test-mldev/parser.c     | 380 ++++++++++++++++++++++++++++++++++++
 app/test-mldev/parser.h     |  55 ++++++
 11 files changed, 912 insertions(+)
 create mode 100644 app/test-mldev/meson.build
 create mode 100644 app/test-mldev/ml_common.h
 create mode 100644 app/test-mldev/ml_main.c
 create mode 100644 app/test-mldev/ml_options.c
 create mode 100644 app/test-mldev/ml_options.h
 create mode 100644 app/test-mldev/ml_test.c
 create mode 100644 app/test-mldev/ml_test.h
 create mode 100644 app/test-mldev/parser.c
 create mode 100644 app/test-mldev/parser.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 0c3e6d28e9..1edea42fad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -538,6 +538,7 @@ F: doc/guides/prog_guide/rawdev.rst
 ML device API - EXPERIMENTAL
 M: Srikanth Yalavarthi <syalavarthi@marvell.com>
 F: lib/mldev/
+F: app/test-mldev/
 F: doc/guides/prog_guide/mldev.rst
 
 
diff --git a/app/meson.build b/app/meson.build
index e32ea4bd5c..74d2420f67 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -23,6 +23,7 @@ apps = [
         'test-fib',
         'test-flow-perf',
         'test-gpudev',
+        'test-mldev',
         'test-pipeline',
         'test-pmd',
         'test-regex',
diff --git a/app/test-mldev/meson.build b/app/test-mldev/meson.build
new file mode 100644
index 0000000000..8ca2e1a1c1
--- /dev/null
+++ b/app/test-mldev/meson.build
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (c) 2022 Marvell.
+
+if is_windows
+    build = false
+    reason = 'not supported on Windows'
+    subdir_done()
+endif
+
+sources = files(
+        'ml_main.c',
+        'ml_options.c',
+        'ml_test.c',
+        'parser.c',
+)
+
+deps += ['mldev']
diff --git a/app/test-mldev/ml_common.h b/app/test-mldev/ml_common.h
new file mode 100644
index 0000000000..065180b619
--- /dev/null
+++ b/app/test-mldev/ml_common.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef _ML_COMMON_
+#define _ML_COMMON_
+
+#include <stdio.h>
+
+#define CLNRM "\x1b[0m"
+#define CLRED "\x1b[31m"
+#define CLGRN "\x1b[32m"
+#define CLYEL "\x1b[33m"
+
+#define ML_STR_FMT 20
+
+#define ml_err(fmt, args...) fprintf(stderr, CLRED "error: %s() " fmt CLNRM "\n", __func__, ##args)
+
+#define ml_info(fmt, args...) fprintf(stdout, CLYEL "" fmt CLNRM "\n", ##args)
+
+#define ml_dump(str, fmt, val...) printf("\t%-*s : " fmt "\n", ML_STR_FMT, str, ##val)
+
+#define ml_dump_begin(str) printf("\t%-*s :\n\t{\n", ML_STR_FMT, str)
+
+#define ml_dump_list(str, id, val) printf("\t%*s[%2u] : %s\n", ML_STR_FMT - 4, str, id, val)
+
+#define ml_dump_end printf("\b\t}\n\n")
+
+#endif /* _ML_COMMON_*/
diff --git a/app/test-mldev/ml_main.c b/app/test-mldev/ml_main.c
new file mode 100644
index 0000000000..d6652cd7b7
--- /dev/null
+++ b/app/test-mldev/ml_main.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_mldev.h>
+
+#include "ml_common.h"
+#include "ml_options.h"
+#include "ml_test.h"
+
+struct ml_options opt;
+struct ml_test *test;
+
+int
+main(int argc, char **argv)
+{
+	uint16_t mldevs;
+	int ret;
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0)
+		rte_panic("invalid EAL arguments\n");
+	argc -= ret;
+	argv += ret;
+
+	mldevs = rte_ml_dev_count();
+	if (!mldevs)
+		rte_panic("no mldev devices found\n");
+
+	/* set default values for options */
+	ml_options_default(&opt);
+
+	/* parse the command line arguments */
+	ret = ml_options_parse(&opt, argc, argv);
+	if (ret) {
+		ml_err("parsing one or more user options failed");
+		goto error;
+	}
+
+	/* get test struct from name */
+	test = ml_test_get(opt.test_name);
+	if (test == NULL) {
+		ml_err("failed to find requested test: %s", opt.test_name);
+		goto error;
+	}
+
+	if (test->ops.test_result == NULL) {
+		ml_err("%s: ops.test_result not found", opt.test_name);
+		goto error;
+	}
+
+	/* check test options */
+	if (test->ops.opt_check) {
+		if (test->ops.opt_check(&opt)) {
+			ml_err("invalid command line argument");
+			goto error;
+		}
+	}
+
+	/* check the device capability */
+	if (test->ops.cap_check) {
+		if (test->ops.cap_check(&opt) == false) {
+			ml_info("unsupported test: %s", opt.test_name);
+			ret = ML_TEST_UNSUPPORTED;
+			goto no_cap;
+		}
+	}
+
+	/* dump options */
+	if (opt.debug) {
+		if (test->ops.opt_dump)
+			test->ops.opt_dump(&opt);
+	}
+
+	/* test specific setup */
+	if (test->ops.test_setup) {
+		if (test->ops.test_setup(test, &opt)) {
+			ml_err("failed to setup test: %s", opt.test_name);
+			goto error;
+		}
+	}
+
+	/* test driver */
+	if (test->ops.test_driver)
+		test->ops.test_driver(test, &opt);
+
+	/* get result */
+	if (test->ops.test_result)
+		ret = test->ops.test_result(test, &opt);
+
+	if (test->ops.test_destroy)
+		test->ops.test_destroy(test, &opt);
+
+no_cap:
+	if (ret == ML_TEST_SUCCESS) {
+		printf("Result: " CLGRN "%s" CLNRM "\n", "Success");
+	} else if (ret == ML_TEST_FAILED) {
+		printf("Result: " CLRED "%s" CLNRM "\n", "Failed");
+		return EXIT_FAILURE;
+	} else if (ret == ML_TEST_UNSUPPORTED) {
+		printf("Result: " CLYEL "%s" CLNRM "\n", "Unsupported");
+	}
+
+	rte_eal_cleanup();
+
+	return 0;
+
+error:
+	rte_eal_cleanup();
+
+	return EXIT_FAILURE;
+}
diff --git a/app/test-mldev/ml_options.c b/app/test-mldev/ml_options.c
new file mode 100644
index 0000000000..8fd7760e36
--- /dev/null
+++ b/app/test-mldev/ml_options.c
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_memory.h>
+#include <rte_mldev.h>
+#include <rte_string_fns.h>
+
+#include "ml_common.h"
+#include "ml_options.h"
+#include "ml_test.h"
+#include "parser.h"
+
+typedef int (*option_parser_t)(struct ml_options *opt, const char *arg);
+
+void
+ml_options_default(struct ml_options *opt)
+{
+	memset(opt, 0, sizeof(*opt));
+	strlcpy(opt->test_name, "ml_test", ML_TEST_NAME_MAX_LEN);
+	opt->dev_id = 0;
+	opt->socket_id = SOCKET_ID_ANY;
+	opt->debug = false;
+}
+
+struct long_opt_parser {
+	const char *lgopt_name;
+	option_parser_t parser_fn;
+};
+
+static int
+ml_parse_test_name(struct ml_options *opt, const char *arg)
+{
+	strlcpy(opt->test_name, arg, ML_TEST_NAME_MAX_LEN);
+	return 0;
+}
+
+static int
+ml_parse_dev_id(struct ml_options *opt, const char *arg)
+{
+	int ret;
+
+	ret = parser_read_int16(&opt->dev_id, arg);
+
+	if (ret < 0)
+		return -EINVAL;
+
+	return ret;
+}
+
+static int
+ml_parse_socket_id(struct ml_options *opt, const char *arg)
+{
+	opt->socket_id = atoi(arg);
+
+	return 0;
+}
+
+static void
+ml_dump_test_options(const char *testname)
+{
+	RTE_SET_USED(testname);
+}
+
+static void
+print_usage(char *program)
+{
+	printf("\nusage : %s [EAL options] -- [application options]\n", program);
+	printf("application options:\n");
+	printf("\t--test             : name of the test application to run\n"
+	       "\t--dev_id           : device id of the ML device\n"
+	       "\t--socket_id        : socket_id of application resources\n"
+	       "\t--debug            : enable debug mode\n"
+	       "\t--help             : print help\n");
+	printf("\n");
+	printf("available tests and test specific application options:\n");
+	ml_test_dump_names(ml_dump_test_options);
+}
+
+static struct option lgopts[] = {{ML_TEST, 1, 0, 0},	  {ML_DEVICE_ID, 1, 0, 0},
+				 {ML_SOCKET_ID, 1, 0, 0}, {ML_DEBUG, 0, 0, 0},
+				 {ML_HELP, 0, 0, 0},	  {NULL, 0, 0, 0}};
+
+static int
+ml_opts_parse_long(int opt_idx, struct ml_options *opt)
+{
+	unsigned int i;
+
+	struct long_opt_parser parsermap[] = {
+		{ML_TEST, ml_parse_test_name},
+		{ML_DEVICE_ID, ml_parse_dev_id},
+		{ML_SOCKET_ID, ml_parse_socket_id},
+	};
+
+	for (i = 0; i < RTE_DIM(parsermap); i++) {
+		if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
+			    strlen(lgopts[opt_idx].name)) == 0)
+			return parsermap[i].parser_fn(opt, optarg);
+	}
+
+	return -EINVAL;
+}
+
+int
+ml_options_parse(struct ml_options *opt, int argc, char **argv)
+{
+	int opt_idx;
+	int retval;
+	int opts;
+
+	while ((opts = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) {
+		switch (opts) {
+		case 0: /* parse long options */
+			if (!strcmp(lgopts[opt_idx].name, "debug")) {
+				opt->debug = true;
+				break;
+			}
+
+			if (!strcmp(lgopts[opt_idx].name, "help")) {
+				print_usage(argv[0]);
+				exit(EXIT_SUCCESS);
+			}
+
+			retval = ml_opts_parse_long(opt_idx, opt);
+			if (retval != 0)
+				return retval;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+void
+ml_options_dump(struct ml_options *opt)
+{
+	struct rte_ml_dev_info dev_info;
+
+	rte_ml_dev_info_get(opt->dev_id, &dev_info);
+
+	ml_dump("driver", "%s", dev_info.driver_name);
+	ml_dump("test", "%s", opt->test_name);
+	ml_dump("dev_id", "%d", opt->dev_id);
+
+	if (opt->socket_id == SOCKET_ID_ANY)
+		ml_dump("socket_id", "%d (SOCKET_ID_ANY)", opt->socket_id);
+	else
+		ml_dump("socket_id", "%d", opt->socket_id);
+
+	ml_dump("debug", "%s", (opt->debug ? "true" : "false"));
+}
diff --git a/app/test-mldev/ml_options.h b/app/test-mldev/ml_options.h
new file mode 100644
index 0000000000..05311a9a47
--- /dev/null
+++ b/app/test-mldev/ml_options.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef _ML_OPTIONS_
+#define _ML_OPTIONS_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define ML_TEST_NAME_MAX_LEN 32
+
+/* Options names */
+#define ML_TEST	     ("test")
+#define ML_DEVICE_ID ("dev_id")
+#define ML_SOCKET_ID ("socket_id")
+#define ML_DEBUG     ("debug")
+#define ML_HELP	     ("help")
+
+struct ml_options {
+	char test_name[ML_TEST_NAME_MAX_LEN];
+	int16_t dev_id;
+	int socket_id;
+	bool debug;
+};
+
+void ml_options_default(struct ml_options *opt);
+int ml_options_parse(struct ml_options *opt, int argc, char **argv);
+void ml_options_dump(struct ml_options *opt);
+
+#endif /* _ML_OPTIONS_ */
diff --git a/app/test-mldev/ml_test.c b/app/test-mldev/ml_test.c
new file mode 100644
index 0000000000..2304712764
--- /dev/null
+++ b/app/test-mldev/ml_test.c
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include "ml_test.h"
+
+static STAILQ_HEAD(, ml_test_entry) head = STAILQ_HEAD_INITIALIZER(head);
+
+void
+ml_test_register(struct ml_test_entry *entry)
+{
+	STAILQ_INSERT_TAIL(&head, entry, next);
+}
+
+struct ml_test *
+ml_test_get(const char *name)
+{
+	struct ml_test_entry *entry;
+
+	if (!name)
+		return NULL;
+
+	STAILQ_FOREACH(entry, &head, next)
+	if (!strncmp(entry->test.name, name, strlen(name)))
+		return &entry->test;
+
+	return NULL;
+}
+
+void
+ml_test_dump_names(void (*f)(const char *name))
+{
+	struct ml_test_entry *entry;
+
+	STAILQ_FOREACH(entry, &head, next)
+	{
+		if (entry->test.name)
+			printf("\t %s\n", entry->test.name);
+		f(entry->test.name);
+	}
+}
diff --git a/app/test-mldev/ml_test.h b/app/test-mldev/ml_test.h
new file mode 100644
index 0000000000..4a1430ec1b
--- /dev/null
+++ b/app/test-mldev/ml_test.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef _ML_TEST_
+#define _ML_TEST_
+
+#include <stdbool.h>
+#include <string.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+
+#include "ml_options.h"
+
+#define ML_TEST_MAX_POOL_SIZE 256
+
+enum ml_test_result {
+	ML_TEST_SUCCESS,
+	ML_TEST_FAILED,
+	ML_TEST_UNSUPPORTED,
+};
+
+struct ml_test;
+
+typedef bool (*ml_test_capability_check_t)(struct ml_options *opt);
+typedef int (*ml_test_options_check_t)(struct ml_options *opt);
+typedef void (*ml_test_options_dump_t)(struct ml_options *opt);
+typedef int (*ml_test_setup_t)(struct ml_test *test, struct ml_options *opt);
+typedef void (*ml_test_destroy_t)(struct ml_test *test, struct ml_options *opt);
+typedef int (*ml_test_driver_t)(struct ml_test *test, struct ml_options *opt);
+typedef int (*ml_test_result_t)(struct ml_test *test, struct ml_options *opt);
+
+struct ml_test_ops {
+	ml_test_capability_check_t cap_check;
+	ml_test_options_check_t opt_check;
+	ml_test_options_dump_t opt_dump;
+	ml_test_setup_t test_setup;
+	ml_test_destroy_t test_destroy;
+	ml_test_driver_t test_driver;
+	ml_test_result_t test_result;
+};
+
+struct ml_test {
+	const char *name;
+	void *test_priv;
+	struct ml_test_ops ops;
+};
+
+struct ml_test_entry {
+	struct ml_test test;
+
+	STAILQ_ENTRY(ml_test_entry) next;
+};
+
+static inline void *
+ml_test_priv(struct ml_test *test)
+{
+	return test->test_priv;
+}
+
+struct ml_test *ml_test_get(const char *name);
+void ml_test_register(struct ml_test_entry *test);
+void ml_test_dump_names(void (*f)(const char *));
+
+#define ML_TEST_REGISTER(nm)                                                                       \
+	static struct ml_test_entry _ml_test_entry_##nm;                                           \
+	RTE_INIT(ml_test_##nm)                                                                     \
+	{                                                                                          \
+		_ml_test_entry_##nm.test.name = RTE_STR(nm);                                       \
+		memcpy(&_ml_test_entry_##nm.test.ops, &nm, sizeof(struct ml_test_ops));            \
+		ml_test_register(&_ml_test_entry_##nm);                                            \
+	}
+
+#endif /* _ML_TEST_ */
diff --git a/app/test-mldev/parser.c b/app/test-mldev/parser.c
new file mode 100644
index 0000000000..0b7fb63fe5
--- /dev/null
+++ b/app/test-mldev/parser.c
@@ -0,0 +1,380 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2016 Intel Corporation.
+ * Copyright (c) 2017 Cavium, Inc.
+ * Copyright (c) 2022 Marvell.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_common.h>
+
+#include "parser.h"
+
+static uint32_t
+get_hex_val(char c)
+{
+	switch (c) {
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+		return c - '0';
+	case 'A':
+	case 'B':
+	case 'C':
+	case 'D':
+	case 'E':
+	case 'F':
+		return c - 'A' + 10;
+	case 'a':
+	case 'b':
+	case 'c':
+	case 'd':
+	case 'e':
+	case 'f':
+		return c - 'a' + 10;
+	default:
+		return 0;
+	}
+}
+
+int
+parser_read_arg_bool(const char *p)
+{
+	p = skip_white_spaces(p);
+	int result = -EINVAL;
+
+	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
+	    ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
+		p += 3;
+		result = 1;
+	}
+
+	if (((p[0] == 'o') && (p[1] == 'n')) || ((p[0] == 'O') && (p[1] == 'N'))) {
+		p += 2;
+		result = 1;
+	}
+
+	if (((p[0] == 'n') && (p[1] == 'o')) || ((p[0] == 'N') && (p[1] == 'O'))) {
+		p += 2;
+		result = 0;
+	}
+
+	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
+	    ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
+		p += 3;
+		result = 0;
+	}
+
+	p = skip_white_spaces(p);
+
+	if (p[0] != '\0')
+		return -EINVAL;
+
+	return result;
+}
+
+int
+parser_read_uint64(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+	if (!isdigit(*p))
+		return -EINVAL;
+
+	val = strtoul(p, &next, 10);
+	if (p == next)
+		return -EINVAL;
+
+	p = next;
+	switch (*p) {
+	case 'T':
+		val *= 1024ULL;
+		/* fall through */
+	case 'G':
+		val *= 1024ULL;
+		/* fall through */
+	case 'M':
+		val *= 1024ULL;
+		/* fall through */
+	case 'k':
+	case 'K':
+		val *= 1024ULL;
+		p++;
+		break;
+	}
+
+	p = skip_white_spaces(p);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_int32(int32_t *value, const char *p)
+{
+	char *next;
+	int32_t val;
+
+	p = skip_white_spaces(p);
+	if (!isdigit(*p))
+		return -EINVAL;
+
+	val = strtol(p, &next, 10);
+	if (p == next)
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_int16(int16_t *value, const char *p)
+{
+	char *next;
+	int16_t val;
+
+	p = skip_white_spaces(p);
+	if (!isdigit(*p))
+		return -EINVAL;
+
+	val = strtol(p, &next, 10);
+	if (p == next)
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint64_hex(uint64_t *value, const char *p)
+{
+	char *next;
+	uint64_t val;
+
+	p = skip_white_spaces(p);
+
+	val = strtoul(p, &next, 16);
+	if (p == next)
+		return -EINVAL;
+
+	p = skip_white_spaces(next);
+	if (*p != '\0')
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint32(uint32_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT32_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint32_hex(uint32_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64_hex(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT32_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint16(uint16_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT16_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint16_hex(uint16_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64_hex(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT16_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint8(uint8_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT8_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parser_read_uint8_hex(uint8_t *value, const char *p)
+{
+	uint64_t val = 0;
+	int ret = parser_read_uint64_hex(&val, p);
+
+	if (ret < 0)
+		return ret;
+
+	if (val > UINT8_MAX)
+		return -ERANGE;
+
+	*value = val;
+	return 0;
+}
+
+int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+	uint32_t i;
+
+	if ((string == NULL) || (tokens == NULL) || (*n_tokens < 1))
+		return -EINVAL;
+
+	for (i = 0; i < *n_tokens; i++) {
+		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+		if (tokens[i] == NULL)
+			break;
+	}
+
+	if ((i == *n_tokens) && (strtok_r(string, PARSE_DELIMITER, &string) != NULL))
+		return -E2BIG;
+
+	*n_tokens = i;
+	return 0;
+}
+
+int
+parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
+{
+	char *c;
+	uint32_t len, i;
+
+	/* Check input parameters */
+	if ((src == NULL) || (dst == NULL) || (size == NULL) || (*size == 0))
+		return -1;
+
+	len = strlen(src);
+	if (((len & 3) != 0) || (len > (*size) * 2))
+		return -1;
+	*size = len / 2;
+
+	for (c = src; *c != 0; c++) {
+		if ((((*c) >= '0') && ((*c) <= '9')) || (((*c) >= 'A') && ((*c) <= 'F')) ||
+		    (((*c) >= 'a') && ((*c) <= 'f')))
+			continue;
+
+		return -1;
+	}
+
+	/* Convert chars to bytes */
+	for (i = 0; i < *size; i++)
+		dst[i] = get_hex_val(src[2 * i]) * 16 + get_hex_val(src[2 * i + 1]);
+
+	return 0;
+}
+
+int
+parse_lcores_list(bool lcores[], int lcores_num, const char *corelist)
+{
+	int i, idx = 0;
+	int min, max;
+	char *end = NULL;
+
+	if (corelist == NULL)
+		return -1;
+	while (isblank(*corelist))
+		corelist++;
+	i = strlen(corelist);
+	while ((i > 0) && isblank(corelist[i - 1]))
+		i--;
+
+	/* Get list of lcores */
+	min = RTE_MAX_LCORE;
+	do {
+		while (isblank(*corelist))
+			corelist++;
+		if (*corelist == '\0')
+			return -1;
+		idx = strtoul(corelist, &end, 10);
+		if (idx < 0 || idx > lcores_num)
+			return -1;
+
+		if (end == NULL)
+			return -1;
+		while (isblank(*end))
+			end++;
+		if (*end == '-') {
+			min = idx;
+		} else if ((*end == ',') || (*end == '\0')) {
+			max = idx;
+			if (min == RTE_MAX_LCORE)
+				min = idx;
+			for (idx = min; idx <= max; idx++) {
+				if (lcores[idx] == 1)
+					return -E2BIG;
+				lcores[idx] = 1;
+			}
+
+			min = RTE_MAX_LCORE;
+		} else
+			return -1;
+		corelist = end + 1;
+	} while (*end != '\0');
+
+	return 0;
+}
diff --git a/app/test-mldev/parser.h b/app/test-mldev/parser.h
new file mode 100644
index 0000000000..f0d5e79e4b
--- /dev/null
+++ b/app/test-mldev/parser.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2010-2016 Intel Corporation.
+ * Copyright (c) 2022 Marvell.
+ */
+
+#ifndef __INCLUDE_PARSER_H__
+#define __INCLUDE_PARSER_H__
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+
+#define skip_white_spaces(pos)                                                                     \
+	({                                                                                         \
+		__typeof__(pos) _p = (pos);                                                        \
+		for (; isspace(*_p); _p++)                                                         \
+			;                                                                          \
+		_p;                                                                                \
+	})
+
+static inline size_t
+skip_digits(const char *src)
+{
+	size_t i;
+
+	for (i = 0; isdigit(src[i]); i++)
+		;
+
+	return i;
+}
+
+int parser_read_arg_bool(const char *p);
+
+int parser_read_uint64(uint64_t *value, const char *p);
+int parser_read_uint32(uint32_t *value, const char *p);
+int parser_read_uint16(uint16_t *value, const char *p);
+int parser_read_uint8(uint8_t *value, const char *p);
+
+int parser_read_uint64_hex(uint64_t *value, const char *p);
+int parser_read_uint32_hex(uint32_t *value, const char *p);
+int parser_read_uint16_hex(uint16_t *value, const char *p);
+int parser_read_uint8_hex(uint8_t *value, const char *p);
+
+int parser_read_int32(int32_t *value, const char *p);
+int parser_read_int16(int16_t *value, const char *p);
+
+int parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
+
+int parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens);
+
+int parse_lcores_list(bool lcores[], int lcores_num, const char *corelist);
+
+#endif /* __INCLUDE_PARSER_H__ */
-- 
2.17.1


  reply	other threads:[~2022-11-29  8:21 UTC|newest]

Thread overview: 122+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-29  7:07 [PATCH v1 00/12] implement mldev test application Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 01/12] app/mldev: implement test framework for mldev Srikanth Yalavarthi
2022-11-29  8:20   ` Srikanth Yalavarthi [this message]
2022-11-29  8:20     ` [PATCH v2 02/12] app/mldev: add common test functions Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 03/12] app/mldev: add test case to validate device ops Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 04/12] app/mldev: add test case to validate model ops Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 05/12] app/mldev: add ordered inference test case Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 06/12] app/mldev: add test case to interleave inferences Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 07/12] app/mldev: enable support for burst inferences Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 08/12] app/mldev: enable support for queue pairs and size Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 09/12] app/mldev: enable support for inference batches Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 10/12] app/mldev: enable support for inference validation Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 11/12] app/mldev: enable reporting stats in mldev app Srikanth Yalavarthi
2022-11-29  8:21     ` [PATCH v2 12/12] app/mldev: add documentation for mldev test cases Srikanth Yalavarthi
2022-12-08 19:29     ` [PATCH v3 01/12] app/mldev: implement test framework for mldev Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 02/12] app/mldev: add common test functions Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 03/12] app/mldev: add test case to validate device ops Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 04/12] app/mldev: add test case to validate model ops Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 05/12] app/mldev: add ordered inference test case Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 06/12] app/mldev: add test case to interleave inferences Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 07/12] app/mldev: enable support for burst inferences Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 08/12] app/mldev: enable support for queue pairs and size Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 09/12] app/mldev: enable support for inference batches Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 10/12] app/mldev: enable support for inference validation Srikanth Yalavarthi
2022-12-08 19:29       ` [PATCH v3 11/12] app/mldev: enable reporting stats in mldev app Srikanth Yalavarthi
2023-02-03  9:49         ` Anup Prabhu
2022-12-08 19:29       ` [PATCH v3 12/12] app/mldev: add documentation for mldev test cases Srikanth Yalavarthi
2023-02-02 12:39         ` Anup Prabhu
2022-11-29  7:07 ` [PATCH v1 02/12] app/mldev: add common test functions Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 03/12] app/mldev: add test case to validate device ops Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 04/12] app/mldev: add test case to validate model ops Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 05/12] app/mldev: add ordered inference test case Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 06/12] app/mldev: add test case to interleave inferences Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 07/12] app/mldev: enable support for burst inferences Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 08/12] app/mldev: enable support for queue pairs and size Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 09/12] app/mldev: enable support for inference batches Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 10/12] app/mldev: enable support for inference validation Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 11/12] app/mldev: enable reporting stats in mldev app Srikanth Yalavarthi
2022-11-29  7:07 ` [PATCH v1 12/12] app/mldev: add documentation for mldev test cases Srikanth Yalavarthi
2023-02-07 15:49 ` [PATCH v4 00/12] Implementation of mldev test application Srikanth Yalavarthi
2023-02-07 15:49   ` [PATCH v4 01/12] app/mldev: implement test framework for mldev Srikanth Yalavarthi
2023-02-14  4:55     ` Shivah Shankar Shankar Narayan Rao
2023-03-03  8:15     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 02/12] app/mldev: add common test functions Srikanth Yalavarthi
2023-02-23  9:03     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 03/12] app/mldev: add test case to validate device ops Srikanth Yalavarthi
2023-03-01  5:35     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 04/12] app/mldev: add test case to validate model ops Srikanth Yalavarthi
2023-03-02  2:58     ` Anup Prabhu
2023-03-09 18:42     ` Thomas Monjalon
2023-03-10  2:55       ` [EXT] " Srikanth Yalavarthi
2023-02-07 15:49   ` [PATCH v4 05/12] app/mldev: add ordered inference test case Srikanth Yalavarthi
2023-02-27  6:11     ` Anup Prabhu
2023-03-09 20:06     ` Thomas Monjalon
2023-03-10  8:13       ` [EXT] " Srikanth Yalavarthi
2023-02-07 15:49   ` [PATCH v4 06/12] app/mldev: add test case to interleave inferences Srikanth Yalavarthi
2023-02-20  6:31     ` Anup Prabhu
2023-03-09 20:15     ` Thomas Monjalon
2023-03-10  8:14       ` [EXT] " Srikanth Yalavarthi
2023-02-07 15:49   ` [PATCH v4 07/12] app/mldev: enable support for burst inferences Srikanth Yalavarthi
2023-02-20 10:11     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 08/12] app/mldev: enable support for queue pairs and size Srikanth Yalavarthi
2023-03-02  8:15     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 09/12] app/mldev: enable support for inference batches Srikanth Yalavarthi
2023-02-27  3:46     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 10/12] app/mldev: enable support for inference validation Srikanth Yalavarthi
2023-02-16 12:23     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 11/12] app/mldev: enable reporting stats in mldev app Srikanth Yalavarthi
2023-02-16  4:21     ` Anup Prabhu
2023-02-07 15:49   ` [PATCH v4 12/12] app/mldev: add documentation for mldev test cases Srikanth Yalavarthi
2023-02-15 12:26     ` Shivah Shankar Shankar Narayan Rao
2023-03-03  6:07     ` Anup Prabhu
2023-03-10  8:09 ` [PATCH v5 00/12] Implementation of mldev test application Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 01/12] app/mldev: implement test framework for mldev Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 02/12] app/mldev: add common test functions Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 03/12] app/mldev: add test case to validate device ops Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 04/12] app/mldev: add test case to validate model ops Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 05/12] app/mldev: add ordered inference test case Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 06/12] app/mldev: add test case to interleave inferences Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 07/12] app/mldev: enable support for burst inferences Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 08/12] app/mldev: enable support for queue pairs and size Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 09/12] app/mldev: enable support for inference batches Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 10/12] app/mldev: enable support for inference validation Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 11/12] app/mldev: enable reporting stats in mldev app Srikanth Yalavarthi
2023-03-10  8:09   ` [PATCH v5 12/12] app/mldev: add documentation for mldev test cases Srikanth Yalavarthi
2023-03-11 15:08 ` [PATCH v6 00/12] Implementation of mldev test application Srikanth Yalavarthi
2023-03-11 15:08   ` [PATCH v6 01/12] app/mldev: implement test framework for mldev Srikanth Yalavarthi
2023-03-11 15:08   ` [PATCH v6 02/12] app/mldev: add common test functions Srikanth Yalavarthi
2023-03-11 15:08   ` [PATCH v6 03/12] app/mldev: add test case to validate device ops Srikanth Yalavarthi
2023-03-11 15:08   ` [PATCH v6 04/12] app/mldev: add test case to validate model ops Srikanth Yalavarthi
2023-03-11 15:08   ` [PATCH v6 05/12] app/mldev: add ordered inference test case Srikanth Yalavarthi
2023-03-16 17:45     ` Thomas Monjalon
2023-03-16 17:47       ` [EXT] " Srikanth Yalavarthi
2023-03-16 18:01         ` Thomas Monjalon
2023-03-16 21:31           ` Srikanth Yalavarthi
2023-03-11 15:08   ` [PATCH v6 06/12] app/mldev: add test case to interleave inferences Srikanth Yalavarthi
2023-03-11 15:09   ` [PATCH v6 07/12] app/mldev: enable support for burst inferences Srikanth Yalavarthi
2023-03-11 15:09   ` [PATCH v6 08/12] app/mldev: enable support for queue pairs and size Srikanth Yalavarthi
2023-03-11 15:09   ` [PATCH v6 09/12] app/mldev: enable support for inference batches Srikanth Yalavarthi
2023-03-16 17:47     ` Thomas Monjalon
2023-03-16 17:52       ` [EXT] " Srikanth Yalavarthi
2023-03-11 15:09   ` [PATCH v6 10/12] app/mldev: enable support for inference validation Srikanth Yalavarthi
2023-03-11 15:09   ` [PATCH v6 11/12] app/mldev: enable reporting stats in mldev app Srikanth Yalavarthi
2023-03-11 15:09   ` [PATCH v6 12/12] app/mldev: add documentation for mldev test cases Srikanth Yalavarthi
2023-03-16 17:50     ` Thomas Monjalon
2023-03-16 17:56       ` [EXT] " Srikanth Yalavarthi
2023-03-16 18:03         ` Thomas Monjalon
2023-03-16 18:07           ` Srikanth Yalavarthi
2023-03-16 21:32             ` Srikanth Yalavarthi
2023-03-16 21:14 ` [PATCH v7 00/11] Implementation of mldev test application Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 01/11] app/mldev: implement test framework for mldev Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 02/11] app/mldev: add common test functions Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 03/11] app/mldev: add test case to validate device ops Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 04/11] app/mldev: add test case to validate model ops Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 05/11] app/mldev: add ordered inference test case Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 06/11] app/mldev: add test case to interleave inferences Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 07/11] app/mldev: enable support for burst inferences Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 08/11] app/mldev: enable support for queue pairs and size Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 09/11] app/mldev: enable support for inference batches Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 10/11] app/mldev: enable support for inference validation Srikanth Yalavarthi
2023-03-16 21:14   ` [PATCH v7 11/11] app/mldev: enable reporting stats in mldev app Srikanth Yalavarthi
2023-03-19 22:08   ` [PATCH v7 00/11] Implementation of mldev test application Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221129082109.6809-1-syalavarthi@marvell.com \
    --to=syalavarthi@marvell.com \
    --cc=dev@dpdk.org \
    --cc=jerinj@marvell.com \
    --cc=sshankarnara@marvell.com \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).