f-stack/dpdk/app/graph/main.c

238 lines
4.2 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2023 Marvell.
*/
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <unistd.h>
#include <rte_cycles.h>
#include <rte_eal.h>
#include <rte_launch.h>
#include "module_api.h"
volatile bool force_quit;
struct conn *conn;
static const char usage[] = "%s EAL_ARGS -- -s SCRIPT [-h HOST] [-p PORT] [--enable-graph-stats] "
"[--help]\n";
static struct app_params {
struct conn_params conn;
char *script_name;
bool enable_graph_stats;
} app = {
.conn = {
.welcome = "\nWelcome!\n\n",
.prompt = "graph> ",
.addr = "0.0.0.0",
.port = 8086,
.buf_size = 1024 * 1024,
.msg_in_len_max = 1024,
.msg_out_len_max = 1024 * 1024,
.msg_handle = cli_process,
.msg_handle_arg = NULL, /* set later. */
},
.script_name = NULL,
.enable_graph_stats = false,
};
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'},
{"enable-graph-stats", 0, 0, 'g'},
};
int h_present, p_present, 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 */
h_present = 0;
p_present = 0;
s_present = 0;
while ((opt = getopt_long(argc, argv, "h:p:s:", lgopts, &option_index)) != EOF) {
switch (opt) {
case 'h':
if (h_present) {
printf("Error: Multiple -h arguments\n");
return -1;
}
h_present = 1;
if (!strlen(optarg)) {
printf("Error: Argument for -h not provided\n");
return -1;
}
app.conn.addr = strdup(optarg);
if (app.conn.addr == NULL) {
printf("Error: Not enough memory\n");
return -1;
}
break;
case 'p':
if (p_present) {
printf("Error: Multiple -p arguments\n");
return -1;
}
p_present = 1;
if (!strlen(optarg)) {
printf("Error: Argument for -p not provided\n");
return -1;
}
app.conn.port = (uint16_t)strtoul(optarg, NULL, 10);
break;
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 'g':
app.enable_graph_stats = true;
printf("WARNING! Telnet session can not be accessed with"
"--enable-graph-stats");
break;
case 'H':
default:
printf(usage, app_name);
return -1;
}
}
optind = 1; /* reset getopt lib */
return 0;
}
bool
app_graph_stats_enabled(void)
{
return app.enable_graph_stats;
}
bool
app_graph_exit(void)
{
struct timeval tv;
fd_set fds;
int ret;
char c;
FD_ZERO(&fds);
FD_SET(0, &fds);
tv.tv_sec = 0;
tv.tv_usec = 100;
ret = select(1, &fds, NULL, NULL, &tv);
if ((ret < 0 && errno == EINTR) || (ret == 1 && read(0, &c, 1) > 0))
return true;
else
return false;
}
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, app.conn.msg_in_len_max,
app.conn.msg_out_len_max, NULL);
}
/* Connectivity */
app.conn.msg_handle_arg = NULL;
conn = conn_init(&app.conn);
if (!conn) {
printf("Error: Connectivity initialization failed\n");
goto exit;
};
rte_delay_ms(1);
printf("Press enter to exit\n");
/* Dispatch loop */
while (!force_quit) {
conn_req_poll(conn);
conn_msg_poll(conn);
if (app_graph_exit())
force_quit = true;
}
exit:
conn_free(conn);
ethdev_stop();
cli_exit();
rte_eal_cleanup();
return 0;
}