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 } 389