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