From a8a283772f07d8ae5b04fae55170c800f871d6fb Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Wed, 14 Feb 2024 16:40:43 +0200 Subject: example: l2fwd: remove symbolic link to performance test application Remove symbolic link to odp_l2fwd performance test application and copy relevant information from old README file to application source file. Signed-off-by: Matias Elo Reviewed-by: Janne Peltonen --- example/l2fwd/README | 14 -------------- example/l2fwd/odp_l2fwd.c | 1 - 2 files changed, 15 deletions(-) delete mode 100644 example/l2fwd/README delete mode 120000 example/l2fwd/odp_l2fwd.c (limited to 'example') diff --git a/example/l2fwd/README b/example/l2fwd/README deleted file mode 100644 index 091d046ea..000000000 --- a/example/l2fwd/README +++ /dev/null @@ -1,14 +0,0 @@ - ODP L2FWD application - -Source code and Makefiles placed under test/performance/ directory. - -This L2 forwarding application can be used as example reference as well -as performance test for different odp modes (direct, queue or scheduler -with parallel, atomic or ordered queues). - -Note that this example is tuned for performance. As a result, when using -scheduled mode with direct packet I/O output or queued output with multiple -output queues, packet order is not guaranteed. To achieve guaranteed order, -use a single worker thread or output interfaces with single output -queues. Other examples of scalable processing using ordered queues that -preserve order can be seen in the odp_pktio_ordered performance test. diff --git a/example/l2fwd/odp_l2fwd.c b/example/l2fwd/odp_l2fwd.c deleted file mode 120000 index fb585f437..000000000 --- a/example/l2fwd/odp_l2fwd.c +++ /dev/null @@ -1 +0,0 @@ -../../test/performance/odp_l2fwd.c \ No newline at end of file -- cgit v1.2.3 From 6349cb348af1b22a87ad4ebd9e0ca96b8657a5d7 Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Wed, 14 Feb 2024 16:50:22 +0200 Subject: example: time: remove odp_time_global_test example application Remove unnecessary old example/test application. A similar test has been added to time validation suite ('time_test_global_mt'). Signed-off-by: Matias Elo Reviewed-by: Janne Peltonen --- example/Makefile.am | 1 - example/m4/configure.m4 | 1 - example/time/.gitignore | 1 - example/time/Makefile.am | 9 - example/time/odp_time_global_test.c | 397 ------------------------------------ 5 files changed, 409 deletions(-) delete mode 100644 example/time/.gitignore delete mode 100644 example/time/Makefile.am delete mode 100644 example/time/odp_time_global_test.c (limited to 'example') diff --git a/example/Makefile.am b/example/Makefile.am index d6d242cf9..9e748345b 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -11,7 +11,6 @@ SUBDIRS = classifier \ simple_pipeline \ switch \ sysinfo \ - time \ timer \ traffic_mgmt diff --git a/example/m4/configure.m4 b/example/m4/configure.m4 index b02fd72a5..852837e0d 100644 --- a/example/m4/configure.m4 +++ b/example/m4/configure.m4 @@ -34,7 +34,6 @@ AC_CONFIG_FILES([example/classifier/Makefile example/simple_pipeline/Makefile example/switch/Makefile example/sysinfo/Makefile - example/time/Makefile example/timer/Makefile example/traffic_mgmt/Makefile example/Makefile]) diff --git a/example/time/.gitignore b/example/time/.gitignore deleted file mode 100644 index 938c1aaed..000000000 --- a/example/time/.gitignore +++ /dev/null @@ -1 +0,0 @@ -odp_time_global diff --git a/example/time/Makefile.am b/example/time/Makefile.am deleted file mode 100644 index b5a1ad35d..000000000 --- a/example/time/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -include $(top_srcdir)/example/Makefile.inc - -bin_PROGRAMS = odp_time_global - -if test_example -TESTS = odp_time_global -endif - -odp_time_global_SOURCES = odp_time_global_test.c diff --git a/example/time/odp_time_global_test.c b/example/time/odp_time_global_test.c deleted file mode 100644 index 7c1409abf..000000000 --- a/example/time/odp_time_global_test.c +++ /dev/null @@ -1,397 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright (c) 2015-2018 Linaro Limited - */ - -/** - * @example odp_time_global_test.c - * - * Time API test application - * - * @cond _ODP_HIDE_FROM_DOXYGEN_ - */ - -#include - -#include -#include - -#define MAX_WORKERS 32 -#define MAX_NUM_BUF 8192 -#define ITERATION_NUM 2048 -#define LOG_BASE 8 -#define LOG_ENTRY_SIZE 19 -#define LOG_LINE_SIZE (LOG_BASE * LOG_ENTRY_SIZE + 1) - -#define QUEUE_NAME_PREFIX "thread_queue_" - -typedef struct { - odp_time_t timestamp; - int id; -} timestamp_event_t; - -typedef struct { - uint8_t thr; - uint8_t id; - odp_time_t time; -} log_entry_t; - -typedef struct { - uint32_t iteration_num; - odp_atomic_u32_t iteration_counter; - odp_atomic_u32_t id_counter; - odp_atomic_u32_t log_counter; - odp_atomic_u32_t err_counter; - odp_barrier_t start_barrier; - odp_barrier_t end_barrier; - int thread_num; - log_entry_t *log; - int log_enries_num; -} test_globals_t; - -static void print_log(test_globals_t *gbls) -{ - uint32_t err_num; - int i, j, k, pad; - char line[LOG_LINE_SIZE]; - - memset(line, '-', LOG_LINE_SIZE - 1); - line[LOG_LINE_SIZE - 1] = 0; - for (i = 1; i <= gbls->thread_num; i++) { - printf("\n==== history of %d buffer, time,ns (thread) ====\n%s\n", - i, line); - - /* print log for buffer */ - k = 0; - for (j = 0; j < gbls->log_enries_num; j++) - if (gbls->log[j].id == i) { - printf("%10" PRIu64 " (%-3d)", - odp_time_to_ns(gbls->log[j].time), - gbls->log[j].thr); - - if (!(++k % LOG_BASE)) - printf(" |\n"); - else - printf(" =>"); - } - - if ((k % LOG_BASE)) { - pad = (LOG_BASE - k % LOG_BASE) * LOG_ENTRY_SIZE - 4; - printf(" end%*c\n%s\n", pad, '|', line); - } else { - printf("%s\n", line); - } - } - - printf("\n\n"); - - err_num = odp_atomic_load_u32(&gbls->err_counter); - if (err_num) - printf("Number of errors: %u\n", err_num); -} - -static void generate_next_queue(test_globals_t *gbls, odp_queue_t *queue, - unsigned int id) -{ - int thr; - uint8_t rand_u8; - char queue_name[sizeof(QUEUE_NAME_PREFIX) + 2]; - unsigned int rand_id = 1; - - thr = odp_thread_id(); - - /* generate next random id */ - if (gbls->thread_num > 1) { - do { - odp_random_data(&rand_u8, 1, ODP_RANDOM_BASIC); - rand_id = rand_u8 % gbls->thread_num + 1; - } while (rand_id == id); - } - - sprintf(queue_name, QUEUE_NAME_PREFIX "%d", rand_id); - *queue = odp_queue_lookup(queue_name); - - if (ODP_QUEUE_INVALID == *queue) - ODPH_ABORT("Cannot lookup thread queue \"%s\", thread %d\n", - queue_name, thr); -} - -static void test_global_timestamps(test_globals_t *gbls, - odp_queue_t queue, unsigned int id) -{ - int thr; - int log_entry; - odp_event_t ev; - odp_time_t time; - odp_buffer_t buf; - odp_queue_t queue_next; - timestamp_event_t *timestamp_ev; - - thr = odp_thread_id(); - while (odp_atomic_load_u32(&gbls->iteration_counter) < - gbls->iteration_num) { - ev = odp_queue_deq(queue); - - if (ev == ODP_EVENT_INVALID) - continue; - - buf = odp_buffer_from_event(ev); - timestamp_ev = (timestamp_event_t *)odp_buffer_addr(buf); - - time = odp_time_global(); - if (odp_time_cmp(time, timestamp_ev->timestamp) < 0) { - ODPH_ERR("timestamp is less than previous time_prev=%" - PRIu64 "ns, time_next=%" - PRIu64 "ns, thread %d\n", - odp_time_to_ns(timestamp_ev->timestamp), - odp_time_to_ns(time), thr); - odp_atomic_inc_u32(&gbls->err_counter); - } - - /* update the log */ - log_entry = odp_atomic_fetch_inc_u32(&gbls->log_counter); - gbls->log[log_entry].time = timestamp_ev->timestamp; - gbls->log[log_entry].id = timestamp_ev->id; - gbls->log[log_entry].thr = thr; - - /* assign new current time and send */ - generate_next_queue(gbls, &queue_next, id); - timestamp_ev->timestamp = time; - if (odp_queue_enq(queue_next, ev)) - ODPH_ABORT("Cannot enqueue event %" PRIu64 " on queue " - "%" PRIu64 ", thread %d\n", - odp_event_to_u64(ev), - odp_queue_to_u64(queue_next), thr); - - odp_atomic_inc_u32(&gbls->iteration_counter); - } -} - -/** - * @internal Worker thread - * - * @param ptr Pointer to test arguments - * - * @return Pointer to exit status - */ -static int run_thread(void *ptr) -{ - int thr; - uint32_t id; - odp_event_t ev; - odp_buffer_t buf; - test_globals_t *gbls; - odp_pool_t buffer_pool; - odp_queue_t queue, queue_next; - timestamp_event_t *timestamp_ev; - char queue_name[sizeof(QUEUE_NAME_PREFIX) + 2]; - - gbls = ptr; - thr = odp_thread_id(); - printf("Thread %i starts on cpu %i\n", thr, odp_cpu_id()); - - /* - * Allocate own queue for receiving timestamps. - * Own queue is needed to guarantee that next thread for receiving - * buffer is not the same thread. - */ - id = odp_atomic_fetch_inc_u32(&gbls->id_counter); - sprintf(queue_name, QUEUE_NAME_PREFIX "%d", id); - queue = odp_queue_create(queue_name, NULL); - if (queue == ODP_QUEUE_INVALID) - ODPH_ABORT("Cannot create thread queue, thread %d", thr); - - /* allocate buffer for timestamp */ - buffer_pool = odp_pool_lookup("time buffers pool"); - if (buffer_pool == ODP_POOL_INVALID) - ODPH_ABORT("Buffer pool was not found, thread %d\n", thr); - - buf = odp_buffer_alloc(buffer_pool); - if (buf == ODP_BUFFER_INVALID) - ODPH_ABORT("Buffer was not allocated, thread %d\n", thr); - - /* wait all threads allocated their queues */ - odp_barrier_wait(&gbls->start_barrier); - - /* enqueue global timestamp to some queue of some other thread */ - generate_next_queue(gbls, &queue_next, id); - - /* save global timestamp and id for tracing */ - ev = odp_buffer_to_event(buf); - timestamp_ev = (timestamp_event_t *)odp_buffer_addr(buf); - timestamp_ev->id = id; - timestamp_ev->timestamp = odp_time_global(); - if (odp_queue_enq(queue_next, ev)) - ODPH_ABORT("Cannot enqueue timestamp event %" PRIu64 " on " - "queue %" PRIu64 ", thread %d", odp_event_to_u64(ev), - odp_queue_to_u64(queue_next), thr); - - test_global_timestamps(gbls, queue, id); - - /* wait all threads are finished their jobs */ - odp_barrier_wait(&gbls->end_barrier); - - /* free all events on the allocated queue */ - while (1) { - ev = odp_queue_deq(queue); - if (ev == ODP_EVENT_INVALID) - break; - - buf = odp_buffer_from_event(ev); - odp_buffer_free(buf); - } - - /* free allocated queue */ - if (odp_queue_destroy(queue)) - ODPH_ABORT("Cannot destroy queue %" PRIu64 "", - odp_queue_to_u64(queue)); - - printf("Thread %i exits\n", thr); - fflush(NULL); - return 0; -} - -int main(int argc, char *argv[]) -{ - int err = 0; - odp_pool_t pool = ODP_POOL_INVALID; - int num_workers; - test_globals_t *gbls; - odp_cpumask_t cpumask; - odp_pool_capability_t pool_capa; - odp_pool_param_t pool_param; - odp_shm_t shm_glbls = ODP_SHM_INVALID; - odp_shm_t shm_log = ODP_SHM_INVALID; - int log_size, log_enries_num; - odph_helper_options_t helper_options; - odph_thread_t thread_tbl[MAX_WORKERS]; - odp_instance_t instance; - odp_init_t init_param; - odph_thread_common_param_t thr_common; - odph_thread_param_t thr_param; - - printf("\nODP global time test starts\n"); - - /* Let helper collect its own arguments (e.g. --odph_proc) */ - argc = odph_parse_options(argc, argv); - if (odph_options(&helper_options)) { - ODPH_ERR("Error: reading ODP helper options failed.\n"); - exit(EXIT_FAILURE); - } - - odp_init_param_init(&init_param); - init_param.mem_model = helper_options.mem_model; - - if (odp_init_global(&instance, &init_param, NULL)) { - err = 1; - ODPH_ERR("ODP global init failed.\n"); - goto end; - } - - /* Init this thread. */ - if (odp_init_local(instance, ODP_THREAD_CONTROL)) { - err = 1; - ODPH_ERR("ODP local init failed.\n"); - goto err_global; - } - - num_workers = MAX_WORKERS; - num_workers = odp_cpumask_default_worker(&cpumask, num_workers); - - shm_glbls = odp_shm_reserve("test_globals", sizeof(test_globals_t), - ODP_CACHE_LINE_SIZE, 0); - if (ODP_SHM_INVALID == shm_glbls) { - err = 1; - ODPH_ERR("Error: shared mem reserve failed.\n"); - goto err; - } - - log_enries_num = num_workers * (ITERATION_NUM + num_workers); - log_size = sizeof(log_entry_t) * log_enries_num; - shm_log = odp_shm_reserve("test_log", log_size, ODP_CACHE_LINE_SIZE, 0); - if (ODP_SHM_INVALID == shm_log) { - err = 1; - ODPH_ERR("Error: shared mem reserve failed.\n"); - goto err; - } - - gbls = odp_shm_addr(shm_glbls); - gbls->thread_num = num_workers; - gbls->iteration_num = ITERATION_NUM; - odp_atomic_store_u32(&gbls->iteration_counter, 0); - odp_atomic_store_u32(&gbls->id_counter, 1); - odp_atomic_store_u32(&gbls->log_counter, 0); - odp_atomic_store_u32(&gbls->err_counter, 0); - gbls->log_enries_num = log_enries_num; - gbls->log = odp_shm_addr(shm_log); - odp_barrier_init(&gbls->start_barrier, num_workers); - odp_barrier_init(&gbls->end_barrier, num_workers); - memset(gbls->log, 0, log_size); - - if (odp_pool_capability(&pool_capa)) { - err = 1; - ODPH_ERR("Error: pool capability failed.\n"); - goto err; - } - - odp_pool_param_init(&pool_param); - - pool_param.buf.size = sizeof(timestamp_event_t); - pool_param.buf.num = MAX_NUM_BUF; - pool_param.type = ODP_POOL_BUFFER; - - if (pool_capa.buf.max_num && MAX_NUM_BUF > pool_capa.buf.max_num) - pool_param.buf.num = pool_capa.buf.max_num; - - pool = odp_pool_create("time buffers pool", &pool_param); - if (pool == ODP_POOL_INVALID) { - err = 1; - ODPH_ERR("Pool create failed.\n"); - goto err; - } - - odph_thread_common_param_init(&thr_common); - odph_thread_param_init(&thr_param); - - thr_param.start = run_thread; - thr_param.arg = gbls; - thr_param.thr_type = ODP_THREAD_WORKER; - - thr_common.instance = instance; - thr_common.cpumask = &cpumask; - thr_common.share_param = 1; - - /* Create and launch worker threads */ - odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers); - - /* Wait for worker threads to exit */ - odph_thread_join(thread_tbl, num_workers); - - print_log(gbls); - -err: - if (pool != ODP_POOL_INVALID) - if (odp_pool_destroy(pool)) - err = 1; - - if (shm_log != ODP_SHM_INVALID) - if (odp_shm_free(shm_log)) - err = 1; - - if (shm_glbls != ODP_SHM_INVALID) - if (odp_shm_free(shm_glbls)) - err = 1; - - if (odp_term_local()) - err = 1; -err_global: - if (odp_term_global(instance)) - err = 1; -end: - if (err) { - ODPH_ERR("Err: ODP global time test failed\n\n"); - return -1; - } - - printf("ODP global time test complete\n\n"); - return 0; -} -- cgit v1.2.3 From 992e1161c8bb5841205fc2c906d8608b08090098 Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Wed, 14 Feb 2024 17:06:22 +0200 Subject: example: timer: remove odp_timer_test example application The odp_timer_test example application has been made redundant by odp_timer_accuracy performance test application. Signed-off-by: Matias Elo Reviewed-by: Janne Peltonen --- example/timer/.gitignore | 1 - example/timer/Makefile.am | 5 +- example/timer/odp_timer_test.c | 569 ----------------------------------------- 3 files changed, 1 insertion(+), 574 deletions(-) delete mode 100644 example/timer/odp_timer_test.c (limited to 'example') diff --git a/example/timer/.gitignore b/example/timer/.gitignore index 2b077829d..952d1bee6 100644 --- a/example/timer/.gitignore +++ b/example/timer/.gitignore @@ -1,5 +1,4 @@ *.log *.trs odp_timer_accuracy -odp_timer_test odp_timer_simple diff --git a/example/timer/Makefile.am b/example/timer/Makefile.am index 66cf0edfb..4d5fac99d 100644 --- a/example/timer/Makefile.am +++ b/example/timer/Makefile.am @@ -1,15 +1,12 @@ include $(top_srcdir)/example/Makefile.inc bin_PROGRAMS = odp_timer_accuracy \ - odp_timer_simple \ - odp_timer_test + odp_timer_simple odp_timer_accuracy_SOURCES = odp_timer_accuracy.c odp_timer_simple_SOURCES = odp_timer_simple.c -odp_timer_test_SOURCES = odp_timer_test.c - if test_example TESTS = odp_timer_accuracy_run.sh \ odp_timer_simple diff --git a/example/timer/odp_timer_test.c b/example/timer/odp_timer_test.c deleted file mode 100644 index 674d4f4ce..000000000 --- a/example/timer/odp_timer_test.c +++ /dev/null @@ -1,569 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright (c) 2013-2018 Linaro Limited - */ - -/** - * @example odp_timer_test.c - * - * Timer test application - * - * @cond _ODP_HIDE_FROM_DOXYGEN_ - */ - -#include -#include -#include - -/* ODP main header */ -#include - -/* ODP helper for Linux apps */ -#include - -/* GNU lib C */ -#include - -/* Max worker threads */ -#define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1) -#define NUM_TMOS 10000 /**< Number of timers */ -#define WAIT_NUM 10 /**< Max tries to rx last tmo per worker */ - -/** Test arguments */ -typedef struct { - unsigned int cpu_count; /**< CPU count*/ - int resolution_us; /**< Timeout resolution in usec*/ - int min_us; /**< Minimum timeout in usec*/ - int max_us; /**< Maximum timeout in usec*/ - int period_us; /**< Timeout period in usec*/ - int tmo_count; /**< Timeout count*/ -} test_args_t; - -/** @private Helper struct for timers */ -struct test_timer { - odp_timer_t tim; - odp_event_t ev; -}; - -/** Test global variables */ -typedef struct { - test_args_t args; /**< Test argunments*/ - odp_barrier_t test_barrier; /**< Barrier for test synchronisation*/ - odp_pool_t pool; /**< pool handle*/ - odp_timer_pool_t tp; /**< Timer pool handle*/ - odp_atomic_u32_t remain; /**< Number of timeouts to receive*/ - struct test_timer tt[256]; /**< Array of all timer helper structs*/ - uint32_t num_workers; /**< Number of threads */ -} test_globals_t; - -/** @private Timer set status ASCII strings */ -static const char *timerset2str(odp_timer_retval_t val) -{ - switch (val) { - case ODP_TIMER_SUCCESS: - return "success"; - case ODP_TIMER_TOO_NEAR: - return "too near"; - case ODP_TIMER_TOO_FAR: - return "too far"; - case ODP_TIMER_FAIL: - return "failure"; - default: - return "?"; - } -} - -/** @private test timeout */ -static void remove_prescheduled_events(void) -{ - odp_event_t ev; - odp_queue_t queue; - odp_schedule_pause(); - while ((ev = odp_schedule(&queue, ODP_SCHED_NO_WAIT)) != - ODP_EVENT_INVALID) { - odp_event_free(ev); - } -} - -/** @private test timeout */ -static void test_abs_timeouts(int thr, test_globals_t *gbls) -{ - uint64_t period; - uint64_t period_ns; - odp_queue_t queue; - uint64_t tick; - struct test_timer *ttp; - odp_timeout_t tmo; - uint32_t num_workers = gbls->num_workers; - - ODPH_DBG(" [%i] test_timeouts\n", thr); - - queue = odp_queue_lookup("timer_queue"); - - period_ns = gbls->args.period_us * ODP_TIME_USEC_IN_NS; - period = odp_timer_ns_to_tick(gbls->tp, period_ns); - - ODPH_DBG(" [%i] period %" PRIu64 " ticks, %" PRIu64 " ns\n", thr, - period, period_ns); - - ODPH_DBG(" [%i] current tick %" PRIu64 "\n", thr, - odp_timer_current_tick(gbls->tp)); - - ttp = &gbls->tt[thr]; - ttp->tim = odp_timer_alloc(gbls->tp, queue, ttp); - if (ttp->tim == ODP_TIMER_INVALID) { - ODPH_ERR("Failed to allocate timer\n"); - return; - } - tmo = odp_timeout_alloc(gbls->pool); - if (tmo == ODP_TIMEOUT_INVALID) { - ODPH_ERR("Failed to allocate timeout\n"); - return; - } - ttp->ev = odp_timeout_to_event(tmo); - tick = odp_timer_current_tick(gbls->tp); - - while (1) { - int wait = 0; - odp_event_t ev; - odp_timer_retval_t rc; - odp_timer_start_t start_param; - - if (ttp) { - tick += period; - - start_param.tick_type = ODP_TIMER_TICK_ABS; - start_param.tick = tick; - start_param.tmo_ev = ttp->ev; - - rc = odp_timer_start(ttp->tim, &start_param); - if (odp_unlikely(rc != ODP_TIMER_SUCCESS)) { - /* Too early or too late timeout requested */ - ODPH_ABORT("odp_timer_start() failed: %s\n", timerset2str(rc)); - } - } - - /* Get the next expired timeout. - * We invoke the scheduler in a loop with a timeout because - * we are not guaranteed to receive any more timeouts. The - * scheduler isn't guaranteeing fairness when scheduling - * buffers to threads. - * Use 1.5 second timeout for scheduler */ - uint64_t sched_tmo = - odp_schedule_wait_time(1500000000ULL); - do { - ev = odp_schedule(&queue, sched_tmo); - /* Check if odp_schedule() timed out, possibly there - * are no remaining timeouts to receive */ - if (++wait > WAIT_NUM && - odp_atomic_load_u32(&gbls->remain) < num_workers) - ODPH_ABORT("At least one TMO was lost\n"); - } while (ev == ODP_EVENT_INVALID && - (int)odp_atomic_load_u32(&gbls->remain) > 0); - - if (ev == ODP_EVENT_INVALID) - break; /* No more timeouts */ - if (odp_event_type(ev) != ODP_EVENT_TIMEOUT) { - /* Not a default timeout event */ - ODPH_ABORT("Unexpected event type (%u) received\n", - odp_event_type(ev)); - } - tmo = odp_timeout_from_event(ev); - tick = odp_timeout_tick(tmo); - ttp = odp_timeout_user_ptr(tmo); - ttp->ev = ev; - - ODPH_DBG(" [%i] timeout, tick %" PRIu64 "\n", thr, tick); - - uint32_t rx_num = odp_atomic_fetch_dec_u32(&gbls->remain); - - if (!rx_num) - ODPH_ABORT("Unexpected timeout received (timer " - "%" PRIu64 ", tick %" PRIu64 ")\n", - odp_timer_to_u64(ttp->tim), tick); - else if (rx_num > num_workers) - continue; - - odp_event_free(ttp->ev); - - if (odp_timer_free(ttp->tim)) - ODPH_ABORT("Timer free failed (%" PRIu64 ")\n", odp_timer_to_u64(ttp->tim)); - - ttp = NULL; - } - - /* Remove any prescheduled events */ - remove_prescheduled_events(); -} - - -/** - * @internal Worker thread - * - * @param ptr Pointer to test arguments - * - * @return Pointer to exit status - */ -static int run_thread(void *ptr) -{ - int thr; - odp_pool_t msg_pool; - test_globals_t *gbls; - - gbls = ptr; - thr = odp_thread_id(); - - printf("Thread %i starts on cpu %i\n", thr, odp_cpu_id()); - - /* - * Find the pool - */ - msg_pool = odp_pool_lookup("msg_pool"); - - if (msg_pool == ODP_POOL_INVALID) { - ODPH_ERR(" [%i] msg_pool not found\n", thr); - return -1; - } - - odp_barrier_wait(&gbls->test_barrier); - - test_abs_timeouts(thr, gbls); - - - printf("Thread %i exits\n", thr); - fflush(NULL); - return 0; -} - - -/** - * @internal Print help - */ -static void print_usage(void) -{ - printf("\n\nUsage: ./odp_example [options]\n"); - printf("Options:\n"); - printf(" -c, --count CPU count, 0=all available, default=1\n"); - printf(" -r, --resolution timeout resolution in usec\n"); - printf(" -m, --min minimum timeout in usec\n"); - printf(" -x, --max maximum timeout in usec\n"); - printf(" -p, --period timeout period in usec\n"); - printf(" -t, --timeouts timeout repeat count\n"); - printf(" -h, --help this help\n"); - printf("\n\n"); -} - - -/** - * @internal Parse arguments - * - * @param argc Argument count - * @param argv Argument vector - * @param args Test arguments - */ -static int parse_args(int argc, char *argv[], test_args_t *args) -{ - int opt; - int long_index; - odp_timer_capability_t timer_capa; - - static const struct option longopts[] = { - {"count", required_argument, NULL, 'c'}, - {"resolution", required_argument, NULL, 'r'}, - {"min", required_argument, NULL, 'm'}, - {"max", required_argument, NULL, 'x'}, - {"period", required_argument, NULL, 'p'}, - {"timeouts", required_argument, NULL, 't'}, - {"help", no_argument, NULL, 'h'}, - {NULL, 0, NULL, 0} - }; - - static const char *shortopts = "+c:r:m:x:p:t:h"; - - /* defaults */ - if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) - return -1; - - args->cpu_count = 1; - args->resolution_us = ODPH_MAX(10000u, timer_capa.highest_res_ns / ODP_TIME_USEC_IN_NS); - args->min_us = 0; - args->max_us = 10000000; - args->period_us = 1000000; - args->tmo_count = 30; - - while (1) { - opt = getopt_long(argc, argv, shortopts, longopts, &long_index); - - if (opt == -1) - break; /* No more options */ - - switch (opt) { - case 'c': - args->cpu_count = atoi(optarg); - break; - case 'r': - args->resolution_us = atoi(optarg); - break; - case 'm': - args->min_us = atoi(optarg); - break; - case 'x': - args->max_us = atoi(optarg); - break; - case 'p': - args->period_us = atoi(optarg); - break; - case 't': - args->tmo_count = atoi(optarg); - break; - case 'h': - print_usage(); - exit(EXIT_SUCCESS); - break; - - default: - break; - } - } - - if (args->period_us < args->resolution_us) - printf("\n\tWarn: timeout is set less then resolution\n"); - - return 0; -} - -/** - * Test main function - */ -int main(int argc, char *argv[]) -{ - odph_helper_options_t helper_options; - odph_thread_t thread_tbl[MAX_WORKERS]; - odph_thread_common_param_t thr_common; - odph_thread_param_t thr_param; - 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_instance_t instance; - odp_init_t init_param; - odp_shm_t shm = ODP_SHM_INVALID; - test_globals_t *gbls = NULL; - int err = 0; - - printf("\nODP timer example starts\n"); - - /* Let helper collect its own arguments (e.g. --odph_proc) */ - argc = odph_parse_options(argc, argv); - if (odph_options(&helper_options)) { - ODPH_ERR("Error: reading ODP helper options failed.\n"); - exit(EXIT_FAILURE); - } - - odp_init_param_init(&init_param); - init_param.mem_model = helper_options.mem_model; - - if (odp_init_global(&instance, &init_param, NULL)) { - err = 1; - printf("ODP global init failed.\n"); - goto err_global; - } - - /* Init this thread. */ - if (odp_init_local(instance, ODP_THREAD_CONTROL)) { - err = 1; - printf("ODP local init failed.\n"); - goto err_local; - } - - printf("\n"); - odp_sys_info_print(); - - /* 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; - ODPH_ERR("Error: shared mem reserve failed.\n"); - goto err; - } - - gbls = odp_shm_addr(shm); - if (NULL == gbls) { - err = 1; - ODPH_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; - - if (parse_args(argc, argv, &gbls->args)) { - ODPH_ERR("Parse args failed.\n"); - goto err; - } - - memset(thread_tbl, 0, sizeof(thread_tbl)); - - num_workers = MAX_WORKERS; - if (gbls->args.cpu_count && gbls->args.cpu_count < MAX_WORKERS) - 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); - - /* Configure scheduler */ - odp_schedule_config(NULL); - - /* - * 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; - ODPH_ERR("Pool create failed.\n"); - goto err; - } - - odp_timer_pool_param_init(&tparams); - 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_DEFAULT; - - gbls->tp = odp_timer_pool_create("timer_pool", &tparams); - if (gbls->tp == ODP_TIMER_POOL_INVALID) { - err = 1; - ODPH_ERR("Timer pool create failed.\n"); - goto err; - } - - if (odp_timer_pool_start_multi(&gbls->tp, 1) != 1) { - ODPH_ERR("Timer pool start failed\n"); - return -1; - } - - 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_schedule_default_prio(); - 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; - ODPH_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_thread_common_param_init(&thr_common); - thr_common.instance = instance; - thr_common.cpumask = &cpumask; - thr_common.share_param = 1; - - odph_thread_param_init(&thr_param); - thr_param.start = run_thread; - thr_param.arg = gbls; - thr_param.thr_type = ODP_THREAD_WORKER; - - odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers); - - /* Wait for worker threads to exit */ - odph_thread_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_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(instance)) - 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; -} -- cgit v1.2.3 From 35815f4e901f8090b3345142a5ab3e23e39b2971 Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Wed, 14 Feb 2024 17:14:17 +0200 Subject: example: timer: move timer accuraty test to performance directory odp_timer_accuracy application belongs to the performance test directory. Signed-off-by: Matias Elo Reviewed-by: Janne Peltonen --- example/timer/.gitignore | 1 - example/timer/Makefile.am | 10 +- example/timer/odp_timer_accuracy.c | 1435 ------------------------------- example/timer/odp_timer_accuracy_run.sh | 7 - 4 files changed, 2 insertions(+), 1451 deletions(-) delete mode 100644 example/timer/odp_timer_accuracy.c delete mode 100755 example/timer/odp_timer_accuracy_run.sh (limited to 'example') diff --git a/example/timer/.gitignore b/example/timer/.gitignore index 952d1bee6..9502b573b 100644 --- a/example/timer/.gitignore +++ b/example/timer/.gitignore @@ -1,4 +1,3 @@ *.log *.trs -odp_timer_accuracy odp_timer_simple diff --git a/example/timer/Makefile.am b/example/timer/Makefile.am index 4d5fac99d..007a2842b 100644 --- a/example/timer/Makefile.am +++ b/example/timer/Makefile.am @@ -1,15 +1,9 @@ include $(top_srcdir)/example/Makefile.inc -bin_PROGRAMS = odp_timer_accuracy \ - odp_timer_simple - -odp_timer_accuracy_SOURCES = odp_timer_accuracy.c +bin_PROGRAMS = odp_timer_simple odp_timer_simple_SOURCES = odp_timer_simple.c if test_example -TESTS = odp_timer_accuracy_run.sh \ - odp_timer_simple +TESTS = odp_timer_simple endif - -EXTRA_DIST = odp_timer_accuracy_run.sh diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c deleted file mode 100644 index e5df1c24e..000000000 --- a/example/timer/odp_timer_accuracy.c +++ /dev/null @@ -1,1435 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright (c) 2018 Linaro Limited - * Copyright (c) 2019-2023 Nokia - */ - -/** - * @example odp_timer_accuracy.c - * - * ODP timer accuracy test application - * - * @cond _ODP_HIDE_FROM_DOXYGEN_ - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1) -#define MAX_QUEUES 1024 -#define MAX_FILENAME 128 - -enum mode_e { - MODE_ONESHOT = 0, - MODE_RESTART_ABS, - MODE_RESTART_REL, - MODE_PERIODIC, -}; - -typedef struct test_opt_t { - int cpu_count; - unsigned long long period_ns; - long long res_ns; - unsigned long long res_hz; - unsigned long long offset_ns; - unsigned long long max_tmo_ns; - unsigned long long num; - unsigned long long num_warmup; - unsigned long long burst; - unsigned long long burst_gap; - odp_fract_u64_t freq; - unsigned long long max_multiplier; - unsigned long long multiplier; - enum mode_e mode; - int clk_src; - odp_queue_type_t queue_type; - int num_queue; - int groups; - int init; - int output; - int early_retry; - uint64_t warmup_timers; - uint64_t tot_timers; - uint64_t alloc_timers; - char filename[MAX_FILENAME + 1]; -} test_opt_t; - -typedef struct timer_ctx_t { - odp_timer_t timer; - odp_event_t event; - uint64_t nsec; - uint64_t count; - uint64_t first_period; - int tmo_tick; - int64_t first_tmo_diff; - int64_t nsec_final; - -} timer_ctx_t; - -typedef struct { - uint64_t nsec_before_sum; - uint64_t nsec_before_min; - uint64_t nsec_before_min_idx; - uint64_t nsec_before_max; - uint64_t nsec_before_max_idx; - - uint64_t nsec_after_sum; - uint64_t nsec_after_min; - uint64_t nsec_after_min_idx; - uint64_t nsec_after_max; - uint64_t nsec_after_max_idx; - - uint64_t num_before; - uint64_t num_exact; - uint64_t num_after; - - uint64_t num_too_near; - -} test_stat_t; - -typedef struct test_log_t { - uint64_t tmo_ns; - int64_t diff_ns; - int tid; - -} test_log_t; - -typedef struct test_global_t { - test_opt_t opt; - - test_stat_t stat[MAX_WORKERS]; - - odp_queue_t queue[MAX_QUEUES]; - odp_schedule_group_t group[MAX_WORKERS]; - odp_timer_pool_t timer_pool; - odp_pool_t timeout_pool; - timer_ctx_t *timer_ctx; - double res_ns; - uint64_t start_tick; - uint64_t start_ns; - uint64_t period_tick; - double period_dbl; - odp_fract_u64_t base_freq; - test_log_t *log; - FILE *file; - odp_barrier_t barrier; - odp_atomic_u64_t events; - odp_atomic_u64_t last_events; - -} test_global_t; - -static void print_usage(void) -{ - printf("\n" - "Timer accuracy test application.\n" - "\n" - "OPTIONS:\n" - " -c, --count CPU count, 0=all available, default=1\n" - " -p, --period Timeout period in nsec. Not used in periodic mode. Default: 200 msec\n" - " -r, --res_ns Timeout resolution in nsec. Default value is 0. Special values:\n" - " 0: Use period / 10 as the resolution\n" - " -1: In periodic mode, use resolution from capabilities\n" - " -R, --res_hz Timeout resolution in hertz. Set resolution either with -r (nsec) or -R (hertz),\n" - " and leave other to 0. Default: 0 (not used)\n" - " -f, --first First timer offset in nsec. Default: 0 for periodic mode, otherwise 300 msec\n" - " -x, --max_tmo Maximum timeout in nsec. Not used in periodic mode.\n" - " When 0, max tmo is calculated from other options. Default: 0\n" - " -n, --num Number of timeout periods. Default: 50\n" - " -w, --warmup Number of warmup periods. Default: 0\n" - " -b, --burst Number of timers per a timeout period. Default: 1\n" - " -g, --burst_gap Gap (in nsec) between timers within a burst. Default: 0\n" - " In periodic mode, first + burst * burst_gap must be less than period length.\n" - " -m, --mode Test mode select (default: 0):\n" - " 0: One-shot. Start all timers at init phase.\n" - " 1: One-shot. Each period, restart timers with absolute time.\n" - " 2: One-shot. Each period, restart timers with relative time.\n" - " 3: Periodic.\n" - " -P, --periodic \n" - " Periodic timer pool parameters. Default: 5:0:0:1 (5 Hz)\n" - " -M, --multiplier Periodic timer multiplier. Default: 1\n" - " -o, --output Output file for measurement logs\n" - " -e, --early_retry When timer restart fails due to ODP_TIMER_TOO_NEAR, retry this many times\n" - " with expiration time incremented by the period. Default: 0\n" - " -s, --clk_src Clock source select (default 0):\n" - " 0: ODP_CLOCK_DEFAULT\n" - " 1: ODP_CLOCK_SRC_1, ...\n" - " -t, --queue_type Queue sync type. Default is 0 (PARALLEL).\n" - " 0: PARALLEL\n" - " 1: ATOMIC\n" - " 2: ORDERED\n" - " -q, --num_queue Number of queues. Default is 1.\n" - " -G, --sched_groups Use dedicated schedule group for each worker.\n" - " -i, --init Set global init parameters. Default: init params not set.\n" - " -h, --help Display help and exit.\n\n"); -} - -static int parse_options(int argc, char *argv[], test_opt_t *test_opt) -{ - int opt, long_index; - const struct option longopts[] = { - {"count", required_argument, NULL, 'c'}, - {"period", required_argument, NULL, 'p'}, - {"res_ns", required_argument, NULL, 'r'}, - {"res_hz", required_argument, NULL, 'R'}, - {"first", required_argument, NULL, 'f'}, - {"max_tmo", required_argument, NULL, 'x'}, - {"num", required_argument, NULL, 'n'}, - {"warmup", required_argument, NULL, 'w'}, - {"burst", required_argument, NULL, 'b'}, - {"burst_gap", required_argument, NULL, 'g'}, - {"mode", required_argument, NULL, 'm'}, - {"periodic", required_argument, NULL, 'P'}, - {"multiplier", required_argument, NULL, 'M'}, - {"output", required_argument, NULL, 'o'}, - {"early_retry", required_argument, NULL, 'e'}, - {"clk_src", required_argument, NULL, 's'}, - {"queue_type", required_argument, NULL, 't'}, - {"num_queue", required_argument, NULL, 'q'}, - {"sched_groups", no_argument, NULL, 'G'}, - {"init", no_argument, NULL, 'i'}, - {"help", no_argument, NULL, 'h'}, - {NULL, 0, NULL, 0} - }; - const char *shortopts = "+c:p:r:R:f:x:n:w:b:g:m:P:M:o:e:s:t:q:Gih"; - int ret = 0; - - memset(test_opt, 0, sizeof(*test_opt)); - - test_opt->cpu_count = 1; - test_opt->period_ns = 200 * ODP_TIME_MSEC_IN_NS; - test_opt->res_ns = 0; - test_opt->res_hz = 0; - test_opt->offset_ns = UINT64_MAX; - test_opt->max_tmo_ns = 0; - test_opt->num = 50; - test_opt->num_warmup = 0; - test_opt->burst = 1; - test_opt->burst_gap = 0; - test_opt->mode = MODE_ONESHOT; - test_opt->freq.integer = ODP_TIME_SEC_IN_NS / test_opt->period_ns; - test_opt->freq.numer = 0; - test_opt->freq.denom = 0; - test_opt->max_multiplier = 1; - test_opt->multiplier = 1; - test_opt->clk_src = ODP_CLOCK_DEFAULT; - test_opt->queue_type = ODP_SCHED_SYNC_PARALLEL; - test_opt->groups = 0; - test_opt->num_queue = 1; - test_opt->init = 0; - test_opt->output = 0; - test_opt->early_retry = 0; - - while (1) { - opt = getopt_long(argc, argv, shortopts, longopts, &long_index); - - if (opt == -1) - break; /* No more options */ - - switch (opt) { - case 'c': - test_opt->cpu_count = atoi(optarg); - break; - case 'p': - test_opt->period_ns = strtoull(optarg, NULL, 0); - break; - case 'r': - test_opt->res_ns = strtoll(optarg, NULL, 0); - break; - case 'R': - test_opt->res_hz = strtoull(optarg, NULL, 0); - break; - case 'f': - test_opt->offset_ns = strtoull(optarg, NULL, 0); - break; - case 'x': - test_opt->max_tmo_ns = strtoull(optarg, NULL, 0); - break; - case 'n': - test_opt->num = strtoull(optarg, NULL, 0); - break; - case 'w': - test_opt->num_warmup = strtoull(optarg, NULL, 0); - break; - case 'b': - test_opt->burst = strtoull(optarg, NULL, 0); - break; - case 'g': - test_opt->burst_gap = strtoull(optarg, NULL, 0); - break; - case 'm': - test_opt->mode = atoi(optarg); - break; - case 'P': - sscanf(optarg, "%" SCNu64 ":%" SCNu64 ":%" SCNu64 ":%llu", - &test_opt->freq.integer, &test_opt->freq.numer, - &test_opt->freq.denom, &test_opt->max_multiplier); - break; - case 'M': - test_opt->multiplier = strtoull(optarg, NULL, 0); - break; - case 'o': - test_opt->output = 1; - /* filename is NULL terminated in anycase */ - strncpy(test_opt->filename, optarg, MAX_FILENAME); - break; - case 'e': - test_opt->early_retry = atoi(optarg); - break; - case 's': - test_opt->clk_src = atoi(optarg); - break; - case 't': - switch (atoi(optarg)) { - case 1: - test_opt->queue_type = ODP_SCHED_SYNC_ATOMIC; - break; - case 2: - test_opt->queue_type = ODP_SCHED_SYNC_ORDERED; - break; - default: - test_opt->queue_type = ODP_SCHED_SYNC_PARALLEL; - break; - } - break; - case 'q': - test_opt->num_queue = atoi(optarg); - break; - case 'G': - test_opt->groups = 1; - break; - case 'i': - test_opt->init = 1; - break; - case 'h': - print_usage(); - ret = -1; - break; - default: - print_usage(); - ret = -1; - break; - } - } - - if (test_opt->mode == MODE_PERIODIC) { - if ((test_opt->freq.integer == 0 && test_opt->freq.numer == 0) || - (test_opt->freq.numer != 0 && test_opt->freq.denom == 0)) { - printf("Bad frequency\n"); - return -1; - } - - test_opt->period_ns = - ODP_TIME_SEC_IN_NS / odp_fract_u64_to_dbl(&test_opt->freq); - - if (test_opt->offset_ns == UINT64_MAX) - test_opt->offset_ns = 0; - } else { - if (test_opt->res_ns < 0) { - printf("Resolution (res_ns) must be >= 0 with single shot timer\n"); - return -1; - } - - if (test_opt->offset_ns == UINT64_MAX) - test_opt->offset_ns = 300 * ODP_TIME_MSEC_IN_NS; - } - - test_opt->warmup_timers = test_opt->num_warmup * test_opt->burst; - test_opt->tot_timers = - test_opt->warmup_timers + test_opt->num * test_opt->burst; - - if (test_opt->mode == MODE_ONESHOT) - test_opt->alloc_timers = test_opt->tot_timers; - else - test_opt->alloc_timers = test_opt->burst; - - return ret; -} - -static int single_shot_params(test_global_t *test_global, odp_timer_pool_param_t *timer_param, - odp_timer_capability_t *timer_capa) -{ - uint64_t res_ns, res_hz; - uint64_t max_res_ns, max_res_hz; - uint64_t period_ns = test_global->opt.period_ns; - uint64_t num_tmo = test_global->opt.num + test_global->opt.num_warmup; - uint64_t offset_ns = test_global->opt.offset_ns; - enum mode_e mode = test_global->opt.mode; - - max_res_ns = timer_capa->max_res.res_ns; - max_res_hz = timer_capa->max_res.res_hz; - - /* Default resolution */ - if (test_global->opt.res_ns == 0 && test_global->opt.res_hz == 0) { - res_ns = test_global->opt.period_ns / 10; - res_hz = 0; - } else if (test_global->opt.res_ns) { - res_ns = test_global->opt.res_ns; - res_hz = 0; - } else { - res_ns = 0; - res_hz = test_global->opt.res_hz; - } - - if (res_ns && res_ns < max_res_ns) { - printf("Resolution %" PRIu64 " nsec too high. Highest resolution %" PRIu64 " nsec. " - "Default resolution is period / 10.\n\n", - res_ns, max_res_ns); - return -1; - } - - if (res_hz && res_hz > max_res_hz) { - printf("Resolution %" PRIu64 " hz too high. Highest resolution %" PRIu64 " hz. " - "Default resolution is period / 10.\n\n", - res_hz, max_res_hz); - return -1; - } - - if (res_ns) - timer_param->res_ns = res_ns; - else - timer_param->res_hz = res_hz; - - if (mode == MODE_ONESHOT) { - timer_param->min_tmo = offset_ns / 2; - timer_param->max_tmo = offset_ns + ((num_tmo + 1) * period_ns); - } else { - timer_param->min_tmo = period_ns / 10; - timer_param->max_tmo = offset_ns + (2 * period_ns); - } - - if (test_global->opt.max_tmo_ns) { - if (test_global->opt.max_tmo_ns < timer_param->max_tmo) { - printf("Max tmo is too small. Must be at least %" PRIu64 " nsec.\n", - timer_param->max_tmo); - return -1; - } - - timer_param->max_tmo = test_global->opt.max_tmo_ns; - } - - printf(" period: %" PRIu64 " nsec\n", period_ns); - printf(" max res nsec: %" PRIu64 "\n", max_res_ns); - printf(" max res hertz: %" PRIu64 "\n", max_res_hz); - - test_global->period_dbl = period_ns; - - return 0; -} - -static int periodic_params(test_global_t *test_global, odp_timer_pool_param_t *timer_param, - odp_timer_capability_t *timer_capa) -{ - int ret; - uint64_t res_ns; - odp_timer_periodic_capability_t capa; - double freq_dbl, min_freq, max_freq; - double opt_freq = odp_fract_u64_to_dbl(&test_global->opt.freq); - odp_fract_u64_t freq = test_global->opt.freq; - uint64_t res_hz = test_global->opt.res_hz; - uint64_t max_multiplier = test_global->opt.max_multiplier; - uint64_t multiplier = test_global->opt.multiplier; - - if (res_hz) { - res_ns = ODP_TIME_SEC_IN_NS / res_hz; - } else { - res_ns = test_global->opt.res_ns; - - /* Default resolution */ - if (res_ns == 0) - res_ns = ODP_TIME_SEC_IN_NS / (10 * multiplier * opt_freq); - } - - if (res_ns == 0) { - printf("Too high resolution\n"); - return -1; - } - - /* Resolution from capa */ - if (test_global->opt.res_ns < 0) - res_ns = 0; - - min_freq = odp_fract_u64_to_dbl(&timer_capa->periodic.min_base_freq_hz); - max_freq = odp_fract_u64_to_dbl(&timer_capa->periodic.max_base_freq_hz); - - capa.base_freq_hz = freq; - capa.max_multiplier = max_multiplier; - capa.res_ns = res_ns; - - ret = odp_timer_periodic_capability(test_global->opt.clk_src, &capa); - - if (ret < 0) { - printf("Requested periodic timer capabilities are not supported.\n" - "Capabilities: min base freq %g Hz, max base freq %g Hz, " - "max res %" PRIu64 " Hz\n", min_freq, max_freq, timer_capa->max_res.res_hz); - return -1; - } - - if (ret == 0) { - printf("Requested base frequency is not met. Using %.2f Hz instead of %.2f Hz.\n", - odp_fract_u64_to_dbl(&capa.base_freq_hz), opt_freq); - - freq = capa.base_freq_hz; - } - - if (res_ns == 0) - res_ns = capa.res_ns; - - freq_dbl = odp_fract_u64_to_dbl(&freq); - test_global->base_freq = freq; - test_global->period_dbl = ODP_TIME_SEC_IN_NS / (multiplier * freq_dbl); - - /* Min/max tmo are ignored, leave those to default values */ - timer_param->timer_type = ODP_TIMER_TYPE_PERIODIC; - timer_param->periodic.base_freq_hz = freq; - timer_param->periodic.max_multiplier = max_multiplier; - - if (res_hz) - timer_param->res_hz = res_hz; - else - timer_param->res_ns = res_ns; - - printf(" min freq capa: %.2f hz\n", min_freq); - printf(" max freq capa: %.2f hz\n", max_freq); - printf(" freq option: %.2f hz\n", opt_freq); - printf(" freq: %.2f hz\n", freq_dbl); - printf(" freq integer: %" PRIu64 "\n", freq.integer); - printf(" freq numer: %" PRIu64 "\n", freq.numer); - printf(" freq denom: %" PRIu64 "\n", freq.denom); - printf(" max_multiplier: %" PRIu64 "\n", max_multiplier); - printf(" multiplier: %" PRIu64 "\n", multiplier); - printf(" timer freq: %.2f hz\n", multiplier * freq_dbl); - printf(" timer period: %.2f nsec\n", test_global->period_dbl); - printf(" resolution capa: %" PRIu64 " nsec\n", capa.res_ns); - - return 0; -} - -static int create_timers(test_global_t *test_global) -{ - odp_pool_t pool; - odp_pool_param_t pool_param; - odp_timer_pool_t timer_pool; - odp_timer_pool_param_t timer_param; - odp_timer_capability_t timer_capa; - odp_timer_t timer; - odp_queue_t *queue; - odp_schedule_group_t *group; - odp_queue_param_t queue_param; - uint64_t offset_ns; - uint32_t max_timers; - odp_event_t event; - odp_timeout_t timeout; - uint64_t i, num_tmo, num_warmup, burst, burst_gap; - uint64_t tot_timers, alloc_timers; - enum mode_e mode; - odp_timer_clk_src_t clk_src; - int ret; - - mode = test_global->opt.mode; - alloc_timers = test_global->opt.alloc_timers; - tot_timers = test_global->opt.tot_timers; - num_warmup = test_global->opt.num_warmup; - num_tmo = num_warmup + test_global->opt.num; - burst = test_global->opt.burst; - burst_gap = test_global->opt.burst_gap; - offset_ns = test_global->opt.offset_ns; - queue = test_global->queue; - group = test_global->group; - - /* Always init globals for destroy calls */ - test_global->timer_pool = ODP_TIMER_POOL_INVALID; - test_global->timeout_pool = ODP_POOL_INVALID; - - for (i = 0; i < alloc_timers; i++) { - test_global->timer_ctx[i].timer = ODP_TIMER_INVALID; - test_global->timer_ctx[i].event = ODP_EVENT_INVALID; - } - - if (test_global->opt.groups) { - /* Create groups */ - - odp_thrmask_t zero; - - odp_thrmask_zero(&zero); - - for (i = 0; i < (uint64_t)test_global->opt.cpu_count; i++) { - group[i] = odp_schedule_group_create(NULL, &zero); - - if (group[i] == ODP_SCHED_GROUP_INVALID) { - printf("Group create failed.\n"); - return -1; - } - } - } - - odp_queue_param_init(&queue_param); - queue_param.type = ODP_QUEUE_TYPE_SCHED; - queue_param.sched.prio = odp_schedule_default_prio(); - queue_param.sched.sync = test_global->opt.queue_type; - queue_param.sched.group = ODP_SCHED_GROUP_ALL; - - for (i = 0; i < (uint64_t)test_global->opt.num_queue; i++) { - if (test_global->opt.groups) - queue_param.sched.group = group[i % test_global->opt.cpu_count]; - - queue[i] = odp_queue_create(NULL, &queue_param); - if (queue[i] == ODP_QUEUE_INVALID) { - printf("Queue create failed.\n"); - return -1; - } - } - - odp_pool_param_init(&pool_param); - pool_param.type = ODP_POOL_TIMEOUT; - pool_param.tmo.num = alloc_timers; - - pool = odp_pool_create("timeout pool", &pool_param); - - if (pool == ODP_POOL_INVALID) { - printf("Timeout pool create failed.\n"); - return -1; - } - - test_global->timeout_pool = pool; - clk_src = test_global->opt.clk_src; - - if (odp_timer_capability(clk_src, &timer_capa)) { - printf("Timer capa failed\n"); - return -1; - } - - max_timers = timer_capa.max_timers; - - if (mode == MODE_PERIODIC) { - if (timer_capa.periodic.max_pools < 1) { - printf("Error: Periodic timers not supported.\n"); - return -1; - } - max_timers = timer_capa.periodic.max_timers; - } - - if (max_timers && test_global->opt.alloc_timers > max_timers) { - printf("Error: Too many timers: %" PRIu64 ".\n" - " Max timers: %u\n", - test_global->opt.alloc_timers, max_timers); - return -1; - } - - printf("\nTest parameters:\n"); - printf(" clock source: %i\n", clk_src); - printf(" max timers capa: %" PRIu32 "\n", max_timers); - printf(" mode: %i\n", mode); - printf(" queue type: %i\n", test_global->opt.queue_type); - printf(" num queue: %i\n", test_global->opt.num_queue); - printf(" sched groups: %s\n", test_global->opt.groups ? "yes" : "no"); - - odp_timer_pool_param_init(&timer_param); - - if (mode == MODE_PERIODIC) - ret = periodic_params(test_global, &timer_param, &timer_capa); - else - ret = single_shot_params(test_global, &timer_param, &timer_capa); - - if (ret) - return ret; - - if (timer_param.res_hz) { - test_global->res_ns = 1000000000.0 / timer_param.res_hz; - printf(" resolution: %" PRIu64 " Hz\n", timer_param.res_hz); - } else { - test_global->res_ns = timer_param.res_ns; - printf(" resolution: %" PRIu64 " nsec\n", timer_param.res_ns); - } - - timer_param.num_timers = alloc_timers; - timer_param.clk_src = clk_src; - - printf(" restart retries: %i\n", test_global->opt.early_retry); - if (test_global->opt.output) - printf(" log file: %s\n", test_global->opt.filename); - printf(" start offset: %" PRIu64 " nsec\n", offset_ns); - printf(" min timeout: %" PRIu64 " nsec\n", timer_param.min_tmo); - printf(" max timeout: %" PRIu64 " nsec\n", timer_param.max_tmo); - printf(" num timeout: %" PRIu64 "\n", num_tmo); - printf(" num warmup: %" PRIu64 "\n", num_warmup); - printf(" burst size: %" PRIu64 "\n", burst); - printf(" burst gap: %" PRIu64 "\n", burst_gap); - printf(" total timers: %" PRIu64 "\n", tot_timers); - printf(" warmup timers: %" PRIu64 "\n", test_global->opt.warmup_timers); - printf(" alloc timers: %" PRIu64 "\n", alloc_timers); - printf(" warmup time: %.2f sec\n", - (offset_ns + (num_warmup * test_global->period_dbl)) / 1000000000.0); - printf(" test run time: %.2f sec\n\n", - (offset_ns + (num_tmo * test_global->period_dbl)) / 1000000000.0); - - timer_pool = odp_timer_pool_create("timer_accuracy", &timer_param); - - if (timer_pool == ODP_TIMER_POOL_INVALID) { - printf("Timer pool create failed\n"); - return -1; - } - - if (odp_timer_pool_start_multi(&timer_pool, 1) != 1) { - ODPH_ERR("Timer pool start failed\n"); - return -1; - } - - odp_timer_pool_print(timer_pool); - - /* Spend some time so that current tick would not be zero */ - odp_time_wait_ns(100 * ODP_TIME_MSEC_IN_NS); - - test_global->timer_pool = timer_pool; - - for (i = 0; i < alloc_timers; i++) { - timer_ctx_t *ctx = &test_global->timer_ctx[i]; - - timer = odp_timer_alloc(timer_pool, queue[i % test_global->opt.num_queue], ctx); - - if (timer == ODP_TIMER_INVALID) { - printf("Timer alloc failed.\n"); - return -1; - } - - ctx->timer = timer; - - timeout = odp_timeout_alloc(pool); - if (timeout == ODP_TIMEOUT_INVALID) { - printf("Timeout alloc failed\n"); - return -1; - } - - ctx->event = odp_timeout_to_event(timeout); - } - - /* Run scheduler few times to ensure that (software) timer is active */ - for (i = 0; i < 1000; i++) { - event = odp_schedule(NULL, ODP_SCHED_NO_WAIT); - - if (event != ODP_EVENT_INVALID) { - printf("Spurious event received\n"); - odp_event_free(event); - return -1; - } - } - - return 0; -} - -static int start_timers(test_global_t *test_global) -{ - odp_timer_pool_t timer_pool; - uint64_t start_tick; - uint64_t period_ns, start_ns, nsec, offset_ns; - odp_time_t time; - uint64_t i, j, idx, num_tmo, num_warmup, burst, burst_gap; - enum mode_e mode; - - mode = test_global->opt.mode; - num_warmup = test_global->opt.num_warmup; - num_tmo = num_warmup + test_global->opt.num; - burst = test_global->opt.burst; - burst_gap = test_global->opt.burst_gap; - period_ns = test_global->opt.period_ns; - offset_ns = test_global->opt.offset_ns; - timer_pool = test_global->timer_pool; - idx = 0; - - /* Record test start time and tick. Memory barriers forbid compiler and out-of-order - * CPU to move samples apart. */ - odp_mb_full(); - start_tick = odp_timer_current_tick(timer_pool); - time = odp_time_global(); - odp_mb_full(); - - start_ns = odp_time_to_ns(time); - test_global->start_tick = start_tick; - test_global->start_ns = start_ns; - test_global->period_tick = odp_timer_ns_to_tick(timer_pool, period_ns); - - /* When mode is not one-shot, set only one burst of timers initially */ - if (mode != MODE_ONESHOT) - num_tmo = 1; - - for (i = 0; i < num_tmo; i++) { - odp_timer_retval_t retval; - - for (j = 0; j < burst; j++) { - timer_ctx_t *ctx = &test_global->timer_ctx[idx]; - odp_timer_start_t start_param; - - if (mode == MODE_PERIODIC) { - odp_timer_periodic_start_t periodic_start; - - nsec = offset_ns + (j * burst_gap); - - /* By default, timer starts one period after current time. Round - * floating point to closest integer number. */ - ctx->nsec = start_ns + test_global->period_dbl + 0.5; - if (nsec) - ctx->nsec = start_ns + nsec; - - ctx->count = 0; - ctx->first_period = start_tick + - odp_timer_ns_to_tick(timer_pool, - test_global->period_dbl + 0.5); - periodic_start.freq_multiplier = test_global->opt.multiplier; - periodic_start.first_tick = 0; - if (nsec) - periodic_start.first_tick = - start_tick + odp_timer_ns_to_tick(timer_pool, nsec); - periodic_start.tmo_ev = ctx->event; - retval = odp_timer_periodic_start(ctx->timer, &periodic_start); - } else { - nsec = offset_ns + (i * period_ns) + (j * burst_gap); - ctx->nsec = start_ns + nsec; - start_param.tick_type = ODP_TIMER_TICK_ABS; - start_param.tick = - start_tick + odp_timer_ns_to_tick(timer_pool, nsec); - start_param.tmo_ev = ctx->event; - retval = odp_timer_start(ctx->timer, &start_param); - } - - if (retval != ODP_TIMER_SUCCESS) { - printf("Timer[%" PRIu64 "] set failed: %i\n", idx, retval); - return -1; - } - - idx++; - } - } - - printf("\nStarting timers took %" PRIu64 " nsec\n", odp_time_global_ns() - start_ns); - - return 0; -} - -static int destroy_timers(test_global_t *test_global) -{ - uint64_t i, alloc_timers; - odp_timer_t timer; - int ret = 0; - - alloc_timers = test_global->opt.alloc_timers; - - for (i = 0; i < alloc_timers; i++) { - timer = test_global->timer_ctx[i].timer; - - if (timer == ODP_TIMER_INVALID) - break; - - if (odp_timer_free(timer)) { - printf("Timer free failed: %" PRIu64 "\n", i); - ret = -1; - } - } - - if (test_global->timer_pool != ODP_TIMER_POOL_INVALID) - odp_timer_pool_destroy(test_global->timer_pool); - - if (test_global->timeout_pool != ODP_POOL_INVALID) { - if (odp_pool_destroy(test_global->timeout_pool)) { - printf("Pool destroy failed.\n"); - ret = -1; - } - } - - for (i = 0; i < (uint64_t)test_global->opt.num_queue; i++) { - if (odp_queue_destroy(test_global->queue[i])) { - printf("Queue destroy failed.\n"); - ret = -1; - } - } - - if (test_global->opt.groups) { - for (i = 0; i < (uint64_t)test_global->opt.cpu_count; i++) { - if (odp_schedule_group_destroy(test_global->group[i])) { - printf("Group destroy failed.\n"); - ret = -1; - } - } - } - - return ret; -} - -static void print_nsec_error(const char *str, int64_t nsec, double res_ns, - int tid, int idx) -{ - printf(" %s: %12" PRIi64 " / %.3fx resolution", - str, nsec, (double)nsec / res_ns); - if (tid >= 0) - printf(", thread %d", tid); - if (idx >= 0) - printf(", event %d", idx); - printf("\n"); -} - -static void print_stat(test_global_t *test_global) -{ - test_stat_t test_stat; - test_stat_t *stat = &test_stat; - uint64_t tot_timers; - test_stat_t *s = test_global->stat; - test_log_t *log = test_global->log; - double res_ns = test_global->res_ns; - uint64_t ave_after = 0; - uint64_t ave_before = 0; - uint64_t nsec_before_min_tid = 0; - uint64_t nsec_before_max_tid = 0; - uint64_t nsec_after_min_tid = 0; - uint64_t nsec_after_max_tid = 0; - - memset(stat, 0, sizeof(*stat)); - stat->nsec_before_min = UINT64_MAX; - stat->nsec_after_min = UINT64_MAX; - - for (int i = 1; i < test_global->opt.cpu_count + 1; i++) { - stat->nsec_before_sum += s[i].nsec_before_sum; - stat->nsec_after_sum += s[i].nsec_after_sum; - stat->num_before += s[i].num_before; - stat->num_exact += s[i].num_exact; - stat->num_after += s[i].num_after; - stat->num_too_near += s[i].num_too_near; - - if (s[i].nsec_before_min < stat->nsec_before_min) { - stat->nsec_before_min = s[i].nsec_before_min; - stat->nsec_before_min_idx = s[i].nsec_before_min_idx; - nsec_before_min_tid = i; - } - - if (s[i].nsec_after_min < stat->nsec_after_min) { - stat->nsec_after_min = s[i].nsec_after_min; - stat->nsec_after_min_idx = s[i].nsec_after_min_idx; - nsec_after_min_tid = i; - } - - if (s[i].nsec_before_max > stat->nsec_before_max) { - stat->nsec_before_max = s[i].nsec_before_max; - stat->nsec_before_max_idx = s[i].nsec_before_max_idx; - nsec_before_max_tid = i; - } - - if (s[i].nsec_after_max > stat->nsec_after_max) { - stat->nsec_after_max = s[i].nsec_after_max; - stat->nsec_after_max_idx = s[i].nsec_after_max_idx; - nsec_after_max_tid = i; - } - } - - if (stat->num_after) - ave_after = stat->nsec_after_sum / stat->num_after; - else - stat->nsec_after_min = 0; - - if (stat->num_before) - ave_before = stat->nsec_before_sum / stat->num_before; - else - stat->nsec_before_min = 0; - - tot_timers = stat->num_before + stat->num_after + stat->num_exact; - - if (log) { - FILE *file = test_global->file; - - fprintf(file, " Timer thread tmo(ns) diff(ns)\n"); - - for (uint64_t i = 0; i < tot_timers; i++) { - fprintf(file, "%8" PRIu64 " %7u %12" PRIu64 " %10" - PRIi64 "\n", i, log[i].tid, log[i].tmo_ns, log[i].diff_ns); - } - - fprintf(file, "\n"); - } - - printf("\nTest results:\n"); - printf(" num after: %12" PRIu64 " / %.2f%%\n", - stat->num_after, 100.0 * stat->num_after / tot_timers); - printf(" num before: %12" PRIu64 " / %.2f%%\n", - stat->num_before, 100.0 * stat->num_before / tot_timers); - printf(" num exact: %12" PRIu64 " / %.2f%%\n", - stat->num_exact, 100.0 * stat->num_exact / tot_timers); - printf(" num retry: %12" PRIu64 " / %.2f%%\n", - stat->num_too_near, 100.0 * stat->num_too_near / tot_timers); - printf(" error after (nsec):\n"); - print_nsec_error("min", stat->nsec_after_min, res_ns, nsec_after_min_tid, - stat->nsec_after_min_idx); - print_nsec_error("max", stat->nsec_after_max, res_ns, nsec_after_max_tid, - stat->nsec_after_max_idx); - print_nsec_error("ave", ave_after, res_ns, -1, -1); - printf(" error before (nsec):\n"); - print_nsec_error("min", stat->nsec_before_min, res_ns, nsec_before_min_tid, - stat->nsec_before_min_idx); - print_nsec_error("max", stat->nsec_before_max, res_ns, nsec_before_max_tid, - stat->nsec_before_max_idx); - print_nsec_error("ave", ave_before, res_ns, -1, -1); - - if (test_global->opt.mode == MODE_PERIODIC && !test_global->opt.offset_ns) { - int idx = 0; - int64_t max = 0; - - for (int i = 0; i < (int)test_global->opt.alloc_timers; i++) { - timer_ctx_t *t = &test_global->timer_ctx[i]; - int64_t v = t->first_tmo_diff; - - if (ODPH_ABS(v) > ODPH_ABS(max)) { - max = v; - idx = i; - } - } - - printf(" first timeout difference to one period, based on %s (nsec):\n", - test_global->timer_ctx[idx].tmo_tick ? "timeout tick" : "time"); - print_nsec_error("max", max, res_ns, -1, -1); - } - - int64_t max = 0; - - for (int i = 0; i < (int)test_global->opt.alloc_timers; i++) { - timer_ctx_t *t = &test_global->timer_ctx[i]; - int64_t v = t->nsec_final; - - if (ODPH_ABS(v) > ODPH_ABS(max)) - max = v; - } - - printf(" final timeout error (nsec):\n"); - print_nsec_error("max", max, res_ns, -1, -1); - - printf("\n"); -} - -static void cancel_periodic_timers(test_global_t *test_global) -{ - uint64_t i, alloc_timers; - odp_timer_t timer; - - alloc_timers = test_global->opt.alloc_timers; - - for (i = 0; i < alloc_timers; i++) { - timer = test_global->timer_ctx[i].timer; - - if (timer == ODP_TIMER_INVALID) - break; - - if (odp_timer_periodic_cancel(timer)) - printf("Failed to cancel periodic timer.\n"); - } -} - -static int run_test(void *arg) -{ - test_global_t *test_global = (test_global_t *)arg; - odp_event_t ev; - odp_time_t time; - uint64_t time_ns, diff_ns; - odp_timeout_t tmo; - uint64_t tmo_ns; - timer_ctx_t *ctx; - odp_thrmask_t mask; - uint64_t wait = odp_schedule_wait_time(10 * ODP_TIME_MSEC_IN_NS); - odp_schedule_group_t group = ODP_SCHED_GROUP_INVALID; - test_log_t *log = test_global->log; - enum mode_e mode = test_global->opt.mode; - uint64_t tot_timers = test_global->opt.tot_timers; - double period_dbl = test_global->period_dbl; - odp_timer_pool_t tp = test_global->timer_pool; - int tid = odp_thread_id(); - - if (tid > test_global->opt.cpu_count) { - printf("Error: tid %d is larger than cpu_count %d.\n", tid, - test_global->opt.cpu_count); - return 0; - } - - test_stat_t *stat = &test_global->stat[tid]; - - memset(stat, 0, sizeof(*stat)); - stat->nsec_before_min = UINT64_MAX; - stat->nsec_after_min = UINT64_MAX; - - if (test_global->opt.groups) { - odp_thrmask_zero(&mask); - odp_thrmask_set(&mask, tid); - group = test_global->group[tid - 1]; - - if (odp_schedule_group_join(group, &mask)) { - printf("odp_schedule_group_join() failed\n"); - return 0; - } - } - - odp_barrier_wait(&test_global->barrier); - - while (1) { - ev = odp_schedule(NULL, wait); - time = odp_time_global_strict(); - - if (ev == ODP_EVENT_INVALID) { - if (mode == MODE_PERIODIC) { - if (odp_atomic_load_u64(&test_global->last_events) >= - test_global->opt.alloc_timers) - break; - - } else if (odp_atomic_load_u64(&test_global->events) >= tot_timers) { - break; - } - - continue; - } - - time_ns = odp_time_to_ns(time); - tmo = odp_timeout_from_event(ev); - ctx = odp_timeout_user_ptr(tmo); - tmo_ns = ctx->nsec; - - if (mode == MODE_PERIODIC) { - if (!ctx->count && !test_global->opt.offset_ns) { - /* - * If first_tick is zero, the API allows the implementation to - * place the timer where it can, so we have to adjust our - * expectation of the timeout time. - */ - - uint64_t tmo_tick = odp_timeout_tick(tmo); - - if (tmo_tick) { - /* - * Adjust by the difference between one period after start - * time and the timeout tick. - */ - ctx->tmo_tick = 1; - ctx->first_tmo_diff = - (int64_t)odp_timer_tick_to_ns(tp, tmo_tick) - - (int64_t)odp_timer_tick_to_ns(tp, ctx->first_period); - tmo_ns += ctx->first_tmo_diff; - } else { - /* - * Timeout tick is not provided, so the best we can do is - * to just take the current time as a baseline. - */ - ctx->first_tmo_diff = (int64_t)time_ns - (int64_t)tmo_ns; - tmo_ns = ctx->nsec = time_ns; - } - - ctx->nsec = tmo_ns; - } - - /* round to closest integer number */ - tmo_ns += ctx->count * period_dbl + 0.5; - ctx->count++; - } - - uint64_t events = odp_atomic_fetch_inc_u64(&test_global->events); - - if (events >= test_global->opt.warmup_timers && events < tot_timers) { - uint64_t i = events - test_global->opt.warmup_timers; - - ctx->nsec_final = (int64_t)time_ns - (int64_t)tmo_ns; - - if (log) { - log[i].tmo_ns = tmo_ns; - log[i].tid = tid; - } - - if (time_ns > tmo_ns) { - diff_ns = time_ns - tmo_ns; - stat->num_after++; - stat->nsec_after_sum += diff_ns; - if (diff_ns < stat->nsec_after_min) { - stat->nsec_after_min = diff_ns; - stat->nsec_after_min_idx = i; - } - if (diff_ns > stat->nsec_after_max) { - stat->nsec_after_max = diff_ns; - stat->nsec_after_max_idx = i; - } - if (log) - log[i].diff_ns = diff_ns; - - } else if (time_ns < tmo_ns) { - diff_ns = tmo_ns - time_ns; - stat->num_before++; - stat->nsec_before_sum += diff_ns; - if (diff_ns < stat->nsec_before_min) { - stat->nsec_before_min = diff_ns; - stat->nsec_before_min_idx = i; - } - if (diff_ns > stat->nsec_before_max) { - stat->nsec_before_max = diff_ns; - stat->nsec_before_max_idx = i; - } - if (log) - log[i].diff_ns = -diff_ns; - } else { - stat->num_exact++; - } - } - - if ((mode == MODE_RESTART_ABS || mode == MODE_RESTART_REL) && - events < tot_timers - 1) { - /* Reset timer for next period */ - odp_timer_t tim; - uint64_t nsec, tick; - odp_timer_retval_t ret; - unsigned int j; - unsigned int retries = test_global->opt.early_retry; - uint64_t start_ns = test_global->start_ns; - uint64_t period_ns = test_global->opt.period_ns; - odp_timer_start_t start_param; - - tim = ctx->timer; - - /* Depending on the option, retry when expiration - * time is too early */ - for (j = 0; j < retries + 1; j++) { - if (mode == MODE_RESTART_ABS) { - /* Absolute time */ - ctx->nsec += period_ns; - nsec = ctx->nsec - start_ns; - tick = test_global->start_tick + - odp_timer_ns_to_tick(tp, nsec); - start_param.tick_type = ODP_TIMER_TICK_ABS; - } else { - /* Relative time */ - tick = test_global->period_tick; - time = odp_time_local(); - time_ns = odp_time_to_ns(time); - ctx->nsec = time_ns + period_ns; - start_param.tick_type = ODP_TIMER_TICK_REL; - } - - start_param.tmo_ev = ev; - start_param.tick = tick; - - ret = odp_timer_start(tim, &start_param); - if (ret == ODP_TIMER_TOO_NEAR) { - if (events >= test_global->opt.warmup_timers) - stat->num_too_near++; - } else { - break; - } - } - - if (ret != ODP_TIMER_SUCCESS) { - printf("Timer set failed: %i. Timeout nsec " - "%" PRIu64 "\n", ret, ctx->nsec); - return 0; - } - } else if (mode == MODE_PERIODIC) { - int ret = odp_timer_periodic_ack(ctx->timer, ev); - - if (ret < 0) - printf("Failed to ack a periodic timer.\n"); - - if (ret == 2) - odp_atomic_inc_u64(&test_global->last_events); - - if (ret == 2 || ret < 0) - odp_event_free(ev); - } else { - odp_event_free(ev); - } - } - - if (test_global->opt.groups) { - if (odp_schedule_group_leave(group, &mask)) - printf("odp_schedule_group_leave() failed\n"); - } - - return 0; -} - -int main(int argc, char *argv[]) -{ - odp_instance_t instance; - odp_init_t init; - test_opt_t test_opt; - test_global_t *test_global; - odph_helper_options_t helper_options; - odp_init_t *init_ptr = NULL; - int ret = 0; - - /* Let helper collect its own arguments (e.g. --odph_proc) */ - argc = odph_parse_options(argc, argv); - if (odph_options(&helper_options)) { - ODPH_ERR("Reading ODP helper options failed.\n"); - exit(EXIT_FAILURE); - } - - if (parse_options(argc, argv, &test_opt)) - return -1; - - /* List features not to be used (may optimize performance) */ - odp_init_param_init(&init); - init.not_used.feat.cls = 1; - init.not_used.feat.compress = 1; - init.not_used.feat.crypto = 1; - init.not_used.feat.ipsec = 1; - init.not_used.feat.tm = 1; - - init.mem_model = helper_options.mem_model; - - if (test_opt.init) - init_ptr = &init; - - /* Init ODP before calling anything else */ - if (odp_init_global(&instance, init_ptr, NULL)) { - printf("Global init failed.\n"); - return -1; - } - - /* Init this thread */ - if (odp_init_local(instance, ODP_THREAD_CONTROL)) { - printf("Local init failed.\n"); - return -1; - } - - odp_sys_info_print(); - - /* Configure scheduler */ - odp_schedule_config(NULL); - - odp_shm_t shm = ODP_SHM_INVALID, shm_ctx = ODP_SHM_INVALID, shm_log = ODP_SHM_INVALID; - uint64_t size = sizeof(test_global_t); - - shm = odp_shm_reserve("timer_accuracy", size, - ODP_CACHE_LINE_SIZE, ODP_SHM_SINGLE_VA); - - if (shm == ODP_SHM_INVALID) { - printf("Shm alloc failed.\n"); - return -1; - } - - test_global = odp_shm_addr(shm); - memset(test_global, 0, size); - memcpy(&test_global->opt, &test_opt, sizeof(test_opt_t)); - - size = test_global->opt.alloc_timers * sizeof(timer_ctx_t); - shm_ctx = odp_shm_reserve("timer_accuracy_ctx", size, - ODP_CACHE_LINE_SIZE, ODP_SHM_SINGLE_VA); - - if (shm_ctx == ODP_SHM_INVALID) { - printf("Timer context alloc failed.\n"); - ret = -1; - goto quit; - } - - test_global->timer_ctx = odp_shm_addr(shm_ctx); - memset(test_global->timer_ctx, 0, size); - - if (test_global->opt.output) { - test_global->file = fopen(test_global->opt.filename, "w"); - if (test_global->file == NULL) { - printf("Failed to open output file %s: %s\n", - test_global->opt.filename, strerror(errno)); - ret = -1; - goto quit; - } - - size = (test_global->opt.tot_timers - test_global->opt.warmup_timers) * - sizeof(test_log_t); - shm_log = odp_shm_reserve("timer_accuracy_log", size, sizeof(test_log_t), - ODP_SHM_SINGLE_VA); - - if (shm_log == ODP_SHM_INVALID) { - printf("Test log alloc failed.\n"); - ret = -1; - goto quit; - } - - test_global->log = odp_shm_addr(shm_log); - memset(test_global->log, 0, size); - } - - odph_thread_t thread_tbl[MAX_WORKERS]; - int num_workers; - odp_cpumask_t cpumask; - char cpumaskstr[ODP_CPUMASK_STR_SIZE]; - odph_thread_common_param_t thr_common; - odph_thread_param_t thr_param; - - memset(thread_tbl, 0, sizeof(thread_tbl)); - - num_workers = MAX_WORKERS; - if (test_global->opt.cpu_count && test_global->opt.cpu_count < MAX_WORKERS) - num_workers = test_global->opt.cpu_count; - num_workers = odp_cpumask_default_worker(&cpumask, num_workers); - test_global->opt.cpu_count = num_workers; - 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); - - ret = create_timers(test_global); - if (ret) - goto quit; - - odp_barrier_init(&test_global->barrier, num_workers + 1); - odp_atomic_init_u64(&test_global->events, 0); - odp_atomic_init_u64(&test_global->last_events, 0); - - odph_thread_param_init(&thr_param); - thr_param.start = run_test; - thr_param.arg = (void *)test_global; - thr_param.thr_type = ODP_THREAD_WORKER; - - odph_thread_common_param_init(&thr_common); - thr_common.instance = instance; - thr_common.cpumask = &cpumask; - thr_common.share_param = 1; - - odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers); - odp_barrier_wait(&test_global->barrier); - - ret = start_timers(test_global); - if (ret) - goto quit; - - if (test_global->opt.mode == MODE_PERIODIC) { - while (odp_atomic_load_u64(&test_global->events) < test_global->opt.tot_timers) - odp_time_wait_ns(10 * ODP_TIME_MSEC_IN_NS); - - cancel_periodic_timers(test_global); - } - - odph_thread_join(thread_tbl, num_workers); - print_stat(test_global); - -quit: - if (test_global->file) - fclose(test_global->file); - - if (destroy_timers(test_global)) - ret = -1; - - if (shm_log != ODP_SHM_INVALID && odp_shm_free(shm_log)) - ret = -1; - - if (shm_ctx != ODP_SHM_INVALID && odp_shm_free(shm_ctx)) - ret = -1; - - if (odp_shm_free(shm)) - ret = -1; - - if (odp_term_local()) { - printf("Term local failed.\n"); - ret = -1; - } - - if (odp_term_global(instance)) { - printf("Term global failed.\n"); - ret = -1; - } - - return ret; -} diff --git a/example/timer/odp_timer_accuracy_run.sh b/example/timer/odp_timer_accuracy_run.sh deleted file mode 100755 index 1c879f4e6..000000000 --- a/example/timer/odp_timer_accuracy_run.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# -# SPDX-License-Identifier: BSD-3-Clause -# Copyright (c) 2022 Nokia -# - -./odp_timer_accuracy${EXEEXT} -p 100000000 -n 10 -- cgit v1.2.3 From 564de214ac7f0f7d29aa319e060c24215b7df9a5 Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Mon, 19 Feb 2024 09:54:02 +0200 Subject: example: generator: remove odp_generator example application The odp_generator example application has been made redundant by odp_packet_gen application. Signed-off-by: Matias Elo Reviewed-by: Janne Peltonen --- example/Makefile.am | 1 - example/generator/.gitignore | 2 - example/generator/Makefile.am | 34 - example/generator/generator_run.sh | 29 - example/generator/odp_generator.c | 1760 ------------------------------------ example/m4/configure.m4 | 1 - 6 files changed, 1827 deletions(-) delete mode 100644 example/generator/.gitignore delete mode 100644 example/generator/Makefile.am delete mode 100755 example/generator/generator_run.sh delete mode 100644 example/generator/odp_generator.c (limited to 'example') diff --git a/example/Makefile.am b/example/Makefile.am index 9e748345b..2ef6abd9d 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -1,6 +1,5 @@ SUBDIRS = classifier \ debug \ - generator \ hello \ ipsec_api \ ipsec_crypto \ diff --git a/example/generator/.gitignore b/example/generator/.gitignore deleted file mode 100644 index 37364a254..000000000 --- a/example/generator/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -odp_generator -pktio_env diff --git a/example/generator/Makefile.am b/example/generator/Makefile.am deleted file mode 100644 index c3c08a663..000000000 --- a/example/generator/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -include $(top_srcdir)/example/Makefile.inc - -bin_PROGRAMS = odp_generator - -odp_generator_SOURCES = odp_generator.c - -TEST_EXTENSIONS = .sh - -if test_example -TESTS = generator_run.sh -endif -EXTRA_DIST = generator_run.sh - -# If building out-of-tree, make check will not copy the scripts and data to the -# $(builddir) assuming that all commands are run locally. However this prevents -# running tests on a remote target using LOG_COMPILER. -# So copy all script and data files explicitly here. -all-local: - if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(EXTRA_DIST); do \ - if [ -e $(srcdir)/$$f ]; then \ - mkdir -p $(builddir)/$$(dirname $$f); \ - cp -f $(srcdir)/$$f $(builddir)/$$f; \ - fi \ - done \ - fi - ln -f -s $(top_srcdir)/platform/$(with_platform)/test/example/generator/pktio_env \ - pktio_env -clean-local: - if [ "x$(srcdir)" != "x$(builddir)" ]; then \ - for f in $(EXTRA_DIST); do \ - rm -f $(builddir)/$$f; \ - done \ - fi diff --git a/example/generator/generator_run.sh b/example/generator/generator_run.sh deleted file mode 100755 index ca69b53bd..000000000 --- a/example/generator/generator_run.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash -# -# SPDX-License-Identifier: BSD-3-Clause -# Copyright (c) 2020 Marvell -# - -if [ -f ./pktio_env ]; then - . ./pktio_env -else - echo "BUG: unable to find pktio_env!" - echo "pktio_env has to be in current directory" - exit 1 -fi - -setup_interfaces - -./odp_generator${EXEEXT} -w 1 -n 1 -I $IF0 -m u -STATUS=$? - -if [ "$STATUS" -ne 0 ]; then - echo "Error: status was: $STATUS, expected 0" - exit 1 -fi - -validate_result - -cleanup_interfaces - -exit 0 diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c deleted file mode 100644 index 6ec19d0ea..000000000 --- a/example/generator/odp_generator.c +++ /dev/null @@ -1,1760 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright (c) 2014-2018 Linaro Limited - */ - -/** - * @example odp_generator.c - * - * Traffic generator and loopback demo application - * - * @cond _ODP_HIDE_FROM_DOXYGEN_ - */ - -/** enable strtok */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -/* Max number of workers */ -#define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1) -#define POOL_NUM_PKT 2048 /* Number of packets in packet pool */ -#define POOL_PKT_LEN 1856 /* Max packet length */ -#define DEFAULT_PKT_INTERVAL 1000 /* Interval between each packet */ -#define DEFAULT_UDP_TX_BURST 16 -#define MAX_UDP_TX_BURST 512 -#define DEFAULT_RX_BURST 32 -#define MAX_RX_BURST 512 -#define STATS_INTERVAL 10 /* Interval between stats prints (sec) */ - -#define APPL_MODE_UDP 0 /**< UDP mode */ -#define APPL_MODE_PING 1 /**< ping mode */ -#define APPL_MODE_RCV 2 /**< receive mode */ - -#define PING_THR_TX 0 -#define PING_THR_RX 1 - -/** print appl mode */ -#define PRINT_APPL_MODE(x) printf("%s(%i)\n", #x, (x)) - -/** Get rid of path in filename - only for unix-type paths using '/' */ -#define NO_PATH(file_name) (strrchr((file_name), '/') ? \ - strrchr((file_name), '/') + 1 : (file_name)) - -/** - * Interfaces - */ - -typedef struct { - odp_pktio_t pktio; - odp_pktio_config_t config; - odp_pktout_queue_t pktout[MAX_WORKERS]; - uint32_t pktout_count; - odp_pktin_queue_t pktin[MAX_WORKERS]; - uint32_t pktin_count; -} interface_t; - -/** - * Parsed command line application arguments - */ -typedef struct { - int num_workers; /**< Number of worker thread */ - const char *mask; /**< CPU mask */ - int if_count; /**< Number of interfaces to be used */ - char **if_names; /**< Array of pointers to interface names */ - char *if_str; /**< Storage for interface names */ - odp_pool_t pool; /**< Pool for packet IO */ - odph_ethaddr_t srcmac; /**< src mac addr */ - odph_ethaddr_t dstmac; /**< dest mac addr */ - unsigned int srcip; /**< src ip addr */ - unsigned int dstip; /**< dest ip addr */ - uint16_t srcport; /**< src udp port */ - uint16_t srcport_end; /**< src udp end port */ - uint16_t dstport; /**< dest udp port */ - uint16_t dstport_end; /**< dest udp end port */ - int mode; /**< work mode */ - int number; /**< packets number to be sent */ - int payload; /**< data len */ - int timeout; /**< wait time */ - int interval; /**< wait interval ms between sending - each packet */ - int udp_tx_burst; /**< number of udp packets to send with one - API call */ - int rx_burst; /**< number of packets to receive with one - API call */ - odp_bool_t csum; /**< use platform csum support if available */ - odp_bool_t sched; /**< use scheduler API to receive packets */ -} appl_args_t; - -/** - * counters -*/ -typedef struct { - uint64_t ctr_pkt_snd; /**< sent packets*/ - uint64_t ctr_pkt_snd_drop; /**< packets dropped in transmit */ - - uint64_t ctr_pkt_rcv; /**< recv packets */ - uint64_t ctr_seq; /**< ip seq to be send */ - uint64_t ctr_udp_rcv; /**< udp packets */ - uint64_t ctr_icmp_reply_rcv; /**< icmp reply packets */ -} counters_t; - -/** UDP Packet processing function argument */ -typedef struct { - odp_bool_t multi_flow; - uint16_t srcport_crt; - uint16_t srcport_start; - uint16_t srcport_end; - uint16_t dstport_crt; - uint16_t dstport_start; - uint16_t dstport_end; -} udp_args_t; - -/** * Thread specific arguments - */ -typedef struct { - counters_t counters; /**< Packet counters */ - odp_bool_t stop; /**< Stop packet processing */ - union { - struct { - odp_pktout_queue_t pktout; /**< Packet output queue */ - odp_pktout_config_opt_t *pktout_cfg; /**< Packet output config*/ - udp_args_t udp_param; /**< UDP configuration */ - } tx; - struct { - odp_pktin_queue_t pktin; /**< Packet input queue */ - } rx; - }; - odp_pool_t pool; /**< Pool for packet IO */ - int mode; /**< Thread mode */ -} thread_args_t; - -/** - * Grouping of both parsed CL args and thread specific args - alloc together - */ -typedef struct { - /** Application (parsed) arguments */ - appl_args_t appl; - /** Thread specific arguments */ - thread_args_t thread[MAX_WORKERS]; - /** Global arguments */ - int thread_cnt; - int tx_burst_size; - int rx_burst_size; - /** Barrier to sync threads execution */ - odp_barrier_t barrier; -} args_t; - -/** Global pointer to args */ -static args_t *args; - -/** Packet processing function types */ -typedef odp_packet_t (*setup_pkt_ref_fn_t)(odp_pool_t, - odp_pktout_config_opt_t *); -typedef int (*setup_pkt_fn_t)(odp_packet_t, odp_pktout_config_opt_t *, - counters_t *, void *); - -/* helper funcs */ -static void parse_args(int argc, char *argv[], appl_args_t *appl_args); -static void print_info(char *progname, appl_args_t *appl_args); -static void usage(char *progname); -static int scan_ip(char *buf, unsigned int *paddr); -static void print_global_stats(int num_workers); - -static void sig_handler(int signo ODP_UNUSED) -{ - int i; - if (args == NULL) - return; - for (i = 0; i < args->thread_cnt; i++) - args->thread[i].stop = 1; -} - -/** - * Scan ip - * Parse ip address. - * - * @param buf ip address string xxx.xxx.xxx.xx - * @param paddr ip address for odp_packet - * @return 1 success, 0 failed -*/ -static int scan_ip(char *buf, unsigned int *paddr) -{ - unsigned int part1, part2, part3, part4; - char tail = 0; - int field; - - if (buf == NULL) - return 0; - - field = sscanf(buf, "%u . %u . %u . %u %c", - &part1, &part2, &part3, &part4, &tail); - - if (field < 4 || field > 5) { - printf("expect 4 field,get %d/n", field); - return 0; - } - - if (tail != 0) { - printf("ip address mixed with non number/n"); - return 0; - } - - if (part1 <= 255 && part2 <= 255 && part3 <= 255 && part4 <= 255) { - if (paddr) - *paddr = part1 << 24 | part2 << 16 | part3 << 8 | part4; - return 1; - } - - printf("not good ip %u:%u:%u:%u/n", part1, part2, part3, part4); - - return 0; -} - -/** - * Setup array of reference packets - * - * @param pool Packet pool - * @param pktout_cfg Interface output configuration - * @param pkt_ref_array Packet array - * @param pkt_ref_array_size Packet array size - * @param setup_ref Packet setup function - * @return 0 success, -1 failed -*/ -static int setup_pkt_ref_array(odp_pool_t pool, - odp_pktout_config_opt_t *pktout_cfg, - odp_packet_t *pkt_ref_array, - int pkt_ref_array_size, - setup_pkt_ref_fn_t setup_ref) -{ - int i; - - for (i = 0; i < pkt_ref_array_size; i++) { - pkt_ref_array[i] = (*setup_ref)(pool, pktout_cfg); - if (pkt_ref_array[i] == ODP_PACKET_INVALID) - break; - } - - if (i < pkt_ref_array_size) { - odp_packet_free_multi(pkt_ref_array, i); - return -1; - } - return 0; -} - -/** - * Setup array of packets - * - * @param pktout_cfg Interface output configuration - * @param pkt_ref_array Reference packet array - * @param pkt_array Packet array - * @param pkt_array_size Packet array size - * @param setup_pkt Packet setup function - * @return 0 success, -1 failed -*/ -static int setup_pkt_array(odp_pktout_config_opt_t *pktout_cfg, - counters_t *counters, - odp_packet_t *pkt_ref_array, - odp_packet_t *pkt_array, - int pkt_array_size, - setup_pkt_fn_t setup_pkt, - void *setup_pkt_arg) -{ - int i; - - for (i = 0; i < pkt_array_size; i++) { - if ((*setup_pkt)(pkt_ref_array[i], pktout_cfg, counters, - setup_pkt_arg)) - break; - - pkt_array[i] = odp_packet_ref_static(pkt_ref_array[i]); - if (pkt_array[i] == ODP_PACKET_INVALID) - break; - } - if (i < pkt_array_size) { - if (i) - odp_packet_free_multi(pkt_array, i - 1); - - return -1; - } - return 0; -} - -/** - * set up an udp packet reference - * - * @param pool Buffer pool to create packet in - * @param pktout_cfg Interface output configuration - * - * - * @retval Handle of created packet - * @retval ODP_PACKET_INVALID Packet could not be created - * - */ -static odp_packet_t setup_udp_pkt_ref(odp_pool_t pool, - odp_pktout_config_opt_t *pktout_cfg) -{ - odp_packet_t pkt; - char *buf; - odph_ethhdr_t *eth; - odph_ipv4hdr_t *ip; - odph_udphdr_t *udp; - - pkt = odp_packet_alloc(pool, args->appl.payload + ODPH_UDPHDR_LEN + - ODPH_IPV4HDR_LEN + ODPH_ETHHDR_LEN); - - if (pkt == ODP_PACKET_INVALID) - return pkt; - - buf = odp_packet_data(pkt); - - /* ether */ - odp_packet_l2_offset_set(pkt, 0); - eth = (odph_ethhdr_t *)buf; - memcpy((char *)eth->src.addr, args->appl.srcmac.addr, ODPH_ETHADDR_LEN); - memcpy((char *)eth->dst.addr, args->appl.dstmac.addr, ODPH_ETHADDR_LEN); - eth->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); - - /* ip */ - odp_packet_l3_offset_set(pkt, ODPH_ETHHDR_LEN); - odp_packet_has_ipv4_set(pkt, 1); - ip = (odph_ipv4hdr_t *)(buf + ODPH_ETHHDR_LEN); - ip->dst_addr = odp_cpu_to_be_32(args->appl.dstip); - ip->src_addr = odp_cpu_to_be_32(args->appl.srcip); - ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; - ip->tot_len = odp_cpu_to_be_16(args->appl.payload + ODPH_UDPHDR_LEN + - ODPH_IPV4HDR_LEN); - ip->proto = ODPH_IPPROTO_UDP; - ip->id = 0; - ip->ttl = 64; - ip->chksum = 0; - - /* udp */ - odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); - odp_packet_has_udp_set(pkt, 1); - udp = (odph_udphdr_t *)(buf + ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); - udp->src_port = odp_cpu_to_be_16(args->appl.srcport); - udp->dst_port = odp_cpu_to_be_16(args->appl.dstport); - udp->length = odp_cpu_to_be_16(args->appl.payload + ODPH_UDPHDR_LEN); - if (!pktout_cfg->bit.udp_chksum) { - udp->chksum = 0; - udp->chksum = odph_ipv4_udp_chksum(pkt); - } - - return pkt; -} - -/** - * set up an udp packet - * - * @param pkt Reference UDP packet - * @param pktout_cfg Interface output configuration - * - * @return Success/Failed - * @retval 0 on success, -1 on fail - */ -static int setup_udp_pkt(odp_packet_t pkt, odp_pktout_config_opt_t *pktout_cfg, - counters_t *counters, void *arg) -{ - char *buf; - odph_ipv4hdr_t *ip; - unsigned short seq; - udp_args_t *udp_arg = (udp_args_t *)arg; - - buf = (char *)odp_packet_data(pkt); - - /*Update IP ID and checksum*/ - ip = (odph_ipv4hdr_t *)(buf + ODPH_ETHHDR_LEN); - seq = counters->ctr_seq % 0xFFFF; - counters->ctr_seq++; - ip->id = odp_cpu_to_be_16(seq); - if (!pktout_cfg->bit.ipv4_chksum) { - ip->chksum = 0; - ip->chksum = ~odp_chksum_ones_comp16(ip, ODPH_IPV4HDR_LEN); - } - - if (udp_arg->multi_flow) { - odph_udphdr_t *udp = (odph_udphdr_t *)(buf + ODPH_ETHHDR_LEN + - ODPH_IPV4HDR_LEN); - - if (udp_arg->srcport_start != udp_arg->srcport_end) { - udp->src_port = odp_cpu_to_be_16(udp_arg->srcport_crt); - if (udp_arg->srcport_crt >= udp_arg->srcport_end) - udp_arg->srcport_crt = udp_arg->srcport_start; - else - udp_arg->srcport_crt++; - } - if (udp_arg->dstport_start != udp_arg->dstport_end) { - udp->dst_port = odp_cpu_to_be_16(udp_arg->dstport_crt); - if (udp_arg->dstport_crt >= udp_arg->dstport_end) - udp_arg->dstport_crt = udp_arg->dstport_start; - else - udp_arg->dstport_crt++; - } - - udp->chksum = 0; - } - - if (pktout_cfg->bit.ipv4_chksum || pktout_cfg->bit.udp_chksum) { - odp_packet_l2_offset_set(pkt, 0); - odp_packet_l3_offset_set(pkt, ODPH_ETHHDR_LEN); - odp_packet_has_ipv4_set(pkt, 1); - odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + - ODPH_IPV4HDR_LEN); - odp_packet_has_udp_set(pkt, 1); - } - return 0; -} - -/** - * Set up an icmp packet reference - * - * @param pool Buffer pool to create packet in - * @param pktout_cfg Interface output configuration - * - * @return Handle of created packet - * @retval ODP_PACKET_INVALID Packet could not be created - */ -static odp_packet_t setup_icmp_pkt_ref(odp_pool_t pool, - odp_pktout_config_opt_t *pktout_cfg) -{ - odp_packet_t pkt; - char *buf; - odph_ethhdr_t *eth; - odph_ipv4hdr_t *ip; - odph_icmphdr_t *icmp; - - (void)pktout_cfg; - - args->appl.payload = 56; - pkt = odp_packet_alloc(pool, args->appl.payload + ODPH_ICMPHDR_LEN + - ODPH_IPV4HDR_LEN + ODPH_ETHHDR_LEN); - - if (pkt == ODP_PACKET_INVALID) - return pkt; - - buf = odp_packet_data(pkt); - - /* ether */ - odp_packet_l2_offset_set(pkt, 0); - eth = (odph_ethhdr_t *)buf; - memcpy((char *)eth->src.addr, args->appl.srcmac.addr, ODPH_ETHADDR_LEN); - memcpy((char *)eth->dst.addr, args->appl.dstmac.addr, ODPH_ETHADDR_LEN); - eth->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); - /* ip */ - odp_packet_l3_offset_set(pkt, ODPH_ETHHDR_LEN); - ip = (odph_ipv4hdr_t *)(buf + ODPH_ETHHDR_LEN); - ip->dst_addr = odp_cpu_to_be_32(args->appl.dstip); - ip->src_addr = odp_cpu_to_be_32(args->appl.srcip); - ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; - ip->ttl = 64; - ip->tot_len = odp_cpu_to_be_16(args->appl.payload + ODPH_ICMPHDR_LEN + - ODPH_IPV4HDR_LEN); - ip->proto = ODPH_IPPROTO_ICMPV4; - ip->id = 0; - ip->chksum = 0; - - /* icmp */ - icmp = (odph_icmphdr_t *)(buf + ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); - icmp->type = ODPH_ICMP_ECHO; - icmp->code = 0; - icmp->un.echo.id = 0; - icmp->un.echo.sequence = 0; - icmp->chksum = 0; - - return pkt; -} - -/** - * Set up an icmp packet - * - * @param pkt Reference ICMP packet - * @param pktout_cfg Interface output configuration - * - * @return Success/Failed - * @retval 0 on success, -1 on fail - */ -static int setup_icmp_pkt(odp_packet_t pkt, - odp_pktout_config_opt_t *pktout_cfg, - counters_t *counters, void *arg ODP_UNUSED) -{ - char *buf; - odph_ipv4hdr_t *ip; - odph_icmphdr_t *icmp; - uint64_t tval; - uint8_t *tval_d; - unsigned short seq; - - buf = (char *)odp_packet_data(pkt); - - /* ip */ - ip = (odph_ipv4hdr_t *)(buf + ODPH_ETHHDR_LEN); - seq = counters->ctr_seq % 0xffff; - counters->ctr_seq++; - ip->id = odp_cpu_to_be_16(seq); - if (!pktout_cfg->bit.ipv4_chksum) { - ip->chksum = 0; - ip->chksum = ~odp_chksum_ones_comp16(ip, ODPH_IPV4HDR_LEN); - } - - /* icmp */ - icmp = (odph_icmphdr_t *)(buf + ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); - icmp->un.echo.sequence = ip->id; - - tval_d = (uint8_t *)(buf + ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN + - ODPH_ICMPHDR_LEN); - tval = odp_time_to_ns(odp_time_local()); - memcpy(tval_d, &tval, sizeof(uint64_t)); - - icmp->chksum = 0; - icmp->chksum = ~odp_chksum_ones_comp16(icmp, args->appl.payload + - ODPH_ICMPHDR_LEN); - - if (pktout_cfg->bit.ipv4_chksum) { - odp_packet_l2_offset_set(pkt, 0); - odp_packet_l3_offset_set(pkt, ODPH_ETHHDR_LEN); - odp_packet_has_ipv4_set(pkt, 1); - odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + - ODPH_IPV4HDR_LEN); - } - - return 0; -} - -/** - * Create a pktio object - * - * @param dev Name of device to open - * @param pool Pool to associate with device for packet RX/TX - * - * @return The handle of the created pktio object. - * @warning This routine aborts if the create is unsuccessful. - */ -static int create_pktio(const char *dev, odp_pool_t pool, - uint32_t num_rx_queues, - uint32_t num_tx_queues, - interface_t *itf) -{ - odp_pktio_capability_t capa; - int ret; - odp_pktio_param_t pktio_param; - odp_pktin_queue_param_t pktin_param; - odp_pktout_queue_param_t pktout_param; - odp_pktio_op_mode_t pktout_mode, pktin_mode; - odp_bool_t sched = args->appl.sched; - - odp_pktio_param_init(&pktio_param); - pktio_param.in_mode = num_rx_queues ? - (sched ? ODP_PKTIN_MODE_SCHED : ODP_PKTIN_MODE_DIRECT) : - ODP_PKTIN_MODE_DISABLED; - pktio_param.out_mode = num_tx_queues ? ODP_PKTOUT_MODE_DIRECT : - ODP_PKTOUT_MODE_DISABLED; - - /* Open a packet IO instance */ - itf->pktio = odp_pktio_open(dev, pool, &pktio_param); - - if (itf->pktio == ODP_PKTIO_INVALID) { - ODPH_ERR("Error: pktio create failed for %s\n", dev); - return -1; - } - - if (odp_pktio_capability(itf->pktio, &capa)) { - ODPH_ERR("Error: Failed to get interface capabilities %s\n", - dev); - return -1; - } - odp_pktio_config_init(&itf->config); - if (args->appl.csum) { - itf->config.pktin.bit.ipv4_chksum = - capa.config.pktin.bit.ipv4_chksum; - itf->config.pktin.bit.udp_chksum = - capa.config.pktin.bit.udp_chksum; - itf->config.pktin.bit.drop_ipv4_err = - capa.config.pktin.bit.drop_ipv4_err; - itf->config.pktin.bit.drop_udp_err = - capa.config.pktin.bit.drop_udp_err; - - itf->config.pktout.bit.ipv4_chksum_ena = - capa.config.pktout.bit.ipv4_chksum_ena; - itf->config.pktout.bit.udp_chksum_ena = - capa.config.pktout.bit.udp_chksum_ena; - itf->config.pktout.bit.ipv4_chksum = - capa.config.pktout.bit.ipv4_chksum; - itf->config.pktout.bit.udp_chksum = - capa.config.pktout.bit.udp_chksum; - } else { /* explicit disable */ - itf->config.pktin.bit.ipv4_chksum = 0; - itf->config.pktin.bit.udp_chksum = 0; - itf->config.pktout.bit.ipv4_chksum_ena = 0; - itf->config.pktout.bit.udp_chksum_ena = 0; - itf->config.pktout.bit.ipv4_chksum = 0; - itf->config.pktout.bit.udp_chksum = 0; - } - - itf->config.parser.layer = ODP_PROTO_LAYER_L2; - if (itf->config.pktin.bit.udp_chksum) - itf->config.parser.layer = ODP_PROTO_LAYER_L4; - else if (itf->config.pktin.bit.ipv4_chksum) - itf->config.parser.layer = ODP_PROTO_LAYER_L3; - - if (odp_pktio_config(itf->pktio, &itf->config)) { - ODPH_ERR("Error: Failed to set interface configuration %s\n", - dev); - return -1; - } - - if (num_rx_queues) { - pktin_mode = ODP_PKTIO_OP_MT_UNSAFE; - if (num_rx_queues > capa.max_input_queues) { - num_rx_queues = capa.max_input_queues; - pktin_mode = ODP_PKTIO_OP_MT; - ODPH_DBG("Warning: Force RX multithread safe mode " - "(slower)on %s\n", dev); - } - - odp_pktin_queue_param_init(&pktin_param); - pktin_param.num_queues = num_rx_queues; - pktin_param.op_mode = pktin_mode; - if (sched) - pktin_param.queue_param.sched.sync = - ODP_SCHED_SYNC_ATOMIC; - - if (odp_pktin_queue_config(itf->pktio, &pktin_param)) { - ODPH_ERR("Error: pktin queue config failed for %s\n", - dev); - return -1; - } - } - - if (num_tx_queues) { - pktout_mode = ODP_PKTIO_OP_MT_UNSAFE; - if (num_tx_queues > capa.max_output_queues) { - num_tx_queues = capa.max_output_queues; - pktout_mode = ODP_PKTIO_OP_MT; - ODPH_DBG("Warning: Force TX multithread safe mode " - "(slower) on %s\n", dev); - } - - odp_pktout_queue_param_init(&pktout_param); - pktout_param.num_queues = num_tx_queues; - pktout_param.op_mode = pktout_mode; - - if (odp_pktout_queue_config(itf->pktio, &pktout_param)) { - ODPH_ERR("Error: pktout queue config failed for %s\n", - dev); - return -1; - } - } - - ret = odp_pktio_start(itf->pktio); - if (ret) - ODPH_ABORT("Error: unable to start %s\n", dev); - - itf->pktout_count = num_tx_queues; - if (itf->pktout_count && - odp_pktout_queue(itf->pktio, itf->pktout, itf->pktout_count) != - (int)itf->pktout_count) { - ODPH_ERR("Error: failed to get output queues for %s\n", dev); - return -1; - } - - itf->pktin_count = num_rx_queues; - if (!sched && itf->pktin_count && - odp_pktin_queue(itf->pktio, itf->pktin, itf->pktin_count) != - (int)itf->pktin_count) { - ODPH_ERR("Error: failed to get input queues for %s\n", dev); - return -1; - } - - printf(" created pktio:%02" PRIu64 - ", dev:%s, queue mode (ATOMIC queues)\n" - " default pktio%02" PRIu64 "\n", - odp_pktio_to_u64(itf->pktio), dev, - odp_pktio_to_u64(itf->pktio)); - fflush(NULL); - - return 0; -} - -/** - * Packet IO loopback worker thread using ODP queues - * - * @param arg thread arguments of type 'thread_args_t *' - */ - -static int gen_send_thread(void *arg) -{ - int thr; - int ret = 0; - thread_args_t *thr_args; - odp_pktout_queue_t pktout; - odp_pktout_config_opt_t *pktout_cfg; - odp_packet_t pkt_ref_array[MAX_UDP_TX_BURST]; - odp_packet_t pkt_array[MAX_UDP_TX_BURST]; - int pkt_array_size, seq_step; - int burst_start, burst_size; - setup_pkt_ref_fn_t setup_pkt_ref = NULL; - setup_pkt_fn_t setup_pkt = NULL; - void *setup_pkt_arg = NULL; - counters_t *counters; - uint64_t pkt_count_max = 0; - - thr = odp_thread_id(); - thr_args = arg; - pktout = thr_args->tx.pktout; - pktout_cfg = thr_args->tx.pktout_cfg; - counters = &thr_args->counters; - - /* Create reference packets*/ - if (args->appl.mode == APPL_MODE_UDP) { - setup_pkt_ref = setup_udp_pkt_ref; - setup_pkt = setup_udp_pkt; - seq_step = args->tx_burst_size * (args->thread_cnt - 1); - if (args->appl.number != -1) - pkt_count_max = args->appl.number / args->thread_cnt + - (args->appl.number % args->thread_cnt ? 1 : 0); - setup_pkt_arg = &thr_args->tx.udp_param; - } else if (args->appl.mode == APPL_MODE_PING) { - setup_pkt_ref = setup_icmp_pkt_ref; - setup_pkt = setup_icmp_pkt; - seq_step = 0; - if (args->appl.number != -1) - pkt_count_max = args->appl.number; - } else { - ODPH_ERR(" [%02i] Error: invalid processing mode %d\n", thr, - args->appl.mode); - return -1; - } - pkt_array_size = args->tx_burst_size; - - if (setup_pkt_ref_array(thr_args->pool, pktout_cfg, - pkt_ref_array, pkt_array_size, - setup_pkt_ref)) { - ODPH_ERR("[%02i] Error: failed to create reference packets\n", - thr); - return -1; - } - - printf(" [%02i] created mode: SEND\n", thr); - - odp_barrier_wait(&args->barrier); - - for (;;) { - if (thr_args->stop) - break; - - if (pkt_count_max && counters->ctr_pkt_snd > pkt_count_max) { - sleep(1); /* wait for stop command */ - continue; - } - - /* Setup TX burst*/ - if (setup_pkt_array(pktout_cfg, counters, - pkt_ref_array, pkt_array, - pkt_array_size, setup_pkt, setup_pkt_arg)) { - ODPH_ERR("[%02i] Error: failed to setup packets\n", - thr); - break; - } - - /* Send TX burst*/ - for (burst_start = 0, burst_size = pkt_array_size;;) { - ret = odp_pktout_send(pktout, &pkt_array[burst_start], - burst_size); - if (ret == burst_size) { - burst_size = 0; - break; - } else if (ret >= 0 && ret < burst_size) { - thr_args->counters.ctr_pkt_snd_drop += - burst_size - ret; - - burst_start += ret; - burst_size -= ret; - continue; - } - ODPH_ERR(" [%02i] packet send failed\n", thr); - odp_packet_free_multi(&pkt_array[burst_start], - burst_size); - break; - } - - counters->ctr_pkt_snd += pkt_array_size - burst_size; - - if (args->appl.interval != 0) - odp_time_wait_ns((uint64_t)args->appl.interval * - ODP_TIME_MSEC_IN_NS); - counters->ctr_seq += seq_step; - } - - odp_packet_free_multi(pkt_ref_array, pkt_array_size); - - return 0; -} - -/** - * Process icmp packets - * - * @param thr worker id - * @param thr_args worker argument - * @param icmp icmp header address - */ - -static void process_icmp_pkt(int thr, thread_args_t *thr_args, - uint8_t *_icmp) -{ - uint64_t trecv; - uint64_t tsend; - uint64_t rtt_ms, rtt_us; - odph_icmphdr_t *icmp = (odph_icmphdr_t *)_icmp; - - if (icmp->type == ODPH_ICMP_ECHOREPLY) { - thr_args->counters.ctr_icmp_reply_rcv++; - - memcpy(&tsend, (uint8_t *)icmp + ODPH_ICMPHDR_LEN, - sizeof(uint64_t)); - trecv = odp_time_to_ns(odp_time_local()); - rtt_ms = (trecv - tsend) / ODP_TIME_MSEC_IN_NS; - rtt_us = (trecv - tsend) / ODP_TIME_USEC_IN_NS - - 1000 * rtt_ms; - printf(" [%02i] ICMP Echo Reply seq %d time %" - PRIu64 ".%.03" PRIu64" ms\n", thr, - odp_be_to_cpu_16(icmp->un.echo.sequence), - rtt_ms, rtt_us); - } else if (icmp->type == ODPH_ICMP_ECHO) { - printf(" [%02i] ICMP Echo Request\n", thr); - } -} - -/** - * Process odp packets - * - * @param thr worker id - * @param thr_args worker argument - * @param pkt_tbl packets to be print - * @param len packet number - */ -static void process_pkts(int thr, thread_args_t *thr_args, - odp_packet_t pkt_tbl[], unsigned len) -{ - odp_packet_t pkt; - uint32_t left, offset, i; - odph_ipv4hdr_t *ip; - - for (i = 0; i < len; ++i) { - pkt = pkt_tbl[i]; - - /* Drop packets with errors */ - if (odp_unlikely(odp_packet_has_error(pkt))) - continue; - - offset = odp_packet_l3_offset(pkt); - left = odp_packet_len(pkt) - offset; - - if (left < sizeof(odph_ipv4hdr_t)) - continue; - - ip = (odph_ipv4hdr_t *)((uint8_t *)odp_packet_data(pkt) + - offset); - - /* only ip pkts */ - if (ODPH_IPV4HDR_VER(ip->ver_ihl) != ODPH_IPV4) - continue; - - thr_args->counters.ctr_pkt_rcv++; - - /* udp */ - if (ip->proto == ODPH_IPPROTO_UDP) { - thr_args->counters.ctr_udp_rcv++; - } else if (ip->proto == ODPH_IPPROTO_ICMPV4) { - uint32_t l3_size = ODPH_IPV4HDR_IHL(ip->ver_ihl) * 4; - - offset += l3_size; - left -= l3_size; - - if (left < sizeof(odph_icmphdr_t)) - continue; - - process_icmp_pkt(thr, thr_args, - (uint8_t *)odp_packet_data(pkt) + - offset); - } - } -} - -/** - * Scheduler receive function - * - * @param arg thread arguments of type 'thread_args_t *' - */ -static int gen_recv_thread(void *arg) -{ - int thr; - thread_args_t *thr_args; - odp_packet_t pkts[MAX_RX_BURST]; - odp_event_t events[MAX_RX_BURST], ev; - int pkt_cnt, ev_cnt, i; - int burst_size; - - thr = odp_thread_id(); - thr_args = (thread_args_t *)arg; - burst_size = args->rx_burst_size; - - printf(" [%02i] created mode: RECEIVE SCHEDULER\n", thr); - odp_barrier_wait(&args->barrier); - - for (;;) { - if (thr_args->stop) - break; - - /* Use schedule to get buf from any input queue */ - ev_cnt = odp_schedule_multi(NULL, ODP_SCHED_NO_WAIT, - events, burst_size); - if (ev_cnt == 0) - continue; - - for (i = 0, pkt_cnt = 0; i < ev_cnt; i++) { - ev = events[i]; - - if (odp_event_type(ev) == ODP_EVENT_PACKET) - pkts[pkt_cnt++] = odp_packet_from_event(ev); - else - odp_event_free(ev); - } - - if (pkt_cnt) { - process_pkts(thr, thr_args, pkts, pkt_cnt); - - odp_packet_free_multi(pkts, pkt_cnt); - } - } - - return 0; -} - -/** - * Direct receive function - * - * @param arg thread arguments of type 'thread_args_t *' - */ -static int gen_recv_direct_thread(void *arg) -{ - int thr; - thread_args_t *thr_args; - odp_packet_t pkts[MAX_RX_BURST]; - int pkt_cnt, burst_size; - odp_pktin_queue_t pktin; - uint64_t wait = odp_pktin_wait_time(ODP_TIME_SEC_IN_NS); - - thr = odp_thread_id(); - thr_args = (thread_args_t *)arg; - pktin = thr_args->rx.pktin; - burst_size = args->rx_burst_size; - - printf(" [%02i] created mode: RECEIVE\n", thr); - odp_barrier_wait(&args->barrier); - - for (;;) { - if (thr_args->stop) - break; - - pkt_cnt = odp_pktin_recv_tmo(pktin, pkts, burst_size, wait); - - if (pkt_cnt > 0) { - process_pkts(thr, thr_args, pkts, pkt_cnt); - - odp_packet_free_multi(pkts, pkt_cnt); - } else if (pkt_cnt == 0) { - continue; - } else { - break; - } - } - - return 0; -} - -#define COUNTER_SUM(_c, _nw) \ -__extension__ ({ \ - int _itr; \ - uint64_t _result = 0; \ - \ - for (_itr = 0; _itr < _nw; _itr++) \ - _result += args->thread[_itr].counters.ctr_ ## _c; \ - \ - _result; \ -}) - -static void garceful_stop_ping(void) -{ - uint64_t snd, rcv; - - if (args->appl.mode != APPL_MODE_PING) - return; - - while (args->appl.timeout >= 0) { - snd = COUNTER_SUM(pkt_snd, 2); - rcv = COUNTER_SUM(icmp_reply_rcv, 2); - if (rcv >= snd) - break; - - sleep(1); - args->appl.timeout--; - } -} - -/** - * printing verbose statistics - * - */ -static void print_global_stats(int num_workers) -{ - odp_time_t cur, wait, next, left; - uint64_t pkts_snd = 0, pkts_snd_prev = 0; - uint64_t pps_snd = 0, maximum_pps_snd = 0; - uint64_t pkts_rcv = 0, pkts_rcv_prev = 0; - uint64_t pps_rcv = 0, maximum_pps_rcv = 0; - uint64_t stall, pkts_snd_drop; - int verbose_interval = STATS_INTERVAL, i; - odp_thrmask_t thrd_mask; - - odp_barrier_wait(&args->barrier); - - wait = odp_time_local_from_ns(verbose_interval * ODP_TIME_SEC_IN_NS); - next = odp_time_sum(odp_time_local(), wait); - - while (odp_thrmask_worker(&thrd_mask) == num_workers) { - if (args->appl.mode != APPL_MODE_RCV && - args->appl.number != -1) { - uint64_t cnt = COUNTER_SUM(pkt_snd, num_workers); - - if (cnt >= (unsigned int)args->appl.number) { - garceful_stop_ping(); - break; - } - } - cur = odp_time_local(); - if (odp_time_cmp(next, cur) > 0) { - left = odp_time_diff(next, cur); - stall = odp_time_to_ns(left); - if (stall / ODP_TIME_SEC_IN_NS) - sleep(1); - else - usleep(stall / ODP_TIME_USEC_IN_NS); - continue; - } - next = odp_time_sum(cur, wait); - - switch (args->appl.mode) { - case APPL_MODE_RCV: - pkts_rcv = COUNTER_SUM(pkt_rcv, num_workers); - pkts_snd = 0; - pkts_snd_drop = 0; - break; - case APPL_MODE_PING: - pkts_snd = COUNTER_SUM(pkt_snd, num_workers); - pkts_snd_drop = COUNTER_SUM(pkt_snd_drop, num_workers); - pkts_rcv = COUNTER_SUM(icmp_reply_rcv, num_workers); - break; - case APPL_MODE_UDP: - pkts_snd = COUNTER_SUM(pkt_snd, num_workers); - pkts_snd_drop = COUNTER_SUM(pkt_snd_drop, num_workers); - break; - default: - continue; - } - - pps_snd = (pkts_snd - pkts_snd_prev) / verbose_interval; - pkts_snd_prev = pkts_snd; - if (pps_snd > maximum_pps_snd) - maximum_pps_snd = pps_snd; - - pps_rcv = (pkts_rcv - pkts_rcv_prev) / verbose_interval; - pkts_rcv_prev = pkts_rcv; - if (pps_rcv > maximum_pps_rcv) - maximum_pps_rcv = pps_rcv; - - printf("sent: %" PRIu64 ", drops: %" PRIu64 ", " - "send rate: %" PRIu64 " pps, " - "max send rate: %" PRIu64 " pps, " - "rcv: %" PRIu64 ", " - "recv rate: %" PRIu64 " pps, " - "max recv rate: %" PRIu64 " pps\n", - pkts_snd, pkts_snd_drop, - pps_snd, maximum_pps_snd, - pkts_rcv, pps_rcv, maximum_pps_rcv); - fflush(NULL); - } - - for (i = 0; i < num_workers; i++) - args->thread[i].stop = 1; -} - -/** - * ODP packet example main function - */ -int main(int argc, char *argv[]) -{ - odph_helper_options_t helper_options; - odph_thread_t thread_tbl[MAX_WORKERS]; - odp_pool_t pool; - int num_workers; - uint32_t num_rx_queues, num_tx_queues; - int i; - odp_shm_t shm; - odp_cpumask_t cpumask; - char cpumaskstr[ODP_CPUMASK_STR_SIZE]; - odp_pool_param_t params; - interface_t *ifs; - odp_instance_t instance; - odp_init_t init_param; - odph_thread_common_param_t thr_common; - odph_thread_param_t thr_param; - - /* Signal handler has to be registered before global init in case ODP - * implementation creates internal threads/processes. */ - signal(SIGINT, sig_handler); - - /* Let helper collect its own arguments (e.g. --odph_proc) */ - argc = odph_parse_options(argc, argv); - if (odph_options(&helper_options)) { - ODPH_ERR("Error: reading ODP helper options failed.\n"); - exit(EXIT_FAILURE); - } - - odp_init_param_init(&init_param); - init_param.mem_model = helper_options.mem_model; - - /* Init ODP before calling anything else */ - if (odp_init_global(&instance, &init_param, NULL)) { - ODPH_ERR("Error: ODP global init failed.\n"); - exit(EXIT_FAILURE); - } - - if (odp_init_local(instance, ODP_THREAD_CONTROL)) { - ODPH_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); - - if (shm == ODP_SHM_INVALID) { - ODPH_ERR("Error: shared mem reserve failed.\n"); - exit(EXIT_FAILURE); - } - - args = odp_shm_addr(shm); - - if (args == NULL) { - ODPH_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); - - num_workers = 1; - num_workers = odp_cpumask_default_worker(&cpumask, num_workers); - - if (args->appl.num_workers) { - /* -w option: number of workers */ - num_workers = args->appl.num_workers; - num_workers = odp_cpumask_default_worker(&cpumask, num_workers); - } else if (args->appl.mask) { - /* -c option: cpumask */ - 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); - fflush(NULL); - - /* ping mode need two workers */ - if (args->appl.mode == APPL_MODE_PING) { - if (num_workers < 2) { - ODPH_ERR("Need at least two worker threads\n"); - exit(EXIT_FAILURE); - } else { - num_workers = 2; - } - } - args->thread_cnt = num_workers; - - /* Burst size */ - if (args->appl.mode == APPL_MODE_PING) { - args->tx_burst_size = 1; - args->rx_burst_size = 1; - } else if (args->appl.mode == APPL_MODE_UDP) { - args->tx_burst_size = args->appl.udp_tx_burst; - args->rx_burst_size = 0; - } else { - args->tx_burst_size = 0; - args->rx_burst_size = args->appl.rx_burst; - } - - /* Configure scheduler */ - odp_schedule_config(NULL); - - /* Create packet pool */ - odp_pool_param_init(¶ms); - params.pkt.seg_len = POOL_PKT_LEN; - params.pkt.len = POOL_PKT_LEN; - params.pkt.num = POOL_NUM_PKT; - params.type = ODP_POOL_PACKET; - - pool = odp_pool_create("packet_pool", ¶ms); - - if (pool == ODP_POOL_INVALID) { - ODPH_ERR("Error: packet pool create failed.\n"); - exit(EXIT_FAILURE); - } - odp_pool_print(pool); - - ifs = malloc(sizeof(interface_t) * args->appl.if_count); - - for (i = 0; i < args->appl.if_count; ++i) { - if (args->appl.mode == APPL_MODE_PING) { - num_rx_queues = 1; - num_tx_queues = 1; - } else if (args->appl.mode == APPL_MODE_UDP) { - num_rx_queues = 0; - num_tx_queues = num_workers / args->appl.if_count; - if (i < num_workers % args->appl.if_count) - num_tx_queues++; - } else { /* APPL_MODE_RCV*/ - num_rx_queues = num_workers / args->appl.if_count; - if (i < num_workers % args->appl.if_count) - num_rx_queues++; - num_tx_queues = 0; - } - - if (create_pktio(args->appl.if_names[i], pool, num_rx_queues, - num_tx_queues, &ifs[i])) { - ODPH_ERR("Error: create interface %s failed.\n", - args->appl.if_names[i]); - exit(EXIT_FAILURE); - } - } - - /* Create and init worker threads */ - memset(thread_tbl, 0, sizeof(thread_tbl)); - - /* Init threads params */ - odph_thread_param_init(&thr_param); - thr_param.thr_type = ODP_THREAD_WORKER; - - odph_thread_common_param_init(&thr_common); - thr_common.instance = instance; - - /* num workers + print thread */ - odp_barrier_init(&args->barrier, num_workers + 1); - - if (args->appl.mode == APPL_MODE_PING) { - odp_cpumask_t cpu_mask; - int cpu_first, cpu_next; - thread_args_t *thr_args; - - odp_cpumask_zero(&cpu_mask); - cpu_first = odp_cpumask_first(&cpumask); - odp_cpumask_set(&cpu_mask, cpu_first); - - thr_args = &args->thread[PING_THR_RX]; - if (!args->appl.sched) - thr_args->rx.pktin = ifs[0].pktin[0]; - thr_args->pool = pool; - thr_args->mode = args->appl.mode; - - if (args->appl.sched) - thr_param.start = gen_recv_thread; - else - thr_param.start = gen_recv_direct_thread; - - thr_param.arg = thr_args; - - thr_common.cpumask = &cpu_mask; - - odph_thread_create(&thread_tbl[PING_THR_RX], &thr_common, - &thr_param, 1); - - thr_args = &args->thread[PING_THR_TX]; - thr_args->tx.pktout = ifs[0].pktout[0]; - thr_args->tx.pktout_cfg = &ifs[0].config.pktout; - thr_args->pool = pool; - thr_args->mode = args->appl.mode; - cpu_next = odp_cpumask_next(&cpumask, cpu_first); - odp_cpumask_zero(&cpu_mask); - odp_cpumask_set(&cpu_mask, cpu_next); - - thr_param.start = gen_send_thread; - thr_param.arg = thr_args; - - odph_thread_create(&thread_tbl[PING_THR_TX], &thr_common, - &thr_param, 1); - - } else { - int cpu = odp_cpumask_first(&cpumask); - udp_args_t *udp_param = NULL; - uint16_t sport_range = args->appl.srcport_end - - args->appl.srcport + 1; - uint16_t dport_range = args->appl.dstport_end - - args->appl.dstport + 1; - float sport_step = (float)(sport_range) / num_workers; - float dport_step = (float)(dport_range) / num_workers; - odp_bool_t multi_flow = false; - - if (sport_range > 1 || dport_range > 1) - multi_flow = true; - - for (i = 0; i < num_workers; ++i) { - odp_cpumask_t thd_mask; - int (*thr_run_func)(void *); - int if_idx, pktq_idx; - uint64_t start_seq; - - if_idx = i % args->appl.if_count; - - if (args->appl.mode == APPL_MODE_RCV) { - pktq_idx = (i / args->appl.if_count) % - ifs[if_idx].pktin_count; - if (!args->appl.sched) - args->thread[i].rx.pktin = - ifs[if_idx].pktin[pktq_idx]; - } else { - udp_param = &args->thread[i].tx.udp_param; - - pktq_idx = (i / args->appl.if_count) % - ifs[if_idx].pktout_count; - start_seq = i * args->tx_burst_size; - - args->thread[i].tx.pktout = - ifs[if_idx].pktout[pktq_idx]; - args->thread[i].tx.pktout_cfg = - &ifs[if_idx].config.pktout; - - udp_param->multi_flow = multi_flow; - udp_param->srcport_start = args->appl.srcport; - udp_param->srcport_end = args->appl.srcport_end; - udp_param->srcport_crt = args->appl.srcport; - if (sport_range > 1) - udp_param->srcport_crt += - (uint16_t)(i * sport_step); - - udp_param->dstport_start = args->appl.dstport; - udp_param->dstport_end = args->appl.dstport_end; - udp_param->dstport_crt = args->appl.dstport; - if (dport_range > 1) - udp_param->dstport_crt += - (uint16_t)(i * dport_step); - - args->thread[i].counters.ctr_seq = start_seq; - } - args->thread[i].pool = pool; - 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) { - if (args->appl.sched) - thr_run_func = gen_recv_thread; - else - thr_run_func = gen_recv_direct_thread; - } else { - ODPH_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); - - thr_param.start = thr_run_func; - thr_param.arg = &args->thread[i]; - - thr_common.cpumask = &thd_mask; - - odph_thread_create(&thread_tbl[i], &thr_common, - &thr_param, 1); - cpu = odp_cpumask_next(&cpumask, cpu); - } - } - - print_global_stats(num_workers); - - /* Master thread waits for other threads to exit */ - odph_thread_join(thread_tbl, num_workers); - - for (i = 0; i < args->appl.if_count; ++i) - odp_pktio_stop(ifs[i].pktio); - - for (i = 0; i < args->appl.if_count; ++i) - odp_pktio_close(ifs[i].pktio); - free(ifs); - free(args->appl.if_names); - free(args->appl.if_str); - args = NULL; - odp_mb_full(); - if (0 != odp_pool_destroy(pool)) - fprintf(stderr, "unable to destroy pool \"pool\"\n"); - if (0 != odp_shm_free(shm)) - fprintf(stderr, "unable to free \"shm\"\n"); - odp_term_local(); - odp_term_global(instance); - printf("Exit\n\n"); - - return 0; -} - -/** - * Parse and store the command line arguments - * - * @param argc argument count - * @param argv[] argument vector - * @param appl_args Store application arguments here - */ -static void parse_args(int argc, char *argv[], appl_args_t *appl_args) -{ - int opt; - int long_index; - char *token; - size_t len; - odp_cpumask_t cpumask, cpumask_args, cpumask_and; - int i, num_workers; - static const struct option longopts[] = { - {"interface", required_argument, NULL, 'I'}, - {"workers", required_argument, NULL, 'w'}, - {"cpumask", required_argument, NULL, 'c'}, - {"srcmac", required_argument, NULL, 'a'}, - {"dstmac", required_argument, NULL, 'b'}, - {"srcip", required_argument, NULL, 's'}, - {"dstip", required_argument, NULL, 'd'}, - {"srcport", required_argument, NULL, 'e'}, - {"srcport_end", required_argument, NULL, 'j'}, - {"dstport", required_argument, NULL, 'f'}, - {"dstport_end", required_argument, NULL, 'k'}, - {"packetsize", required_argument, NULL, 'p'}, - {"mode", required_argument, NULL, 'm'}, - {"count", required_argument, NULL, 'n'}, - {"timeout", required_argument, NULL, 't'}, - {"interval", required_argument, NULL, 'i'}, - {"help", no_argument, NULL, 'h'}, - {"udp_tx_burst", required_argument, NULL, 'x'}, - {"rx_burst", required_argument, NULL, 'r'}, - {"csum", no_argument, NULL, 'y'}, - {"sched", no_argument, NULL, 'z'}, - {NULL, 0, NULL, 0} - }; - - static const char *shortopts = "+I:a:b:s:d:p:i:m:n:t:w:c:x:he:j:f:k" - ":yr:z"; - - appl_args->mode = -1; /* Invalid, must be changed by parsing */ - appl_args->number = -1; - appl_args->payload = 56; - appl_args->timeout = -1; - appl_args->interval = DEFAULT_PKT_INTERVAL; - appl_args->udp_tx_burst = DEFAULT_UDP_TX_BURST; - appl_args->rx_burst = DEFAULT_RX_BURST; - appl_args->srcport = 0; - appl_args->srcport_end = 0; - appl_args->dstport = 0; - appl_args->dstport_end = 0; - appl_args->csum = 0; - appl_args->sched = 0; - appl_args->num_workers = -1; - - while (1) { - opt = getopt_long(argc, argv, shortopts, longopts, &long_index); - if (opt == -1) - break; /* No more options */ - - switch (opt) { - case 'w': - appl_args->num_workers = atoi(optarg); - break; - case 'c': - appl_args->mask = optarg; - odp_cpumask_from_str(&cpumask_args, args->appl.mask); - num_workers = odp_cpumask_default_worker(&cpumask, 0); - odp_cpumask_and(&cpumask_and, &cpumask_args, &cpumask); - if (odp_cpumask_count(&cpumask_and) < - odp_cpumask_count(&cpumask_args) || - odp_cpumask_count(&cpumask_args) > MAX_WORKERS) { - ODPH_ERR("Wrong cpu mask, max cpu's:%d\n", - num_workers < MAX_WORKERS ? - num_workers : MAX_WORKERS); - exit(EXIT_FAILURE); - } - break; - /* parse packet-io interface names */ - case 'I': - len = strlen(optarg); - if (len == 0) { - usage(argv[0]); - exit(EXIT_FAILURE); - } - len += 1; /* add room for '\0' */ - - appl_args->if_str = malloc(len); - if (appl_args->if_str == NULL) { - usage(argv[0]); - exit(EXIT_FAILURE); - } - - /* count the number of tokens separated by ',' */ - strcpy(appl_args->if_str, optarg); - for (token = strtok(appl_args->if_str, ","), i = 0; - token != NULL; - token = strtok(NULL, ","), i++) - ; - - appl_args->if_count = i; - - if (appl_args->if_count == 0) { - usage(argv[0]); - exit(EXIT_FAILURE); - } - - /* allocate storage for the if names */ - appl_args->if_names = - calloc(appl_args->if_count, sizeof(char *)); - - /* store the if names (reset names string) */ - strcpy(appl_args->if_str, optarg); - for (token = strtok(appl_args->if_str, ","), i = 0; - token != NULL; token = strtok(NULL, ","), i++) { - appl_args->if_names[i] = token; - } - break; - - case 'm': - if (optarg[0] == 'u') { - appl_args->mode = APPL_MODE_UDP; - } else if (optarg[0] == 'p') { - appl_args->mode = APPL_MODE_PING; - } else if (optarg[0] == 'r') { - appl_args->mode = APPL_MODE_RCV; - } else { - ODPH_ERR("wrong mode!\n"); - exit(EXIT_FAILURE); - } - break; - - case 'a': - if (odph_eth_addr_parse(&appl_args->srcmac, optarg)) { - ODPH_ERR("wrong src mac:%s\n", optarg); - exit(EXIT_FAILURE); - } - break; - - case 'b': - if (odph_eth_addr_parse(&appl_args->dstmac, optarg)) { - ODPH_ERR("wrong dst mac:%s\n", optarg); - exit(EXIT_FAILURE); - } - break; - - case 's': - if (scan_ip(optarg, &appl_args->srcip) != 1) { - ODPH_ERR("wrong src ip:%s\n", optarg); - exit(EXIT_FAILURE); - } - break; - - case 'd': - if (scan_ip(optarg, &appl_args->dstip) != 1) { - ODPH_ERR("wrong dst ip:%s\n", optarg); - exit(EXIT_FAILURE); - } - break; - - case 'e': - appl_args->srcport = (unsigned short)atoi(optarg); - break; - case 'j': - appl_args->srcport_end = (unsigned short)atoi(optarg); - break; - case 'f': - appl_args->dstport = (unsigned short)atoi(optarg); - break; - case 'k': - appl_args->dstport_end = (unsigned short)atoi(optarg); - break; - case 'p': - appl_args->payload = atoi(optarg); - break; - - case 'n': - appl_args->number = atoi(optarg); - break; - - case 't': - appl_args->timeout = atoi(optarg); - break; - - case 'i': - appl_args->interval = atoi(optarg); - if (appl_args->interval <= 200 && geteuid() != 0) { - ODPH_ERR("should be root user\n"); - exit(EXIT_FAILURE); - } - break; - case 'x': - appl_args->udp_tx_burst = atoi(optarg); - if (appl_args->udp_tx_burst > MAX_UDP_TX_BURST) { - ODPH_ERR("wrong UDP Tx burst size (max %d)\n", - MAX_UDP_TX_BURST); - exit(EXIT_FAILURE); - } - break; - case 'r': - appl_args->rx_burst = atoi(optarg); - if (appl_args->rx_burst > MAX_RX_BURST) { - ODPH_ERR("wrong Rx burst size (max %d)\n", - MAX_RX_BURST); - exit(EXIT_FAILURE); - } - break; - - case 'y': - appl_args->csum = 1; - break; - case 'z': - appl_args->sched = 1; - break; - case 'h': - usage(argv[0]); - exit(EXIT_SUCCESS); - break; - - default: - break; - } - } - - if (appl_args->num_workers < 0) - appl_args->num_workers = 0; - else if (appl_args->num_workers == 0 || - appl_args->num_workers > MAX_WORKERS) - appl_args->num_workers = MAX_WORKERS; - - if (appl_args->if_count == 0 || appl_args->mode == -1) { - usage(argv[0]); - exit(EXIT_FAILURE); - } - - if ((appl_args->srcport != 0 && appl_args->srcport_end == 0) || - (appl_args->srcport_end < appl_args->srcport)) - appl_args->srcport_end = appl_args->srcport; - - if ((appl_args->dstport != 0 && appl_args->dstport_end == 0) || - (appl_args->dstport_end < appl_args->dstport)) - appl_args->dstport_end = appl_args->dstport; - - optind = 1; /* reset 'extern optind' from the getopt lib */ -} - -/** - * Print system and application info - */ -static void print_info(char *progname, appl_args_t *appl_args) -{ - int i; - - odp_sys_info_print(); - - printf("Running ODP appl: \"%s\"\n" - "-----------------\n" - "IF-count: %i\n" - "Using IFs: ", - progname, appl_args->if_count); - for (i = 0; i < appl_args->if_count; ++i) - printf(" %s", appl_args->if_names[i]); - printf("\n" - "Mode: "); - if (appl_args->mode == 0) - PRINT_APPL_MODE(APPL_MODE_UDP); - else if (appl_args->mode == 1) - PRINT_APPL_MODE(APPL_MODE_PING); - else - PRINT_APPL_MODE(APPL_MODE_RCV); - printf("\n\n"); - fflush(NULL); -} - -/** - * Print usage information - */ -static void usage(char *progname) -{ - printf("\n" - "Usage: %s OPTIONS\n" - " E.g. %s -I eth1 -r\n" - "\n" - "OpenDataPlane example application.\n" - "\n" - " Work mode:\n" - " 1.send ipv4 udp packets\n" - " odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44 --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2 -m u\n" - " 2.receive ipv4 packets\n" - " odp_generator -I eth0 -m r\n" - " 3.work likes ping\n" - " odp_generator -I eth0 --srcmac fe:0f:97:c9:e0:44 --dstmac 32:cb:9b:27:2f:1a --srcip 192.168.0.1 --dstip 192.168.0.2 --cpumask 0xc -m p\n" - "\n" - "Mandatory OPTIONS:\n" - " -I, --interface Eth interfaces (comma-separated, no spaces)\n" - " -a, --srcmac src mac address\n" - " -b, --dstmac dst mac address\n" - " -s, --srcip src ip address\n" - " -d, --dstip dst ip address\n" - " -m, --mode work mode: send udp(u), receive(r), send icmp(p)\n" - "\n" - "Optional OPTIONS\n" - " -h, --help Display help and exit.\n" - " -e, --srcport udp source port start value\n" - " default is 0\n" - " -j, --srcport_end udp source port end value\n" - " default is udp source port start value\n" - " -f, --dstport udp destination port start value\n" - " default is 0\n" - " -k, --dstport_end udp destination port end value\n" - " default is udp destination port start value\n" - " -p, --packetsize payload length of the packets\n" - " -t, --timeout only for ping mode, wait ICMP reply timeout seconds\n" - " -i, --interval wait interval ms between sending each packet\n" - " default is 1000ms. 0 for flood mode\n" - " -w, --workers specify number of workers need to be assigned to application\n" - " default is 1, 0 for all available\n" - " -n, --count the number of packets to be send\n" - " -c, --cpumask to set on cores\n" - " -x, --udp_tx_burst size of UDP TX burst\n" - " -r, --rx_burst size of RX burst\n" - " -y, --csum use platform checksum support if available\n" - " default is disabled\n" - " -z, --sched use scheduler API to receive packets\n" - " default is direct mode API\n" - "\n", NO_PATH(progname), NO_PATH(progname) - ); -} diff --git a/example/m4/configure.m4 b/example/m4/configure.m4 index 852837e0d..b51d8bd42 100644 --- a/example/m4/configure.m4 +++ b/example/m4/configure.m4 @@ -22,7 +22,6 @@ AM_CONDITIONAL([test_example], [test x$test_example = xyes ]) AC_CONFIG_FILES([example/classifier/Makefile example/cli/Makefile example/debug/Makefile - example/generator/Makefile example/hello/Makefile example/ipsec_api/Makefile example/ipsec_crypto/Makefile -- cgit v1.2.3 From 210320702853e0cca96dc1867efe13eb1d663ff8 Mon Sep 17 00:00:00 2001 From: Fan Hong Date: Thu, 23 Nov 2023 02:24:25 +0000 Subject: example: classifier: fix memory leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free if_name, which is allocated using malloc(). Memory leak reported by GCC address sanitizer. Also, remove the conditional from another free() call, since free(NULL) is a no-op. Signed-off-by: Fan Hong Signed-off-by: Jere Leppänen Reviewed-by: Janne Peltonen Reviewed-by: Matias Elo --- example/classifier/odp_classifier.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'example') diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c index f4218fd9c..a361bb124 100644 --- a/example/classifier/odp_classifier.c +++ b/example/classifier/odp_classifier.c @@ -783,6 +783,8 @@ int main(int argc, char *argv[]) if (odp_pool_destroy(pool)) ODPH_ERR("err: odp_pool_destroy error\n"); + free(args->if_name); + args_error: odp_shm_free(shm); @@ -1281,9 +1283,7 @@ static int parse_args(int argc, char *argv[], appl_args_t *appl_args) if (ret) { usage(); - - if (appl_args->if_name) - free(appl_args->if_name); + free(appl_args->if_name); } /* reset optind from the getopt lib */ -- cgit v1.2.3 From 28f9d6cc214b169671d6ad481d4ff40069999f20 Mon Sep 17 00:00:00 2001 From: Fan Hong Date: Thu, 23 Nov 2023 07:50:46 +0000 Subject: example: ipsec: free interface names at exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free memory allocated for interface names at program termination. Memory leak reported by GCC address sanitizer. Signed-off-by: Fan Hong Signed-off-by: Jere Leppänen Reviewed-by: Janne Peltonen Reviewed-by: Matias Elo --- example/ipsec_api/odp_ipsec.c | 7 ++++--- example/ipsec_crypto/odp_ipsec.c | 7 ++++--- example/ipsec_crypto/odp_ipsec_stream.c | 25 ++++++++++++++++++++++++- example/ipsec_crypto/odp_ipsec_stream.h | 7 +++++-- 4 files changed, 37 insertions(+), 9 deletions(-) (limited to 'example') diff --git a/example/ipsec_api/odp_ipsec.c b/example/ipsec_api/odp_ipsec.c index a67a3a1e8..b6cc9ee22 100644 --- a/example/ipsec_api/odp_ipsec.c +++ b/example/ipsec_api/odp_ipsec.c @@ -45,6 +45,7 @@ #include #else static void init_stream_db(void) {} +static void deinit_stream_db(void) {} static void resolve_stream_db(void) {} static int create_stream_db_inputs(void) { @@ -1154,9 +1155,9 @@ main(int argc, char *argv[]) shm = odp_shm_lookup("shm_sp_db"); if (odp_shm_free(shm) != 0) ODPH_ERR("Error: shm free shm_sp_db failed\n"); - shm = odp_shm_lookup("stream_db"); - if (odp_shm_free(shm) != 0) - ODPH_ERR("Error: shm free stream_db failed\n"); + + deinit_stream_db(); + if (odp_shm_free(global->shm)) { ODPH_ERR("Error: shm free global data failed\n"); exit(EXIT_FAILURE); diff --git a/example/ipsec_crypto/odp_ipsec.c b/example/ipsec_crypto/odp_ipsec.c index 92e32d301..490d2ad0a 100644 --- a/example/ipsec_crypto/odp_ipsec.c +++ b/example/ipsec_crypto/odp_ipsec.c @@ -46,6 +46,7 @@ #include #else static void init_stream_db(void) {} +static void deinit_stream_db(void) {} static void resolve_stream_db(void) {} static int create_stream_db_inputs(void) { @@ -1437,9 +1438,9 @@ main(int argc, char *argv[]) shm = odp_shm_lookup("shm_sp_db"); if (odp_shm_free(shm) != 0) ODPH_ERR("Error: shm free shm_sp_db failed\n"); - shm = odp_shm_lookup("stream_db"); - if (odp_shm_free(shm) != 0) - ODPH_ERR("Error: shm free stream_db failed\n"); + + deinit_stream_db(); + if (odp_shm_free(global->shm)) { ODPH_ERR("Error: shm free global data failed\n"); exit(EXIT_FAILURE); diff --git a/example/ipsec_crypto/odp_ipsec_stream.c b/example/ipsec_crypto/odp_ipsec_stream.c index 330b4cc54..505ee900b 100644 --- a/example/ipsec_crypto/odp_ipsec_stream.c +++ b/example/ipsec_crypto/odp_ipsec_stream.c @@ -40,13 +40,14 @@ typedef struct ODP_PACKED stream_pkt_hdr_s { uint8_t data[]; /**< Incrementing data stream */ } stream_pkt_hdr_t; +static const char *shm_name = "stream_db"; stream_db_t *stream_db; void init_stream_db(void) { odp_shm_t shm; - shm = odp_shm_reserve("stream_db", + shm = odp_shm_reserve(shm_name, sizeof(stream_db_t), ODP_CACHE_LINE_SIZE, 0); @@ -65,6 +66,28 @@ void init_stream_db(void) memset(stream_db, 0, sizeof(*stream_db)); } +void deinit_stream_db(void) +{ + stream_db_entry_t *stream = NULL; + + for (stream = stream_db->list; NULL != stream; stream = stream->next) { + free(stream->input.intf); + free(stream->output.intf); + } + + odp_shm_t shm = odp_shm_lookup(shm_name); + + if (shm == ODP_SHM_INVALID) { + ODPH_ERR("Error: shared mem not found.\n"); + exit(EXIT_FAILURE); + } + + if (odp_shm_free(shm)) { + ODPH_ERR("Error: shared mem free failed.\n"); + exit(EXIT_FAILURE); + } +} + int create_stream_db_entry(char *input) { int pos = 0; diff --git a/example/ipsec_crypto/odp_ipsec_stream.h b/example/ipsec_crypto/odp_ipsec_stream.h index 8e1e936dd..c6bbb618b 100644 --- a/example/ipsec_crypto/odp_ipsec_stream.h +++ b/example/ipsec_crypto/odp_ipsec_stream.h @@ -31,14 +31,14 @@ typedef struct stream_db_entry_s { uint32_t verified; /**< Number successfully verified */ const EVP_MD *evp_md; /**< Digest method */ struct { - const char *intf; /**< Input interface name */ + char *intf; /**< Input interface name */ odp_pktio_t pktio; /**< Input PktI/O interface */ uint32_t ah_seq; /**< AH sequence number if present */ uint32_t esp_seq; /**< ESP sequence number if present */ ipsec_cache_entry_t *entry; /**< IPsec to apply on input */ } input; struct { - const char *intf; /**< Output interface name */ + char *intf; /**< Output interface name */ odp_pktio_t pktio; /**< Output PktI/O interface */ ipsec_cache_entry_t *entry; /**t IPsec to verify on output */ } output; @@ -58,6 +58,9 @@ extern stream_db_t *stream_db; /** Initialize stream database global control structure */ void init_stream_db(void); +/** Deinitialize stream database global control structure */ +void deinit_stream_db(void); + /** * Create an stream DB entry * -- cgit v1.2.3 From 752e5d66aca0a9ec09b409973c47f31d64cd590f Mon Sep 17 00:00:00 2001 From: Fan Hong Date: Mon, 27 Nov 2023 02:55:23 +0000 Subject: example: simple_pipeline: fix memory leaks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free the dynamically allocated interface name pointer array and the string containing the interface names. Memory leak reported by GCC address sanitizer. Signed-off-by: Fan Hong Signed-off-by: Jere Leppänen Reviewed-by: Janne Peltonen Reviewed-by: Matias Elo --- example/simple_pipeline/odp_simple_pipeline.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'example') diff --git a/example/simple_pipeline/odp_simple_pipeline.c b/example/simple_pipeline/odp_simple_pipeline.c index ad80bc394..3a05bf1c5 100644 --- a/example/simple_pipeline/odp_simple_pipeline.c +++ b/example/simple_pipeline/odp_simple_pipeline.c @@ -922,6 +922,9 @@ int main(int argc, char **argv) odph_thread_join(thr_tbl, num_threads); + free(global->appl.if_names); + free(global->appl.if_str); + if (odp_pktio_close(global->if0)) { printf("Error: failed to close interface %s\n", argv[1]); exit(EXIT_FAILURE); -- cgit v1.2.3 From 3c2f48311b4e52ea62f933fafe931742447cf1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Wed, 20 Mar 2024 10:13:57 +0200 Subject: example: ipfragreass: avoid undefined behavior in bit shift in hash() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid undefined behavior in bit shift in hash() by casting to an unsigned integer of sufficient width before the shift operation. Fixes GCC undefined sanitizer error: odp_ipfragreass_reassemble.c:92:23: runtime error: left shift of 40448 by 16 places cannot be represented in type 'int' Signed-off-by: Jere Leppänen Reviewed-by: Janne Peltonen --- example/ipfragreass/odp_ipfragreass_reassemble.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'example') diff --git a/example/ipfragreass/odp_ipfragreass_reassemble.c b/example/ipfragreass/odp_ipfragreass_reassemble.c index 55ee42504..89055e6e4 100644 --- a/example/ipfragreass/odp_ipfragreass_reassemble.c +++ b/example/ipfragreass/odp_ipfragreass_reassemble.c @@ -89,7 +89,7 @@ static inline uint32_t hash(odph_ipv4hdr_t *hdr) { uint32_t a = hdr->src_addr; uint32_t b = hdr->dst_addr; - uint32_t c = hdr->id << 16 | hdr->proto; + uint32_t c = (uint32_t)hdr->id << 16 | hdr->proto; /* A degenerate 3x32-bit Jenkins hash */ c ^= b; -- cgit v1.2.3 From 9795b754631140566d6e793ec76d56f5ead064c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Wed, 20 Mar 2024 17:19:54 +0200 Subject: example: ipsec: use unsigned integers to form ip4 address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In parse_ipv4_string(), use unsigned variables and scanf formatters to avoid negative values, and cast to uint32_t in order to avoid undefined behavior in bit shift operations. Fixes GCC undefined sanitizer error: odp_ipsec_misc.h:192:47: runtime error: left shift of 192 by 24 places cannot be represented in type 'int' Signed-off-by: Jere Leppänen Reviewed-by: Janne Peltonen --- example/ipsec_crypto/odp_ipsec_misc.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'example') diff --git a/example/ipsec_crypto/odp_ipsec_misc.h b/example/ipsec_crypto/odp_ipsec_misc.h index 921c4e3c0..5fba274d0 100644 --- a/example/ipsec_crypto/odp_ipsec_misc.h +++ b/example/ipsec_crypto/odp_ipsec_misc.h @@ -167,18 +167,18 @@ char *ipv4_addr_str(char *b, uint32_t addr) static inline int parse_ipv4_string(char *ipaddress, uint32_t *addr, uint32_t *mask) { - int b[4]; + unsigned int b[4]; int qualifier = 32; int converted; if (strchr(ipaddress, '/')) { - converted = sscanf(ipaddress, "%d.%d.%d.%d/%d", + converted = sscanf(ipaddress, "%u.%u.%u.%u/%d", &b[3], &b[2], &b[1], &b[0], &qualifier); if (5 != converted) return -1; } else { - converted = sscanf(ipaddress, "%d.%d.%d.%d", + converted = sscanf(ipaddress, "%u.%u.%u.%u", &b[3], &b[2], &b[1], &b[0]); if (4 != converted) return -1; @@ -189,7 +189,7 @@ int parse_ipv4_string(char *ipaddress, uint32_t *addr, uint32_t *mask) if (!qualifier || (qualifier > 32)) return -1; - *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; + *addr = (uint32_t)b[0] | (uint32_t)b[1] << 8 | (uint32_t)b[2] << 16 | (uint32_t)b[3] << 24; if (mask) *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) - 1)); -- cgit v1.2.3 From 0e1ed04ce2ecbca74edbdc7a3169eea2e268470c Mon Sep 17 00:00:00 2001 From: Tuomas Taipale Date: Tue, 23 Apr 2024 05:31:08 +0000 Subject: example: cli: utilize new join function Utilize new `odph_thread_join_result()` to check the return values of joined threads. Signed-off-by: Tuomas Taipale Reviewed-by: Matias Elo --- example/cli/odp_cli.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'example') diff --git a/example/cli/odp_cli.c b/example/cli/odp_cli.c index 381fc8a59..bc5dad960 100644 --- a/example/cli/odp_cli.c +++ b/example/cli/odp_cli.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright (c) 2021 Nokia + * Copyright (c) 2021-2024 Nokia */ /** @@ -101,7 +101,7 @@ static int cli_server(void *arg ODP_UNUSED) /* Run CLI server. */ if (odph_cli_run()) { ODPH_ERR("odph_cli_run() failed.\n"); - exit(EXIT_FAILURE); + return -1; } return 0; @@ -178,6 +178,7 @@ int main(int argc, char *argv[]) odph_thread_common_param_t thr_common; odph_thread_param_t thr_param; odph_thread_t thr_server; + odph_thread_join_result_t res; if (odp_cpumask_default_control(&cpumask, 1) != 1) { ODPH_ERR("Failed to get default CPU mask.\n"); @@ -199,7 +200,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - printf("CLI server started on %s:%d\n", cli_param.address, + printf("CLI server started on %s:%d.\n", cli_param.address, cli_param.port); /* Wait for the given number of seconds. */ @@ -215,11 +216,17 @@ int main(int argc, char *argv[]) } /* Wait for server thread to exit. */ - if (odph_thread_join(&thr_server, 1) != 1) { + if (odph_thread_join_result(&thr_server, &res, 1) != 1) { ODPH_ERR("Failed to join server thread.\n"); exit(EXIT_FAILURE); } + if (res.is_sig || res.ret != 0) { + ODPH_ERR("Worker thread failure%s: %d.\n", res.is_sig ? " (signaled)" : "", + res.ret); + exit(EXIT_FAILURE); + } + /* Terminate CLI helper. */ if (odph_cli_term()) { ODPH_ERR("CLI helper termination failed.\n"); -- cgit v1.2.3 From 3009450e7a9faf32ed5a6f5356341e6e87f80325 Mon Sep 17 00:00:00 2001 From: Tuomas Taipale Date: Tue, 23 Apr 2024 05:31:49 +0000 Subject: example: l2fwd_simple: utilize new join function Utilize new `odph_thread_join_result()` to check the return values of joined threads. Signed-off-by: Tuomas Taipale Reviewed-by: Matias Elo --- example/l2fwd_simple/odp_l2fwd_simple.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'example') diff --git a/example/l2fwd_simple/odp_l2fwd_simple.c b/example/l2fwd_simple/odp_l2fwd_simple.c index 5d9aaec87..1ea08cce1 100644 --- a/example/l2fwd_simple/odp_l2fwd_simple.c +++ b/example/l2fwd_simple/odp_l2fwd_simple.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2016-2018 Linaro Limited + * Copyright (c) 2024 Nokia */ /** @@ -101,12 +102,12 @@ static int run_worker(void *arg ODP_UNUSED) if (odp_pktio_start(global->if0)) { printf("unable to start input interface\n"); - exit(1); + return -1; } printf("started input interface\n"); if (odp_pktio_start(global->if1)) { printf("unable to start output interface\n"); - exit(1); + return -1; } printf("started output interface\n"); printf("started all\n"); @@ -159,6 +160,7 @@ int main(int argc, char **argv) odph_ethaddr_t correct_src; uint32_t mtu1, mtu2; odp_shm_t shm; + odph_thread_join_result_t res[MAX_WORKERS]; /* Let helper collect its own arguments (e.g. --odph_proc) */ argc = odph_parse_options(argc, argv); @@ -271,11 +273,19 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - if (odph_thread_join(thd, MAX_WORKERS) != MAX_WORKERS) { + if (odph_thread_join_result(thd, res, MAX_WORKERS) != MAX_WORKERS) { printf("Error: failed to join threads\n"); exit(EXIT_FAILURE); } + for (int i = 0; i < MAX_WORKERS; i++) { + if (res[i].is_sig || res[i].ret != 0) { + printf("Error: thread failure%s: %d\n", res[i].is_sig ? + " (signaled)" : "", res[i].ret); + exit(EXIT_FAILURE); + } + } + if (odp_pktio_stop(global->if0) || odp_pktio_close(global->if0)) { printf("Error: failed to close interface %s\n", argv[1]); exit(EXIT_FAILURE); -- cgit v1.2.3 From bc854b8eab342247da1f927a870f68a3774a10d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Fri, 16 Feb 2024 14:29:28 +0200 Subject: test, example: use odph_strcpy() instead of strncpy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use odph_strcpy() instead of strncpy(). Signed-off-by: Jere Leppänen Reviewed-by: Matias Elo --- example/classifier/odp_classifier.c | 42 ++++++++++++++++----------------- example/ipsec_crypto/odp_ipsec_fwd_db.c | 3 +-- example/l3fwd/odp_l3fwd_db.c | 3 +-- example/sysinfo/odp_sysinfo.c | 2 +- 4 files changed, 24 insertions(+), 26 deletions(-) (limited to 'example') diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c index a361bb124..d24224e6f 100644 --- a/example/classifier/odp_classifier.c +++ b/example/classifier/odp_classifier.c @@ -979,16 +979,16 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) case ODP_PMR_TCP_SPORT: /* :: */ token = strtok(NULL, ":"); - strncpy(stats[policy_count].value, token, - DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].value, token, + DISPLAY_STRING_LEN); value = strtoul(token, NULL, 0); u16 = value; u16 = odp_cpu_to_be_16(u16); memcpy(stats[policy_count].rule.value_be, &u16, sizeof(u16)); token = strtok(NULL, ":"); - strncpy(stats[policy_count].mask, token, - DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].mask, token, + DISPLAY_STRING_LEN); mask = strtoul(token, NULL, 0); u16 = mask; u16 = odp_cpu_to_be_16(u16); @@ -1001,8 +1001,8 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) case ODP_PMR_SIP_ADDR: /* :: */ token = strtok(NULL, ":"); - strncpy(stats[policy_count].value, token, - DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].value, token, + DISPLAY_STRING_LEN); if (odph_ipv4_addr_parse(&ip_addr, token)) { ODPH_ERR("Bad IP address\n"); @@ -1013,8 +1013,8 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) memcpy(stats[policy_count].rule.value_be, &u32, sizeof(u32)); token = strtok(NULL, ":"); - strncpy(stats[policy_count].mask, token, - DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].mask, token, + DISPLAY_STRING_LEN); mask = strtoul(token, NULL, 0); u32 = mask; u32 = odp_cpu_to_be_32(u32); @@ -1025,8 +1025,8 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) case ODP_PMR_DMAC: /* :: */ token = strtok(NULL, ":"); - strncpy(stats[policy_count].value, token, - DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].value, token, + DISPLAY_STRING_LEN); /* Replace hyphens in the MAC string with colons to be compatible with * odph_eth_addr_parse(). */ @@ -1043,7 +1043,7 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) stats[policy_count].rule.val_sz = 6; token = strtok(NULL, ":"); - strncpy(stats[policy_count].mask, token, DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].mask, token, DISPLAY_STRING_LEN); mask_sz = parse_custom(token, stats[policy_count].rule.mask_be, ODPH_ETHADDR_LEN); if (mask_sz != ODPH_ETHADDR_LEN) { ODPH_ERR("Invalid mask. Provide mask without 0x prefix.\n"); @@ -1062,8 +1062,8 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) goto error; token = strtok(NULL, ":"); - strncpy(stats[policy_count].value, token, - DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].value, token, + DISPLAY_STRING_LEN); val_sz = parse_custom(token, stats[policy_count].rule.value_be, MAX_VAL_SIZE); @@ -1072,8 +1072,8 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) goto error; token = strtok(NULL, ":"); - strncpy(stats[policy_count].mask, token, - DISPLAY_STRING_LEN - 1); + odph_strcpy(stats[policy_count].mask, token, + DISPLAY_STRING_LEN); mask_sz = parse_custom(token, stats[policy_count].rule.mask_be, MAX_VAL_SIZE); @@ -1093,13 +1093,13 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *optarg) if (cos1) { stats[policy_count].has_src_cos = 1; - strncpy(stats[policy_count].src_cos_name, cos0, - ODP_COS_NAME_LEN - 1); - strncpy(stats[policy_count].cos_name, cos1, - ODP_COS_NAME_LEN - 1); + odph_strcpy(stats[policy_count].src_cos_name, cos0, + ODP_COS_NAME_LEN); + odph_strcpy(stats[policy_count].cos_name, cos1, + ODP_COS_NAME_LEN); } else { - strncpy(stats[policy_count].cos_name, cos0, - ODP_COS_NAME_LEN - 1); + odph_strcpy(stats[policy_count].cos_name, cos0, + ODP_COS_NAME_LEN); } appl_args->policy_count++; diff --git a/example/ipsec_crypto/odp_ipsec_fwd_db.c b/example/ipsec_crypto/odp_ipsec_fwd_db.c index 292d9c7c6..482813d41 100644 --- a/example/ipsec_crypto/odp_ipsec_fwd_db.c +++ b/example/ipsec_crypto/odp_ipsec_fwd_db.c @@ -78,8 +78,7 @@ int create_fwd_db_entry(char *input, char **if_names, int if_count) &entry->subnet.mask); break; case 1: - strncpy(entry->oif, token, OIF_LEN - 1); - entry->oif[OIF_LEN - 1] = 0; + odph_strcpy(entry->oif, token, OIF_LEN); for (i = 0; i < if_count; i++) { if (!strcmp(if_names[i], entry->oif)) { match = 1; diff --git a/example/l3fwd/odp_l3fwd_db.c b/example/l3fwd/odp_l3fwd_db.c index 7d82695be..622c0a118 100644 --- a/example/l3fwd/odp_l3fwd_db.c +++ b/example/l3fwd/odp_l3fwd_db.c @@ -401,8 +401,7 @@ int create_fwd_db_entry(char *input, char **oif, uint8_t **dst_mac) &entry->subnet.depth); break; case 1: - strncpy(entry->oif, token, OIF_LEN - 1); - entry->oif[OIF_LEN - 1] = 0; + odph_strcpy(entry->oif, token, OIF_LEN); *oif = entry->oif; break; case 2: diff --git a/example/sysinfo/odp_sysinfo.c b/example/sysinfo/odp_sysinfo.c index df33f45cf..d6eb4ee43 100644 --- a/example/sysinfo/odp_sysinfo.c +++ b/example/sysinfo/odp_sysinfo.c @@ -686,7 +686,7 @@ static void parse_interfaces(appl_args_t *config, const char *optarg) MAX_NAME_LEN); exit(EXIT_FAILURE); } - strncpy(config->pktio[config->num_pktio].name, tmp, MAX_NAME_LEN); + odph_strcpy(config->pktio[config->num_pktio].name, tmp, MAX_NAME_LEN); config->num_pktio++; -- cgit v1.2.3 From 435afcf7ca74fb2af72d782908156ed4d54b57f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jere=20Lepp=C3=A4nen?= Date: Mon, 11 Mar 2024 11:54:23 +0200 Subject: validation, example: tm: use new ODP_TM_NAME_LEN constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use new ODP_TM_NAME_LEN constant to reserve space for traffic manager object names. Signed-off-by: Jere Leppänen Reviewed-by: Tuomas Taipale --- example/traffic_mgmt/odp_traffic_mgmt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'example') diff --git a/example/traffic_mgmt/odp_traffic_mgmt.c b/example/traffic_mgmt/odp_traffic_mgmt.c index 4ed4f2044..17dcbaa13 100644 --- a/example/traffic_mgmt/odp_traffic_mgmt.c +++ b/example/traffic_mgmt/odp_traffic_mgmt.c @@ -343,7 +343,7 @@ static uint32_t create_profile_set(profile_params_set_t *profile_params_set, odp_tm_shaper_params_t shaper_params, *shaper; odp_tm_wred_params_t wred_params, *wred; uint32_t err_cnt, color; - char name[64], wred_name[64]; + char name[ODP_TM_NAME_LEN], wred_name[ODP_TM_NAME_LEN]; err_cnt = 0; if (name_idx == 0) @@ -477,7 +477,7 @@ static int config_example_user(odp_tm_node_t cos_tm_node, odp_tm_node_t user_tm_node; profile_set_t *profile_set; uint32_t app_idx, queue_idx, svc_class_queue_num; - char user_name[64]; + char user_name[ODP_TM_NAME_LEN]; int rc; profile_set = &USER_PROFILE_SETS[svc_class]; @@ -538,7 +538,7 @@ static int config_company_node(const char *company_name) profile_set_t *profile_set; odp_tm_node_t company_tm_node, cos_tm_node; uint32_t cos_idx, user_idx; - char cos_node_name[64]; + char cos_node_name[ODP_TM_NAME_LEN]; profile_set = &COMPANY_PROFILE_SET; odp_tm_node_params_init(&tm_node_params); -- cgit v1.2.3 From 6b47594fdc9c7e36288bbf1618c4f115a19a6e29 Mon Sep 17 00:00:00 2001 From: Janne Peltonen Date: Fri, 26 Apr 2024 16:44:44 +0300 Subject: example: sysinfo: add new crypto algorithms Add the newly added crypto algorithms and add the old 3DES-ECB algorithm that has been missing from sysinfo. Signed-off-by: Janne Peltonen Reviewed-by: Petri Savolainen Acked-by: Anoob Joseph --- example/sysinfo/odp_sysinfo.c | 92 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) (limited to 'example') diff --git a/example/sysinfo/odp_sysinfo.c b/example/sysinfo/odp_sysinfo.c index d6eb4ee43..6ddbf0ad9 100644 --- a/example/sysinfo/odp_sysinfo.c +++ b/example/sysinfo/odp_sysinfo.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) 2018 Linaro Limited - * Copyright (c) 2022-2023 Nokia + * Copyright (c) 2022-2024 Nokia */ /** @@ -169,6 +169,8 @@ static const char *cipher_alg_name(odp_cipher_alg_t cipher) return "des"; case ODP_CIPHER_ALG_3DES_CBC: return "3des_cbc"; + case ODP_CIPHER_ALG_3DES_ECB: + return "3des_ecb"; case ODP_CIPHER_ALG_AES_CBC: return "aes_cbc"; case ODP_CIPHER_ALG_AES_CTR: @@ -193,6 +195,20 @@ static const char *cipher_alg_name(odp_cipher_alg_t cipher) return "aes_eea2"; case ODP_CIPHER_ALG_ZUC_EEA3: return "zuc_eea3"; + case ODP_CIPHER_ALG_SNOW_V: + return "snow_v"; + case ODP_CIPHER_ALG_SNOW_V_GCM: + return "snow_v_gcm"; + case ODP_CIPHER_ALG_SM4_ECB: + return "sm4_ecb"; + case ODP_CIPHER_ALG_SM4_CBC: + return "sm4_cbc"; + case ODP_CIPHER_ALG_SM4_CTR: + return "sm4_ctr"; + case ODP_CIPHER_ALG_SM4_GCM: + return "sm4_gcm"; + case ODP_CIPHER_ALG_SM4_CCM: + return "sm4_ccm"; default: return "Unknown"; } @@ -215,6 +231,14 @@ static const char *auth_alg_name(odp_auth_alg_t auth) return "sha384_hmac"; case ODP_AUTH_ALG_SHA512_HMAC: return "sha512_hmac"; + case ODP_AUTH_ALG_SHA3_224_HMAC: + return "sha3_224_hmac"; + case ODP_AUTH_ALG_SHA3_256_HMAC: + return "sha3_256_hmac"; + case ODP_AUTH_ALG_SHA3_384_HMAC: + return "sha3_384_hmac"; + case ODP_AUTH_ALG_SHA3_512_HMAC: + return "sha3_512_hmac"; case ODP_AUTH_ALG_AES_GCM: return "aes_gcm"; case ODP_AUTH_ALG_AES_GMAC: @@ -235,6 +259,18 @@ static const char *auth_alg_name(odp_auth_alg_t auth) return "aes_eia2"; case ODP_AUTH_ALG_ZUC_EIA3: return "zuc_eia3"; + case ODP_AUTH_ALG_SNOW_V_GCM: + return "snow_v_gcm"; + case ODP_AUTH_ALG_SNOW_V_GMAC: + return "snow_v_gmac"; + case ODP_AUTH_ALG_SM3_HMAC: + return "sm3_hmac"; + case ODP_AUTH_ALG_SM4_GCM: + return "sm4_gcm"; + case ODP_AUTH_ALG_SM4_GMAC: + return "sm4_gmac"; + case ODP_AUTH_ALG_SM4_CCM: + return "sm4_ccm"; case ODP_AUTH_ALG_MD5: return "md5"; case ODP_AUTH_ALG_SHA1: @@ -247,6 +283,16 @@ static const char *auth_alg_name(odp_auth_alg_t auth) return "sha384"; case ODP_AUTH_ALG_SHA512: return "sha512"; + case ODP_AUTH_ALG_SHA3_224: + return "sha3_224"; + case ODP_AUTH_ALG_SHA3_256: + return "sha3_256"; + case ODP_AUTH_ALG_SHA3_384: + return "sha3_384"; + case ODP_AUTH_ALG_SHA3_512: + return "sha3_512"; + case ODP_AUTH_ALG_SM3: + return "sm3"; default: return "Unknown"; } @@ -289,6 +335,20 @@ static void foreach_cipher(odp_crypto_cipher_algos_t ciphers, cipher_op_t op) op(ODP_CIPHER_ALG_AES_EEA2); if (ciphers.bit.zuc_eea3) op(ODP_CIPHER_ALG_ZUC_EEA3); + if (ciphers.bit.snow_v) + op(ODP_CIPHER_ALG_SNOW_V); + if (ciphers.bit.snow_v_gcm) + op(ODP_CIPHER_ALG_SNOW_V_GCM); + if (ciphers.bit.sm4_ecb) + op(ODP_CIPHER_ALG_SM4_ECB); + if (ciphers.bit.sm4_cbc) + op(ODP_CIPHER_ALG_SM4_CBC); + if (ciphers.bit.sm4_ctr) + op(ODP_CIPHER_ALG_SM4_CTR); + if (ciphers.bit.sm4_gcm) + op(ODP_CIPHER_ALG_SM4_GCM); + if (ciphers.bit.sm4_ccm) + op(ODP_CIPHER_ALG_SM4_CCM); } static void foreach_auth(odp_crypto_auth_algos_t auths, auth_op_t op) @@ -307,6 +367,14 @@ static void foreach_auth(odp_crypto_auth_algos_t auths, auth_op_t op) op(ODP_AUTH_ALG_SHA384_HMAC); if (auths.bit.sha512_hmac) op(ODP_AUTH_ALG_SHA512_HMAC); + if (auths.bit.sha3_224_hmac) + op(ODP_AUTH_ALG_SHA3_224_HMAC); + if (auths.bit.sha3_256_hmac) + op(ODP_AUTH_ALG_SHA3_256_HMAC); + if (auths.bit.sha3_384_hmac) + op(ODP_AUTH_ALG_SHA3_384_HMAC); + if (auths.bit.sha3_512_hmac) + op(ODP_AUTH_ALG_SHA3_512_HMAC); if (auths.bit.aes_gcm) op(ODP_AUTH_ALG_AES_GCM); if (auths.bit.aes_gmac) @@ -327,6 +395,18 @@ static void foreach_auth(odp_crypto_auth_algos_t auths, auth_op_t op) op(ODP_AUTH_ALG_AES_EIA2); if (auths.bit.zuc_eia3) op(ODP_AUTH_ALG_ZUC_EIA3); + if (auths.bit.snow_v_gcm) + op(ODP_AUTH_ALG_SNOW_V_GCM); + if (auths.bit.snow_v_gmac) + op(ODP_AUTH_ALG_SNOW_V_GMAC); + if (auths.bit.sm3_hmac) + op(ODP_AUTH_ALG_SM3_HMAC); + if (auths.bit.sm4_gcm) + op(ODP_AUTH_ALG_SM4_GCM); + if (auths.bit.sm4_gmac) + op(ODP_AUTH_ALG_SM4_GMAC); + if (auths.bit.sm4_ccm) + op(ODP_AUTH_ALG_SM4_CCM); if (auths.bit.md5) op(ODP_AUTH_ALG_MD5); if (auths.bit.sha1) @@ -339,6 +419,16 @@ static void foreach_auth(odp_crypto_auth_algos_t auths, auth_op_t op) op(ODP_AUTH_ALG_SHA384); if (auths.bit.sha512) op(ODP_AUTH_ALG_SHA512); + if (auths.bit.sha3_224) + op(ODP_AUTH_ALG_SHA3_224); + if (auths.bit.sha3_256) + op(ODP_AUTH_ALG_SHA3_256); + if (auths.bit.sha3_384) + op(ODP_AUTH_ALG_SHA3_384); + if (auths.bit.sha3_512) + op(ODP_AUTH_ALG_SHA3_512); + if (auths.bit.sm3) + op(ODP_AUTH_ALG_SM3); } static void print_cipher_capa(odp_cipher_alg_t cipher) -- cgit v1.2.3