diff options
Diffstat (limited to 'test/performance/odp_bench_packet.c')
-rw-r--r-- | test/performance/odp_bench_packet.c | 1777 |
1 files changed, 1777 insertions, 0 deletions
diff --git a/test/performance/odp_bench_packet.c b/test/performance/odp_bench_packet.c new file mode 100644 index 000000000..a8494bd28 --- /dev/null +++ b/test/performance/odp_bench_packet.c @@ -0,0 +1,1777 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2017-2018 Linaro Limited + * Copyright (c) 2022-2023 Nokia + */ + +/** + * @example odp_bench_packet.c + * + * Microbenchmark application for packet API functions + * + * @cond _ODP_HIDE_FROM_DOXYGEN_ + */ + +#include <stdlib.h> +#include <getopt.h> +#include <unistd.h> +#include <errno.h> +#include <inttypes.h> +#include <signal.h> + +#include <test_packet_ipv4.h> +#include <test_packet_ipv6.h> + +#include <odp_api.h> +#include <odp/helper/odph_api.h> + +#include "bench_common.h" + +/** Packet user area size in bytes */ +#define PKT_POOL_UAREA_SIZE 8 + +/** Minimum test packet size */ +#define TEST_MIN_PKT_SIZE 64 + +/** Maximum test packet size */ +#define TEST_MAX_PKT_SIZE 2048 + +/** Number of API function calls per test case */ +#define TEST_REPEAT_COUNT 1000 + +/** Number of rounds per test case */ +#define TEST_ROUNDS 2u + +/** Maximum burst size for *_multi operations */ +#define TEST_MAX_BURST 64 + +/** Offset of the contiguous area */ +#define TEST_ALIGN_OFFSET 16 + +/** Length of the contiguous area */ +#define TEST_ALIGN_LEN 32 + +/** Minimum byte alignment of contiguous area */ +#define TEST_ALIGN 32 + +/** Test packet offsets */ +#define TEST_L2_OFFSET 0 +#define TEST_L3_OFFSET (TEST_MIN_PKT_SIZE / 4) +#define TEST_L4_OFFSET (TEST_MIN_PKT_SIZE / 2) + +/** Default burst size for *_multi operations */ +#define TEST_DEF_BURST 8 + +/** 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)) + +#define BENCH_INFO(run_fn, init_fn, term_fn, alt_name) \ + {.name = #run_fn, .run = run_fn, .init = init_fn, .term = term_fn, .desc = alt_name} + +ODP_STATIC_ASSERT((TEST_ALIGN_OFFSET + TEST_ALIGN_LEN) <= TEST_MIN_PKT_SIZE, + "Invalid_alignment"); + +/** Test packet sizes */ +const uint32_t test_packet_len[] = {TEST_MIN_PKT_SIZE, 128, 256, 512, + 1024, 1518, TEST_MAX_PKT_SIZE}; + +/** + * Parsed command line arguments + */ +typedef struct { + int bench_idx; /** Benchmark index to run indefinitely */ + int burst_size; /** Burst size for *_multi operations */ + int cache_size; /** Pool cache size */ + int time; /** Measure time vs. CPU cycles */ + uint32_t rounds; /** Rounds per test case */ +} appl_args_t; + +/** + * Grouping of all global data + */ +typedef struct { + /** Application (parsed) arguments */ + appl_args_t appl; + /** Common benchmark suite data */ + bench_suite_t suite; + /** Packet pool */ + odp_pool_t pool; + struct { + /** Test packet length */ + uint32_t len; + /** Minimum test packet headroom */ + uint32_t headroom; + /** Minimum test packet tailroom */ + uint32_t tailroom; + /** Minimum test packet segment length */ + uint32_t seg_len; + } pkt; + /** Array for storing test packets */ + odp_packet_t pkt_tbl[TEST_REPEAT_COUNT * TEST_MAX_BURST]; + /** Array for storing test packets */ + odp_packet_t pkt2_tbl[TEST_REPEAT_COUNT]; + /** Array for storing test event */ + odp_event_t event_tbl[TEST_REPEAT_COUNT * TEST_MAX_BURST]; + /** Array for storing test pointers */ + void *ptr_tbl[TEST_REPEAT_COUNT]; + /** Array for storing test segments */ + odp_packet_seg_t seg_tbl[TEST_REPEAT_COUNT]; + /** Array for storing test outputs */ + uint32_t output_tbl[TEST_REPEAT_COUNT]; + /** Array for storing test pool handles */ + odp_pool_t pool_tbl[TEST_REPEAT_COUNT]; + /** Array for storing test pktio handles */ + odp_pktio_t pktio_tbl[TEST_REPEAT_COUNT]; + /** Array for storing test timestamps */ + odp_time_t ts_tbl[TEST_REPEAT_COUNT]; + /** Array for storing test data */ + uint8_t data_tbl[TEST_REPEAT_COUNT][TEST_MAX_PKT_SIZE]; +} args_t; + +/** Global pointer to args */ +static args_t *gbl_args; + +static void sig_handler(int signo ODP_UNUSED) +{ + if (gbl_args == NULL) + return; + odp_atomic_store_u32(&gbl_args->suite.exit_worker, 1); +} + +/** + * Master function for running the microbenchmarks + */ +static int run_benchmarks(void *arg) +{ + int i; + args_t *args = arg; + bench_suite_t *suite = &args->suite; + int num_sizes = ODPH_ARRAY_SIZE(test_packet_len); + double results[num_sizes][suite->num_bench]; + + memset(results, 0, sizeof(results)); + + for (i = 0; i < num_sizes; i++) { + printf("Packet length: %6d bytes", test_packet_len[i]); + + gbl_args->pkt.len = test_packet_len[i]; + + suite->result = results[i]; + + bench_run(suite); + } + + printf("\n%-35s", "Benchmark / packet_size [B]"); + for (i = 0; i < num_sizes; i++) + printf("%8.1d ", test_packet_len[i]); + + printf("\n---------------------------------"); + for (i = 0; i < num_sizes; i++) + printf("----------"); + + for (i = 0; i < suite->num_bench; i++) { + printf("\n[%02d] odp_%-26s", i + 1, suite->bench[i].desc != NULL ? + suite->bench[i].desc : suite->bench[i].name); + + for (int j = 0; j < num_sizes; j++) + printf("%8.1f ", results[j][i]); + } + printf("\n\n"); + return 0; +} + +static void allocate_test_packets(uint32_t len, odp_packet_t pkt[], int num) +{ + int pkts = 0; + + while (pkts < num) { + int ret; + + ret = odp_packet_alloc_multi(gbl_args->pool, len, &pkt[pkts], + num - pkts); + if (ret < 0) + ODPH_ABORT("Allocating test packets failed\n"); + + pkts += ret; + } +} + +static void alloc_packets_half(void) +{ + allocate_test_packets(gbl_args->pkt.len / 2, gbl_args->pkt_tbl, + TEST_REPEAT_COUNT); +} + +static void alloc_packets_multi(void) +{ + allocate_test_packets(gbl_args->pkt.len, gbl_args->pkt_tbl, + TEST_REPEAT_COUNT * gbl_args->appl.burst_size); +} + +static void alloc_concat_packets(void) +{ + allocate_test_packets(gbl_args->pkt.len / 2, gbl_args->pkt_tbl, + TEST_REPEAT_COUNT); + allocate_test_packets(gbl_args->pkt.len / 2, gbl_args->pkt2_tbl, + TEST_REPEAT_COUNT); +} + +static void alloc_ref_packets(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *ref_tbl = gbl_args->pkt2_tbl; + + allocate_test_packets(gbl_args->pkt.len, pkt_tbl, TEST_REPEAT_COUNT); + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + ref_tbl[i] = odp_packet_ref(pkt_tbl[i], TEST_MIN_PKT_SIZE / 2); + if (ref_tbl[i] == ODP_PACKET_INVALID) + ODPH_ABORT("Allocating packet reference failed\n"); + } +} + +static void alloc_packets_twice(void) +{ + allocate_test_packets(gbl_args->pkt.len, gbl_args->pkt_tbl, + TEST_REPEAT_COUNT); + allocate_test_packets(gbl_args->pkt.len, gbl_args->pkt2_tbl, + TEST_REPEAT_COUNT); +} + +static void alloc_parse_packets(const void *pkt_data, uint32_t len) +{ + int i; + + allocate_test_packets(len, gbl_args->pkt_tbl, TEST_REPEAT_COUNT); + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + if (odp_packet_copy_from_mem(gbl_args->pkt_tbl[i], 0, len, + pkt_data)) + ODPH_ABORT("Copying test packet failed\n"); + } +} + +static void alloc_parse_packets_ipv4_tcp(void) +{ + alloc_parse_packets(test_packet_ipv4_tcp, sizeof(test_packet_ipv4_tcp)); +} + +static void alloc_parse_packets_ipv4_udp(void) +{ + alloc_parse_packets(test_packet_ipv4_udp, sizeof(test_packet_ipv4_udp)); +} + +static void alloc_parse_packets_ipv6_tcp(void) +{ + alloc_parse_packets(test_packet_ipv6_tcp, sizeof(test_packet_ipv6_tcp)); +} + +static void alloc_parse_packets_ipv6_udp(void) +{ + alloc_parse_packets(test_packet_ipv6_udp, sizeof(test_packet_ipv6_udp)); +} + +static void alloc_parse_packets_multi(const void *pkt_data, uint32_t len) +{ + int i; + + allocate_test_packets(len, gbl_args->pkt_tbl, + TEST_REPEAT_COUNT * gbl_args->appl.burst_size); + + for (i = 0; i < TEST_REPEAT_COUNT * gbl_args->appl.burst_size; i++) { + if (odp_packet_copy_from_mem(gbl_args->pkt_tbl[i], 0, len, + pkt_data)) + ODPH_ABORT("Copying test packet failed\n"); + } +} + +static void alloc_parse_packets_multi_ipv4_tcp(void) +{ + alloc_parse_packets_multi(test_packet_ipv4_tcp, + sizeof(test_packet_ipv4_tcp)); +} + +static void alloc_parse_packets_multi_ipv4_udp(void) +{ + alloc_parse_packets_multi(test_packet_ipv4_udp, + sizeof(test_packet_ipv4_udp)); +} + +static void alloc_parse_packets_multi_ipv6_tcp(void) +{ + alloc_parse_packets_multi(test_packet_ipv6_tcp, + sizeof(test_packet_ipv6_tcp)); +} + +static void alloc_parse_packets_multi_ipv6_udp(void) +{ + alloc_parse_packets_multi(test_packet_ipv6_udp, + sizeof(test_packet_ipv6_udp)); +} + +static void create_packets(void) +{ + int i; + uint32_t headroom, tailroom, seg_len; + uint32_t min_headroom = 0; + uint32_t min_tailroom = 0; + uint32_t min_seg_len = 0; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_seg_t *seg_tbl = gbl_args->seg_tbl; + + allocate_test_packets(gbl_args->pkt.len, gbl_args->pkt_tbl, + TEST_REPEAT_COUNT); + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + headroom = odp_packet_headroom(pkt_tbl[i]); + tailroom = odp_packet_tailroom(pkt_tbl[i]); + seg_len = odp_packet_seg_len(pkt_tbl[i]); + + seg_tbl[i] = odp_packet_first_seg(pkt_tbl[i]); + + if (i == 0) { + min_headroom = headroom; + min_tailroom = tailroom; + min_seg_len = seg_len; + } else { + if (headroom < min_headroom) + min_headroom = headroom; + if (tailroom < min_tailroom) + min_tailroom = tailroom; + if (seg_len < min_seg_len) + min_seg_len = seg_len; + } + + if (odp_packet_l2_offset_set(pkt_tbl[i], TEST_L2_OFFSET) || + odp_packet_l3_offset_set(pkt_tbl[i], TEST_L3_OFFSET) || + odp_packet_l4_offset_set(pkt_tbl[i], TEST_L4_OFFSET)) + ODPH_ABORT("Setting test packet offsets failed\n"); + + odp_packet_flow_hash_set(pkt_tbl[i], i); + odp_packet_ts_set(pkt_tbl[i], odp_time_local()); + } + gbl_args->pkt.headroom = min_headroom; + gbl_args->pkt.tailroom = min_tailroom; + gbl_args->pkt.seg_len = min_seg_len; +} + +static void create_events(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + create_packets(); + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->event_tbl[i] = odp_packet_to_event(pkt_tbl[i]); +} + +static void create_events_multi(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + allocate_test_packets(gbl_args->pkt.len, gbl_args->pkt_tbl, + TEST_REPEAT_COUNT * gbl_args->appl.burst_size); + + for (i = 0; i < TEST_REPEAT_COUNT * gbl_args->appl.burst_size; i++) + gbl_args->event_tbl[i] = odp_packet_to_event(pkt_tbl[i]); +} + +static void free_packets(void) +{ + odp_packet_free_multi(gbl_args->pkt_tbl, TEST_REPEAT_COUNT); +} + +static void free_packets_multi(void) +{ + odp_packet_free_multi(gbl_args->pkt_tbl, + TEST_REPEAT_COUNT * gbl_args->appl.burst_size); +} + +static void free_packets_twice(void) +{ + odp_packet_free_multi(gbl_args->pkt_tbl, TEST_REPEAT_COUNT); + odp_packet_free_multi(gbl_args->pkt2_tbl, TEST_REPEAT_COUNT); +} + +static int packet_alloc(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + odp_packet_t pkt; + + pkt = odp_packet_alloc(gbl_args->pool, gbl_args->pkt.len); + + gbl_args->pkt_tbl[i] = pkt; + } + + return i; +} + +static int packet_alloc_multi(void) +{ + int i; + int pkts = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + pkts += odp_packet_alloc_multi(gbl_args->pool, + gbl_args->pkt.len, + &gbl_args->pkt_tbl[pkts], + gbl_args->appl.burst_size); + return pkts; +} + +static int packet_free(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + odp_packet_free(gbl_args->pkt_tbl[i]); + + return i; +} + +static int packet_free_multi(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + int pkt_idx = i * gbl_args->appl.burst_size; + + odp_packet_free_multi(&gbl_args->pkt_tbl[pkt_idx], + gbl_args->appl.burst_size); + } + return i; +} + +static int packet_free_sp(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + int pkt_idx = i * gbl_args->appl.burst_size; + + odp_packet_free_sp(&gbl_args->pkt_tbl[pkt_idx], + gbl_args->appl.burst_size); + } + return i; +} + +static int packet_alloc_free(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + odp_packet_t pkt; + + pkt = odp_packet_alloc(gbl_args->pool, gbl_args->pkt.len); + + odp_packet_free(pkt); + } + return i; +} + +static int packet_alloc_free_multi(void) +{ + int i; + int pkts; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + pkts = odp_packet_alloc_multi(gbl_args->pool, gbl_args->pkt.len, + gbl_args->pkt_tbl, + gbl_args->appl.burst_size); + + if (pkts < 0) + ODPH_ABORT("Packet alloc failed\n"); + + odp_packet_free_multi(gbl_args->pkt_tbl, pkts); + } + return i; +} + +static int packet_reset(void) +{ + int i; + int ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_reset(gbl_args->pkt_tbl[i], + gbl_args->pkt.len); + return !ret; +} + +static int packet_from_event(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + pkt_tbl[i] = odp_packet_from_event(gbl_args->event_tbl[i]); + + return i; +} + +static int packet_from_event_multi(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + int idx = i * gbl_args->appl.burst_size; + + odp_packet_from_event_multi(&gbl_args->pkt_tbl[idx], + &gbl_args->event_tbl[idx], + gbl_args->appl.burst_size); + } + return i; +} + +static int packet_to_event(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->event_tbl[i] = odp_packet_to_event(pkt_tbl[i]); + + return i; +} + +static int packet_to_event_multi(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + int idx = i * gbl_args->appl.burst_size; + + odp_packet_to_event_multi(&gbl_args->pkt_tbl[idx], + &gbl_args->event_tbl[idx], + gbl_args->appl.burst_size); + } + return i; +} + +static int packet_head(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_head(gbl_args->pkt_tbl[i]); + + return i; +} + +static int packet_buf_len(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_buf_len(gbl_args->pkt_tbl[i]); + + return ret; +} + +static int packet_data(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_data(gbl_args->pkt_tbl[i]); + + return i; +} + +static int packet_data_seg_len(void) +{ + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + uint32_t *output_tbl = gbl_args->output_tbl; + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_data_seg_len(pkt_tbl[i], + &output_tbl[i]); + return i; +} + +static int packet_seg_len(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_seg_len(gbl_args->pkt_tbl[i]); + + return ret; +} + +static int packet_len(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_len(gbl_args->pkt_tbl[i]); + + return ret; +} + +static int packet_headroom(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_headroom(gbl_args->pkt_tbl[i]); + + return i + ret; +} + +static int packet_tailroom(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_tailroom(gbl_args->pkt_tbl[i]); + + return i + ret; +} + +static int packet_tail(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_tail(gbl_args->pkt_tbl[i]); + + return i; +} + +static int packet_offset(void) +{ + int i; + uint32_t offset = gbl_args->pkt.len / 2; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_offset(gbl_args->pkt_tbl[i], + offset, NULL, NULL); + return i; +} + +static int packet_prefetch(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + odp_packet_prefetch(gbl_args->pkt_tbl[i], 0, gbl_args->pkt.len); + + return i; +} + +static int packet_push_head(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + uint32_t hroom = gbl_args->pkt.headroom; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_push_head(pkt_tbl[i], hroom); + + return i; +} + +static int packet_pull_head(void) +{ + int i; + uint32_t len = gbl_args->pkt.seg_len - 1; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_pull_head(pkt_tbl[i], len); + + return i; +} + +static int packet_push_tail(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + uint32_t troom = gbl_args->pkt.tailroom; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_push_tail(pkt_tbl[i], troom); + + return i; +} + +static int packet_pull_tail(void) +{ + int i; + uint32_t len = gbl_args->pkt.seg_len - 1; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_pull_tail(pkt_tbl[i], len); + + return i; +} + +static int packet_extend_head(void) +{ + int i; + int ret = 0; + uint32_t len = gbl_args->pkt.len / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + void **ptr_tbl = gbl_args->ptr_tbl; + uint32_t *data_tbl = gbl_args->output_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_extend_head(&pkt_tbl[i], len, &ptr_tbl[i], + &data_tbl[i]); + return ret >= 0; +} + +static int packet_trunc_head(void) +{ + int i; + int ret = 0; + uint32_t len = gbl_args->pkt.len / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + void **ptr_tbl = gbl_args->ptr_tbl; + uint32_t *data_tbl = gbl_args->output_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_trunc_head(&pkt_tbl[i], len, &ptr_tbl[i], + &data_tbl[i]); + return ret >= 0; +} + +static int packet_extend_tail(void) +{ + int i; + int ret = 0; + uint32_t len = gbl_args->pkt.len / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + void **ptr_tbl = gbl_args->ptr_tbl; + uint32_t *data_tbl = gbl_args->output_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_extend_tail(&pkt_tbl[i], len, &ptr_tbl[i], + &data_tbl[i]); + return ret >= 0; +} + +static int packet_trunc_tail(void) +{ + int i; + int ret = 0; + uint32_t len = gbl_args->pkt.len / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + void **ptr_tbl = gbl_args->ptr_tbl; + uint32_t *data_tbl = gbl_args->output_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_trunc_tail(&pkt_tbl[i], len, &ptr_tbl[i], + &data_tbl[i]); + return ret >= 0; +} + +static int packet_add_data(void) +{ + int i; + int ret = 0; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + uint32_t len = gbl_args->pkt.len / 2; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_add_data(&pkt_tbl[i], 0, len); + + return ret >= 0; +} + +static int packet_rem_data(void) +{ + int i; + int ret = 0; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + uint32_t len = gbl_args->pkt.len / 2; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_rem_data(&pkt_tbl[i], 0, len); + + return ret >= 0; +} + +static int packet_align(void) +{ + int i; + int ret = 0; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_align(&pkt_tbl[i], TEST_ALIGN_OFFSET, + TEST_ALIGN_LEN, TEST_ALIGN); + return ret >= 0; +} + +static int packet_is_segmented(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_is_segmented(gbl_args->pkt_tbl[i]); + + return (ret == 0) ? 1 : ret; +} + +static int packet_num_segs(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_num_segs(gbl_args->pkt_tbl[i]); + + return ret; +} + +static int packet_first_seg(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->seg_tbl[i] = odp_packet_first_seg(pkt_tbl[i]); + + return i; +} + +static int packet_last_seg(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->seg_tbl[i] = odp_packet_last_seg(pkt_tbl[i]); + + return i; +} + +static int packet_next_seg(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_seg_t *seg_tbl = gbl_args->seg_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->seg_tbl[i] = odp_packet_next_seg(pkt_tbl[i], + seg_tbl[i]); + return i; +} + +static int packet_seg_data(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_seg_t *seg_tbl = gbl_args->seg_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_seg_data(pkt_tbl[i], + seg_tbl[i]); + return i; +} + +static int packet_seg_data_len(void) +{ + int i; + uint32_t ret = 0; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_seg_t *seg_tbl = gbl_args->seg_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_seg_data_len(pkt_tbl[i], seg_tbl[i]); + + return ret; +} + +static int packet_concat(void) +{ + int i; + int ret = 0; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *frag_tbl = gbl_args->pkt2_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_concat(&pkt_tbl[i], frag_tbl[i]); + + return ret >= 0; +} + +static int packet_split(void) +{ + int i; + int ret = 0; + uint32_t head_len; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *frag_tbl = gbl_args->pkt2_tbl; + + head_len = odp_packet_len(pkt_tbl[0]) / 2; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_split(&pkt_tbl[i], head_len, &frag_tbl[i]); + + return ret >= 0; +} + +static int packet_copy(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *cpy_tbl = gbl_args->pkt2_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + cpy_tbl[i] = odp_packet_copy(pkt_tbl[i], gbl_args->pool); + + return i; +} + +static int packet_copy_part(void) +{ + int i; + uint32_t len = gbl_args->pkt.len / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *cpy_tbl = gbl_args->pkt2_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + cpy_tbl[i] = odp_packet_copy_part(pkt_tbl[i], 0, len, + gbl_args->pool); + return i; +} + +static int packet_copy_to_mem(void) +{ + int i; + uint32_t ret = 0; + uint32_t len = gbl_args->pkt.len; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_copy_to_mem(pkt_tbl[i], 0, len, + gbl_args->data_tbl[i]); + return !ret; +} + +static int packet_copy_from_mem(void) +{ + int i; + uint32_t ret = 0; + uint32_t len = gbl_args->pkt.len; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_copy_from_mem(pkt_tbl[i], 0, len, + gbl_args->data_tbl[i]); + return !ret; +} + +static int packet_copy_from_pkt(void) +{ + int i; + uint32_t ret = 0; + uint32_t len = gbl_args->pkt.len; + odp_packet_t *dst_tbl = gbl_args->pkt_tbl; + odp_packet_t *src_tbl = gbl_args->pkt2_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_copy_from_pkt(dst_tbl[i], 0, src_tbl[i], 0, + len); + return !ret; +} + +static int packet_copy_data(void) +{ + int i; + uint32_t ret = 0; + uint32_t len = gbl_args->pkt.len / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_copy_data(pkt_tbl[i], 0, len, len); + + return !ret; +} + +static int packet_move_data(void) +{ + int i; + uint32_t ret = 0; + uint32_t len = gbl_args->pkt.len / 2; + uint32_t offset = len / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_move_data(pkt_tbl[i], offset, len, len); + + return !ret; +} + +static int packet_pool(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->pool_tbl[i] = odp_packet_pool(gbl_args->pkt_tbl[i]); + + return i; +} + +static int packet_input(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->pktio_tbl[i] = odp_packet_input(gbl_args->pkt_tbl[i]); + + return i; +} + +static int packet_input_index(void) +{ + int i; + int ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_input_index(gbl_args->pkt_tbl[i]); + + return (ret == 0) ? 1 : ret; +} + +static int packet_user_ptr(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_user_ptr(pkt_tbl[i]); + + return i; +} + +static int packet_user_ptr_set(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + odp_packet_user_ptr_set(gbl_args->pkt_tbl[i], + gbl_args->ptr_tbl[i]); + + return i; +} + +static int packet_user_area(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_user_area(pkt_tbl[i]); + + return i; +} + +static int packet_user_area_size(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_user_area_size(gbl_args->pkt_tbl[i]); + + return ret; +} + +static int packet_user_flag(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += !odp_packet_user_flag(gbl_args->pkt_tbl[i]); + + return ret; +} + +static int packet_user_flag_set(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + odp_packet_user_flag_set(gbl_args->pkt_tbl[i], 1); + + return i; +} + +static int packet_l2_ptr(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_l2_ptr(gbl_args->pkt_tbl[i], + NULL); + return i; +} + +static int packet_l2_offset(void) +{ + int i; + int ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_l2_offset(gbl_args->pkt_tbl[i]); + + return ret >= 0; +} + +static int packet_l2_offset_set(void) +{ + int i; + uint32_t ret = 0; + uint32_t offset = gbl_args->pkt.len / 2; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_l2_offset_set(gbl_args->pkt_tbl[i], offset); + + return !ret; +} + +static int packet_l3_ptr(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_l3_ptr(gbl_args->pkt_tbl[i], + NULL); + return i; +} + +static int packet_l3_offset(void) +{ + int i; + int ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_l3_offset(gbl_args->pkt_tbl[i]); + + return ret >= 0; +} + +static int packet_l3_offset_set(void) +{ + int i; + uint32_t ret = 0; + uint32_t offset = gbl_args->pkt.len / 2; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_l3_offset_set(gbl_args->pkt_tbl[i], offset); + + return !ret; +} + +static int packet_l4_ptr(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ptr_tbl[i] = odp_packet_l4_ptr(gbl_args->pkt_tbl[i], + NULL); + return i; +} + +static int packet_l4_offset(void) +{ + int i; + int ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_l4_offset(gbl_args->pkt_tbl[i]); + + return ret >= 0; +} + +static int packet_l4_offset_set(void) +{ + int i; + uint32_t ret = 0; + uint32_t offset = gbl_args->pkt.len / 2; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_l4_offset_set(gbl_args->pkt_tbl[i], offset); + + return !ret; +} + +static int packet_flow_hash(void) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_flow_hash(gbl_args->pkt_tbl[i]); + + return ret; +} + +static int packet_flow_hash_set(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + odp_packet_flow_hash_set(gbl_args->pkt_tbl[i], i); + + return i; +} + +static int packet_ts(void) +{ + int i; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->ts_tbl[i] = odp_packet_ts(gbl_args->pkt_tbl[i]); + + return i; +} + +static int packet_ts_set(void) +{ + int i; + odp_time_t ts = odp_time_local(); + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + odp_packet_ts_set(gbl_args->pkt_tbl[i], ts); + + return i; +} + +static int packet_ref_static(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *ref_tbl = gbl_args->pkt2_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ref_tbl[i] = odp_packet_ref_static(pkt_tbl[i]); + + return i; +} + +static int packet_ref(void) +{ + int i; + uint32_t offset = TEST_MIN_PKT_SIZE / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *ref_tbl = gbl_args->pkt2_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ref_tbl[i] = odp_packet_ref(pkt_tbl[i], offset); + + return i; +} + +static int packet_ref_pkt(void) +{ + int i; + uint32_t offset = TEST_MIN_PKT_SIZE / 2; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + odp_packet_t *hdr_tbl = gbl_args->pkt2_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + hdr_tbl[i] = odp_packet_ref_pkt(pkt_tbl[i], offset, hdr_tbl[i]); + + return i; +} + +static int packet_has_ref(void) +{ + int i; + uint32_t ret = 0; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_has_ref(pkt_tbl[i]); + + return i + ret; +} + +static int packet_subtype(void) +{ + int i; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + gbl_args->output_tbl[i] = odp_packet_subtype(pkt_tbl[i]); + + return i; +} + +static int packet_parse(void) +{ + odp_packet_parse_param_t param; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + int ret = 0; + int i; + + memset(¶m, 0, sizeof(odp_packet_parse_param_t)); + param.proto = ODP_PROTO_ETH; + param.last_layer = ODP_PROTO_LAYER_ALL; + param.chksums.chksum.ipv4 = 1; + param.chksums.chksum.tcp = 1; + param.chksums.chksum.udp = 1; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) + ret += odp_packet_parse(pkt_tbl[i], 0, ¶m); + + return !ret; +} + +static int packet_parse_multi(void) +{ + int burst_size = gbl_args->appl.burst_size; + int ret = 0; + int i; + odp_packet_parse_param_t param; + odp_packet_t *pkt_tbl = gbl_args->pkt_tbl; + uint32_t offsets[burst_size]; + + memset(&offsets, 0, sizeof(offsets)); + + memset(¶m, 0, sizeof(odp_packet_parse_param_t)); + param.proto = ODP_PROTO_ETH; + param.last_layer = ODP_PROTO_LAYER_ALL; + param.chksums.chksum.ipv4 = 1; + param.chksums.chksum.tcp = 1; + param.chksums.chksum.udp = 1; + + for (i = 0; i < TEST_REPEAT_COUNT; i++) { + int idx = i * burst_size; + + ret += odp_packet_parse_multi(&pkt_tbl[idx], offsets, + burst_size, ¶m); + } + return (ret == TEST_REPEAT_COUNT * burst_size); +} + +/** + * Print usage information + */ +static void usage(char *progname) +{ + printf("\n" + "OpenDataPlane Packet function microbenchmark.\n" + "\n" + "Usage: %s OPTIONS\n" + " E.g. %s\n" + "\n" + "Optional OPTIONS:\n" + " -b, --burst <num> Test packet burst size.\n" + " -c, --cache_size <num> Pool cache size.\n" + " -i, --index <idx> Benchmark index to run indefinitely.\n" + " -r, --rounds <num> Run each test case 'num' times (default %u).\n" + " -t, --time <opt> Time measurement. 0: measure CPU cycles (default), 1: measure time\n" + " -h, --help Display help and exit.\n\n" + "\n", NO_PATH(progname), NO_PATH(progname), TEST_ROUNDS); +} + +/** + * 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; + static const struct option longopts[] = { + {"burst", required_argument, NULL, 'b'}, + {"cache_size", required_argument, NULL, 'c'}, + {"index", required_argument, NULL, 'i'}, + {"rounds", required_argument, NULL, 'r'}, + {"time", required_argument, NULL, 't'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + static const char *shortopts = "c:b:i:r:t:h"; + + appl_args->bench_idx = 0; /* Run all benchmarks */ + appl_args->burst_size = TEST_DEF_BURST; + appl_args->cache_size = -1; + appl_args->rounds = TEST_ROUNDS; + appl_args->time = 0; + + while (1) { + opt = getopt_long(argc, argv, shortopts, longopts, &long_index); + + if (opt == -1) + break; /* No more options */ + + switch (opt) { + case 'c': + appl_args->cache_size = atoi(optarg); + break; + case 'b': + appl_args->burst_size = atoi(optarg); + break; + case 'i': + appl_args->bench_idx = atoi(optarg); + break; + case 'r': + appl_args->rounds = atoi(optarg); + break; + case 't': + appl_args->time = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(EXIT_SUCCESS); + break; + default: + usage(argv[0]); + exit(EXIT_FAILURE); + } + } + + if (appl_args->burst_size < 1 || + appl_args->burst_size > TEST_MAX_BURST) { + printf("Invalid burst size (max %d)\n", TEST_MAX_BURST); + exit(EXIT_FAILURE); + } + + if (appl_args->rounds < 1) { + printf("Invalid number test rounds: %d\n", appl_args->rounds); + exit(EXIT_FAILURE); + } + + 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 ODP_UNUSED) +{ + odp_sys_info_print(); + + printf("Running ODP appl: \"%s\"\n" + "-----------------\n", progname); + fflush(NULL); +} + +/** + * Test functions + */ +bench_info_t test_suite[] = { + BENCH_INFO(packet_alloc, NULL, free_packets, NULL), + BENCH_INFO(packet_alloc_multi, NULL, free_packets_multi, NULL), + BENCH_INFO(packet_free, create_packets, NULL, NULL), + BENCH_INFO(packet_free_multi, alloc_packets_multi, NULL, NULL), + BENCH_INFO(packet_free_sp, alloc_packets_multi, NULL, NULL), + BENCH_INFO(packet_alloc_free, NULL, NULL, NULL), + BENCH_INFO(packet_alloc_free_multi, NULL, NULL, NULL), + BENCH_INFO(packet_reset, create_packets, free_packets, NULL), + BENCH_INFO(packet_from_event, create_events, free_packets, NULL), + BENCH_INFO(packet_from_event_multi, create_events_multi, free_packets_multi, NULL), + BENCH_INFO(packet_to_event, create_packets, free_packets, NULL), + BENCH_INFO(packet_to_event_multi, alloc_packets_multi, free_packets_multi, NULL), + BENCH_INFO(packet_head, create_packets, free_packets, NULL), + BENCH_INFO(packet_buf_len, create_packets, free_packets, NULL), + BENCH_INFO(packet_data, create_packets, free_packets, NULL), + BENCH_INFO(packet_data_seg_len, create_packets, free_packets, NULL), + BENCH_INFO(packet_seg_len, create_packets, free_packets, NULL), + BENCH_INFO(packet_len, create_packets, free_packets, NULL), + BENCH_INFO(packet_headroom, create_packets, free_packets, NULL), + BENCH_INFO(packet_tailroom, create_packets, free_packets, NULL), + BENCH_INFO(packet_tail, create_packets, free_packets, NULL), + BENCH_INFO(packet_offset, create_packets, free_packets, NULL), + BENCH_INFO(packet_prefetch, create_packets, free_packets, NULL), + BENCH_INFO(packet_push_head, create_packets, free_packets, NULL), + BENCH_INFO(packet_pull_head, create_packets, free_packets, NULL), + BENCH_INFO(packet_push_tail, create_packets, free_packets, NULL), + BENCH_INFO(packet_pull_tail, create_packets, free_packets, NULL), + BENCH_INFO(packet_extend_head, alloc_packets_half, free_packets, NULL), + BENCH_INFO(packet_trunc_head, create_packets, free_packets, NULL), + BENCH_INFO(packet_extend_tail, alloc_packets_half, free_packets, NULL), + BENCH_INFO(packet_trunc_tail, create_packets, free_packets, NULL), + BENCH_INFO(packet_add_data, alloc_packets_half, free_packets, NULL), + BENCH_INFO(packet_rem_data, create_packets, free_packets, NULL), + BENCH_INFO(packet_align, create_packets, free_packets, NULL), + BENCH_INFO(packet_is_segmented, create_packets, free_packets, NULL), + BENCH_INFO(packet_num_segs, create_packets, free_packets, NULL), + BENCH_INFO(packet_first_seg, create_packets, free_packets, NULL), + BENCH_INFO(packet_last_seg, create_packets, free_packets, NULL), + BENCH_INFO(packet_next_seg, create_packets, free_packets, NULL), + BENCH_INFO(packet_seg_data, create_packets, free_packets, NULL), + BENCH_INFO(packet_seg_data_len, create_packets, free_packets, NULL), + BENCH_INFO(packet_concat, alloc_concat_packets, free_packets, NULL), + BENCH_INFO(packet_split, create_packets, free_packets_twice, NULL), + BENCH_INFO(packet_copy, create_packets, free_packets_twice, NULL), + BENCH_INFO(packet_copy_part, create_packets, free_packets_twice, NULL), + BENCH_INFO(packet_copy_to_mem, create_packets, free_packets, NULL), + BENCH_INFO(packet_copy_from_mem, create_packets, free_packets, NULL), + BENCH_INFO(packet_copy_from_pkt, alloc_packets_twice, free_packets_twice, NULL), + BENCH_INFO(packet_copy_data, create_packets, free_packets, NULL), + BENCH_INFO(packet_move_data, create_packets, free_packets, NULL), + BENCH_INFO(packet_pool, create_packets, free_packets, NULL), + BENCH_INFO(packet_input, create_packets, free_packets, NULL), + BENCH_INFO(packet_input_index, create_packets, free_packets, NULL), + BENCH_INFO(packet_user_ptr, create_packets, free_packets, NULL), + BENCH_INFO(packet_user_ptr_set, create_packets, free_packets, NULL), + BENCH_INFO(packet_user_area, create_packets, free_packets, NULL), + BENCH_INFO(packet_user_area_size, create_packets, free_packets, NULL), + BENCH_INFO(packet_user_flag, create_packets, free_packets, NULL), + BENCH_INFO(packet_user_flag_set, create_packets, free_packets, NULL), + BENCH_INFO(packet_l2_ptr, create_packets, free_packets, NULL), + BENCH_INFO(packet_l2_offset, create_packets, free_packets, NULL), + BENCH_INFO(packet_l2_offset_set, create_packets, free_packets, NULL), + BENCH_INFO(packet_l3_ptr, create_packets, free_packets, NULL), + BENCH_INFO(packet_l3_offset, create_packets, free_packets, NULL), + BENCH_INFO(packet_l3_offset_set, create_packets, free_packets, NULL), + BENCH_INFO(packet_l4_ptr, create_packets, free_packets, NULL), + BENCH_INFO(packet_l4_offset, create_packets, free_packets, NULL), + BENCH_INFO(packet_l4_offset_set, create_packets, free_packets, NULL), + BENCH_INFO(packet_flow_hash, create_packets, free_packets, NULL), + BENCH_INFO(packet_flow_hash_set, create_packets, free_packets, NULL), + BENCH_INFO(packet_ts, create_packets, free_packets, NULL), + BENCH_INFO(packet_ts_set, create_packets, free_packets, NULL), + BENCH_INFO(packet_ref_static, create_packets, free_packets_twice, NULL), + BENCH_INFO(packet_ref, create_packets, free_packets_twice, NULL), + BENCH_INFO(packet_ref_pkt, alloc_packets_twice, free_packets_twice, NULL), + BENCH_INFO(packet_has_ref, alloc_ref_packets, free_packets_twice, NULL), + BENCH_INFO(packet_subtype, create_packets, free_packets, NULL), + BENCH_INFO(packet_parse, alloc_parse_packets_ipv4_tcp, free_packets, + "packet_parse ipv4/tcp"), + BENCH_INFO(packet_parse, alloc_parse_packets_ipv4_udp, free_packets, + "packet_parse ipv4/udp"), + BENCH_INFO(packet_parse, alloc_parse_packets_ipv6_tcp, free_packets, + "packet_parse ipv6/tcp"), + BENCH_INFO(packet_parse, alloc_parse_packets_ipv6_udp, free_packets, + "packet_parse ipv6/udp"), + BENCH_INFO(packet_parse_multi, alloc_parse_packets_multi_ipv4_tcp, free_packets_multi, + "packet_parse_multi ipv4/tcp"), + BENCH_INFO(packet_parse_multi, alloc_parse_packets_multi_ipv4_udp, free_packets_multi, + "packet_parse_multi ipv4/udp"), + BENCH_INFO(packet_parse_multi, alloc_parse_packets_multi_ipv6_tcp, free_packets_multi, + "packet_parse_multi ipv6/tcp"), + BENCH_INFO(packet_parse_multi, alloc_parse_packets_multi_ipv6_udp, free_packets_multi, + "packet_parse_multi ipv6/udp"), +}; + +/** + * ODP packet microbenchmark application + */ +int main(int argc, char *argv[]) +{ + odph_helper_options_t helper_options; + odph_thread_t worker_thread; + odph_thread_common_param_t thr_common; + odph_thread_param_t thr_param; + int cpu; + odp_shm_t shm; + odp_cpumask_t cpumask; + char cpumaskstr[ODP_CPUMASK_STR_SIZE]; + odp_pool_capability_t capa; + odp_pool_param_t params; + odp_instance_t instance; + odp_init_t init_param; + uint32_t pkt_num, seg_len; + uint8_t ret; + + /* 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); + } + + /* Init this thread */ + 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); + } + + gbl_args = odp_shm_addr(shm); + + if (gbl_args == NULL) { + ODPH_ERR("Error: shared mem alloc failed.\n"); + exit(EXIT_FAILURE); + } + + memset(gbl_args, 0, sizeof(args_t)); + + /* Parse and store the application arguments */ + parse_args(argc, argv, &gbl_args->appl); + + bench_suite_init(&gbl_args->suite); + gbl_args->suite.bench = test_suite; + gbl_args->suite.num_bench = ODPH_ARRAY_SIZE(test_suite); + gbl_args->suite.indef_idx = gbl_args->appl.bench_idx; + gbl_args->suite.rounds = gbl_args->appl.rounds; + gbl_args->suite.repeat_count = TEST_REPEAT_COUNT; + gbl_args->suite.measure_time = !!gbl_args->appl.time; + + /* Print both system and application information */ + print_info(NO_PATH(argv[0]), &gbl_args->appl); + + /* Get default worker cpumask */ + if (odp_cpumask_default_worker(&cpumask, 1) != 1) { + ODPH_ERR("Error: unable to allocate worker thread.\n"); + exit(EXIT_FAILURE); + } + + (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr)); + + /* Check pool capability */ + if (odp_pool_capability(&capa)) { + ODPH_ERR("Error: unable to query pool capability.\n"); + exit(EXIT_FAILURE); + } + + /* At least 2 x TEST_REPEAT_COUNT packets required */ + pkt_num = (gbl_args->appl.burst_size > 2) ? + gbl_args->appl.burst_size * TEST_REPEAT_COUNT : + 2 * TEST_REPEAT_COUNT; + + if (capa.pkt.max_num && capa.pkt.max_num < pkt_num) { + ODPH_ERR("Error: packet pool size not supported.\n"); + printf("MAX: %" PRIu32 "\n", capa.pkt.max_num); + exit(EXIT_FAILURE); + } else if (capa.pkt.max_len && + capa.pkt.max_len < 2 * TEST_MAX_PKT_SIZE) { + ODPH_ERR("Error: packet length not supported.\n"); + exit(EXIT_FAILURE); + } else if (capa.pkt.max_uarea_size && + capa.pkt.max_uarea_size < PKT_POOL_UAREA_SIZE) { + ODPH_ERR("Error: user area size not supported.\n"); + exit(EXIT_FAILURE); + } else if (gbl_args->appl.cache_size > (int)capa.pkt.max_cache_size) { + ODPH_ERR("Error: cache size not supported (max %" PRIu32 ")\n", + capa.pkt.max_cache_size); + exit(EXIT_FAILURE); + } + + seg_len = TEST_MAX_PKT_SIZE; + if (capa.pkt.max_seg_len && capa.pkt.max_seg_len < seg_len) { + seg_len = capa.pkt.max_seg_len; + printf("\nWarn: allocated packets may be segmented (min seg_len=%" PRIu32 ")\n\n", + seg_len); + } + + /* Create packet pool */ + odp_pool_param_init(¶ms); + params.pkt.seg_len = seg_len; + /* Using packet length as twice the TEST_MAX_PKT_SIZE as some + * test cases (packet_ref_pkt) might allocate a bigger + * packet than TEST_MAX_PKT_SIZE. + */ + params.pkt.len = 2 * TEST_MAX_PKT_SIZE; + params.pkt.num = pkt_num; + params.pkt.uarea_size = PKT_POOL_UAREA_SIZE; + if (gbl_args->appl.cache_size >= 0) + params.pkt.cache_size = gbl_args->appl.cache_size; + params.type = ODP_POOL_PACKET; + + gbl_args->pool = odp_pool_create("packet pool", ¶ms); + + if (gbl_args->pool == ODP_POOL_INVALID) { + ODPH_ERR("Error: packet pool create failed.\n"); + exit(EXIT_FAILURE); + } + + printf("CPU: %i\n", odp_cpumask_first(&cpumask)); + printf("CPU mask: %s\n", cpumaskstr); + printf("Burst size: %d\n", gbl_args->appl.burst_size); + printf("Bench repeat: %d\n", TEST_REPEAT_COUNT); + printf("Measurement unit: %s\n", gbl_args->appl.time ? "nsec" : "CPU cycles"); + printf("Test rounds: %u\n", gbl_args->appl.rounds); + if (gbl_args->appl.cache_size < 0) + printf("Pool cache size: default\n"); + else + printf("Pool cache size: %d\n", gbl_args->appl.cache_size); + + odp_pool_print(gbl_args->pool); + + memset(&worker_thread, 0, sizeof(odph_thread_t)); + + signal(SIGINT, sig_handler); + + /* Create worker threads */ + cpu = odp_cpumask_first(&cpumask); + + odp_cpumask_t thd_mask; + + odp_cpumask_zero(&thd_mask); + odp_cpumask_set(&thd_mask, cpu); + + odph_thread_common_param_init(&thr_common); + thr_common.instance = instance; + thr_common.cpumask = &thd_mask; + thr_common.share_param = 1; + + odph_thread_param_init(&thr_param); + thr_param.start = run_benchmarks; + thr_param.arg = gbl_args; + thr_param.thr_type = ODP_THREAD_WORKER; + + odph_thread_create(&worker_thread, &thr_common, &thr_param, 1); + + odph_thread_join(&worker_thread, 1); + + ret = gbl_args->suite.retval; + + if (odp_pool_destroy(gbl_args->pool)) { + ODPH_ERR("Error: pool destroy\n"); + exit(EXIT_FAILURE); + } + gbl_args = NULL; + odp_mb_full(); + + if (odp_shm_free(shm)) { + ODPH_ERR("Error: shm free\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_local()) { + ODPH_ERR("Error: term local\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_global(instance)) { + ODPH_ERR("Error: term global\n"); + exit(EXIT_FAILURE); + } + + return ret; +} |