static int test_init(void) { odp_pool_param_t params; odp_queue_param_t qparam; odp_queue_t inq_def; char inq_name[ODP_QUEUE_NAME_LEN]; memset(¶ms, 0, sizeof(params)); params.pkt.len = PKT_HDR_LEN + gbl_args->args.pkt_len; params.pkt.seg_len = params.pkt.len; params.pkt.num = PKT_BUF_NUM; params.type = ODP_POOL_PACKET; transmit_pkt_pool = odp_pool_create("pkt_pool_transmit", ODP_SHM_NULL, ¶ms); if (transmit_pkt_pool == ODP_POOL_INVALID) LOG_ABORT("Failed to create transmit pool\n"); odp_atomic_init_u32(&ip_seq, 0); odp_atomic_init_u32(&shutdown, 0); /* create pktios and associate input/output queues */ gbl_args->pktio_tx = create_pktio(gbl_args->args.ifaces[0]); if (gbl_args->args.num_ifaces > 1) gbl_args->pktio_rx = create_pktio(gbl_args->args.ifaces[1]); else gbl_args->pktio_rx = gbl_args->pktio_tx; if (gbl_args->pktio_rx == ODP_PKTIO_INVALID || gbl_args->pktio_tx == ODP_PKTIO_INVALID) { LOG_ERR("failed to open pktio\n"); return -1; } /* create and associate an input queue for the RX side */ qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; qparam.sched.sync = ODP_SCHED_SYNC_NONE; qparam.sched.group = ODP_SCHED_GROUP_DEFAULT; snprintf(inq_name, sizeof(inq_name), "inq-pktio-%" PRIu64, odp_pktio_to_u64(gbl_args->pktio_rx)); inq_def = odp_queue_lookup(inq_name); if (inq_def == ODP_QUEUE_INVALID) inq_def = odp_queue_create(inq_name, ODP_QUEUE_TYPE_PKTIN, &qparam); if (inq_def == ODP_QUEUE_INVALID) return -1; if (odp_pktio_inq_setdef(gbl_args->pktio_rx, inq_def) != 0) return -1; return 0; }
void pktio_test_recv_on_wonly(void) { odp_pktio_t pktio; odp_packet_t pkt; int ret; pktio = create_pktio(0, ODP_PKTIN_MODE_DISABLED, ODP_PKTOUT_MODE_SEND); if (pktio == ODP_PKTIO_INVALID) { CU_FAIL("failed to open pktio"); return; } ret = odp_pktio_start(pktio); CU_ASSERT_FATAL(ret == 0); ret = odp_pktio_recv(pktio, &pkt, 1); CU_ASSERT(ret < 0); if (ret > 0) odp_packet_free(pkt); ret = odp_pktio_stop(pktio); CU_ASSERT_FATAL(ret == 0); ret = odp_pktio_close(pktio); CU_ASSERT_FATAL(ret == 0); }
void pktio_test_inq_remdef(void) { odp_pktio_t pktio; odp_queue_t inq; odp_event_t ev; uint64_t wait; int i; pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED, ODP_PKTOUT_MODE_SEND); CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID); CU_ASSERT(create_inq(pktio, ODP_QUEUE_TYPE_POLL) == 0); inq = odp_pktio_inq_getdef(pktio); CU_ASSERT(inq != ODP_QUEUE_INVALID); CU_ASSERT(odp_pktio_inq_remdef(pktio) == 0); wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS); for (i = 0; i < 100; i++) { ev = odp_schedule(NULL, wait); if (ev != ODP_EVENT_INVALID) { odp_event_free(ev); CU_FAIL("received unexpected event"); } } CU_ASSERT(odp_queue_destroy(inq) == 0); CU_ASSERT(odp_pktio_close(pktio) == 0); }
void pktio_test_promisc(void) { int ret; odp_pktio_t pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED, ODP_PKTOUT_MODE_SEND); CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID); ret = odp_pktio_promisc_mode_set(pktio, 1); CU_ASSERT(0 == ret); /* Verify that promisc mode set */ ret = odp_pktio_promisc_mode(pktio); CU_ASSERT(1 == ret); ret = odp_pktio_promisc_mode_set(pktio, 0); CU_ASSERT(0 == ret); /* Verify that promisc mode is not set */ ret = odp_pktio_promisc_mode(pktio); CU_ASSERT(0 == ret); ret = odp_pktio_close(pktio); CU_ASSERT(ret == 0); }
void pktio_test_mac(void) { unsigned char mac_addr[ODPH_ETHADDR_LEN]; int mac_len; int ret; odp_pktio_t pktio; pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED, ODP_PKTOUT_MODE_SEND); CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID); printf("testing mac for %s\n", iface_name[0]); mac_len = odp_pktio_mac_addr(pktio, mac_addr, sizeof(mac_addr)); CU_ASSERT(ODPH_ETHADDR_LEN == mac_len); printf(" %X:%X:%X:%X:%X:%X ", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); /* Fail case: wrong addr_size. Expected <0. */ mac_len = odp_pktio_mac_addr(pktio, mac_addr, 2); CU_ASSERT(mac_len < 0); ret = odp_pktio_close(pktio); CU_ASSERT(0 == ret); }
void pktio_test_send_on_ronly(void) { odp_pktio_t pktio; odp_packet_t pkt; int ret; pktio = create_pktio(0, ODP_PKTIN_MODE_RECV, ODP_PKTOUT_MODE_DISABLED); if (pktio == ODP_PKTIO_INVALID) { CU_FAIL("failed to open pktio"); return; } ret = odp_pktio_start(pktio); CU_ASSERT_FATAL(ret == 0); pkt = odp_packet_alloc(default_pkt_pool, packet_len); CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID) pktio_init_packet(pkt); ret = odp_pktio_send(pktio, &pkt, 1); CU_ASSERT(ret < 0); if (ret <= 0) odp_packet_free(pkt); ret = odp_pktio_stop(pktio); CU_ASSERT_FATAL(ret == 0); ret = odp_pktio_close(pktio); CU_ASSERT_FATAL(ret == 0); }
static void test_txrx(odp_pktio_input_mode_t in_mode, int num_pkts) { int ret, i, if_b; pktio_info_t pktios[MAX_NUM_IFACES]; pktio_info_t *io; uint32_t mtu, min_mtu = UINT32_MAX; /* create pktios and associate input/output queues */ for (i = 0; i < num_ifaces; ++i) { io = &pktios[i]; io->name = iface_name[i]; io->id = create_pktio(i, in_mode, ODP_PKTOUT_MODE_SEND); if (io->id == ODP_PKTIO_INVALID) { CU_FAIL("failed to open iface"); return; } io->outq = odp_pktio_outq_getdef(io->id); io->in_mode = in_mode; if (in_mode == ODP_PKTIN_MODE_POLL) { create_inq(io->id, ODP_QUEUE_TYPE_POLL); io->inq = odp_pktio_inq_getdef(io->id); } else if (in_mode == ODP_PKTIN_MODE_SCHED) { create_inq(io->id, ODP_QUEUE_TYPE_SCHED); io->inq = ODP_QUEUE_INVALID; } } for (i = 0; i < num_ifaces; ++i) { io = &pktios[i]; ret = odp_pktio_start(io->id); CU_ASSERT(ret == 0); mtu = odp_pktio_mtu(io->id); if (mtu < min_mtu) min_mtu = mtu; } /* Skip test if packet len is larger than the MTU */ if (min_mtu >= packet_len) { /* if we have two interfaces then send through one and receive * on another but if there's only one assume it's a loopback */ if_b = (num_ifaces == 1) ? 0 : 1; pktio_txrx_multi(&pktios[0], &pktios[if_b], num_pkts); } for (i = 0; i < num_ifaces; ++i) { ret = odp_pktio_stop(pktios[i].id); CU_ASSERT(ret == 0); if (in_mode != ODP_PKTIN_MODE_RECV) destroy_inq(pktios[i].id); ret = odp_pktio_close(pktios[i].id); CU_ASSERT(ret == 0); } }
void pktio_test_inq(void) { odp_pktio_t pktio; pktio = create_pktio(0, ODP_PKTIN_MODE_POLL, ODP_PKTOUT_MODE_SEND); CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID); CU_ASSERT(create_inq(pktio, ODP_QUEUE_TYPE_POLL) == 0); CU_ASSERT(destroy_inq(pktio) == 0); CU_ASSERT(odp_pktio_close(pktio) == 0); }
void pktio_test_mtu(void) { int ret; int mtu; odp_pktio_t pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED, ODP_PKTOUT_MODE_SEND); CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID); mtu = odp_pktio_mtu(pktio); CU_ASSERT(mtu > 0); printf(" %d ", mtu); ret = odp_pktio_close(pktio); CU_ASSERT(ret == 0); }
void pktio_test_open(void) { odp_pktio_t pktio; odp_pktio_param_t pktio_param; int i; /* test the sequence open->close->open->close() */ for (i = 0; i < 2; ++i) { pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED, ODP_PKTOUT_MODE_SEND); CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID); CU_ASSERT(odp_pktio_close(pktio) == 0); } odp_pktio_param_init(&pktio_param); pktio_param.in_mode = ODP_PKTIN_MODE_SCHED; pktio = odp_pktio_open("nothere", default_pkt_pool, &pktio_param); CU_ASSERT(pktio == ODP_PKTIO_INVALID); }
static int test_init(void) { odp_pool_param_t params; const char *iface; int schedule; odp_pool_param_init(¶ms); params.pkt.len = PKT_HDR_LEN + gbl_args->args.pkt_len; params.pkt.seg_len = params.pkt.len; params.pkt.num = PKT_BUF_NUM; params.type = ODP_POOL_PACKET; transmit_pkt_pool = odp_pool_create("pkt_pool_transmit", ¶ms); if (transmit_pkt_pool == ODP_POOL_INVALID) LOG_ABORT("Failed to create transmit pool\n"); odp_atomic_init_u32(&ip_seq, 0); odp_atomic_init_u32(&shutdown, 0); iface = gbl_args->args.ifaces[0]; schedule = gbl_args->args.schedule; /* create pktios and associate input/output queues */ gbl_args->pktio_tx = create_pktio(iface, schedule); if (gbl_args->args.num_ifaces > 1) { iface = gbl_args->args.ifaces[1]; gbl_args->pktio_rx = create_pktio(iface, schedule); } else { gbl_args->pktio_rx = gbl_args->pktio_tx; } odp_pktio_mac_addr(gbl_args->pktio_tx, gbl_args->src_mac, ODPH_ETHADDR_LEN); odp_pktio_mac_addr(gbl_args->pktio_rx, gbl_args->dst_mac, ODPH_ETHADDR_LEN); if (gbl_args->pktio_rx == ODP_PKTIO_INVALID || gbl_args->pktio_tx == ODP_PKTIO_INVALID) { LOG_ERR("failed to open pktio\n"); return -1; } /* Create single queue with default parameters */ if (odp_pktout_queue_config(gbl_args->pktio_tx, NULL)) { LOG_ERR("failed to configure pktio_tx queue\n"); return -1; } /* Configure also input side (with defaults) */ if (odp_pktin_queue_config(gbl_args->pktio_tx, NULL)) { LOG_ERR("failed to configure pktio_tx queue\n"); return -1; } if (gbl_args->args.num_ifaces > 1) { if (odp_pktout_queue_config(gbl_args->pktio_rx, NULL)) { LOG_ERR("failed to configure pktio_rx queue\n"); return -1; } if (odp_pktin_queue_config(gbl_args->pktio_rx, NULL)) { LOG_ERR("failed to configure pktio_rx queue\n"); return -1; } } if (odp_pktio_start(gbl_args->pktio_tx) != 0) return -1; if (gbl_args->args.num_ifaces > 1 && odp_pktio_start(gbl_args->pktio_rx)) return -1; return 0; }
/** * ODP packet example main function */ int main(int argc, char * argv[]) { odph_linux_pthread_t thread_tbl[MAX_WORKERS]; odp_pool_t pool; int num_workers; int i; odp_shm_t shm; odp_cpumask_t cpumask; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; odp_pool_param_t params; odp_timer_pool_param_t tparams; odp_timer_pool_t tp; odp_pool_t tmop; /* Init ODP before calling anything else */ if (odp_init_global(NULL, NULL)) { EXAMPLE_ERR("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } if (odp_init_local(ODP_THREAD_CONTROL)) { EXAMPLE_ERR("Error: ODP local init failed.\n"); exit(EXIT_FAILURE); } my_sleep(1 + __k1_get_cluster_id() / 4); /* init counters */ odp_atomic_init_u64(&counters.seq, 0); odp_atomic_init_u64(&counters.ip, 0); odp_atomic_init_u64(&counters.udp, 0); odp_atomic_init_u64(&counters.icmp, 0); odp_atomic_init_u64(&counters.cnt, 0); /* Reserve memory for args from shared mem */ shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0); args = odp_shm_addr(shm); if (args == NULL) { EXAMPLE_ERR("Error: shared mem alloc failed.\n"); exit(EXIT_FAILURE); } memset(args, 0, sizeof(*args)); /* Parse and store the application arguments */ parse_args(argc, argv, &args->appl); /* Print both system and application information */ print_info(NO_PATH(argv[0]), &args->appl); /* Default to system CPU count unless user specified */ num_workers = MAX_WORKERS; if (args->appl.cpu_count) num_workers = args->appl.cpu_count; num_workers = odp_cpumask_default_worker(&cpumask, num_workers); if (args->appl.mask) { odp_cpumask_from_str(&cpumask, args->appl.mask); num_workers = odp_cpumask_count(&cpumask); } (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); printf("num worker threads: %i\n", num_workers); printf("first CPU: %i\n", odp_cpumask_first(&cpumask)); printf("cpu mask: %s\n", cpumaskstr); /* ping mode need two workers */ if (args->appl.mode == APPL_MODE_PING) { if (num_workers < 2) { EXAMPLE_ERR("Need at least two worker threads\n"); exit(EXIT_FAILURE); } else { num_workers = 2; } } /* Create packet pool */ odp_pool_param_init(¶ms); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE/SHM_PKT_POOL_BUF_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet_pool", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } odp_pool_print(pool); /* Create timer pool */ tparams.res_ns = 1 * ODP_TIME_MSEC_IN_NS; tparams.min_tmo = 0; tparams.max_tmo = 10000 * ODP_TIME_SEC_IN_NS; tparams.num_timers = num_workers; /* One timer per worker */ tparams.priv = 0; /* Shared */ tparams.clk_src = ODP_CLOCK_CPU; tp = odp_timer_pool_create("timer_pool", &tparams); if (tp == ODP_TIMER_POOL_INVALID) { EXAMPLE_ERR("Timer pool create failed.\n"); exit(EXIT_FAILURE); } odp_timer_pool_start(); /* Create timeout pool */ memset(¶ms, 0, sizeof(params)); params.tmo.num = tparams.num_timers; /* One timeout per timer */ params.type = ODP_POOL_TIMEOUT; tmop = odp_pool_create("timeout_pool", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } for (i = 0; i < args->appl.if_count; ++i) create_pktio(args->appl.if_names[i], pool); /* Create and init worker threads */ memset(thread_tbl, 0, sizeof(thread_tbl)); if (args->appl.mode == APPL_MODE_PING) { odp_cpumask_t cpu_mask; odp_queue_t tq; int cpu_first, cpu_next; odp_cpumask_zero(&cpu_mask); cpu_first = odp_cpumask_first(&cpumask); odp_cpumask_set(&cpu_mask, cpu_first); tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL); if (tq == ODP_QUEUE_INVALID) abort(); args->thread[1].pktio_dev = args->appl.if_names[0]; args->thread[1].pool = pool; args->thread[1].tp = tp; args->thread[1].tq = tq; args->thread[1].tim = odp_timer_alloc(tp, tq, NULL); if (args->thread[1].tim == ODP_TIMER_INVALID) abort(); args->thread[1].tmo_ev = odp_timeout_alloc(tmop); if (args->thread[1].tmo_ev == ODP_TIMEOUT_INVALID) abort(); args->thread[1].mode = args->appl.mode; odph_linux_pthread_create(&thread_tbl[1], &cpu_mask, gen_recv_thread, &args->thread[1], ODP_THREAD_WORKER); tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL); if (tq == ODP_QUEUE_INVALID) abort(); args->thread[0].pktio_dev = args->appl.if_names[0]; args->thread[0].pool = pool; args->thread[0].tp = tp; args->thread[0].tq = tq; args->thread[0].tim = odp_timer_alloc(tp, tq, NULL); if (args->thread[0].tim == ODP_TIMER_INVALID) abort(); args->thread[0].tmo_ev = odp_timeout_alloc(tmop); if (args->thread[0].tmo_ev == ODP_TIMEOUT_INVALID) abort(); args->thread[0].mode = args->appl.mode; cpu_next = odp_cpumask_next(&cpumask, cpu_first); odp_cpumask_zero(&cpu_mask); odp_cpumask_set(&cpu_mask, cpu_next); odph_linux_pthread_create(&thread_tbl[0], &cpu_mask, gen_send_thread, &args->thread[0], ODP_THREAD_WORKER); } else { int cpu = odp_cpumask_first(&cpumask); for (i = 0; i < num_workers; ++i) { odp_cpumask_t thd_mask; void *(*thr_run_func) (void *); int if_idx; odp_queue_t tq; if_idx = i % args->appl.if_count; args->thread[i].pktio_dev = args->appl.if_names[if_idx]; tq = odp_queue_create("", ODP_QUEUE_TYPE_POLL, NULL); if (tq == ODP_QUEUE_INVALID) abort(); args->thread[i].pool = pool; args->thread[i].tp = tp; args->thread[i].tq = tq; args->thread[i].tim = odp_timer_alloc(tp, tq, NULL); if (args->thread[i].tim == ODP_TIMER_INVALID) abort(); args->thread[i].tmo_ev = odp_timeout_alloc(tmop); if (args->thread[i].tmo_ev == ODP_TIMEOUT_INVALID) abort(); args->thread[i].mode = args->appl.mode; if (args->appl.mode == APPL_MODE_UDP) { thr_run_func = gen_send_thread; } else if (args->appl.mode == APPL_MODE_RCV) { thr_run_func = gen_recv_thread; } else { EXAMPLE_ERR("ERR MODE\n"); exit(EXIT_FAILURE); } /* * Create threads one-by-one instead of all-at-once, * because each thread might get different arguments. * Calls odp_thread_create(cpu) for each thread */ odp_cpumask_zero(&thd_mask); odp_cpumask_set(&thd_mask, cpu); odph_linux_pthread_create(&thread_tbl[i], &thd_mask, thr_run_func, &args->thread[i], ODP_THREAD_WORKER); cpu = odp_cpumask_next(&cpumask, cpu); } } print_global_stats(num_workers); /* Master thread waits for other threads to exit */ odph_linux_pthread_join(thread_tbl, num_workers); free(args->appl.if_names); free(args->appl.if_str); printf("Exit\n\n"); return 0; }
/** * ODP L2 forwarding main function */ int main(int argc, char *argv[]) { odph_linux_pthread_t thread_tbl[MAX_WORKERS]; odp_pool_t pool; int i; int cpu; int num_workers; odp_shm_t shm; odp_cpumask_t cpumask; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; odph_ethaddr_t new_addr; odp_pktio_t pktio; odp_pool_param_t params; int ret; stats_t *stats; /* Init ODP before calling anything else */ if (odp_init_global(NULL, NULL)) { LOG_ERR("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } /* Init this thread */ if (odp_init_local(ODP_THREAD_CONTROL)) { LOG_ERR("Error: ODP local init failed.\n"); exit(EXIT_FAILURE); } /* Reserve memory for args from shared mem */ shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0); gbl_args = odp_shm_addr(shm); if (gbl_args == NULL) { LOG_ERR("Error: shared mem alloc failed.\n"); exit(EXIT_FAILURE); } memset(gbl_args, 0, sizeof(*gbl_args)); /* Parse and store the application arguments */ parse_args(argc, argv, &gbl_args->appl); /* Print both system and application information */ print_info(NO_PATH(argv[0]), &gbl_args->appl); /* Default to system CPU count unless user specified */ num_workers = MAX_WORKERS; if (gbl_args->appl.cpu_count) num_workers = gbl_args->appl.cpu_count; /* Get default worker cpumask */ num_workers = odp_cpumask_default_worker(&cpumask, num_workers); (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); printf("num worker threads: %i\n", num_workers); printf("first CPU: %i\n", odp_cpumask_first(&cpumask)); printf("cpu mask: %s\n", cpumaskstr); if (num_workers < gbl_args->appl.if_count) { LOG_ERR("Error: CPU count %d less than interface count\n", num_workers); exit(EXIT_FAILURE); } /* Create packet pool */ odp_pool_param_init(¶ms); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE/SHM_PKT_POOL_BUF_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet pool", ¶ms); if (pool == ODP_POOL_INVALID) { LOG_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } odp_pool_print(pool); for (i = 0; i < gbl_args->appl.if_count; ++i) { pktio = create_pktio(gbl_args->appl.if_names[i], pool); if (pktio == ODP_PKTIO_INVALID) exit(EXIT_FAILURE); gbl_args->pktios[i] = pktio; /* Save interface ethernet address */ if (odp_pktio_mac_addr(pktio, gbl_args->port_eth_addr[i].addr, ODPH_ETHADDR_LEN) != ODPH_ETHADDR_LEN) { LOG_ERR("Error: interface ethernet address unknown\n"); exit(EXIT_FAILURE); } /* Save destination eth address */ if (gbl_args->appl.dst_change) { /* 02:00:00:00:00:XX */ memset(&new_addr, 0, sizeof(odph_ethaddr_t)); new_addr.addr[0] = 0x02; new_addr.addr[5] = i; gbl_args->dst_eth_addr[i] = new_addr; } /* Save interface destination port */ gbl_args->dst_port[i] = find_dest_port(i); } gbl_args->pktios[i] = ODP_PKTIO_INVALID; memset(thread_tbl, 0, sizeof(thread_tbl)); stats = gbl_args->stats; odp_barrier_init(&barrier, num_workers + 1); /* Create worker threads */ cpu = odp_cpumask_first(&cpumask); for (i = 0; i < num_workers; ++i) { odp_cpumask_t thd_mask; void *(*thr_run_func) (void *); if (gbl_args->appl.mode == DIRECT_RECV) thr_run_func = pktio_direct_recv_thread; else /* SCHED_NONE / SCHED_ATOMIC / SCHED_ORDERED */ thr_run_func = pktio_queue_thread; gbl_args->thread[i].src_idx = i % gbl_args->appl.if_count; gbl_args->thread[i].stats = &stats[i]; odp_cpumask_zero(&thd_mask); odp_cpumask_set(&thd_mask, cpu); odph_linux_pthread_create(&thread_tbl[i], &thd_mask, thr_run_func, &gbl_args->thread[i], ODP_THREAD_WORKER); cpu = odp_cpumask_next(&cpumask, cpu); } /* Start packet receive and transmit */ for (i = 0; i < gbl_args->appl.if_count; ++i) { pktio = gbl_args->pktios[i]; ret = odp_pktio_start(pktio); if (ret) { LOG_ERR("Error: unable to start %s\n", gbl_args->appl.if_names[i]); exit(EXIT_FAILURE); } } ret = print_speed_stats(num_workers, stats, gbl_args->appl.time, gbl_args->appl.accuracy); exit_threads = 1; /* Master thread waits for other threads to exit */ odph_linux_pthread_join(thread_tbl, num_workers); free(gbl_args->appl.if_names); free(gbl_args->appl.if_str); printf("Exit\n\n"); return ret; }
void pktio_test_send_failure(void) { odp_pktio_t pktio_tx, pktio_rx; odp_packet_t pkt_tbl[TX_BATCH_LEN]; uint32_t pkt_seq[TX_BATCH_LEN]; int ret, mtu, i, alloc_pkts; odp_pool_param_t pool_params; odp_pool_t pkt_pool; int long_pkt_idx = TX_BATCH_LEN / 2; pktio_info_t info_rx; pktio_tx = create_pktio(0, ODP_PKTIN_MODE_RECV, ODP_PKTOUT_MODE_SEND); if (pktio_tx == ODP_PKTIO_INVALID) { CU_FAIL("failed to open pktio"); return; } /* read the MTU from the transmit interface */ mtu = odp_pktio_mtu(pktio_tx); ret = odp_pktio_start(pktio_tx); CU_ASSERT_FATAL(ret == 0); /* configure the pool so that we can generate test packets larger * than the interface MTU */ memset(&pool_params, 0, sizeof(pool_params)); pool_params.pkt.len = mtu + 32; pool_params.pkt.seg_len = pool_params.pkt.len; pool_params.pkt.num = TX_BATCH_LEN + 1; pool_params.type = ODP_POOL_PACKET; pkt_pool = odp_pool_create("pkt_pool_oversize", &pool_params); CU_ASSERT_FATAL(pkt_pool != ODP_POOL_INVALID); if (num_ifaces > 1) { pktio_rx = create_pktio(1, ODP_PKTIN_MODE_RECV, ODP_PKTOUT_MODE_SEND); ret = odp_pktio_start(pktio_rx); CU_ASSERT_FATAL(ret == 0); } else { pktio_rx = pktio_tx; } /* generate a batch of packets with a single overly long packet * in the middle */ for (i = 0; i < TX_BATCH_LEN; ++i) { uint32_t pkt_len; if (i == long_pkt_idx) pkt_len = pool_params.pkt.len; else pkt_len = PKT_LEN_NORMAL; pkt_tbl[i] = odp_packet_alloc(pkt_pool, pkt_len); if (pkt_tbl[i] == ODP_PACKET_INVALID) break; pkt_seq[i] = pktio_init_packet(pkt_tbl[i]); pktio_pkt_set_macs(pkt_tbl[i], pktio_tx, pktio_rx); if (pktio_fixup_checksums(pkt_tbl[i]) != 0) { odp_packet_free(pkt_tbl[i]); break; } if (pkt_seq[i] == TEST_SEQ_INVALID) { odp_packet_free(pkt_tbl[i]); break; } } alloc_pkts = i; if (alloc_pkts == TX_BATCH_LEN) { /* try to send the batch with the long packet in the middle, * the initial short packets should be sent successfully */ odp_errno_zero(); ret = odp_pktio_send(pktio_tx, pkt_tbl, TX_BATCH_LEN); CU_ASSERT(ret == long_pkt_idx); CU_ASSERT(odp_errno() == 0); info_rx.id = pktio_rx; info_rx.outq = ODP_QUEUE_INVALID; info_rx.inq = ODP_QUEUE_INVALID; info_rx.in_mode = ODP_PKTIN_MODE_RECV; for (i = 0; i < ret; ++i) { pkt_tbl[i] = wait_for_packet(&info_rx, pkt_seq[i], ODP_TIME_SEC_IN_NS); if (pkt_tbl[i] == ODP_PACKET_INVALID) break; } if (i == ret) { /* now try to send starting with the too-long packet * and verify it fails */ odp_errno_zero(); ret = odp_pktio_send(pktio_tx, &pkt_tbl[long_pkt_idx], TX_BATCH_LEN - long_pkt_idx); CU_ASSERT(ret == -1); CU_ASSERT(odp_errno() != 0); } else { CU_FAIL("failed to receive transmitted packets\n"); } /* now reduce the size of the long packet and attempt to send * again - should work this time */ i = long_pkt_idx; odp_packet_pull_tail(pkt_tbl[i], odp_packet_len(pkt_tbl[i]) - PKT_LEN_NORMAL); pkt_seq[i] = pktio_init_packet(pkt_tbl[i]); pktio_pkt_set_macs(pkt_tbl[i], pktio_tx, pktio_rx); ret = pktio_fixup_checksums(pkt_tbl[i]); CU_ASSERT_FATAL(ret == 0); CU_ASSERT_FATAL(pkt_seq[i] != TEST_SEQ_INVALID); ret = odp_pktio_send(pktio_tx, &pkt_tbl[i], TX_BATCH_LEN - i); CU_ASSERT_FATAL(ret == (TX_BATCH_LEN - i)); for (; i < TX_BATCH_LEN; ++i) { pkt_tbl[i] = wait_for_packet(&info_rx, pkt_seq[i], ODP_TIME_SEC_IN_NS); if (pkt_tbl[i] == ODP_PACKET_INVALID) break; } CU_ASSERT(i == TX_BATCH_LEN); } else { CU_FAIL("failed to generate test packets\n"); } for (i = 0; i < alloc_pkts; ++i) { if (pkt_tbl[i] != ODP_PACKET_INVALID) odp_packet_free(pkt_tbl[i]); } if (pktio_rx != pktio_tx) CU_ASSERT(odp_pktio_close(pktio_rx) == 0); CU_ASSERT(odp_pktio_close(pktio_tx) == 0); CU_ASSERT(odp_pool_destroy(pkt_pool) == 0); }
void pktio_test_start_stop(void) { odp_pktio_t pktio[MAX_NUM_IFACES]; odp_packet_t pkt; odp_event_t tx_ev[100]; odp_event_t ev; int i, pkts, ret, alloc = 0; odp_queue_t outq; uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS); for (i = 0; i < num_ifaces; i++) { pktio[i] = create_pktio(i, ODP_PKTIN_MODE_SCHED, ODP_PKTOUT_MODE_SEND); CU_ASSERT_FATAL(pktio[i] != ODP_PKTIO_INVALID); create_inq(pktio[i], ODP_QUEUE_TYPE_SCHED); } outq = odp_pktio_outq_getdef(pktio[0]); /* Interfaces are stopped by default, * Check that stop when stopped generates an error */ ret = odp_pktio_stop(pktio[0]); CU_ASSERT(ret <= 0); /* start first */ ret = odp_pktio_start(pktio[0]); CU_ASSERT(ret == 0); /* Check that start when started generates an error */ ret = odp_pktio_start(pktio[0]); CU_ASSERT(ret < 0); /* Test Rx on a stopped interface. Only works if there are 2 */ if (num_ifaces > 1) { for (alloc = 0; alloc < 100; alloc++) { pkt = odp_packet_alloc(default_pkt_pool, packet_len); if (pkt == ODP_PACKET_INVALID) break; pktio_init_packet(pkt); pktio_pkt_set_macs(pkt, pktio[0], pktio[1]); if (pktio_fixup_checksums(pkt) != 0) { odp_packet_free(pkt); break; } tx_ev[alloc] = odp_packet_to_event(pkt); } for (pkts = 0; pkts != alloc; ) { ret = odp_queue_enq_multi(outq, &tx_ev[pkts], alloc - pkts); if (ret < 0) { CU_FAIL("unable to enqueue packet\n"); break; } pkts += ret; } /* check that packets did not arrive */ for (i = 0, pkts = 0; i < 1000; i++) { ev = odp_schedule(NULL, wait); if (ev == ODP_EVENT_INVALID) continue; if (odp_event_type(ev) == ODP_EVENT_PACKET) { pkt = odp_packet_from_event(ev); if (pktio_pkt_seq(pkt) != TEST_SEQ_INVALID) pkts++; } odp_event_free(ev); } if (pkts) CU_FAIL("pktio stopped, received unexpected events"); /* start both, send and get packets */ /* 0 already started */ ret = odp_pktio_start(pktio[1]); CU_ASSERT(ret == 0); /* flush packets with magic number in pipes */ for (i = 0; i < 1000; i++) { ev = odp_schedule(NULL, wait); if (ev != ODP_EVENT_INVALID) odp_event_free(ev); } } /* alloc */ for (alloc = 0; alloc < 100; alloc++) { pkt = odp_packet_alloc(default_pkt_pool, packet_len); if (pkt == ODP_PACKET_INVALID) break; pktio_init_packet(pkt); if (num_ifaces > 1) { pktio_pkt_set_macs(pkt, pktio[0], pktio[1]); if (pktio_fixup_checksums(pkt) != 0) { odp_packet_free(pkt); break; } } tx_ev[alloc] = odp_packet_to_event(pkt); } /* send */ for (pkts = 0; pkts != alloc; ) { ret = odp_queue_enq_multi(outq, &tx_ev[pkts], alloc - pkts); if (ret < 0) { CU_FAIL("unable to enqueue packet\n"); break; } pkts += ret; } /* get */ for (i = 0, pkts = 0; i < 100; i++) { ev = odp_schedule(NULL, wait); if (ev != ODP_EVENT_INVALID) { if (odp_event_type(ev) == ODP_EVENT_PACKET) { pkt = odp_packet_from_event(ev); if (pktio_pkt_seq(pkt) != TEST_SEQ_INVALID) pkts++; } odp_event_free(ev); } } CU_ASSERT(pkts == alloc); for (i = 0; i < num_ifaces; i++) { CU_ASSERT(odp_pktio_stop(pktio[i]) == 0); destroy_inq(pktio[i]); CU_ASSERT(odp_pktio_close(pktio[i]) == 0); } }
/** * ODP L2 forwarding main function */ int main(int argc, char *argv[]) { odph_linux_pthread_t thread_tbl[MAX_WORKERS]; odp_pool_t pool; int i; int cpu; int num_workers; odp_shm_t shm; odp_cpumask_t cpumask; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; odp_pool_param_t params; /* Init ODP before calling anything else */ if (odp_init_global(NULL, NULL)) { LOG_ERR("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } /* Init this thread */ if (odp_init_local(ODP_THREAD_CONTROL)) { LOG_ERR("Error: ODP local init failed.\n"); exit(EXIT_FAILURE); } /* Reserve memory for args from shared mem */ shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0); gbl_args = odp_shm_addr(shm); if (gbl_args == NULL) { LOG_ERR("Error: shared mem alloc failed.\n"); exit(EXIT_FAILURE); } memset(gbl_args, 0, sizeof(*gbl_args)); /* Parse and store the application arguments */ parse_args(argc, argv, &gbl_args->appl); /* Print both system and application information */ print_info(NO_PATH(argv[0]), &gbl_args->appl); /* Default to system CPU count unless user specified */ num_workers = MAX_WORKERS; if (gbl_args->appl.cpu_count) num_workers = gbl_args->appl.cpu_count; /* Get default worker cpumask */ num_workers = odp_cpumask_def_worker(&cpumask, num_workers); (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); printf("num worker threads: %i\n", num_workers); printf("first CPU: %i\n", odp_cpumask_first(&cpumask)); printf("cpu mask: %s\n", cpumaskstr); if (num_workers < gbl_args->appl.if_count) { LOG_ERR("Error: CPU count %d less than interface count\n", num_workers); exit(EXIT_FAILURE); } if (gbl_args->appl.if_count % 2 != 0) { LOG_ERR("Error: interface count %d is odd in fwd appl.\n", gbl_args->appl.if_count); exit(EXIT_FAILURE); } /* Create packet pool */ memset(¶ms, 0, sizeof(params)); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE/SHM_PKT_POOL_BUF_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet pool", ¶ms); if (pool == ODP_POOL_INVALID) { LOG_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } odp_pool_print(pool); for (i = 0; i < gbl_args->appl.if_count; ++i) { gbl_args->pktios[i] = create_pktio(gbl_args->appl.if_names[i], pool, gbl_args->appl.mode); if (gbl_args->pktios[i] == ODP_PKTIO_INVALID) exit(EXIT_FAILURE); } gbl_args->pktios[i] = ODP_PKTIO_INVALID; memset(thread_tbl, 0, sizeof(thread_tbl)); stats_t **stats = calloc(1, sizeof(stats_t) * num_workers); odp_barrier_init(&barrier, num_workers + 1); /* Create worker threads */ cpu = odp_cpumask_first(&cpumask); for (i = 0; i < num_workers; ++i) { odp_cpumask_t thd_mask; void *(*thr_run_func) (void *); if (gbl_args->appl.mode == APPL_MODE_PKT_BURST) thr_run_func = pktio_ifburst_thread; else /* APPL_MODE_PKT_QUEUE */ thr_run_func = pktio_queue_thread; gbl_args->thread[i].src_idx = i % gbl_args->appl.if_count; gbl_args->thread[i].stats = &stats[i]; odp_cpumask_zero(&thd_mask); odp_cpumask_set(&thd_mask, cpu); odph_linux_pthread_create(&thread_tbl[i], &thd_mask, thr_run_func, &gbl_args->thread[i]); cpu = odp_cpumask_next(&cpumask, cpu); } print_speed_stats(num_workers, stats, gbl_args->appl.time, gbl_args->appl.accuracy); free(stats); exit_threads = 1; /* Master thread waits for other threads to exit */ odph_linux_pthread_join(thread_tbl, num_workers); free(gbl_args->appl.if_names); free(gbl_args->appl.if_str); printf("Exit\n\n"); return 0; }
static int ipc_second_process(void) { odp_pktio_t ipc_pktio; odp_pool_param_t params; odp_pool_t pool; odp_packet_t pkt_tbl[MAX_PKT_BURST]; odp_packet_t alloc_pkt; int pkts; int ret; int i; odp_time_t start_cycle; odp_time_t cycle; odp_time_t diff; odp_time_t wait; uint64_t stat_pkts = 0; odp_pktin_queue_t pktin; /* Create packet pool */ memset(¶ms, 0, sizeof(params)); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet_pool2", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } ipc_pktio = create_pktio(pool); wait = odp_time_local_from_ns(run_time_sec * ODP_TIME_SEC_IN_NS); start_cycle = odp_time_local(); if (odp_pktin_queue(ipc_pktio, &pktin, 1) != 1) { EXAMPLE_ERR("no input queue\n"); return -1; } /* start ipc pktio, i.e. wait until other process connects */ for (;;) { /* 1. exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { printf("timeout exit, run_time_sec %d\n", run_time_sec); goto not_started; } } ret = odp_pktio_start(ipc_pktio); if (!ret) break; } for (;;) { /* exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { EXAMPLE_DBG("exit after %d seconds\n", run_time_sec); break; } } /* recv some packets and change MAGIC to MAGIC_2 */ pkts = odp_pktin_recv(pktin, pkt_tbl, MAX_PKT_BURST); if (pkts <= 0) continue; for (i = 0; i < pkts; i++) { odp_packet_t pkt = pkt_tbl[i]; pkt_head_t head; size_t off; off = odp_packet_l4_offset(pkt); if (off == ODP_PACKET_OFFSET_INVALID) EXAMPLE_ABORT("invalid l4 offset\n"); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_to_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable copy out head data"); if (head.magic != TEST_SEQ_MAGIC) EXAMPLE_ABORT("Wrong head magic!"); /* Modify magic number in packet */ head.magic = TEST_SEQ_MAGIC_2; ret = odp_packet_copy_from_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); } /* send all packets back */ ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, pkts); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += ret; /* alloc packet from local pool, set magic to ALLOC_MAGIC, * and send it.*/ alloc_pkt = odp_packet_alloc(pool, SHM_PKT_POOL_BUF_SIZE); if (alloc_pkt != ODP_PACKET_INVALID) { pkt_head_t head; size_t off; odp_packet_l4_offset_set(alloc_pkt, 30); head.magic = TEST_ALLOC_MAGIC; off = odp_packet_l4_offset(alloc_pkt); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_from_mem(alloc_pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); pkt_tbl[0] = alloc_pkt; ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, 1); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += 1; } } /* cleanup and exit */ ret = odp_pktio_stop(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_stop error %d\n", ret); return -1; } not_started: ret = odp_pktio_close(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_close error %d\n", ret); return -1; } ret = odp_pool_destroy(pool); if (ret) EXAMPLE_DBG("ipc2: pool_destroy error %d\n", ret); return stat_pkts > 1000 ? 0 : -1; }
int main(int argc, char **argv) { odph_odpthread_t thread_tbl[MAX_WORKERS]; int i, j; int cpu; int num_workers; odp_shm_t shm; odp_cpumask_t cpumask; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; odp_pool_param_t params; int ret; stats_t (*stats)[MAX_PKTIOS]; int if_count; odp_instance_t instance; odph_odpthread_params_t thr_params; /* Init ODP before calling anything else */ if (odp_init_global(&instance, NULL, NULL)) { printf("Error: ODP global init failed.\n"); exit(EXIT_FAILURE); } /* Init this thread */ if (odp_init_local(instance, ODP_THREAD_CONTROL)) { printf("Error: ODP local init failed.\n"); exit(EXIT_FAILURE); } /* Reserve memory for args from shared mem */ shm = odp_shm_reserve("shm_args", sizeof(args_t), ODP_CACHE_LINE_SIZE, 0); gbl_args = odp_shm_addr(shm); if (gbl_args == NULL) { printf("Error: shared mem alloc failed.\n"); exit(EXIT_FAILURE); } gbl_args_init(gbl_args); for (i = 0; (unsigned)i < MAC_TBL_SIZE; i++) odp_atomic_init_u64(&gbl_args->mac_tbl[i], 0); /* Parse and store the application arguments */ parse_args(argc, argv, &gbl_args->appl); /* Print both system and application information */ print_info(NO_PATH(argv[0]), &gbl_args->appl); /* Default to system CPU count unless user specified */ num_workers = MAX_WORKERS; if (gbl_args->appl.cpu_count) num_workers = gbl_args->appl.cpu_count; /* Get default worker cpumask */ num_workers = odp_cpumask_default_worker(&cpumask, num_workers); (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); gbl_args->appl.num_workers = num_workers; if_count = gbl_args->appl.if_count; printf("num worker threads: %i\n", num_workers); printf("first CPU: %i\n", odp_cpumask_first(&cpumask)); printf("cpu mask: %s\n", cpumaskstr); /* Create packet pool */ odp_pool_param_init(¶ms); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE; params.type = ODP_POOL_PACKET; gbl_args->pool = odp_pool_create("packet pool", ¶ms); if (gbl_args->pool == ODP_POOL_INVALID) { printf("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } odp_pool_print(gbl_args->pool); bind_workers(); for (i = 0; i < if_count; ++i) { const char *dev = gbl_args->appl.if_names[i]; int num_rx; /* An RX queue per assigned worker and a private TX queue for * each worker */ num_rx = gbl_args->pktios[i].num_rx_thr; if (create_pktio(dev, i, num_rx, num_workers, gbl_args->pool)) exit(EXIT_FAILURE); ret = odp_pktio_promisc_mode_set(gbl_args->pktios[i].pktio, 1); if (ret != 0) { printf("Error: failed to set port to promiscuous mode.\n"); exit(EXIT_FAILURE); } } gbl_args->pktios[i].pktio = ODP_PKTIO_INVALID; bind_queues(); print_port_mapping(); memset(thread_tbl, 0, sizeof(thread_tbl)); odp_barrier_init(&barrier, num_workers + 1); stats = gbl_args->stats; memset(&thr_params, 0, sizeof(thr_params)); thr_params.thr_type = ODP_THREAD_WORKER; thr_params.instance = instance; thr_params.start = run_worker; /* Create worker threads */ cpu = odp_cpumask_first(&cpumask); for (i = 0; i < num_workers; ++i) { odp_cpumask_t thd_mask; for (j = 0; j < MAX_PKTIOS; j++) gbl_args->thread[i].stats[j] = &stats[i][j]; thr_params.arg = &gbl_args->thread[i]; odp_cpumask_zero(&thd_mask); odp_cpumask_set(&thd_mask, cpu); odph_odpthreads_create(&thread_tbl[i], &thd_mask, &thr_params); cpu = odp_cpumask_next(&cpumask, cpu); } /* Start packet receive and transmit */ for (i = 0; i < if_count; ++i) { odp_pktio_t pktio; pktio = gbl_args->pktios[i].pktio; ret = odp_pktio_start(pktio); if (ret) { printf("Error: unable to start %s\n", gbl_args->appl.if_names[i]); exit(EXIT_FAILURE); } } ret = print_speed_stats(num_workers, gbl_args->stats, gbl_args->appl.time, gbl_args->appl.accuracy); exit_threads = 1; /* Master thread waits for other threads to exit */ for (i = 0; i < num_workers; ++i) odph_odpthreads_join(&thread_tbl[i]); free(gbl_args->appl.if_names); free(gbl_args->appl.if_str); if (odp_pool_destroy(gbl_args->pool)) { printf("Error: pool destroy\n"); exit(EXIT_FAILURE); } if (odp_term_local()) { printf("Error: term local\n"); exit(EXIT_FAILURE); } if (odp_term_global(instance)) { printf("Error: term global\n"); exit(EXIT_FAILURE); } printf("Exit: %d\n\n", ret); return ret; }