1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5 * Copyright(c) 2014 6WIND S.A. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <stdio.h> 36 #include <stdarg.h> 37 #include <stdint.h> 38 #include <string.h> 39 #include <stdlib.h> 40 #include <netinet/in.h> 41 #include <termios.h> 42 #ifndef __linux__ 43 #ifndef __FreeBSD__ 44 #include <net/socket.h> 45 #endif 46 #endif 47 #include <inttypes.h> 48 #include <errno.h> 49 #include <sys/queue.h> 50 51 #include <rte_common.h> 52 #include <rte_log.h> 53 #include <rte_debug.h> 54 #include <rte_memory.h> 55 #include <rte_memcpy.h> 56 #include <rte_memzone.h> 57 #include <rte_launch.h> 58 #include <rte_cycles.h> 59 #include <rte_tailq.h> 60 #include <rte_eal.h> 61 #include <rte_per_lcore.h> 62 #include <rte_lcore.h> 63 #include <rte_atomic.h> 64 #include <rte_branch_prediction.h> 65 #include <rte_ring.h> 66 #include <rte_mempool.h> 67 #include <rte_mbuf.h> 68 #include <rte_devargs.h> 69 70 #include <cmdline_rdline.h> 71 #include <cmdline_parse.h> 72 #include <cmdline_parse_ipaddr.h> 73 #include <cmdline_parse_num.h> 74 #include <cmdline_parse_string.h> 75 #include <cmdline.h> 76 77 #include "test.h" 78 79 /****************/ 80 81 static struct test_commands_list commands_list = 82 TAILQ_HEAD_INITIALIZER(commands_list); 83 84 void 85 add_test_command(struct test_command *t) 86 { 87 TAILQ_INSERT_TAIL(&commands_list, t, next); 88 } 89 90 struct cmd_autotest_result { 91 cmdline_fixed_string_t autotest; 92 }; 93 94 static void cmd_autotest_parsed(void *parsed_result, 95 __attribute__((unused)) struct cmdline *cl, 96 __attribute__((unused)) void *data) 97 { 98 struct test_command *t; 99 struct cmd_autotest_result *res = parsed_result; 100 int ret = 0; 101 102 TAILQ_FOREACH(t, &commands_list, next) { 103 if (!strcmp(res->autotest, t->command)) 104 ret = t->callback(); 105 } 106 107 if (ret == 0) 108 printf("Test OK\n"); 109 else 110 printf("Test Failed\n"); 111 fflush(stdout); 112 } 113 114 cmdline_parse_token_string_t cmd_autotest_autotest = 115 TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest, 116 ""); 117 118 cmdline_parse_inst_t cmd_autotest = { 119 .f = cmd_autotest_parsed, /* function to call */ 120 .data = NULL, /* 2nd arg of func */ 121 .help_str = "launch autotest", 122 .tokens = { /* token list, NULL terminated */ 123 (void *)&cmd_autotest_autotest, 124 NULL, 125 }, 126 }; 127 128 /****************/ 129 130 struct cmd_dump_result { 131 cmdline_fixed_string_t dump; 132 }; 133 134 static void 135 dump_struct_sizes(void) 136 { 137 #define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t)); 138 DUMP_SIZE(struct rte_mbuf); 139 DUMP_SIZE(struct rte_mempool); 140 DUMP_SIZE(struct rte_ring); 141 #undef DUMP_SIZE 142 } 143 144 static void cmd_dump_parsed(void *parsed_result, 145 __attribute__((unused)) struct cmdline *cl, 146 __attribute__((unused)) void *data) 147 { 148 struct cmd_dump_result *res = parsed_result; 149 150 if (!strcmp(res->dump, "dump_physmem")) 151 rte_dump_physmem_layout(stdout); 152 else if (!strcmp(res->dump, "dump_memzone")) 153 rte_memzone_dump(stdout); 154 else if (!strcmp(res->dump, "dump_log_history")) 155 rte_log_dump_history(stdout); 156 else if (!strcmp(res->dump, "dump_struct_sizes")) 157 dump_struct_sizes(); 158 else if (!strcmp(res->dump, "dump_ring")) 159 rte_ring_list_dump(stdout); 160 else if (!strcmp(res->dump, "dump_mempool")) 161 rte_mempool_list_dump(stdout); 162 else if (!strcmp(res->dump, "dump_devargs")) 163 rte_eal_devargs_dump(stdout); 164 } 165 166 cmdline_parse_token_string_t cmd_dump_dump = 167 TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, 168 "dump_physmem#dump_memzone#dump_log_history#" 169 "dump_struct_sizes#dump_ring#dump_mempool#" 170 "dump_devargs"); 171 172 cmdline_parse_inst_t cmd_dump = { 173 .f = cmd_dump_parsed, /* function to call */ 174 .data = NULL, /* 2nd arg of func */ 175 .help_str = "dump status", 176 .tokens = { /* token list, NULL terminated */ 177 (void *)&cmd_dump_dump, 178 NULL, 179 }, 180 }; 181 182 /****************/ 183 184 struct cmd_dump_one_result { 185 cmdline_fixed_string_t dump; 186 cmdline_fixed_string_t name; 187 }; 188 189 static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl, 190 __attribute__((unused)) void *data) 191 { 192 struct cmd_dump_one_result *res = parsed_result; 193 194 if (!strcmp(res->dump, "dump_ring")) { 195 struct rte_ring *r; 196 r = rte_ring_lookup(res->name); 197 if (r == NULL) { 198 cmdline_printf(cl, "Cannot find ring\n"); 199 return; 200 } 201 rte_ring_dump(stdout, r); 202 } 203 else if (!strcmp(res->dump, "dump_mempool")) { 204 struct rte_mempool *mp; 205 mp = rte_mempool_lookup(res->name); 206 if (mp == NULL) { 207 cmdline_printf(cl, "Cannot find mempool\n"); 208 return; 209 } 210 rte_mempool_dump(stdout, mp); 211 } 212 } 213 214 cmdline_parse_token_string_t cmd_dump_one_dump = 215 TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump, 216 "dump_ring#dump_mempool"); 217 218 cmdline_parse_token_string_t cmd_dump_one_name = 219 TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL); 220 221 cmdline_parse_inst_t cmd_dump_one = { 222 .f = cmd_dump_one_parsed, /* function to call */ 223 .data = NULL, /* 2nd arg of func */ 224 .help_str = "dump one ring/mempool: dump_ring|dump_mempool <name>", 225 .tokens = { /* token list, NULL terminated */ 226 (void *)&cmd_dump_one_dump, 227 (void *)&cmd_dump_one_name, 228 NULL, 229 }, 230 }; 231 232 /****************/ 233 234 struct cmd_set_ring_result { 235 cmdline_fixed_string_t set; 236 cmdline_fixed_string_t name; 237 uint32_t value; 238 }; 239 240 static void cmd_set_ring_parsed(void *parsed_result, struct cmdline *cl, 241 __attribute__((unused)) void *data) 242 { 243 struct cmd_set_ring_result *res = parsed_result; 244 struct rte_ring *r; 245 int ret; 246 247 r = rte_ring_lookup(res->name); 248 if (r == NULL) { 249 cmdline_printf(cl, "Cannot find ring\n"); 250 return; 251 } 252 253 if (!strcmp(res->set, "set_watermark")) { 254 ret = rte_ring_set_water_mark(r, res->value); 255 if (ret != 0) 256 cmdline_printf(cl, "Cannot set water mark\n"); 257 } 258 } 259 260 cmdline_parse_token_string_t cmd_set_ring_set = 261 TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, set, 262 "set_watermark"); 263 264 cmdline_parse_token_string_t cmd_set_ring_name = 265 TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, name, NULL); 266 267 cmdline_parse_token_num_t cmd_set_ring_value = 268 TOKEN_NUM_INITIALIZER(struct cmd_set_ring_result, value, UINT32); 269 270 cmdline_parse_inst_t cmd_set_ring = { 271 .f = cmd_set_ring_parsed, /* function to call */ 272 .data = NULL, /* 2nd arg of func */ 273 .help_str = "set watermark: " 274 "set_watermark <ring_name> <value>", 275 .tokens = { /* token list, NULL terminated */ 276 (void *)&cmd_set_ring_set, 277 (void *)&cmd_set_ring_name, 278 (void *)&cmd_set_ring_value, 279 NULL, 280 }, 281 }; 282 283 /****************/ 284 285 struct cmd_quit_result { 286 cmdline_fixed_string_t quit; 287 }; 288 289 static void 290 cmd_quit_parsed(__attribute__((unused)) void *parsed_result, 291 struct cmdline *cl, 292 __attribute__((unused)) void *data) 293 { 294 cmdline_quit(cl); 295 } 296 297 cmdline_parse_token_string_t cmd_quit_quit = 298 TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, 299 "quit"); 300 301 cmdline_parse_inst_t cmd_quit = { 302 .f = cmd_quit_parsed, /* function to call */ 303 .data = NULL, /* 2nd arg of func */ 304 .help_str = "exit application", 305 .tokens = { /* token list, NULL terminated */ 306 (void *)&cmd_quit_quit, 307 NULL, 308 }, 309 }; 310 311 /****************/ 312 313 struct cmd_set_rxtx_result { 314 cmdline_fixed_string_t set; 315 cmdline_fixed_string_t mode; 316 }; 317 318 static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl, 319 __attribute__((unused)) void *data) 320 { 321 struct cmd_set_rxtx_result *res = parsed_result; 322 if (test_set_rxtx_conf(res->mode) < 0) 323 cmdline_printf(cl, "Cannot find such mode\n"); 324 } 325 326 cmdline_parse_token_string_t cmd_set_rxtx_set = 327 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set, 328 "set_rxtx_mode"); 329 330 cmdline_parse_token_string_t cmd_set_rxtx_mode = 331 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL); 332 333 cmdline_parse_inst_t cmd_set_rxtx = { 334 .f = cmd_set_rxtx_parsed, /* function to call */ 335 .data = NULL, /* 2nd arg of func */ 336 .help_str = "set rxtx routine: " 337 "set_rxtx <mode>", 338 .tokens = { /* token list, NULL terminated */ 339 (void *)&cmd_set_rxtx_set, 340 (void *)&cmd_set_rxtx_mode, 341 NULL, 342 }, 343 }; 344 345 /****************/ 346 347 struct cmd_set_rxtx_anchor { 348 cmdline_fixed_string_t set; 349 cmdline_fixed_string_t type; 350 }; 351 352 static void 353 cmd_set_rxtx_anchor_parsed(void *parsed_result, 354 struct cmdline *cl, 355 __attribute__((unused)) void *data) 356 { 357 struct cmd_set_rxtx_anchor *res = parsed_result; 358 if (test_set_rxtx_anchor(res->type) < 0) 359 cmdline_printf(cl, "Cannot find such anchor\n"); 360 } 361 362 cmdline_parse_token_string_t cmd_set_rxtx_anchor_set = 363 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, set, 364 "set_rxtx_anchor"); 365 366 cmdline_parse_token_string_t cmd_set_rxtx_anchor_type = 367 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, type, NULL); 368 369 cmdline_parse_inst_t cmd_set_rxtx_anchor = { 370 .f = cmd_set_rxtx_anchor_parsed, /* function to call */ 371 .data = NULL, /* 2nd arg of func */ 372 .help_str = "set rxtx anchor: " 373 "set_rxtx_anchor <type>", 374 .tokens = { /* token list, NULL terminated */ 375 (void *)&cmd_set_rxtx_anchor_set, 376 (void *)&cmd_set_rxtx_anchor_type, 377 NULL, 378 }, 379 }; 380 381 /****************/ 382 383 /* for stream control */ 384 struct cmd_set_rxtx_sc { 385 cmdline_fixed_string_t set; 386 cmdline_fixed_string_t type; 387 }; 388 389 static void 390 cmd_set_rxtx_sc_parsed(void *parsed_result, 391 struct cmdline *cl, 392 __attribute__((unused)) void *data) 393 { 394 struct cmd_set_rxtx_sc *res = parsed_result; 395 if (test_set_rxtx_sc(res->type) < 0) 396 cmdline_printf(cl, "Cannot find such stream control\n"); 397 } 398 399 cmdline_parse_token_string_t cmd_set_rxtx_sc_set = 400 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set, 401 "set_rxtx_sc"); 402 403 cmdline_parse_token_string_t cmd_set_rxtx_sc_type = 404 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL); 405 406 cmdline_parse_inst_t cmd_set_rxtx_sc = { 407 .f = cmd_set_rxtx_sc_parsed, /* function to call */ 408 .data = NULL, /* 2nd arg of func */ 409 .help_str = "set rxtx stream control: " 410 "set_rxtx_sc <type>", 411 .tokens = { /* token list, NULL terminated */ 412 (void *)&cmd_set_rxtx_sc_set, 413 (void *)&cmd_set_rxtx_sc_type, 414 NULL, 415 }, 416 }; 417 418 /****************/ 419 420 421 cmdline_parse_ctx_t main_ctx[] = { 422 (cmdline_parse_inst_t *)&cmd_autotest, 423 (cmdline_parse_inst_t *)&cmd_dump, 424 (cmdline_parse_inst_t *)&cmd_dump_one, 425 (cmdline_parse_inst_t *)&cmd_set_ring, 426 (cmdline_parse_inst_t *)&cmd_quit, 427 (cmdline_parse_inst_t *)&cmd_set_rxtx, 428 (cmdline_parse_inst_t *)&cmd_set_rxtx_anchor, 429 (cmdline_parse_inst_t *)&cmd_set_rxtx_sc, 430 NULL, 431 }; 432 433 int commands_init(void) 434 { 435 struct test_command *t; 436 char *commands, *ptr; 437 int commands_len = 0; 438 439 TAILQ_FOREACH(t, &commands_list, next) { 440 commands_len += strlen(t->command) + 1; 441 } 442 443 commands = malloc(commands_len); 444 if (!commands) 445 return -1; 446 447 ptr = commands; 448 TAILQ_FOREACH(t, &commands_list, next) { 449 ptr += sprintf(ptr, "%s#", t->command); 450 } 451 ptr--; 452 ptr[0] = '\0'; 453 454 cmd_autotest_autotest.string_data.str = commands; 455 return 0; 456 } 457