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