34 #include <odp/helper/odph_api.h>
37 #define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1)
40 #define DEFAULT_NUM_PKT (16 * 1024)
43 #define POOL_PKT_LEN 1536
46 #define MAX_PKT_BURST 32
58 #define DEFAULT_VEC_SIZE MAX_PKT_BURST
61 #define DEFAULT_VEC_TMO ODP_TIME_MSEC_IN_NS
64 #define EXTRA_STR_LEN 32
67 typedef enum pktin_mode_t {
76 typedef enum pktout_mode_t {
81 static inline int sched_mode(pktin_mode_t in_mode)
83 return (in_mode == SCHED_PARALLEL) ||
84 (in_mode == SCHED_ATOMIC) ||
85 (in_mode == SCHED_ORDERED);
89 #define NO_PATH(file_name) (strrchr((file_name), '/') ? \
90 strrchr((file_name), '/') + 1 : (file_name))
125 unsigned int cpu_count;
130 odph_ethaddr_t addrs[MAX_PKTIOS];
131 pktin_mode_t in_mode;
132 pktout_mode_t out_mode;
163 uint32_t thr_compl_id;
164 uint32_t tot_compl_id;
167 char *output_map[MAX_PKTIOS];
182 uint64_t tx_c_misses;
191 uint8_t padding[ODP_CACHE_LINE_SIZE];
222 typedef struct thread_args_t {
251 odph_thread_t thread_tbl[MAX_WORKERS];
253 thread_args_t thread_args[MAX_WORKERS];
260 odph_ethaddr_t port_eth_addr[MAX_PKTIOS];
262 odph_ethaddr_t dst_eth_addr[MAX_PKTIOS];
264 int dst_port[MAX_PKTIOS];
279 } pktios[MAX_PKTIOS];
292 uint32_t vector_max_size;
298 static args_t *gbl_args;
302 if (gbl_args == NULL)
307 static int setup_sig_handler(
void)
309 struct sigaction action = { .sa_handler = sig_handler };
311 if (sigemptyset(&action.sa_mask) || sigaction(SIGINT, &action, NULL))
328 static inline int drop_err_pkts(
odp_packet_t pkt_tbl[],
unsigned num)
331 unsigned dropped = 0;
334 for (i = 0, j = 0; i < num; ++i) {
341 pkt_tbl[j - 1] = pkt;
348 static inline void prefetch_data(uint8_t prefetch,
odp_packet_t pkt_tbl[], uint32_t num)
353 for (uint32_t i = 0; i < num; i++)
364 static inline void fill_eth_addrs(
odp_packet_t pkt_tbl[],
365 unsigned num,
int dst_port)
371 if (!gbl_args->appl.dst_change && !gbl_args->appl.src_change)
374 for (i = 0; i < num; ++i) {
378 if (gbl_args->appl.src_change)
379 eth->src = gbl_args->port_eth_addr[dst_port];
381 if (gbl_args->appl.dst_change)
382 eth->dst = gbl_args->dst_eth_addr[dst_port];
395 while (sent < pkts) {
409 static inline void chksum_insert(
odp_packet_t *pkt_tbl,
int pkts)
414 for (i = 0; i < pkts; i++) {
421 static void print_packets(
odp_packet_t *pkt_tbl,
int num)
427 for (
int i = 0; i < num; i++) {
431 for (bit = 0, align = 1; bit < 32; bit++, align *= 2)
432 if (data_ptr & (0x1 << bit))
435 printf(
" Packet data: 0x%" PRIxPTR
"\n"
437 " Packet seg len: %u\n"
439 " Num segments: %i\n"
440 " Headroom size: %u\n"
441 " User area size: %u\n\n",
448 static inline void data_rd(
odp_packet_t *pkt_tbl,
int num, uint16_t rd_words, stats_t *stats)
453 uint32_t len, words, j;
456 for (i = 0; i < num; i++) {
462 if (rd_words * 8 > len)
465 for (j = 0; j < words; j++)
469 stats->s.dummy_sum += sum;
472 static inline int copy_packets(
odp_packet_t *pkt_tbl,
int pkts)
479 for (i = 0; i < pkts; i++) {
480 old_pkt = pkt_tbl[i];
484 pkt_tbl[i] = new_pkt;
497 static inline int process_extra_features(
const appl_args_t *appl_args,
odp_packet_t *pkt_tbl,
498 int pkts, stats_t *stats)
501 uint16_t rd_words = appl_args->data_rd;
503 if (appl_args->verbose_pkt)
504 print_packets(pkt_tbl, pkts);
507 data_rd(pkt_tbl, pkts, rd_words, stats);
509 if (appl_args->packet_copy) {
512 fails = copy_packets(pkt_tbl, pkts);
513 stats->s.copy_fails += fails;
516 if (appl_args->chksum)
517 chksum_insert(pkt_tbl, pkts);
519 if (appl_args->error_check) {
523 rx_drops = drop_err_pkts(pkt_tbl, pkts);
526 stats->s.rx_drops += rx_drops;
527 if (pkts == rx_drops)
537 static inline void handle_tx_event_compl(tx_compl_t *tx_c,
odp_packet_t pkts[],
int num,
538 int tx_idx, stats_t *stats)
541 int next_req = tx_c->next_req;
542 const int interval = tx_c->interval;
544 tx_c->opt.queue = gbl_args->pktios[tx_idx].compl_q;
546 while (next_req <= num) {
547 pkt = pkts[next_req - 1];
550 stats->s.tx_c_fails++;
556 next_req += interval;
559 tx_c->next_req = next_req - num;
562 static inline void handle_tx_poll_compl(tx_compl_t *tx_c,
odp_packet_t pkts[],
int num,
int tx_idx,
565 uint32_t num_act = tx_c->num_act, poll_head = tx_c->poll_head, free_head = tx_c->free_head;
566 const uint32_t max = tx_c->max, init = tx_c->init, max_act = tx_c->max_act;
567 odp_pktio_t pktio = gbl_args->pktios[tx_idx].pktio;
568 int next_req = tx_c->next_req;
570 const int interval = tx_c->interval;
572 while (num_act > 0) {
578 if (++poll_head > max)
582 while (next_req <= num) {
583 pkt = pkts[next_req - 1];
585 if (num_act == max_act) {
586 stats->s.tx_c_misses++;
592 tx_c->opt.compl_id = free_head;
595 stats->s.tx_c_fails++;
601 if (++free_head > max)
605 next_req += interval;
608 tx_c->free_head = free_head;
609 tx_c->poll_head = poll_head;
610 tx_c->num_act = num_act;
611 tx_c->next_req = next_req - num;
614 static inline void handle_tx_state(state_t *state,
odp_packet_t pkts[],
int num,
int tx_idx,
617 tx_compl_t *tx_c = &state->tx_compl;
620 handle_tx_event_compl(tx_c, pkts, num, tx_idx, stats);
622 handle_tx_poll_compl(tx_c, pkts, num, tx_idx, stats);
625 static inline void handle_state_failure(state_t *state,
odp_packet_t packet)
628 --state->tx_compl.num_act;
629 --state->tx_compl.free_head;
631 if (state->tx_compl.free_head == UINT32_MAX ||
632 state->tx_compl.free_head < state->tx_compl.init)
633 state->tx_compl.free_head = state->tx_compl.max;
647 unsigned int tx_drops;
652 handle_tx_state(state, pkt_tbl, pkts, tx_idx, stats);
655 sent = event_queue_send(tx_queue, pkt_tbl, pkts);
660 tx_drops = pkts - sent;
663 stats->s.tx_drops += tx_drops;
666 for (i = sent; i < pkts; i++) {
668 handle_state_failure(state, pkt);
673 stats->s.packets += pkts;
676 static int handle_rx_state(state_t *state,
odp_event_t evs[],
int num)
692 static int run_worker_sched_mode_vector(
void *arg)
696 int pktio, num_pktio;
701 thread_args_t *thr_args = arg;
702 stats_t *stats = &thr_args->stats;
703 const appl_args_t *appl_args = &gbl_args->appl;
704 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
705 int use_event_queue = gbl_args->appl.out_mode;
706 pktin_mode_t in_mode = gbl_args->appl.in_mode;
709 max_burst = gbl_args->appl.burst_rx;
715 for (i = 0; i < thr_args->num_grp_join; i++) {
717 ODPH_ERR(
"Join failed: %i\n", i);
722 num_pktio = thr_args->num_pktio;
724 if (num_pktio > MAX_PKTIOS) {
725 ODPH_ERR(
"Too many pktios %i\n", num_pktio);
729 for (pktio = 0; pktio < num_pktio; pktio++) {
730 tx_queue[pktio] = thr_args->pktio[pktio].tx_queue;
731 pktout[pktio] = thr_args->
pktio[pktio].pktout;
734 printf(
"[%02i] PKTIN_SCHED_%s_VECTOR, %s\n", thr,
735 (in_mode == SCHED_PARALLEL) ?
"PARALLEL" :
736 ((in_mode == SCHED_ATOMIC) ?
"ATOMIC" :
"ORDERED"),
737 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT");
751 for (i = 0; i < events; i++) {
755 int src_idx, dst_idx;
762 }
else if (
odp_event_type(ev_tbl[i]) == ODP_EVENT_PACKET_VECTOR) {
765 }
else if (state != NULL) {
766 pkts = handle_rx_state(state, ev_tbl, events);
772 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
774 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats);
784 ODPH_ASSERT(src_idx >= 0);
785 dst_idx = gbl_args->dst_port_from_idx[src_idx];
786 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
788 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue[dst_idx],
789 pktout[dst_idx], state, stats);
841 static int run_worker_sched_mode(
void *arg)
847 int pktio, num_pktio;
852 char extra_str[EXTRA_STR_LEN];
853 thread_args_t *thr_args = arg;
854 stats_t *stats = &thr_args->stats;
855 const appl_args_t *appl_args = &gbl_args->appl;
856 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
857 int use_event_queue = gbl_args->appl.out_mode;
858 pktin_mode_t in_mode = gbl_args->appl.in_mode;
861 max_burst = gbl_args->appl.burst_rx;
863 memset(extra_str, 0, EXTRA_STR_LEN);
868 for (i = 0; i < thr_args->num_grp_join; i++) {
870 ODPH_ERR(
"Join failed: %i\n", i);
874 if (gbl_args->appl.verbose) {
875 uint64_t tmp = (uint64_t)(uintptr_t)thr_args->group[i];
877 printf(
"[%02i] Joined group 0x%" PRIx64
"\n", thr, tmp);
881 if (thr_args->num_grp_join)
882 snprintf(extra_str, EXTRA_STR_LEN,
", joined %i groups", thr_args->num_grp_join);
883 else if (gbl_args->appl.num_groups == 0)
884 snprintf(extra_str, EXTRA_STR_LEN,
", GROUP_ALL");
885 else if (gbl_args->appl.num_groups)
886 snprintf(extra_str, EXTRA_STR_LEN,
", GROUP_WORKER");
888 num_pktio = thr_args->num_pktio;
890 if (num_pktio > MAX_PKTIOS) {
891 ODPH_ERR(
"Too many pktios %i\n", num_pktio);
895 for (pktio = 0; pktio < num_pktio; pktio++) {
896 tx_queue[pktio] = thr_args->pktio[pktio].tx_queue;
897 pktout[pktio] = thr_args->
pktio[pktio].pktout;
900 printf(
"[%02i] PKTIN_SCHED_%s, %s%s\n", thr,
901 (in_mode == SCHED_PARALLEL) ?
"PARALLEL" :
902 ((in_mode == SCHED_ATOMIC) ?
"ATOMIC" :
"ORDERED"),
903 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT", extra_str);
919 pkts = handle_rx_state(state, ev_tbl, pkts);
927 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
929 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats);
936 ODPH_ASSERT(src_idx >= 0);
937 dst_idx = gbl_args->dst_port_from_idx[src_idx];
938 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
940 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue[dst_idx],
941 pktout[dst_idx], state, stats);
988 static int run_worker_plain_queue_mode(
void *arg)
994 int dst_idx, num_pktio;
999 thread_args_t *thr_args = arg;
1000 stats_t *stats = &thr_args->stats;
1001 const appl_args_t *appl_args = &gbl_args->appl;
1002 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
1003 int use_event_queue = gbl_args->appl.out_mode;
1007 max_burst = gbl_args->appl.burst_rx;
1009 num_pktio = thr_args->num_pktio;
1010 dst_idx = thr_args->pktio[pktio].tx_idx;
1011 queue = thr_args->pktio[pktio].rx_queue;
1012 pktout = thr_args->
pktio[pktio].pktout;
1013 tx_queue = thr_args->pktio[pktio].tx_queue;
1015 printf(
"[%02i] num pktios %i, PKTIN_QUEUE, %s\n", thr, num_pktio,
1016 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT");
1024 if (num_pktio > 1) {
1025 dst_idx = thr_args->pktio[pktio].tx_idx;
1026 queue = thr_args->pktio[pktio].rx_queue;
1027 pktout = thr_args->
pktio[pktio].pktout;
1029 tx_queue = thr_args->pktio[pktio].tx_queue;
1032 if (pktio == num_pktio)
1042 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
1044 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats);
1049 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
1051 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue, pktout, state,
1062 for (i = 0; i < num_pktio; i++) {
1066 queue = thr_args->pktio[i].rx_queue;
1087 static int run_worker_direct_mode(
void *arg)
1093 int dst_idx, num_pktio;
1098 thread_args_t *thr_args = arg;
1099 stats_t *stats = &thr_args->stats;
1100 const appl_args_t *appl_args = &gbl_args->appl;
1101 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
1102 int use_event_queue = gbl_args->appl.out_mode;
1105 max_burst = gbl_args->appl.burst_rx;
1107 num_pktio = thr_args->num_pktio;
1108 dst_idx = thr_args->pktio[pktio].tx_idx;
1109 pktin = thr_args->
pktio[pktio].pktin;
1110 pktout = thr_args->
pktio[pktio].pktout;
1111 tx_queue = thr_args->pktio[pktio].tx_queue;
1113 printf(
"[%02i] num pktios %i, PKTIN_DIRECT, %s\n", thr, num_pktio,
1114 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT");
1120 if (num_pktio > 1) {
1121 dst_idx = thr_args->pktio[pktio].tx_idx;
1122 pktin = thr_args->
pktio[pktio].pktin;
1123 pktout = thr_args->
pktio[pktio].pktout;
1125 tx_queue = thr_args->pktio[pktio].tx_queue;
1128 if (pktio == num_pktio)
1136 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
1138 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats);
1143 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
1145 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue, pktout, state,
1158 uint64_t vec_tmo_ns;
1164 if (gbl_args->appl.vec_size == 0)
1165 vec_size = DEFAULT_VEC_SIZE;
1167 vec_size = gbl_args->appl.vec_size;
1171 if (gbl_args->appl.vec_size == 0) {
1174 printf(
"\nWarning: Modified vector size to %u\n\n", vec_size);
1176 ODPH_ERR(
"Invalid pktio vector size %u, valid range [%u, %u]\n",
1183 if (gbl_args->appl.vec_tmo_ns == 0)
1184 vec_tmo_ns = DEFAULT_VEC_TMO;
1186 vec_tmo_ns = gbl_args->appl.vec_tmo_ns;
1190 if (gbl_args->appl.vec_tmo_ns == 0) {
1193 printf(
"\nWarning: Modified vector timeout to %" PRIu64
"\n\n", vec_tmo_ns);
1195 ODPH_ERR(
"Invalid vector timeout %" PRIu64
", valid range [%" PRIu64
1196 ", %" PRIu64
"]\n", vec_tmo_ns,
1215 static int create_pktio(
const char *dev,
int idx,
int num_rx,
int num_tx,
odp_pool_t pool,
1228 pktin_mode_t in_mode = gbl_args->appl.in_mode;
1234 if (in_mode == PLAIN_QUEUE)
1236 else if (in_mode != DIRECT_RECV)
1239 if (gbl_args->appl.out_mode != PKTOUT_DIRECT)
1250 ODPH_ERR(
"Pktio open failed: %s\n", dev);
1255 ODPH_ERR(
"Pktio info failed: %s\n", dev);
1260 ODPH_ERR(
"Pktio capability query failed: %s\n", dev);
1266 if (gbl_args->appl.input_ts) {
1268 ODPH_ERR(
"Packet input timestamping not supported: %s\n", dev);
1275 if (gbl_args->appl.error_check || gbl_args->appl.chksum)
1278 if (gbl_args->appl.chksum) {
1287 ODPH_ERR(
"Transmit event completion not supported: %s\n", dev);
1294 ODPH_ERR(
"Transmit poll completion not supported: %s\n", dev);
1310 if (gbl_args->appl.pause_rx) {
1312 ODPH_ERR(
"Reception of pause frames not supported: %s\n", dev);
1318 if (gbl_args->appl.pause_tx) {
1320 ODPH_ERR(
"Transmission of pause frames not supported: %s\n", dev);
1330 ODPH_ERR(
"Promisc mode set not supported: %s\n", dev);
1336 ODPH_ERR(
"Promisc mode enable failed: %s\n", dev);
1341 if (gbl_args->appl.mtu) {
1342 uint32_t maxlen_input = pktio_capa.
maxlen.
max_input ? gbl_args->appl.mtu : 0;
1343 uint32_t maxlen_output = pktio_capa.
maxlen.
max_output ? gbl_args->appl.mtu : 0;
1346 ODPH_ERR(
"Modifying interface MTU not supported: %s\n", dev);
1353 ODPH_ERR(
"Unsupported MTU value %" PRIu32
" for %s "
1354 "(min %" PRIu32
", max %" PRIu32
")\n", maxlen_input, dev,
1358 if (maxlen_output &&
1361 ODPH_ERR(
"Unsupported MTU value %" PRIu32
" for %s "
1362 "(min %" PRIu32
", max %" PRIu32
")\n", maxlen_output, dev,
1368 ODPH_ERR(
"Setting MTU failed: %s\n", dev);
1381 if (gbl_args->appl.sched_mode) {
1384 if (gbl_args->appl.num_prio) {
1385 prio = gbl_args->appl.prio[idx];
1388 gbl_args->appl.prio[idx] = prio;
1391 if (gbl_args->appl.in_mode == SCHED_ATOMIC)
1393 else if (gbl_args->appl.in_mode == SCHED_ORDERED)
1411 ODPH_ERR(
"Creating completion queue failed: %s\n", dev);
1420 printf(
"Warning: %s: maximum number of input queues: %i\n", dev, num_rx);
1423 if (num_rx < gbl_args->appl.num_workers)
1424 printf(
"Warning: %s: sharing %i input queues between %i workers\n",
1425 dev, num_rx, gbl_args->appl.num_workers);
1428 printf(
"Warning: %s: sharing %i output queues between %i workers\n",
1434 pktin_param.
hash_enable = (num_rx > 1 || gbl_args->appl.flow_aware) ? 1 : 0;
1437 pktin_param.
op_mode = mode_rx;
1439 pktout_param.
op_mode = mode_tx;
1442 if (gbl_args->appl.vector_mode) {
1444 ODPH_ERR(
"Packet vector input not supported: %s\n", dev);
1447 if (set_pktin_vector_params(&pktin_param, vec_pool, pktio_capa))
1452 ODPH_ERR(
"Input queue config failed: %s\n", dev);
1457 ODPH_ERR(
"Output queue config failed: %s\n", dev);
1462 if (gbl_args->appl.in_mode == DIRECT_RECV) {
1465 ODPH_ERR(
"Pktin queue query failed: %s\n", dev);
1471 ODPH_ERR(
"Pktin event queue query failed: %s\n", dev);
1478 if (gbl_args->appl.out_mode == PKTOUT_DIRECT) {
1481 ODPH_ERR(
"Pktout queue query failed: %s\n", dev);
1487 ODPH_ERR(
"Event queue query failed: %s\n", dev);
1494 ODPH_ETHADDR_LEN) != ODPH_ETHADDR_LEN) {
1495 ODPH_ERR(
"Reading interface Ethernet address failed: %s\n", dev);
1498 addr = gbl_args->port_eth_addr[idx].addr;
1500 printf(
" dev: %s, drv: %s, rx_queues: %i, tx_queues: %i, mac: "
1501 "%02x:%02x:%02x:%02x:%02x:%02x\n", dev, info.
drv_name, num_rx, num_tx,
1502 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
1504 if (gbl_args->appl.verbose)
1507 gbl_args->pktios[idx].num_rx_queue = num_rx;
1508 gbl_args->pktios[idx].num_tx_queue = num_tx;
1509 gbl_args->pktios[idx].pktio = pktio;
1522 static int print_speed_stats(
int num_workers, stats_t **thr_stats,
1523 int duration,
int timeout)
1526 uint64_t pkts_prev = 0;
1528 uint64_t rx_drops, tx_drops, tx_c_misses, tx_c_fails, copy_fails;
1529 uint64_t maximum_pps = 0;
1532 int stats_enabled = 1;
1533 int loop_forever = (duration == 0);
1552 for (i = 0; i < num_workers; i++) {
1553 pkts += thr_stats[i]->s.packets;
1554 rx_drops += thr_stats[i]->s.rx_drops;
1555 tx_drops += thr_stats[i]->s.tx_drops;
1556 tx_c_misses += thr_stats[i]->s.tx_c_misses;
1557 tx_c_fails += thr_stats[i]->s.tx_c_fails;
1558 copy_fails += thr_stats[i]->s.copy_fails;
1560 if (stats_enabled) {
1561 pps = (pkts - pkts_prev) / timeout;
1562 if (pps > maximum_pps)
1564 printf(
"%" PRIu64
" pps, %" PRIu64
" max pps, ", pps,
1567 if (gbl_args->appl.packet_copy)
1568 printf(
"%" PRIu64
" copy fails, ", copy_fails);
1571 printf(
"%" PRIu64
" tx compl misses, %" PRIu64
" tx compl fails, ",
1572 tx_c_misses, tx_c_fails);
1574 printf(
"%" PRIu64
" rx drops, %" PRIu64
" tx drops\n",
1575 rx_drops, tx_drops);
1581 (elapsed < duration)));
1584 printf(
"TEST RESULT: %" PRIu64
" maximum packets per second.\n",
1587 return pkts > 100 ? 0 : -1;
1590 static void print_port_mapping(
void)
1595 if_count = gbl_args->appl.if_count;
1597 printf(
"\nPort config\n--------------------\n");
1599 for (pktio = 0; pktio < if_count; pktio++) {
1600 const char *dev = gbl_args->appl.if_names[pktio];
1602 printf(
"Port %i (%s)\n", pktio, dev);
1603 printf(
" rx workers %i\n",
1604 gbl_args->pktios[pktio].num_rx_thr);
1605 printf(
" tx workers %i\n",
1606 gbl_args->pktios[pktio].num_tx_thr);
1607 printf(
" rx queues %i\n",
1608 gbl_args->pktios[pktio].num_rx_queue);
1609 printf(
" tx queues %i\n",
1610 gbl_args->pktios[pktio].num_tx_queue);
1621 static int find_dest_port(
int port)
1623 const char *output = gbl_args->appl.output_map[port];
1627 for (
int i = 0; i < gbl_args->appl.if_count; i++)
1628 if (strcmp(output, gbl_args->appl.if_names[i]) == 0)
1632 if (gbl_args->appl.if_count % 2 == 0)
1633 return (port % 2 == 0) ? port + 1 : port - 1;
1636 if (port == gbl_args->appl.if_count - 1)
1656 static void bind_workers(
void)
1658 int if_count, num_workers;
1659 int rx_idx, tx_idx, thr, pktio, i;
1660 thread_args_t *thr_args;
1662 if_count = gbl_args->appl.if_count;
1663 num_workers = gbl_args->appl.num_workers;
1665 if (gbl_args->appl.sched_mode) {
1667 for (i = 0; i < if_count; i++) {
1668 gbl_args->pktios[i].num_rx_thr = num_workers;
1669 gbl_args->pktios[i].num_tx_thr = num_workers;
1672 for (thr = 0; thr < num_workers; thr++) {
1673 thr_args = &gbl_args->thread_args[thr];
1674 thr_args->num_pktio = if_count;
1678 for (i = 0; i < if_count; i++) {
1679 thr_args->pktio[i].rx_idx = i;
1680 thr_args->pktio[i].tx_idx = i;
1685 for (rx_idx = 0; rx_idx < if_count; rx_idx++)
1686 gbl_args->dst_port[rx_idx] = find_dest_port(rx_idx);
1688 if (if_count > num_workers) {
1693 for (rx_idx = 0; rx_idx < if_count; rx_idx++) {
1694 thr_args = &gbl_args->thread_args[thr];
1695 pktio = thr_args->num_pktio;
1697 tx_idx = gbl_args->dst_port[rx_idx];
1698 thr_args->pktio[pktio].rx_idx = rx_idx;
1699 thr_args->pktio[pktio].tx_idx = tx_idx;
1700 thr_args->num_pktio++;
1702 gbl_args->pktios[rx_idx].num_rx_thr++;
1703 gbl_args->pktios[tx_idx].num_tx_thr++;
1706 if (thr >= num_workers)
1714 for (thr = 0; thr < num_workers; thr++) {
1715 thr_args = &gbl_args->thread_args[thr];
1716 pktio = thr_args->num_pktio;
1718 tx_idx = gbl_args->dst_port[rx_idx];
1719 thr_args->pktio[pktio].rx_idx = rx_idx;
1720 thr_args->pktio[pktio].tx_idx = tx_idx;
1721 thr_args->num_pktio++;
1723 gbl_args->pktios[rx_idx].num_rx_thr++;
1724 gbl_args->pktios[tx_idx].num_tx_thr++;
1727 if (rx_idx >= if_count)
1737 static void bind_queues(
void)
1742 num_workers = gbl_args->appl.num_workers;
1744 printf(
"\nQueue binding (indexes)\n-----------------------\n");
1746 for (thr = 0; thr < num_workers; thr++) {
1748 thread_args_t *thr_args = &gbl_args->thread_args[thr];
1749 int num = thr_args->num_pktio;
1751 printf(
"worker %i\n", thr);
1753 for (i = 0; i < num; i++) {
1754 int rx_queue, tx_queue;
1756 rx_idx = thr_args->pktio[i].rx_idx;
1757 tx_idx = thr_args->pktio[i].tx_idx;
1758 rx_queue = gbl_args->pktios[rx_idx].next_rx_queue;
1759 tx_queue = gbl_args->pktios[tx_idx].next_tx_queue;
1761 thr_args->pktio[i].rx_queue_idx = rx_queue;
1762 thr_args->pktio[i].tx_queue_idx = tx_queue;
1763 thr_args->pktio[i].pktin =
1764 gbl_args->pktios[rx_idx].pktin[rx_queue];
1765 thr_args->pktio[i].rx_queue =
1766 gbl_args->pktios[rx_idx].rx_q[rx_queue];
1767 thr_args->pktio[i].pktout =
1768 gbl_args->pktios[tx_idx].pktout[tx_queue];
1769 thr_args->pktio[i].tx_queue =
1770 gbl_args->pktios[tx_idx].tx_q[tx_queue];
1772 if (!gbl_args->appl.sched_mode)
1773 printf(
" rx: pktio %i, queue %i\n",
1776 printf(
" tx: pktio %i, queue %i\n",
1782 if (rx_queue >= gbl_args->pktios[rx_idx].num_rx_queue)
1784 if (tx_queue >= gbl_args->pktios[tx_idx].num_tx_queue)
1787 gbl_args->pktios[rx_idx].next_rx_queue = rx_queue;
1788 gbl_args->pktios[tx_idx].next_tx_queue = tx_queue;
1795 static void init_state(
const appl_args_t *args, state_t *state,
int thr_idx)
1797 const uint32_t cnt = args->tx_compl.thr_compl_id + 1;
1799 state->tx_compl.opt.mode = args->tx_compl.mode;
1800 state->tx_compl.init = thr_idx * cnt;
1801 state->tx_compl.max = state->tx_compl.init + cnt - 1;
1802 state->tx_compl.free_head = state->tx_compl.init;
1803 state->tx_compl.poll_head = state->tx_compl.init;
1804 state->tx_compl.num_act = 0;
1805 state->tx_compl.max_act = state->tx_compl.max - state->tx_compl.init + 1;
1806 state->tx_compl.interval = args->tx_compl.nth;
1807 state->tx_compl.next_req = state->tx_compl.interval;
1810 static void init_port_lookup_tbl(
void)
1812 int rx_idx, if_count;
1814 if_count = gbl_args->appl.if_count;
1816 for (rx_idx = 0; rx_idx < if_count; rx_idx++) {
1817 odp_pktio_t pktio = gbl_args->pktios[rx_idx].pktio;
1819 int dst_port = find_dest_port(rx_idx);
1821 if (pktio_idx < 0) {
1822 ODPH_ERR(
"Reading pktio (%s) index failed: %i\n",
1823 gbl_args->appl.if_names[rx_idx], pktio_idx);
1828 gbl_args->dst_port_from_idx[pktio_idx] = dst_port;
1835 static void usage(
char *progname)
1838 "OpenDataPlane L2 forwarding application.\n"
1840 "Usage: %s [options]\n"
1842 " E.g. %s -i eth0,eth1,eth2,eth3 -m 0 -t 1\n"
1843 " In the above example,\n"
1844 " eth0 will send pkts to eth1 and vice versa\n"
1845 " eth2 will send pkts to eth3 and vice versa\n"
1847 "Mandatory OPTIONS:\n"
1848 " -i, --interface <name> Eth interfaces (comma-separated, no spaces)\n"
1849 " Interface count min 1, max %i\n"
1851 "Optional OPTIONS:\n"
1852 " -m, --mode <arg> Packet input mode\n"
1853 " 0: Direct mode: PKTIN_MODE_DIRECT (default)\n"
1854 " 1: Scheduler mode with parallel queues:\n"
1855 " PKTIN_MODE_SCHED + SCHED_SYNC_PARALLEL\n"
1856 " 2: Scheduler mode with atomic queues:\n"
1857 " PKTIN_MODE_SCHED + SCHED_SYNC_ATOMIC\n"
1858 " 3: Scheduler mode with ordered queues:\n"
1859 " PKTIN_MODE_SCHED + SCHED_SYNC_ORDERED\n"
1860 " 4: Plain queue mode: PKTIN_MODE_QUEUE\n"
1861 " -o, --out_mode <arg> Packet output mode\n"
1862 " 0: Direct mode: PKTOUT_MODE_DIRECT (default)\n"
1863 " 1: Queue mode: PKTOUT_MODE_QUEUE\n"
1864 " -O, --output_map <list> List of destination ports for passed interfaces\n"
1865 " (comma-separated, no spaces). Ordering follows\n"
1866 " the '--interface' option, e.g. passing\n"
1867 " '-i eth0,eth1' and '-O eth0,eth1' would result\n"
1868 " in eth0 and eth1 looping packets back.\n"
1869 " -c, --count <num> CPU count, 0=all available, default=1\n"
1870 " -t, --time <sec> Time in seconds to run.\n"
1871 " -a, --accuracy <sec> Time in seconds get print statistics\n"
1872 " (default is 1 second).\n"
1873 " -d, --dst_change <arg> 0: Don't change packets' dst eth addresses\n"
1874 " 1: Change packets' dst eth addresses (default)\n"
1875 " -s, --src_change <arg> 0: Don't change packets' src eth addresses\n"
1876 " 1: Change packets' src eth addresses (default)\n"
1877 " -r, --dst_addr <addr> Destination addresses (comma-separated, no\n"
1878 " spaces) Requires also the -d flag to be set\n"
1879 " -e, --error_check <arg> 0: Don't check packet errors (default)\n"
1880 " 1: Check packet errors\n"
1881 " -k, --chksum <arg> 0: Don't use checksum offload (default)\n"
1882 " 1: Use checksum offload\n",
1883 NO_PATH(progname), NO_PATH(progname), MAX_PKTIOS);
1885 printf(
" -g, --groups <num> Number of new groups to create (1 ... num).\n"
1886 " Interfaces are placed into the groups in round\n"
1888 " 0: Use SCHED_GROUP_ALL (default)\n"
1889 " -1: Use SCHED_GROUP_WORKER\n"
1890 " -G, --group_mode <arg> Select how threads join new groups\n"
1892 " 0: All threads join all created groups\n"
1894 " 1: All threads join first N created groups.\n"
1895 " N is number of interfaces (== active\n"
1897 " 2: Each thread joins a part of the first N\n"
1898 " groups (in round robin).\n"
1899 " -I, --prio <prio list> Schedule priority of packet input queues.\n"
1900 " Comma separated list of priorities (no spaces).\n"
1901 " A value per interface. All queues of an\n"
1902 " interface have the same priority. Values must\n"
1903 " be between odp_schedule_min_prio and\n"
1904 " odp_schedule_max_prio.\n"
1905 " odp_schedule_default_prio is used by default.\n"
1906 " -b, --burst_rx <num> 0: Use max burst size (default)\n"
1907 " num: Max number of packets per receive call\n"
1908 " -q, --rx_queues <num> Number of RX queues per interface in scheduler\n"
1910 " 0: RX queue per worker CPU (default)\n"
1911 " -p, --packet_copy 0: Don't copy packet (default)\n"
1912 " 1: Create and send copy of the received packet.\n"
1913 " Free the original packet.\n"
1914 " -R, --data_rd <num> Number of packet data words (uint64_t) to read\n"
1915 " from every received packet. Number of words is\n"
1916 " rounded down to fit into the first segment of a\n"
1917 " packet. Default is 0.\n"
1918 " -y, --pool_per_if Create a packet (and packet vector) pool per\n"
1920 " 0: Share a single pool between all interfaces\n"
1922 " 1: Create a pool per interface\n"
1923 " -n, --num_pkt <num> Number of packets per pool. Default is 16k or\n"
1924 " the maximum capability. Use 0 for the default.\n"
1925 " -u, --vector_mode Enable vector mode.\n"
1926 " Supported only with scheduler packet input\n"
1928 " -w, --num_vec <num> Number of vectors per pool.\n"
1929 " Default is num_pkts divided by vec_size.\n"
1930 " -x, --vec_size <num> Vector size (default %i).\n"
1931 " -z, --vec_tmo_ns <ns> Vector timeout in ns (default %llu ns).\n"
1932 " -M, --mtu <len> Interface MTU in bytes.\n"
1933 " -P, --promisc_mode Enable promiscuous mode.\n"
1934 " -l, --packet_len <len> Maximum length of packets supported\n"
1936 " -L, --seg_len <len> Packet pool segment length\n"
1937 " (default equal to packet length).\n"
1938 " -F, --prefetch <num> Prefetch packet data in 64 byte multiples\n"
1940 " -f, --flow_aware Enable flow aware scheduling.\n"
1941 " -T, --input_ts Enable packet input timestamping.\n",
1942 DEFAULT_VEC_SIZE, DEFAULT_VEC_TMO, POOL_PKT_LEN);
1944 printf(
" -C, --tx_compl <mode,n,max_id> Enable transmit completion with a specified\n"
1945 " completion mode for nth packet, with maximum\n"
1946 " completion ID per worker thread in case of poll\n"
1947 " completion (comma-separated, no spaces).\n"
1948 " 0: Event completion mode\n"
1949 " 1: Poll completion mode\n"
1950 " -X, --flow_control <mode> Ethernet flow control mode.\n"
1951 " 0: Flow control disabled (default)\n"
1952 " 1: Enable reception of pause frames\n"
1953 " 2: Enable transmission of pause frames\n"
1954 " 3: Enable reception and transmission of pause\n"
1956 " -v, --verbose Verbose output.\n"
1957 " -V, --verbose_pkt Print debug information on every received\n"
1959 " -h, --help Display help and exit.\n\n"
1970 static void parse_args(
int argc,
char *argv[], appl_args_t *appl_args)
1974 char *tmp_str, *tmp;
1975 size_t str_len, len;
1977 static const struct option longopts[] = {
1978 {
"count", required_argument, NULL,
'c'},
1979 {
"time", required_argument, NULL,
't'},
1980 {
"accuracy", required_argument, NULL,
'a'},
1981 {
"interface", required_argument, NULL,
'i'},
1982 {
"mode", required_argument, NULL,
'm'},
1983 {
"out_mode", required_argument, NULL,
'o'},
1984 {
"output_map", required_argument, NULL,
'O'},
1985 {
"dst_addr", required_argument, NULL,
'r'},
1986 {
"dst_change", required_argument, NULL,
'd'},
1987 {
"src_change", required_argument, NULL,
's'},
1988 {
"error_check", required_argument, NULL,
'e'},
1989 {
"chksum", required_argument, NULL,
'k'},
1990 {
"groups", required_argument, NULL,
'g'},
1991 {
"group_mode", required_argument, NULL,
'G'},
1992 {
"prio", required_argument, NULL,
'I'},
1993 {
"burst_rx", required_argument, NULL,
'b'},
1994 {
"rx_queues", required_argument, NULL,
'q'},
1995 {
"packet_copy", required_argument, NULL,
'p'},
1996 {
"data_rd", required_argument, NULL,
'R'},
1997 {
"pool_per_if", required_argument, NULL,
'y'},
1998 {
"num_pkt", required_argument, NULL,
'n'},
1999 {
"num_vec", required_argument, NULL,
'w'},
2000 {
"vec_size", required_argument, NULL,
'x'},
2001 {
"vec_tmo_ns", required_argument, NULL,
'z'},
2002 {
"vector_mode", no_argument, NULL,
'u'},
2003 {
"mtu", required_argument, NULL,
'M'},
2004 {
"promisc_mode", no_argument, NULL,
'P'},
2005 {
"packet_len", required_argument, NULL,
'l'},
2006 {
"seg_len", required_argument, NULL,
'L'},
2007 {
"prefetch", required_argument, NULL,
'F'},
2008 {
"flow_aware", no_argument, NULL,
'f'},
2009 {
"input_ts", no_argument, NULL,
'T'},
2010 {
"tx_compl", required_argument, NULL,
'C'},
2011 {
"flow_control", required_argument, NULL,
'X'},
2012 {
"verbose", no_argument, NULL,
'v'},
2013 {
"verbose_pkt", no_argument, NULL,
'V'},
2014 {
"help", no_argument, NULL,
'h'},
2018 static const char *shortopts =
"+c:t:a:i:m:o:O:r:d:s:e:k:g:G:I:"
2019 "b:q:p:R:y:n:l:L:w:x:X:z:M:F:uPfTC:vVh";
2021 appl_args->time = 0;
2022 appl_args->accuracy = 1;
2023 appl_args->cpu_count = 1;
2024 appl_args->dst_change = 1;
2025 appl_args->src_change = 1;
2026 appl_args->num_groups = 0;
2027 appl_args->group_mode = 0;
2028 appl_args->error_check = 0;
2029 appl_args->packet_copy = 0;
2030 appl_args->burst_rx = 0;
2031 appl_args->rx_queues = 0;
2032 appl_args->verbose = 0;
2033 appl_args->verbose_pkt = 0;
2034 appl_args->chksum = 0;
2035 appl_args->pool_per_if = 0;
2036 appl_args->num_pkt = 0;
2037 appl_args->packet_len = POOL_PKT_LEN;
2038 appl_args->seg_len = UINT32_MAX;
2040 appl_args->promisc_mode = 0;
2041 appl_args->vector_mode = 0;
2042 appl_args->num_vec = 0;
2043 appl_args->vec_size = 0;
2044 appl_args->vec_tmo_ns = 0;
2045 appl_args->flow_aware = 0;
2046 appl_args->input_ts = 0;
2047 appl_args->num_prio = 0;
2048 appl_args->prefetch = 1;
2049 appl_args->data_rd = 0;
2050 appl_args->flow_control = 0;
2053 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
2060 appl_args->cpu_count = atoi(optarg);
2063 appl_args->time = atoi(optarg);
2066 appl_args->accuracy = atoi(optarg);
2069 len = strlen(optarg);
2071 ODPH_ERR(
"Bad dest address string\n");
2077 tmp_str = malloc(str_len);
2078 if (tmp_str == NULL) {
2079 ODPH_ERR(
"Dest address malloc() failed\n");
2084 memcpy(tmp_str, optarg, str_len);
2085 for (token = strtok(tmp_str,
","), i = 0;
2086 token != NULL; token = strtok(NULL,
","), i++) {
2087 if (i >= MAX_PKTIOS) {
2088 ODPH_ERR(
"Too many MAC addresses\n");
2091 if (odph_eth_addr_parse(&appl_args->addrs[i], token) != 0) {
2092 ODPH_ERR(
"Invalid MAC address\n");
2096 appl_args->addr_count = i;
2097 if (appl_args->addr_count < 1) {
2098 ODPH_ERR(
"Bad dest address count\n");
2104 len = strlen(optarg);
2106 ODPH_ERR(
"Bad pktio interface string\n");
2112 appl_args->if_str = malloc(str_len);
2113 if (appl_args->if_str == NULL) {
2114 ODPH_ERR(
"Pktio interface malloc() failed\n");
2119 memcpy(appl_args->if_str, optarg, str_len);
2120 for (token = strtok(appl_args->if_str,
","), i = 0;
2122 token = strtok(NULL,
","), i++)
2125 appl_args->if_count = i;
2127 if (appl_args->if_count < 1 || appl_args->if_count > MAX_PKTIOS) {
2128 ODPH_ERR(
"Bad pktio interface count: %i\n", appl_args->if_count);
2133 appl_args->if_names = calloc(appl_args->if_count,
sizeof(
char *));
2136 memcpy(appl_args->if_str, optarg, str_len);
2137 for (token = strtok(appl_args->if_str,
","), i = 0;
2138 token != NULL; token = strtok(NULL,
","), i++) {
2139 appl_args->if_names[i] = token;
2145 appl_args->in_mode = SCHED_PARALLEL;
2147 appl_args->in_mode = SCHED_ATOMIC;
2149 appl_args->in_mode = SCHED_ORDERED;
2151 appl_args->in_mode = PLAIN_QUEUE;
2153 appl_args->in_mode = DIRECT_RECV;
2158 appl_args->out_mode = PKTOUT_QUEUE;
2161 if (strlen(optarg) == 0) {
2162 ODPH_ERR(
"Bad output map string\n");
2166 tmp_str = strdup(optarg);
2168 if (tmp_str == NULL) {
2169 ODPH_ERR(
"Output map string duplication failed\n");
2173 token = strtok(tmp_str,
",");
2176 if (appl_args->num_om >= MAX_PKTIOS) {
2177 ODPH_ERR(
"Bad output map element count\n");
2181 appl_args->output_map[appl_args->num_om] = strdup(token);
2183 if (appl_args->output_map[appl_args->num_om] == NULL) {
2184 ODPH_ERR(
"Output map element duplication failed\n");
2188 appl_args->num_om++;
2189 token = strtok(NULL,
",");
2195 appl_args->dst_change = atoi(optarg);
2198 appl_args->src_change = atoi(optarg);
2201 appl_args->error_check = atoi(optarg);
2204 appl_args->chksum = atoi(optarg);
2207 appl_args->num_groups = atoi(optarg);
2210 appl_args->group_mode = atoi(optarg);
2213 len = strlen(optarg);
2215 ODPH_ERR(
"Bad priority list\n");
2221 tmp_str = malloc(str_len);
2222 if (tmp_str == NULL) {
2223 ODPH_ERR(
"Priority list malloc() failed\n");
2227 memcpy(tmp_str, optarg, str_len);
2228 token = strtok(tmp_str,
",");
2230 for (i = 0; token != NULL; token = strtok(NULL,
","), i++) {
2231 if (i >= MAX_PKTIOS) {
2232 ODPH_ERR(
"Too many priorities\n");
2236 appl_args->prio[i] = atoi(token);
2237 appl_args->num_prio++;
2240 if (appl_args->num_prio == 0) {
2241 ODPH_ERR(
"Bad priority list\n");
2248 appl_args->burst_rx = atoi(optarg);
2251 appl_args->rx_queues = atoi(optarg);
2254 appl_args->packet_copy = atoi(optarg);
2257 appl_args->data_rd = atoi(optarg);
2260 appl_args->pool_per_if = atoi(optarg);
2263 appl_args->num_pkt = atoi(optarg);
2266 appl_args->packet_len = atoi(optarg);
2269 appl_args->seg_len = atoi(optarg);
2272 appl_args->mtu = atoi(optarg);
2275 appl_args->promisc_mode = 1;
2278 appl_args->vector_mode = 1;
2281 appl_args->num_vec = atoi(optarg);
2284 appl_args->vec_size = atoi(optarg);
2287 appl_args->flow_control = atoi(optarg);
2288 if (appl_args->flow_control == 1 || appl_args->flow_control == 3)
2289 appl_args->pause_rx =
true;
2290 if (appl_args->flow_control == 2 || appl_args->flow_control == 3)
2291 appl_args->pause_tx =
true;
2294 appl_args->vec_tmo_ns = atoi(optarg);
2297 appl_args->prefetch = atoi(optarg);
2300 appl_args->flow_aware = 1;
2303 appl_args->input_ts = 1;
2306 if (strlen(optarg) == 0) {
2307 ODPH_ERR(
"Bad transmit completion parameter string\n");
2311 tmp_str = strdup(optarg);
2313 if (tmp_str == NULL) {
2314 ODPH_ERR(
"Transmit completion parameter string duplication"
2319 tmp = strtok(tmp_str,
",");
2322 ODPH_ERR(
"Invalid transmit completion parameter format\n");
2333 tmp = strtok(NULL,
",");
2336 ODPH_ERR(
"Invalid transmit completion parameter format\n");
2340 appl_args->tx_compl.nth = atoi(tmp);
2343 tmp = strtok(NULL,
",");
2346 ODPH_ERR(
"Invalid transmit completion parameter format\n");
2350 appl_args->tx_compl.thr_compl_id = atoi(tmp);
2356 appl_args->verbose = 1;
2359 appl_args->verbose_pkt = 1;
2370 if (appl_args->if_count == 0) {
2371 ODPH_ERR(
"No pktio interfaces\n");
2375 if (appl_args->num_om && appl_args->num_om != appl_args->if_count) {
2376 ODPH_ERR(
"Different number of output mappings and pktio interfaces\n");
2380 if (appl_args->num_prio && appl_args->num_prio != appl_args->if_count) {
2381 ODPH_ERR(
"Different number of priorities and pktio interfaces\n");
2385 if (appl_args->addr_count != 0 && appl_args->addr_count != appl_args->if_count) {
2386 ODPH_ERR(
"Number of dest addresses differs from number of interfaces\n");
2390 if (appl_args->burst_rx > MAX_PKT_BURST) {
2391 ODPH_ERR(
"Burst size (%i) too large. Maximum is %i.\n",
2392 appl_args->burst_rx, MAX_PKT_BURST);
2397 appl_args->tx_compl.nth == 0) {
2398 ODPH_ERR(
"Invalid packet interval for transmit completion: %u\n",
2399 appl_args->tx_compl.nth);
2404 (appl_args->in_mode == PLAIN_QUEUE || appl_args->in_mode == DIRECT_RECV)) {
2405 ODPH_ERR(
"Transmit event completion mode not supported with plain queue or direct "
2410 appl_args->tx_compl.tot_compl_id = (appl_args->tx_compl.thr_compl_id + 1) *
2411 appl_args->cpu_count - 1;
2413 if (appl_args->burst_rx == 0)
2414 appl_args->burst_rx = MAX_PKT_BURST;
2416 appl_args->extra_feat = 0;
2417 if (appl_args->error_check || appl_args->chksum ||
2418 appl_args->packet_copy || appl_args->data_rd || appl_args->verbose_pkt)
2419 appl_args->extra_feat = 1;
2421 appl_args->has_state = 0;
2423 appl_args->has_state = 1;
2428 static void print_options(
void)
2431 appl_args_t *appl_args = &gbl_args->appl;
2434 "odp_l2fwd options\n"
2435 "-----------------\n"
2437 "Using IFs: ", appl_args->if_count);
2439 for (i = 0; i < appl_args->if_count; ++i)
2440 printf(
" %s", appl_args->if_names[i]);
2443 if (appl_args->in_mode == DIRECT_RECV)
2444 printf(
"PKTIN_DIRECT, ");
2445 else if (appl_args->in_mode == PLAIN_QUEUE)
2446 printf(
"PKTIN_QUEUE, ");
2447 else if (appl_args->in_mode == SCHED_PARALLEL)
2448 printf(
"PKTIN_SCHED_PARALLEL, ");
2449 else if (appl_args->in_mode == SCHED_ATOMIC)
2450 printf(
"PKTIN_SCHED_ATOMIC, ");
2451 else if (appl_args->in_mode == SCHED_ORDERED)
2452 printf(
"PKTIN_SCHED_ORDERED, ");
2454 if (appl_args->out_mode)
2455 printf(
"PKTOUT_QUEUE\n");
2457 printf(
"PKTOUT_DIRECT\n");
2459 if (appl_args->num_om > 0) {
2460 printf(
"Output mappings: ");
2462 for (i = 0; i < appl_args->num_om; ++i)
2463 printf(
" %s", appl_args->output_map[i]);
2470 printf(
"%i bytes\n", appl_args->mtu);
2472 printf(
"interface default\n");
2473 printf(
"Promisc mode: %s\n", appl_args->promisc_mode ?
2474 "enabled" :
"disabled");
2475 if (appl_args->flow_control)
2476 printf(
"Flow control: %s%s\n",
2477 appl_args->pause_rx ?
"rx " :
"",
2478 appl_args->pause_tx ?
"tx" :
"");
2479 printf(
"Flow aware: %s\n", appl_args->flow_aware ?
2481 printf(
"Input TS: %s\n", appl_args->input_ts ?
"yes" :
"no");
2482 printf(
"Burst size: %i\n", appl_args->burst_rx);
2483 printf(
"RX queues per IF: %i\n", appl_args->rx_queues);
2484 printf(
"Number of pools: %i\n", appl_args->pool_per_if ?
2485 appl_args->if_count : 1);
2487 if (appl_args->extra_feat || appl_args->has_state) {
2488 printf(
"Extra features: %s%s%s%s%s%s\n",
2489 appl_args->error_check ?
"error_check " :
"",
2490 appl_args->chksum ?
"chksum " :
"",
2491 appl_args->packet_copy ?
"packet_copy " :
"",
2492 appl_args->data_rd ?
"data_rd" :
"",
2494 appl_args->verbose_pkt ?
"verbose_pkt" :
"");
2497 printf(
"Num worker threads: %i\n", appl_args->num_workers);
2498 printf(
"CPU mask: %s\n", gbl_args->cpumaskstr);
2500 if (appl_args->num_groups > 0)
2501 printf(
"num groups: %i\n", appl_args->num_groups);
2502 else if (appl_args->num_groups == 0)
2503 printf(
"group: ODP_SCHED_GROUP_ALL\n");
2505 printf(
"group: ODP_SCHED_GROUP_WORKER\n");
2507 printf(
"Packets per pool: %u\n", appl_args->num_pkt);
2508 printf(
"Packet length: %u\n", appl_args->packet_len);
2509 printf(
"Segment length: %u\n", appl_args->seg_len == UINT32_MAX ? 0 :
2510 appl_args->seg_len);
2511 printf(
"Read data: %u bytes\n", appl_args->data_rd * 8);
2512 printf(
"Prefetch data %u bytes\n", appl_args->prefetch * 64);
2513 printf(
"Vectors per pool: %u\n", appl_args->num_vec);
2514 printf(
"Vector size: %u\n", appl_args->vec_size);
2515 printf(
"Priority per IF: ");
2517 for (i = 0; i < appl_args->if_count; i++)
2518 printf(
" %i", appl_args->prio[i]);
2523 static void gbl_args_init(args_t *args)
2527 memset(args, 0,
sizeof(args_t));
2530 for (pktio = 0; pktio < MAX_PKTIOS; pktio++) {
2533 for (queue = 0; queue < MAX_QUEUES; queue++)
2550 for (i = 0; i < num; i++) {
2554 ODPH_ERR(
"Group create failed\n");
2562 uint32_t num_vec, vec_size;
2564 if (gbl_args->appl.vec_size == 0)
2565 vec_size = DEFAULT_VEC_SIZE;
2567 vec_size = gbl_args->appl.vec_size;
2571 if (gbl_args->appl.vec_size == 0) {
2573 printf(
"\nWarning: Vector size reduced to %u\n\n", vec_size);
2575 ODPH_ERR(
"Vector size too big %u. Maximum is %u.\n",
2581 if (gbl_args->appl.num_vec == 0) {
2582 uint32_t num_pkt = gbl_args->appl.num_pkt ?
2583 gbl_args->appl.num_pkt : DEFAULT_NUM_PKT;
2585 num_vec = (num_pkt + vec_size - 1) / vec_size;
2587 num_vec = gbl_args->appl.num_vec;
2591 if (gbl_args->appl.num_vec == 0) {
2593 printf(
"\nWarning: number of vectors reduced to %u\n\n", num_vec);
2595 ODPH_ERR(
"Too many vectors (%u) per pool. Maximum is %u.\n",
2611 int main(
int argc,
char *argv[])
2613 odph_helper_options_t helper_options;
2614 odph_thread_param_t thr_param[MAX_WORKERS];
2615 odph_thread_common_param_t thr_common;
2617 int num_workers, num_thr;
2620 odph_ethaddr_t new_addr;
2623 stats_t *stats[MAX_WORKERS];
2624 int if_count, num_pools, num_vec_pools;
2625 int (*thr_run_func)(
void *);
2627 int num_groups, max_groups;
2629 odp_pool_t pool_tbl[MAX_PKTIOS], vec_pool_tbl[MAX_PKTIOS];
2635 uint32_t pkt_len, num_pkt, seg_len;
2638 argc = odph_parse_options(argc, argv);
2639 if (odph_options(&helper_options)) {
2640 ODPH_ERR(
"Reading ODP helper options failed.\n");
2654 init.
mem_model = helper_options.mem_model;
2656 if (setup_sig_handler()) {
2657 ODPH_ERR(
"Signal handler setup failed\n");
2663 ODPH_ERR(
"ODP global init failed.\n");
2669 ODPH_ERR(
"ODP local init failed.\n");
2675 ODP_CACHE_LINE_SIZE, 0);
2678 ODPH_ERR(
"Shared mem reserve failed.\n");
2684 if (gbl_args == NULL) {
2685 ODPH_ERR(
"Shared mem addr failed.\n");
2688 gbl_args_init(gbl_args);
2691 parse_args(argc, argv, &gbl_args->appl);
2695 if (sched_mode(gbl_args->appl.in_mode))
2696 gbl_args->appl.sched_mode = 1;
2698 num_workers = MAX_WORKERS;
2699 if (gbl_args->appl.cpu_count && gbl_args->appl.cpu_count < MAX_WORKERS)
2700 num_workers = gbl_args->appl.cpu_count;
2704 (void)
odp_cpumask_to_str(&cpumask, gbl_args->cpumaskstr,
sizeof(gbl_args->cpumaskstr));
2706 gbl_args->appl.num_workers = num_workers;
2710 for (i = 0; i < num_workers; i++)
2711 gbl_args->thread_args[i].thr_idx = i;
2713 if_count = gbl_args->appl.if_count;
2716 if (gbl_args->appl.pool_per_if)
2717 num_pools = if_count;
2720 ODPH_ERR(
"Pool capability failed\n");
2725 ODPH_ERR(
"Too many pools %i\n", num_pools);
2729 pkt_len = gbl_args->appl.packet_len;
2733 printf(
"\nWarning: packet length reduced to %u\n\n", pkt_len);
2736 if (gbl_args->appl.seg_len == UINT32_MAX)
2737 seg_len = gbl_args->appl.packet_len;
2739 seg_len = gbl_args->appl.seg_len;
2752 if ((gbl_args->appl.seg_len != UINT32_MAX) && (seg_len != gbl_args->appl.seg_len))
2753 printf(
"\nWarning: Segment length requested %d configured %d\n",
2754 gbl_args->appl.seg_len, seg_len);
2756 if (seg_len < gbl_args->appl.data_rd * 8) {
2757 ODPH_ERR(
"Requested data read length %u exceeds maximum segment length %u\n",
2758 gbl_args->appl.data_rd * 8, seg_len);
2763 if (gbl_args->appl.num_pkt == 0)
2764 num_pkt = DEFAULT_NUM_PKT;
2766 num_pkt = gbl_args->appl.num_pkt;
2769 if (gbl_args->appl.num_pkt == 0) {
2771 printf(
"\nWarning: number of packets reduced to %u\n\n",
2774 ODPH_ERR(
"Too many packets %u. Maximum is %u.\n",
2780 gbl_args->num_pkt = num_pkt;
2781 gbl_args->pkt_len = pkt_len;
2782 gbl_args->seg_len = seg_len;
2784 printf(
"Resulting pool parameter values:\n");
2785 printf(
"Packets per pool: %u\n", num_pkt);
2786 printf(
"Packet length: %u\n", pkt_len);
2787 printf(
"Segment length: %u\n", seg_len);
2792 params.
pkt.
len = pkt_len;
2793 params.
pkt.
num = num_pkt;
2796 for (i = 0; i < num_pools; i++) {
2800 ODPH_ERR(
"Pool create failed %i\n", i);
2804 if (gbl_args->appl.verbose)
2810 if (gbl_args->appl.vector_mode) {
2811 if (!sched_mode(gbl_args->appl.in_mode)) {
2812 ODPH_ERR(
"Vector mode only supports scheduler pktin modes (1-3)\n");
2816 num_vec_pools = gbl_args->appl.pool_per_if ? if_count : 1;
2818 ODPH_ERR(
"Too many vector pools %i\n", num_vec_pools);
2823 if (set_vector_pool_params(¶ms, &pool_capa))
2826 gbl_args->vector_num = params.
vector.
num;
2830 printf(
"Vectors per pool: %u\n", gbl_args->vector_num);
2831 printf(
"Vector size: %u\n", gbl_args->vector_max_size);
2833 for (i = 0; i < num_vec_pools; i++) {
2837 ODPH_ERR(
"Vector pool create failed %i\n", i);
2841 if (gbl_args->appl.verbose)
2853 ODPH_ERR(
"Schedule capability failed\n");
2857 if (gbl_args->appl.flow_aware) {
2861 ODPH_ERR(
"Flow aware mode not supported\n");
2866 num_groups = gbl_args->appl.num_groups;
2869 if (max_groups > MAX_GROUPS)
2870 max_groups = MAX_GROUPS;
2872 if (num_groups > max_groups) {
2873 ODPH_ERR(
"Too many groups. Maximum is %i.\n", max_groups);
2880 if (num_groups == 0) {
2883 }
else if (num_groups == -1) {
2887 create_groups(num_groups, group);
2891 vec_pool = vec_pool_tbl[0];
2893 printf(
"\nInterfaces\n----------\n");
2895 for (i = 0; i < if_count; ++i) {
2896 const char *dev = gbl_args->appl.if_names[i];
2901 num_rx = gbl_args->appl.rx_queues > 0 ? gbl_args->appl.rx_queues : num_workers;
2902 num_tx = num_workers;
2904 if (!gbl_args->appl.sched_mode) {
2906 num_rx = gbl_args->pktios[i].num_rx_thr;
2907 num_tx = gbl_args->pktios[i].num_tx_thr;
2911 grp = group[i % num_groups];
2913 if (gbl_args->appl.pool_per_if) {
2915 vec_pool = vec_pool_tbl[i];
2918 if (create_pktio(dev, i, num_rx, num_tx, pool, vec_pool, grp))
2922 if (gbl_args->appl.dst_change) {
2924 memset(&new_addr, 0,
sizeof(odph_ethaddr_t));
2925 if (gbl_args->appl.addr_count) {
2926 memcpy(&new_addr, &gbl_args->appl.addrs[i],
2927 sizeof(odph_ethaddr_t));
2929 new_addr.addr[0] = 0x02;
2930 new_addr.addr[5] = i;
2932 gbl_args->dst_eth_addr[i] = new_addr;
2940 init_port_lookup_tbl();
2942 if (!gbl_args->appl.sched_mode)
2943 print_port_mapping();
2948 if (gbl_args->appl.in_mode == DIRECT_RECV)
2949 thr_run_func = run_worker_direct_mode;
2950 else if (gbl_args->appl.in_mode == PLAIN_QUEUE)
2951 thr_run_func = run_worker_plain_queue_mode;
2953 thr_run_func = gbl_args->appl.vector_mode ?
2954 run_worker_sched_mode_vector : run_worker_sched_mode;
2957 odph_thread_common_param_init(&thr_common);
2959 thr_common.instance = instance;
2960 thr_common.cpumask = &cpumask;
2963 thr_common.sync = 1;
2965 for (i = 0; i < num_workers; ++i) {
2968 int mode = gbl_args->appl.group_mode;
2970 init_state(&gbl_args->appl, &gbl_args->thread_args[i].state, i);
2971 odph_thread_param_init(&thr_param[i]);
2972 thr_param[i].start = thr_run_func;
2973 thr_param[i].arg = &gbl_args->thread_args[i];
2976 gbl_args->thread_args[i].num_grp_join = 0;
2979 if (gbl_args->appl.num_groups > 0) {
2980 num_join = if_count < num_groups ? if_count : num_groups;
2982 if (mode == 0 || mode == 1) {
2985 num_join = num_groups;
2987 gbl_args->thread_args[i].num_grp_join = num_join;
2989 for (j = 0; j < num_join; j++)
2990 gbl_args->thread_args[i].group[j] = group[j];
2993 if (num_workers >= num_join) {
2994 gbl_args->thread_args[i].num_grp_join = 1;
2995 gbl_args->thread_args[i].group[0] = group[i % num_join];
2999 for (j = 0; i + j < num_join; j += num_workers) {
3000 gbl_args->thread_args[i].group[cnt] = group[i + j];
3004 gbl_args->thread_args[i].num_grp_join = cnt;
3009 stats[i] = &gbl_args->thread_args[i].stats;
3012 num_thr = odph_thread_create(gbl_args->thread_tbl, &thr_common,
3013 thr_param, num_workers);
3015 if (num_thr != num_workers) {
3016 ODPH_ERR(
"Worker create failed: %i\n", num_thr);
3020 if (gbl_args->appl.verbose)
3024 for (i = 0; i < if_count; ++i) {
3027 pktio = gbl_args->pktios[i].pktio;
3030 ODPH_ERR(
"Pktio start failed: %s\n", gbl_args->appl.if_names[i]);
3035 ret = print_speed_stats(num_workers, stats, gbl_args->appl.time,
3036 gbl_args->appl.accuracy);
3038 for (i = 0; i < if_count; ++i) {
3040 ODPH_ERR(
"Pktio stop failed: %s\n", gbl_args->appl.if_names[i]);
3046 if (gbl_args->appl.in_mode != DIRECT_RECV)
3049 odph_thread_join_result_t res[num_workers];
3052 if (odph_thread_join_result(gbl_args->thread_tbl, res, num_workers) != num_workers) {
3053 ODPH_ERR(
"Worker join failed\n");
3057 for (i = 0; i < num_workers; i++) {
3058 if (res[i].is_sig || res[i].ret != 0) {
3059 ODPH_ERR(
"Worker thread failure%s: %d\n", res[i].is_sig ?
3060 " (signaled)" :
"", res[i].ret);
3065 for (i = 0; i < if_count; ++i) {
3069 printf(
"Pktio %s extra statistics:\n", gbl_args->appl.if_names[i]);
3077 ODPH_ERR(
"Pktio close failed: %s\n", gbl_args->appl.if_names[i]);
3082 free(gbl_args->appl.if_names);
3083 free(gbl_args->appl.if_str);
3085 for (i = 0; i < gbl_args->appl.num_om; i++)
3086 free(gbl_args->appl.output_map[i]);
3091 for (i = 0; i < num_pools; i++) {
3093 ODPH_ERR(
"Pool destroy failed: %i\n", i);
3098 for (i = 0; i < num_vec_pools; i++) {
3100 ODPH_ERR(
"Vector pool destroy failed: %i\n", i);
3106 ODPH_ERR(
"Shm free failed\n");
3111 ODPH_ERR(
"Term local failed\n");
3116 ODPH_ERR(
"Term global failed\n");
void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val)
Initialize atomic uint32 variable.
uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom)
Load value of atomic uint32 variable.
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val)
Store value to atomic uint32 variable.
void odp_barrier_init(odp_barrier_t *barr, int count)
Initialize barrier with thread count.
void odp_mb_full(void)
Full memory barrier.
void odp_barrier_wait(odp_barrier_t *barr)
Synchronize thread execution on barrier.
#define ODP_ALIGNED_CACHE
Defines type/struct/variable to be cache line size aligned.
#define odp_unlikely(x)
Branch unlikely taken.
#define ODP_UNUSED
Intentionally unused variables of functions.
#define odp_likely(x)
Branch likely taken.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
void odp_event_free_multi(const odp_event_t event[], int num)
Free multiple events.
void odp_event_free(odp_event_t event)
Free event.
odp_event_type_t odp_event_type(odp_event_t event)
Event type of an event.
#define ODP_EVENT_INVALID
Invalid event.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
int odp_pktio_mac_addr(odp_pktio_t pktio, void *mac_addr, int size)
Get the default MAC address of a packet IO interface.
void odp_pktin_queue_param_init(odp_pktin_queue_param_t *param)
Initialize packet input queue parameters.
void odp_pktio_param_init(odp_pktio_param_t *param)
Initialize pktio params.
int odp_pktio_promisc_mode(odp_pktio_t pktio)
Determine if promiscuous mode is enabled for a packet IO interface.
int odp_pktio_close(odp_pktio_t pktio)
Close a packet IO interface.
int odp_pktio_info(odp_pktio_t pktio, odp_pktio_info_t *info)
Retrieve information about a pktio.
int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num)
Direct packet output queues.
int odp_pktio_maxlen_set(odp_pktio_t pktio, uint32_t maxlen_input, uint32_t maxlen_output)
Set maximum frame lengths.
int odp_pktio_promisc_mode_set(odp_pktio_t pktio, odp_bool_t enable)
Set promiscuous mode.
void odp_pktio_extra_stats_print(odp_pktio_t pktio)
Print extra statistics for a packet IO interface.
void odp_pktio_config_init(odp_pktio_config_t *config)
Initialize packet IO configuration options.
int odp_pktin_event_queue(odp_pktio_t pktio, odp_queue_t queues[], int num)
Event queues for packet input.
odp_pktio_t odp_pktio_open(const char *name, odp_pool_t pool, const odp_pktio_param_t *param)
Open a packet IO interface.
int odp_pktio_config(odp_pktio_t pktio, const odp_pktio_config_t *config)
Configure packet IO interface options.
void odp_pktio_print(odp_pktio_t pktio)
Print pktio info to the console.
int odp_pktio_start(odp_pktio_t pktio)
Start packet receive and transmit.
#define ODP_PKTIO_INVALID
Invalid packet IO handle.
int odp_pktin_queue(odp_pktio_t pktio, odp_pktin_queue_t queues[], int num)
Direct packet input queues.
void odp_pktout_queue_param_init(odp_pktout_queue_param_t *param)
Initialize packet output queue parameters.
int odp_pktout_event_queue(odp_pktio_t pktio, odp_queue_t queues[], int num)
Event queues for packet output.
int odp_pktio_stop(odp_pktio_t pktio)
Stop packet receive and transmit.
int odp_pktin_recv(odp_pktin_queue_t queue, odp_packet_t packets[], int num)
Receive packets directly from an interface input queue.
int odp_pktio_index(odp_pktio_t pktio)
Get pktio interface index.
int odp_pktio_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa)
Query packet IO interface capabilities.
#define ODP_PKTIO_MAX_INDEX
Maximum packet IO interface index.
int odp_pktout_send(odp_pktout_queue_t queue, const odp_packet_t packets[], int num)
Send packets directly to an interface output queue.
odp_pktio_op_mode_t
Packet IO operation mode.
int odp_pktio_extra_stat_info(odp_pktio_t pktio, odp_pktio_extra_stat_info_t info[], int num)
Get extra statistics counter information for a packet IO interface.
int odp_pktin_queue_config(odp_pktio_t pktio, const odp_pktin_queue_param_t *param)
Configure packet input queues.
int odp_pktout_queue_config(odp_pktio_t pktio, const odp_pktout_queue_param_t *param)
Configure packet output queues.
@ ODP_PKTOUT_MODE_QUEUE
Packet output through event queues.
@ ODP_PKTOUT_MODE_DISABLED
Application will never send to this interface.
@ ODP_PKTIO_OP_MT_UNSAFE
Not multithread safe operation.
@ ODP_PKTIO_OP_MT
Multithread safe operation.
@ ODP_PKTIO_LINK_PAUSE_ON
Pause frame flow control enabled.
@ ODP_PKTIN_MODE_QUEUE
Packet input through plain event queues.
@ ODP_PKTIN_MODE_DISABLED
Application will never receive from this interface.
@ ODP_PKTIN_MODE_SCHED
Packet input through scheduler and scheduled event queues.
void odp_packet_from_event_multi(odp_packet_t pkt[], const odp_event_t ev[], int num)
Convert multiple packet events to packet handles.
int odp_packet_tx_compl_request(odp_packet_t pkt, const odp_packet_tx_compl_opt_t *opt)
Request packet transmit completion.
int odp_packet_input_index(odp_packet_t pkt)
Packet input interface index.
int odp_packet_tx_compl_done(odp_pktio_t pktio, uint32_t compl_id)
Check packet transmit completion.
void odp_packet_to_event_multi(const odp_packet_t pkt[], odp_event_t ev[], int num)
Convert multiple packet handles to events.
uint32_t odp_packet_seg_len(odp_packet_t pkt)
Packet data length following the data pointer.
uint32_t odp_packet_headroom(odp_packet_t pkt)
Packet headroom length.
void odp_packet_prefetch(odp_packet_t pkt, uint32_t offset, uint32_t len)
Packet data prefetch.
odp_packet_vector_t odp_packet_vector_from_event(odp_event_t ev)
Get packet vector handle from event.
int odp_packet_num_segs(odp_packet_t pkt)
Number of segments.
odp_packet_t odp_packet_copy(odp_packet_t pkt, odp_pool_t pool)
Full copy of a packet.
uint32_t odp_packet_user_area_size(odp_packet_t pkt)
User area size.
void * odp_packet_data(odp_packet_t pkt)
Packet data pointer.
odp_packet_tx_compl_mode_t
Packet transmit completion mode.
uint32_t odp_packet_len(odp_packet_t pkt)
Packet data length.
int odp_packet_has_error(odp_packet_t pkt)
Check for all parse errors in packet.
int odp_packet_has_tx_compl_request(odp_packet_t pkt)
Check if packet transmit completion is requested.
odp_packet_t odp_packet_from_event(odp_event_t ev)
Get packet handle from event.
void odp_packet_free(odp_packet_t pkt)
Free packet.
void odp_packet_vector_free(odp_packet_vector_t pktv)
Free packet vector.
void odp_packet_l4_chksum_insert(odp_packet_t pkt, int insert)
Layer 4 checksum insertion override.
#define ODP_PACKET_INVALID
Invalid packet.
uint32_t odp_packet_vector_tbl(odp_packet_vector_t pktv, odp_packet_t **pkt_tbl)
Get packet vector table.
odp_pool_t odp_packet_pool(odp_packet_t pkt)
Packet pool.
#define ODP_PACKET_VECTOR_INVALID
Invalid packet vector.
void odp_packet_l3_chksum_insert(odp_packet_t pkt, int insert)
Layer 3 checksum insertion override.
@ ODP_PROTO_LAYER_ALL
All layers.
@ ODP_PROTO_LAYER_NONE
No layers.
@ ODP_PACKET_TX_COMPL_POLL
Enable packet transmit completion check through polling.
@ ODP_PACKET_TX_COMPL_DISABLED
Disable packet transmit completion.
@ ODP_PACKET_TX_COMPL_EVENT
Enable packet transmit completion event.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
int odp_pool_capability(odp_pool_capability_t *capa)
Query pool capabilities.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
void odp_pool_print(odp_pool_t pool)
Print pool info.
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_VECTOR
Vector event pool.
@ ODP_POOL_PACKET
Packet pool.
int odp_queue_enq_multi(odp_queue_t queue, const odp_event_t events[], int num)
Enqueue multiple events to a queue.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
#define ODP_QUEUE_INVALID
Invalid queue.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
odp_queue_t odp_queue_create(const char *name, const odp_queue_param_t *param)
Queue create.
int odp_queue_destroy(odp_queue_t queue)
Destroy ODP queue.
int odp_queue_deq_multi(odp_queue_t queue, odp_event_t events[], int num)
Dequeue multiple events from a queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
int odp_schedule_sync_t
Scheduler synchronization method.
int odp_schedule_multi_no_wait(odp_queue_t *from, odp_event_t events[], int num)
Schedule, do not wait for events.
#define ODP_SCHED_SYNC_PARALLEL
Parallel scheduled queues.
int odp_schedule_prio_t
Scheduling priority level.
int odp_schedule_group_t
Scheduler thread group.
void odp_schedule_config_init(odp_schedule_config_t *config)
Initialize schedule configuration options.
int odp_schedule_group_join(odp_schedule_group_t group, const odp_thrmask_t *mask)
Join a schedule group.
#define ODP_SCHED_SYNC_ATOMIC
Atomic queue synchronization.
#define ODP_SCHED_SYNC_ORDERED
Ordered queue synchronization.
#define ODP_SCHED_GROUP_WORKER
Group of all worker threads.
#define ODP_SCHED_GROUP_INVALID
Invalid scheduler group.
#define ODP_SCHED_NO_WAIT
Do not wait.
int odp_schedule_default_prio(void)
Default scheduling priority level.
void odp_schedule_pause(void)
Pause scheduling.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
uint64_t odp_schedule_wait_time(uint64_t ns)
Schedule wait time.
int odp_schedule_capability(odp_schedule_capability_t *capa)
Query scheduler capabilities.
odp_schedule_group_t odp_schedule_group_create(const char *name, const odp_thrmask_t *mask)
Schedule group create.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
void odp_schedule_resume(void)
Resume scheduling.
#define ODP_SCHED_GROUP_ALL
Group of all threads.
void odp_shm_print_all(void)
Print all shared memory blocks.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
#define ODP_SHM_INVALID
Invalid shared memory block.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
void odp_sys_info_print(void)
Print system info.
void odp_thrmask_set(odp_thrmask_t *mask, int thr)
Add thread to mask.
int odp_thread_id(void)
Get thread identifier.
void odp_thrmask_zero(odp_thrmask_t *mask)
Clear entire thread mask.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
uint64_t odp_time_to_ns(odp_time_t time)
Convert time to nanoseconds.
odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1)
Time difference.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
odp_time_t odp_time_local(void)
Current local time.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
odp_feature_t not_used
Unused features.
Packet transmit completion request options.
Packet input queue parameters.
uint32_t num_queues
Number of input queues to be created.
odp_pktio_op_mode_t op_mode
Operation mode.
odp_queue_param_t queue_param
Queue parameters.
odp_pktin_hash_proto_t hash_proto
Protocol field selection for hashing.
odp_bool_t hash_enable
Enable flow hashing.
odp_pktin_vector_config_t vector
Packet input vector configuration.
uint64_t max_tmo_ns
Maximum timeout in nanoseconds for the producer to wait for the vector of packets.
uint64_t min_tmo_ns
Minimum value allowed to be configured to odp_pktin_vector_config_t::max_tmo_ns.
uint32_t min_size
Minimum value allowed to be configured to odp_pktin_vector_config_t::max_size.
uint32_t max_size
Maximum number of packets that can be accumulated into a packet vector by a producer.
odp_support_t supported
Packet input vector availability.
odp_bool_t enable
Enable packet input vector.
uint32_t max_size
Maximum number of packets in a vector.
uint64_t max_tmo_ns
Maximum time to wait for packets.
odp_pool_t pool
Vector pool.
odp_bool_t queue_type_sched
Scheduled queue support.
uint32_t mode_poll
Packet transmit completion mode ODP_PACKET_TX_COMPL_POLL support.
odp_pktio_set_op_t set_op
Supported set operations.
uint32_t max_output
Maximum valid value for 'maxlen_output'.
odp_pktin_vector_capability_t vector
Packet input vector capability.
uint32_t max_input_queues
Maximum number of input queues.
uint32_t max_input
Maximum valid value for 'maxlen_input'.
struct odp_pktio_capability_t::@110 flow_control
Supported flow control modes.
odp_pktio_config_t config
Supported pktio configuration options.
uint32_t min_output
Minimum valid value for 'maxlen_output'.
uint32_t max_output_queues
Maximum number of output queues.
uint32_t max_compl_id
Maximum supported completion ID value.
struct odp_pktio_capability_t::@108 tx_compl
Supported packet Tx completion options.
uint32_t min_input
Minimum valid value for 'maxlen_input'.
uint32_t mode_event
Packet transmit completion mode ODP_PACKET_TX_COMPL_EVENT support.
struct odp_pktio_capability_t::@107 maxlen
Supported frame lengths for odp_pktio_maxlen_set()
uint32_t pause_tx
Generation of traditional Ethernet pause frames.
uint32_t pause_rx
Reception of traditional Ethernet pause frames.
Packet IO configuration options.
uint32_t max_compl_id
Maximum completion index.
uint32_t mode_event
Enable packet transmit completion events.
odp_pktio_link_pause_t pause_tx
Transmission of flow control frames.
odp_pktout_config_opt_t pktout
Packet output configuration options bit field.
struct odp_pktio_config_t::@102 flow_control
Link flow control configuration.
uint32_t mode_poll
Enable packet transmit completion check through polling.
odp_pktio_link_pause_t pause_rx
Reception of flow control frames.
odp_pktio_parser_config_t parser
Packet input parser configuration.
struct odp_pktio_config_t::@103 tx_compl
Packet transmit completion configuration.
odp_pktin_config_opt_t pktin
Packet input configuration options bit field.
const char * drv_name
Packet IO driver name (implementation specific)
odp_pktin_mode_t in_mode
Packet input mode.
odp_pktout_mode_t out_mode
Packet output mode.
odp_proto_layer_t layer
Protocol parsing level in packet input.
Packet output queue parameters.
odp_pktio_op_mode_t op_mode
Operation mode.
uint32_t num_queues
Number of output queues to be created.
struct odp_pool_capability_t::@122 pkt
Packet pool capabilities
uint32_t max_num
Maximum number of buffers of any size.
uint32_t max_segs_per_pkt
Maximum number of segments per packet.
struct odp_pool_capability_t::@124 vector
Vector pool capabilities.
uint32_t max_size
Maximum buffer data size in bytes.
uint32_t min_seg_len
Minimum packet segment data length in bytes.
uint32_t max_pools
Maximum number of pools of any type (odp_pool_type_t)
uint32_t max_seg_len
Maximum packet segment data length in bytes.
uint32_t max_len
Maximum packet data length in bytes.
uint32_t num
Number of buffers in the pool.
odp_pool_type_t type
Pool type.
uint32_t len
Minimum length of 'num' packets.
uint32_t max_size
Maximum number of handles (such as odp_packet_t) in a vector.
uint32_t seg_len
Minimum number of packet data bytes that can be stored in the first segment of a newly allocated pack...
struct odp_pool_param_t::@126 pkt
Parameters for packet pools.
struct odp_pool_param_t::@128 vector
Parameters for vector pools.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
uint32_t max_flow_id
Maximum flow ID per queue.
uint32_t max_groups
Maximum number of scheduling groups.
uint32_t max_flow_id
Maximum flow ID per queue.
odp_schedule_group_t group
Thread group.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
uint32_t tm
Traffic Manager APIs, e.g., odp_tm_xxx()
uint32_t crypto
Crypto APIs, e.g., odp_crypto_xxx()
uint32_t ipsec
IPsec APIs, e.g., odp_ipsec_xxx()
uint32_t timer
Timer APIs, e.g., odp_timer_xxx(), odp_timeout_xxx()
uint32_t cls
Classifier APIs, e.g., odp_cls_xxx(), odp_cos_xxx()
struct odp_feature_t::@148 feat
Individual feature bits.
uint32_t compress
Compression APIs, e.g., odp_comp_xxx()
uint64_t ts_all
Timestamp all packets on packet input.
struct odp_pktin_config_opt_t::@100 bit
Option flags.
uint32_t ipv4_udp
IPv4 addresses and UDP port numbers.
struct odp_pktin_hash_proto_t::@99 proto
Protocol header fields for hashing.
struct odp_pktio_set_op_t::@104 op
Operation flags.
uint32_t maxlen
Maximum frame length.
uint32_t promisc_mode
Promiscuous mode.
struct odp_pktout_config_opt_t::@101 bit
Option flags for packet output.
uint64_t no_packet_refs
Packet references not used on packet output.
uint64_t ipv4_chksum_ena
Enable IPv4 header checksum insertion.
uint64_t tcp_chksum_ena
Enable TCP checksum insertion.
uint64_t udp_chksum_ena
Enable UDP checksum insertion.