diff options
Diffstat (limited to 'example/debug/odp_debug.c')
-rw-r--r-- | example/debug/odp_debug.c | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/example/debug/odp_debug.c b/example/debug/odp_debug.c new file mode 100644 index 000000000..79107ca8f --- /dev/null +++ b/example/debug/odp_debug.c @@ -0,0 +1,724 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2020-2022 Nokia + */ + +/** + * @example odp_debug.c + * + * This example application demonstrates the usage of various debug print functions of ODP API. + * + * @cond _ODP_HIDE_FROM_DOXYGEN_ + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <string.h> +#include <getopt.h> + +#include <odp_api.h> +#include <odp/helper/odph_api.h> + +#define MAX_NAME_LEN 128 + +typedef struct test_global_t { + int system; + int shm; + int pool; + int queue; + int pktio; + int ipsec; + int timer; + int stash; + char pktio_name[MAX_NAME_LEN]; + +} test_global_t; + +static test_global_t test_global; + +static void print_usage(void) +{ + printf("This example prints out debug information on various ODP objects.\n" + "Select debug functions to be called with options. All listed functions\n" + "are called when no options are given.\n" + "\n" + "OPTIONS:\n" + " -S, --system Call odp_sys_info_print() and odp_sys_config_print()\n" + " -s, --shm Create a SHM and call odp_shm_print()\n" + " -p, --pool Create various types of pools and call odp_pool_print()\n" + " -q, --queue Create various types of queues and call odp_queue_print()\n" + " -i, --interface <name> Start a packet IO interface, and call odp_pktio_print(),\n" + " odp_pktio_extra_stats_print(), etc. Uses loop interface by default.\n" + " -I, --ipsec Call odp_ipsec_print()\n" + " -t, --timer Call timer pool, timer and timeout print functions\n" + " -a, --stash Create stash and call odp_stash_print()\n" + " -h, --help Display help and exit.\n\n"); +} + +static int parse_options(int argc, char *argv[], test_global_t *global) +{ + int opt, long_index; + char *str; + uint32_t str_len = 0; + + const struct option longopts[] = { + {"system", no_argument, NULL, 'S'}, + {"shm", no_argument, NULL, 's'}, + {"pool", no_argument, NULL, 'p'}, + {"queue", no_argument, NULL, 'q'}, + {"interface", required_argument, NULL, 'i'}, + {"ipsec", no_argument, NULL, 'I'}, + {"timer", no_argument, NULL, 't'}, + {"stash", no_argument, NULL, 'a'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + const char *shortopts = "+Sspqi:Itah"; + int ret = 0; + + while (1) { + opt = getopt_long(argc, argv, shortopts, longopts, &long_index); + + if (opt == -1) + break; /* No more options */ + + switch (opt) { + case 'S': + global->system = 1; + break; + case 's': + global->shm = 1; + break; + case 'p': + global->pool = 1; + break; + case 'q': + global->queue = 1; + break; + case 'i': + global->pktio = 1; + str = optarg; + str_len = strlen(str); + + if (str_len && str_len < MAX_NAME_LEN) + strcpy(global->pktio_name, str); + break; + case 'I': + global->ipsec = 1; + break; + case 't': + global->timer = 1; + break; + case 'a': + global->stash = 1; + break; + case 'h': + default: + print_usage(); + return -1; + } + } + + if (global->pktio && (str_len == 0 || str_len >= MAX_NAME_LEN)) { + ODPH_ERR("Bad interface name length: %u\n", str_len); + ret = -1; + } + + return ret; +} + +static int shm_debug(void) +{ + const char *name = "debug_shm"; + odp_shm_t shm = ODP_SHM_INVALID; + + shm = odp_shm_reserve(name, 8 * 1024, 64, 0); + if (shm == ODP_SHM_INVALID) { + ODPH_ERR("SHM reserve failed: %s\n", name); + return -1; + } + + printf("\n"); + odp_shm_print_all(); + + printf("\n"); + odp_shm_print(shm); + + if (odp_shm_free(shm)) { + ODPH_ERR("SHM free failed: %s\n", name); + return -1; + } + + return 0; +} + +static int buffer_debug(odp_pool_t pool) +{ + odp_buffer_t buf = odp_buffer_alloc(pool); + + if (buf == ODP_BUFFER_INVALID) { + ODPH_ERR("Buffer alloc failed\n"); + return -1; + } + + printf("\n"); + odp_buffer_print(buf); + + odp_buffer_free(buf); + + return 0; +} + +static int packet_debug(odp_pool_t pool, int len) +{ + odp_packet_t pkt = odp_packet_alloc(pool, len); + + if (pkt == ODP_PACKET_INVALID) { + ODPH_ERR("Packet alloc failed\n"); + return -1; + } + + printf("\n"); + odp_packet_print(pkt); + + printf("\n"); + odp_packet_print_data(pkt, 0, len); + + odp_packet_free(pkt); + + return 0; +} + +static int pool_debug(void) +{ + odp_pool_t pool; + odp_pool_param_t param; + const char *name; + int pkt_len = 100; + + name = "debug_buffer_pool"; + odp_pool_param_init(¶m); + param.type = ODP_POOL_BUFFER; + param.buf.num = 10; + param.buf.size = 1000; + + pool = odp_pool_create(name, ¶m); + + if (pool == ODP_POOL_INVALID) { + ODPH_ERR("Pool create failed: %s\n", name); + return -1; + } + + printf("\n"); + odp_pool_print(pool); + + if (buffer_debug(pool)) + return -1; + + if (odp_pool_destroy(pool)) { + ODPH_ERR("Pool destroy failed: %s\n", name); + return -1; + } + + name = "debug_packet_pool"; + odp_pool_param_init(¶m); + param.type = ODP_POOL_PACKET; + param.pkt.num = 10; + param.pkt.len = pkt_len; + param.pkt.max_len = 1000; + + pool = odp_pool_create(name, ¶m); + + if (pool == ODP_POOL_INVALID) { + ODPH_ERR("Pool create failed: %s\n", name); + return -1; + } + + printf("\n"); + odp_pool_print(pool); + + if (packet_debug(pool, pkt_len)) + return -1; + + if (odp_pool_destroy(pool)) { + ODPH_ERR("Pool destroy failed: %s\n", name); + return -1; + } + + name = "debug_tmo_pool"; + odp_pool_param_init(¶m); + param.type = ODP_POOL_TIMEOUT; + param.tmo.num = 10; + + pool = odp_pool_create(name, ¶m); + + if (pool == ODP_POOL_INVALID) { + ODPH_ERR("Pool create failed: %s\n", name); + return -1; + } + + printf("\n"); + odp_pool_print(pool); + + if (odp_pool_destroy(pool)) { + ODPH_ERR("Pool destroy failed: %s\n", name); + return -1; + } + + return 0; +} + +static int queue_debug(void) +{ + odp_queue_param_t param; + const char *name; + int i; + int num = 3; + odp_queue_t queue[num]; + + name = "plain_queue"; + odp_queue_param_init(¶m); + param.type = ODP_QUEUE_TYPE_PLAIN; + + queue[0] = odp_queue_create(name, ¶m); + + if (queue[0] == ODP_QUEUE_INVALID) { + ODPH_ERR("Queue create failed: %s\n", name); + return -1; + } + + printf("\n"); + odp_queue_print(queue[0]); + + name = "parallel_sched_queue"; + odp_queue_param_init(¶m); + param.type = ODP_QUEUE_TYPE_SCHED; + + queue[1] = odp_queue_create(name, ¶m); + + if (queue[1] == ODP_QUEUE_INVALID) { + ODPH_ERR("Queue create failed: %s\n", name); + return -1; + } + + printf("\n"); + odp_queue_print(queue[1]); + + name = "atomic_sched_queue"; + param.sched.sync = ODP_SCHED_SYNC_ATOMIC; + param.sched.prio = odp_schedule_max_prio(); + + queue[2] = odp_queue_create(name, ¶m); + + if (queue[2] == ODP_QUEUE_INVALID) { + ODPH_ERR("Queue create failed: %s\n", name); + return -1; + } + + printf("\n"); + odp_queue_print(queue[2]); + + printf("\n"); + odp_queue_print_all(); + + printf("\n"); + odp_schedule_print(); + + for (i = 0; i < num; i++) { + if (odp_queue_destroy(queue[i])) { + ODPH_ERR("Queue destroy failed: %i\n", i); + return -1; + } + } + + return 0; +} + +static int pktio_debug(test_global_t *global) +{ + odp_pool_t pool; + odp_pool_param_t pool_param; + odp_pktio_t pktio; + odp_pktio_link_info_t info; + uint8_t mac[ODPH_ETHADDR_LEN]; + int pkt_len = 100; + + odp_pool_param_init(&pool_param); + pool_param.type = ODP_POOL_PACKET; + pool_param.pkt.num = 10; + pool_param.pkt.len = pkt_len; + + pool = odp_pool_create("debug_pktio_pool", &pool_param); + + if (pool == ODP_POOL_INVALID) { + ODPH_ERR("Pool create failed\n"); + return -1; + } + + pktio = odp_pktio_open(global->pktio_name, pool, NULL); + + if (pktio == ODP_PKTIO_INVALID) { + ODPH_ERR("Pktio open failed\n"); + return -1; + } + + /* Start interface with default config */ + if (odp_pktin_queue_config(pktio, NULL)) { + ODPH_ERR("Packet input queue config failed\n"); + return -1; + } + + if (odp_pktout_queue_config(pktio, NULL)) { + ODPH_ERR("Packet output queue config failed\n"); + return -1; + } + + if (odp_pktio_start(pktio)) { + ODPH_ERR("Pktio start failed\n"); + return -1; + } + + printf("\nWaiting link up"); + + /* Wait max 5 seconds for link up */ + for (int i = 0; i < 25; i++) { + if (odp_pktio_link_status(pktio) == ODP_PKTIO_LINK_STATUS_UP) + break; + + odp_time_wait_ns(200 * ODP_TIME_MSEC_IN_NS); + printf("."); + fflush(NULL); + } + + printf("\n\n"); + + printf("Packet IO\n---------\n"); + printf(" index: %i\n", odp_pktio_index(pktio)); + printf(" handle: 0x%" PRIx64 "\n", odp_pktio_to_u64(pktio)); + + if (odp_pktio_mac_addr(pktio, mac, ODPH_ETHADDR_LEN) == ODPH_ETHADDR_LEN) { + printf(" mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + } + + printf(" input maxlen: %u\n", odp_pktin_maxlen(pktio)); + printf(" output maxlen: %u\n", odp_pktout_maxlen(pktio)); + printf(" promisc mode: %i\n", odp_pktio_promisc_mode(pktio)); + printf(" timestamp res: %" PRIu64 " Hz\n\n", odp_pktio_ts_res(pktio)); + + if (odp_pktio_link_info(pktio, &info) == 0) { + printf("Link info\n---------\n"); + printf(" auto neg: %i\n", info.autoneg); + printf(" duplex: %i\n", info.duplex); + printf(" media: %s\n", info.media); + printf(" pause_rx: %i\n", info.pause_rx); + printf(" pause_tx: %i\n", info.pause_tx); + printf(" speed: %u Mbit/s\n", info.speed); + printf(" status: %i\n", info.status); + } + + printf("\n"); + odp_pktio_print(pktio); + + printf("\n"); + odp_pktio_extra_stats_print(pktio); + + if (odp_pktio_stop(pktio)) { + ODPH_ERR("Pktio stop failed\n"); + return -1; + } + + if (odp_pktio_close(pktio)) { + ODPH_ERR("Pktio close failed\n"); + return -1; + } + + if (odp_pool_destroy(pool)) { + ODPH_ERR("Pool destroy failed\n"); + return -1; + } + + return 0; +} + +static int ipsec_debug(void) +{ + printf("\n"); + odp_ipsec_print(); + + return 0; +} + +static int timer_debug(void) +{ + odp_pool_t pool; + odp_pool_param_t pool_param; + odp_timeout_t timeout; + odp_timer_res_capability_t timer_res_capa; + odp_timer_capability_t timer_capa; + odp_timer_pool_t timer_pool; + odp_timer_pool_param_t timer_param; + odp_timer_start_t start_param; + odp_timer_t timer; + odp_queue_t queue; + odp_queue_param_t queue_param; + odp_event_t event; + uint64_t tick; + uint64_t max_tmo = ODP_TIME_SEC_IN_NS; + uint64_t res = 100 * ODP_TIME_MSEC_IN_NS; + int started = 0; + + odp_pool_param_init(&pool_param); + pool_param.type = ODP_POOL_TIMEOUT; + pool_param.tmo.num = 10; + + pool = odp_pool_create("debug_timer", &pool_param); + + if (pool == ODP_POOL_INVALID) { + ODPH_ERR("Pool create failed\n"); + return -1; + } + + timeout = odp_timeout_alloc(pool); + if (timeout == ODP_TIMEOUT_INVALID) { + ODPH_ERR("Timeout alloc failed\n"); + return -1; + } + + if (odp_timer_capability(ODP_CLOCK_DEFAULT, &timer_capa)) { + ODPH_ERR("Timer capa failed\n"); + return -1; + } + + if (timer_capa.max_tmo.max_tmo < max_tmo) + max_tmo = timer_capa.max_tmo.max_tmo; + + memset(&timer_res_capa, 0, sizeof(odp_timer_res_capability_t)); + timer_res_capa.max_tmo = max_tmo; + if (odp_timer_res_capability(ODP_CLOCK_DEFAULT, &timer_res_capa)) { + ODPH_ERR("Timer resolution capability failed\n"); + return -1; + } + + if (timer_res_capa.res_ns > res) + res = timer_res_capa.res_ns; + + odp_timer_pool_param_init(&timer_param); + timer_param.res_ns = res; + timer_param.min_tmo = max_tmo / 10; + timer_param.max_tmo = max_tmo; + timer_param.num_timers = 10; + timer_param.clk_src = ODP_CLOCK_DEFAULT; + + timer_pool = odp_timer_pool_create("debug_timer", &timer_param); + + if (timer_pool == ODP_TIMER_POOL_INVALID) { + ODPH_ERR("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_queue_param_init(&queue_param); + if (timer_capa.queue_type_sched) + queue_param.type = ODP_QUEUE_TYPE_SCHED; + + queue = odp_queue_create("debug_timer", &queue_param); + if (queue == ODP_QUEUE_INVALID) { + ODPH_ERR("Queue create failed.\n"); + return -1; + } + + printf("\n"); + odp_timer_pool_print(timer_pool); + + tick = odp_timer_ns_to_tick(timer_pool, max_tmo / 2); + + timer = odp_timer_alloc(timer_pool, queue, (void *)(uintptr_t)0xdeadbeef); + + printf("\n"); + odp_timeout_print(timeout); + + event = odp_timeout_to_event(timeout); + + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = tick; + start_param.tmo_ev = event; + + if (odp_timer_start(timer, &start_param) == ODP_TIMER_SUCCESS) + started = 1; + else + ODPH_ERR("Timer start failed.\n"); + + printf("\n"); + odp_timer_print(timer); + + if (started && odp_timer_cancel(timer, &event) != ODP_TIMER_SUCCESS) { + ODPH_ERR("Timer cancel failed\n"); + return -1; + } else { + timeout = odp_timeout_from_event(event); + + printf("\n"); + odp_timeout_print(timeout); + + odp_timeout_free(timeout); + } + + if (odp_timer_free(timer)) { + ODPH_ERR("Timer free failed\n"); + return -1; + } + + odp_timer_pool_destroy(timer_pool); + + if (odp_queue_destroy(queue)) { + ODPH_ERR("Queue destroy failed\n"); + return -1; + } + + if (odp_pool_destroy(pool)) { + ODPH_ERR("Pool destroy failed\n"); + return -1; + } + + return 0; +} + +static int stash_debug(void) +{ + odp_stash_param_t param; + odp_stash_t stash; + uint32_t val = 0xdeadbeef; + + odp_stash_param_init(¶m); + param.num_obj = 10; + param.obj_size = 4; + + stash = odp_stash_create("debug_stash", ¶m); + + if (stash == ODP_STASH_INVALID) { + ODPH_ERR("Stash create failed\n"); + return -1; + } + + if (odp_stash_put_u32(stash, &val, 1) != 1) { + ODPH_ERR("Stash put failed\n"); + return -1; + } + + printf("\n"); + odp_stash_print(stash); + + if (odp_stash_get_u32(stash, &val, 1) != 1) { + ODPH_ERR("Stash get failed\n"); + return -1; + } + + if (odp_stash_destroy(stash)) { + ODPH_ERR("Stash destroy failed\n"); + return -1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + odp_instance_t inst; + test_global_t *global = &test_global; + + printf("ODP debug example\n\n"); + memset(global, 0, sizeof(test_global_t)); + + if (argc < 2) { + /* If not arguments, run all test cases */ + global->system = 1; + global->shm = 1; + global->pool = 1; + global->queue = 1; + global->pktio = 1; + global->ipsec = 1; + global->timer = 1; + global->stash = 1; + strcpy(global->pktio_name, "loop"); + } else { + if (parse_options(argc, argv, global)) + exit(EXIT_FAILURE); + } + + if (odp_init_global(&inst, NULL, NULL)) { + ODPH_ERR("Global init failed.\n"); + exit(EXIT_FAILURE); + } + + if (odp_init_local(inst, ODP_THREAD_CONTROL)) { + ODPH_ERR("Local init failed.\n"); + exit(EXIT_FAILURE); + } + + /* Configure scheduler before creating any scheduled queues */ + if (odp_schedule_config(NULL)) { + ODPH_ERR("Schedule config failed\n"); + exit(EXIT_FAILURE); + } + + if (global->system) { + printf("\n"); + odp_sys_info_print(); + + printf("\n"); + odp_sys_config_print(); + } + + if (global->shm && shm_debug()) { + ODPH_ERR("SHM debug failed.\n"); + exit(EXIT_FAILURE); + } + + if (global->pool && pool_debug()) { + ODPH_ERR("Pool debug failed.\n"); + exit(EXIT_FAILURE); + } + + if (global->queue && queue_debug()) { + ODPH_ERR("Queue debug failed.\n"); + exit(EXIT_FAILURE); + } + + if (global->pktio && pktio_debug(global)) { + ODPH_ERR("Packet debug failed.\n"); + exit(EXIT_FAILURE); + } + + if (global->ipsec && ipsec_debug()) { + ODPH_ERR("IPSEC debug failed.\n"); + exit(EXIT_FAILURE); + } + + if (global->timer && timer_debug()) { + ODPH_ERR("Timer debug failed.\n"); + exit(EXIT_FAILURE); + } + + if (global->stash && stash_debug()) { + ODPH_ERR("Stash debug failed.\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_local()) { + ODPH_ERR("Local term failed.\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_global(inst)) { + ODPH_ERR("Global term failed.\n"); + exit(EXIT_FAILURE); + } + + return 0; +} |