15b21ffb2SSunil Kumar Kori /* SPDX-License-Identifier: BSD-3-Clause
25b21ffb2SSunil Kumar Kori * Copyright(c) 2023 Marvell.
35b21ffb2SSunil Kumar Kori */
45b21ffb2SSunil Kumar Kori
53f90eda5SSunil Kumar Kori #include <errno.h>
65b21ffb2SSunil Kumar Kori #include <fcntl.h>
75b21ffb2SSunil Kumar Kori #include <getopt.h>
85b21ffb2SSunil Kumar Kori #include <signal.h>
95b21ffb2SSunil Kumar Kori #include <stdio.h>
105b21ffb2SSunil Kumar Kori #include <stdlib.h>
115b21ffb2SSunil Kumar Kori #include <string.h>
125b21ffb2SSunil Kumar Kori #include <sys/select.h>
135b21ffb2SSunil Kumar Kori #include <unistd.h>
145b21ffb2SSunil Kumar Kori
153f90eda5SSunil Kumar Kori #include <rte_cycles.h>
165b21ffb2SSunil Kumar Kori #include <rte_eal.h>
175b21ffb2SSunil Kumar Kori #include <rte_launch.h>
185b21ffb2SSunil Kumar Kori
195b21ffb2SSunil Kumar Kori #include "module_api.h"
205b21ffb2SSunil Kumar Kori
215b21ffb2SSunil Kumar Kori volatile bool force_quit;
223f90eda5SSunil Kumar Kori struct conn *conn;
235b21ffb2SSunil Kumar Kori
24*6f1407a1SSunil Kumar Kori static const char usage[] = "%s EAL_ARGS -- -s SCRIPT [-h HOST] [-p PORT] [--enable-graph-stats] "
255b21ffb2SSunil Kumar Kori "[--help]\n";
265b21ffb2SSunil Kumar Kori
275b21ffb2SSunil Kumar Kori static struct app_params {
283f90eda5SSunil Kumar Kori struct conn_params conn;
295b21ffb2SSunil Kumar Kori char *script_name;
30*6f1407a1SSunil Kumar Kori bool enable_graph_stats;
315b21ffb2SSunil Kumar Kori } app = {
323f90eda5SSunil Kumar Kori .conn = {
333f90eda5SSunil Kumar Kori .welcome = "\nWelcome!\n\n",
343f90eda5SSunil Kumar Kori .prompt = "graph> ",
353f90eda5SSunil Kumar Kori .addr = "0.0.0.0",
363f90eda5SSunil Kumar Kori .port = 8086,
373f90eda5SSunil Kumar Kori .buf_size = 1024 * 1024,
383f90eda5SSunil Kumar Kori .msg_in_len_max = 1024,
393f90eda5SSunil Kumar Kori .msg_out_len_max = 1024 * 1024,
403f90eda5SSunil Kumar Kori .msg_handle = cli_process,
413f90eda5SSunil Kumar Kori .msg_handle_arg = NULL, /* set later. */
423f90eda5SSunil Kumar Kori },
435b21ffb2SSunil Kumar Kori .script_name = NULL,
44*6f1407a1SSunil Kumar Kori .enable_graph_stats = false,
455b21ffb2SSunil Kumar Kori };
465b21ffb2SSunil Kumar Kori
475b21ffb2SSunil Kumar Kori static void
signal_handler(int signum)485b21ffb2SSunil Kumar Kori signal_handler(int signum)
495b21ffb2SSunil Kumar Kori {
505b21ffb2SSunil Kumar Kori if (signum == SIGINT || signum == SIGTERM) {
515b21ffb2SSunil Kumar Kori printf("\n\nSignal %d received, preparing to exit...\n", signum);
525b21ffb2SSunil Kumar Kori force_quit = true;
535b21ffb2SSunil Kumar Kori }
545b21ffb2SSunil Kumar Kori }
555b21ffb2SSunil Kumar Kori
565b21ffb2SSunil Kumar Kori static int
app_args_parse(int argc,char ** argv)575b21ffb2SSunil Kumar Kori app_args_parse(int argc, char **argv)
585b21ffb2SSunil Kumar Kori {
595b21ffb2SSunil Kumar Kori struct option lgopts[] = {
605b21ffb2SSunil Kumar Kori {"help", 0, 0, 'H'},
61*6f1407a1SSunil Kumar Kori {"enable-graph-stats", 0, 0, 'g'},
625b21ffb2SSunil Kumar Kori };
633f90eda5SSunil Kumar Kori int h_present, p_present, s_present, n_args, i;
645b21ffb2SSunil Kumar Kori char *app_name = argv[0];
655b21ffb2SSunil Kumar Kori int opt, option_index;
665b21ffb2SSunil Kumar Kori
675b21ffb2SSunil Kumar Kori /* Skip EAL input args */
685b21ffb2SSunil Kumar Kori n_args = argc;
695b21ffb2SSunil Kumar Kori for (i = 0; i < n_args; i++)
705b21ffb2SSunil Kumar Kori if (strcmp(argv[i], "--") == 0) {
715b21ffb2SSunil Kumar Kori argc -= i;
725b21ffb2SSunil Kumar Kori argv += i;
735b21ffb2SSunil Kumar Kori break;
745b21ffb2SSunil Kumar Kori }
755b21ffb2SSunil Kumar Kori
765b21ffb2SSunil Kumar Kori if (i == n_args)
775b21ffb2SSunil Kumar Kori return 0;
785b21ffb2SSunil Kumar Kori
795b21ffb2SSunil Kumar Kori /* Parse args */
803f90eda5SSunil Kumar Kori h_present = 0;
813f90eda5SSunil Kumar Kori p_present = 0;
825b21ffb2SSunil Kumar Kori s_present = 0;
835b21ffb2SSunil Kumar Kori
843f90eda5SSunil Kumar Kori while ((opt = getopt_long(argc, argv, "h:p:s:", lgopts, &option_index)) != EOF) {
855b21ffb2SSunil Kumar Kori switch (opt) {
863f90eda5SSunil Kumar Kori case 'h':
873f90eda5SSunil Kumar Kori if (h_present) {
883f90eda5SSunil Kumar Kori printf("Error: Multiple -h arguments\n");
893f90eda5SSunil Kumar Kori return -1;
903f90eda5SSunil Kumar Kori }
913f90eda5SSunil Kumar Kori h_present = 1;
923f90eda5SSunil Kumar Kori
933f90eda5SSunil Kumar Kori if (!strlen(optarg)) {
943f90eda5SSunil Kumar Kori printf("Error: Argument for -h not provided\n");
953f90eda5SSunil Kumar Kori return -1;
963f90eda5SSunil Kumar Kori }
973f90eda5SSunil Kumar Kori
983f90eda5SSunil Kumar Kori app.conn.addr = strdup(optarg);
993f90eda5SSunil Kumar Kori if (app.conn.addr == NULL) {
1003f90eda5SSunil Kumar Kori printf("Error: Not enough memory\n");
1013f90eda5SSunil Kumar Kori return -1;
1023f90eda5SSunil Kumar Kori }
1033f90eda5SSunil Kumar Kori break;
1043f90eda5SSunil Kumar Kori
1053f90eda5SSunil Kumar Kori case 'p':
1063f90eda5SSunil Kumar Kori if (p_present) {
1073f90eda5SSunil Kumar Kori printf("Error: Multiple -p arguments\n");
1083f90eda5SSunil Kumar Kori return -1;
1093f90eda5SSunil Kumar Kori }
1103f90eda5SSunil Kumar Kori p_present = 1;
1113f90eda5SSunil Kumar Kori
1123f90eda5SSunil Kumar Kori if (!strlen(optarg)) {
1133f90eda5SSunil Kumar Kori printf("Error: Argument for -p not provided\n");
1143f90eda5SSunil Kumar Kori return -1;
1153f90eda5SSunil Kumar Kori }
1163f90eda5SSunil Kumar Kori
1173f90eda5SSunil Kumar Kori app.conn.port = (uint16_t)strtoul(optarg, NULL, 10);
1183f90eda5SSunil Kumar Kori break;
1193f90eda5SSunil Kumar Kori
1205b21ffb2SSunil Kumar Kori case 's':
1215b21ffb2SSunil Kumar Kori if (s_present) {
1225b21ffb2SSunil Kumar Kori printf("Error: Multiple -s arguments\n");
1235b21ffb2SSunil Kumar Kori return -1;
1245b21ffb2SSunil Kumar Kori }
1255b21ffb2SSunil Kumar Kori s_present = 1;
1265b21ffb2SSunil Kumar Kori
1275b21ffb2SSunil Kumar Kori if (!strlen(optarg)) {
1285b21ffb2SSunil Kumar Kori printf("Error: Argument for -s not provided\n");
1295b21ffb2SSunil Kumar Kori return -1;
1305b21ffb2SSunil Kumar Kori }
1315b21ffb2SSunil Kumar Kori
1325b21ffb2SSunil Kumar Kori app.script_name = strdup(optarg);
1335b21ffb2SSunil Kumar Kori if (app.script_name == NULL) {
1345b21ffb2SSunil Kumar Kori printf("Error: Not enough memory\n");
1355b21ffb2SSunil Kumar Kori return -1;
1365b21ffb2SSunil Kumar Kori }
1375b21ffb2SSunil Kumar Kori break;
1385b21ffb2SSunil Kumar Kori
139*6f1407a1SSunil Kumar Kori case 'g':
140*6f1407a1SSunil Kumar Kori app.enable_graph_stats = true;
141*6f1407a1SSunil Kumar Kori printf("WARNING! Telnet session can not be accessed with"
142*6f1407a1SSunil Kumar Kori "--enable-graph-stats");
143*6f1407a1SSunil Kumar Kori break;
144*6f1407a1SSunil Kumar Kori
1455b21ffb2SSunil Kumar Kori case 'H':
1465b21ffb2SSunil Kumar Kori default:
1475b21ffb2SSunil Kumar Kori printf(usage, app_name);
1485b21ffb2SSunil Kumar Kori return -1;
1495b21ffb2SSunil Kumar Kori }
1505b21ffb2SSunil Kumar Kori }
1515b21ffb2SSunil Kumar Kori optind = 1; /* reset getopt lib */
1525b21ffb2SSunil Kumar Kori
1535b21ffb2SSunil Kumar Kori return 0;
1545b21ffb2SSunil Kumar Kori }
1555b21ffb2SSunil Kumar Kori
1563f90eda5SSunil Kumar Kori bool
app_graph_stats_enabled(void)157*6f1407a1SSunil Kumar Kori app_graph_stats_enabled(void)
158*6f1407a1SSunil Kumar Kori {
159*6f1407a1SSunil Kumar Kori return app.enable_graph_stats;
160*6f1407a1SSunil Kumar Kori }
161*6f1407a1SSunil Kumar Kori
162*6f1407a1SSunil Kumar Kori bool
app_graph_exit(void)1633f90eda5SSunil Kumar Kori app_graph_exit(void)
1643f90eda5SSunil Kumar Kori {
1653f90eda5SSunil Kumar Kori struct timeval tv;
1663f90eda5SSunil Kumar Kori fd_set fds;
1673f90eda5SSunil Kumar Kori int ret;
1683f90eda5SSunil Kumar Kori char c;
1693f90eda5SSunil Kumar Kori
1703f90eda5SSunil Kumar Kori FD_ZERO(&fds);
1713f90eda5SSunil Kumar Kori FD_SET(0, &fds);
1723f90eda5SSunil Kumar Kori tv.tv_sec = 0;
1733f90eda5SSunil Kumar Kori tv.tv_usec = 100;
1743f90eda5SSunil Kumar Kori ret = select(1, &fds, NULL, NULL, &tv);
1753f90eda5SSunil Kumar Kori if ((ret < 0 && errno == EINTR) || (ret == 1 && read(0, &c, 1) > 0))
1763f90eda5SSunil Kumar Kori return true;
1773f90eda5SSunil Kumar Kori else
1783f90eda5SSunil Kumar Kori return false;
1793f90eda5SSunil Kumar Kori
1803f90eda5SSunil Kumar Kori }
1813f90eda5SSunil Kumar Kori
1825b21ffb2SSunil Kumar Kori int
main(int argc,char ** argv)1835b21ffb2SSunil Kumar Kori main(int argc, char **argv)
1845b21ffb2SSunil Kumar Kori {
1855b21ffb2SSunil Kumar Kori int rc;
1865b21ffb2SSunil Kumar Kori
1875b21ffb2SSunil Kumar Kori /* Parse application arguments */
1885b21ffb2SSunil Kumar Kori rc = app_args_parse(argc, argv);
1895b21ffb2SSunil Kumar Kori if (rc < 0)
1905b21ffb2SSunil Kumar Kori return rc;
1915b21ffb2SSunil Kumar Kori
1925b21ffb2SSunil Kumar Kori /* EAL */
1935b21ffb2SSunil Kumar Kori rc = rte_eal_init(argc, argv);
1945b21ffb2SSunil Kumar Kori if (rc < 0) {
1955b21ffb2SSunil Kumar Kori printf("Error: EAL initialization failed (%d)\n", rc);
1965b21ffb2SSunil Kumar Kori return rc;
1975b21ffb2SSunil Kumar Kori };
1985b21ffb2SSunil Kumar Kori
1995b21ffb2SSunil Kumar Kori force_quit = false;
2005b21ffb2SSunil Kumar Kori signal(SIGINT, signal_handler);
2015b21ffb2SSunil Kumar Kori signal(SIGTERM, signal_handler);
2025b21ffb2SSunil Kumar Kori
2035b21ffb2SSunil Kumar Kori cli_init();
2045b21ffb2SSunil Kumar Kori
2055b21ffb2SSunil Kumar Kori /* Script */
2065b21ffb2SSunil Kumar Kori if (app.script_name) {
2073f90eda5SSunil Kumar Kori cli_script_process(app.script_name, app.conn.msg_in_len_max,
2083f90eda5SSunil Kumar Kori app.conn.msg_out_len_max, NULL);
2095b21ffb2SSunil Kumar Kori }
2105b21ffb2SSunil Kumar Kori
2113f90eda5SSunil Kumar Kori /* Connectivity */
2123f90eda5SSunil Kumar Kori app.conn.msg_handle_arg = NULL;
2133f90eda5SSunil Kumar Kori conn = conn_init(&app.conn);
2143f90eda5SSunil Kumar Kori if (!conn) {
2153f90eda5SSunil Kumar Kori printf("Error: Connectivity initialization failed\n");
2163f90eda5SSunil Kumar Kori goto exit;
2173f90eda5SSunil Kumar Kori };
2183f90eda5SSunil Kumar Kori
2193f90eda5SSunil Kumar Kori rte_delay_ms(1);
2203f90eda5SSunil Kumar Kori printf("Press enter to exit\n");
2213f90eda5SSunil Kumar Kori
2223f90eda5SSunil Kumar Kori /* Dispatch loop */
2233f90eda5SSunil Kumar Kori while (!force_quit) {
2243f90eda5SSunil Kumar Kori conn_req_poll(conn);
2253f90eda5SSunil Kumar Kori
2263f90eda5SSunil Kumar Kori conn_msg_poll(conn);
2273f90eda5SSunil Kumar Kori if (app_graph_exit())
2283f90eda5SSunil Kumar Kori force_quit = true;
2293f90eda5SSunil Kumar Kori }
2303f90eda5SSunil Kumar Kori
2313f90eda5SSunil Kumar Kori exit:
2323f90eda5SSunil Kumar Kori conn_free(conn);
2333850cb06SSunil Kumar Kori ethdev_stop();
2345b21ffb2SSunil Kumar Kori cli_exit();
2355b21ffb2SSunil Kumar Kori rte_eal_cleanup();
2365b21ffb2SSunil Kumar Kori return 0;
2375b21ffb2SSunil Kumar Kori }
238