1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Cavium, Inc 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <inttypes.h> 8 #include <getopt.h> 9 10 #include <rte_string_fns.h> 11 #include <rte_common.h> 12 #include <rte_eventdev.h> 13 #include <rte_lcore.h> 14 15 #include "evt_options.h" 16 #include "evt_test.h" 17 #include "parser.h" 18 19 void 20 evt_options_default(struct evt_options *opt) 21 { 22 memset(opt, 0, sizeof(*opt)); 23 opt->verbose_level = 1; /* Enable minimal prints */ 24 opt->dev_id = 0; 25 strncpy(opt->test_name, "order_queue", EVT_TEST_NAME_MAX_LEN); 26 opt->nb_flows = 1024; 27 opt->socket_id = SOCKET_ID_ANY; 28 opt->pool_sz = 16 * 1024; 29 opt->prod_enq_burst_sz = 1; 30 opt->wkr_deq_dep = 16; 31 opt->nb_pkts = (1ULL << 26); /* do ~64M packets */ 32 opt->nb_timers = 1E8; 33 opt->nb_timer_adptrs = 1; 34 opt->timer_tick_nsec = 1E3; /* 1000ns ~ 1us */ 35 opt->max_tmo_nsec = 1E5; /* 100000ns ~100us */ 36 opt->expiry_nsec = 1E4; /* 10000ns ~10us */ 37 opt->prod_type = EVT_PROD_TYPE_SYNT; 38 opt->eth_queues = 1; 39 opt->vector_size = 64; 40 opt->vector_tmo_nsec = 100E3; 41 } 42 43 typedef int (*option_parser_t)(struct evt_options *opt, 44 const char *arg); 45 46 struct long_opt_parser { 47 const char *lgopt_name; 48 option_parser_t parser_fn; 49 }; 50 51 static int 52 evt_parse_nb_flows(struct evt_options *opt, const char *arg) 53 { 54 int ret; 55 56 ret = parser_read_uint32(&(opt->nb_flows), arg); 57 58 return ret; 59 } 60 61 static int 62 evt_parse_dev_id(struct evt_options *opt, const char *arg) 63 { 64 int ret; 65 66 ret = parser_read_uint8(&(opt->dev_id), arg); 67 68 return ret; 69 } 70 71 static int 72 evt_parse_verbose(struct evt_options *opt, const char *arg __rte_unused) 73 { 74 opt->verbose_level = atoi(arg); 75 return 0; 76 } 77 78 static int 79 evt_parse_fwd_latency(struct evt_options *opt, const char *arg __rte_unused) 80 { 81 opt->fwd_latency = 1; 82 return 0; 83 } 84 85 static int 86 evt_parse_queue_priority(struct evt_options *opt, const char *arg __rte_unused) 87 { 88 opt->q_priority = 1; 89 return 0; 90 } 91 92 static int 93 evt_parse_deq_tmo_nsec(struct evt_options *opt, const char *arg) 94 { 95 int ret; 96 97 ret = parser_read_uint32(&(opt->deq_tmo_nsec), arg); 98 99 return ret; 100 } 101 102 static int 103 evt_parse_eth_prod_type(struct evt_options *opt, const char *arg __rte_unused) 104 { 105 opt->prod_type = EVT_PROD_TYPE_ETH_RX_ADPTR; 106 return 0; 107 } 108 109 static int 110 evt_parse_timer_prod_type(struct evt_options *opt, const char *arg __rte_unused) 111 { 112 opt->prod_type = EVT_PROD_TYPE_EVENT_TIMER_ADPTR; 113 return 0; 114 } 115 116 static int 117 evt_parse_timer_prod_type_burst(struct evt_options *opt, 118 const char *arg __rte_unused) 119 { 120 opt->prod_type = EVT_PROD_TYPE_EVENT_TIMER_ADPTR; 121 opt->timdev_use_burst = 1; 122 return 0; 123 } 124 125 static int 126 evt_parse_crypto_prod_type(struct evt_options *opt, 127 const char *arg __rte_unused) 128 { 129 opt->prod_type = EVT_PROD_TYPE_EVENT_CRYPTO_ADPTR; 130 return 0; 131 } 132 133 static int 134 evt_parse_crypto_adptr_mode(struct evt_options *opt, const char *arg) 135 { 136 uint8_t mode; 137 int ret; 138 139 ret = parser_read_uint8(&mode, arg); 140 opt->crypto_adptr_mode = mode ? RTE_EVENT_CRYPTO_ADAPTER_OP_FORWARD : 141 RTE_EVENT_CRYPTO_ADAPTER_OP_NEW; 142 return ret; 143 } 144 145 static int 146 evt_parse_test_name(struct evt_options *opt, const char *arg) 147 { 148 strlcpy(opt->test_name, arg, EVT_TEST_NAME_MAX_LEN); 149 return 0; 150 } 151 152 static int 153 evt_parse_socket_id(struct evt_options *opt, const char *arg) 154 { 155 opt->socket_id = atoi(arg); 156 return 0; 157 } 158 159 static int 160 evt_parse_wkr_deq_dep(struct evt_options *opt, const char *arg) 161 { 162 int ret; 163 164 ret = parser_read_uint16(&(opt->wkr_deq_dep), arg); 165 return ret; 166 } 167 168 static int 169 evt_parse_nb_pkts(struct evt_options *opt, const char *arg) 170 { 171 int ret; 172 173 ret = parser_read_uint64(&(opt->nb_pkts), arg); 174 175 return ret; 176 } 177 178 static int 179 evt_parse_nb_timers(struct evt_options *opt, const char *arg) 180 { 181 int ret; 182 183 ret = parser_read_uint64(&(opt->nb_timers), arg); 184 185 return ret; 186 } 187 188 static int 189 evt_parse_timer_tick_nsec(struct evt_options *opt, const char *arg) 190 { 191 int ret; 192 193 ret = parser_read_uint64(&(opt->timer_tick_nsec), arg); 194 195 return ret; 196 } 197 198 static int 199 evt_parse_max_tmo_nsec(struct evt_options *opt, const char *arg) 200 { 201 int ret; 202 203 ret = parser_read_uint64(&(opt->max_tmo_nsec), arg); 204 205 return ret; 206 } 207 208 static int 209 evt_parse_expiry_nsec(struct evt_options *opt, const char *arg) 210 { 211 int ret; 212 213 ret = parser_read_uint64(&(opt->expiry_nsec), arg); 214 215 return ret; 216 } 217 218 static int 219 evt_parse_nb_timer_adptrs(struct evt_options *opt, const char *arg) 220 { 221 int ret; 222 223 ret = parser_read_uint8(&(opt->nb_timer_adptrs), arg); 224 if (opt->nb_timer_adptrs <= 0) { 225 evt_err("Number of timer adapters cannot be <= 0"); 226 return -EINVAL; 227 } 228 229 return ret; 230 } 231 232 static int 233 evt_parse_pool_sz(struct evt_options *opt, const char *arg) 234 { 235 opt->pool_sz = atoi(arg); 236 237 return 0; 238 } 239 240 static int 241 evt_parse_plcores(struct evt_options *opt, const char *corelist) 242 { 243 int ret; 244 245 ret = parse_lcores_list(opt->plcores, RTE_MAX_LCORE, corelist); 246 if (ret == -E2BIG) 247 evt_err("duplicate lcores in plcores"); 248 249 return ret; 250 } 251 252 static int 253 evt_parse_work_lcores(struct evt_options *opt, const char *corelist) 254 { 255 int ret; 256 257 ret = parse_lcores_list(opt->wlcores, RTE_MAX_LCORE, corelist); 258 if (ret == -E2BIG) 259 evt_err("duplicate lcores in wlcores"); 260 261 return ret; 262 } 263 264 static int 265 evt_parse_mbuf_sz(struct evt_options *opt, const char *arg) 266 { 267 int ret; 268 269 ret = parser_read_uint16(&(opt->mbuf_sz), arg); 270 271 return ret; 272 } 273 274 static int 275 evt_parse_max_pkt_sz(struct evt_options *opt, const char *arg) 276 { 277 int ret; 278 279 ret = parser_read_uint32(&(opt->max_pkt_sz), arg); 280 281 return ret; 282 } 283 284 static int 285 evt_parse_ena_vector(struct evt_options *opt, const char *arg __rte_unused) 286 { 287 opt->ena_vector = 1; 288 return 0; 289 } 290 291 static int 292 evt_parse_vector_size(struct evt_options *opt, const char *arg) 293 { 294 int ret; 295 296 ret = parser_read_uint16(&(opt->vector_size), arg); 297 298 return ret; 299 } 300 301 static int 302 evt_parse_vector_tmo_ns(struct evt_options *opt, const char *arg) 303 { 304 int ret; 305 306 ret = parser_read_uint64(&(opt->vector_tmo_nsec), arg); 307 308 return ret; 309 } 310 311 static int 312 evt_parse_eth_queues(struct evt_options *opt, const char *arg) 313 { 314 int ret; 315 316 ret = parser_read_uint16(&(opt->eth_queues), arg); 317 318 return ret; 319 } 320 321 static int 322 evt_parse_per_port_pool(struct evt_options *opt, const char *arg __rte_unused) 323 { 324 opt->per_port_pool = 1; 325 return 0; 326 } 327 328 static int 329 evt_parse_prod_enq_burst_sz(struct evt_options *opt, const char *arg) 330 { 331 int ret; 332 333 ret = parser_read_uint32(&(opt->prod_enq_burst_sz), arg); 334 335 return ret; 336 } 337 338 static void 339 usage(char *program) 340 { 341 printf("usage : %s [EAL options] -- [application options]\n", program); 342 printf("application options:\n"); 343 printf("\t--verbose : verbose level\n" 344 "\t--dev : device id of the event device\n" 345 "\t--test : name of the test application to run\n" 346 "\t--socket_id : socket_id of application resources\n" 347 "\t--pool_sz : pool size of the mempool\n" 348 "\t--plcores : list of lcore ids for producers\n" 349 "\t--wlcores : list of lcore ids for workers\n" 350 "\t--stlist : list of scheduled types of the stages\n" 351 "\t--nb_flows : number of flows to produce\n" 352 "\t--nb_pkts : number of packets to produce\n" 353 "\t--worker_deq_depth : dequeue depth of the worker\n" 354 "\t--fwd_latency : perform fwd_latency measurement\n" 355 "\t--queue_priority : enable queue priority\n" 356 "\t--deq_tmo_nsec : global dequeue timeout\n" 357 "\t--prod_type_ethdev : use ethernet device as producer.\n" 358 "\t--prod_type_cryptodev : use crypto device as producer.\n" 359 "\t--prod_type_timerdev : use event timer device as producer.\n" 360 "\t expiry_nsec would be the timeout\n" 361 "\t in ns.\n" 362 "\t--prod_type_timerdev_burst : use timer device as producer\n" 363 "\t burst mode.\n" 364 "\t--nb_timers : number of timers to arm.\n" 365 "\t--nb_timer_adptrs : number of timer adapters to use.\n" 366 "\t--timer_tick_nsec : timer tick interval in ns.\n" 367 "\t--max_tmo_nsec : max timeout interval in ns.\n" 368 "\t--expiry_nsec : event timer expiry ns.\n" 369 "\t--crypto_adptr_mode : 0 for OP_NEW mode (default) and\n" 370 "\t 1 for OP_FORWARD mode.\n" 371 "\t--mbuf_sz : packet mbuf size.\n" 372 "\t--max_pkt_sz : max packet size.\n" 373 "\t--prod_enq_burst_sz : producer enqueue burst size.\n" 374 "\t--nb_eth_queues : number of ethernet Rx queues.\n" 375 "\t--enable_vector : enable event vectorization.\n" 376 "\t--vector_size : Max vector size.\n" 377 "\t--vector_tmo_ns : Max vector timeout in nanoseconds\n" 378 "\t--per_port_pool : Configure unique pool per ethdev port\n" 379 ); 380 printf("available tests:\n"); 381 evt_test_dump_names(); 382 } 383 384 static int 385 evt_parse_sched_type_list(struct evt_options *opt, const char *arg) 386 { 387 char c; 388 int i = 0, j = -1; 389 390 for (i = 0; i < EVT_MAX_STAGES; i++) 391 opt->sched_type_list[i] = (uint8_t)-1; 392 393 i = 0; 394 395 do { 396 c = arg[++j]; 397 398 switch (c) { 399 case 'o': 400 case 'O': 401 opt->sched_type_list[i++] = RTE_SCHED_TYPE_ORDERED; 402 break; 403 case 'a': 404 case 'A': 405 opt->sched_type_list[i++] = RTE_SCHED_TYPE_ATOMIC; 406 break; 407 case 'p': 408 case 'P': 409 opt->sched_type_list[i++] = RTE_SCHED_TYPE_PARALLEL; 410 break; 411 case ',': 412 break; 413 default: 414 if (c != '\0') { 415 evt_err("invalid sched_type %c", c); 416 return -EINVAL; 417 } 418 } 419 } while (c != '\0'); 420 421 opt->nb_stages = i; 422 return 0; 423 } 424 425 static struct option lgopts[] = { 426 { EVT_NB_FLOWS, 1, 0, 0 }, 427 { EVT_DEVICE, 1, 0, 0 }, 428 { EVT_VERBOSE, 1, 0, 0 }, 429 { EVT_TEST, 1, 0, 0 }, 430 { EVT_PROD_LCORES, 1, 0, 0 }, 431 { EVT_WORK_LCORES, 1, 0, 0 }, 432 { EVT_SOCKET_ID, 1, 0, 0 }, 433 { EVT_POOL_SZ, 1, 0, 0 }, 434 { EVT_NB_PKTS, 1, 0, 0 }, 435 { EVT_WKR_DEQ_DEP, 1, 0, 0 }, 436 { EVT_SCHED_TYPE_LIST, 1, 0, 0 }, 437 { EVT_FWD_LATENCY, 0, 0, 0 }, 438 { EVT_QUEUE_PRIORITY, 0, 0, 0 }, 439 { EVT_DEQ_TMO_NSEC, 1, 0, 0 }, 440 { EVT_PROD_ETHDEV, 0, 0, 0 }, 441 { EVT_PROD_CRYPTODEV, 0, 0, 0 }, 442 { EVT_PROD_TIMERDEV, 0, 0, 0 }, 443 { EVT_PROD_TIMERDEV_BURST, 0, 0, 0 }, 444 { EVT_CRYPTO_ADPTR_MODE, 1, 0, 0 }, 445 { EVT_NB_TIMERS, 1, 0, 0 }, 446 { EVT_NB_TIMER_ADPTRS, 1, 0, 0 }, 447 { EVT_TIMER_TICK_NSEC, 1, 0, 0 }, 448 { EVT_MAX_TMO_NSEC, 1, 0, 0 }, 449 { EVT_EXPIRY_NSEC, 1, 0, 0 }, 450 { EVT_MBUF_SZ, 1, 0, 0 }, 451 { EVT_MAX_PKT_SZ, 1, 0, 0 }, 452 { EVT_PROD_ENQ_BURST_SZ, 1, 0, 0 }, 453 { EVT_NB_ETH_QUEUES, 1, 0, 0 }, 454 { EVT_ENA_VECTOR, 0, 0, 0 }, 455 { EVT_VECTOR_SZ, 1, 0, 0 }, 456 { EVT_VECTOR_TMO, 1, 0, 0 }, 457 { EVT_PER_PORT_POOL, 0, 0, 0 }, 458 { EVT_HELP, 0, 0, 0 }, 459 { NULL, 0, 0, 0 } 460 }; 461 462 static int 463 evt_opts_parse_long(int opt_idx, struct evt_options *opt) 464 { 465 unsigned int i; 466 467 struct long_opt_parser parsermap[] = { 468 { EVT_NB_FLOWS, evt_parse_nb_flows}, 469 { EVT_DEVICE, evt_parse_dev_id}, 470 { EVT_VERBOSE, evt_parse_verbose}, 471 { EVT_TEST, evt_parse_test_name}, 472 { EVT_PROD_LCORES, evt_parse_plcores}, 473 { EVT_WORK_LCORES, evt_parse_work_lcores}, 474 { EVT_SOCKET_ID, evt_parse_socket_id}, 475 { EVT_POOL_SZ, evt_parse_pool_sz}, 476 { EVT_NB_PKTS, evt_parse_nb_pkts}, 477 { EVT_WKR_DEQ_DEP, evt_parse_wkr_deq_dep}, 478 { EVT_SCHED_TYPE_LIST, evt_parse_sched_type_list}, 479 { EVT_FWD_LATENCY, evt_parse_fwd_latency}, 480 { EVT_QUEUE_PRIORITY, evt_parse_queue_priority}, 481 { EVT_DEQ_TMO_NSEC, evt_parse_deq_tmo_nsec}, 482 { EVT_PROD_ETHDEV, evt_parse_eth_prod_type}, 483 { EVT_PROD_CRYPTODEV, evt_parse_crypto_prod_type}, 484 { EVT_PROD_TIMERDEV, evt_parse_timer_prod_type}, 485 { EVT_PROD_TIMERDEV_BURST, evt_parse_timer_prod_type_burst}, 486 { EVT_CRYPTO_ADPTR_MODE, evt_parse_crypto_adptr_mode}, 487 { EVT_NB_TIMERS, evt_parse_nb_timers}, 488 { EVT_NB_TIMER_ADPTRS, evt_parse_nb_timer_adptrs}, 489 { EVT_TIMER_TICK_NSEC, evt_parse_timer_tick_nsec}, 490 { EVT_MAX_TMO_NSEC, evt_parse_max_tmo_nsec}, 491 { EVT_EXPIRY_NSEC, evt_parse_expiry_nsec}, 492 { EVT_MBUF_SZ, evt_parse_mbuf_sz}, 493 { EVT_MAX_PKT_SZ, evt_parse_max_pkt_sz}, 494 { EVT_PROD_ENQ_BURST_SZ, evt_parse_prod_enq_burst_sz}, 495 { EVT_NB_ETH_QUEUES, evt_parse_eth_queues}, 496 { EVT_ENA_VECTOR, evt_parse_ena_vector}, 497 { EVT_VECTOR_SZ, evt_parse_vector_size}, 498 { EVT_VECTOR_TMO, evt_parse_vector_tmo_ns}, 499 { EVT_PER_PORT_POOL, evt_parse_per_port_pool}, 500 }; 501 502 for (i = 0; i < RTE_DIM(parsermap); i++) { 503 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name, 504 strlen(lgopts[opt_idx].name)) == 0) 505 return parsermap[i].parser_fn(opt, optarg); 506 } 507 508 return -EINVAL; 509 } 510 511 int 512 evt_options_parse(struct evt_options *opt, int argc, char **argv) 513 { 514 int opts, retval, opt_idx; 515 516 while ((opts = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) { 517 switch (opts) { 518 case 0: /* long options */ 519 if (!strcmp(lgopts[opt_idx].name, "help")) { 520 usage(argv[0]); 521 exit(EXIT_SUCCESS); 522 } 523 524 retval = evt_opts_parse_long(opt_idx, opt); 525 if (retval != 0) 526 return retval; 527 break; 528 default: 529 return -EINVAL; 530 } 531 } 532 return 0; 533 } 534 535 void 536 evt_options_dump(struct evt_options *opt) 537 { 538 int lcore_id; 539 struct rte_event_dev_info dev_info; 540 541 rte_event_dev_info_get(opt->dev_id, &dev_info); 542 evt_dump("driver", "%s", dev_info.driver_name); 543 evt_dump("test", "%s", opt->test_name); 544 evt_dump("dev", "%d", opt->dev_id); 545 evt_dump("verbose_level", "%d", opt->verbose_level); 546 evt_dump("socket_id", "%d", opt->socket_id); 547 evt_dump("pool_sz", "%d", opt->pool_sz); 548 evt_dump("main lcore", "%d", rte_get_main_lcore()); 549 evt_dump("nb_pkts", "%"PRIu64, opt->nb_pkts); 550 evt_dump("nb_timers", "%"PRIu64, opt->nb_timers); 551 evt_dump_begin("available lcores"); 552 RTE_LCORE_FOREACH(lcore_id) 553 printf("%d ", lcore_id); 554 evt_dump_end; 555 evt_dump_nb_flows(opt); 556 evt_dump_worker_dequeue_depth(opt); 557 } 558