xref: /dpdk/app/graph/main.c (revision 6f1407a19532991ac49054116ca30692bc274f80)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2023 Marvell.
3  */
4 
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <getopt.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/select.h>
13 #include <unistd.h>
14 
15 #include <rte_cycles.h>
16 #include <rte_eal.h>
17 #include <rte_launch.h>
18 
19 #include "module_api.h"
20 
21 volatile bool force_quit;
22 struct conn *conn;
23 
24 static const char usage[] = "%s EAL_ARGS -- -s SCRIPT [-h HOST] [-p PORT] [--enable-graph-stats] "
25 			    "[--help]\n";
26 
27 static struct app_params {
28 	struct conn_params conn;
29 	char *script_name;
30 	bool enable_graph_stats;
31 } app = {
32 	.conn = {
33 		.welcome = "\nWelcome!\n\n",
34 		.prompt = "graph> ",
35 		.addr = "0.0.0.0",
36 		.port = 8086,
37 		.buf_size = 1024 * 1024,
38 		.msg_in_len_max = 1024,
39 		.msg_out_len_max = 1024 * 1024,
40 		.msg_handle = cli_process,
41 		.msg_handle_arg = NULL, /* set later. */
42 	},
43 	.script_name = NULL,
44 	.enable_graph_stats = false,
45 };
46 
47 static void
signal_handler(int signum)48 signal_handler(int signum)
49 {
50 	if (signum == SIGINT || signum == SIGTERM) {
51 		printf("\n\nSignal %d received, preparing to exit...\n", signum);
52 		force_quit = true;
53 	}
54 }
55 
56 static int
app_args_parse(int argc,char ** argv)57 app_args_parse(int argc, char **argv)
58 {
59 	struct option lgopts[] = {
60 		{"help", 0, 0, 'H'},
61 		{"enable-graph-stats", 0, 0, 'g'},
62 	};
63 	int h_present, p_present, s_present, n_args, i;
64 	char *app_name = argv[0];
65 	int opt, option_index;
66 
67 	/* Skip EAL input args */
68 	n_args = argc;
69 	for (i = 0; i < n_args; i++)
70 		if (strcmp(argv[i], "--") == 0) {
71 			argc -= i;
72 			argv += i;
73 			break;
74 		}
75 
76 	if (i == n_args)
77 		return 0;
78 
79 	/* Parse args */
80 	h_present = 0;
81 	p_present = 0;
82 	s_present = 0;
83 
84 	while ((opt = getopt_long(argc, argv, "h:p:s:", lgopts, &option_index)) != EOF) {
85 		switch (opt) {
86 		case 'h':
87 			if (h_present) {
88 				printf("Error: Multiple -h arguments\n");
89 				return -1;
90 			}
91 			h_present = 1;
92 
93 			if (!strlen(optarg)) {
94 				printf("Error: Argument for -h not provided\n");
95 				return -1;
96 			}
97 
98 			app.conn.addr = strdup(optarg);
99 			if (app.conn.addr == NULL) {
100 				printf("Error: Not enough memory\n");
101 				return -1;
102 			}
103 			break;
104 
105 		case 'p':
106 			if (p_present) {
107 				printf("Error: Multiple -p arguments\n");
108 				return -1;
109 			}
110 			p_present = 1;
111 
112 			if (!strlen(optarg)) {
113 				printf("Error: Argument for -p not provided\n");
114 				return -1;
115 			}
116 
117 			app.conn.port = (uint16_t)strtoul(optarg, NULL, 10);
118 			break;
119 
120 		case 's':
121 			if (s_present) {
122 				printf("Error: Multiple -s arguments\n");
123 				return -1;
124 			}
125 			s_present = 1;
126 
127 			if (!strlen(optarg)) {
128 				printf("Error: Argument for -s not provided\n");
129 				return -1;
130 			}
131 
132 			app.script_name = strdup(optarg);
133 			if (app.script_name == NULL) {
134 				printf("Error: Not enough memory\n");
135 				return -1;
136 			}
137 			break;
138 
139 		case 'g':
140 			app.enable_graph_stats = true;
141 			printf("WARNING! Telnet session can not be accessed with"
142 			       "--enable-graph-stats");
143 			break;
144 
145 		case 'H':
146 		default:
147 			printf(usage, app_name);
148 			return -1;
149 		}
150 	}
151 	optind = 1; /* reset getopt lib */
152 
153 	return 0;
154 }
155 
156 bool
app_graph_stats_enabled(void)157 app_graph_stats_enabled(void)
158 {
159 	return app.enable_graph_stats;
160 }
161 
162 bool
app_graph_exit(void)163 app_graph_exit(void)
164 {
165 	struct timeval tv;
166 	fd_set fds;
167 	int ret;
168 	char c;
169 
170 	FD_ZERO(&fds);
171 	FD_SET(0, &fds);
172 	tv.tv_sec = 0;
173 	tv.tv_usec = 100;
174 	ret = select(1, &fds, NULL, NULL, &tv);
175 	if ((ret < 0 && errno == EINTR) || (ret == 1 && read(0, &c, 1) > 0))
176 		return true;
177 	else
178 		return false;
179 
180 }
181 
182 int
main(int argc,char ** argv)183 main(int argc, char **argv)
184 {
185 	int rc;
186 
187 	/* Parse application arguments */
188 	rc = app_args_parse(argc, argv);
189 	if (rc < 0)
190 		return rc;
191 
192 	/* EAL */
193 	rc = rte_eal_init(argc, argv);
194 	if (rc < 0) {
195 		printf("Error: EAL initialization failed (%d)\n", rc);
196 		return rc;
197 	};
198 
199 	force_quit = false;
200 	signal(SIGINT, signal_handler);
201 	signal(SIGTERM, signal_handler);
202 
203 	cli_init();
204 
205 	/* Script */
206 	if (app.script_name) {
207 		cli_script_process(app.script_name, app.conn.msg_in_len_max,
208 			app.conn.msg_out_len_max, NULL);
209 	}
210 
211 	/* Connectivity */
212 	app.conn.msg_handle_arg = NULL;
213 	conn = conn_init(&app.conn);
214 	if (!conn) {
215 		printf("Error: Connectivity initialization failed\n");
216 		goto exit;
217 	};
218 
219 	rte_delay_ms(1);
220 	printf("Press enter to exit\n");
221 
222 	/* Dispatch loop */
223 	while (!force_quit) {
224 		conn_req_poll(conn);
225 
226 		conn_msg_poll(conn);
227 		if (app_graph_exit())
228 			force_quit = true;
229 	}
230 
231 exit:
232 	conn_free(conn);
233 	ethdev_stop();
234 	cli_exit();
235 	rte_eal_cleanup();
236 	return 0;
237 }
238