int pktio_suite_term(void) { char pool_name[ODP_POOL_NAME_LEN]; odp_pool_t pool; int i; int ret = 0; for (i = 0; i < num_ifaces; ++i) { snprintf(pool_name, sizeof(pool_name), "pkt_pool_%s_%d", iface_name[i], pool_segmentation); pool = odp_pool_lookup(pool_name); if (pool == ODP_POOL_INVALID) continue; if (odp_pool_destroy(pool) != 0) { fprintf(stderr, "error: failed to destroy pool %s\n", pool_name); ret = -1; } } if (odp_pool_destroy(default_pkt_pool) != 0) { fprintf(stderr, "error: failed to destroy default pool\n"); ret = -1; } default_pkt_pool = ODP_POOL_INVALID; return ret; }
static int test_term(void) { char pool_name[ODP_POOL_NAME_LEN]; odp_pool_t pool; int i; int ret = 0; if (gbl_args->pktio_tx != gbl_args->pktio_rx) { if (odp_pktio_stop(gbl_args->pktio_tx)) { LOG_ERR("Failed to stop pktio_tx\n"); return -1; } if (odp_pktio_close(gbl_args->pktio_tx)) { LOG_ERR("Failed to close pktio_tx\n"); ret = -1; } } empty_inq(gbl_args->pktio_rx); if (odp_pktio_stop(gbl_args->pktio_rx)) { LOG_ERR("Failed to stop pktio_rx\n"); return -1; } if (odp_pktio_close(gbl_args->pktio_rx) != 0) { LOG_ERR("Failed to close pktio_rx\n"); ret = -1; } for (i = 0; i < gbl_args->args.num_ifaces; ++i) { snprintf(pool_name, sizeof(pool_name), "pkt_pool_%s", gbl_args->args.ifaces[i]); pool = odp_pool_lookup(pool_name); if (pool == ODP_POOL_INVALID) continue; if (odp_pool_destroy(pool) != 0) { LOG_ERR("Failed to destroy pool %s\n", pool_name); ret = -1; } } if (odp_pool_destroy(transmit_pkt_pool) != 0) { LOG_ERR("Failed to destroy transmit pool\n"); ret = -1; } free(gbl_args->args.if_str); if (odp_shm_free(odp_shm_lookup("test_globals")) != 0) { LOG_ERR("Failed to free test_globals\n"); ret = -1; } return ret; }
int ofp_timer_term_global(void) { int i; struct ofp_timer_internal *bufdata, *next; int rc = 0; if (ofp_timer_lookup_shared_memory()) return -1; CHECK_ERROR(ofp_timer_stop_global(), rc); /* Cleanup long timers*/ for (i = 0; i < TIMER_NUM_LONG_SLOTS; i++) { bufdata = shm->long_table[i]; if (!bufdata) continue; while (bufdata) { next = bufdata->next; odp_buffer_free(bufdata->buf); bufdata = next; } } /* Cleanup timer related ODP objects*/ if (shm->queue != ODP_QUEUE_INVALID) { CHECK_ERROR(odp_queue_destroy(shm->queue), rc); shm->queue = ODP_QUEUE_INVALID; } if (shm->socket_timer_pool != ODP_TIMER_POOL_INVALID) { odp_timer_pool_destroy(shm->socket_timer_pool); shm->socket_timer_pool = ODP_TIMER_POOL_INVALID; } if (shm->buf_pool != ODP_POOL_INVALID) { CHECK_ERROR(odp_pool_destroy(shm->buf_pool), rc); shm->buf_pool = ODP_POOL_INVALID; } if (shm->pool != ODP_POOL_INVALID) { CHECK_ERROR(odp_pool_destroy(shm->pool), rc); shm->pool = ODP_POOL_INVALID; } CHECK_ERROR(ofp_timer_free_shared_memory(), rc); return rc; }
void classification_test_cos_set_drop(void) { int retval; char cosname[ODP_COS_NAME_LEN]; odp_cos_t cos_drop; odp_queue_t queue; odp_pool_t pool; odp_cls_cos_param_t cls_param; pool = pool_create("cls_basic_pool"); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); queue = queue_create("cls_basic_queue", true); CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID); sprintf(cosname, "CoSDrop"); odp_cls_cos_param_init(&cls_param); cls_param.pool = pool; cls_param.queue = queue; cls_param.drop_policy = ODP_COS_DROP_POOL; cos_drop = odp_cls_cos_create(cosname, &cls_param); CU_ASSERT_FATAL(cos_drop != ODP_COS_INVALID); retval = odp_cos_drop_set(cos_drop, ODP_COS_DROP_POOL); CU_ASSERT(retval == 0); retval = odp_cos_drop_set(cos_drop, ODP_COS_DROP_NEVER); CU_ASSERT(retval == 0); odp_cos_destroy(cos_drop); odp_pool_destroy(pool); odp_queue_destroy(queue); }
void classification_test_destroy_cos(void) { odp_cos_t cos; char name[ODP_COS_NAME_LEN]; odp_pool_t pool; odp_queue_t queue; odp_cls_cos_param_t cls_param; int retval; pool = pool_create("cls_basic_pool"); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); queue = queue_create("cls_basic_queue", true); CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID); sprintf(name, "ClassOfService"); odp_cls_cos_param_init(&cls_param); cls_param.pool = pool; cls_param.queue = queue; cls_param.drop_policy = ODP_COS_DROP_POOL; cos = odp_cls_cos_create(name, &cls_param); CU_ASSERT_FATAL(cos != ODP_COS_INVALID); retval = odp_cos_destroy(cos); CU_ASSERT(retval == 0); retval = odp_cos_destroy(ODP_COS_INVALID); CU_ASSERT(retval < 0); odp_pool_destroy(pool); odp_queue_destroy(queue); }
void timer_test_timeout_pool_free(void) { odp_pool_t pool; odp_timeout_t tmo; odp_pool_param_t params; odp_pool_param_init(¶ms); params.type = ODP_POOL_TIMEOUT; params.tmo.num = 1; pool = odp_pool_create("timeout_pool_free", ¶ms); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); odp_pool_print(pool); /* Allocate the only timeout from the pool */ tmo = odp_timeout_alloc(pool); CU_ASSERT_FATAL(tmo != ODP_TIMEOUT_INVALID); /* Pool should have only one timeout */ CU_ASSERT_FATAL(odp_timeout_alloc(pool) == ODP_TIMEOUT_INVALID) odp_timeout_free(tmo); /* Check that the timeout was returned back to the pool */ tmo = odp_timeout_alloc(pool); CU_ASSERT_FATAL(tmo != ODP_TIMEOUT_INVALID); odp_timeout_free(tmo); CU_ASSERT(odp_pool_destroy(pool) == 0); }
static int destroy_queues(void) { int i, j, prios; prios = odp_schedule_num_prio(); for (i = 0; i < prios; i++) { for (j = 0; j < QUEUES_PER_PRIO; j++) { char name[32]; snprintf(name, sizeof(name), "sched_%d_%d_n", i, j); if (destroy_queue(name) != 0) return -1; snprintf(name, sizeof(name), "sched_%d_%d_a", i, j); if (destroy_queue(name) != 0) return -1; snprintf(name, sizeof(name), "sched_%d_%d_o", i, j); if (destroy_queue(name) != 0) return -1; snprintf(name, sizeof(name), "plain_%d_%d_o", i, j); if (destroy_queue(name) != 0) return -1; } } if (odp_pool_destroy(queue_ctx_pool) != 0) { fprintf(stderr, "error: failed to destroy queue ctx pool\n"); return -1; } return 0; }
int classification_suite_term(void) { int i; int retcode = 0; if (0 > destroy_inq(pktio_loop)) { fprintf(stderr, "destroy pktio inq failed.\n"); retcode = -1; } if (0 > odp_pktio_close(pktio_loop)) { fprintf(stderr, "pktio close failed.\n"); retcode = -1; } if (0 != odp_pool_destroy(pool_default)) { fprintf(stderr, "pool_default destroy failed.\n"); retcode = -1; } for (i = 0; i < CLS_ENTRIES; i++) odp_cos_destroy(cos_list[i]); for (i = 0; i < CLS_ENTRIES; i++) odp_pmr_destroy(pmr_list[i]); for (i = 0; i < CLS_ENTRIES; i++) odp_queue_destroy(queue_list[i]); return retcode; }
int odp_schedule_term_global(void) { int ret = 0; int rc = 0; int i, j; for (i = 0; i < ODP_CONFIG_SCHED_PRIOS; i++) { for (j = 0; j < QUEUES_PER_PRIO; j++) { odp_queue_t pri_q; odp_event_t ev; pri_q = sched->pri_queue[i][j]; while ((ev = odp_queue_deq(pri_q)) != ODP_EVENT_INVALID) { odp_buffer_t buf; sched_cmd_t *sched_cmd; buf = odp_buffer_from_event(ev); sched_cmd = odp_buffer_addr(buf); if (sched_cmd->cmd == SCHED_CMD_DEQUEUE) { queue_entry_t *qe; odp_buffer_hdr_t *buf_hdr[1]; int num; qe = sched_cmd->qe; num = queue_deq_multi(qe, buf_hdr, 1); if (num < 0) queue_destroy_finalize(qe); if (num > 0) ODP_ERR("Queue not empty\n"); } else odp_buffer_free(buf); } if (odp_queue_destroy(pri_q)) { ODP_ERR("Pri queue destroy fail.\n"); rc = -1; } } } if (odp_pool_destroy(sched->pool) != 0) { ODP_ERR("Pool destroy fail.\n"); rc = -1; } ret = odp_shm_free(sched->shm); if (ret < 0) { ODP_ERR("Shm free failed for odp_scheduler"); rc = -1; } return rc; }
int classification_suite_init(void) { odp_pool_t pool; odp_pool_param_t param; odp_queue_t inq_def; odp_queue_param_t qparam; char queuename[ODP_QUEUE_NAME_LEN]; int i; int ret; memset(¶m, 0, sizeof(param)); param.pkt.seg_len = SHM_PKT_BUF_SIZE; param.pkt.len = SHM_PKT_BUF_SIZE; param.pkt.num = SHM_PKT_NUM_BUFS; param.type = ODP_POOL_PACKET; pool = odp_pool_create("classification_pool", ¶m); if (ODP_POOL_INVALID == pool) { fprintf(stderr, "Packet pool creation failed.\n"); return -1; } pool_default = odp_pool_lookup("classification_pool"); if (pool_default == ODP_POOL_INVALID) return -1; pktio_loop = odp_pktio_open("loop", pool_default); if (pktio_loop == ODP_PKTIO_INVALID) { ret = odp_pool_destroy(pool_default); if (ret) fprintf(stderr, "unable to destroy pool.\n"); return -1; } qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; qparam.sched.group = ODP_SCHED_GROUP_DEFAULT; sprintf(queuename, "%s", "inq_loop"); inq_def = odp_queue_create(queuename, ODP_QUEUE_TYPE_PKTIN, &qparam); odp_pktio_inq_setdef(pktio_loop, inq_def); for (i = 0; i < CLS_ENTRIES; i++) cos_list[i] = ODP_COS_INVALID; for (i = 0; i < CLS_ENTRIES; i++) pmr_list[i] = ODP_PMR_INVAL; for (i = 0; i < CLS_ENTRIES; i++) queue_list[i] = ODP_QUEUE_INVALID; odp_atomic_init_u32(&seq, 0); return 0; }
int ofp_uma_term_global(void) { uint32_t i; int rc = 0; for (i = 0; i < OFP_NUM_UMA_POOLS; i++) if (shm->pools[i] != ODP_POOL_INVALID) CHECK_ERROR(odp_pool_destroy(shm->pools[i]), rc); CHECK_ERROR(ofp_uma_free_shared_memory(), rc); return rc; }
static void pool_create_destroy(odp_pool_param_t *params) { odp_pool_t pool; char pool_name[ODP_POOL_NAME_LEN]; snprintf(pool_name, sizeof(pool_name), "test_pool-%d", pool_name_number++); pool = odp_pool_create(pool_name, params); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); CU_ASSERT(odp_pool_to_u64(pool) != odp_pool_to_u64(ODP_POOL_INVALID)); CU_ASSERT(odp_pool_destroy(pool) == 0); }
int ofp_uma_pool_destroy(uma_zone_t zone) { int ret = 0; if (zone > OFP_NUM_UMA_POOLS || zone < 0) return -1; if (shm->pools[zone] == ODP_POOL_INVALID) return -1; ret = odp_pool_destroy(shm->pools[zone]); shm->pools[zone] = ODP_POOL_INVALID; return ret; }
int scheduler_suite_term(void) { odp_pool_t pool; if (destroy_queues() != 0) { fprintf(stderr, "error: failed to destroy queues\n"); return -1; } pool = odp_pool_lookup(MSG_POOL_NAME); if (odp_pool_destroy(pool) != 0) fprintf(stderr, "error: failed to destroy pool\n"); return 0; }
void timer_test_timeout_pool_alloc(void) { odp_pool_t pool; const int num = 3; odp_timeout_t tmo[num]; odp_event_t ev; int index; char wrong_type = 0; odp_pool_param_t params; odp_pool_param_init(¶ms); params.type = ODP_POOL_TIMEOUT; params.tmo.num = num; pool = odp_pool_create("timeout_pool_alloc", ¶ms); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); odp_pool_print(pool); /* Try to allocate num items from the pool */ for (index = 0; index < num; index++) { tmo[index] = odp_timeout_alloc(pool); if (tmo[index] == ODP_TIMEOUT_INVALID) break; ev = odp_timeout_to_event(tmo[index]); if (odp_event_type(ev) != ODP_EVENT_TIMEOUT) wrong_type = 1; } /* Check that the pool had at least num items */ CU_ASSERT(index == num); /* index points out of buffer[] or it point to an invalid buffer */ index--; /* Check that the pool had correct buffers */ CU_ASSERT(wrong_type == 0); for (; index >= 0; index--) odp_timeout_free(tmo[index]); CU_ASSERT(odp_pool_destroy(pool) == 0); }
void scheduler_test_groups(void) { odp_pool_t p; odp_pool_param_t params; odp_queue_t queue_grp1, queue_grp2; odp_buffer_t buf; odp_event_t ev; uint32_t *u32; int i, j, rc; odp_schedule_sync_t sync[] = {ODP_SCHED_SYNC_PARALLEL, ODP_SCHED_SYNC_ATOMIC, ODP_SCHED_SYNC_ORDERED}; int thr_id = odp_thread_id(); odp_thrmask_t zeromask, mymask, testmask; odp_schedule_group_t mygrp1, mygrp2, lookup; odp_schedule_group_info_t info; odp_thrmask_zero(&zeromask); odp_thrmask_zero(&mymask); odp_thrmask_set(&mymask, thr_id); /* Can't find a group before we create it */ lookup = odp_schedule_group_lookup("Test Group 1"); CU_ASSERT(lookup == ODP_SCHED_GROUP_INVALID); /* Now create the group */ mygrp1 = odp_schedule_group_create("Test Group 1", &zeromask); CU_ASSERT_FATAL(mygrp1 != ODP_SCHED_GROUP_INVALID); /* Verify we can now find it */ lookup = odp_schedule_group_lookup("Test Group 1"); CU_ASSERT(lookup == mygrp1); /* Threadmask should be retrievable and be what we expect */ rc = odp_schedule_group_thrmask(mygrp1, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(!odp_thrmask_isset(&testmask, thr_id)); /* Now join the group and verify we're part of it */ rc = odp_schedule_group_join(mygrp1, &mymask); CU_ASSERT(rc == 0); rc = odp_schedule_group_thrmask(mygrp1, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(odp_thrmask_isset(&testmask, thr_id)); /* Info struct */ memset(&info, 0, sizeof(odp_schedule_group_info_t)); rc = odp_schedule_group_info(mygrp1, &info); CU_ASSERT(rc == 0); CU_ASSERT(odp_thrmask_equal(&info.thrmask, &mymask) != 0); CU_ASSERT(strcmp(info.name, "Test Group 1") == 0); /* We can't join or leave an unknown group */ rc = odp_schedule_group_join(ODP_SCHED_GROUP_INVALID, &mymask); CU_ASSERT(rc != 0); rc = odp_schedule_group_leave(ODP_SCHED_GROUP_INVALID, &mymask); CU_ASSERT(rc != 0); /* But we can leave our group */ rc = odp_schedule_group_leave(mygrp1, &mymask); CU_ASSERT(rc == 0); rc = odp_schedule_group_thrmask(mygrp1, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(!odp_thrmask_isset(&testmask, thr_id)); /* We shouldn't be able to find our second group before creating it */ lookup = odp_schedule_group_lookup("Test Group 2"); CU_ASSERT(lookup == ODP_SCHED_GROUP_INVALID); /* Now create it and verify we can find it */ mygrp2 = odp_schedule_group_create("Test Group 2", &zeromask); CU_ASSERT_FATAL(mygrp2 != ODP_SCHED_GROUP_INVALID); lookup = odp_schedule_group_lookup("Test Group 2"); CU_ASSERT(lookup == mygrp2); /* Verify we're not part of it */ rc = odp_schedule_group_thrmask(mygrp2, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(!odp_thrmask_isset(&testmask, thr_id)); /* Now join the group and verify we're part of it */ rc = odp_schedule_group_join(mygrp2, &mymask); CU_ASSERT(rc == 0); rc = odp_schedule_group_thrmask(mygrp2, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(odp_thrmask_isset(&testmask, thr_id)); /* Now verify scheduler adherence to groups */ odp_pool_param_init(¶ms); params.buf.size = 100; params.buf.align = 0; params.buf.num = 2; params.type = ODP_POOL_BUFFER; p = odp_pool_create("sched_group_pool", ¶ms); CU_ASSERT_FATAL(p != ODP_POOL_INVALID); for (i = 0; i < 3; i++) { odp_queue_param_t qp; odp_queue_t queue, from; odp_schedule_group_t mygrp[NUM_GROUPS]; odp_queue_t queue_grp[NUM_GROUPS]; int num = NUM_GROUPS; odp_queue_param_init(&qp); qp.type = ODP_QUEUE_TYPE_SCHED; qp.sched.prio = ODP_SCHED_PRIO_DEFAULT; qp.sched.sync = sync[i]; qp.sched.group = mygrp1; /* Create and populate a group in group 1 */ queue_grp1 = odp_queue_create("sched_group_test_queue_1", &qp); CU_ASSERT_FATAL(queue_grp1 != ODP_QUEUE_INVALID); CU_ASSERT_FATAL(odp_queue_sched_group(queue_grp1) == mygrp1); buf = odp_buffer_alloc(p); CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); u32 = odp_buffer_addr(buf); u32[0] = MAGIC1; ev = odp_buffer_to_event(buf); rc = odp_queue_enq(queue_grp1, ev); CU_ASSERT(rc == 0); if (rc) odp_buffer_free(buf); /* Now create and populate a queue in group 2 */ qp.sched.group = mygrp2; queue_grp2 = odp_queue_create("sched_group_test_queue_2", &qp); CU_ASSERT_FATAL(queue_grp2 != ODP_QUEUE_INVALID); CU_ASSERT_FATAL(odp_queue_sched_group(queue_grp2) == mygrp2); buf = odp_buffer_alloc(p); CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); u32 = odp_buffer_addr(buf); u32[0] = MAGIC2; ev = odp_buffer_to_event(buf); rc = odp_queue_enq(queue_grp2, ev); CU_ASSERT(rc == 0); if (rc) odp_buffer_free(buf); /* Swap between two groups. Application should serve both * groups to avoid potential head of line blocking in * scheduler. */ mygrp[0] = mygrp1; mygrp[1] = mygrp2; queue_grp[0] = queue_grp1; queue_grp[1] = queue_grp2; j = 0; /* Ensure that each test run starts from mygrp1 */ odp_schedule_group_leave(mygrp1, &mymask); odp_schedule_group_leave(mygrp2, &mymask); odp_schedule_group_join(mygrp1, &mymask); while (num) { queue = queue_grp[j]; ev = odp_schedule(&from, ODP_SCHED_NO_WAIT); if (ev == ODP_EVENT_INVALID) { /* change group */ rc = odp_schedule_group_leave(mygrp[j], &mymask); CU_ASSERT_FATAL(rc == 0); j = (j + 1) % NUM_GROUPS; rc = odp_schedule_group_join(mygrp[j], &mymask); CU_ASSERT_FATAL(rc == 0); continue; } CU_ASSERT_FATAL(from == queue); buf = odp_buffer_from_event(ev); u32 = odp_buffer_addr(buf); if (from == queue_grp1) { /* CU_ASSERT_FATAL needs these brackets */ CU_ASSERT_FATAL(u32[0] == MAGIC1); } else { CU_ASSERT_FATAL(u32[0] == MAGIC2); } odp_buffer_free(buf); /* Tell scheduler we're about to request an event. * Not needed, but a convenient place to test this API. */ odp_schedule_prefetch(1); num--; } /* Release schduler context and leave groups */ odp_schedule_group_join(mygrp1, &mymask); odp_schedule_group_join(mygrp2, &mymask); CU_ASSERT(exit_schedule_loop() == 0); odp_schedule_group_leave(mygrp1, &mymask); odp_schedule_group_leave(mygrp2, &mymask); /* Done with queues for this round */ CU_ASSERT_FATAL(odp_queue_destroy(queue_grp1) == 0); CU_ASSERT_FATAL(odp_queue_destroy(queue_grp2) == 0); /* Verify we can no longer find our queues */ CU_ASSERT_FATAL(odp_queue_lookup("sched_group_test_queue_1") == ODP_QUEUE_INVALID); CU_ASSERT_FATAL(odp_queue_lookup("sched_group_test_queue_2") == ODP_QUEUE_INVALID); } CU_ASSERT_FATAL(odp_schedule_group_destroy(mygrp1) == 0); CU_ASSERT_FATAL(odp_schedule_group_destroy(mygrp2) == 0); CU_ASSERT_FATAL(odp_pool_destroy(p) == 0); }
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; }
void scheduler_test_queue_destroy(void) { odp_pool_t p; odp_pool_param_t params; odp_queue_param_t qp; odp_queue_t queue, from; odp_buffer_t buf; odp_event_t ev; uint32_t *u32; int i; odp_schedule_sync_t sync[] = {ODP_SCHED_SYNC_PARALLEL, ODP_SCHED_SYNC_ATOMIC, ODP_SCHED_SYNC_ORDERED}; odp_queue_param_init(&qp); odp_pool_param_init(¶ms); params.buf.size = 100; params.buf.align = 0; params.buf.num = 1; params.type = ODP_POOL_BUFFER; p = odp_pool_create("sched_destroy_pool", ¶ms); CU_ASSERT_FATAL(p != ODP_POOL_INVALID); for (i = 0; i < 3; i++) { qp.type = ODP_QUEUE_TYPE_SCHED; qp.sched.prio = ODP_SCHED_PRIO_DEFAULT; qp.sched.sync = sync[i]; qp.sched.group = ODP_SCHED_GROUP_ALL; queue = odp_queue_create("sched_destroy_queue", &qp); CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID); buf = odp_buffer_alloc(p); CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); u32 = odp_buffer_addr(buf); u32[0] = MAGIC; ev = odp_buffer_to_event(buf); if (!(CU_ASSERT(odp_queue_enq(queue, ev) == 0))) odp_buffer_free(buf); ev = odp_schedule(&from, ODP_SCHED_WAIT); CU_ASSERT_FATAL(ev != ODP_EVENT_INVALID); CU_ASSERT_FATAL(from == queue); buf = odp_buffer_from_event(ev); u32 = odp_buffer_addr(buf); CU_ASSERT_FATAL(u32[0] == MAGIC); odp_buffer_free(buf); odp_schedule_release_ordered(); CU_ASSERT_FATAL(odp_queue_destroy(queue) == 0); } CU_ASSERT_FATAL(odp_pool_destroy(p) == 0); }
int queue_suite_term(void) { return odp_pool_destroy(pool); }
int main(int argc, char **argv) { int ret; ret = odp_init_global(NULL, NULL); if(ret < 0) { fprintf(stderr, "global init failure!\n"); exit(EXIT_FAILURE); } ret = odp_init_local(ODP_THREAD_CONTROL); if(ret < 0) { fprintf(stderr, "local init failure!\n"); exit(EXIT_FAILURE); } parse_param(argc, argv); packet_classifier_init(glb_param.rule_file, glb_param.fib_file); hash_env_init(); sm_hdl = sm_build(glb_param.pat_file); hs_tbl = create_hash_table(); odp_pool_t pkt_pool; pkt_pool = create_pkt_pool("PACKET_POOL",PACKET_POOL_OBJ_SZ, PACKET_POOL_MAX_ELT_NUM); if(pkt_pool == ODP_POOL_INVALID) { fprintf(stderr, "create packet pool failure!\n"); exit(EXIT_FAILURE); } if(init_all_if(pkt_pool) == -1) { fprintf(stderr, "init nic faliure!\n"); exit(EXIT_FAILURE); } odph_linux_pthread_t thr_tbl[ODP_CONFIG_PKTIO_ENTRIES]; int thr_num; thr_num = odph_linux_pthread_create(thr_tbl, &glb_param.cpu_mask, thread_fwd_routine, NULL); if(thr_num != glb_param.nic.num) { fprintf(stderr, "some nic thread start failure!\n"); exit(EXIT_FAILURE); } odph_linux_pthread_t thr_stat_hdl; odp_cpumask_t thr_stat_mask; odp_cpumask_zero(&thr_stat_mask); odp_cpumask_set(&thr_stat_mask, glb_param.nic.num); if(odph_linux_pthread_create(&thr_stat_hdl, &thr_stat_mask, thread_stat_routine, NULL) != 1) { fprintf(stderr, "stat thread start failure!\n"); exit(EXIT_FAILURE); } odph_linux_pthread_join(thr_tbl, thr_num); odph_linux_pthread_join(&thr_stat_hdl, 1); int nic_id; for(nic_id = 0; nic_id < glb_param.nic.num; nic_id++) { odp_pktio_close(thr_data.nic_hdl[nic_id]); } sm_destroy(sm_hdl); odph_hash_free(hs_tbl); odp_pool_destroy(pkt_pool); odp_term_local(); odp_term_global(); return 0; }
static int term_test() { test_assert_ret(odp_pktio_close(pktio) == 0); test_assert_ret(odp_pool_destroy(pool) == 0); 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; }
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); }
static void chaos_run(unsigned int qtype) { odp_pool_t pool; odp_pool_param_t params; odp_queue_param_t qp; odp_buffer_t buf; chaos_buf *cbuf; test_globals_t *globals; thread_args_t *args; odp_shm_t shm; int i, rc; odp_schedule_sync_t sync[] = {ODP_SCHED_SYNC_PARALLEL, ODP_SCHED_SYNC_ATOMIC, ODP_SCHED_SYNC_ORDERED}; const unsigned num_sync = (sizeof(sync) / sizeof(odp_schedule_sync_t)); const char *const qtypes[] = {"parallel", "atomic", "ordered"}; /* Set up the scheduling environment */ shm = odp_shm_lookup(GLOBALS_SHM_NAME); CU_ASSERT_FATAL(shm != ODP_SHM_INVALID); globals = odp_shm_addr(shm); CU_ASSERT_PTR_NOT_NULL_FATAL(globals); shm = odp_shm_lookup(SHM_THR_ARGS_NAME); CU_ASSERT_FATAL(shm != ODP_SHM_INVALID); args = odp_shm_addr(shm); CU_ASSERT_PTR_NOT_NULL_FATAL(args); args->globals = globals; args->cu_thr.numthrds = globals->num_workers; odp_queue_param_init(&qp); odp_pool_param_init(¶ms); params.buf.size = sizeof(chaos_buf); params.buf.align = 0; params.buf.num = CHAOS_NUM_EVENTS; params.type = ODP_POOL_BUFFER; pool = odp_pool_create("sched_chaos_pool", ¶ms); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); qp.type = ODP_QUEUE_TYPE_SCHED; qp.sched.prio = ODP_SCHED_PRIO_DEFAULT; qp.sched.group = ODP_SCHED_GROUP_ALL; for (i = 0; i < CHAOS_NUM_QUEUES; i++) { uint32_t ndx = (qtype == num_sync ? i % num_sync : qtype); qp.sched.sync = sync[ndx]; snprintf(globals->chaos_q[i].name, sizeof(globals->chaos_q[i].name), "chaos queue %d - %s", i, qtypes[ndx]); globals->chaos_q[i].handle = odp_queue_create(globals->chaos_q[i].name, &qp); CU_ASSERT_FATAL(globals->chaos_q[i].handle != ODP_QUEUE_INVALID); rc = odp_queue_context_set(globals->chaos_q[i].handle, CHAOS_NDX_TO_PTR(i), 0); CU_ASSERT_FATAL(rc == 0); } /* Now populate the queues with the initial seed elements */ for (i = 0; i < CHAOS_NUM_EVENTS; i++) { buf = odp_buffer_alloc(pool); CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); cbuf = odp_buffer_addr(buf); cbuf->evno = i; cbuf->seqno = 0; rc = odp_queue_enq( globals->chaos_q[i % CHAOS_NUM_QUEUES].handle, odp_buffer_to_event(buf)); CU_ASSERT_FATAL(rc == 0); } /* Run the test */ odp_cunit_thread_create(chaos_thread, &args->cu_thr); odp_cunit_thread_exit(&args->cu_thr); if (CHAOS_DEBUG) printf("Thread %d returning from chaos threads..cleaning up\n", odp_thread_id()); drain_queues(); exit_schedule_loop(); for (i = 0; i < CHAOS_NUM_QUEUES; i++) { if (CHAOS_DEBUG) printf("Destroying queue %s\n", globals->chaos_q[i].name); rc = odp_queue_destroy(globals->chaos_q[i].handle); CU_ASSERT(rc == 0); } rc = odp_pool_destroy(pool); CU_ASSERT(rc == 0); }
void timer_test_odp_timer_cancel(void) { odp_pool_t pool; odp_pool_param_t params; odp_timer_pool_param_t tparam; odp_timer_pool_t tp; odp_queue_t queue; odp_timer_t tim; odp_event_t ev; odp_timeout_t tmo; odp_timer_set_t rc; uint64_t tick; odp_pool_param_init(¶ms); params.type = ODP_POOL_TIMEOUT; params.tmo.num = 1; pool = odp_pool_create("tmo_pool_for_cancel", ¶ms); if (pool == ODP_POOL_INVALID) CU_FAIL_FATAL("Timeout pool create failed"); tparam.res_ns = 100 * ODP_TIME_MSEC_IN_NS; tparam.min_tmo = 1 * ODP_TIME_SEC_IN_NS; tparam.max_tmo = 10 * ODP_TIME_SEC_IN_NS; tparam.num_timers = 1; tparam.priv = 0; tparam.clk_src = ODP_CLOCK_CPU; tp = odp_timer_pool_create("timer_pool0", &tparam); if (tp == ODP_TIMER_POOL_INVALID) CU_FAIL_FATAL("Timer pool create failed"); /* Start all created timer pools */ odp_timer_pool_start(); queue = odp_queue_create("timer_queue", NULL); if (queue == ODP_QUEUE_INVALID) CU_FAIL_FATAL("Queue create failed"); #define USER_PTR ((void *)0xdead) tim = odp_timer_alloc(tp, queue, USER_PTR); if (tim == ODP_TIMER_INVALID) CU_FAIL_FATAL("Failed to allocate timer"); LOG_DBG("Timer handle: %" PRIu64 "\n", odp_timer_to_u64(tim)); ev = odp_timeout_to_event(odp_timeout_alloc(pool)); if (ev == ODP_EVENT_INVALID) CU_FAIL_FATAL("Failed to allocate timeout"); tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC_IN_NS); rc = odp_timer_set_rel(tim, tick, &ev); if (rc != ODP_TIMER_SUCCESS) CU_FAIL_FATAL("Failed to set timer (relative time)"); ev = ODP_EVENT_INVALID; if (odp_timer_cancel(tim, &ev) != 0) CU_FAIL_FATAL("Failed to cancel timer (relative time)"); if (ev == ODP_EVENT_INVALID) CU_FAIL_FATAL("Cancel did not return event"); tmo = odp_timeout_from_event(ev); if (tmo == ODP_TIMEOUT_INVALID) CU_FAIL_FATAL("Cancel did not return timeout"); LOG_DBG("Timeout handle: %" PRIu64 "\n", odp_timeout_to_u64(tmo)); if (odp_timeout_timer(tmo) != tim) CU_FAIL("Cancel invalid tmo.timer"); if (odp_timeout_user_ptr(tmo) != USER_PTR) CU_FAIL("Cancel invalid tmo.user_ptr"); odp_timeout_free(tmo); ev = odp_timer_free(tim); if (ev != ODP_EVENT_INVALID) CU_FAIL_FATAL("Free returned event"); odp_timer_pool_destroy(tp); if (odp_queue_destroy(queue) != 0) CU_FAIL_FATAL("Failed to destroy queue"); if (odp_pool_destroy(pool) != 0) CU_FAIL_FATAL("Failed to destroy pool"); }
void scheduler_test_chaos(void) { odp_pool_t pool; odp_pool_param_t params; odp_queue_param_t qp; odp_buffer_t buf; chaos_buf *cbuf; odp_event_t ev; test_globals_t *globals; thread_args_t *args; odp_shm_t shm; odp_queue_t from; int i, rc; uint64_t wait; odp_schedule_sync_t sync[] = {ODP_SCHED_SYNC_NONE, ODP_SCHED_SYNC_ATOMIC/* , */ /* ODP_SCHED_SYNC_ORDERED */}; const int num_sync = (sizeof(sync) / sizeof(sync[0])); const char *const qtypes[] = {"parallel", "atomic", "ordered"}; /* Set up the scheduling environment */ shm = odp_shm_lookup(GLOBALS_SHM_NAME); CU_ASSERT_FATAL(shm != ODP_SHM_INVALID); globals = odp_shm_addr(shm); CU_ASSERT_PTR_NOT_NULL_FATAL(shm); shm = odp_shm_lookup(SHM_THR_ARGS_NAME); CU_ASSERT_FATAL(shm != ODP_SHM_INVALID); args = odp_shm_addr(shm); CU_ASSERT_PTR_NOT_NULL_FATAL(args); args->globals = globals; args->cu_thr.numthrds = globals->num_workers; odp_queue_param_init(&qp); odp_pool_param_init(¶ms); params.buf.size = sizeof(chaos_buf); params.buf.align = 0; params.buf.num = CHAOS_NUM_EVENTS; params.type = ODP_POOL_BUFFER; pool = odp_pool_create("sched_chaos_pool", ¶ms); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); qp.sched.prio = ODP_SCHED_PRIO_DEFAULT; for (i = 0; i < CHAOS_NUM_QUEUES; i++) { qp.sched.sync = sync[i % num_sync]; snprintf(globals->chaos_q[i].name, sizeof(globals->chaos_q[i].name), "chaos queue %d - %s", i, qtypes[i % num_sync]); globals->chaos_q[i].handle = odp_queue_create(globals->chaos_q[i].name, ODP_QUEUE_TYPE_SCHED, &qp); CU_ASSERT_FATAL(globals->chaos_q[i].handle != ODP_QUEUE_INVALID); rc = odp_queue_context_set(globals->chaos_q[i].handle, CHAOS_NDX_TO_PTR(i)); CU_ASSERT_FATAL(rc == 0); } /* Now populate the queues with the initial seed elements */ odp_atomic_init_u32(&globals->chaos_pending_event_count, 0); for (i = 0; i < CHAOS_NUM_EVENTS; i++) { buf = odp_buffer_alloc(pool); CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); cbuf = odp_buffer_addr(buf); cbuf->evno = i; cbuf->seqno = 0; rc = odp_queue_enq( globals->chaos_q[i % CHAOS_NUM_QUEUES].handle, odp_buffer_to_event(buf)); CU_ASSERT_FATAL(rc == 0); odp_atomic_inc_u32(&globals->chaos_pending_event_count); } /* Run the test */ odp_cunit_thread_create(chaos_thread, &args->cu_thr); odp_cunit_thread_exit(&args->cu_thr); if (CHAOS_DEBUG) printf("Thread %d returning from chaos threads..cleaning up\n", odp_thread_id()); /* Cleanup: Drain queues, free events */ wait = odp_schedule_wait_time(CHAOS_WAIT_FAIL); while (odp_atomic_fetch_dec_u32( &globals->chaos_pending_event_count) > 0) { ev = odp_schedule(&from, wait); CU_ASSERT_FATAL(ev != ODP_EVENT_INVALID); cbuf = odp_buffer_addr(odp_buffer_from_event(ev)); if (CHAOS_DEBUG) printf("Draining event %" PRIu64 " seq %" PRIu64 " from Q %s...\n", cbuf->evno, cbuf->seqno, globals-> chaos_q [CHAOS_PTR_TO_NDX(odp_queue_context(from))]. name); odp_event_free(ev); } odp_schedule_release_ordered(); for (i = 0; i < CHAOS_NUM_QUEUES; i++) { if (CHAOS_DEBUG) printf("Destroying queue %s\n", globals->chaos_q[i].name); rc = odp_queue_destroy(globals->chaos_q[i].handle); CU_ASSERT(rc == 0); } rc = odp_pool_destroy(pool); CU_ASSERT(rc == 0); }
/** * Test main function */ int main(int argc, char *argv[]) { odph_linux_pthread_t thread_tbl[MAX_WORKERS]; int num_workers; odp_queue_t queue; uint64_t tick, ns; odp_queue_param_t param; odp_pool_param_t params; odp_timer_pool_param_t tparams; odp_timer_pool_info_t tpinfo; odp_cpumask_t cpumask; char cpumaskstr[ODP_CPUMASK_STR_SIZE]; odp_shm_t shm = ODP_SHM_INVALID; test_globals_t *gbls = NULL; int err = 0; printf("\nODP timer example starts\n"); if (odp_init_global(NULL, NULL)) { err = 1; printf("ODP global init failed.\n"); goto err_global; } /* Init this thread. */ if (odp_init_local(ODP_THREAD_CONTROL)) { err = 1; printf("ODP local init failed.\n"); goto err_local; } printf("\n"); printf("ODP system info\n"); printf("---------------\n"); printf("ODP API version: %s\n", odp_version_api_str()); printf("CPU model: %s\n", odp_cpu_model_str()); printf("CPU freq (hz): %"PRIu64"\n", odp_cpu_hz_max()); printf("Cache line size: %i\n", odp_sys_cache_line_size()); printf("Max CPU count: %i\n", odp_cpu_count()); printf("\n"); /* Reserve memory for test_globals_t from shared mem */ shm = odp_shm_reserve("shm_test_globals", sizeof(test_globals_t), ODP_CACHE_LINE_SIZE, 0); if (ODP_SHM_INVALID == shm) { err = 1; EXAMPLE_ERR("Error: shared mem reserve failed.\n"); goto err; } gbls = odp_shm_addr(shm); if (NULL == gbls) { err = 1; EXAMPLE_ERR("Error: shared mem alloc failed.\n"); goto err; } memset(gbls, 0, sizeof(test_globals_t)); gbls->pool = ODP_POOL_INVALID; gbls->tp = ODP_TIMER_POOL_INVALID; parse_args(argc, argv, &gbls->args); memset(thread_tbl, 0, sizeof(thread_tbl)); /* Default to system CPU count unless user specified */ num_workers = MAX_WORKERS; if (gbls->args.cpu_count) num_workers = gbls->args.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); printf("resolution: %i usec\n", gbls->args.resolution_us); printf("min timeout: %i usec\n", gbls->args.min_us); printf("max timeout: %i usec\n", gbls->args.max_us); printf("period: %i usec\n", gbls->args.period_us); printf("timeouts: %i\n", gbls->args.tmo_count); /* * Create pool for timeouts */ odp_pool_param_init(¶ms); params.tmo.num = NUM_TMOS; params.type = ODP_POOL_TIMEOUT; gbls->pool = odp_pool_create("msg_pool", ¶ms); if (gbls->pool == ODP_POOL_INVALID) { err = 1; EXAMPLE_ERR("Pool create failed.\n"); goto err; } tparams.res_ns = gbls->args.resolution_us * ODP_TIME_USEC_IN_NS; tparams.min_tmo = gbls->args.min_us * ODP_TIME_USEC_IN_NS; tparams.max_tmo = gbls->args.max_us * ODP_TIME_USEC_IN_NS; tparams.num_timers = num_workers; /* One timer per worker */ tparams.priv = 0; /* Shared */ tparams.clk_src = ODP_CLOCK_CPU; gbls->tp = odp_timer_pool_create("timer_pool", &tparams); if (gbls->tp == ODP_TIMER_POOL_INVALID) { err = 1; EXAMPLE_ERR("Timer pool create failed.\n"); goto err; } odp_timer_pool_start(); odp_shm_print_all(); (void)odp_timer_pool_info(gbls->tp, &tpinfo); printf("Timer pool\n"); printf("----------\n"); printf(" name: %s\n", tpinfo.name); printf(" resolution: %"PRIu64" ns\n", tpinfo.param.res_ns); printf(" min tmo: %"PRIu64" ticks\n", tpinfo.param.min_tmo); printf(" max tmo: %"PRIu64" ticks\n", tpinfo.param.max_tmo); printf("\n"); /* * Create a queue for timer test */ odp_queue_param_init(¶m); param.type = ODP_QUEUE_TYPE_SCHED; param.sched.prio = ODP_SCHED_PRIO_DEFAULT; param.sched.sync = ODP_SCHED_SYNC_PARALLEL; param.sched.group = ODP_SCHED_GROUP_ALL; queue = odp_queue_create("timer_queue", ¶m); if (queue == ODP_QUEUE_INVALID) { err = 1; EXAMPLE_ERR("Timer queue create failed.\n"); goto err; } printf("CPU freq %"PRIu64" Hz\n", odp_cpu_hz_max()); printf("Timer ticks vs nanoseconds:\n"); ns = 0; tick = odp_timer_ns_to_tick(gbls->tp, ns); printf(" %12" PRIu64 " ns -> %12" PRIu64 " ticks\n", ns, tick); printf(" %12" PRIu64 " ticks -> %12" PRIu64 " ns\n", tick, odp_timer_tick_to_ns(gbls->tp, tick)); for (ns = 1; ns <= 100 * ODP_TIME_SEC_IN_NS; ns *= 10) { tick = odp_timer_ns_to_tick(gbls->tp, ns); printf(" %12" PRIu64 " ns -> %12" PRIu64 " ticks\n", ns, tick); printf(" %12" PRIu64 " ticks -> %12" PRIu64 " ns\n", tick, odp_timer_tick_to_ns(gbls->tp, tick)); } printf("\n"); gbls->num_workers = num_workers; /* Initialize number of timeouts to receive */ odp_atomic_init_u32(&gbls->remain, gbls->args.tmo_count * num_workers); /* Barrier to sync test case execution */ odp_barrier_init(&gbls->test_barrier, num_workers); /* Create and launch worker threads */ odph_linux_pthread_create(thread_tbl, &cpumask, run_thread, gbls, ODP_THREAD_WORKER); /* Wait for worker threads to exit */ odph_linux_pthread_join(thread_tbl, num_workers); /* free resources */ if (odp_queue_destroy(queue)) err = 1; err: if (gbls != NULL && gbls->tp != ODP_TIMER_POOL_INVALID) odp_timer_pool_destroy(gbls->tp); if (gbls != NULL && gbls->pool != ODP_TIMER_POOL_INVALID) if (odp_pool_destroy(gbls->pool)) err = 1; if (shm != ODP_SHM_INVALID) if (odp_shm_free(shm)) err = 1; if (odp_term_local()) err = 1; err_local: if (odp_term_global()) err = 1; err_global: if (err) { printf("Err: ODP timer test failed\n\n"); return -1; } printf("ODP timer test complete\n\n"); return 0; }
int ofp_term_post_global(const char *pool_name) { odp_pool_t pool; int rc = 0; if (ofp_inet_term()) { OFP_ERR("Failed to cleanup inet/inet6 domains.\n"); rc = -1; } /* Cleanup sockets */ CHECK_ERROR(ofp_socket_term_global(), rc); /* Cleanup vxlan */ CHECK_ERROR(ofp_vxlan_term_global(), rc); /* Cleanup interface related objects */ CHECK_ERROR(ofp_portconf_term_global(), rc); /* Cleanup routes */ CHECK_ERROR(ofp_route_term_global(), rc); /* Cleanup ARP*/ CHECK_ERROR(ofp_arp_term_global(), rc); /* Cleanup hooks */ CHECK_ERROR(ofp_hook_term_global(), rc); /* Cleanup stats */ CHECK_ERROR(ofp_stat_term_global(), rc); /* Cleanup packet capture */ CHECK_ERROR(ofp_pcap_term_global(), rc); /* Cleanup reassembly queues*/ CHECK_ERROR(ofp_reassembly_term_global(), rc); /* Cleanup avl trees*/ CHECK_ERROR(ofp_avl_term_global(), rc); /* Cleanup timers - phase 1*/ CHECK_ERROR(ofp_timer_stop_global(), rc); /* Cleanup pending events */ schedule_shutdown(); /* Cleanup timers - phase 2*/ CHECK_ERROR(ofp_timer_term_global(), rc); /* Cleanup packet pool */ pool = odp_pool_lookup(pool_name); if (pool == ODP_POOL_INVALID) { OFP_ERR("Failed to locate pool %s\n", pool_name); rc = -1; } else if (odp_pool_destroy(pool) < 0) { OFP_ERR("Failed to destroy pool %s.\n", pool_name); rc = -1; pool = ODP_POOL_INVALID; } CHECK_ERROR(ofp_global_config_free_shared_memory(), rc); CHECK_ERROR(ofp_unregister_sysctls(), rc); return rc; }
void scheduler_test_groups(void) { odp_pool_t p; odp_pool_param_t params; odp_queue_param_t qp; odp_queue_t queue_grp1, queue_grp2, from; odp_buffer_t buf; odp_event_t ev; uint32_t *u32; int i, j, rc; odp_schedule_sync_t sync[] = {ODP_SCHED_SYNC_NONE, ODP_SCHED_SYNC_ATOMIC/* , */ /* ODP_SCHED_SYNC_ORDERED */}; const int num_sync = (sizeof(sync) / sizeof(sync[0])); int thr_id = odp_thread_id(); odp_thrmask_t zeromask, mymask, testmask; odp_schedule_group_t mygrp1, mygrp2, lookup; odp_thrmask_zero(&zeromask); odp_thrmask_zero(&mymask); odp_thrmask_set(&mymask, thr_id); /* Can't find a group before we create it */ lookup = odp_schedule_group_lookup("Test Group 1"); CU_ASSERT(lookup == ODP_SCHED_GROUP_INVALID); /* Now create the group */ mygrp1 = odp_schedule_group_create("Test Group 1", &zeromask); CU_ASSERT_FATAL(mygrp1 != ODP_SCHED_GROUP_INVALID); /* Verify we can now find it */ lookup = odp_schedule_group_lookup("Test Group 1"); CU_ASSERT(lookup == mygrp1); /* Threadmask should be retrievable and be what we expect */ rc = odp_schedule_group_thrmask(mygrp1, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(!odp_thrmask_isset(&testmask, thr_id)); /* Now join the group and verify we're part of it */ rc = odp_schedule_group_join(mygrp1, &mymask); CU_ASSERT(rc == 0); rc = odp_schedule_group_thrmask(mygrp1, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(odp_thrmask_isset(&testmask, thr_id)); /* We can't join or leave an unknown group */ rc = odp_schedule_group_join(ODP_SCHED_GROUP_INVALID, &mymask); CU_ASSERT(rc != 0); rc = odp_schedule_group_leave(ODP_SCHED_GROUP_INVALID, &mymask); CU_ASSERT(rc != 0); /* But we can leave our group */ rc = odp_schedule_group_leave(mygrp1, &mymask); CU_ASSERT(rc == 0); rc = odp_schedule_group_thrmask(mygrp1, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(!odp_thrmask_isset(&testmask, thr_id)); /* We shouldn't be able to find our second group before creating it */ lookup = odp_schedule_group_lookup("Test Group 2"); CU_ASSERT(lookup == ODP_SCHED_GROUP_INVALID); /* Now create it and verify we can find it */ mygrp2 = odp_schedule_group_create("Test Group 2", &zeromask); CU_ASSERT_FATAL(mygrp2 != ODP_SCHED_GROUP_INVALID); lookup = odp_schedule_group_lookup("Test Group 2"); CU_ASSERT(lookup == mygrp2); /* Verify we're not part of it */ rc = odp_schedule_group_thrmask(mygrp2, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(!odp_thrmask_isset(&testmask, thr_id)); /* Now join the group and verify we're part of it */ rc = odp_schedule_group_join(mygrp2, &mymask); CU_ASSERT(rc == 0); rc = odp_schedule_group_thrmask(mygrp2, &testmask); CU_ASSERT(rc == 0); CU_ASSERT(odp_thrmask_isset(&testmask, thr_id)); /* Now verify scheduler adherence to groups */ odp_queue_param_init(&qp); odp_pool_param_init(¶ms); params.buf.size = 100; params.buf.align = 0; params.buf.num = 2; params.type = ODP_POOL_BUFFER; p = odp_pool_create("sched_group_pool", ¶ms); CU_ASSERT_FATAL(p != ODP_POOL_INVALID); for (i = 0; i < num_sync; i++) { qp.sched.prio = ODP_SCHED_PRIO_DEFAULT; qp.sched.sync = sync[i]; qp.sched.group = mygrp1; /* Create and populate a group in group 1 */ queue_grp1 = odp_queue_create("sched_group_test_queue_1", ODP_QUEUE_TYPE_SCHED, &qp); CU_ASSERT_FATAL(queue_grp1 != ODP_QUEUE_INVALID); CU_ASSERT_FATAL(odp_queue_sched_group(queue_grp1) == mygrp1); buf = odp_buffer_alloc(p); CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); u32 = odp_buffer_addr(buf); u32[0] = MAGIC1; ev = odp_buffer_to_event(buf); if (!(CU_ASSERT(odp_queue_enq(queue_grp1, ev) == 0))) odp_buffer_free(buf); /* Now create and populate a queue in group 2 */ qp.sched.group = mygrp2; queue_grp2 = odp_queue_create("sched_group_test_queue_2", ODP_QUEUE_TYPE_SCHED, &qp); CU_ASSERT_FATAL(queue_grp2 != ODP_QUEUE_INVALID); CU_ASSERT_FATAL(odp_queue_sched_group(queue_grp2) == mygrp2); buf = odp_buffer_alloc(p); CU_ASSERT_FATAL(buf != ODP_BUFFER_INVALID); u32 = odp_buffer_addr(buf); u32[0] = MAGIC2; ev = odp_buffer_to_event(buf); if (!(CU_ASSERT(odp_queue_enq(queue_grp2, ev) == 0))) odp_buffer_free(buf); /* Scheduler should give us the event from Group 2 */ ev = odp_schedule(&from, ODP_SCHED_WAIT); CU_ASSERT_FATAL(ev != ODP_EVENT_INVALID); CU_ASSERT_FATAL(from == queue_grp2); buf = odp_buffer_from_event(ev); u32 = odp_buffer_addr(buf); CU_ASSERT_FATAL(u32[0] == MAGIC2); odp_buffer_free(buf); /* Scheduler should not return anything now since we're * not in Group 1 and Queue 2 is empty. Do this several * times to confirm. */ for (j = 0; j < 10; j++) { ev = odp_schedule(&from, ODP_SCHED_NO_WAIT); CU_ASSERT_FATAL(ev == ODP_EVENT_INVALID) } /* Now join group 1 and verify we can get the event */ rc = odp_schedule_group_join(mygrp1, &mymask); CU_ASSERT_FATAL(rc == 0); /* Tell scheduler we're about to request an event. * Not needed, but a convenient place to test this API. */ odp_schedule_prefetch(1); /* Now get the event from Queue 1 */ ev = odp_schedule(&from, ODP_SCHED_WAIT); CU_ASSERT_FATAL(ev != ODP_EVENT_INVALID); CU_ASSERT_FATAL(from == queue_grp1); buf = odp_buffer_from_event(ev); u32 = odp_buffer_addr(buf); CU_ASSERT_FATAL(u32[0] == MAGIC1); odp_buffer_free(buf); /* Leave group 1 for next pass */ rc = odp_schedule_group_leave(mygrp1, &mymask); CU_ASSERT_FATAL(rc == 0); /* We must release order before destroying queues */ odp_schedule_release_ordered(); /* Done with queues for this round */ CU_ASSERT_FATAL(odp_queue_destroy(queue_grp1) == 0); CU_ASSERT_FATAL(odp_queue_destroy(queue_grp2) == 0); /* Verify we can no longer find our queues */ CU_ASSERT_FATAL(odp_queue_lookup("sched_group_test_queue_1") == ODP_QUEUE_INVALID); CU_ASSERT_FATAL(odp_queue_lookup("sched_group_test_queue_2") == ODP_QUEUE_INVALID); } CU_ASSERT_FATAL(odp_schedule_group_destroy(mygrp1) == 0); CU_ASSERT_FATAL(odp_schedule_group_destroy(mygrp2) == 0); CU_ASSERT_FATAL(odp_pool_destroy(p) == 0); }