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