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_eal.h> 60 #include <rte_per_lcore.h> 61 #include <rte_lcore.h> 62 #include <rte_atomic.h> 63 #include <rte_branch_prediction.h> 64 #include <rte_ring.h> 65 #include <rte_mempool.h> 66 #include <rte_mbuf.h> 67 #include <rte_devargs.h> 68 69 #include <cmdline_rdline.h> 70 #include <cmdline_parse.h> 71 #include <cmdline_parse_ipaddr.h> 72 #include <cmdline_parse_num.h> 73 #include <cmdline_parse_string.h> 74 #include <cmdline.h> 75 76 #include "test.h" 77 78 /****************/ 79 80 static struct test_commands_list commands_list = 81 TAILQ_HEAD_INITIALIZER(commands_list); 82 83 void 84 add_test_command(struct test_command *t) 85 { 86 TAILQ_INSERT_TAIL(&commands_list, t, next); 87 } 88 89 struct cmd_autotest_result { 90 cmdline_fixed_string_t autotest; 91 }; 92 93 static void cmd_autotest_parsed(void *parsed_result, 94 __attribute__((unused)) struct cmdline *cl, 95 __attribute__((unused)) void *data) 96 { 97 struct test_command *t; 98 struct cmd_autotest_result *res = parsed_result; 99 int ret = 0; 100 101 TAILQ_FOREACH(t, &commands_list, next) { 102 if (!strcmp(res->autotest, t->command)) 103 ret = t->callback(); 104 } 105 106 if (ret == 0) 107 printf("Test OK\n"); 108 else 109 printf("Test Failed\n"); 110 fflush(stdout); 111 } 112 113 cmdline_parse_token_string_t cmd_autotest_autotest = 114 TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest, 115 ""); 116 117 cmdline_parse_inst_t cmd_autotest = { 118 .f = cmd_autotest_parsed, /* function to call */ 119 .data = NULL, /* 2nd arg of func */ 120 .help_str = "launch autotest", 121 .tokens = { /* token list, NULL terminated */ 122 (void *)&cmd_autotest_autotest, 123 NULL, 124 }, 125 }; 126 127 /****************/ 128 129 struct cmd_dump_result { 130 cmdline_fixed_string_t dump; 131 }; 132 133 static void 134 dump_struct_sizes(void) 135 { 136 #define DUMP_SIZE(t) printf("sizeof(" #t ") = %u\n", (unsigned)sizeof(t)); 137 DUMP_SIZE(struct rte_mbuf); 138 DUMP_SIZE(struct rte_mempool); 139 DUMP_SIZE(struct rte_ring); 140 #undef DUMP_SIZE 141 } 142 143 static void cmd_dump_parsed(void *parsed_result, 144 __attribute__((unused)) struct cmdline *cl, 145 __attribute__((unused)) void *data) 146 { 147 struct cmd_dump_result *res = parsed_result; 148 149 if (!strcmp(res->dump, "dump_physmem")) 150 rte_dump_physmem_layout(stdout); 151 else if (!strcmp(res->dump, "dump_memzone")) 152 rte_memzone_dump(stdout); 153 else if (!strcmp(res->dump, "dump_log_history")) 154 rte_log_dump_history(stdout); 155 else if (!strcmp(res->dump, "dump_struct_sizes")) 156 dump_struct_sizes(); 157 else if (!strcmp(res->dump, "dump_ring")) 158 rte_ring_list_dump(stdout); 159 else if (!strcmp(res->dump, "dump_mempool")) 160 rte_mempool_list_dump(stdout); 161 else if (!strcmp(res->dump, "dump_devargs")) 162 rte_eal_devargs_dump(stdout); 163 } 164 165 cmdline_parse_token_string_t cmd_dump_dump = 166 TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, 167 "dump_physmem#dump_memzone#dump_log_history#" 168 "dump_struct_sizes#dump_ring#dump_mempool#" 169 "dump_devargs"); 170 171 cmdline_parse_inst_t cmd_dump = { 172 .f = cmd_dump_parsed, /* function to call */ 173 .data = NULL, /* 2nd arg of func */ 174 .help_str = "dump status", 175 .tokens = { /* token list, NULL terminated */ 176 (void *)&cmd_dump_dump, 177 NULL, 178 }, 179 }; 180 181 /****************/ 182 183 struct cmd_dump_one_result { 184 cmdline_fixed_string_t dump; 185 cmdline_fixed_string_t name; 186 }; 187 188 static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl, 189 __attribute__((unused)) void *data) 190 { 191 struct cmd_dump_one_result *res = parsed_result; 192 193 if (!strcmp(res->dump, "dump_ring")) { 194 struct rte_ring *r; 195 r = rte_ring_lookup(res->name); 196 if (r == NULL) { 197 cmdline_printf(cl, "Cannot find ring\n"); 198 return; 199 } 200 rte_ring_dump(stdout, r); 201 } 202 else if (!strcmp(res->dump, "dump_mempool")) { 203 struct rte_mempool *mp; 204 mp = rte_mempool_lookup(res->name); 205 if (mp == NULL) { 206 cmdline_printf(cl, "Cannot find mempool\n"); 207 return; 208 } 209 rte_mempool_dump(stdout, mp); 210 } 211 } 212 213 cmdline_parse_token_string_t cmd_dump_one_dump = 214 TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump, 215 "dump_ring#dump_mempool"); 216 217 cmdline_parse_token_string_t cmd_dump_one_name = 218 TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL); 219 220 cmdline_parse_inst_t cmd_dump_one = { 221 .f = cmd_dump_one_parsed, /* function to call */ 222 .data = NULL, /* 2nd arg of func */ 223 .help_str = "dump one ring/mempool: dump_ring|dump_mempool <name>", 224 .tokens = { /* token list, NULL terminated */ 225 (void *)&cmd_dump_one_dump, 226 (void *)&cmd_dump_one_name, 227 NULL, 228 }, 229 }; 230 231 /****************/ 232 233 struct cmd_set_ring_result { 234 cmdline_fixed_string_t set; 235 cmdline_fixed_string_t name; 236 uint32_t value; 237 }; 238 239 static void cmd_set_ring_parsed(void *parsed_result, struct cmdline *cl, 240 __attribute__((unused)) void *data) 241 { 242 struct cmd_set_ring_result *res = parsed_result; 243 struct rte_ring *r; 244 int ret; 245 246 r = rte_ring_lookup(res->name); 247 if (r == NULL) { 248 cmdline_printf(cl, "Cannot find ring\n"); 249 return; 250 } 251 252 if (!strcmp(res->set, "set_watermark")) { 253 ret = rte_ring_set_water_mark(r, res->value); 254 if (ret != 0) 255 cmdline_printf(cl, "Cannot set water mark\n"); 256 } 257 } 258 259 cmdline_parse_token_string_t cmd_set_ring_set = 260 TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, set, 261 "set_watermark"); 262 263 cmdline_parse_token_string_t cmd_set_ring_name = 264 TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, name, NULL); 265 266 cmdline_parse_token_num_t cmd_set_ring_value = 267 TOKEN_NUM_INITIALIZER(struct cmd_set_ring_result, value, UINT32); 268 269 cmdline_parse_inst_t cmd_set_ring = { 270 .f = cmd_set_ring_parsed, /* function to call */ 271 .data = NULL, /* 2nd arg of func */ 272 .help_str = "set watermark: " 273 "set_watermark <ring_name> <value>", 274 .tokens = { /* token list, NULL terminated */ 275 (void *)&cmd_set_ring_set, 276 (void *)&cmd_set_ring_name, 277 (void *)&cmd_set_ring_value, 278 NULL, 279 }, 280 }; 281 282 /****************/ 283 284 struct cmd_quit_result { 285 cmdline_fixed_string_t quit; 286 }; 287 288 static void 289 cmd_quit_parsed(__attribute__((unused)) void *parsed_result, 290 struct cmdline *cl, 291 __attribute__((unused)) void *data) 292 { 293 cmdline_quit(cl); 294 } 295 296 cmdline_parse_token_string_t cmd_quit_quit = 297 TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, 298 "quit"); 299 300 cmdline_parse_inst_t cmd_quit = { 301 .f = cmd_quit_parsed, /* function to call */ 302 .data = NULL, /* 2nd arg of func */ 303 .help_str = "exit application", 304 .tokens = { /* token list, NULL terminated */ 305 (void *)&cmd_quit_quit, 306 NULL, 307 }, 308 }; 309 310 /****************/ 311 312 struct cmd_set_rxtx_result { 313 cmdline_fixed_string_t set; 314 cmdline_fixed_string_t mode; 315 }; 316 317 static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl, 318 __attribute__((unused)) void *data) 319 { 320 struct cmd_set_rxtx_result *res = parsed_result; 321 if (test_set_rxtx_conf(res->mode) < 0) 322 cmdline_printf(cl, "Cannot find such mode\n"); 323 } 324 325 cmdline_parse_token_string_t cmd_set_rxtx_set = 326 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set, 327 "set_rxtx_mode"); 328 329 cmdline_parse_token_string_t cmd_set_rxtx_mode = 330 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL); 331 332 cmdline_parse_inst_t cmd_set_rxtx = { 333 .f = cmd_set_rxtx_parsed, /* function to call */ 334 .data = NULL, /* 2nd arg of func */ 335 .help_str = "set rxtx routine: " 336 "set_rxtx <mode>", 337 .tokens = { /* token list, NULL terminated */ 338 (void *)&cmd_set_rxtx_set, 339 (void *)&cmd_set_rxtx_mode, 340 NULL, 341 }, 342 }; 343 344 /****************/ 345 346 struct cmd_set_rxtx_anchor { 347 cmdline_fixed_string_t set; 348 cmdline_fixed_string_t type; 349 }; 350 351 static void 352 cmd_set_rxtx_anchor_parsed(void *parsed_result, 353 struct cmdline *cl, 354 __attribute__((unused)) void *data) 355 { 356 struct cmd_set_rxtx_anchor *res = parsed_result; 357 if (test_set_rxtx_anchor(res->type) < 0) 358 cmdline_printf(cl, "Cannot find such anchor\n"); 359 } 360 361 cmdline_parse_token_string_t cmd_set_rxtx_anchor_set = 362 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, set, 363 "set_rxtx_anchor"); 364 365 cmdline_parse_token_string_t cmd_set_rxtx_anchor_type = 366 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, type, NULL); 367 368 cmdline_parse_inst_t cmd_set_rxtx_anchor = { 369 .f = cmd_set_rxtx_anchor_parsed, /* function to call */ 370 .data = NULL, /* 2nd arg of func */ 371 .help_str = "set rxtx anchor: " 372 "set_rxtx_anchor <type>", 373 .tokens = { /* token list, NULL terminated */ 374 (void *)&cmd_set_rxtx_anchor_set, 375 (void *)&cmd_set_rxtx_anchor_type, 376 NULL, 377 }, 378 }; 379 380 /****************/ 381 382 /* for stream control */ 383 struct cmd_set_rxtx_sc { 384 cmdline_fixed_string_t set; 385 cmdline_fixed_string_t type; 386 }; 387 388 static void 389 cmd_set_rxtx_sc_parsed(void *parsed_result, 390 struct cmdline *cl, 391 __attribute__((unused)) void *data) 392 { 393 struct cmd_set_rxtx_sc *res = parsed_result; 394 if (test_set_rxtx_sc(res->type) < 0) 395 cmdline_printf(cl, "Cannot find such stream control\n"); 396 } 397 398 cmdline_parse_token_string_t cmd_set_rxtx_sc_set = 399 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set, 400 "set_rxtx_sc"); 401 402 cmdline_parse_token_string_t cmd_set_rxtx_sc_type = 403 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL); 404 405 cmdline_parse_inst_t cmd_set_rxtx_sc = { 406 .f = cmd_set_rxtx_sc_parsed, /* function to call */ 407 .data = NULL, /* 2nd arg of func */ 408 .help_str = "set rxtx stream control: " 409 "set_rxtx_sc <type>", 410 .tokens = { /* token list, NULL terminated */ 411 (void *)&cmd_set_rxtx_sc_set, 412 (void *)&cmd_set_rxtx_sc_type, 413 NULL, 414 }, 415 }; 416 417 /****************/ 418 419 420 cmdline_parse_ctx_t main_ctx[] = { 421 (cmdline_parse_inst_t *)&cmd_autotest, 422 (cmdline_parse_inst_t *)&cmd_dump, 423 (cmdline_parse_inst_t *)&cmd_dump_one, 424 (cmdline_parse_inst_t *)&cmd_set_ring, 425 (cmdline_parse_inst_t *)&cmd_quit, 426 (cmdline_parse_inst_t *)&cmd_set_rxtx, 427 (cmdline_parse_inst_t *)&cmd_set_rxtx_anchor, 428 (cmdline_parse_inst_t *)&cmd_set_rxtx_sc, 429 NULL, 430 }; 431 432 int commands_init(void) 433 { 434 struct test_command *t; 435 char *commands, *ptr; 436 int commands_len = 0; 437 438 TAILQ_FOREACH(t, &commands_list, next) { 439 commands_len += strlen(t->command) + 1; 440 } 441 442 commands = malloc(commands_len + 1); 443 if (!commands) 444 return -1; 445 446 ptr = commands; 447 TAILQ_FOREACH(t, &commands_list, next) { 448 ptr += sprintf(ptr, "%s#", t->command); 449 } 450 ptr--; 451 ptr[0] = '\0'; 452 453 cmd_autotest_autotest.string_data.str = commands; 454 return 0; 455 } 456