From fee7bbb8a1512c37c118605a09867476f3bbef77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Fri, 29 Jan 2021 13:26:03 +0200 Subject: example: add CLI helper example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This example shows how to start and stop ODP CLI using the CLI helper API functions. Signed-off-by: Jere Leppänen Reviewed-by: Matias Elo --- doc/application-api-guide/examples.dox | 5 + example/Makefile.am | 4 + example/cli/.gitignore | 3 + example/cli/Makefile.am | 31 ++++++ example/cli/odp_cli.c | 176 +++++++++++++++++++++++++++++++++ example/cli/odp_cli_run.sh | 9 ++ example/m4/configure.m4 | 1 + 7 files changed, 229 insertions(+) create mode 100644 example/cli/.gitignore create mode 100644 example/cli/Makefile.am create mode 100644 example/cli/odp_cli.c create mode 100755 example/cli/odp_cli_run.sh diff --git a/doc/application-api-guide/examples.dox b/doc/application-api-guide/examples.dox index 98e66d72b..18817cd63 100644 --- a/doc/application-api-guide/examples.dox +++ b/doc/application-api-guide/examples.dox @@ -9,6 +9,11 @@ * Classifier example application */ +/** + * @example odp_cli.c + * CLI example application + */ + /** * @example odp_debug.c * Debug example application diff --git a/example/Makefile.am b/example/Makefile.am index fc4623d1f..d6d242cf9 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -18,3 +18,7 @@ SUBDIRS = classifier \ if HAVE_DW_ATOMIC_CMP_EXC SUBDIRS += ipfragreass endif + +if helper_cli +SUBDIRS += cli +endif diff --git a/example/cli/.gitignore b/example/cli/.gitignore new file mode 100644 index 000000000..2a19d7a64 --- /dev/null +++ b/example/cli/.gitignore @@ -0,0 +1,3 @@ +odp_cli +*.log +*.trs diff --git a/example/cli/Makefile.am b/example/cli/Makefile.am new file mode 100644 index 000000000..0e97a09ed --- /dev/null +++ b/example/cli/Makefile.am @@ -0,0 +1,31 @@ +include $(top_srcdir)/example/Makefile.inc + +bin_PROGRAMS = odp_cli + +odp_cli_SOURCES = odp_cli.c + +if test_example +TESTS = odp_cli_run.sh +endif + +EXTRA_DIST = odp_cli_run.sh + +# If building out-of-tree, make check will not copy the scripts and data to the +# $(builddir) assuming that all commands are run locally. However this prevents +# running tests on a remote target using LOG_COMPILER. +# So copy all script and data files explicitly here. +all-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + if [ -e $(srcdir)/$$f ]; then \ + mkdir -p $(builddir)/$$(dirname $$f); \ + cp -f $(srcdir)/$$f $(builddir)/$$f; \ + fi \ + done \ + fi +clean-local: + if [ "x$(srcdir)" != "x$(builddir)" ]; then \ + for f in $(EXTRA_DIST); do \ + rm -f $(builddir)/$$f; \ + done \ + fi diff --git a/example/cli/odp_cli.c b/example/cli/odp_cli.c new file mode 100644 index 000000000..e3998129c --- /dev/null +++ b/example/cli/odp_cli.c @@ -0,0 +1,176 @@ +/* Copyright (c) 2021, Nokia + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ODP CLI Helper Example + * + * This example shows how to start and stop ODP CLI using the CLI helper + * API functions. This example application can also be used to try out + * the CLI by connecting to a running application with a telnet client. + */ + +#include +#include + +#include +#include +#include + +typedef struct { + int time; + char *addr; + uint16_t port; +} options_t; + +static void usage(const char *prog) +{ + printf("\n" + "Usage: %s [options]\n" + "\n" + "OPTIONS:\n" + " -t, --time Keep CLI open for seconds. (default -1 (infinite))\n" + " -a, --address Bind listening socket to IP address .\n" + " -p, --port Bind listening socket to port .\n" + "\n" + "ODP helper defaults are used for address and port, if the options are\n" + "not given.\n" + "\n", + prog); +} + +static void parse_args(int argc, char *argv[], options_t *opt) +{ + static const struct option longopts[] = { + { "time", required_argument, NULL, 't' }, + { "address", required_argument, NULL, 'a' }, + { "port", required_argument, NULL, 'p' }, + { "help", no_argument, NULL, 'h' }, + { NULL, 0, NULL, 0 } + }; + + static const char *shortopts = "+t:a:p:h"; + + while (1) { + int c = getopt_long(argc, argv, shortopts, longopts, NULL); + + if (c == -1) + break; /* No more options */ + + switch (c) { + case 't': + opt->time = atoi(optarg); + break; + case 'a': + opt->addr = optarg; + break; + case 'p': + opt->port = atoi(optarg); + break; + default: + usage(argv[0]); + exit(EXIT_SUCCESS); + break; + } + } + + optind = 1; /* reset 'extern optind' from the getopt lib */ +} + +static volatile int shutdown_sig; + +static void sig_handler(int signo) +{ + (void)signo; + + shutdown_sig = 1; +} + +int main(int argc, char *argv[]) +{ + signal(SIGINT, sig_handler); + + odph_helper_options_t helper_options; + + /* Let helper collect its own arguments (e.g. --odph_proc) */ + argc = odph_parse_options(argc, argv); + if (odph_options(&helper_options)) { + ODPH_ERR("Error: reading ODP helper options failed.\n"); + exit(EXIT_FAILURE); + } + + odp_init_t init; + + odp_init_param_init(&init); + init.mem_model = helper_options.mem_model; + + options_t opt = { + .time = -1, + .addr = NULL, + .port = 0, + }; + + parse_args(argc, argv, &opt); + + /* Initialize ODP. */ + + odp_instance_t inst; + + if (odp_init_global(&inst, &init, NULL)) { + ODPH_ERR("Global init failed.\n"); + exit(EXIT_FAILURE); + } + + if (odp_init_local(inst, ODP_THREAD_CONTROL)) { + ODPH_ERR("Local init failed.\n"); + exit(EXIT_FAILURE); + } + + /* Prepare CLI parameters. */ + + odph_cli_param_t cli_param; + + odph_cli_param_init(&cli_param); + + if (opt.addr) + cli_param.address = opt.addr; + + if (opt.port) + cli_param.port = opt.port; + + /* Start CLI server. */ + if (odph_cli_start(inst, &cli_param)) { + ODPH_ERR("CLI start failed.\n"); + exit(EXIT_FAILURE); + } + + printf("CLI server started on %s:%d\n", cli_param.address, cli_param.port); + + /* Wait for the given number of seconds. */ + for (int i = 0; (opt.time < 0 || i < opt.time) && !shutdown_sig; i++) + odp_time_wait_ns(ODP_TIME_SEC_IN_NS); + + printf("Stopping CLI server.\n"); + + /* Stop CLI server. */ + if (odph_cli_stop()) { + ODPH_ERR("CLI stop failed.\n"); + exit(EXIT_FAILURE); + } + + /* Terminate ODP. */ + + if (odp_term_local()) { + ODPH_ERR("Local term failed.\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_global(inst)) { + ODPH_ERR("Global term failed.\n"); + exit(EXIT_FAILURE); + } + + return 0; +} diff --git a/example/cli/odp_cli_run.sh b/example/cli/odp_cli_run.sh new file mode 100755 index 000000000..0dc00b793 --- /dev/null +++ b/example/cli/odp_cli_run.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# +# Copyright (c) 2021, Nokia +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +./odp_cli${EXEEXT} -t 2 diff --git a/example/m4/configure.m4 b/example/m4/configure.m4 index a1668e2b3..b02fd72a5 100644 --- a/example/m4/configure.m4 +++ b/example/m4/configure.m4 @@ -20,6 +20,7 @@ AC_ARG_ENABLE([test-example], AM_CONDITIONAL([test_example], [test x$test_example = xyes ]) AC_CONFIG_FILES([example/classifier/Makefile + example/cli/Makefile example/debug/Makefile example/generator/Makefile example/hello/Makefile -- cgit v1.2.3