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