eal: support strlcat function
[dpdk.git] / test / test / commands.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright(c) 2014 6WIND S.A.
4  */
5
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <netinet/in.h>
12 #include <termios.h>
13 #ifndef __linux__
14 #ifndef __FreeBSD__
15 #include <net/socket.h>
16 #endif
17 #endif
18 #include <inttypes.h>
19 #include <errno.h>
20 #include <sys/queue.h>
21
22 #include <rte_common.h>
23 #include <rte_log.h>
24 #include <rte_debug.h>
25 #include <rte_memory.h>
26 #include <rte_memcpy.h>
27 #include <rte_memzone.h>
28 #include <rte_launch.h>
29 #include <rte_cycles.h>
30 #include <rte_eal.h>
31 #include <rte_per_lcore.h>
32 #include <rte_lcore.h>
33 #include <rte_atomic.h>
34 #include <rte_branch_prediction.h>
35 #include <rte_ring.h>
36 #include <rte_malloc.h>
37 #include <rte_mempool.h>
38 #include <rte_mbuf.h>
39 #include <rte_devargs.h>
40
41 #include <cmdline_rdline.h>
42 #include <cmdline_parse.h>
43 #include <cmdline_parse_ipaddr.h>
44 #include <cmdline_parse_num.h>
45 #include <cmdline_parse_string.h>
46 #include <cmdline.h>
47
48 #include "test.h"
49
50 /****************/
51
52 static struct test_commands_list commands_list =
53         TAILQ_HEAD_INITIALIZER(commands_list);
54
55 void
56 add_test_command(struct test_command *t)
57 {
58         TAILQ_INSERT_TAIL(&commands_list, t, next);
59 }
60
61 struct cmd_autotest_result {
62         cmdline_fixed_string_t autotest;
63 };
64
65 static void cmd_autotest_parsed(void *parsed_result,
66                                 __attribute__((unused)) struct cmdline *cl,
67                                 __attribute__((unused)) void *data)
68 {
69         struct test_command *t;
70         struct cmd_autotest_result *res = parsed_result;
71         int ret = 0;
72
73         TAILQ_FOREACH(t, &commands_list, next) {
74                 if (!strcmp(res->autotest, t->command))
75                         ret = t->callback();
76         }
77
78         last_test_result = ret;
79         if (ret == 0)
80                 printf("Test OK\n");
81         else if (ret == TEST_SKIPPED)
82                 printf("Test Skipped\n");
83         else
84                 printf("Test Failed\n");
85         fflush(stdout);
86 }
87
88 cmdline_parse_token_string_t cmd_autotest_autotest =
89         TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest,
90                                  "");
91
92 cmdline_parse_inst_t cmd_autotest = {
93         .f = cmd_autotest_parsed,  /* function to call */
94         .data = NULL,      /* 2nd arg of func */
95         .help_str = "launch autotest",
96         .tokens = {        /* token list, NULL terminated */
97                 (void *)&cmd_autotest_autotest,
98                 NULL,
99         },
100 };
101
102 /****************/
103
104 struct cmd_dump_result {
105         cmdline_fixed_string_t dump;
106 };
107
108 static void
109 dump_struct_sizes(void)
110 {
111 #define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t));
112         DUMP_SIZE(struct rte_mbuf);
113         DUMP_SIZE(struct rte_mempool);
114         DUMP_SIZE(struct rte_ring);
115 #undef DUMP_SIZE
116 }
117
118 static void cmd_dump_parsed(void *parsed_result,
119                             __attribute__((unused)) struct cmdline *cl,
120                             __attribute__((unused)) void *data)
121 {
122         struct cmd_dump_result *res = parsed_result;
123
124         if (!strcmp(res->dump, "dump_physmem"))
125                 rte_dump_physmem_layout(stdout);
126         else if (!strcmp(res->dump, "dump_memzone"))
127                 rte_memzone_dump(stdout);
128         else if (!strcmp(res->dump, "dump_struct_sizes"))
129                 dump_struct_sizes();
130         else if (!strcmp(res->dump, "dump_ring"))
131                 rte_ring_list_dump(stdout);
132         else if (!strcmp(res->dump, "dump_mempool"))
133                 rte_mempool_list_dump(stdout);
134         else if (!strcmp(res->dump, "dump_devargs"))
135                 rte_devargs_dump(stdout);
136         else if (!strcmp(res->dump, "dump_log_types"))
137                 rte_log_dump(stdout);
138         else if (!strcmp(res->dump, "dump_malloc_stats"))
139                 rte_malloc_dump_stats(stdout, NULL);
140         else if (!strcmp(res->dump, "dump_malloc_heaps"))
141                 rte_malloc_dump_heaps(stdout);
142 }
143
144 cmdline_parse_token_string_t cmd_dump_dump =
145         TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
146                                  "dump_physmem#"
147                                  "dump_memzone#"
148                                  "dump_struct_sizes#"
149                                  "dump_ring#"
150                                  "dump_mempool#"
151                                  "dump_malloc_stats#"
152                                  "dump_malloc_heaps#"
153                                  "dump_devargs#"
154                                  "dump_log_types");
155
156 cmdline_parse_inst_t cmd_dump = {
157         .f = cmd_dump_parsed,  /* function to call */
158         .data = NULL,      /* 2nd arg of func */
159         .help_str = "dump status",
160         .tokens = {        /* token list, NULL terminated */
161                 (void *)&cmd_dump_dump,
162                 NULL,
163         },
164 };
165
166 /****************/
167
168 struct cmd_dump_one_result {
169         cmdline_fixed_string_t dump;
170         cmdline_fixed_string_t name;
171 };
172
173 static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl,
174                                 __attribute__((unused)) void *data)
175 {
176         struct cmd_dump_one_result *res = parsed_result;
177
178         if (!strcmp(res->dump, "dump_ring")) {
179                 struct rte_ring *r;
180                 r = rte_ring_lookup(res->name);
181                 if (r == NULL) {
182                         cmdline_printf(cl, "Cannot find ring\n");
183                         return;
184                 }
185                 rte_ring_dump(stdout, r);
186         }
187         else if (!strcmp(res->dump, "dump_mempool")) {
188                 struct rte_mempool *mp;
189                 mp = rte_mempool_lookup(res->name);
190                 if (mp == NULL) {
191                         cmdline_printf(cl, "Cannot find mempool\n");
192                         return;
193                 }
194                 rte_mempool_dump(stdout, mp);
195         }
196 }
197
198 cmdline_parse_token_string_t cmd_dump_one_dump =
199         TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump,
200                                  "dump_ring#dump_mempool");
201
202 cmdline_parse_token_string_t cmd_dump_one_name =
203         TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL);
204
205 cmdline_parse_inst_t cmd_dump_one = {
206         .f = cmd_dump_one_parsed,  /* function to call */
207         .data = NULL,      /* 2nd arg of func */
208         .help_str = "dump one ring/mempool: dump_ring|dump_mempool <name>",
209         .tokens = {        /* token list, NULL terminated */
210                 (void *)&cmd_dump_one_dump,
211                 (void *)&cmd_dump_one_name,
212                 NULL,
213         },
214 };
215
216 /****************/
217
218 struct cmd_quit_result {
219         cmdline_fixed_string_t quit;
220 };
221
222 static void
223 cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
224                 struct cmdline *cl,
225                 __attribute__((unused)) void *data)
226 {
227         cmdline_quit(cl);
228 }
229
230 cmdline_parse_token_string_t cmd_quit_quit =
231         TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit,
232                                  "quit");
233
234 cmdline_parse_inst_t cmd_quit = {
235         .f = cmd_quit_parsed,  /* function to call */
236         .data = NULL,      /* 2nd arg of func */
237         .help_str = "exit application",
238         .tokens = {        /* token list, NULL terminated */
239                 (void *)&cmd_quit_quit,
240                 NULL,
241         },
242 };
243
244 /****************/
245
246 struct cmd_set_rxtx_result {
247         cmdline_fixed_string_t set;
248         cmdline_fixed_string_t mode;
249 };
250
251 static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl,
252                                 __attribute__((unused)) void *data)
253 {
254         struct cmd_set_rxtx_result *res = parsed_result;
255         if (test_set_rxtx_conf(res->mode) < 0)
256                 cmdline_printf(cl, "Cannot find such mode\n");
257 }
258
259 cmdline_parse_token_string_t cmd_set_rxtx_set =
260         TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set,
261                                  "set_rxtx_mode");
262
263 cmdline_parse_token_string_t cmd_set_rxtx_mode =
264         TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL);
265
266 cmdline_parse_inst_t cmd_set_rxtx = {
267         .f = cmd_set_rxtx_parsed,  /* function to call */
268         .data = NULL,      /* 2nd arg of func */
269         .help_str = "set rxtx routine: "
270                         "set_rxtx <mode>",
271         .tokens = {        /* token list, NULL terminated */
272                 (void *)&cmd_set_rxtx_set,
273                 (void *)&cmd_set_rxtx_mode,
274                 NULL,
275         },
276 };
277
278 /****************/
279
280 struct cmd_set_rxtx_anchor {
281         cmdline_fixed_string_t set;
282         cmdline_fixed_string_t type;
283 };
284
285 static void
286 cmd_set_rxtx_anchor_parsed(void *parsed_result,
287                            struct cmdline *cl,
288                            __attribute__((unused)) void *data)
289 {
290         struct cmd_set_rxtx_anchor *res = parsed_result;
291         if (test_set_rxtx_anchor(res->type) < 0)
292                 cmdline_printf(cl, "Cannot find such anchor\n");
293 }
294
295 cmdline_parse_token_string_t cmd_set_rxtx_anchor_set =
296         TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, set,
297                                  "set_rxtx_anchor");
298
299 cmdline_parse_token_string_t cmd_set_rxtx_anchor_type =
300         TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, type, NULL);
301
302 cmdline_parse_inst_t cmd_set_rxtx_anchor = {
303         .f = cmd_set_rxtx_anchor_parsed,  /* function to call */
304         .data = NULL,      /* 2nd arg of func */
305         .help_str = "set rxtx anchor: "
306                         "set_rxtx_anchor <type>",
307         .tokens = {        /* token list, NULL terminated */
308                 (void *)&cmd_set_rxtx_anchor_set,
309                 (void *)&cmd_set_rxtx_anchor_type,
310                 NULL,
311         },
312 };
313
314 /****************/
315
316 /* for stream control */
317 struct cmd_set_rxtx_sc {
318         cmdline_fixed_string_t set;
319         cmdline_fixed_string_t type;
320 };
321
322 static void
323 cmd_set_rxtx_sc_parsed(void *parsed_result,
324                            struct cmdline *cl,
325                            __attribute__((unused)) void *data)
326 {
327         struct cmd_set_rxtx_sc *res = parsed_result;
328         if (test_set_rxtx_sc(res->type) < 0)
329                 cmdline_printf(cl, "Cannot find such stream control\n");
330 }
331
332 cmdline_parse_token_string_t cmd_set_rxtx_sc_set =
333         TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set,
334                                  "set_rxtx_sc");
335
336 cmdline_parse_token_string_t cmd_set_rxtx_sc_type =
337         TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL);
338
339 cmdline_parse_inst_t cmd_set_rxtx_sc = {
340         .f = cmd_set_rxtx_sc_parsed,  /* function to call */
341         .data = NULL,      /* 2nd arg of func */
342         .help_str = "set rxtx stream control: "
343                         "set_rxtx_sc <type>",
344         .tokens = {        /* token list, NULL terminated */
345                 (void *)&cmd_set_rxtx_sc_set,
346                 (void *)&cmd_set_rxtx_sc_type,
347                 NULL,
348         },
349 };
350
351 /****************/
352
353
354 cmdline_parse_ctx_t main_ctx[] = {
355         (cmdline_parse_inst_t *)&cmd_autotest,
356         (cmdline_parse_inst_t *)&cmd_dump,
357         (cmdline_parse_inst_t *)&cmd_dump_one,
358         (cmdline_parse_inst_t *)&cmd_quit,
359         (cmdline_parse_inst_t *)&cmd_set_rxtx,
360         (cmdline_parse_inst_t *)&cmd_set_rxtx_anchor,
361         (cmdline_parse_inst_t *)&cmd_set_rxtx_sc,
362         NULL,
363 };
364
365 int commands_init(void)
366 {
367         struct test_command *t;
368         char *commands, *ptr;
369         int commands_len = 0;
370
371         TAILQ_FOREACH(t, &commands_list, next) {
372                 commands_len += strlen(t->command) + 1;
373         }
374
375         commands = malloc(commands_len + 1);
376         if (!commands)
377                 return -1;
378
379         ptr = commands;
380         TAILQ_FOREACH(t, &commands_list, next) {
381                 ptr += sprintf(ptr, "%s#", t->command);
382         }
383         ptr--;
384         ptr[0] = '\0';
385
386         cmd_autotest_autotest.string_data.str = commands;
387         return 0;
388 }