[v4,01/14] app/graph: add application framework to read CLI

Message ID 20230919160455.1678716-1-skori@marvell.com (mailing list archive)
State Changes Requested, archived
Delegated to: Thomas Monjalon
Headers
Series [v4,01/14] app/graph: add application framework to read CLI |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Sunil Kumar Kori Sept. 19, 2023, 4:04 p.m. UTC
  From: Sunil Kumar Kori <skori@marvell.com>

It adds base framework to read a given .cli file as a command line
parameter "-s".

Example:
 # ./dpdk-graph -c 0xff -- -s ./app/graph/examples/dummy.cli

Each .cli file will contain commands to configure different module like
mempool, ethdev, lookup tables, graph etc. Command parsing is backed by
commandline library.

Each module needs to expose its supported commands & corresponding
callback functions to commandline library to get them parsed.

Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
Signed-off-by: Rakesh Kudurumalla <rkudurumalla@marvell.com>
---
v3..v4:
 - Addressed Nithin's review comments

 app/graph/cli.c        | 113 ++++++++++++++++++++++++++++++++++++
 app/graph/cli.h        |  32 +++++++++++
 app/graph/main.c       | 127 +++++++++++++++++++++++++++++++++++++++++
 app/graph/meson.build  |  14 +++++
 app/graph/module_api.h |  16 ++++++
 app/meson.build        |   1 +
 6 files changed, 303 insertions(+)
 create mode 100644 app/graph/cli.c
 create mode 100644 app/graph/cli.h
 create mode 100644 app/graph/main.c
 create mode 100644 app/graph/meson.build
 create mode 100644 app/graph/module_api.h
  

Comments

Jerin Jacob Sept. 20, 2023, 4:40 a.m. UTC | #1
On Tue, Sep 19, 2023 at 9:35 PM <skori@marvell.com> wrote:
>
> From: Sunil Kumar Kori <skori@marvell.com>
>
> It adds base framework to read a given .cli file as a command line
> parameter "-s".
>
> Example:
>  # ./dpdk-graph -c 0xff -- -s ./app/graph/examples/dummy.cli
>
> Each .cli file will contain commands to configure different module like
> mempool, ethdev, lookup tables, graph etc. Command parsing is backed by
> commandline library.
>
> Each module needs to expose its supported commands & corresponding
> callback functions to commandline library to get them parsed.
>
> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
> Signed-off-by: Rakesh Kudurumalla <rkudurumalla@marvell.com>
> ---
> v3..v4:
>  - Addressed Nithin's review comments

List the review comments for next versions or minimum, share the
patchwork URL for review comments.


> +               return -EINVAL;
> +
> +       msg_in = malloc(msg_in_len_max + 1);
> +       msg_out = malloc(msg_out_len_max + 1);
> +       if ((msg_in == NULL) || (msg_out == NULL)) {
> +               free(msg_out);
> +               free(msg_in);
> +               return -ENOMEM;

Please switch to goto exit; scheme.

> +       }
> +
> +       /* Open input file */
> +       f = fopen(file_name, "r");
> +       if (f == NULL) {
> +               free(msg_out);
> +               free(msg_in);
> +               return -EIO;

Same as here.

> +       }
  

Patch

