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