Merged,
Maxim.

On 01/23/17 17:35, Matias Elo wrote:
> The application calls each packet function TEST_REPEAT_COUNT times and
> calculates the average cycle count per call.
> 
> Main options:
> -b: Burst size for *_multi operations
> -i: Benchmark index to run indefinitely
> 
> The application prints benchmark results as a table, which can be copied
> as is to a spreadsheet application.
> 
> Signed-off-by: Matias Elo <matias....@nokia.com>
> Reviewed-and-tested-by: Bill Fischofer <bill.fischo...@linaro.org>
> ---
> V2:
> - Rebase to master
> - Fix Makefile (Maxim)
> 
>  test/common_plat/performance/.gitignore         |    1 +
>  test/common_plat/performance/Makefile.am        |    7 +-
>  test/common_plat/performance/odp_bench_packet.c | 1611 
> +++++++++++++++++++++++
>  3 files changed, 1618 insertions(+), 1 deletion(-)
>  create mode 100644 test/common_plat/performance/odp_bench_packet.c
> 
> diff --git a/test/common_plat/performance/.gitignore 
> b/test/common_plat/performance/.gitignore
> index 1527d25..eeacf2f 100644
> --- a/test/common_plat/performance/.gitignore
> +++ b/test/common_plat/performance/.gitignore
> @@ -1,6 +1,7 @@
>  *.log
>  *.trs
>  odp_atomic
> +odp_bench_packet
>  odp_crypto
>  odp_l2fwd
>  odp_pktio_perf
> diff --git a/test/common_plat/performance/Makefile.am 
> b/test/common_plat/performance/Makefile.am
> index f184609..bcbf9cd 100644
> --- a/test/common_plat/performance/Makefile.am
> +++ b/test/common_plat/performance/Makefile.am
> @@ -2,7 +2,9 @@ include $(top_srcdir)/test/Makefile.inc
>  
>  TESTS_ENVIRONMENT += TEST_DIR=${builddir}
>  
> -EXECUTABLES = odp_crypto$(EXEEXT) odp_pktio_perf$(EXEEXT)
> +EXECUTABLES = odp_bench_packet$(EXEEXT) \
> +                       odp_crypto$(EXEEXT) \
> +                       odp_pktio_perf$(EXEEXT)
>  
>  COMPILE_ONLY = odp_l2fwd$(EXEEXT) \
>              odp_sched_latency$(EXEEXT) \
> @@ -20,6 +22,8 @@ endif
>  
>  bin_PROGRAMS = $(EXECUTABLES) $(COMPILE_ONLY)
>  
> +odp_bench_packet_LDFLAGS = $(AM_LDFLAGS) -static
> +odp_bench_packet_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test
>  odp_crypto_LDFLAGS = $(AM_LDFLAGS) -static
>  odp_crypto_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test
>  odp_sched_latency_LDFLAGS = $(AM_LDFLAGS) -static
> @@ -30,6 +34,7 @@ odp_scheduling_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test
>  noinst_HEADERS = \
>                 $(top_srcdir)/test/test_debug.h
>  
> +dist_odp_bench_packet_SOURCES = odp_bench_packet.c
>  dist_odp_crypto_SOURCES = odp_crypto.c
>  dist_odp_sched_latency_SOURCES = odp_sched_latency.c
>  dist_odp_scheduling_SOURCES = odp_scheduling.c
> diff --git a/test/common_plat/performance/odp_bench_packet.c 
> b/test/common_plat/performance/odp_bench_packet.c
> new file mode 100644
> index 0000000..1aa9d81
> --- /dev/null
> +++ b/test/common_plat/performance/odp_bench_packet.c
> @@ -0,0 +1,1611 @@
> +/* Copyright (c) 2017, Linaro Limited
> + * All rights reserved.
> + *
> + * SPDX-License-Identifier:     BSD-3-Clause
> + */
> +
> +/**
> + * @file
> + *
> + * @example odp_bench_packet.c  Microbenchmarks for packet functions
> + */
> +
> +#include <stdlib.h>
> +#include <getopt.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <inttypes.h>
> +#include <signal.h>
> +
> +#include <test_debug.h>
> +
> +#include <odp_api.h>
> +#include <odp/helper/threads.h>
> +#include <odp/helper/eth.h>
> +#include <odp/helper/ip.h>
> +#include <odp/helper/udp.h>
> +
> +/** Minimum number of packet data bytes in the first segment */
> +#define PKT_POOL_SEG_LEN 128
> +
> +/** 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 test runs per individual benchmark */
> +#define TEST_REPEAT_COUNT 1000
> +
> +/** Number of times to run tests for each packet size */
> +#define TEST_SIZE_RUN_COUNT 10
> +
> +/** 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, init, term, name) \
> +     {#run, run, init, term, name}
> +
> +ODP_STATIC_ASSERT((TEST_ALIGN_OFFSET + TEST_ALIGN_LEN) <= TEST_MIN_PKT_SIZE,
> +               "Invalid_alignment");
> +
> +/** Warm up round packet size */
> +#define WARM_UP TEST_MIN_PKT_SIZE
> +
> +/** Test packet sizes */
> +const uint32_t test_packet_len[] = {WARM_UP, 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 */
> +} appl_args_t;
> +
> +/**
> + * Initialize benchmark resources
> + */
> +typedef void (*bench_init_fn_t)(void);
> +
> +/**
> + * Run benchmark
> + *
> + * @retval >0 on success
> + * */
> +typedef int (*bench_run_fn_t)(void);
> +
> +/**
> + * Release benchmark resources
> + */
> +typedef void (*bench_term_fn_t)(void);
> +
> +/**
> + * Benchmark data
> + */
> +typedef struct {
> +     const char *name;
> +     bench_run_fn_t run;
> +     bench_init_fn_t init;
> +     bench_term_fn_t term;
> +     const char *desc;
> +} bench_info_t;
> +
> +/**
> + * Grouping of all global data
> + */
> +typedef struct {
> +     /** Application (parsed) arguments */
> +     appl_args_t appl;
> +     /** Packet pool */
> +     odp_pool_t pool;
> +     /** Benchmark functions */
> +     bench_info_t *bench;
> +     /** Number of benchmark functions */
> +     int num_bench;
> +     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];
> +     /** 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];
> +     /** Benchmark run failed */
> +     uint8_t bench_failed;
> +} args_t;
> +
> +/** Global pointer to args */
> +static args_t *gbl_args;
> +/** Global barrier to synchronize main and worker */
> +static odp_barrier_t barrier;
> +/** Break worker loop if set to 1 */
> +static int exit_thread;
> +
> +static void sig_handler(int signo ODP_UNUSED)
> +{
> +     exit_thread = 1;
> +}
> +
> +/**
> + * Run given benchmark indefinitely
> + */
> +static void run_indef(args_t *args, int idx)
> +{
> +     const char *desc;
> +
> +     desc = args->bench[idx].desc != NULL ?
> +                     args->bench[idx].desc : args->bench[idx].name;
> +
> +     printf("Running %s() indefinitely\n", desc);
> +
> +     while (!exit_thread) {
> +             int ret;
> +
> +             if (args->bench[idx].init != NULL)
> +                     args->bench[idx].init();
> +
> +             ret = args->bench[idx].run();
> +
> +             if (args->bench[idx].term != NULL)
> +                     args->bench[idx].term();
> +
> +             if (!ret)
> +                     LOG_ABORT("Benchmark %s failed\n", desc);
> +     }
> +}
> +
> +/**
> + * Master function for running the microbenchmarks
> + */
> +static int run_benchmarks(void *arg)
> +{
> +     int i, j, k;
> +     args_t *args = arg;
> +     int num_sizes = sizeof(test_packet_len) / sizeof(test_packet_len[0]);
> +     double results[gbl_args->num_bench][num_sizes];
> +
> +     memset(results, 0, sizeof(results));
> +
> +     printf("\nRunning benchmarks (cycles per call)\n"
> +            "------------------------------------\n");
> +
> +     for (i = 0; i < num_sizes; i++) {
> +             uint64_t tot_cycles = 0;
> +
> +             printf("\nPacket length: %6d bytes\n"
> +                    "---------------------------\n", test_packet_len[i]);
> +
> +             gbl_args->pkt.len = test_packet_len[i];
> +
> +             for (j = 0, k = 1; j < gbl_args->num_bench; k++) {
> +                     int ret;
> +                     uint64_t c1, c2;
> +                     const char *desc;
> +
> +                     if (args->appl.bench_idx &&
> +                         (j + 1) != args->appl.bench_idx) {
> +                             j++;
> +                             continue;
> +                     } else if (args->appl.bench_idx &&
> +                                (j + 1) == args->appl.bench_idx) {
> +                             run_indef(args, j);
> +                             return 0;
> +                     }
> +
> +                     desc = args->bench[j].desc != NULL ?
> +                                     args->bench[j].desc :
> +                                     args->bench[j].name;
> +
> +                     if (args->bench[j].init != NULL)
> +                             args->bench[j].init();
> +
> +                     c1 = odp_cpu_cycles();
> +                     ret = args->bench[j].run();
> +                     c2 = odp_cpu_cycles();
> +
> +                     if (args->bench[j].term != NULL)
> +                             args->bench[j].term();
> +
> +                     if (!ret) {
> +                             LOG_ERR("Benchmark %s failed\n", desc);
> +                             args->bench_failed = 1;
> +                             return -1;
> +                     }
> +
> +                     tot_cycles += odp_cpu_cycles_diff(c2, c1);
> +
> +                     if (k >= TEST_SIZE_RUN_COUNT) {
> +                             double cycles;
> +
> +                             /** Each benchmark runs internally
> +                              *  TEST_REPEAT_COUNT times. */
> +                             cycles = ((double)tot_cycles) /
> +                                      (TEST_SIZE_RUN_COUNT *
> +                                       TEST_REPEAT_COUNT);
> +                             results[j][i] = cycles;
> +
> +                             printf("%-30s: %8.1f\n", desc, cycles);
> +
> +                             j++;
> +                             k = 0;
> +                             tot_cycles = 0;
> +                     }
> +             }
> +     }
> +     printf("\n%-30s", "Benchmark / packet_size [B]");
> +     for (i = 0; i < num_sizes; i++) {
> +             if (i == 0)
> +                     printf("      WARM UP  ");
> +             else
> +                     printf("%8.1d  ", test_packet_len[i]);
> +     }
> +     printf("\n---------------------------------");
> +     for (i = 0; i < num_sizes; i++)
> +             printf("----------");
> +
> +     for (i = 0; i < gbl_args->num_bench; i++) {
> +             printf("\n[%02d] %-30s", i + 1, args->bench[i].desc != NULL ?
> +                    args->bench[i].desc : args->bench[i].name);
> +
> +             for (j = 0; j < num_sizes; j++)
> +                     printf("%8.1f  ", results[i][j]);
> +     }
> +     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)
> +                     LOG_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_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 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))
> +                     LOG_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 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 bench_empty(void)
> +{
> +     int i;
> +
> +     for (i = 0; i < TEST_REPEAT_COUNT; i++)
> +             gbl_args->output_tbl[i] = i;
> +
> +     return i;
> +}
> +
> +static int bench_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 bench_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 bench_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 bench_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 bench_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 bench_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);
> +             odp_packet_free_multi(gbl_args->pkt_tbl, pkts);
> +     }
> +     return i;
> +}
> +
> +static int bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 ret;
> +}
> +
> +static int bench_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 ret;
> +}
> +
> +static int bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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 bench_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;
> +}
> +
> +/**
> + * Prinf 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      Test packet burst size.\n"
> +            "  -i, --index      Benchmark index to run indefinitely.\n"
> +            "  -h, --help       Display help and exit.\n\n"
> +            "\n", NO_PATH(progname), NO_PATH(progname));
> +}
> +
> +/**
> + * 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'},
> +             {"help", no_argument, NULL, 'h'},
> +             {"index", required_argument, NULL, 'i'},
> +             {NULL, 0, NULL, 0}
> +     };
> +
> +     static const char *shortopts =  "b:i:h";
> +
> +     /* Let helper collect its own arguments (e.g. --odph_proc) */
> +     odph_parse_options(argc, argv, shortopts, longopts);
> +
> +     opterr = 0; /* Do not issue errors on helper options */
> +
> +     appl_args->bench_idx = 0; /* Run all benchmarks */
> +     appl_args->burst_size = TEST_DEF_BURST;
> +
> +     while (1) {
> +             opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
> +
> +             if (opt == -1)
> +                     break;  /* No more options */
> +
> +             switch (opt) {
> +             case 'b':
> +                     appl_args->burst_size = atoi(optarg);
> +                     break;
> +             case 'h':
> +                     usage(argv[0]);
> +                     exit(EXIT_SUCCESS);
> +                     break;
> +             case 'i':
> +                     appl_args->bench_idx = atoi(optarg);
> +                     break;
> +             default:
> +                     break;
> +             }
> +     }
> +
> +     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);
> +     }
> +
> +     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)
> +{
> +     printf("\n"
> +            "ODP system info\n"
> +            "---------------\n"
> +            "ODP API version: %s\n"
> +            "ODP impl name:   %s\n"
> +            "CPU model:       %s\n"
> +            "CPU freq (hz):   %" PRIu64 "\n"
> +            "Cache line size: %i\n"
> +            "CPU count:       %i\n"
> +            "\n",
> +            odp_version_api_str(), odp_version_impl_name(),
> +            odp_cpu_model_str(), odp_cpu_hz_max(),
> +            odp_sys_cache_line_size(), odp_cpu_count());
> +
> +     printf("Running ODP appl: \"%s\"\n"
> +            "-----------------\n", progname);
> +     fflush(NULL);
> +}
> +
> +/**
> + * Test functions
> + */
> +bench_info_t test_suite[] = {
> +             BENCH_INFO(bench_empty, NULL, NULL, NULL),
> +             BENCH_INFO(bench_packet_alloc, NULL, free_packets, NULL),
> +             BENCH_INFO(bench_packet_alloc_multi, NULL, free_packets_multi,
> +                        NULL),
> +             BENCH_INFO(bench_packet_free, create_packets, NULL, NULL),
> +             BENCH_INFO(bench_packet_free_multi, alloc_packets_multi, NULL,
> +                        NULL),
> +             BENCH_INFO(bench_packet_alloc_free, NULL, NULL, NULL),
> +             BENCH_INFO(bench_packet_alloc_free_multi, NULL, NULL, NULL),
> +             BENCH_INFO(bench_packet_reset, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_from_event, create_events, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_to_event, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_head, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_buf_len, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_data, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_seg_len, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_len, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_headroom, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_tailroom, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_tail, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_offset, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_prefetch, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_push_head, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_pull_head, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_push_tail, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_pull_tail, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_extend_head, alloc_packets_half,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_trunc_head, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_extend_tail, alloc_packets_half,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_trunc_tail, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_add_data, alloc_packets_half,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_rem_data, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_align, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_is_segmented, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_num_segs, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_first_seg, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_last_seg, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_next_seg, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_seg_data, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_seg_data_len, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_concat, alloc_concat_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_split, create_packets,
> +                        free_packets_twice, NULL),
> +             BENCH_INFO(bench_packet_copy, create_packets,
> +                        free_packets_twice, NULL),
> +             BENCH_INFO(bench_packet_copy_part, create_packets,
> +                        free_packets_twice, NULL),
> +             BENCH_INFO(bench_packet_copy_to_mem, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_copy_from_mem, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_copy_from_pkt, alloc_packets_twice,
> +                        free_packets_twice, NULL),
> +             BENCH_INFO(bench_packet_copy_data, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_move_data, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_pool, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_input, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_input_index, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_user_ptr, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_user_ptr_set, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_user_area, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_user_area_size, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_l2_ptr, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_l2_offset, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_l2_offset_set, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_l3_ptr, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_l3_offset, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_l3_offset_set, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_l4_ptr, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_l4_offset, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_l4_offset_set, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_flow_hash, create_packets, free_packets,
> +                        NULL),
> +             BENCH_INFO(bench_packet_flow_hash_set, create_packets,
> +                        free_packets, NULL),
> +             BENCH_INFO(bench_packet_ts, create_packets, free_packets, NULL),
> +             BENCH_INFO(bench_packet_ts_set, create_packets, free_packets,
> +                        NULL),
> +};
> +
> +/**
> + * ODP packet microbenchmark application
> + */
> +int main(int argc, char *argv[])
> +{
> +     odph_odpthread_t worker_thread;
> +     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;
> +     uint32_t pkt_num;
> +     uint8_t ret;
> +
> +     /* Init ODP before calling anything else */
> +     if (odp_init_global(&instance, NULL, NULL)) {
> +             LOG_ERR("Error: ODP global init failed.\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     /* Init this thread */
> +     if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
> +             LOG_ERR("Error: ODP local init failed.\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     /* Reserve memory for args from shared mem */
> +     shm = odp_shm_reserve("shm_args", sizeof(args_t),
> +                           ODP_CACHE_LINE_SIZE, 0);
> +
> +     if (shm == ODP_SHM_INVALID) {
> +             LOG_ERR("Error: shared mem reserve failed.\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     gbl_args = odp_shm_addr(shm);
> +
> +     if (gbl_args == NULL) {
> +             LOG_ERR("Error: shared mem alloc failed.\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     memset(gbl_args, 0, sizeof(args_t));
> +
> +     gbl_args->bench = test_suite;
> +     gbl_args->num_bench = sizeof(test_suite) / sizeof(test_suite[0]);
> +
> +     /* Parse and store the application arguments */
> +     parse_args(argc, argv, &gbl_args->appl);
> +
> +     /* Print both system and application information */
> +     print_info(NO_PATH(argv[0]), &gbl_args->appl);
> +
> +     /* Get default worker cpumask */
> +     if (odp_cpumask_default_worker(&cpumask, 1) != 1) {
> +             LOG_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)) {
> +             LOG_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) {
> +             LOG_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 < TEST_MAX_PKT_SIZE) {
> +             LOG_ERR("Error: packet length not supported.\n");
> +             exit(EXIT_FAILURE);
> +     } else if (capa.pkt.max_seg_len &&
> +                capa.pkt.max_seg_len < PKT_POOL_SEG_LEN) {
> +             LOG_ERR("Error: segment length not supported.\n");
> +             exit(EXIT_FAILURE);
> +     } else if (capa.pkt.max_uarea_size &&
> +                capa.pkt.max_uarea_size < PKT_POOL_UAREA_SIZE) {
> +             LOG_ERR("Error: user area size not supported.\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     /* Create packet pool */
> +     odp_pool_param_init(&params);
> +     params.pkt.seg_len = PKT_POOL_SEG_LEN;
> +     params.pkt.len     = TEST_MAX_PKT_SIZE;
> +     params.pkt.num     = pkt_num;
> +     params.pkt.uarea_size = PKT_POOL_UAREA_SIZE;
> +     params.type        = ODP_POOL_PACKET;
> +
> +     gbl_args->pool = odp_pool_create("packet pool", &params);
> +
> +     if (gbl_args->pool == ODP_POOL_INVALID) {
> +             LOG_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);
> +
> +     odp_pool_print(gbl_args->pool);
> +
> +     memset(&worker_thread, 0, sizeof(odph_odpthread_t));
> +
> +     odp_barrier_init(&barrier, 1 + 1);
> +
> +     signal(SIGINT, sig_handler);
> +
> +     /* Create worker threads */
> +     cpu = odp_cpumask_first(&cpumask);
> +
> +     odp_cpumask_t thd_mask;
> +     odph_odpthread_params_t thr_params;
> +
> +     memset(&thr_params, 0, sizeof(thr_params));
> +     thr_params.start    = run_benchmarks;
> +     thr_params.arg      = gbl_args;
> +     thr_params.thr_type = ODP_THREAD_WORKER;
> +     thr_params.instance = instance;
> +
> +     odp_cpumask_zero(&thd_mask);
> +     odp_cpumask_set(&thd_mask, cpu);
> +     odph_odpthreads_create(&worker_thread, &thd_mask,
> +                            &thr_params);
> +
> +     odph_odpthreads_join(&worker_thread);
> +
> +     ret = gbl_args->bench_failed;
> +
> +     if (odp_pool_destroy(gbl_args->pool)) {
> +             LOG_ERR("Error: pool destroy\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     if (odp_shm_free(shm)) {
> +             LOG_ERR("Error: shm free\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     if (odp_term_local()) {
> +             LOG_ERR("Error: term local\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     if (odp_term_global(instance)) {
> +             LOG_ERR("Error: term global\n");
> +             exit(EXIT_FAILURE);
> +     }
> +
> +     return ret;
> +}
> 

Reply via email to