diff --git a/app/graph/cli.c b/app/graph/cli.c
new file mode 100644
index 0000000000..473fa1635a
--- /dev/null
+++ b/app/graph/cli.c
@@ -0,0 +1,113 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Marvell.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_socket.h>
+#include <rte_common.h>
+
+#include "module_api.h"
+
+#define CMD_MAX_TOKENS 256
+#define MAX_LINE_SIZE 2048
+
+cmdline_parse_ctx_t modules_ctx[] = {
+	NULL,
+};
+
+static struct cmdline *cl;
+
+static int
+is_comment(char *in)
+{
+	if ((strlen(in) && index("!#%;", in[0])) ||
+		(strncmp(in, "//", 2) == 0) ||
+		(strncmp(in, "--", 2) == 0))
+		return 1;
+
+	return 0;
+}
+
+void
+cli_init(void)
+{
+	cl = cmdline_stdin_new(modules_ctx, "");
+}
+
+void
+cli_exit(void)
+{
+	cmdline_stdin_exit(cl);
+}
+
+void
+cli_process(char *in, char *out, size_t out_size, __rte_unused void *obj)
+{
+	int rc;
+
+	if (is_comment(in))
+		return;
+
+	rc = cmdline_parse(cl, in);
+	if (rc == CMDLINE_PARSE_AMBIGUOUS)
+		snprintf(out, out_size, MSG_CMD_FAIL, "Ambiguous command");
+	else if (rc == CMDLINE_PARSE_NOMATCH)
+		snprintf(out, out_size, MSG_CMD_FAIL, "Command mismatch");
+	else if (rc == CMDLINE_PARSE_BAD_ARGS)
+		snprintf(out, out_size, MSG_CMD_FAIL, "Bad arguments");
+
+	return;
+
+}
+
+int
+cli_script_process(const char *file_name, size_t msg_in_len_max, size_t msg_out_len_max, void *obj)
+{
+	char *msg_in = NULL, *msg_out = NULL;
+	FILE *f = NULL;
+
+	/* Check input arguments */
+	if ((file_name == NULL) || (strlen(file_name) == 0) || (msg_in_len_max == 0) ||
+	    (msg_out_len_max == 0))
+		return -EINVAL;
+
+	msg_in = malloc(msg_in_len_max + 1);
+	msg_out = malloc(msg_out_len_max + 1);
+	if ((msg_in == NULL) || (msg_out == NULL)) {
+		free(msg_out);
+		free(msg_in);
+		return -ENOMEM;
+	}
+
+	/* Open input file */
+	f = fopen(file_name, "r");
+	if (f == NULL) {
+		free(msg_out);
+		free(msg_in);
+		return -EIO;
+	}
+
+	/* Read file */
+	while (fgets(msg_in, msg_in_len_max, f) != NULL) {
+		msg_out[0] = 0;
+
+		cli_process(msg_in, msg_out, msg_out_len_max, obj);
+
+		if (strlen(msg_out))
+			printf("%s", msg_out);
+	}
+
+	/* Close file */
+	fclose(f);
+	free(msg_out);
+	free(msg_in);
+	return 0;
+}
diff --git a/app/graph/cli.h b/app/graph/cli.h
new file mode 100644
index 0000000000..652f948352
--- /dev/null
+++ b/app/graph/cli.h
@@ -0,0 +1,32 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Marvell.
+ */
+
+#ifndef APP_GRAPH_CLI_H
+#define APP_GRAPH_CLI_H
+
+/* Macros */
+#define MSG_OUT_OF_MEMORY   "Not enough memory.\n"
+#define MSG_CMD_UNKNOWN     "Unknown command \"%s\".\n"
+#define MSG_CMD_UNIMPLEM    "Command \"%s\" not implemented.\n"
+#define MSG_ARG_NOT_ENOUGH  "Not enough arguments for command \"%s\".\n"
+#define MSG_ARG_TOO_MANY    "Too many arguments for command \"%s\".\n"
+#define MSG_ARG_MISMATCH    "Wrong number of arguments for command \"%s\".\n"
+#define MSG_ARG_NOT_FOUND   "Argument \"%s\" not found.\n"
+#define MSG_ARG_INVALID     "Invalid value for argument \"%s\".\n"
+#define MSG_FILE_ERR        "Error in file \"%s\" at line %u.\n"
+#define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
+#define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
+
+#define APP_CLI_CMD_NAME_SIZE	64
+
+void cli_init(void);
+
+void cli_exit(void);
+
+void cli_process(char *in, char *out, size_t out_size, void *arg);
+
+int cli_script_process(const char *file_name, size_t msg_in_len_max, size_t msg_out_len_max,
+		       void *arg);
+
+#endif
diff --git a/app/graph/main.c b/app/graph/main.c
new file mode 100644
index 0000000000..a4af1ec7e1
--- /dev/null
+++ b/app/graph/main.c
@@ -0,0 +1,127 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Marvell.
+ */
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_eal.h>
+#include <rte_launch.h>
+
+#include "module_api.h"
+
+volatile bool force_quit;
+
+static const char usage[] = "%s EAL_ARGS -- -s SCRIPT "
+			    "[--help]\n";
+
+static struct app_params {
+	char *script_name;
+} app = {
+	.script_name = NULL,
+};
+
+static void
+signal_handler(int signum)
+{
+	if (signum == SIGINT || signum == SIGTERM) {
+		printf("\n\nSignal %d received, preparing to exit...\n", signum);
+		force_quit = true;
+	}
+}
+
+static int
+app_args_parse(int argc, char **argv)
+{
+	struct option lgopts[] = {
+		{"help", 0, 0, 'H'},
+	};
+	int s_present, n_args, i;
+	char *app_name = argv[0];
+	int opt, option_index;
+
+	/* Skip EAL input args */
+	n_args = argc;
+	for (i = 0; i < n_args; i++)
+		if (strcmp(argv[i], "--") == 0) {
+			argc -= i;
+			argv += i;
+			break;
+		}
+
+	if (i == n_args)
+		return 0;
+
+	/* Parse args */
+	s_present = 0;
+
+	while ((opt = getopt_long(argc, argv, "s:", lgopts, &option_index)) != EOF) {
+		switch (opt) {
+		case 's':
+			if (s_present) {
+				printf("Error: Multiple -s arguments\n");
+				return -1;
+			}
+			s_present = 1;
+
+			if (!strlen(optarg)) {
+				printf("Error: Argument for -s not provided\n");
+				return -1;
+			}
+
+			app.script_name = strdup(optarg);
+			if (app.script_name == NULL) {
+				printf("Error: Not enough memory\n");
+				return -1;
+			}
+			break;
+
+		case 'H':
+		default:
+			printf(usage, app_name);
+			return -1;
+		}
+	}
+	optind = 1; /* reset getopt lib */
+
+	return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+	int rc;
+
+	/* Parse application arguments */
+	rc = app_args_parse(argc, argv);
+	if (rc < 0)
+		return rc;
+
+	/* EAL */
+	rc = rte_eal_init(argc, argv);
+	if (rc < 0) {
+		printf("Error: EAL initialization failed (%d)\n", rc);
+		return rc;
+	};
+
+	force_quit = false;
+	signal(SIGINT, signal_handler);
+	signal(SIGTERM, signal_handler);
+
+	cli_init();
+
+	/* Script */
+	if (app.script_name) {
+		cli_script_process(app.script_name, 0,
+			0, NULL);
+	}
+
+	cli_exit();
+	rte_eal_cleanup();
+	return 0;
+}
\ No newline at end of file
diff --git a/app/graph/meson.build b/app/graph/meson.build
new file mode 100644
index 0000000000..87c4ce30a8
--- /dev/null
+++ b/app/graph/meson.build
@@ -0,0 +1,14 @@ 
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 Marvell.
+
+# override default name to drop the hyphen
+name = 'graph'
+if not build
+    subdir_done()
+endif
+
+deps += ['bus_pci', 'graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline']
+sources = files(
+        'cli.c',
+        'main.c',
+)
diff --git a/app/graph/module_api.h b/app/graph/module_api.h
new file mode 100644
index 0000000000..372aeae7e3
--- /dev/null
+++ b/app/graph/module_api.h
@@ -0,0 +1,16 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Marvell.
+ */
+
+#ifndef APP_GRAPH_MODULE_API_H
+#define APP_GRAPH_MODULE_API_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "cli.h"
+/*
+ * Externs
+ */
+extern volatile bool force_quit;
+
+#endif
diff --git a/app/meson.build b/app/meson.build
index e4bf5c531c..728c936383 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -17,6 +17,7 @@  endif
 apps = [
         'dumpcap',
         'pdump',
+        'graph',
         'proc-info',
         'test-acl',
         'test-bbdev',