34#include <odp/helper/odph_api.h>
35#include <pktio_common.h>
38#define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1)
41#define DEFAULT_NUM_PKT (16 * 1024)
44#define POOL_PKT_LEN 1536
47#define MAX_PKT_BURST 32
50#define MAX_QUEUES 2048
59#define DEFAULT_VEC_SIZE MAX_PKT_BURST
62#define MAX_EVENT_VEC_SIZE (4U * MAX_PKT_BURST)
65#define DEFAULT_VEC_TMO ODP_TIME_MSEC_IN_NS
68#define EXTRA_STR_LEN 32
71typedef enum pktin_mode_t {
80typedef enum pktout_mode_t {
86typedef enum vector_mode_t {
87 VECTOR_MODE_DISABLED = 0,
88 VECTOR_MODE_EVENT = 1,
89 VECTOR_MODE_PACKET = 2
92static inline int sched_mode(pktin_mode_t in_mode)
94 return (in_mode == SCHED_PARALLEL) ||
95 (in_mode == SCHED_ATOMIC) ||
96 (in_mode == SCHED_ORDERED);
100#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
101 strrchr((file_name), '/') + 1 : (file_name))
136 unsigned int cpu_count;
141 odph_ethaddr_t addrs[MAX_PKTIOS];
142 pktin_mode_t in_mode;
143 pktout_mode_t out_mode;
157 vector_mode_t vector_mode;
162 uint64_t memcpy_bytes;
172 uint32_t sched_prefetch;
179 uint32_t thr_compl_id;
180 uint32_t tot_compl_id;
183 char *output_map[MAX_PKTIOS];
198 uint64_t tx_c_misses;
207 uint8_t padding[ODP_CACHE_LINE_SIZE];
238typedef struct thread_args_t {
267 odph_thread_t thread_tbl[MAX_WORKERS];
269 thread_args_t thread_args[MAX_WORKERS];
276 odph_ethaddr_t port_eth_addr[MAX_PKTIOS];
278 odph_ethaddr_t dst_eth_addr[MAX_PKTIOS];
280 int dst_port[MAX_PKTIOS];
295 } pktios[MAX_PKTIOS];
308 uint32_t vector_max_size;
311 uint8_t *memcpy_data;
318 OPT_SCHED_PREFETCH = 257,
319 OPT_CACHE_STASH = 258
323static args_t *gbl_args;
327 if (gbl_args == NULL)
332static int setup_sig_handler(
void)
334 struct sigaction action = { .sa_handler = sig_handler };
336 if (sigemptyset(&action.sa_mask) || sigaction(SIGINT, &action, NULL))
353static inline int drop_err_pkts(
odp_packet_t pkt_tbl[],
unsigned num)
356 unsigned dropped = 0;
359 for (i = 0, j = 0; i < num; ++i) {
366 pkt_tbl[j - 1] = pkt;
373static inline void prefetch_data(uint8_t prefetch,
odp_packet_t pkt_tbl[], uint32_t num)
378 for (uint32_t i = 0; i < num; i++)
389static inline void fill_eth_addrs(
odp_packet_t pkt_tbl[],
390 unsigned num,
int dst_port)
396 if (!gbl_args->appl.dst_change && !gbl_args->appl.src_change)
399 for (i = 0; i < num; ++i) {
403 if (gbl_args->appl.src_change)
404 eth->src = gbl_args->port_eth_addr[dst_port];
406 if (gbl_args->appl.dst_change)
407 eth->dst = gbl_args->dst_eth_addr[dst_port];
420 while (sent < pkts) {
434static inline void chksum_insert(
odp_packet_t *pkt_tbl,
int pkts)
439 for (i = 0; i < pkts; i++) {
446static void print_packets(
odp_packet_t *pkt_tbl,
int num)
452 for (
int i = 0; i < num; i++) {
456 for (bit = 0, align = 1; bit < 32; bit++, align *= 2)
457 if (data_ptr & (0x1 << bit))
460 printf(
" Packet data: 0x%" PRIxPTR
"\n"
462 " Packet seg len: %u\n"
464 " Num segments: %i\n"
465 " Headroom size: %u\n"
466 " User area size: %u\n\n",
473static inline void data_rd(
odp_packet_t *pkt_tbl,
int num, uint16_t rd_words, stats_t *stats)
478 uint32_t len, words, j;
481 for (i = 0; i < num; i++) {
487 if (rd_words * 8 > len)
490 for (j = 0; j < words; j++)
494 stats->s.dummy_sum += sum;
497static inline int copy_packets(
odp_packet_t *pkt_tbl,
int pkts)
504 for (i = 0; i < pkts; i++) {
505 old_pkt = pkt_tbl[i];
509 pkt_tbl[i] = new_pkt;
522static inline int process_extra_features(
const appl_args_t *appl_args,
odp_packet_t *pkt_tbl,
523 int pkts, stats_t *stats, uint8_t *
const memcpy_src)
526 uint16_t rd_words = appl_args->data_rd;
528 if (appl_args->verbose_pkt)
529 print_packets(pkt_tbl, pkts);
532 data_rd(pkt_tbl, pkts, rd_words, stats);
534 if (appl_args->packet_copy) {
537 fails = copy_packets(pkt_tbl, pkts);
538 stats->s.copy_fails += fails;
541 if (appl_args->chksum)
542 chksum_insert(pkt_tbl, pkts);
544 if (appl_args->error_check) {
548 rx_drops = drop_err_pkts(pkt_tbl, pkts);
551 stats->s.rx_drops += rx_drops;
552 if (pkts == rx_drops)
559 if (appl_args->wait_ns)
562 if (appl_args->memcpy_bytes) {
563 const uint64_t bytes = appl_args->memcpy_bytes;
564 uint8_t *memcpy_dst = memcpy_src + bytes;
566 memcpy(memcpy_dst, memcpy_src, bytes);
572static inline void handle_tx_event_compl(tx_compl_t *tx_c,
odp_packet_t pkts[],
int num,
573 int tx_idx, stats_t *stats)
576 int next_req = tx_c->next_req;
577 const int interval = tx_c->interval;
579 tx_c->opt.queue = gbl_args->pktios[tx_idx].compl_q;
581 while (next_req <= num) {
582 pkt = pkts[next_req - 1];
585 stats->s.tx_c_fails++;
591 next_req += interval;
594 tx_c->next_req = next_req - num;
597static inline void handle_tx_poll_compl(tx_compl_t *tx_c,
odp_packet_t pkts[],
int num,
int tx_idx,
600 uint32_t num_act = tx_c->num_act, poll_head = tx_c->poll_head, free_head = tx_c->free_head;
601 const uint32_t max = tx_c->max, init = tx_c->init, max_act = tx_c->max_act;
602 odp_pktio_t pktio = gbl_args->pktios[tx_idx].pktio;
603 int next_req = tx_c->next_req;
605 const int interval = tx_c->interval;
607 while (num_act > 0) {
613 if (++poll_head > max)
617 while (next_req <= num) {
618 pkt = pkts[next_req - 1];
620 if (num_act == max_act) {
621 stats->s.tx_c_misses++;
627 tx_c->opt.compl_id = free_head;
630 stats->s.tx_c_fails++;
636 if (++free_head > max)
640 next_req += interval;
643 tx_c->free_head = free_head;
644 tx_c->poll_head = poll_head;
645 tx_c->num_act = num_act;
646 tx_c->next_req = next_req - num;
649static inline void handle_tx_state(state_t *state,
odp_packet_t pkts[],
int num,
int tx_idx,
652 tx_compl_t *tx_c = &state->tx_compl;
655 handle_tx_event_compl(tx_c, pkts, num, tx_idx, stats);
657 handle_tx_poll_compl(tx_c, pkts, num, tx_idx, stats);
660static inline void handle_state_failure(state_t *state,
odp_packet_t packet)
663 --state->tx_compl.num_act;
664 --state->tx_compl.free_head;
666 if (state->tx_compl.free_head == UINT32_MAX ||
667 state->tx_compl.free_head < state->tx_compl.init)
668 state->tx_compl.free_head = state->tx_compl.max;
682 unsigned int tx_drops;
687 handle_tx_state(state, pkt_tbl, pkts, tx_idx, stats);
690 sent = event_queue_send(tx_queue, pkt_tbl, pkts);
695 tx_drops = pkts - sent;
698 stats->s.tx_drops += tx_drops;
701 for (i = sent; i < pkts; i++) {
703 handle_state_failure(state, pkt);
708 stats->s.packets += pkts;
711static int handle_rx_state(state_t *state,
odp_event_t evs[],
int num)
727static int run_worker_sched_mode_vector(
void *arg)
731 int pktio, num_pktio;
736 thread_args_t *thr_args = arg;
737 const int thr_idx = thr_args->thr_idx;
738 stats_t *stats = &thr_args->stats;
739 const appl_args_t *appl_args = &gbl_args->appl;
740 uint8_t *
const memcpy_src = appl_args->memcpy_bytes ?
741 &gbl_args->memcpy_data[thr_idx * 2 * appl_args->memcpy_bytes] : NULL;
742 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
743 int use_event_queue = gbl_args->appl.out_mode;
744 pktin_mode_t in_mode = gbl_args->appl.in_mode;
745 const uint32_t sched_prefetch = appl_args->sched_prefetch;
747 max_burst = gbl_args->appl.burst_rx;
753 for (i = 0; i < thr_args->num_grp_join; i++) {
755 ODPH_ERR(
"Join failed: %i\n", i);
760 num_pktio = thr_args->num_pktio;
762 if (num_pktio > MAX_PKTIOS) {
763 ODPH_ERR(
"Too many pktios %i\n", num_pktio);
767 for (pktio = 0; pktio < num_pktio; pktio++) {
768 tx_queue[pktio] = thr_args->pktio[pktio].tx_queue;
769 pktout[pktio] = thr_args->pktio[pktio].pktout;
772 printf(
"[%02i] PKTIN_SCHED_%s_PACKET_VECTOR, %s\n", thr,
773 (in_mode == SCHED_PARALLEL) ?
"PARALLEL" :
774 ((in_mode == SCHED_ATOMIC) ?
"ATOMIC" :
"ORDERED"),
775 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT");
789 for (i = 0; i < events; i++) {
793 int src_idx, dst_idx;
800 }
else if (
odp_event_type(ev_tbl[i]) == ODP_EVENT_PACKET_VECTOR) {
803 }
else if (state != NULL) {
804 pkts = handle_rx_state(state, ev_tbl, events);
810 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
812 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats, memcpy_src);
822 ODPH_ASSERT(src_idx >= 0);
823 dst_idx = gbl_args->dst_port_from_idx[src_idx];
824 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
829 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue[dst_idx],
830 pktout[dst_idx], state, stats);
882static int run_worker_sched_mode_event_vector(
void *arg)
886 int pktio, num_pktio;
891 thread_args_t *thr_args = arg;
892 const int thr_idx = thr_args->thr_idx;
893 stats_t *stats = &thr_args->stats;
894 const appl_args_t *appl_args = &gbl_args->appl;
895 uint8_t *
const memcpy_src = appl_args->memcpy_bytes ?
896 &gbl_args->memcpy_data[thr_idx * 2 * appl_args->memcpy_bytes] : NULL;
897 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
898 int use_event_queue = gbl_args->appl.out_mode;
899 pktin_mode_t in_mode = gbl_args->appl.in_mode;
900 const uint32_t sched_prefetch = appl_args->sched_prefetch;
902 max_burst = gbl_args->appl.burst_rx;
908 for (i = 0; i < thr_args->num_grp_join; i++) {
910 ODPH_ERR(
"Join failed: %i\n", i);
915 num_pktio = thr_args->num_pktio;
917 if (num_pktio > MAX_PKTIOS) {
918 ODPH_ERR(
"Too many pktios %i\n", num_pktio);
922 for (pktio = 0; pktio < num_pktio; pktio++) {
923 tx_queue[pktio] = thr_args->pktio[pktio].tx_queue;
924 pktout[pktio] = thr_args->pktio[pktio].pktout;
927 printf(
"[%02i] PKTIN_SCHED_%s_EVENT_VECTOR, %s\n", thr,
928 (in_mode == SCHED_PARALLEL) ?
"PARALLEL" :
929 ((in_mode == SCHED_ATOMIC) ?
"ATOMIC" :
"ORDERED"),
930 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT");
945 for (i = 0; i < events; i++) {
948 int src_idx, dst_idx;
961 }
else if (state != NULL) {
962 pkts = handle_rx_state(state, ev_tbl, events);
968 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
970 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats, memcpy_src);
977 ODPH_ASSERT(src_idx >= 0);
978 dst_idx = gbl_args->dst_port_from_idx[src_idx];
979 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
984 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue[dst_idx],
985 pktout[dst_idx], state, stats);
1033static int run_worker_sched_mode(
void *arg)
1039 int pktio, num_pktio;
1044 char extra_str[EXTRA_STR_LEN];
1045 thread_args_t *thr_args = arg;
1046 const int thr_idx = thr_args->thr_idx;
1047 stats_t *stats = &thr_args->stats;
1048 const appl_args_t *appl_args = &gbl_args->appl;
1049 uint8_t *
const memcpy_src = appl_args->memcpy_bytes ?
1050 &gbl_args->memcpy_data[thr_idx * 2 * appl_args->memcpy_bytes] : NULL;
1051 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
1052 int use_event_queue = gbl_args->appl.out_mode;
1053 pktin_mode_t in_mode = gbl_args->appl.in_mode;
1054 const uint32_t sched_prefetch = appl_args->sched_prefetch;
1056 max_burst = gbl_args->appl.burst_rx;
1058 memset(extra_str, 0, EXTRA_STR_LEN);
1063 for (i = 0; i < thr_args->num_grp_join; i++) {
1065 ODPH_ERR(
"Join failed: %i\n", i);
1069 if (gbl_args->appl.verbose) {
1070 uint64_t tmp = (uint64_t)(uintptr_t)thr_args->group[i];
1072 printf(
"[%02i] Joined group 0x%" PRIx64
"\n", thr, tmp);
1076 if (thr_args->num_grp_join)
1077 snprintf(extra_str, EXTRA_STR_LEN,
", joined %i groups", thr_args->num_grp_join);
1078 else if (gbl_args->appl.num_groups == 0)
1079 snprintf(extra_str, EXTRA_STR_LEN,
", GROUP_ALL");
1080 else if (gbl_args->appl.num_groups)
1081 snprintf(extra_str, EXTRA_STR_LEN,
", GROUP_WORKER");
1083 num_pktio = thr_args->num_pktio;
1085 if (num_pktio > MAX_PKTIOS) {
1086 ODPH_ERR(
"Too many pktios %i\n", num_pktio);
1090 for (pktio = 0; pktio < num_pktio; pktio++) {
1091 tx_queue[pktio] = thr_args->pktio[pktio].tx_queue;
1092 pktout[pktio] = thr_args->pktio[pktio].pktout;
1095 printf(
"[%02i] PKTIN_SCHED_%s, %s%s\n", thr,
1096 (in_mode == SCHED_PARALLEL) ?
"PARALLEL" :
1097 ((in_mode == SCHED_ATOMIC) ?
"ATOMIC" :
"ORDERED"),
1098 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT", extra_str);
1114 pkts = handle_rx_state(state, ev_tbl, pkts);
1122 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
1124 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats, memcpy_src);
1131 ODPH_ASSERT(src_idx >= 0);
1132 dst_idx = gbl_args->dst_port_from_idx[src_idx];
1133 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
1138 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue[dst_idx],
1139 pktout[dst_idx], state, stats);
1186static int run_worker_plain_queue_mode(
void *arg)
1192 int dst_idx, num_pktio;
1197 thread_args_t *thr_args = arg;
1198 const int thr_idx = thr_args->thr_idx;
1199 stats_t *stats = &thr_args->stats;
1200 const appl_args_t *appl_args = &gbl_args->appl;
1201 uint8_t *
const memcpy_src = appl_args->memcpy_bytes ?
1202 &gbl_args->memcpy_data[thr_idx * 2 * appl_args->memcpy_bytes] : NULL;
1203 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
1204 int use_event_queue = gbl_args->appl.out_mode;
1207 max_burst = gbl_args->appl.burst_rx;
1209 num_pktio = thr_args->num_pktio;
1210 dst_idx = thr_args->pktio[pktio].tx_idx;
1211 queue = thr_args->pktio[pktio].rx_queue;
1212 pktout = thr_args->pktio[pktio].pktout;
1213 tx_queue = thr_args->pktio[pktio].tx_queue;
1215 printf(
"[%02i] num pktios %i, PKTIN_QUEUE, %s\n", thr, num_pktio,
1216 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT");
1224 if (num_pktio > 1) {
1225 dst_idx = thr_args->pktio[pktio].tx_idx;
1226 queue = thr_args->pktio[pktio].rx_queue;
1227 pktout = thr_args->pktio[pktio].pktout;
1229 tx_queue = thr_args->pktio[pktio].tx_queue;
1232 if (pktio == num_pktio)
1242 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
1244 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats, memcpy_src);
1249 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
1251 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue, pktout, state,
1262 for (i = 0; i < num_pktio; i++) {
1266 queue = thr_args->pktio[i].rx_queue;
1287static int run_worker_direct_mode(
void *arg)
1293 int dst_idx, num_pktio;
1298 thread_args_t *thr_args = arg;
1299 const int thr_idx = thr_args->thr_idx;
1300 stats_t *stats = &thr_args->stats;
1301 const appl_args_t *appl_args = &gbl_args->appl;
1302 uint8_t *
const memcpy_src = appl_args->memcpy_bytes ?
1303 &gbl_args->memcpy_data[thr_idx * 2 * appl_args->memcpy_bytes] : NULL;
1304 state_t *state = appl_args->has_state ? &thr_args->state : NULL;
1305 int use_event_queue = gbl_args->appl.out_mode;
1307 max_burst = gbl_args->appl.burst_rx;
1309 num_pktio = thr_args->num_pktio;
1310 dst_idx = thr_args->pktio[pktio].tx_idx;
1311 pktin = thr_args->pktio[pktio].pktin;
1312 pktout = thr_args->pktio[pktio].pktout;
1313 tx_queue = thr_args->pktio[pktio].tx_queue;
1315 printf(
"[%02i] num pktios %i, PKTIN_DIRECT, %s\n", thr, num_pktio,
1316 (use_event_queue) ?
"PKTOUT_QUEUE" :
"PKTOUT_DIRECT");
1322 if (num_pktio > 1) {
1323 dst_idx = thr_args->pktio[pktio].tx_idx;
1324 pktin = thr_args->pktio[pktio].pktin;
1325 pktout = thr_args->pktio[pktio].pktout;
1327 tx_queue = thr_args->pktio[pktio].tx_queue;
1330 if (pktio == num_pktio)
1338 prefetch_data(appl_args->prefetch, pkt_tbl, pkts);
1340 pkts = process_extra_features(appl_args, pkt_tbl, pkts, stats, memcpy_src);
1345 fill_eth_addrs(pkt_tbl, pkts, dst_idx);
1347 send_packets(pkt_tbl, pkts, use_event_queue, dst_idx, tx_queue, pktout, state,
1360 uint64_t vec_tmo_ns;
1366 if (gbl_args->appl.vec_size == 0)
1367 vec_size = DEFAULT_VEC_SIZE;
1369 vec_size = gbl_args->appl.vec_size;
1371 if (vec_size > pktio_capa->
vector.
max_size || vec_size < pktio_capa->vector.min_size) {
1372 if (gbl_args->appl.vec_size == 0) {
1375 printf(
"\nWarning: Modified vector size to %u\n\n", vec_size);
1377 ODPH_ERR(
"Invalid pktio vector size %u, valid range [%u, %u]\n",
1385 vec_tmo_ns = gbl_args->appl.vec_tmo_ns < 0 ? DEFAULT_VEC_TMO :
1386 (uint64_t)gbl_args->appl.vec_tmo_ns;
1389 vec_tmo_ns < pktio_capa->vector.min_tmo_ns) {
1390 if (gbl_args->appl.vec_tmo_ns < 0) {
1393 printf(
"\nWarning: Modified vector timeout to %" PRIu64
"\n\n", vec_tmo_ns);
1395 ODPH_ERR(
"Invalid vector timeout %" PRIu64
", valid range [%" PRIu64
1396 ", %" PRIu64
"]\n", vec_tmo_ns,
1409 uint64_t vec_tmo_ns;
1410 uint32_t vec_size, max_size;
1413 config->
pool = vec_pool;
1416 vec_size = gbl_args->appl.vec_size == 0 ? DEFAULT_VEC_SIZE :
1417 (uint64_t)gbl_args->appl.vec_size;
1419 max_size = ODPH_MIN(capa->
aggr.
max_size, MAX_EVENT_VEC_SIZE);
1420 if (vec_size > max_size || vec_size < capa->aggr.min_size) {
1421 if (gbl_args->appl.vec_size == 0) {
1422 vec_size = vec_size > max_size ? max_size : capa->
aggr.
min_size;
1423 printf(
"\nWarning: Modified vector size to %u\n\n", vec_size);
1425 ODPH_ERR(
"Invalid vector size %u, valid range [%u, %u]\n",
1432 vec_tmo_ns = gbl_args->appl.vec_tmo_ns < 0 ? DEFAULT_VEC_TMO :
1433 (uint64_t)gbl_args->appl.vec_tmo_ns;
1435 if (vec_tmo_ns > capa->
aggr.
max_tmo_ns || vec_tmo_ns < capa->aggr.min_tmo_ns) {
1436 if (gbl_args->appl.vec_tmo_ns < 0) {
1439 printf(
"\nWarning: Modified vector timeout to %" PRIu64
"\n\n", vec_tmo_ns);
1441 ODPH_ERR(
"Invalid vector timeout %" PRIu64
", valid range [%" PRIu64
1442 ", %" PRIu64
"]\n", vec_tmo_ns,
1461static int create_pktio(
const char *dev,
int idx,
int num_rx,
int num_tx,
odp_pool_t pool,
1475 pktin_mode_t in_mode = gbl_args->appl.in_mode;
1481 if (in_mode == PLAIN_QUEUE)
1483 else if (in_mode != DIRECT_RECV)
1486 if (gbl_args->appl.out_mode != PKTOUT_DIRECT)
1497 ODPH_ERR(
"Pktio open failed: %s\n", dev);
1502 ODPH_ERR(
"Pktio info failed: %s\n", dev);
1507 ODPH_ERR(
"Pktio capability query failed: %s\n", dev);
1513 if (gbl_args->appl.input_ts) {
1515 ODPH_ERR(
"Packet input timestamping not supported: %s\n", dev);
1522 if (gbl_args->appl.error_check || gbl_args->appl.chksum)
1525 if (gbl_args->appl.chksum) {
1534 ODPH_ERR(
"Transmit event completion not supported: %s\n", dev);
1541 ODPH_ERR(
"Transmit poll completion not supported: %s\n", dev);
1557 if (gbl_args->appl.pause_rx) {
1559 ODPH_ERR(
"Reception of pause frames not supported: %s\n", dev);
1565 if (gbl_args->appl.pause_tx) {
1567 ODPH_ERR(
"Transmission of pause frames not supported: %s\n", dev);
1577 ODPH_ERR(
"Promisc mode set not supported: %s\n", dev);
1583 ODPH_ERR(
"Promisc mode enable failed: %s\n", dev);
1588 if (gbl_args->appl.mtu) {
1589 uint32_t maxlen_input = pktio_capa.
maxlen.
max_input ? gbl_args->appl.mtu : 0;
1590 uint32_t maxlen_output = pktio_capa.
maxlen.
max_output ? gbl_args->appl.mtu : 0;
1593 ODPH_ERR(
"Modifying interface MTU not supported: %s\n", dev);
1600 ODPH_ERR(
"Unsupported MTU value %" PRIu32
" for %s "
1601 "(min %" PRIu32
", max %" PRIu32
")\n", maxlen_input, dev,
1605 if (maxlen_output &&
1608 ODPH_ERR(
"Unsupported MTU value %" PRIu32
" for %s "
1609 "(min %" PRIu32
", max %" PRIu32
")\n", maxlen_output, dev,
1615 ODPH_ERR(
"Setting MTU failed: %s\n", dev);
1628 if (gbl_args->appl.sched_mode) {
1631 if (gbl_args->appl.num_prio) {
1632 prio = gbl_args->appl.prio[idx];
1635 gbl_args->appl.prio[idx] = prio;
1638 if (gbl_args->appl.in_mode == SCHED_ATOMIC)
1640 else if (gbl_args->appl.in_mode == SCHED_ORDERED)
1658 ODPH_ERR(
"Creating completion queue failed: %s\n", dev);
1667 printf(
"Warning: %s: maximum number of input queues: %i\n", dev, num_rx);
1670 if (num_rx < gbl_args->appl.num_workers)
1671 printf(
"Warning: %s: sharing %i input queues between %i workers\n",
1672 dev, num_rx, gbl_args->appl.num_workers);
1675 int num_tx_orig = num_tx;
1678 printf(
"Warning: %s: sharing %i output queues between %i workers\n",
1679 dev, num_tx, num_tx_orig);
1683 pktin_param.
hash_enable = (num_rx > 1 || gbl_args->appl.flow_aware) ? 1 : 0;
1686 pktin_param.
op_mode = mode_rx;
1688 pktout_param.
op_mode = mode_tx;
1691 if (gbl_args->appl.vector_mode == VECTOR_MODE_PACKET) {
1693 ODPH_ERR(
"Packet vector input not supported: %s\n", dev);
1696 if (set_pktin_vector_params(&pktin_param, vec_pool, &pktio_capa))
1700 if (gbl_args->appl.vector_mode == VECTOR_MODE_EVENT) {
1704 ODPH_ERR(
"Scheduler capability query failed: %s\n", dev);
1709 ODPH_ERR(
"Event vector input not supported: %s\n", dev);
1712 if (set_event_aggr_config(&aggr_config, vec_pool, &sched_capa))
1719 ODPH_ERR(
"Input queue config failed: %s\n", dev);
1724 ODPH_ERR(
"Output queue config failed: %s\n", dev);
1729 if (gbl_args->appl.in_mode == DIRECT_RECV) {
1732 ODPH_ERR(
"Pktin queue query failed: %s\n", dev);
1738 ODPH_ERR(
"Pktin event queue query failed: %s\n", dev);
1745 if (gbl_args->appl.out_mode == PKTOUT_DIRECT) {
1748 ODPH_ERR(
"Pktout queue query failed: %s\n", dev);
1754 ODPH_ERR(
"Event queue query failed: %s\n", dev);
1761 ODPH_ETHADDR_LEN) != ODPH_ETHADDR_LEN) {
1762 ODPH_ERR(
"Reading interface Ethernet address failed: %s\n", dev);
1765 addr = gbl_args->port_eth_addr[idx].addr;
1767 printf(
" dev: %s, drv: %s, rx_queues: %i, tx_queues: %i, mac: "
1768 "%02x:%02x:%02x:%02x:%02x:%02x\n", dev, info.
drv_name, num_rx, num_tx,
1769 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
1771 if (gbl_args->appl.verbose)
1774 gbl_args->pktios[idx].num_rx_queue = num_rx;
1775 gbl_args->pktios[idx].num_tx_queue = num_tx;
1776 gbl_args->pktios[idx].pktio = pktio;
1781static int start_pktios(args_t *gbl_args)
1783 appl_args_t *appl = &gbl_args->appl;
1784 int if_count = appl->if_count;
1786 const char *names[MAX_PKTIOS];
1788 for (
int i = 0; i < if_count; i++) {
1790 ODPH_ERR(
"Error (%s): Pktio start failed.\n", appl->if_names[i]);
1794 pktios[i] = gbl_args->pktios[i].pktio;
1795 names[i] = appl->if_names[i];
1799 if (appl->wait_sec && pktio_common_check_link_status_wait(pktios, names, if_count,
1800 appl->wait_sec) == -1)
1803 pktio_common_print_link_info_multi(pktios, names, if_count);
1808static int stop_pktios(args_t *gbl_args)
1813 appl_args_t *appl = &gbl_args->appl;
1814 uint32_t if_count = appl->if_count;
1816 for (i = 0; i < if_count; i++) {
1817 pktio = gbl_args->pktios[i].pktio;
1823 ODPH_ERR(
"Error (%s): Pktio stop failed.\n", appl->if_names[i]);
1839static int print_speed_stats(
int num_workers, stats_t **thr_stats,
1840 int duration,
int timeout)
1843 uint64_t pkts_prev = 0;
1845 uint64_t rx_drops, tx_drops, tx_c_misses, tx_c_fails, copy_fails;
1846 uint64_t maximum_pps = 0;
1849 int stats_enabled = 1;
1850 int loop_forever = (duration == 0);
1869 for (i = 0; i < num_workers; i++) {
1870 pkts += thr_stats[i]->s.packets;
1871 rx_drops += thr_stats[i]->s.rx_drops;
1872 tx_drops += thr_stats[i]->s.tx_drops;
1873 tx_c_misses += thr_stats[i]->s.tx_c_misses;
1874 tx_c_fails += thr_stats[i]->s.tx_c_fails;
1875 copy_fails += thr_stats[i]->s.copy_fails;
1877 if (stats_enabled) {
1878 pps = (pkts - pkts_prev) / timeout;
1879 if (pps > maximum_pps)
1881 printf(
"%" PRIu64
" pps, %" PRIu64
" max pps, ", pps,
1884 if (gbl_args->appl.packet_copy)
1885 printf(
"%" PRIu64
" copy fails, ", copy_fails);
1888 printf(
"%" PRIu64
" tx compl misses, %" PRIu64
" tx compl fails, ",
1889 tx_c_misses, tx_c_fails);
1891 printf(
"%" PRIu64
" rx drops, %" PRIu64
" tx drops\n",
1892 rx_drops, tx_drops);
1898 (elapsed < duration)));
1901 printf(
"TEST RESULT: %" PRIu64
" maximum packets per second.\n",
1904 return pkts > 100 ? 0 : -1;
1907static void print_port_mapping(
void)
1912 if_count = gbl_args->appl.if_count;
1914 printf(
"\nPort config\n--------------------\n");
1916 for (pktio = 0; pktio < if_count; pktio++) {
1917 const char *dev = gbl_args->appl.if_names[pktio];
1919 printf(
"Port %i (%s)\n", pktio, dev);
1920 printf(
" rx workers %i\n",
1921 gbl_args->pktios[pktio].num_rx_thr);
1922 printf(
" tx workers %i\n",
1923 gbl_args->pktios[pktio].num_tx_thr);
1924 printf(
" rx queues %i\n",
1925 gbl_args->pktios[pktio].num_rx_queue);
1926 printf(
" tx queues %i\n",
1927 gbl_args->pktios[pktio].num_tx_queue);
1938static int find_dest_port(
int port)
1940 const char *output = gbl_args->appl.output_map[port];
1944 for (
int i = 0; i < gbl_args->appl.if_count; i++)
1945 if (strcmp(output, gbl_args->appl.if_names[i]) == 0)
1949 if (gbl_args->appl.if_count % 2 == 0)
1950 return (port % 2 == 0) ? port + 1 : port - 1;
1953 if (port == gbl_args->appl.if_count - 1)
1973static void bind_workers(
void)
1975 int if_count, num_workers;
1976 int rx_idx, tx_idx, thr, pktio, i;
1977 thread_args_t *thr_args;
1979 if_count = gbl_args->appl.if_count;
1980 num_workers = gbl_args->appl.num_workers;
1982 if (gbl_args->appl.sched_mode) {
1984 for (i = 0; i < if_count; i++) {
1985 gbl_args->pktios[i].num_rx_thr = num_workers;
1986 gbl_args->pktios[i].num_tx_thr = num_workers;
1989 for (thr = 0; thr < num_workers; thr++) {
1990 thr_args = &gbl_args->thread_args[thr];
1991 thr_args->num_pktio = if_count;
1995 for (i = 0; i < if_count; i++) {
1996 thr_args->pktio[i].rx_idx = i;
1997 thr_args->pktio[i].tx_idx = i;
2002 for (rx_idx = 0; rx_idx < if_count; rx_idx++)
2003 gbl_args->dst_port[rx_idx] = find_dest_port(rx_idx);
2005 if (if_count > num_workers) {
2010 for (rx_idx = 0; rx_idx < if_count; rx_idx++) {
2011 thr_args = &gbl_args->thread_args[thr];
2012 pktio = thr_args->num_pktio;
2014 tx_idx = gbl_args->dst_port[rx_idx];
2015 thr_args->pktio[pktio].rx_idx = rx_idx;
2016 thr_args->pktio[pktio].tx_idx = tx_idx;
2017 thr_args->num_pktio++;
2019 gbl_args->pktios[rx_idx].num_rx_thr++;
2020 gbl_args->pktios[tx_idx].num_tx_thr++;
2023 if (thr >= num_workers)
2031 for (thr = 0; thr < num_workers; thr++) {
2032 thr_args = &gbl_args->thread_args[thr];
2033 pktio = thr_args->num_pktio;
2035 tx_idx = gbl_args->dst_port[rx_idx];
2036 thr_args->pktio[pktio].rx_idx = rx_idx;
2037 thr_args->pktio[pktio].tx_idx = tx_idx;
2038 thr_args->num_pktio++;
2040 gbl_args->pktios[rx_idx].num_rx_thr++;
2041 gbl_args->pktios[tx_idx].num_tx_thr++;
2044 if (rx_idx >= if_count)
2054static void bind_queues(
void)
2059 num_workers = gbl_args->appl.num_workers;
2061 printf(
"\nQueue binding (indexes)\n-----------------------\n");
2063 for (thr = 0; thr < num_workers; thr++) {
2065 thread_args_t *thr_args = &gbl_args->thread_args[thr];
2066 int num = thr_args->num_pktio;
2068 printf(
"worker %i\n", thr);
2070 for (i = 0; i < num; i++) {
2071 int rx_queue, tx_queue;
2073 rx_idx = thr_args->pktio[i].rx_idx;
2074 tx_idx = thr_args->pktio[i].tx_idx;
2075 rx_queue = gbl_args->pktios[rx_idx].next_rx_queue;
2076 tx_queue = gbl_args->pktios[tx_idx].next_tx_queue;
2078 thr_args->pktio[i].rx_queue_idx = rx_queue;
2079 thr_args->pktio[i].tx_queue_idx = tx_queue;
2080 thr_args->pktio[i].pktin =
2081 gbl_args->pktios[rx_idx].pktin[rx_queue];
2082 thr_args->pktio[i].rx_queue =
2083 gbl_args->pktios[rx_idx].rx_q[rx_queue];
2084 thr_args->pktio[i].pktout =
2085 gbl_args->pktios[tx_idx].pktout[tx_queue];
2086 thr_args->pktio[i].tx_queue =
2087 gbl_args->pktios[tx_idx].tx_q[tx_queue];
2089 if (!gbl_args->appl.sched_mode)
2090 printf(
" rx: pktio %i, queue %i\n",
2093 printf(
" tx: pktio %i, queue %i\n",
2099 if (rx_queue >= gbl_args->pktios[rx_idx].num_rx_queue)
2101 if (tx_queue >= gbl_args->pktios[tx_idx].num_tx_queue)
2104 gbl_args->pktios[rx_idx].next_rx_queue = rx_queue;
2105 gbl_args->pktios[tx_idx].next_tx_queue = tx_queue;
2112static void init_state(
const appl_args_t *args, state_t *state,
int thr_idx)
2114 const uint32_t cnt = args->tx_compl.thr_compl_id + 1;
2116 state->tx_compl.opt.mode = args->tx_compl.mode;
2117 state->tx_compl.init = thr_idx * cnt;
2118 state->tx_compl.max = state->tx_compl.init + cnt - 1;
2119 state->tx_compl.free_head = state->tx_compl.init;
2120 state->tx_compl.poll_head = state->tx_compl.init;
2121 state->tx_compl.num_act = 0;
2122 state->tx_compl.max_act = state->tx_compl.max - state->tx_compl.init + 1;
2123 state->tx_compl.interval = args->tx_compl.nth;
2124 state->tx_compl.next_req = state->tx_compl.interval;
2127static void init_port_lookup_tbl(
void)
2129 int rx_idx, if_count;
2131 if_count = gbl_args->appl.if_count;
2133 for (rx_idx = 0; rx_idx < if_count; rx_idx++) {
2134 odp_pktio_t pktio = gbl_args->pktios[rx_idx].pktio;
2136 int dst_port = find_dest_port(rx_idx);
2138 if (pktio_idx < 0) {
2139 ODPH_ERR(
"Reading pktio (%s) index failed: %i\n",
2140 gbl_args->appl.if_names[rx_idx], pktio_idx);
2145 gbl_args->dst_port_from_idx[pktio_idx] = dst_port;
2153 region->
l2.
len = len;
2156 region->
l3.
len = len;
2161static int parse_cache_stash_config(
char *optarg, appl_args_t *appl)
2163 uint32_t region, level, offset, len;
2167 if (sscanf(optarg,
"%u,%u,%u,%u", ®ion, &level, &offset, &len) != 4) {
2168 ODPH_ERR(
"Invalid number of arguments for cache stashing\n");
2173 ODPH_ERR(
"Invalid region for cache stashing: %u\n", region);
2178 ODPH_ERR(
"Invalid cache level for cache stashing: %u\n", level);
2183 ODPH_ERR(
"Invalid len for cache stashing: %u\n", len);
2218 set_cache_stash(stash_region, level, len, offset);
2226static void usage(
char *progname)
2229 "OpenDataPlane L2 forwarding application.\n"
2231 "Usage: %s [options]\n"
2233 " E.g. %s -i eth0,eth1,eth2,eth3 -m 0 -t 1\n"
2234 " In the above example,\n"
2235 " eth0 will send pkts to eth1 and vice versa\n"
2236 " eth2 will send pkts to eth3 and vice versa\n"
2238 "Mandatory OPTIONS:\n"
2239 " -i, --interface <name> Eth interfaces (comma-separated, no spaces)\n"
2240 " Interface count min 1, max %i\n"
2242 "Optional OPTIONS:\n"
2243 " -m, --mode <arg> Packet input mode\n"
2244 " 0: Direct mode: PKTIN_MODE_DIRECT (default)\n"
2245 " 1: Scheduler mode with parallel queues:\n"
2246 " PKTIN_MODE_SCHED + SCHED_SYNC_PARALLEL\n"
2247 " 2: Scheduler mode with atomic queues:\n"
2248 " PKTIN_MODE_SCHED + SCHED_SYNC_ATOMIC\n"
2249 " 3: Scheduler mode with ordered queues:\n"
2250 " PKTIN_MODE_SCHED + SCHED_SYNC_ORDERED\n"
2251 " 4: Plain queue mode: PKTIN_MODE_QUEUE\n"
2252 " -o, --out_mode <arg> Packet output mode\n"
2253 " 0: Direct mode: PKTOUT_MODE_DIRECT (default)\n"
2254 " 1: Queue mode: PKTOUT_MODE_QUEUE\n"
2255 " -O, --output_map <list> List of destination ports for passed interfaces\n"
2256 " (comma-separated, no spaces). Ordering follows\n"
2257 " the '--interface' option, e.g. passing\n"
2258 " '-i eth0,eth1' and '-O eth0,eth1' would result\n"
2259 " in eth0 and eth1 looping packets back.\n"
2260 " -c, --count <num> CPU count, 0=all available, default=1\n"
2261 " -t, --time <sec> Time in seconds to run.\n"
2262 " -a, --accuracy <sec> Time in seconds get print statistics\n"
2263 " (default is 1 second).\n"
2264 " -d, --dst_change <arg> 0: Don't change packets' dst eth addresses\n"
2265 " 1: Change packets' dst eth addresses (default)\n"
2266 " -s, --src_change <arg> 0: Don't change packets' src eth addresses\n"
2267 " 1: Change packets' src eth addresses (default)\n"
2268 " -r, --dst_addr <addr> Destination addresses (comma-separated, no\n"
2269 " spaces) Requires also the -d flag to be set\n"
2270 " -e, --error_check <arg> 0: Don't check packet errors (default)\n"
2271 " 1: Check packet errors\n"
2272 " -k, --chksum <arg> 0: Don't use checksum offload (default)\n"
2273 " 1: Use checksum offload\n",
2274 NO_PATH(progname), NO_PATH(progname), MAX_PKTIOS);
2276 printf(
" -g, --groups <num> Number of new groups to create (1 ... num).\n"
2277 " Interfaces are placed into the groups in round\n"
2279 " 0: Use SCHED_GROUP_ALL (default)\n"
2280 " -1: Use SCHED_GROUP_WORKER\n"
2281 " -G, --group_mode <arg> Select how threads join new groups\n"
2283 " 0: All threads join all created groups\n"
2285 " 1: All threads join first N created groups.\n"
2286 " N is number of interfaces (== active\n"
2288 " 2: Each thread joins a part of the first N\n"
2289 " groups (in round robin).\n"
2290 " -I, --prio <prio list> Schedule priority of packet input queues.\n"
2291 " Comma separated list of priorities (no spaces).\n"
2292 " A value per interface. All queues of an\n"
2293 " interface have the same priority. Values must\n"
2294 " be between odp_schedule_min_prio and\n"
2295 " odp_schedule_max_prio.\n"
2296 " odp_schedule_default_prio is used by default.\n"
2297 " -b, --burst_rx <num> 0: Use max burst size (default)\n"
2298 " num: Max number of packets per receive call\n"
2299 " -q, --rx_queues <num> Number of RX queues per interface in scheduler\n"
2301 " 0: RX queue per worker CPU (default)\n"
2302 " -p, --packet_copy 0: Don't copy packet (default)\n"
2303 " 1: Create and send copy of the received packet.\n"
2304 " Free the original packet.\n"
2305 " -R, --data_rd <num> Number of packet data words (uint64_t) to read\n"
2306 " from every received packet. Number of words is\n"
2307 " rounded down to fit into the first segment of a\n"
2308 " packet. Default is 0.\n"
2309 " -E, --memcpy <num> Number of bytes to memcpy per RX burst before\n"
2310 " forwarding packets. Default: 0.\n"
2311 " -W, --wait_ns <ns> Number of nsecs to wait per receive burst before\n"
2312 " forwarding packets. Default: 0.\n"
2313 " -y, --pool_per_if Create a packet (and packet vector) pool per\n"
2315 " 0: Share a single pool between all interfaces\n"
2317 " 1: Create a pool per interface\n"
2318 " -n, --num_pkt <num> Number of packets per pool. Default is 16k or\n"
2319 " the maximum capability. Use 0 for the default.\n"
2320 " -u, --vector_mode <num> Enable vector mode.\n"
2321 " Supported only with scheduler packet input\n"
2323 " 0: Disabled (default)\n"
2324 " 1: Event vector mode\n"
2325 " 2: Packet vector mode\n"
2326 " -w, --num_vec <num> Number of vectors per pool.\n"
2327 " Default is num_pkts divided by vec_size.\n"
2328 " -x, --vec_size <num> Vector size (default %i).\n"
2329 " -z, --vec_tmo_ns <ns> Vector timeout in ns (default %llu ns).\n",
2330 DEFAULT_VEC_SIZE, DEFAULT_VEC_TMO);
2332 printf(
" -M, --mtu <len> Interface MTU in bytes.\n"
2333 " -P, --promisc_mode Enable promiscuous mode.\n"
2334 " -l, --packet_len <len> Maximum length of packets supported\n"
2336 " -L, --seg_len <len> Packet pool segment length\n"
2337 " (default equal to packet length).\n"
2338 " -F, --prefetch <num> Prefetch packet data in 64 byte multiples\n"
2340 " -f, --flow_aware Enable flow aware scheduling.\n"
2341 " -T, --input_ts Enable packet input timestamping.\n"
2342 " -C, --tx_compl <mode,n,max_id> Enable transmit completion with a specified\n"
2343 " completion mode for nth packet, with maximum\n"
2344 " completion ID per worker thread in case of poll\n"
2345 " completion (comma-separated, no spaces).\n"
2346 " 0: Event completion mode\n"
2347 " 1: Poll completion mode\n"
2348 " -X, --flow_control <mode> Ethernet flow control mode.\n"
2349 " 0: Flow control disabled (default)\n"
2350 " 1: Enable reception of pause frames\n"
2351 " 2: Enable transmission of pause frames\n"
2352 " 3: Enable reception and transmission of pause\n"
2354 " --cache_stash <num> Enable common group level cache stashing. Format: region,level,offset,len\n"
2355 " region: 0: Event metadata, 1: Event data, 2: Event user area, 3: Queue context\n"
2356 " level: 0: L2, 1: L3\n"
2357 " offset/len: in bytes\n"
2358 " E.g.: 1,0,16,32 enables 32-byte L2 stash on event data with a 16-byte offset\n"
2359 " A region can be cached on multiple levels by specifying this option more than once.\n"
2360 " Similarly, to stash multiple regions, use --cache_stash multiple times.\n"
2361 " --schedule_prefetch <num> Number of events to be prefetched for scheduling. Default: 0.\n"
2362 " --wait_link <sec> Wait up to <sec> seconds for network links to be up.\n"
2363 " Default: 0 (don't check link status)\n"
2364 " -v, --verbose Verbose output.\n"
2365 " -V, --verbose_pkt Print debug information on every received\n"
2367 " -h, --help Display help and exit.\n\n"
2368 "\n", POOL_PKT_LEN);
2378static void parse_args(
int argc,
char *argv[], appl_args_t *appl_args)
2382 char *tmp_str, *tmp;
2383 size_t str_len, len;
2385 static const struct option longopts[] = {
2386 {
"count", required_argument, NULL,
'c'},
2387 {
"time", required_argument, NULL,
't'},
2388 {
"accuracy", required_argument, NULL,
'a'},
2389 {
"interface", required_argument, NULL,
'i'},
2390 {
"mode", required_argument, NULL,
'm'},
2391 {
"memcpy", required_argument, NULL,
'E'},
2392 {
"out_mode", required_argument, NULL,
'o'},
2393 {
"output_map", required_argument, NULL,
'O'},
2394 {
"dst_addr", required_argument, NULL,
'r'},
2395 {
"dst_change", required_argument, NULL,
'd'},
2396 {
"src_change", required_argument, NULL,
's'},
2397 {
"error_check", required_argument, NULL,
'e'},
2398 {
"chksum", required_argument, NULL,
'k'},
2399 {
"groups", required_argument, NULL,
'g'},
2400 {
"group_mode", required_argument, NULL,
'G'},
2401 {
"prio", required_argument, NULL,
'I'},
2402 {
"burst_rx", required_argument, NULL,
'b'},
2403 {
"rx_queues", required_argument, NULL,
'q'},
2404 {
"packet_copy", required_argument, NULL,
'p'},
2405 {
"data_rd", required_argument, NULL,
'R'},
2406 {
"pool_per_if", required_argument, NULL,
'y'},
2407 {
"num_pkt", required_argument, NULL,
'n'},
2408 {
"num_vec", required_argument, NULL,
'w'},
2409 {
"wait_ns", required_argument, NULL,
'W'},
2410 {
"wait_link", required_argument, NULL, OPT_WAIT_LINK},
2411 {
"vec_size", required_argument, NULL,
'x'},
2412 {
"vec_tmo_ns", required_argument, NULL,
'z'},
2413 {
"vector_mode", required_argument, NULL,
'u'},
2414 {
"mtu", required_argument, NULL,
'M'},
2415 {
"promisc_mode", no_argument, NULL,
'P'},
2416 {
"packet_len", required_argument, NULL,
'l'},
2417 {
"seg_len", required_argument, NULL,
'L'},
2418 {
"prefetch", required_argument, NULL,
'F'},
2419 {
"flow_aware", no_argument, NULL,
'f'},
2420 {
"input_ts", no_argument, NULL,
'T'},
2421 {
"tx_compl", required_argument, NULL,
'C'},
2422 {
"flow_control", required_argument, NULL,
'X'},
2423 {
"cache_stash", required_argument, NULL, OPT_CACHE_STASH},
2424 {
"schedule_prefetch", required_argument, NULL, OPT_SCHED_PREFETCH},
2425 {
"verbose", no_argument, NULL,
'v'},
2426 {
"verbose_pkt", no_argument, NULL,
'V'},
2427 {
"help", no_argument, NULL,
'h'},
2431 static const char *shortopts =
"+c:t:a:i:m:o:O:r:d:s:e:E:k:g:G:I:"
2432 "b:q:p:R:y:n:l:L:w:W:x:X:z:M:F:u:PfTC:vVh";
2434 appl_args->accuracy = 1;
2435 appl_args->cpu_count = 1;
2436 appl_args->dst_change = 1;
2437 appl_args->src_change = 1;
2438 appl_args->packet_len = POOL_PKT_LEN;
2439 appl_args->seg_len = UINT32_MAX;
2440 appl_args->vector_mode = VECTOR_MODE_DISABLED;
2441 appl_args->vec_tmo_ns = -1;
2442 appl_args->prefetch = 1;
2445 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
2452 appl_args->cpu_count = atoi(optarg);
2455 appl_args->time = atoi(optarg);
2458 appl_args->accuracy = atoi(optarg);
2461 len = strlen(optarg);
2463 ODPH_ERR(
"Bad dest address string\n");
2469 tmp_str = malloc(str_len);
2470 if (tmp_str == NULL) {
2471 ODPH_ERR(
"Dest address malloc() failed\n");
2476 memcpy(tmp_str, optarg, str_len);
2477 for (token = strtok(tmp_str,
","), i = 0;
2478 token != NULL; token = strtok(NULL,
","), i++) {
2479 if (i >= MAX_PKTIOS) {
2480 ODPH_ERR(
"Too many MAC addresses\n");
2483 if (odph_eth_addr_parse(&appl_args->addrs[i], token) != 0) {
2484 ODPH_ERR(
"Invalid MAC address\n");
2488 appl_args->addr_count = i;
2489 if (appl_args->addr_count < 1) {
2490 ODPH_ERR(
"Bad dest address count\n");
2496 len = strlen(optarg);
2498 ODPH_ERR(
"Bad pktio interface string\n");
2504 appl_args->if_str = malloc(str_len);
2505 if (appl_args->if_str == NULL) {
2506 ODPH_ERR(
"Pktio interface malloc() failed\n");
2511 memcpy(appl_args->if_str, optarg, str_len);
2512 for (token = strtok(appl_args->if_str,
","), i = 0;
2514 token = strtok(NULL,
","), i++)
2517 appl_args->if_count = i;
2519 if (appl_args->if_count < 1 || appl_args->if_count > MAX_PKTIOS) {
2520 ODPH_ERR(
"Bad pktio interface count: %i\n", appl_args->if_count);
2525 appl_args->if_names = calloc(appl_args->if_count,
sizeof(
char *));
2528 memcpy(appl_args->if_str, optarg, str_len);
2529 for (token = strtok(appl_args->if_str,
","), i = 0;
2530 token != NULL; token = strtok(NULL,
","), i++) {
2531 appl_args->if_names[i] = token;
2537 appl_args->in_mode = SCHED_PARALLEL;
2539 appl_args->in_mode = SCHED_ATOMIC;
2541 appl_args->in_mode = SCHED_ORDERED;
2543 appl_args->in_mode = PLAIN_QUEUE;
2545 appl_args->in_mode = DIRECT_RECV;
2550 appl_args->out_mode = PKTOUT_QUEUE;
2553 if (strlen(optarg) == 0) {
2554 ODPH_ERR(
"Bad output map string\n");
2558 tmp_str = strdup(optarg);
2560 if (tmp_str == NULL) {
2561 ODPH_ERR(
"Output map string duplication failed\n");
2565 token = strtok(tmp_str,
",");
2568 if (appl_args->num_om >= MAX_PKTIOS) {
2569 ODPH_ERR(
"Bad output map element count\n");
2573 appl_args->output_map[appl_args->num_om] = strdup(token);
2575 if (appl_args->output_map[appl_args->num_om] == NULL) {
2576 ODPH_ERR(
"Output map element duplication failed\n");
2580 appl_args->num_om++;
2581 token = strtok(NULL,
",");
2587 appl_args->dst_change = atoi(optarg);
2590 appl_args->src_change = atoi(optarg);
2593 appl_args->error_check = atoi(optarg);
2596 appl_args->memcpy_bytes = atoll(optarg);
2599 appl_args->chksum = atoi(optarg);
2602 appl_args->num_groups = atoi(optarg);
2605 appl_args->group_mode = atoi(optarg);
2608 len = strlen(optarg);
2610 ODPH_ERR(
"Bad priority list\n");
2616 tmp_str = malloc(str_len);
2617 if (tmp_str == NULL) {
2618 ODPH_ERR(
"Priority list malloc() failed\n");
2622 memcpy(tmp_str, optarg, str_len);
2623 token = strtok(tmp_str,
",");
2625 for (i = 0; token != NULL; token = strtok(NULL,
","), i++) {
2626 if (i >= MAX_PKTIOS) {
2627 ODPH_ERR(
"Too many priorities\n");
2631 appl_args->prio[i] = atoi(token);
2632 appl_args->num_prio++;
2635 if (appl_args->num_prio == 0) {
2636 ODPH_ERR(
"Bad priority list\n");
2643 appl_args->burst_rx = atoi(optarg);
2646 appl_args->rx_queues = atoi(optarg);
2649 appl_args->packet_copy = atoi(optarg);
2652 appl_args->data_rd = atoi(optarg);
2655 appl_args->pool_per_if = atoi(optarg);
2658 appl_args->num_pkt = atoi(optarg);
2661 appl_args->packet_len = atoi(optarg);
2664 appl_args->seg_len = atoi(optarg);
2667 appl_args->mtu = atoi(optarg);
2670 appl_args->promisc_mode = 1;
2673 appl_args->vector_mode = atoi(optarg);
2676 appl_args->num_vec = atoi(optarg);
2679 appl_args->wait_ns = atoll(optarg);
2682 appl_args->vec_size = atoi(optarg);
2685 appl_args->flow_control = atoi(optarg);
2686 if (appl_args->flow_control == 1 || appl_args->flow_control == 3)
2687 appl_args->pause_rx =
true;
2688 if (appl_args->flow_control == 2 || appl_args->flow_control == 3)
2689 appl_args->pause_tx =
true;
2692 appl_args->vec_tmo_ns = atoi(optarg);
2695 appl_args->wait_sec = atoi(optarg);
2698 appl_args->prefetch = atoi(optarg);
2701 appl_args->flow_aware = 1;
2704 appl_args->input_ts = 1;
2707 if (strlen(optarg) == 0) {
2708 ODPH_ERR(
"Bad transmit completion parameter string\n");
2712 tmp_str = strdup(optarg);
2714 if (tmp_str == NULL) {
2715 ODPH_ERR(
"Transmit completion parameter string duplication"
2720 tmp = strtok(tmp_str,
",");
2723 ODPH_ERR(
"Invalid transmit completion parameter format\n");
2734 tmp = strtok(NULL,
",");
2737 ODPH_ERR(
"Invalid transmit completion parameter format\n");
2741 appl_args->tx_compl.nth = atoi(tmp);
2744 tmp = strtok(NULL,
",");
2747 ODPH_ERR(
"Invalid transmit completion parameter format\n");
2751 appl_args->tx_compl.thr_compl_id = atoi(tmp);
2756 case OPT_CACHE_STASH:
2757 if (parse_cache_stash_config(optarg, appl_args))
2760 case OPT_SCHED_PREFETCH:
2761 appl_args->sched_prefetch = atoi(optarg);
2764 appl_args->verbose = 1;
2767 appl_args->verbose_pkt = 1;
2778 if (appl_args->if_count == 0) {
2779 ODPH_ERR(
"No pktio interfaces\n");
2783 if (appl_args->num_om && appl_args->num_om != appl_args->if_count) {
2784 ODPH_ERR(
"Different number of output mappings and pktio interfaces\n");
2788 if (appl_args->num_prio && appl_args->num_prio != appl_args->if_count) {
2789 ODPH_ERR(
"Different number of priorities and pktio interfaces\n");
2793 if (appl_args->addr_count != 0 && appl_args->addr_count != appl_args->if_count) {
2794 ODPH_ERR(
"Number of dest addresses differs from number of interfaces\n");
2798 if (appl_args->burst_rx > MAX_PKT_BURST) {
2799 ODPH_ERR(
"Burst size (%i) too large. Maximum is %i.\n",
2800 appl_args->burst_rx, MAX_PKT_BURST);
2804 if (appl_args->rx_queues > MAX_QUEUES) {
2805 ODPH_ERR(
"Number of RX queues per interface (%i) too large. Maximum is %i.\n",
2806 appl_args->rx_queues, MAX_QUEUES);
2810 if (appl_args->vector_mode != VECTOR_MODE_DISABLED &&
2811 appl_args->vector_mode != VECTOR_MODE_PACKET &&
2812 appl_args->vector_mode != VECTOR_MODE_EVENT) {
2813 ODPH_ERR(
"Invalid vector mode: %d\n", appl_args->vector_mode);
2818 appl_args->tx_compl.nth == 0) {
2819 ODPH_ERR(
"Invalid packet interval for transmit completion: %u\n",
2820 appl_args->tx_compl.nth);
2825 (appl_args->in_mode == PLAIN_QUEUE || appl_args->in_mode == DIRECT_RECV)) {
2826 ODPH_ERR(
"Transmit event completion mode not supported with plain queue or direct "
2831 appl_args->tx_compl.tot_compl_id = (appl_args->tx_compl.thr_compl_id + 1) *
2832 appl_args->cpu_count - 1;
2834 if (appl_args->burst_rx == 0)
2835 appl_args->burst_rx = MAX_PKT_BURST;
2837 appl_args->extra_feat = 0;
2838 if (appl_args->error_check || appl_args->chksum || appl_args->packet_copy ||
2839 appl_args->data_rd || appl_args->verbose_pkt || appl_args->wait_ns ||
2840 appl_args->memcpy_bytes)
2841 appl_args->extra_feat = 1;
2843 appl_args->has_state = 0;
2845 appl_args->has_state = 1;
2850static void print_options(
void)
2853 appl_args_t *appl_args = &gbl_args->appl;
2857 "odp_l2fwd options\n"
2858 "-----------------\n"
2860 "Using IFs: ", appl_args->if_count);
2862 for (i = 0; i < appl_args->if_count; ++i)
2863 printf(
" %s", appl_args->if_names[i]);
2866 if (appl_args->in_mode == DIRECT_RECV)
2867 printf(
"PKTIN_DIRECT, ");
2868 else if (appl_args->in_mode == PLAIN_QUEUE)
2869 printf(
"PKTIN_QUEUE, ");
2870 else if (appl_args->in_mode == SCHED_PARALLEL)
2871 printf(
"PKTIN_SCHED_PARALLEL, ");
2872 else if (appl_args->in_mode == SCHED_ATOMIC)
2873 printf(
"PKTIN_SCHED_ATOMIC, ");
2874 else if (appl_args->in_mode == SCHED_ORDERED)
2875 printf(
"PKTIN_SCHED_ORDERED, ");
2877 if (appl_args->out_mode)
2878 printf(
"PKTOUT_QUEUE\n");
2880 printf(
"PKTOUT_DIRECT\n");
2882 if (appl_args->num_om > 0) {
2883 printf(
"Output mappings: ");
2885 for (i = 0; i < appl_args->num_om; ++i)
2886 printf(
" %s", appl_args->output_map[i]);
2893 printf(
"%i bytes\n", appl_args->mtu);
2895 printf(
"interface default\n");
2896 printf(
"Promisc mode: %s\n", appl_args->promisc_mode ?
2897 "enabled" :
"disabled");
2898 if (appl_args->flow_control)
2899 printf(
"Flow control: %s%s\n",
2900 appl_args->pause_rx ?
"rx " :
"",
2901 appl_args->pause_tx ?
"tx" :
"");
2902 printf(
"Flow aware: %s\n", appl_args->flow_aware ?
2904 printf(
"Input TS: %s\n", appl_args->input_ts ?
"yes" :
"no");
2905 printf(
"Burst size: %i\n", appl_args->burst_rx);
2906 printf(
"RX queues per IF: %i\n", appl_args->rx_queues);
2907 printf(
"Number of pools: %i\n", appl_args->pool_per_if ?
2908 appl_args->if_count : 1);
2910 if (appl_args->extra_feat || appl_args->has_state) {
2911 printf(
"Extra features: %s%s%s%s%s%s%s%s\n",
2912 appl_args->error_check ?
"error_check " :
"",
2913 appl_args->chksum ?
"chksum " :
"",
2914 appl_args->packet_copy ?
"packet_copy " :
"",
2915 appl_args->data_rd ?
"data_rd" :
"",
2917 appl_args->verbose_pkt ?
"verbose_pkt" :
"",
2918 appl_args->wait_ns ?
"wait_ns" :
"",
2919 appl_args->memcpy_bytes ?
"memcpy" :
"");
2921 if (appl_args->memcpy_bytes)
2922 printf(
" Memcpy: %" PRIu64
" bytes\n", appl_args->memcpy_bytes);
2923 if (appl_args->wait_ns)
2924 printf(
" Wait: %" PRIu64
" ns\n", appl_args->wait_ns);
2927 printf(
"Num worker threads: %i\n", appl_args->num_workers);
2928 printf(
"CPU mask: %s\n", gbl_args->cpumaskstr);
2930 if (appl_args->num_groups > 0)
2931 printf(
"num groups: %i\n", appl_args->num_groups);
2932 else if (appl_args->num_groups == 0)
2933 printf(
"group: ODP_SCHED_GROUP_ALL\n");
2935 printf(
"group: ODP_SCHED_GROUP_WORKER\n");
2937 printf(
"Packets per pool: %u\n", appl_args->num_pkt);
2938 printf(
"Packet length: %u\n", appl_args->packet_len);
2939 printf(
"Segment length: %u\n", appl_args->seg_len == UINT32_MAX ? 0 :
2940 appl_args->seg_len);
2941 printf(
"Read data: %u bytes\n", appl_args->data_rd * 8);
2942 printf(
"Prefetch data: %u bytes\n", appl_args->prefetch * 64);
2943 printf(
"Vector mode: %s\n", appl_args->vector_mode == VECTOR_MODE_PACKET ?
2944 "packet" : appl_args->vector_mode == VECTOR_MODE_EVENT ?
"event" :
"disabled");
2945 printf(
"Vectors per pool: %u\n", appl_args->num_vec);
2946 printf(
"Vector size: %u\n", appl_args->vec_size);
2947 printf(
"Priority per IF: ");
2949 for (i = 0; i < appl_args->if_count; i++)
2950 printf(
" %i", appl_args->prio[i]);
2953 printf(
"Schedule prefetch: %u events\n", appl_args->sched_prefetch);
2955 printf(
"Cache stash: ");
2957 printf(
"\n%-18s %10s %8s %10s %8s\n",
2958 "Region",
"L2 offset",
"L2 len",
"L3 offset",
"L3 len");
2959 printf(
"----------------------------------------------------------\n");
2961 printf(
"%-18s %10d %8d %10d %8d\n",
2968 printf(
"%-18s %10d %8d %10d %8d\n",
2975 printf(
"%-18s %10d %8d %10d %8d\n",
2982 printf(
"%-18s %10d %8d %10d %8d\n",
2989 printf(
"disabled\n");
2995static void gbl_args_init(args_t *args)
2999 memset(args, 0,
sizeof(args_t));
3003 for (pktio = 0; pktio < MAX_PKTIOS; pktio++) {
3006 for (queue = 0; queue < MAX_QUEUES; queue++)
3027 for (i = 0; i < num; i++) {
3031 ODPH_ERR(
"Group create failed\n");
3039 uint32_t num_vec, vec_size;
3041 vec_size = gbl_args->appl.vec_size == 0 ? DEFAULT_VEC_SIZE : gbl_args->appl.vec_size;
3045 if (gbl_args->appl.vec_size == 0) {
3047 printf(
"\nWarning: Vector size reduced to %u\n\n", vec_size);
3049 ODPH_ERR(
"Vector size too big %u. Maximum is %u.\n",
3055 if (gbl_args->appl.num_vec == 0) {
3056 uint32_t num_pkt = gbl_args->appl.num_pkt ?
3057 gbl_args->appl.num_pkt : DEFAULT_NUM_PKT;
3059 num_vec = (num_pkt + vec_size - 1) / vec_size;
3061 num_vec = gbl_args->appl.num_vec;
3065 if (gbl_args->appl.num_vec == 0) {
3067 printf(
"\nWarning: number of vectors reduced to %u\n\n", num_vec);
3069 ODPH_ERR(
"Too many vectors (%u) per pool. Maximum is %u.\n",
3085 uint32_t num_vec, vec_size, max_size;
3087 vec_size = gbl_args->appl.vec_size == 0 ? DEFAULT_VEC_SIZE : gbl_args->appl.vec_size;
3090 if (vec_size > max_size) {
3091 if (gbl_args->appl.vec_size == 0) {
3092 vec_size = max_size;
3093 printf(
"\nWarning: Vector size reduced to %u\n\n", vec_size);
3095 ODPH_ERR(
"Vector size too big %u. Maximum is %u.\n", vec_size, max_size);
3100 if (gbl_args->appl.num_vec == 0) {
3101 uint32_t num_pkt = gbl_args->appl.num_pkt ?
3102 gbl_args->appl.num_pkt : DEFAULT_NUM_PKT;
3104 num_vec = (num_pkt + vec_size - 1) / vec_size;
3106 num_vec = gbl_args->appl.num_vec;
3110 if (gbl_args->appl.num_vec == 0) {
3112 printf(
"\nWarning: number of vectors reduced to %u\n\n", num_vec);
3114 ODPH_ERR(
"Too many vectors (%u) per pool. Maximum is %u.\n",
3127static int reserve_memcpy_memory(args_t *args)
3129 uint64_t total_bytes;
3131 if (args->appl.memcpy_bytes == 0)
3135 total_bytes = 2 * args->appl.memcpy_bytes * args->appl.num_workers;
3137 args->memcpy_shm =
odp_shm_reserve(
"memcpy_shm", total_bytes, ODP_CACHE_LINE_SIZE, 0);
3139 ODPH_ERR(
"Reserving %" PRIu64
" bytes for memcpy failed.\n", total_bytes);
3143 if (args->memcpy_data == NULL) {
3144 ODPH_ERR(
"Shared mem addr for memcpy failed.\n");
3156 vector_mode_t mode = args->appl.vector_mode;
3158 if (mode == VECTOR_MODE_DISABLED)
3161 if (!sched_mode(args->appl.in_mode)) {
3162 ODPH_ERR(
"Vector mode only supports scheduler pktin modes (1-3)\n");
3166 num_vec_pools = args->appl.pool_per_if ? gbl_args->appl.if_count : 1;
3168 if ((mode == VECTOR_MODE_PACKET && num_vec_pools > (
int)pool_capa->
vector.
max_pools) ||
3170 ODPH_ERR(
"Too many vector pools %i\n", num_vec_pools);
3176 if (mode == VECTOR_MODE_PACKET) {
3177 if (set_vector_pool_params(¶ms, pool_capa))
3180 if (set_event_vector_pool_params(¶ms, pool_capa))
3185 args->vector_max_size = mode == VECTOR_MODE_PACKET ? params.
vector.
max_size :
3189 printf(
"Vectors per pool: %u\n", args->vector_num);
3190 printf(
"Vector size: %u\n", args->vector_max_size);
3192 for (
int i = 0; i < num_vec_pools; i++) {
3196 ODPH_ERR(
"Vector pool create failed %i\n", i);
3200 if (args->appl.verbose)
3204 return num_vec_pools;
3210int main(
int argc,
char *argv[])
3212 odph_helper_options_t helper_options;
3213 odph_thread_param_t thr_param[MAX_WORKERS];
3214 odph_thread_common_param_t thr_common;
3216 int num_workers, num_thr;
3219 odph_ethaddr_t new_addr;
3222 stats_t *stats[MAX_WORKERS];
3223 int if_count, num_pools, num_vec_pools;
3224 int (*thr_run_func)(
void *);
3226 int num_groups, max_groups;
3228 odp_pool_t pool_tbl[MAX_PKTIOS], vec_pool_tbl[MAX_PKTIOS];
3234 uint32_t pkt_len, num_pkt, seg_len;
3238 argc = odph_parse_options(argc, argv);
3239 if (odph_options(&helper_options)) {
3240 ODPH_ERR(
"Reading ODP helper options failed.\n");
3254 init.
mem_model = helper_options.mem_model;
3256 if (setup_sig_handler()) {
3257 ODPH_ERR(
"Signal handler setup failed\n");
3263 ODPH_ERR(
"ODP global init failed.\n");
3269 ODPH_ERR(
"ODP local init failed.\n");
3275 ODP_CACHE_LINE_SIZE, 0);
3278 ODPH_ERR(
"Shared mem reserve failed.\n");
3284 if (gbl_args == NULL) {
3285 ODPH_ERR(
"Shared mem addr failed.\n");
3288 gbl_args_init(gbl_args);
3291 parse_args(argc, argv, &gbl_args->appl);
3295 if (sched_mode(gbl_args->appl.in_mode))
3296 gbl_args->appl.sched_mode = 1;
3298 num_workers = MAX_WORKERS;
3299 if (gbl_args->appl.cpu_count && gbl_args->appl.cpu_count < MAX_WORKERS)
3300 num_workers = gbl_args->appl.cpu_count;
3304 (void)
odp_cpumask_to_str(&cpumask, gbl_args->cpumaskstr,
sizeof(gbl_args->cpumaskstr));
3306 gbl_args->appl.num_workers = num_workers;
3310 if (reserve_memcpy_memory(gbl_args))
3313 if_count = gbl_args->appl.if_count;
3316 if (gbl_args->appl.pool_per_if)
3317 num_pools = if_count;
3320 ODPH_ERR(
"Pool capability failed\n");
3325 ODPH_ERR(
"Too many pools %i\n", num_pools);
3329 pkt_len = gbl_args->appl.packet_len;
3333 printf(
"\nWarning: packet length reduced to %u\n\n", pkt_len);
3336 if (gbl_args->appl.seg_len == UINT32_MAX)
3337 seg_len = gbl_args->appl.packet_len;
3339 seg_len = gbl_args->appl.seg_len;
3352 if ((gbl_args->appl.seg_len != UINT32_MAX) && (seg_len != gbl_args->appl.seg_len))
3353 printf(
"\nWarning: Segment length requested %d configured %d\n",
3354 gbl_args->appl.seg_len, seg_len);
3356 if (seg_len < gbl_args->appl.data_rd * 8) {
3357 ODPH_ERR(
"Requested data read length %u exceeds maximum segment length %u\n",
3358 gbl_args->appl.data_rd * 8, seg_len);
3363 if (gbl_args->appl.num_pkt == 0)
3364 num_pkt = DEFAULT_NUM_PKT;
3366 num_pkt = gbl_args->appl.num_pkt;
3369 if (gbl_args->appl.num_pkt == 0) {
3371 printf(
"\nWarning: number of packets reduced to %u\n\n",
3374 ODPH_ERR(
"Too many packets %u. Maximum is %u.\n",
3380 gbl_args->num_pkt = num_pkt;
3381 gbl_args->pkt_len = pkt_len;
3382 gbl_args->seg_len = seg_len;
3384 printf(
"Resulting pool parameter values:\n");
3385 printf(
"Packets per pool: %u\n", num_pkt);
3386 printf(
"Packet length: %u\n", pkt_len);
3387 printf(
"Segment length: %u\n", seg_len);
3392 params.
pkt.
len = pkt_len;
3393 params.
pkt.
num = num_pkt;
3396 for (i = 0; i < num_pools; i++) {
3400 ODPH_ERR(
"Pool create failed %i\n", i);
3404 if (gbl_args->appl.verbose)
3408 num_vec_pools = create_vector_pools(gbl_args, &pool_capa, vec_pool_tbl);
3409 if (num_vec_pools < 0)
3421 ODPH_ERR(
"Schedule capability failed\n");
3425 if (gbl_args->appl.flow_aware) {
3429 ODPH_ERR(
"Flow aware mode not supported\n");
3434 num_groups = gbl_args->appl.num_groups;
3437 if (max_groups > MAX_GROUPS)
3438 max_groups = MAX_GROUPS;
3440 if (num_groups > max_groups) {
3441 ODPH_ERR(
"Too many groups. Maximum is %i.\n", max_groups);
3445 if (num_groups == -1)
3447 else if (num_groups == 0)
3451 ODPH_ERR(
"Schedule configuration failed\n");
3456 if (num_groups == 0) {
3459 }
else if (num_groups == -1) {
3463 create_groups(num_groups, group, &gbl_args->appl.cache_stash_config);
3467 vec_pool = vec_pool_tbl[0];
3469 printf(
"\nInterfaces\n----------\n");
3471 for (i = 0; i < if_count; ++i) {
3472 const char *dev = gbl_args->appl.if_names[i];
3477 num_rx = gbl_args->appl.rx_queues > 0 ? gbl_args->appl.rx_queues : num_workers;
3478 num_tx = num_workers;
3480 if (!gbl_args->appl.sched_mode) {
3482 num_rx = gbl_args->pktios[i].num_rx_thr;
3483 num_tx = gbl_args->pktios[i].num_tx_thr;
3487 grp = group[i % num_groups];
3489 if (gbl_args->appl.pool_per_if) {
3491 vec_pool = vec_pool_tbl[i];
3494 if (create_pktio(dev, i, num_rx, num_tx, pool, vec_pool, grp))
3498 if (gbl_args->appl.dst_change) {
3500 memset(&new_addr, 0,
sizeof(odph_ethaddr_t));
3501 if (gbl_args->appl.addr_count) {
3502 memcpy(&new_addr, &gbl_args->appl.addrs[i],
3503 sizeof(odph_ethaddr_t));
3505 new_addr.addr[0] = 0x02;
3506 new_addr.addr[5] = i;
3508 gbl_args->dst_eth_addr[i] = new_addr;
3516 init_port_lookup_tbl();
3518 if (!gbl_args->appl.sched_mode)
3519 print_port_mapping();
3524 if (gbl_args->appl.in_mode == DIRECT_RECV) {
3525 thr_run_func = run_worker_direct_mode;
3526 }
else if (gbl_args->appl.in_mode == PLAIN_QUEUE) {
3527 thr_run_func = run_worker_plain_queue_mode;
3529 if (gbl_args->appl.vector_mode == VECTOR_MODE_PACKET)
3530 thr_run_func = run_worker_sched_mode_vector;
3531 else if (gbl_args->appl.vector_mode == VECTOR_MODE_EVENT)
3532 thr_run_func = run_worker_sched_mode_event_vector;
3534 thr_run_func = run_worker_sched_mode;
3538 odph_thread_common_param_init(&thr_common);
3540 thr_common.instance = instance;
3541 thr_common.cpumask = &cpumask;
3544 thr_common.sync = 1;
3546 for (i = 0; i < num_workers; ++i) {
3549 int mode = gbl_args->appl.group_mode;
3551 init_state(&gbl_args->appl, &gbl_args->thread_args[i].state, i);
3552 odph_thread_param_init(&thr_param[i]);
3553 thr_param[i].start = thr_run_func;
3554 thr_param[i].arg = &gbl_args->thread_args[i];
3557 gbl_args->thread_args[i].num_grp_join = 0;
3558 gbl_args->thread_args[i].thr_idx = i;
3561 if (gbl_args->appl.num_groups > 0) {
3562 num_join = if_count < num_groups ? if_count : num_groups;
3564 if (mode == 0 || mode == 1) {
3567 num_join = num_groups;
3569 gbl_args->thread_args[i].num_grp_join = num_join;
3571 for (j = 0; j < num_join; j++)
3572 gbl_args->thread_args[i].group[j] = group[j];
3575 if (num_workers >= num_join) {
3576 gbl_args->thread_args[i].num_grp_join = 1;
3577 gbl_args->thread_args[i].group[0] = group[i % num_join];
3581 for (j = 0; i + j < num_join; j += num_workers) {
3582 gbl_args->thread_args[i].group[cnt] = group[i + j];
3586 gbl_args->thread_args[i].num_grp_join = cnt;
3591 stats[i] = &gbl_args->thread_args[i].stats;
3594 num_thr = odph_thread_create(gbl_args->thread_tbl, &thr_common,
3595 thr_param, num_workers);
3597 if (num_thr != num_workers) {
3598 ODPH_ERR(
"Worker create failed: %i\n", num_thr);
3602 if (gbl_args->appl.verbose)
3605 if (start_pktios(gbl_args))
3608 ret = print_speed_stats(num_workers, stats, gbl_args->appl.time,
3609 gbl_args->appl.accuracy);
3611 if (stop_pktios(gbl_args))
3615 if (gbl_args->appl.in_mode != DIRECT_RECV)
3618 odph_thread_join_result_t res[num_workers];
3621 if (odph_thread_join_result(gbl_args->thread_tbl, res, num_workers) != num_workers) {
3622 ODPH_ERR(
"Worker join failed\n");
3626 for (i = 0; i < num_workers; i++) {
3627 if (res[i].is_sig || res[i].ret != 0) {
3628 ODPH_ERR(
"Worker thread failure%s: %d\n", res[i].is_sig ?
3629 " (signaled)" :
"", res[i].ret);
3634 for (i = 0; i < if_count; ++i) {
3638 printf(
"Pktio %s extra statistics:\n", gbl_args->appl.if_names[i]);
3646 ODPH_ERR(
"Pktio close failed: %s\n", gbl_args->appl.if_names[i]);
3651 free(gbl_args->appl.if_names);
3652 free(gbl_args->appl.if_str);
3655 ODPH_ERR(
"Shared mem free failed\n");
3659 for (i = 0; i < gbl_args->appl.num_om; i++)
3660 free(gbl_args->appl.output_map[i]);
3665 for (i = 0; i < num_pools; i++) {
3667 ODPH_ERR(
"Pool destroy failed: %i\n", i);
3672 for (i = 0; i < num_vec_pools; i++) {
3674 ODPH_ERR(
"Vector pool destroy failed: %i\n", i);
3680 ODPH_ERR(
"Shm free failed\n");
3685 ODPH_ERR(
"Term local failed\n");
3690 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_vector_free(odp_event_vector_t evv)
Free event vector.
odp_event_vector_t odp_event_vector_from_event(odp_event_t ev)
Get event vector handle from event.
uint32_t odp_event_vector_tbl(odp_event_vector_t evv, odp_event_t **event_tbl)
Get event vector table.
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.
@ ODP_POOL_EVENT_VECTOR
Event vector 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.
void odp_schedule_group_param_init(odp_schedule_group_param_t *param)
Initialize schedule group parameters.
#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.
void odp_schedule_prefetch(int num)
Prefetch events for next schedule call.
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_2(const char *name, const odp_thrmask_t *mask, const odp_schedule_group_param_t *param)
Schedule group create with parameters.
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.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_INVALID
Invalid shared memory block.
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.
void odp_time_wait_ns(uint64_t ns)
Wait the specified number of nanoseconds.
odp_time_t odp_time_local(void)
Current local time.
Cache stashing configuration.
uint32_t event_data_l2
Enable/disable event_data L2 cache stashing.
uint32_t queue_context_l2
Enable/disable queue_context L2 cache stashing.
union odp_cache_stash_config_t::@161 regions
Region specific configuration toggle.
uint32_t event_metadata_l3
Enable/disable event_metadata L3 cache stashing.
uint32_t event_metadata_l2
Enable/disable event_metadata L2 cache stashing.
uint32_t queue_context_l3
Enable/disable queue_context L3 cache stashing.
odp_cache_stash_region_t event_user_area
Cache stashing for event user area.
uint32_t event_data_l3
Enable/disable event_data L3 cache stashing.
odp_cache_stash_region_t event_data
Cache stashing for event data.
uint32_t all
All bits of the bit field structure.
uint32_t event_user_area_l2
Enable/disable event_user_area L2 cache stashing.
odp_cache_stash_region_t event_metadata
Cache stashing for event metadata.
odp_cache_stash_region_t queue_context
Cache stashing for queue context region.
uint32_t event_user_area_l3
Enable/disable event_user_area L3 cache stashing.
Region specific cache stashing configuration.
uint32_t len
Length in bytes to cache.
struct odp_cache_stash_region_t::@160 l3
L3 cache stashing.
struct odp_cache_stash_region_t::@159 l2
L2 cache stashing.
uint32_t offset
Byte offset into a region to start caching from.
uint32_t max_size
Maximum number of events that can be aggregated into an event vector.
uint64_t min_tmo_ns
Minimum time in nanoseconds for an aggregator to form an event vector.
uint32_t min_size
Minimum number of events that can be aggregated into an event vector.
uint64_t max_tmo_ns
Maximum allowed value of odp_event_aggr_config_t::max_tmo_ns.
uint32_t max_num
Maximum number of event aggregators for this queue type.
Event vector configuration.
odp_event_type_t event_type
Event type.
uint64_t max_tmo_ns
Maximum time to wait for events.
uint32_t max_size
Maximum number of events in vector.
odp_pool_t pool
Event vector pool.
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'.
odp_pktio_config_t config
Supported pktio configuration options.
struct odp_pktio_capability_t::@115 maxlen
Supported frame lengths for odp_pktio_maxlen_set()
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.
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::@116 tx_compl
Supported packet Tx completion options.
uint32_t pause_tx
Generation of traditional Ethernet pause frames.
uint32_t pause_rx
Reception of traditional Ethernet pause frames.
struct odp_pktio_capability_t::@118 flow_control
Supported flow control modes.
Packet IO configuration options.
uint32_t max_compl_id
Maximum completion index.
struct odp_pktio_config_t::@111 tx_compl
Packet transmit completion configuration.
uint32_t mode_event
Enable packet transmit completion events.
odp_pktio_link_pause_t pause_tx
Transmission of flow control frames.
struct odp_pktio_config_t::@110 flow_control
Link flow control configuration.
odp_pktout_config_opt_t pktout
Packet output configuration options bit field.
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.
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.
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::@134 pkt
Packet pool capabilities
struct odp_pool_capability_t::@137 event_vector
Event vector pool capabilities.
uint32_t max_size
Maximum buffer data size in bytes.
struct odp_pool_capability_t::@136 vector
Vector pool capabilities.
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.
struct odp_pool_param_t::@139 pkt
Parameters for packet pools.
struct odp_pool_param_t::@142 event_vector
Parameters for event vector pools.
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::@141 vector
Parameters for vector pools.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
const odp_event_aggr_config_t * aggr
Event aggregator configuration parameters.
uint32_t num_aggr
Number of event aggregators.
uint32_t max_flow_id
Maximum flow ID per queue.
uint32_t max_groups
Maximum number of scheduling groups.
odp_event_aggr_capability_t aggr
Event aggregator capabilities for scheduled queues.
struct odp_schedule_config_t::@169 sched_group
Enable/disable predefined scheduling groups.
odp_schedule_group_param_t all_param
Parameters for ODP_SCHED_GROUP_ALL schedule group.
uint32_t max_flow_id
Maximum flow ID per queue.
odp_schedule_group_param_t worker_param
Parameters for ODP_SCHED_GROUP_WORKER schedule group.
Schedule group parameters.
odp_cache_stash_config_t common
Common group specific cache stashing hints.
struct odp_schedule_group_param_t::@165 cache_stash_hints
Group specific cache stashing hints.
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::@174 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::@108 bit
Option flags.
struct odp_pktin_hash_proto_t::@107 proto
Protocol header fields for hashing.
uint32_t ipv4_udp
IPv4 addresses and UDP port numbers.
struct odp_pktio_set_op_t::@112 op
Operation flags.
uint32_t maxlen
Maximum frame length.
uint32_t promisc_mode
Promiscuous mode.
struct odp_pktout_config_opt_t::@109 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.