API Reference Manual 1.51.0
Loading...
Searching...
No Matches
odp_cli.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (c) 2021-2024 Nokia
3 */
4
15#include <odp_api.h>
16#include <odp/helper/odph_api.h>
17
18#include <stdio.h>
19#include <stdint.h>
20#include <signal.h>
21
22typedef struct {
23 int time;
24 char *addr;
25 uint16_t port;
26} options_t;
27
28static void usage(const char *prog)
29{
30 printf("\n"
31 "Usage: %s [options]\n"
32 "\n"
33 "OPTIONS:\n"
34 " -t, --time <sec> Keep CLI open for <sec> seconds. (default -1 (infinite))\n"
35 " -a, --address <addr> Bind listening socket to IP address <addr>.\n"
36 " -p, --port <port> Bind listening socket to port <port>.\n"
37 "\n"
38 "ODP helper defaults are used for address and port, if the options are\n"
39 "not given.\n"
40 "\n",
41 prog);
42}
43
44static void parse_args(int argc, char *argv[], options_t *opt)
45{
46 static const struct option longopts[] = {
47 { "time", required_argument, NULL, 't' },
48 { "address", required_argument, NULL, 'a' },
49 { "port", required_argument, NULL, 'p' },
50 { "help", no_argument, NULL, 'h' },
51 { NULL, 0, NULL, 0 }
52 };
53
54 static const char *shortopts = "+t:a:p:h";
55
56 while (1) {
57 int c = getopt_long(argc, argv, shortopts, longopts, NULL);
58
59 if (c == -1)
60 break; /* No more options */
61
62 switch (c) {
63 case 't':
64 opt->time = atoi(optarg);
65 break;
66 case 'a':
67 opt->addr = optarg;
68 break;
69 case 'p':
70 opt->port = atoi(optarg);
71 break;
72 default:
73 usage(argv[0]);
74 exit(EXIT_SUCCESS);
75 break;
76 }
77 }
78
79 optind = 1; /* reset 'extern optind' from the getopt lib */
80}
81
82static volatile int shutdown_sig;
83
84static void sig_handler(int signo)
85{
86 (void)signo;
87
88 shutdown_sig = 1;
89}
90
91static void my_cmd(int argc, char *argv[])
92{
93 odph_cli_log("%s(%d): %s\n", __FILE__, __LINE__, __func__);
94
95 for (int i = 0; i < argc; i++)
96 odph_cli_log("argv[%d]: %s\n", i, argv[i]);
97}
98
99static int cli_server(void *arg ODP_UNUSED)
100{
101 /* Run CLI server. */
102 if (odph_cli_run()) {
103 ODPH_ERR("odph_cli_run() failed.\n");
104 return -1;
105 }
106
107 return 0;
108}
109
110int main(int argc, char *argv[])
111{
112 signal(SIGINT, sig_handler);
113
114 odph_helper_options_t helper_options;
115
116 /* Let helper collect its own arguments (e.g. --odph_proc) */
117 argc = odph_parse_options(argc, argv);
118 if (odph_options(&helper_options)) {
119 ODPH_ERR("Error: reading ODP helper options failed.\n");
120 exit(EXIT_FAILURE);
121 }
122
123 odp_init_t init;
124
125 odp_init_param_init(&init);
126 init.mem_model = helper_options.mem_model;
127
128 options_t opt = {
129 .time = -1,
130 .addr = NULL,
131 .port = 0,
132 };
133
134 parse_args(argc, argv, &opt);
135
136 /* Initialize ODP. */
137
138 odp_instance_t inst;
139
140 if (odp_init_global(&inst, &init, NULL)) {
141 ODPH_ERR("Global init failed.\n");
142 exit(EXIT_FAILURE);
143 }
144
146 ODPH_ERR("Local init failed.\n");
147 exit(EXIT_FAILURE);
148 }
149
150 /* Prepare CLI parameters. */
151
152 odph_cli_param_t cli_param;
153
154 odph_cli_param_init(&cli_param);
155
156 if (opt.addr)
157 cli_param.address = opt.addr;
158
159 if (opt.port)
160 cli_param.port = opt.port;
161
162 /* Initialize CLI helper. */
163 if (odph_cli_init(&cli_param)) {
164 ODPH_ERR("CLI helper initialization failed.\n");
165 exit(EXIT_FAILURE);
166 }
167
168 /* Register user command. */
169 if (odph_cli_register_command("my_command", my_cmd,
170 "Example user command.")) {
171 ODPH_ERR("Registering user command failed.\n");
172 exit(EXIT_FAILURE);
173 }
174
175 /* Create server thread. */
176
177 odp_cpumask_t cpumask;
178 odph_thread_common_param_t thr_common;
179 odph_thread_param_t thr_param;
180 odph_thread_t thr_server;
181 odph_thread_join_result_t res;
182
183 if (odp_cpumask_default_control(&cpumask, 1) != 1) {
184 ODPH_ERR("Failed to get default CPU mask.\n");
185 exit(EXIT_FAILURE);
186 }
187
188 odph_thread_common_param_init(&thr_common);
189 thr_common.instance = inst;
190 thr_common.cpumask = &cpumask;
191
192 odph_thread_param_init(&thr_param);
193 thr_param.thr_type = ODP_THREAD_CONTROL;
194 thr_param.start = cli_server;
195
196 memset(&thr_server, 0, sizeof(thr_server));
197
198 if (odph_thread_create(&thr_server, &thr_common, &thr_param, 1) != 1) {
199 ODPH_ERR("Failed to create server thread.\n");
200 exit(EXIT_FAILURE);
201 }
202
203 printf("CLI server started on %s:%d.\n", cli_param.address,
204 cli_param.port);
205
206 /* Wait for the given number of seconds. */
207 for (int i = 0; (opt.time < 0 || i < opt.time) && !shutdown_sig; i++)
209
210 printf("Stopping CLI server.\n");
211
212 /* Stop CLI server. */
213 if (odph_cli_stop()) {
214 ODPH_ERR("CLI stop failed.\n");
215 exit(EXIT_FAILURE);
216 }
217
218 /* Wait for server thread to exit. */
219 if (odph_thread_join_result(&thr_server, &res, 1) != 1) {
220 ODPH_ERR("Failed to join server thread.\n");
221 exit(EXIT_FAILURE);
222 }
223
224 if (res.is_sig || res.ret != 0) {
225 ODPH_ERR("Worker thread failure%s: %d.\n", res.is_sig ? " (signaled)" : "",
226 res.ret);
227 exit(EXIT_FAILURE);
228 }
229
230 /* Terminate CLI helper. */
231 if (odph_cli_term()) {
232 ODPH_ERR("CLI helper termination failed.\n");
233 exit(EXIT_FAILURE);
234 }
235
236 /* Terminate ODP. */
237
238 if (odp_term_local()) {
239 ODPH_ERR("Local term failed.\n");
240 exit(EXIT_FAILURE);
241 }
242
243 if (odp_term_global(inst)) {
244 ODPH_ERR("Global term failed.\n");
245 exit(EXIT_FAILURE);
246 }
247
248 return 0;
249}
#define ODP_UNUSED
Intentionally unused variables of functions.
Definition spec/hints.h:54
int odp_cpumask_default_control(odp_cpumask_t *mask, int num)
Default CPU mask for control threads.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
@ ODP_THREAD_CONTROL
Control thread.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
void odp_time_wait_ns(uint64_t ns)
Wait the specified number of nanoseconds.
The OpenDataPlane API.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.