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_struct_sizes")) 154 dump_struct_sizes(); 155 else if (!strcmp(res->dump, "dump_ring")) 156 rte_ring_list_dump(stdout); 157 else if (!strcmp(res->dump, "dump_mempool")) 158 rte_mempool_list_dump(stdout); 159 else if (!strcmp(res->dump, "dump_devargs")) 160 rte_eal_devargs_dump(stdout); 161 } 162 163 cmdline_parse_token_string_t cmd_dump_dump = 164 TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, 165 "dump_physmem#dump_memzone#" 166 "dump_struct_sizes#dump_ring#dump_mempool#" 167 "dump_devargs"); 168 169 cmdline_parse_inst_t cmd_dump = { 170 .f = cmd_dump_parsed, /* function to call */ 171 .data = NULL, /* 2nd arg of func */ 172 .help_str = "dump status", 173 .tokens = { /* token list, NULL terminated */ 174 (void *)&cmd_dump_dump, 175 NULL, 176 }, 177 }; 178 179 /****************/ 180 181 struct cmd_dump_one_result { 182 cmdline_fixed_string_t dump; 183 cmdline_fixed_string_t name; 184 }; 185 186 static void cmd_dump_one_parsed(void *parsed_result, struct cmdline *cl, 187 __attribute__((unused)) void *data) 188 { 189 struct cmd_dump_one_result *res = parsed_result; 190 191 if (!strcmp(res->dump, "dump_ring")) { 192 struct rte_ring *r; 193 r = rte_ring_lookup(res->name); 194 if (r == NULL) { 195 cmdline_printf(cl, "Cannot find ring\n"); 196 return; 197 } 198 rte_ring_dump(stdout, r); 199 } 200 else if (!strcmp(res->dump, "dump_mempool")) { 201 struct rte_mempool *mp; 202 mp = rte_mempool_lookup(res->name); 203 if (mp == NULL) { 204 cmdline_printf(cl, "Cannot find mempool\n"); 205 return; 206 } 207 rte_mempool_dump(stdout, mp); 208 } 209 } 210 211 cmdline_parse_token_string_t cmd_dump_one_dump = 212 TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, dump, 213 "dump_ring#dump_mempool"); 214 215 cmdline_parse_token_string_t cmd_dump_one_name = 216 TOKEN_STRING_INITIALIZER(struct cmd_dump_one_result, name, NULL); 217 218 cmdline_parse_inst_t cmd_dump_one = { 219 .f = cmd_dump_one_parsed, /* function to call */ 220 .data = NULL, /* 2nd arg of func */ 221 .help_str = "dump one ring/mempool: dump_ring|dump_mempool <name>", 222 .tokens = { /* token list, NULL terminated */ 223 (void *)&cmd_dump_one_dump, 224 (void *)&cmd_dump_one_name, 225 NULL, 226 }, 227 }; 228 229 /****************/ 230 231 struct cmd_set_ring_result { 232 cmdline_fixed_string_t set; 233 cmdline_fixed_string_t name; 234 uint32_t value; 235 }; 236 237 static void cmd_set_ring_parsed(void *parsed_result, struct cmdline *cl, 238 __attribute__((unused)) void *data) 239 { 240 struct cmd_set_ring_result *res = parsed_result; 241 struct rte_ring *r; 242 int ret; 243 244 r = rte_ring_lookup(res->name); 245 if (r == NULL) { 246 cmdline_printf(cl, "Cannot find ring\n"); 247 return; 248 } 249 250 if (!strcmp(res->set, "set_watermark")) { 251 ret = rte_ring_set_water_mark(r, res->value); 252 if (ret != 0) 253 cmdline_printf(cl, "Cannot set water mark\n"); 254 } 255 } 256 257 cmdline_parse_token_string_t cmd_set_ring_set = 258 TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, set, 259 "set_watermark"); 260 261 cmdline_parse_token_string_t cmd_set_ring_name = 262 TOKEN_STRING_INITIALIZER(struct cmd_set_ring_result, name, NULL); 263 264 cmdline_parse_token_num_t cmd_set_ring_value = 265 TOKEN_NUM_INITIALIZER(struct cmd_set_ring_result, value, UINT32); 266 267 cmdline_parse_inst_t cmd_set_ring = { 268 .f = cmd_set_ring_parsed, /* function to call */ 269 .data = NULL, /* 2nd arg of func */ 270 .help_str = "set watermark: " 271 "set_watermark <ring_name> <value>", 272 .tokens = { /* token list, NULL terminated */ 273 (void *)&cmd_set_ring_set, 274 (void *)&cmd_set_ring_name, 275 (void *)&cmd_set_ring_value, 276 NULL, 277 }, 278 }; 279 280 /****************/ 281 282 struct cmd_quit_result { 283 cmdline_fixed_string_t quit; 284 }; 285 286 static void 287 cmd_quit_parsed(__attribute__((unused)) void *parsed_result, 288 struct cmdline *cl, 289 __attribute__((unused)) void *data) 290 { 291 cmdline_quit(cl); 292 } 293 294 cmdline_parse_token_string_t cmd_quit_quit = 295 TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, 296 "quit"); 297 298 cmdline_parse_inst_t cmd_quit = { 299 .f = cmd_quit_parsed, /* function to call */ 300 .data = NULL, /* 2nd arg of func */ 301 .help_str = "exit application", 302 .tokens = { /* token list, NULL terminated */ 303 (void *)&cmd_quit_quit, 304 NULL, 305 }, 306 }; 307 308 /****************/ 309 310 struct cmd_set_rxtx_result { 311 cmdline_fixed_string_t set; 312 cmdline_fixed_string_t mode; 313 }; 314 315 static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl, 316 __attribute__((unused)) void *data) 317 { 318 struct cmd_set_rxtx_result *res = parsed_result; 319 if (test_set_rxtx_conf(res->mode) < 0) 320 cmdline_printf(cl, "Cannot find such mode\n"); 321 } 322 323 cmdline_parse_token_string_t cmd_set_rxtx_set = 324 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set, 325 "set_rxtx_mode"); 326 327 cmdline_parse_token_string_t cmd_set_rxtx_mode = 328 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL); 329 330 cmdline_parse_inst_t cmd_set_rxtx = { 331 .f = cmd_set_rxtx_parsed, /* function to call */ 332 .data = NULL, /* 2nd arg of func */ 333 .help_str = "set rxtx routine: " 334 "set_rxtx <mode>", 335 .tokens = { /* token list, NULL terminated */ 336 (void *)&cmd_set_rxtx_set, 337 (void *)&cmd_set_rxtx_mode, 338 NULL, 339 }, 340 }; 341 342 /****************/ 343 344 struct cmd_set_rxtx_anchor { 345 cmdline_fixed_string_t set; 346 cmdline_fixed_string_t type; 347 }; 348 349 static void 350 cmd_set_rxtx_anchor_parsed(void *parsed_result, 351 struct cmdline *cl, 352 __attribute__((unused)) void *data) 353 { 354 struct cmd_set_rxtx_anchor *res = parsed_result; 355 if (test_set_rxtx_anchor(res->type) < 0) 356 cmdline_printf(cl, "Cannot find such anchor\n"); 357 } 358 359 cmdline_parse_token_string_t cmd_set_rxtx_anchor_set = 360 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, set, 361 "set_rxtx_anchor"); 362 363 cmdline_parse_token_string_t cmd_set_rxtx_anchor_type = 364 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_anchor, type, NULL); 365 366 cmdline_parse_inst_t cmd_set_rxtx_anchor = { 367 .f = cmd_set_rxtx_anchor_parsed, /* function to call */ 368 .data = NULL, /* 2nd arg of func */ 369 .help_str = "set rxtx anchor: " 370 "set_rxtx_anchor <type>", 371 .tokens = { /* token list, NULL terminated */ 372 (void *)&cmd_set_rxtx_anchor_set, 373 (void *)&cmd_set_rxtx_anchor_type, 374 NULL, 375 }, 376 }; 377 378 /****************/ 379 380 /* for stream control */ 381 struct cmd_set_rxtx_sc { 382 cmdline_fixed_string_t set; 383 cmdline_fixed_string_t type; 384 }; 385 386 static void 387 cmd_set_rxtx_sc_parsed(void *parsed_result, 388 struct cmdline *cl, 389 __attribute__((unused)) void *data) 390 { 391 struct cmd_set_rxtx_sc *res = parsed_result; 392 if (test_set_rxtx_sc(res->type) < 0) 393 cmdline_printf(cl, "Cannot find such stream control\n"); 394 } 395 396 cmdline_parse_token_string_t cmd_set_rxtx_sc_set = 397 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set, 398 "set_rxtx_sc"); 399 400 cmdline_parse_token_string_t cmd_set_rxtx_sc_type = 401 TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL); 402 403 cmdline_parse_inst_t cmd_set_rxtx_sc = { 404 .f = cmd_set_rxtx_sc_parsed, /* function to call */ 405 .data = NULL, /* 2nd arg of func */ 406 .help_str = "set rxtx stream control: " 407 "set_rxtx_sc <type>", 408 .tokens = { /* token list, NULL terminated */ 409 (void *)&cmd_set_rxtx_sc_set, 410 (void *)&cmd_set_rxtx_sc_type, 411 NULL, 412 }, 413 }; 414 415 /****************/ 416 417 418 cmdline_parse_ctx_t main_ctx[] = { 419 (cmdline_parse_inst_t *)&cmd_autotest, 420 (cmdline_parse_inst_t *)&cmd_dump, 421 (cmdline_parse_inst_t *)&cmd_dump_one, 422 (cmdline_parse_inst_t *)&cmd_set_ring, 423 (cmdline_parse_inst_t *)&cmd_quit, 424 (cmdline_parse_inst_t *)&cmd_set_rxtx, 425 (cmdline_parse_inst_t *)&cmd_set_rxtx_anchor, 426 (cmdline_parse_inst_t *)&cmd_set_rxtx_sc, 427 NULL, 428 }; 429 430 int commands_init(void) 431 { 432 struct test_command *t; 433 char *commands, *ptr; 434 int commands_len = 0; 435 436 TAILQ_FOREACH(t, &commands_list, next) { 437 commands_len += strlen(t->command) + 1; 438 } 439 440 commands = malloc(commands_len + 1); 441 if (!commands) 442 return -1; 443 444 ptr = commands; 445 TAILQ_FOREACH(t, &commands_list, next) { 446 ptr += sprintf(ptr, "%s#", t->command); 447 } 448 ptr--; 449 ptr[0] = '\0'; 450 451 cmd_autotest_autotest.string_data.str = commands; 452 return 0; 453 } 454