xref: /dpdk/app/test/commands.c (revision bf56fce1fb45b83747527e6312f61c0fcf3789b8)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   Copyright(c) 2014 6WIND S.A.
6  *   All rights reserved.
7  *
8  *   Redistribution and use in source and binary forms, with or without
9  *   modification, are permitted provided that the following conditions
10  *   are met:
11  *
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in
16  *       the documentation and/or other materials provided with the
17  *       distribution.
18  *     * Neither the name of Intel Corporation nor the names of its
19  *       contributors may be used to endorse or promote products derived
20  *       from this software without specific prior written permission.
21  *
22  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <netinet/in.h>
41 #include <termios.h>
42 #ifndef __linux__
43 #ifndef __FreeBSD__
44 #include <net/socket.h>
45 #endif
46 #endif
47 #include <inttypes.h>
48 #include <errno.h>
49 #include <sys/queue.h>
50 
51 #include <rte_common.h>
52 #include <rte_log.h>
53 #include <rte_debug.h>
54 #include <rte_memory.h>
55 #include <rte_memcpy.h>
56 #include <rte_memzone.h>
57 #include <rte_launch.h>
58 #include <rte_cycles.h>
59 #include <rte_eal.h>
60 #include <rte_per_lcore.h>
61 #include <rte_lcore.h>
62 #include <rte_atomic.h>
63 #include <rte_branch_prediction.h>
64 #include <rte_ring.h>
65 #include <rte_mempool.h>
66 #include <rte_mbuf.h>
67 #include <rte_devargs.h>
68 
69 #include <cmdline_rdline.h>
70 #include <cmdline_parse.h>
71 #include <cmdline_parse_ipaddr.h>
72 #include <cmdline_parse_num.h>
73 #include <cmdline_parse_string.h>
74 #include <cmdline.h>
75 
76 #include "test.h"
77 
78 /****************/
79 
80 static struct test_commands_list commands_list =
81 	TAILQ_HEAD_INITIALIZER(commands_list);
82 
83 void
84 add_test_command(struct test_command *t)
85 {
86 	TAILQ_INSERT_TAIL(&commands_list, t, next);
87 }
88 
89 struct cmd_autotest_result {
90 	cmdline_fixed_string_t autotest;
91 };
92 
93 static void cmd_autotest_parsed(void *parsed_result,
94 				__attribute__((unused)) struct cmdline *cl,
95 				__attribute__((unused)) void *data)
96 {
97 	struct test_command *t;
98 	struct cmd_autotest_result *res = parsed_result;
99 	int ret = 0;
100 
101 	TAILQ_FOREACH(t, &commands_list, next) {
102 		if (!strcmp(res->autotest, t->command))
103 			ret = t->callback();
104 	}
105 
106 	if (ret == 0)
107 		printf("Test OK\n");
108 	else
109 		printf("Test Failed\n");
110 	fflush(stdout);
111 }
112 
113 cmdline_parse_token_string_t cmd_autotest_autotest =
114 	TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest,
115 				 "");
116 
117 cmdline_parse_inst_t cmd_autotest = {
118 	.f = cmd_autotest_parsed,  /* function to call */
119 	.data = NULL,      /* 2nd arg of func */
120 	.help_str = "launch autotest",
121 	.tokens = {        /* token list, NULL terminated */
122 		(void *)&cmd_autotest_autotest,
123 		NULL,
124 	},
125 };
126 
127 /****************/
128 
129 struct cmd_dump_result {
130 	cmdline_fixed_string_t dump;
131 };
132 
133 static void
134 dump_struct_sizes(void)
135 {
136 #define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t));
137 	DUMP_SIZE(struct rte_mbuf);
138 	DUMP_SIZE(struct rte_mempool);
139 	DUMP_SIZE(struct rte_ring);
140 #undef DUMP_SIZE
141 }
142 
143 static void cmd_dump_parsed(void *parsed_result,
144 			    __attribute__((unused)) struct cmdline *cl,
145 			    __attribute__((unused)) void *data)
146 {
147 	struct cmd_dump_result *res = parsed_result;
148 
149 	if (!strcmp(res->dump, "dump_physmem"))
150 		rte_dump_physmem_layout(stdout);
151 	else if (!strcmp(res->dump, "dump_memzone"))
152 		rte_memzone_dump(stdout);
153 	else if (!strcmp(res->dump, "dump_struct_sizes"))
154 		dump_struct_sizes();
155 	else if (!strcmp(res->dump, "dump_ring"))
156 		rte_ring_list_dump(stdout);
157 	else if (!strcmp(res->dump, "dump_mempool"))
158 		rte_mempool_list_dump(stdout);
159 	else if (!strcmp(res->dump, "dump_devargs"))
160 		rte_eal_devargs_dump(stdout);
161 }
162 
163 cmdline_parse_token_string_t cmd_dump_dump =
164 	TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
165 				 "dump_physmem#dump_memzone#"
166 				 "dump_struct_sizes#dump_ring#dump_mempool#"
167 				 "dump_devargs");
168 
169 cmdline_parse_inst_t cmd_dump = {
170 	.f = cmd_dump_parsed,  /* function to call */
171 	.data = NULL,      /* 2nd arg of func */
172 	.help_str = "dump status",
173 	.tokens = {        /* token list, NULL terminated */
174 		(void *)&cmd_dump_dump,
175 		NULL,
176 	},
177 };
178 
179 /****************/
180 
181 struct cmd_dump_one_result {
182 	cmdline_fixed_string_t dump;
183 	cmdline_fixed_string_t name;
184 };
185 
186 static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl,
187 				__attribute__((unused)) void *data)
188 {
189 	struct cmd_dump_one_result *res = parsed_result;
190 
191 	if (!strcmp(res->dump, "dump_ring")) {
192 		struct rte_ring *r;
193 		r = rte_ring_lookup(res->name);
194 		if (r == NULL) {
195 			cmdline_printf(cl, "Cannot find ring\n");
196 			return;
197 		}
198 		rte_ring_dump(stdout, r);
199 	}
200 	else if (!strcmp(res->dump, "dump_mempool")) {
201 		struct rte_mempool *mp;
202 		mp = rte_mempool_lookup(res->name);
203 		if (mp == NULL) {
204 			cmdline_printf(cl, "Cannot find mempool\n");
205 			return;
206 		}
207 		rte_mempool_dump(stdout, mp);
208 	}
209 }
210 
211 cmdline_parse_token_string_t cmd_dump_one_dump =
212 	TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump,
213 				 "dump_ring#dump_mempool");
214 
215 cmdline_parse_token_string_t cmd_dump_one_name =
216 	TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL);
217 
218 cmdline_parse_inst_t cmd_dump_one = {
219 	.f = cmd_dump_one_parsed,  /* function to call */
220 	.data = NULL,      /* 2nd arg of func */
221 	.help_str = "dump one ring/mempool: dump_ring|dump_mempool <name>",
222 	.tokens = {        /* token list, NULL terminated */
223 		(void *)&cmd_dump_one_dump,
224 		(void *)&cmd_dump_one_name,
225 		NULL,
226 	},
227 };
228 
229 /****************/
230 
231 struct cmd_set_ring_result {
232 	cmdline_fixed_string_t set;
233 	cmdline_fixed_string_t name;
234 	uint32_t value;
235 };
236 
237 static void cmd_set_ring_parsed(void *parsed_result, struct cmdline *cl,
238 				__attribute__((unused)) void *data)
239 {
240 	struct cmd_set_ring_result *res = parsed_result;
241 	struct rte_ring *r;
242 	int ret;
243 
244 	r = rte_ring_lookup(res->name);
245 	if (r == NULL) {
246 		cmdline_printf(cl, "Cannot find ring\n");
247 		return;
248 	}
249 
250 	if (!strcmp(res->set, "set_watermark")) {
251 		ret = rte_ring_set_water_mark(r, res->value);
252 		if (ret != 0)
253 			cmdline_printf(cl, "Cannot set water mark\n");
254 	}
255 }
256 
257 cmdline_parse_token_string_t cmd_set_ring_set =
258 	TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, set,
259 				 "set_watermark");
260 
261 cmdline_parse_token_string_t cmd_set_ring_name =
262 	TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, name, NULL);
263 
264 cmdline_parse_token_num_t cmd_set_ring_value =
265 	TOKEN_NUM_INITIALIZER(struct cmd_set_ring_result, value, UINT32);
266 
267 cmdline_parse_inst_t cmd_set_ring = {
268 	.f = cmd_set_ring_parsed,  /* function to call */
269 	.data = NULL,      /* 2nd arg of func */
270 	.help_str = "set watermark: "
271 			"set_watermark <ring_name> <value>",
272 	.tokens = {        /* token list, NULL terminated */
273 		(void *)&cmd_set_ring_set,
274 		(void *)&cmd_set_ring_name,
275 		(void *)&cmd_set_ring_value,
276 		NULL,
277 	},
278 };
279 
280 /****************/
281 
282 struct cmd_quit_result {
283 	cmdline_fixed_string_t quit;
284 };
285 
286 static void
287 cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
288 		struct cmdline *cl,
289 		__attribute__((unused)) void *data)
290 {
291 	cmdline_quit(cl);
292 }
293 
294 cmdline_parse_token_string_t cmd_quit_quit =
295 	TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit,
296 				 "quit");
297 
298 cmdline_parse_inst_t cmd_quit = {
299 	.f = cmd_quit_parsed,  /* function to call */
300 	.data = NULL,      /* 2nd arg of func */
301 	.help_str = "exit application",
302 	.tokens = {        /* token list, NULL terminated */
303 		(void *)&cmd_quit_quit,
304 		NULL,
305 	},
306 };
307 
308 /****************/
309 
310 struct cmd_set_rxtx_result {
311 	cmdline_fixed_string_t set;
312 	cmdline_fixed_string_t mode;
313 };
314 
315 static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl,
316 				__attribute__((unused)) void *data)
317 {
318 	struct cmd_set_rxtx_result *res = parsed_result;
319 	if (test_set_rxtx_conf(res->mode) < 0)
320 		cmdline_printf(cl, "Cannot find such mode\n");
321 }
322 
323 cmdline_parse_token_string_t cmd_set_rxtx_set =
324 	TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set,
325 				 "set_rxtx_mode");
326 
327 cmdline_parse_token_string_t cmd_set_rxtx_mode =
328 	TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL);
329 
330 cmdline_parse_inst_t cmd_set_rxtx = {
331 	.f = cmd_set_rxtx_parsed,  /* function to call */
332 	.data = NULL,      /* 2nd arg of func */
333 	.help_str = "set rxtx routine: "
334 			"set_rxtx <mode>",
335 	.tokens = {        /* token list, NULL terminated */
336 		(void *)&cmd_set_rxtx_set,
337 		(void *)&cmd_set_rxtx_mode,
338 		NULL,
339 	},
340 };
341 
342 /****************/
343 
344 struct cmd_set_rxtx_anchor {
345 	cmdline_fixed_string_t set;
346 	cmdline_fixed_string_t type;
347 };
348 
349 static void
350 cmd_set_rxtx_anchor_parsed(void *parsed_result,
351 			   struct cmdline *cl,
352 			   __attribute__((unused)) void *data)
353 {
354 	struct cmd_set_rxtx_anchor *res = parsed_result;
355 	if (test_set_rxtx_anchor(res->type) < 0)
356 		cmdline_printf(cl, "Cannot find such anchor\n");
357 }
358 
359 cmdline_parse_token_string_t cmd_set_rxtx_anchor_set =
360 	TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, set,
361 				 "set_rxtx_anchor");
362 
363 cmdline_parse_token_string_t cmd_set_rxtx_anchor_type =
364 	TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, type, NULL);
365 
366 cmdline_parse_inst_t cmd_set_rxtx_anchor = {
367 	.f = cmd_set_rxtx_anchor_parsed,  /* function to call */
368 	.data = NULL,      /* 2nd arg of func */
369 	.help_str = "set rxtx anchor: "
370 			"set_rxtx_anchor <type>",
371 	.tokens = {        /* token list, NULL terminated */
372 		(void *)&cmd_set_rxtx_anchor_set,
373 		(void *)&cmd_set_rxtx_anchor_type,
374 		NULL,
375 	},
376 };
377 
378 /****************/
379 
380 /* for stream control */
381 struct cmd_set_rxtx_sc {
382 	cmdline_fixed_string_t set;
383 	cmdline_fixed_string_t type;
384 };
385 
386 static void
387 cmd_set_rxtx_sc_parsed(void *parsed_result,
388 			   struct cmdline *cl,
389 			   __attribute__((unused)) void *data)
390 {
391 	struct cmd_set_rxtx_sc *res = parsed_result;
392 	if (test_set_rxtx_sc(res->type) < 0)
393 		cmdline_printf(cl, "Cannot find such stream control\n");
394 }
395 
396 cmdline_parse_token_string_t cmd_set_rxtx_sc_set =
397 	TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set,
398 				 "set_rxtx_sc");
399 
400 cmdline_parse_token_string_t cmd_set_rxtx_sc_type =
401 	TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL);
402 
403 cmdline_parse_inst_t cmd_set_rxtx_sc = {
404 	.f = cmd_set_rxtx_sc_parsed,  /* function to call */
405 	.data = NULL,      /* 2nd arg of func */
406 	.help_str = "set rxtx stream control: "
407 			"set_rxtx_sc <type>",
408 	.tokens = {        /* token list, NULL terminated */
409 		(void *)&cmd_set_rxtx_sc_set,
410 		(void *)&cmd_set_rxtx_sc_type,
411 		NULL,
412 	},
413 };
414 
415 /****************/
416 
417 
418 cmdline_parse_ctx_t main_ctx[] = {
419 	(cmdline_parse_inst_t *)&cmd_autotest,
420 	(cmdline_parse_inst_t *)&cmd_dump,
421 	(cmdline_parse_inst_t *)&cmd_dump_one,
422 	(cmdline_parse_inst_t *)&cmd_set_ring,
423 	(cmdline_parse_inst_t *)&cmd_quit,
424 	(cmdline_parse_inst_t *)&cmd_set_rxtx,
425 	(cmdline_parse_inst_t *)&cmd_set_rxtx_anchor,
426 	(cmdline_parse_inst_t *)&cmd_set_rxtx_sc,
427 	NULL,
428 };
429 
430 int commands_init(void)
431 {
432 	struct test_command *t;
433 	char *commands, *ptr;
434 	int commands_len = 0;
435 
436 	TAILQ_FOREACH(t, &commands_list, next) {
437 		commands_len += strlen(t->command) + 1;
438 	}
439 
440 	commands = malloc(commands_len + 1);
441 	if (!commands)
442 		return -1;
443 
444 	ptr = commands;
445 	TAILQ_FOREACH(t, &commands_list, next) {
446 		ptr += sprintf(ptr, "%s#", t->command);
447 	}
448 	ptr--;
449 	ptr[0] = '\0';
450 
451 	cmd_autotest_autotest.string_data.str = commands;
452 	return 0;
453 }
454