28 #include <odp/helper/odph_api.h>
30 #define EXIT_NOT_SUP 2
31 #define PROG_NAME "odp_dmafwd"
40 #define DEF_CPY_TYPE SW_COPY
41 #define DEF_CNT 32768U
43 #define DEF_WORKERS 1U
47 #define MAX_OUT_QS 32U
49 #define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1)
51 #define DIV_IF(a, b) ((b) > 0U ? ((a) / (b)) : 0U)
54 ODP_STATIC_ASSERT(MAX_OUT_QS < UINT8_MAX,
"Too large maximum output queue count");
70 typedef struct prog_config_s prog_config_t;
77 uint64_t buf_alloc_errs;
78 uint64_t compl_alloc_errs;
79 uint64_t pkt_alloc_errs;
80 uint64_t trs_poll_errs;
86 uint64_t sched_rounds;
91 prog_config_t *prog_config;
102 typedef struct pktio_s {
119 odp_dma_seg_t *dst_segs, pktio_t *pktio, thread_config_t *config);
124 typedef void (*pkt_fn_t)(
odp_packet_t pkts[],
int num, pktio_t *pktio, init_fn_t init_fn,
125 start_fn_t start_fn, thread_config_t *config);
127 typedef void (*drain_fn_t)(thread_config_t *config);
129 typedef struct prog_config_s {
131 odph_thread_t thread_tbl[MAX_WORKERS];
132 thread_config_t thread_config[MAX_WORKERS];
133 pktio_t pktios[MAX_IFS];
134 dynamic_defs_t dyn_defs;
150 uint64_t inflight_obj_size;
155 uint32_t num_inflight;
156 uint32_t trs_cache_size;
157 uint32_t compl_cache_size;
158 uint32_t stash_cache_size;
172 static prog_config_t *prog_conf;
179 static void init_config(prog_config_t *config)
185 thread_config_t *thr;
187 memset(config, 0,
sizeof(*config));
191 burst_size = ODPH_MIN(burst_size, MAX_BURST);
192 config->dyn_defs.burst_size = burst_size;
196 config->dyn_defs.num_pkts = pool_capa.
pkt.
max_num > 0U ?
197 ODPH_MIN(pool_capa.
pkt.
max_num, DEF_CNT) : DEF_CNT;
198 config->dyn_defs.pkt_len = pool_capa.
pkt.
max_len > 0U ?
199 ODPH_MIN(pool_capa.
pkt.
max_len, DEF_LEN) : DEF_LEN;
207 config->burst_size = config->dyn_defs.burst_size;
208 config->num_pkts = config->dyn_defs.num_pkts;
209 config->pkt_len = config->dyn_defs.pkt_len;
210 config->cache_size = config->dyn_defs.cache_size;
211 config->time_sec = DEF_TIME;
212 config->num_thrs = DEF_WORKERS;
213 config->copy_type = DEF_CPY_TYPE;
215 for (
int i = 0; i < MAX_WORKERS; ++i) {
216 thr = &config->thread_config[i];
223 for (uint32_t i = 0U; i < MAX_IFS; ++i)
227 static void print_usage(dynamic_defs_t *dyn_defs)
230 "DMA performance tester with packet I/O. Receive and forward packets after\n"
231 "software copy or DMA offload copy.\n"
233 "Usage: " PROG_NAME
" OPTIONS\n"
235 " E.g. " PROG_NAME
" -i eth0\n"
236 " " PROG_NAME
" -i eth0 -t 0\n"
237 " " PROG_NAME
" -i eth0 -t 1 -b 15 -l 4096 -c 5\n"
239 "Mandatory OPTIONS:\n"
241 " -i, --interfaces Ethernet interfaces for packet I/O, comma-separated, no\n"
244 "Optional OPTIONS:\n"
246 " -t, --copy_type Type of copy. %u by default.\n"
248 " 1: DMA with event completion\n"
249 " 2: DMA with poll completion\n"
250 " -b, --burst_size Copy burst size. This many packets are accumulated before\n"
251 " copy. %u by default.\n"
252 " -n, --num_pkts Number of packet buffers allocated for packet I/O pool.\n"
254 " -l, --pkt_len Maximum size of packet buffers in packet I/O pool. %u by\n"
256 " -c, --worker_count Amount of workers. %u by default.\n"
257 " -C, --cache_size Maximum cache size for pools. %u by default.\n"
258 " -T, --time_sec Time in seconds to run. 0 means infinite. %u by default.\n"
259 " -h, --help This help.\n"
260 "\n", DEF_CPY_TYPE, dyn_defs->burst_size, dyn_defs->num_pkts, dyn_defs->pkt_len,
261 DEF_WORKERS, dyn_defs->cache_size, DEF_TIME);
264 static void parse_interfaces(prog_config_t *config,
const char *optarg)
266 char *tmp_str = strdup(optarg), *tmp;
271 tmp = strtok(tmp_str, DELIMITER);
273 while (tmp && config->num_ifs < MAX_IFS) {
274 config->pktios[config->num_ifs].name = strdup(tmp);
276 if (config->pktios[config->num_ifs].name != NULL)
279 tmp = strtok(NULL, DELIMITER);
300 static parse_result_t check_options(prog_config_t *config)
309 if (config->num_ifs == 0U) {
310 ODPH_ERR(
"Invalid number of interfaces: %u (min: 1, max: %u)\n", config->num_ifs,
315 if (config->copy_type != SW_COPY && config->copy_type != DMA_COPY_EV &&
316 config->copy_type != DMA_COPY_POLL) {
317 ODPH_ERR(
"Invalid copy type: %u\n", config->copy_type);
321 if (config->num_thrs <= 0 || config->num_thrs > MAX_WORKERS) {
322 ODPH_ERR(
"Invalid worker count: %d (min: 1, max: %d)\n", config->num_thrs,
328 ODPH_ERR(
"Error querying DMA capabilities\n");
332 if ((uint32_t)config->num_thrs > dma_capa.
max_sessions) {
333 ODPH_ERR(
"Unsupported DMA session count: %d (max: %u)\n", config->num_thrs,
339 burst_size = ODPH_MIN(burst_size, MAX_BURST);
341 if (config->burst_size == 0U || config->burst_size > burst_size) {
342 ODPH_ERR(
"Invalid segment count for DMA: %u (min: 1, max: %u)\n",
343 config->burst_size, burst_size);
348 ODPH_ERR(
"Invalid packet length for DMA: %u (max: %u)\n", config->pkt_len,
356 ODPH_ERR(
"Error querying pool capabilities\n");
362 ODPH_ERR(
"Invalid pool cache size: %u (min: %u, max: %u)\n", config->cache_size,
367 if (config->copy_type != SW_COPY)
368 config->trs_cache_size = ODPH_MIN(ODPH_MAX(config->cache_size,
372 if (config->copy_type == DMA_COPY_EV) {
375 ODPH_ERR(
"Unsupported DMA completion mode: event (mode support: %x, "
382 ODPH_ERR(
"Invalid amount of DMA completion pools: %d (max: %u)\n",
387 if (config->num_inflight > dma_capa.
pool.
max_num) {
388 ODPH_ERR(
"Invalid amount of DMA completion events: %u (max: %u)\n",
393 config->compl_cache_size = ODPH_MIN(ODPH_MAX(config->cache_size,
396 }
else if (config->copy_type == DMA_COPY_POLL) {
398 ODPH_ERR(
"Unsupported DMA completion mode: poll (mode support: %x)\n",
403 if (!get_stash_capa(&stash_capa, &config->stash_type)) {
404 ODPH_ERR(
"Error querying stash capabilities\n");
408 if ((uint32_t)config->num_thrs > stash_capa.
max_stashes) {
409 ODPH_ERR(
"Invalid amount of stashes: %d (max: %u)\n", config->num_thrs,
414 if (obj_size ==
sizeof(uint8_t)) {
416 }
else if (obj_size ==
sizeof(uint16_t)) {
418 }
else if (obj_size <=
sizeof(uint32_t)) {
420 }
else if (obj_size <=
sizeof(uint64_t)) {
425 ODPH_ERR(
"Invalid stash object size: %" PRIu64
"\n", obj_size);
429 if (config->num_inflight > max_num) {
430 ODPH_ERR(
"Invalid stash size: %u (max: %" PRIu64
")\n",
431 config->num_inflight, max_num);
435 config->inflight_obj_size = obj_size;
436 config->stash_cache_size = ODPH_MIN(config->cache_size, stash_capa.
max_cache_size);
439 if (config->num_pkts == 0U ||
441 ODPH_ERR(
"Invalid pool packet count: %u (min: 1, max: %u)\n", config->num_pkts,
446 if (config->pkt_len == 0U ||
448 ODPH_ERR(
"Invalid pool packet length: %u (min: 1, max: %u)\n", config->pkt_len,
453 if (config->num_inflight > pool_capa.
buf.
max_num) {
454 ODPH_ERR(
"Invalid pool buffer count: %u (max: %u)\n", config->num_inflight,
462 static parse_result_t parse_options(
int argc,
char **argv, prog_config_t *config)
466 static const struct option longopts[] = {
467 {
"interfaces", required_argument, NULL,
'i' },
468 {
"copy_type", required_argument, NULL,
't' },
469 {
"burst_size", required_argument, NULL,
'b' },
470 {
"num_pkts", required_argument, NULL,
'n' },
471 {
"pkt_len", required_argument, NULL,
'l' },
472 {
"worker_count", required_argument, NULL,
'c' },
473 {
"cache_size", required_argument, NULL,
'C' },
474 {
"time_sec", required_argument, NULL,
'T' },
475 {
"help", no_argument, NULL,
'h' },
479 static const char *shortopts =
"i:t:b:n:l:c:C:T:h";
484 opt = getopt_long(argc, argv, shortopts, longopts, NULL);
491 parse_interfaces(config, optarg);
494 config->copy_type = atoi(optarg);
497 config->burst_size = atoi(optarg);
500 config->num_pkts = atoi(optarg);
503 config->pkt_len = atoi(optarg);
506 config->num_thrs = atoi(optarg);
509 config->cache_size = atoi(optarg);
512 config->time_sec = atof(optarg);
515 print_usage(&config->dyn_defs);
519 print_usage(&config->dyn_defs);
524 return check_options(config);
527 static parse_result_t setup_program(
int argc,
char **argv, prog_config_t *config)
529 struct sigaction action = { .sa_handler = terminate };
531 if (sigemptyset(&action.sa_mask) == -1 || sigaddset(&action.sa_mask, SIGINT) == -1 ||
532 sigaddset(&action.sa_mask, SIGTERM) == -1 ||
533 sigaddset(&action.sa_mask, SIGHUP) == -1 || sigaction(SIGINT, &action, NULL) == -1 ||
534 sigaction(SIGTERM, &action, NULL) == -1 || sigaction(SIGHUP, &action, NULL) == -1) {
535 ODPH_ERR(
"Error installing signal handler\n");
539 return parse_options(argc, argv, config);
547 ret = ret < 0 ? 0 : ret;
554 static void sw_copy_and_send_packets(
odp_packet_t pkts[],
int num, pktio_t *pktio,
556 thread_config_t *config)
561 int num_out_pkts = 0, num_sent;
562 stats_t *stats = &config->stats;
564 for (
int i = 0; i < num; ++i) {
569 out_pkts[num_out_pkts++] = new_pkt;
576 if (num_out_pkts > 0) {
577 num_sent = send_packets(pktio->out_qs[config->thr_idx % pktio->num_out_qs],
578 out_pkts, num_out_pkts);
579 stats->fwd_pkts += num_sent;
580 stats->discards += num_out_pkts - num_sent;
587 thread_config_t *config)
590 stats_t *stats = &config->stats;
597 ++stats->buf_alloc_errs;
615 ++stats->compl_alloc_errs;
620 compl_param->
queue = config->compl_q;
622 memset(src_segs, 0,
sizeof(*src_segs) * MAX_BURST);
623 memset(dst_segs, 0,
sizeof(*dst_segs) * MAX_BURST);
631 thread_config_t *config)
634 stats_t *stats = &config->stats;
640 ++stats->buf_alloc_errs;
658 ++stats->compl_alloc_errs;
663 memset(src_segs, 0,
sizeof(*src_segs) * MAX_BURST);
664 memset(dst_segs, 0,
sizeof(*dst_segs) * MAX_BURST);
696 ODPH_ABORT(
"DMA inflight transfer stash overflow, aborting");
701 static void dma_copy(
odp_packet_t pkts[],
int num, pktio_t *pktio, init_fn_t init_fn,
702 start_fn_t start_fn, thread_config_t *config)
707 transfer_t *trs = NULL;
709 uint32_t num_segs = 0U, pkt_len;
711 stats_t *stats = &config->stats;
716 for (
int i = 0; i < num; ++i) {
720 trs = init_fn(&trs_param, &compl_param, src_segs, dst_segs, pktio, config);
729 src_segs[num_segs].
packet = pkt;
730 src_segs[num_segs].
len = pkt_len;
735 ++stats->pkt_alloc_errs;
739 dst_segs[num_segs].
len = pkt_len;
740 trs->src_pkts[num_segs] = src_segs[num_segs].
packet;
741 trs->dst_pkts[num_segs] = dst_segs[num_segs].
packet;
749 if (
odp_unlikely(!start_fn(&trs_param, &compl_param, config))) {
756 static void drain_events(thread_config_t *config
ODP_UNUSED)
772 if (type == ODP_EVENT_DMA_COMPL) {
773 memset(&res, 0,
sizeof(res));
786 static void drain_polled(thread_config_t *config)
798 memset(&res, 0,
sizeof(res));
817 static odp_bool_t setup_copy(prog_config_t *config)
820 thread_config_t *thr;
833 pool_param.
pkt.
len = config->pkt_len;
834 pool_param.
pkt.
num = config->num_pkts;
840 ODPH_ERR(
"Error creating packet copy pool\n");
844 if (config->copy_type == SW_COPY) {
845 config->pkt_fn = sw_copy_and_send_packets;
847 for (
int i = 0; i < config->num_thrs; ++i)
848 config->thread_config[i].copy_pool = config->copy_pool;
853 pool_param.
buf.
num = config->num_inflight;
854 pool_param.
buf.
size =
sizeof(transfer_t);
860 ODPH_ERR(
"Error creating DMA transfer tracking pool\n");
864 for (
int i = 0; i < config->num_thrs; ++i) {
865 thr = &config->thread_config[i];
866 thr->copy_pool = config->copy_pool;
867 thr->trs_pool = config->trs_pool;
871 ODPH_ERR(
"Error creating DMA session\n");
875 if (config->copy_type == DMA_COPY_EV) {
877 compl_pool_param.
num = config->num_inflight;
878 compl_pool_param.
cache_size = config->compl_cache_size;
883 ODPH_ERR(
"Error creating DMA event completion pool\n");
894 ODPH_ERR(
"Error creating DMA completion queue\n");
898 config->init_fn = init_dma_ev_trs;
899 config->start_fn = start_dma_ev_trs;
900 config->drain_fn = drain_events;
903 stash_param.
type = config->stash_type;
906 stash_param.
num_obj = config->num_inflight;
907 stash_param.
obj_size = config->inflight_obj_size;
908 stash_param.
cache_size = config->stash_cache_size;
912 ODPH_ERR(
"Error creating DMA inflight transfer stash\n");
916 config->init_fn = init_dma_poll_trs;
917 config->start_fn = start_dma_poll_trs;
918 config->drain_fn = drain_polled;
922 config->pkt_fn = dma_copy;
927 static odp_bool_t setup_pktios(prog_config_t *config)
933 uint32_t num_input_qs, num_output_qs;
939 pool_param.
pkt.
len = config->pkt_len;
940 pool_param.
pkt.
num = config->num_pkts;
946 ODPH_ERR(
"Error creating packet I/O pool\n");
950 for (uint32_t i = 0U; i < config->num_ifs; ++i) {
951 pktio = &config->pktios[i];
955 pktio->handle =
odp_pktio_open(pktio->name, config->pktio_pool, &pktio_param);
958 ODPH_ERR(
"Error opening packet I/O (%s)\n", pktio->name);
965 ODPH_ERR(
"Error querying packet I/O capabilities (%s)\n", pktio->name);
971 num_output_qs = ODPH_MIN(num_output_qs, MAX_OUT_QS);
974 if (num_input_qs > 1) {
983 ODPH_ERR(
"Error configuring packet I/O input queues (%s)\n", pktio->name);
989 if (num_output_qs == (uint32_t)config->num_thrs)
993 pktio->num_out_qs = num_output_qs;
996 ODPH_ERR(
"Error configuring packet I/O output queues (%s)\n", pktio->name);
1001 (
int)num_output_qs) {
1002 ODPH_ERR(
"Error querying packet I/O output queues (%s)\n", pktio->name);
1007 ODPH_ERR(
"Error starting packet I/O (%s)\n", pktio->name);
1015 static inline void send_dma_poll_trs_pkts(
int burst_size, thread_config_t *config)
1017 odp_stash_t stash_handle = config->inflight_stash;
1020 odp_dma_t dma_handle = config->dma_handle;
1027 stats_t *stats = &config->stats;
1035 for (int32_t i = 0; i < num; ++i) {
1043 ODPH_ABORT(
"DMA inflight transfer stash overflow,"
1046 ++stats->trs_polled;
1053 ++stats->trs_poll_errs;
1062 num_sent = send_packets(pktio->out_qs[config->thr_idx %
1064 trs->dst_pkts, trs->num);
1066 stats->fwd_pkts += num_sent;
1067 stats->discards += trs->num - num_sent;
1079 static inline void send_dma_ev_trs_pkts(
odp_dma_compl_t compl_ev, thread_config_t *config)
1086 stats_t *stats = &config->stats;
1088 memset(&res, 0,
sizeof(res));
1095 num_sent = send_packets(pktio->out_qs[config->thr_idx % pktio->num_out_qs],
1096 trs->dst_pkts, trs->num);
1098 stats->fwd_pkts += num_sent;
1099 stats->discards += trs->num - num_sent;
1110 static inline void push_packet(
odp_packet_t pkt, pkt_vec_t pkt_vecs[], uint8_t *pktio_idx_map)
1113 pkt_vec_t *pkt_vec = &pkt_vecs[idx];
1115 pkt_vec->pkts[pkt_vec->num++] = pkt;
1118 static inline void pop_packets(pkt_vec_t *pkt_vec,
int num_procd)
1120 pkt_vec->num -= num_procd;
1122 for (
int i = 0, j = num_procd; i < pkt_vec->num; ++i, ++j)
1123 pkt_vec->pkts[i] = pkt_vec->pkts[j];
1126 static void free_pending_packets(pkt_vec_t pkt_vecs[], uint32_t num_ifs, stats_t *stats)
1128 for (uint32_t i = 0U; i < num_ifs; ++i) {
1129 stats->pkt_cleanup += pkt_vecs[i].num;
1134 static int process_packets(
void *args)
1136 thread_config_t *config = args;
1137 const uint8_t num_ifs = config->prog_config->num_ifs;
1138 pkt_vec_t pkt_vecs[num_ifs], *pkt_vec;
1140 uint64_t c1, c2, c3, c4, cdiff = 0U, rounds = 0U;
1141 const uint8_t copy_type = config->prog_config->copy_type;
1142 const int burst_size = config->prog_config->burst_size;
1147 uint8_t *pktio_map = config->prog_config->pktio_idx_map;
1148 stats_t *stats = &config->stats;
1149 init_fn_t init_fn = config->prog_config->init_fn;
1150 start_fn_t start_fn = config->prog_config->start_fn;
1151 pkt_fn_t pkt_fn = config->prog_config->pkt_fn;
1153 for (uint32_t i = 0U; i < num_ifs; ++i) {
1154 pkt_vecs[i].pktio = &config->prog_config->pktios[i];
1155 pkt_vecs[i].num = 0;
1169 if (copy_type == DMA_COPY_POLL)
1170 send_dma_poll_trs_pkts(burst_size, config);
1175 for (
int i = 0; i < num_evs; ++i) {
1179 if (type == ODP_EVENT_DMA_COMPL) {
1181 }
else if (type == ODP_EVENT_PACKET) {
1189 for (uint32_t i = 0U; i < num_ifs; ++i) {
1190 pkt_vec = &pkt_vecs[i];
1192 if (pkt_vec->num >= burst_size) {
1193 pkt_fn(pkt_vec->pkts, burst_size, pkt_vec->pktio, init_fn,
1195 pop_packets(pkt_vec, burst_size);
1201 stats->sched_cc = cdiff;
1203 stats->sched_rounds = rounds;
1204 free_pending_packets(pkt_vecs, num_ifs, stats);
1207 if (config->prog_config->drain_fn)
1208 config->prog_config->drain_fn(config);
1213 static odp_bool_t setup_workers(prog_config_t *config)
1217 odph_thread_common_param_t thr_common;
1218 odph_thread_param_t thr_param[config->num_thrs];
1221 odph_thread_common_param_init(&thr_common);
1222 thr_common.instance = config->odp_instance;
1223 thr_common.cpumask = &cpumask;
1225 for (
int i = 0; i < config->num_thrs; ++i) {
1226 odph_thread_param_init(&thr_param[i]);
1227 thr_param[i].start = process_packets;
1229 config->thread_config[i].prog_config = config;
1230 thr_param[i].arg = &config->thread_config[i];
1233 num_workers = odph_thread_create(config->thread_tbl, &thr_common, thr_param, num_workers);
1235 if (num_workers != config->num_thrs) {
1236 ODPH_ERR(
"Error configuring worker threads\n");
1243 static odp_bool_t setup_test(prog_config_t *config)
1248 if (!setup_copy(config))
1251 if (!setup_pktios(config))
1254 if (!setup_workers(config))
1262 static void stop_test(prog_config_t *config)
1264 for (uint32_t i = 0U; i < config->num_ifs; ++i)
1269 (void)odph_thread_join(config->thread_tbl, config->num_thrs);
1272 static void teardown(prog_config_t *config)
1274 thread_config_t *thr;
1276 for (uint32_t i = 0U; i < config->num_ifs; ++i) {
1277 free(config->pktios[i].name);
1286 for (
int i = 0; i < config->num_thrs; ++i) {
1287 thr = &config->thread_config[i];
1309 static void print_stats(
const prog_config_t *config)
1311 const stats_t *stats;
1312 const char *align1 = config->copy_type == DMA_COPY_EV ?
" " :
"";
1313 const char *align2 = config->copy_type == SW_COPY ?
" " :
1314 config->copy_type == DMA_COPY_EV ?
" " :
1317 printf(
"\n==================\n\n"
1318 "DMA forwarder done\n\n"
1321 " packet length: %u\n"
1322 " max cache size: %u\n", config->copy_type == SW_COPY ?
"SW" :
1323 config->copy_type == DMA_COPY_EV ?
"DMA-event" :
"DMA-poll",
1324 config->burst_size, config->pkt_len, config->cache_size);
1326 for (
int i = 0; i < config->num_thrs; ++i) {
1327 stats = &config->thread_config[i].stats;
1329 printf(
"\n worker %d:\n", i);
1331 if (config->copy_type == SW_COPY) {
1332 printf(
" packet copy errors: %" PRIu64
"\n",
1335 printf(
" successful DMA transfers: %s%" PRIu64
"\n"
1336 " DMA transfer start errors: %s%" PRIu64
"\n"
1337 " DMA transfer errors: %s%" PRIu64
"\n"
1338 " transfer buffer allocation errors: %s%" PRIu64
"\n"
1339 " copy packet allocation errors: %s%" PRIu64
"\n",
1340 align1, stats->trs, align1, stats->start_errs, align1,
1341 stats->trs_errs, align1, stats->buf_alloc_errs, align1,
1342 stats->pkt_alloc_errs);
1344 if (config->copy_type == DMA_COPY_EV)
1345 printf(
" completion event allocation errors: %" PRIu64
"\n",
1346 stats->compl_alloc_errs);
1348 printf(
" transfer ID allocation errors: %" PRIu64
"\n"
1349 " transfer poll errors: %" PRIu64
"\n"
1350 " transfers polled: %" PRIu64
"\n",
1351 stats->compl_alloc_errs, stats->trs_poll_errs,
1355 printf(
" packets forwarded:%s%" PRIu64
"\n"
1356 " packets dropped: %s%" PRIu64
"\n"
1357 " packets cleanup: %s%" PRIu64
"\n"
1358 " call cycles per schedule round:\n"
1359 " total: %" PRIu64
"\n"
1360 " schedule: %" PRIu64
"\n"
1361 " rounds: %" PRIu64
"\n", align2, stats->fwd_pkts, align2,
1362 stats->discards, align2, stats->pkt_cleanup, DIV_IF(stats->tot_cc,
1363 stats->sched_rounds), DIV_IF(stats->sched_cc, stats->sched_rounds),
1364 stats->sched_rounds);
1367 printf(
"\n==================\n");
1370 int main(
int argc,
char **argv)
1372 odph_helper_options_t odph_opts;
1376 int ret = EXIT_SUCCESS;
1377 parse_result_t parse_res;
1379 argc = odph_parse_options(argc, argv);
1381 if (odph_options(&odph_opts) == -1) {
1382 ODPH_ERR(
"Error while reading ODP helper options, exiting\n");
1387 init_param.
mem_model = odph_opts.mem_model;
1390 ODPH_ERR(
"ODP global init failed, exiting\n");
1395 ODPH_ERR(
"ODP local init failed, exiting\n");
1399 shm_cfg =
odp_shm_reserve(PROG_NAME
"_cfg",
sizeof(prog_config_t), ODP_CACHE_LINE_SIZE,
1403 ODPH_ERR(
"Error reserving shared memory\n");
1410 if (prog_conf == NULL) {
1411 ODPH_ERR(
"Error resolving shared memory address\n");
1416 parse_res = setup_program(argc, argv, prog_conf);
1418 if (parse_res == PRS_NOK) {
1423 if (parse_res == PRS_TERM) {
1428 if (parse_res == PRS_NOT_SUP) {
1434 ODPH_ERR(
"Error configuring scheduler\n");
1442 if (!setup_test(prog_conf)) {
1447 if (prog_conf->time_sec > 0.001) {
1450 ts.tv_sec = prog_conf->time_sec;
1452 nanosleep(&ts, NULL);
1459 stop_test(prog_conf);
1460 print_stats(prog_conf);
1463 teardown(prog_conf);
1470 ODPH_ERR(
"ODP local terminate failed, exiting\n");
1475 ODPH_ERR(
"ODP global terminate failed, exiting\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_barrier_wait(odp_barrier_t *barr)
Synchronize thread execution on barrier.
odp_buffer_t odp_buffer_alloc(odp_pool_t pool)
Buffer alloc.
void odp_buffer_free(odp_buffer_t buf)
Buffer free.
void * odp_buffer_addr(odp_buffer_t buf)
Buffer start address.
_odp_abi_buffer_t * odp_buffer_t
ODP buffer.
#define ODP_BUFFER_INVALID
Invalid buffer.
#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.
uint64_t odp_cpu_cycles_diff(uint64_t c2, uint64_t c1)
CPU cycle count difference.
uint64_t odp_cpu_cycles(void)
Current CPU cycle count.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
odp_dma_t odp_dma_create(const char *name, const odp_dma_param_t *param)
Create DMA session.
odp_pool_t odp_dma_pool_create(const char *name, const odp_dma_pool_param_t *pool_param)
Create DMA completion event pool.
int odp_dma_transfer_done(odp_dma_t dma, odp_dma_transfer_id_t transfer_id, odp_dma_result_t *result)
Check if DMA transfer has completed.
#define ODP_DMA_TYPE_COPY
Copy data.
void odp_dma_transfer_id_free(odp_dma_t dma, odp_dma_transfer_id_t transfer_id)
Free DMA transfer identifier.
#define ODP_DMA_COMPL_EVENT
Asynchronous transfer with completion event.
void odp_dma_transfer_param_init(odp_dma_transfer_param_t *trs_param)
Initialize DMA transfer parameters.
int odp_dma_destroy(odp_dma_t dma)
Destroy DMA session.
int odp_dma_compl_result(odp_dma_compl_t dma_compl, odp_dma_result_t *result)
Check DMA completion event.
void odp_dma_compl_param_init(odp_dma_compl_param_t *compl_param)
Initialize DMA transfer completion parameters.
#define ODP_DMA_TRANSFER_ID_INVALID
Invalid DMA transfer identifier.
#define ODP_DMA_COMPL_INVALID
Invalid DMA completion event.
odp_event_t odp_dma_compl_to_event(odp_dma_compl_t dma_compl)
Convert DMA completion event to event.
void odp_dma_pool_param_init(odp_dma_pool_param_t *pool_param)
Initialize DMA completion event pool parameters.
int odp_dma_transfer_start(odp_dma_t dma, const odp_dma_transfer_param_t *trs_param, const odp_dma_compl_param_t *compl_param)
Start DMA transfer.
uint64_t odp_dma_transfer_id_t
DMA transfer identifier.
odp_dma_compl_t odp_dma_compl_from_event(odp_event_t ev)
Convert event to DMA completion event.
#define ODP_DMA_MAIN_TO_MAIN
DMA transfer within the main memory.
int odp_dma_capability(odp_dma_capability_t *capa)
Query DMA capabilities.
odp_dma_transfer_id_t odp_dma_transfer_id_alloc(odp_dma_t dma)
Allocate DMA transfer identifier.
void odp_dma_compl_free(odp_dma_compl_t dma_compl)
Free DMA completion event.
#define ODP_DMA_INVALID
Invalid DMA session.
#define ODP_DMA_COMPL_POLL
Asynchronous transfer with completion polling.
odp_dma_compl_t odp_dma_compl_alloc(odp_pool_t pool)
Allocate DMA completion event.
@ ODP_DMA_MT_SERIAL
Application serializes operations.
@ ODP_DMA_FORMAT_PACKET
Data format is odp_packet_t.
@ ODP_DMA_ORDER_NONE
No specific ordering between transfers.
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.
odp_event_type_t
Event type.
#define ODP_EVENT_INVALID
Invalid event.
int odp_instance(odp_instance_t *instance)
Get instance handle.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
#define ODP_STATIC_ASSERT(cond, msg)
Compile time assertion macro.
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.
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_close(odp_pktio_t pktio)
Close a packet IO interface.
int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num)
Direct packet output queues.
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_start(odp_pktio_t pktio)
Start packet receive and transmit.
#define ODP_PKTIO_INVALID
Invalid packet IO handle.
void odp_pktout_queue_param_init(odp_pktout_queue_param_t *param)
Initialize packet output queue parameters.
int odp_pktio_stop(odp_pktio_t pktio)
Stop packet receive and transmit.
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.
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_DIRECT
Direct packet output on the interface.
@ ODP_PKTIO_OP_MT_UNSAFE
Not multithread safe operation.
@ ODP_PKTIN_MODE_SCHED
Packet input through scheduler and scheduled event queues.
int odp_packet_input_index(odp_packet_t pkt)
Packet input interface index.
odp_packet_t odp_packet_copy(odp_packet_t pkt, odp_pool_t pool)
Full copy of a packet.
uint32_t odp_packet_len(odp_packet_t pkt)
Packet data length.
odp_packet_t odp_packet_alloc(odp_pool_t pool, uint32_t len)
Allocate a packet from a packet pool.
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.
#define ODP_PACKET_INVALID
Invalid packet.
void odp_packet_free_multi(const odp_packet_t pkt[], int num)
Free multiple packets.
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()
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_BUFFER
Buffer pool.
@ ODP_POOL_PACKET
Packet pool.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
#define ODP_QUEUE_INVALID
Invalid 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.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
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_default_prio(void)
Default scheduling priority level.
int odp_schedule_max_prio(void)
Maximum scheduling priority level.
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.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
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.
odp_stash_type_t
Stash types.
#define ODP_STASH_INVALID
Invalid stash handle.
int32_t odp_stash_put(odp_stash_t stash, const void *obj, int32_t num)
Put object handles into a stash.
void odp_stash_param_init(odp_stash_param_t *param)
Initialize stash params.
int32_t odp_stash_get(odp_stash_t stash, void *obj, int32_t num)
Get object handles from a stash.
int odp_stash_destroy(odp_stash_t stash)
Destroy a stash.
int odp_stash_capability(odp_stash_capability_t *capa, odp_stash_type_t type)
Query stash capabilities.
odp_stash_t odp_stash_create(const char *name, const odp_stash_param_t *param)
Create a stash.
@ ODP_STASH_TYPE_DEFAULT
The default stash type.
@ ODP_STASH_TYPE_FIFO
Stash type FIFO.
@ ODP_STASH_OP_LOCAL
Thread local operation.
bool odp_bool_t
Boolean type.
int odp_thread_id(void)
Get thread identifier.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
#define ODP_TIME_SEC_IN_NS
A second in nanoseconds.
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
uint32_t max_sessions
Maximum number of DMA sessions.
uint32_t max_transfers
Maximum number of transfers per DMA session.
odp_dma_pool_capability_t pool
DMA completion event pool capabilities.
uint32_t max_dst_segs
Maximum number of destination segments in a single transfer.
uint32_t max_src_segs
Maximum number of source segments in a single transfer.
odp_bool_t queue_type_sched
Scheduled queue support.
odp_dma_compl_mode_t compl_mode_mask
Supported completion modes.
uint32_t max_seg_len
Maximum segment length in bytes.
DMA transfer completion parameters.
odp_dma_transfer_id_t transfer_id
Transfer identifier.
void * user_ptr
User context pointer.
odp_event_t event
Completion event.
odp_dma_compl_mode_t compl_mode
Completion mode.
odp_queue_t queue
Completion queue.
odp_dma_direction_t direction
Transfer direction.
uint32_t min_cache_size
Minimum size of thread local cache.
uint32_t max_cache_size
Maximum size of thread local cache.
uint32_t max_pools
Maximum number of DMA completion event pools.
uint32_t max_num
Maximum number of DMA completion events in a pool.
DMA completion event pool parameters.
uint32_t cache_size
Maximum number of events cached locally per thread.
uint32_t num
Number of DMA completion events in the pool.
void * user_ptr
User context pointer.
odp_bool_t success
DMA transfer success.
odp_packet_t packet
Packet handle.
uint32_t len
Segment length in bytes.
odp_dma_seg_t * dst_seg
Table of destination segments.
odp_dma_data_format_t dst_format
Destination data format.
uint32_t num_dst
Number of destination segments.
uint32_t num_src
Number of source segments.
odp_dma_seg_t * src_seg
Table of source segments.
odp_dma_data_format_t src_format
Source data format.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
Packet input queue parameters.
uint32_t num_queues
Number of input queues to be created.
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.
uint32_t max_input_queues
Maximum number of input queues.
uint32_t max_output_queues
Maximum number of output queues.
odp_pktin_mode_t in_mode
Packet input mode.
odp_pktout_mode_t out_mode
Packet output mode.
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::@121 buf
Buffer pool capabilities
struct odp_pool_capability_t::@122 pkt
Packet pool capabilities
uint32_t max_num
Maximum number of buffers of any size.
uint32_t min_cache_size
Minimum size of thread local cache.
uint32_t max_cache_size
Maximum size of thread local cache.
uint32_t max_len
Maximum packet data length in bytes.
uint32_t num
Number of buffers in the pool.
uint32_t cache_size
Maximum number of buffers cached locally per thread.
uint32_t size
Minimum buffer size in bytes.
odp_pool_type_t type
Pool type.
uint32_t len
Minimum length of 'num' packets.
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::@125 buf
Parameters for buffer pools.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
Stash capabilities (per stash type)
struct odp_stash_capability_t::@145 max_num
Maximum number of object handles per stash for each object size.
uint64_t u16
Maximum number of 2 byte object handles.
uint64_t u128
Maximum number of 16 byte object handles.
uint32_t max_stashes
Maximum number of stashes of this type.
uint64_t u64
Maximum number of 8 byte object handles.
uint32_t max_cache_size
Maximum size of thread local cache.
uint64_t u32
Maximum number of 4 byte object handles.
uint64_t u8
Maximum number of 1 byte object handles.
uint32_t cache_size
Maximum number of object handles cached locally per thread.
odp_stash_op_mode_t get_mode
Get operation mode.
uint32_t obj_size
Object handle size in bytes.
odp_stash_type_t type
Stash type.
odp_stash_op_mode_t put_mode
Put operation mode.
uint64_t num_obj
Number of object handles.
128-bit unsigned integer structure
struct odp_pktin_hash_proto_t::@99 proto
Protocol header fields for hashing.
uint32_t ipv4
IPv4 addresses.