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