diff options
author | Matias Elo <matias.elo@nokia.com> | 2023-02-16 15:59:06 +0200 |
---|---|---|
committer | Matias Elo <matias.elo@nokia.com> | 2023-02-16 15:59:06 +0200 |
commit | ddfe9c540512bf16a541e79ba75c23bdc740a75a (patch) | |
tree | 97720c8348cf4fa16f661bcc8e441927d0e65a37 /test | |
parent | 282188e33695bb6863e289df61e0dfbd87ca205c (diff) | |
parent | 30930db550a640df1a25847c7623e5ecfe670b9b (diff) |
Merge tag 'v1.40.0.0' of https://github.com/OpenDataPlane/odp into odp-dpdk
Signed-off-by: Matias Elo <matias.elo@nokia.com>
Diffstat (limited to 'test')
23 files changed, 2045 insertions, 341 deletions
diff --git a/test/Makefile.inc b/test/Makefile.inc index f5235f471..6d14f9c17 100644 --- a/test/Makefile.inc +++ b/test/Makefile.inc @@ -10,6 +10,7 @@ LIBODP = $(LIB)/libodphelper.la $(LIB)/lib$(ODP_LIB_NAME).la LIBCUNIT_COMMON = $(COMMON_DIR)/libcunit_common.la LIBCPUMASK_COMMON = $(COMMON_DIR)/libcpumask_common.la +LIBPACKET_COMMON = $(COMMON_DIR)/libpacket_common.la LIBTHRMASK_COMMON = $(COMMON_DIR)/libthrmask_common.la #in the following line, the libs using the symbols should come before diff --git a/test/common/Makefile.am b/test/common/Makefile.am index 694b442c2..72658df73 100644 --- a/test/common/Makefile.am +++ b/test/common/Makefile.am @@ -2,13 +2,19 @@ include $(top_srcdir)/test/Makefile.inc if cunit_support -noinst_LTLIBRARIES = libcunit_common.la libcpumask_common.la libthrmask_common.la +noinst_LTLIBRARIES = \ + libcunit_common.la \ + libcpumask_common.la \ + libpacket_common.la \ + libthrmask_common.la libcunit_common_la_SOURCES = odp_cunit_common.c odp_cunit_common.h libcunit_common_la_LIBADD = $(CUNIT_LIBS) libcpumask_common_la_SOURCES = mask_common.c mask_common.h +libpacket_common_la_SOURCES = packet_common.c packet_common.h + libthrmask_common_la_SOURCES = mask_common.c mask_common.h libthrmask_common_la_CFLAGS = $(AM_CFLAGS) -DTEST_THRMASK diff --git a/test/common/packet_common.c b/test/common/packet_common.c new file mode 100644 index 000000000..e0bca3147 --- /dev/null +++ b/test/common/packet_common.c @@ -0,0 +1,133 @@ +/* Copyright (c) 2023, Nokia + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <packet_common.h> +#include <string.h> + +void test_packet_set_md(odp_packet_t pkt) +{ + const int binary_flag = 1; + const uint32_t offset = 1; + uint8_t *uarea = odp_packet_user_area(pkt); + uint32_t uarea_size = odp_packet_user_area_size(pkt); + + for (uint32_t n = 0; n < uarea_size; n++) + uarea[n] = n; + + /* + * Some of these flags cannot be set simultaneously, but we do not + * care here if some flags get cleared. + */ + odp_packet_has_l2_set(pkt, binary_flag); + odp_packet_has_l3_set(pkt, binary_flag); + odp_packet_has_l4_set(pkt, binary_flag); + odp_packet_has_eth_set(pkt, binary_flag); + odp_packet_has_eth_bcast_set(pkt, binary_flag); + odp_packet_has_eth_mcast_set(pkt, !binary_flag); + odp_packet_has_jumbo_set(pkt, binary_flag); + odp_packet_has_vlan_set(pkt, binary_flag); + odp_packet_has_vlan_qinq_set(pkt, binary_flag); + odp_packet_has_arp_set(pkt, binary_flag); + odp_packet_has_ipv4_set(pkt, binary_flag); + odp_packet_has_ipv6_set(pkt, !binary_flag); + odp_packet_has_ip_bcast_set(pkt, binary_flag); + odp_packet_has_ip_mcast_set(pkt, binary_flag); + odp_packet_has_ipfrag_set(pkt, binary_flag); + odp_packet_has_ipopt_set(pkt, binary_flag); + odp_packet_has_ipsec_set(pkt, binary_flag); + odp_packet_has_udp_set(pkt, binary_flag); + odp_packet_has_tcp_set(pkt, !binary_flag); + odp_packet_has_sctp_set(pkt, binary_flag); + odp_packet_has_icmp_set(pkt, binary_flag); + + odp_packet_user_ptr_set(pkt, &pkt); + odp_packet_user_flag_set(pkt, binary_flag); + (void)odp_packet_l2_offset_set(pkt, offset); + (void)odp_packet_l3_offset_set(pkt, offset); + (void)odp_packet_l4_offset_set(pkt, offset); + odp_packet_flow_hash_set(pkt, 0x12345678); + odp_packet_ts_set(pkt, odp_time_local_from_ns(ODP_TIME_SEC_IN_NS)); + odp_packet_color_set(pkt, ODP_PACKET_YELLOW); + odp_packet_drop_eligible_set(pkt, binary_flag); + odp_packet_shaper_len_adjust_set(pkt, -42); + (void)odp_packet_payload_offset_set(pkt, offset); +} + +void test_packet_get_md(odp_packet_t pkt, test_packet_md_t *md) +{ + uint8_t *uarea = odp_packet_user_area(pkt); + uint32_t uarea_size = odp_packet_user_area_size(pkt); + + memset(md, 0, sizeof(*md)); + + if (uarea) + md->user_area_chksum = odp_chksum_ones_comp16(uarea, uarea_size); + + md->has_error = !!odp_packet_has_error(pkt); + md->has_l2_error = !!odp_packet_has_l2_error(pkt); + md->has_l3_error = !!odp_packet_has_l3_error(pkt); + md->has_l4_error = !!odp_packet_has_l4_error(pkt); + md->has_l2 = !!odp_packet_has_l2(pkt); + md->has_l3 = !!odp_packet_has_l3(pkt); + md->has_l4 = !!odp_packet_has_l4(pkt); + md->has_eth = !!odp_packet_has_eth(pkt); + md->has_eth_bcast = !!odp_packet_has_eth_bcast(pkt); + md->has_eth_mcast = !!odp_packet_has_eth_mcast(pkt); + md->has_jumbo = !!odp_packet_has_jumbo(pkt); + md->has_vlan = !!odp_packet_has_vlan(pkt); + md->has_vlan_qinq = !!odp_packet_has_vlan_qinq(pkt); + md->has_arp = !!odp_packet_has_arp(pkt); + md->has_ipv4 = !!odp_packet_has_ipv4(pkt); + md->has_ipv6 = !!odp_packet_has_ipv6(pkt); + md->has_ip_bcast = !!odp_packet_has_ip_bcast(pkt); + md->has_ip_mcast = !!odp_packet_has_ip_mcast(pkt); + md->has_ipfrag = !!odp_packet_has_ipfrag(pkt); + md->has_ipopt = !!odp_packet_has_ipopt(pkt); + md->has_ipsec = !!odp_packet_has_ipsec(pkt); + md->has_udp = !!odp_packet_has_udp(pkt); + md->has_tcp = !!odp_packet_has_tcp(pkt); + md->has_sctp = !!odp_packet_has_sctp(pkt); + md->has_icmp = !!odp_packet_has_icmp(pkt); + md->has_flow_hash = !!odp_packet_has_flow_hash(pkt); + md->has_ts = !!odp_packet_has_ts(pkt); + + md->len = odp_packet_len(pkt); + md->packet_pool = odp_packet_pool(pkt); + md->packet_input = odp_packet_input(pkt); + md->user_ptr = odp_packet_user_ptr(pkt); + md->user_flag = odp_packet_user_flag(pkt); + md->l2_offset = odp_packet_l2_offset(pkt); + md->l3_offset = odp_packet_l3_offset(pkt); + md->l4_offset = odp_packet_l4_offset(pkt); + md->l2_type = odp_packet_l2_type(pkt); + md->l3_type = odp_packet_l3_type(pkt); + md->l4_type = odp_packet_l4_type(pkt); + md->l3_chksum_status = odp_packet_l3_chksum_status(pkt); + md->l4_chksum_status = odp_packet_l4_chksum_status(pkt); + md->flow_hash = md->has_flow_hash ? odp_packet_flow_hash(pkt) : 0; + md->ts = md->has_ts ? odp_packet_ts(pkt) : odp_time_global_from_ns(0); + md->color = odp_packet_color(pkt); + md->drop_eligible = !!odp_packet_drop_eligible(pkt); + md->shaper_len_adjust = odp_packet_shaper_len_adjust(pkt); + md->cls_mark = odp_packet_cls_mark(pkt); + md->has_lso_request = !!odp_packet_has_lso_request(pkt); + md->payload_offset = odp_packet_payload_offset(pkt); + md->aging_tmo = odp_packet_aging_tmo(pkt); + md->has_tx_compl_request = !!odp_packet_has_tx_compl_request(pkt); + md->proto_stats = odp_packet_proto_stats(pkt); +} + +int test_packet_is_md_equal(const test_packet_md_t *md_1, + const test_packet_md_t *md_2) +{ + /* + * With certain assumptions this should typically work. If it does + * not, we would get false negatives which we should spot as test + * failures. + */ + + return (!memcmp(md_1, md_2, sizeof(*md_1))); +} diff --git a/test/common/packet_common.h b/test/common/packet_common.h new file mode 100644 index 000000000..c7cd5e27f --- /dev/null +++ b/test/common/packet_common.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2023, Nokia + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <odp_api.h> + +typedef struct test_packet_md_t { + int has_error; + int has_l2_error; + int has_l3_error; + int has_l4_error; + int has_l2; + int has_l3; + int has_l4; + int has_eth; + int has_eth_bcast; + int has_eth_mcast; + int has_jumbo; + int has_vlan; + int has_vlan_qinq; + int has_arp; + int has_ipv4; + int has_ipv6; + int has_ip_bcast; + int has_ip_mcast; + int has_ipfrag; + int has_ipopt; + int has_ipsec; + int has_udp; + int has_tcp; + int has_sctp; + int has_icmp; + int has_flow_hash; + int has_ts; + uint32_t len; + odp_pool_t packet_pool; + odp_pktio_t packet_input; + void *user_ptr; + uint16_t user_area_chksum; + int user_flag; + uint32_t l2_offset; + uint32_t l3_offset; + uint32_t l4_offset; + odp_proto_l2_type_t l2_type; + odp_proto_l3_type_t l3_type; + odp_proto_l4_type_t l4_type; + odp_packet_chksum_status_t l3_chksum_status; + odp_packet_chksum_status_t l4_chksum_status; + uint32_t flow_hash; + odp_time_t ts; + odp_packet_color_t color; + odp_bool_t drop_eligible; + int8_t shaper_len_adjust; + uint64_t cls_mark; + int has_lso_request; + uint32_t payload_offset; + uint64_t aging_tmo; + int has_tx_compl_request; + odp_proto_stats_t proto_stats; +} test_packet_md_t; + +void test_packet_set_md(odp_packet_t pkt); +void test_packet_get_md(odp_packet_t pkt, test_packet_md_t *md); +int test_packet_is_md_equal(const test_packet_md_t *md_1, + const test_packet_md_t *md_2); diff --git a/test/performance/.gitignore b/test/performance/.gitignore index ec1915bba..b86699c91 100644 --- a/test/performance/.gitignore +++ b/test/performance/.gitignore @@ -3,6 +3,7 @@ odp_atomic odp_atomic_perf odp_bench_buffer +odp_bench_misc odp_bench_packet odp_cpu_bench odp_crc diff --git a/test/performance/Makefile.am b/test/performance/Makefile.am index 336a46d22..beeb652cc 100644 --- a/test/performance/Makefile.am +++ b/test/performance/Makefile.am @@ -4,6 +4,7 @@ TESTS_ENVIRONMENT += TEST_DIR=${builddir} EXECUTABLES = odp_atomic_perf \ odp_bench_buffer \ + odp_bench_misc \ odp_bench_packet \ odp_crc \ odp_lock_perf \ @@ -54,6 +55,7 @@ bin_PROGRAMS = $(EXECUTABLES) $(COMPILE_ONLY) odp_atomic_perf_SOURCES = odp_atomic_perf.c odp_bench_buffer_SOURCES = odp_bench_buffer.c +odp_bench_misc_SOURCES = odp_bench_misc.c odp_bench_packet_SOURCES = odp_bench_packet.c odp_cpu_bench_SOURCES = odp_cpu_bench.c odp_crc_SOURCES = odp_crc.c diff --git a/test/performance/odp_bench_buffer.c b/test/performance/odp_bench_buffer.c index e7029f57d..e0e7c85cd 100644 --- a/test/performance/odp_bench_buffer.c +++ b/test/performance/odp_bench_buffer.c @@ -199,7 +199,7 @@ static int run_benchmarks(void *arg) /* Skip unsupported tests */ if (args->bench[j].cond != NULL && !args->bench[j].cond()) { j++; - k = 0; + k = 1; if (i > 0) printf("[%02d] odp_%-26s: n/a\n", j, desc); continue; @@ -236,7 +236,7 @@ static int run_benchmarks(void *arg) printf("[%02d] odp_%-26s: %8.1f\n", j + 1, desc, cycles); j++; - k = 0; + k = 1; tot_cycles = 0; } } diff --git a/test/performance/odp_bench_misc.c b/test/performance/odp_bench_misc.c new file mode 100644 index 000000000..8b9e27bf2 --- /dev/null +++ b/test/performance/odp_bench_misc.c @@ -0,0 +1,1069 @@ +/* Copyright (c) 2022, Nokia + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* Needed for sigaction */ +#endif + +#include <odp_api.h> +#include <odp/helper/odph_api.h> + +#include <getopt.h> +#include <inttypes.h> +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> + +/* Number of API function calls per test case */ +#define REPEAT_COUNT 1000 + +/* Default number of rounds per test case */ +#define ROUNDS 1000u + +#define BENCH_INFO(run, init, max, name) \ + {#run, run, init, max, name} + +typedef struct { + /* Measure time vs CPU cycles */ + int time; + + /* Benchmark index to run indefinitely */ + int bench_idx; + + /* Rounds per test case */ + uint32_t rounds; + +} appl_args_t; + +/* Initialize benchmark resources */ +typedef void (*bench_init_fn_t)(void); + +/* Run benchmark, returns >0 on success */ +typedef int (*bench_run_fn_t)(void); + +/* Benchmark data */ +typedef struct { + /* Default test name */ + const char *name; + + /* Test function to run */ + bench_run_fn_t run; + + /* Test init function */ + bench_init_fn_t init; + + /* Test specific limit for rounds (tuning for slow implementation) */ + uint32_t max_rounds; + + /* Override default test name */ + const char *desc; + +} bench_info_t; + +/* Global data */ +typedef struct { + appl_args_t appl; + + /* Benchmark functions */ + bench_info_t *bench; + + /* Number of benchmark functions */ + int num_bench; + + /* Break worker loop if set to 1 */ + odp_atomic_u32_t exit_thread; + + /* Test case input / output data */ + odp_time_t t1[REPEAT_COUNT]; + odp_time_t t2[REPEAT_COUNT]; + odp_time_t t3[REPEAT_COUNT]; + uint64_t a1[REPEAT_COUNT]; + uint64_t a2[REPEAT_COUNT]; + uint32_t b1[REPEAT_COUNT]; + uint32_t b2[REPEAT_COUNT]; + uint16_t c1[REPEAT_COUNT]; + uint16_t c2[REPEAT_COUNT]; + + /* Dummy result */ + uint64_t dummy; + + /* Benchmark run failed */ + int bench_failed; + + /* CPU mask as string */ + char cpumask_str[ODP_CPUMASK_STR_SIZE]; + +} gbl_args_t; + +static gbl_args_t *gbl_args; + +static void sig_handler(int signo ODP_UNUSED) +{ + if (gbl_args == NULL) + return; + odp_atomic_store_u32(&gbl_args->exit_thread, 1); +} + +static int setup_sig_handler(void) +{ + struct sigaction action; + + memset(&action, 0, sizeof(action)); + action.sa_handler = sig_handler; + + /* No additional signals blocked. By default, the signal which triggered + * the handler is blocked. */ + if (sigemptyset(&action.sa_mask)) + return -1; + + if (sigaction(SIGINT, &action, NULL)) + return -1; + + return 0; +} + +/* Run given benchmark indefinitely */ +static void run_indef(gbl_args_t *args, int idx) +{ + const char *desc; + const bench_info_t *bench = &args->bench[idx]; + + desc = bench->desc != NULL ? bench->desc : bench->name; + + printf("Running odp_%s test indefinitely\n", desc); + + while (!odp_atomic_load_u32(&gbl_args->exit_thread)) { + int ret; + + if (bench->init != NULL) + bench->init(); + + ret = bench->run(); + + if (!ret) + ODPH_ABORT("Benchmark %s failed\n", desc); + } +} + +static int run_benchmarks(void *arg) +{ + int i, j; + uint64_t c1, c2; + odp_time_t t1, t2; + gbl_args_t *args = arg; + const int meas_time = args->appl.time; + + printf("\nAverage %s per function call\n", meas_time ? "time (nsec)" : "CPU cycles"); + printf("-------------------------------------------------\n"); + + /* Run each test twice. Results from the first warm-up round are ignored. */ + for (i = 0; i < 2; i++) { + uint64_t total = 0; + uint32_t round = 1; + + for (j = 0; j < gbl_args->num_bench; round++) { + int ret; + const char *desc; + const bench_info_t *bench = &args->bench[j]; + uint32_t max_rounds = args->appl.rounds; + + if (bench->max_rounds && max_rounds > bench->max_rounds) + max_rounds = bench->max_rounds; + + /* Run selected test indefinitely */ + if (args->appl.bench_idx) { + if ((j + 1) != args->appl.bench_idx) { + j++; + continue; + } + + run_indef(args, j); + return 0; + } + + desc = bench->desc != NULL ? bench->desc : bench->name; + + if (bench->init != NULL) + bench->init(); + + if (meas_time) + t1 = odp_time_local(); + else + c1 = odp_cpu_cycles(); + + ret = bench->run(); + + if (meas_time) + t2 = odp_time_local(); + else + c2 = odp_cpu_cycles(); + + if (!ret) { + ODPH_ERR("Benchmark odp_%s failed\n", desc); + args->bench_failed = -1; + return -1; + } + + if (meas_time) + total += odp_time_diff_ns(t2, t1); + else + total += odp_cpu_cycles_diff(c2, c1); + + if (round >= max_rounds) { + double result; + + /* Each benchmark runs internally REPEAT_COUNT times. */ + result = ((double)total) / (max_rounds * REPEAT_COUNT); + + /* No print from warm-up round */ + if (i > 0) + printf("[%02d] odp_%-26s: %12.2f\n", j + 1, desc, result); + + j++; + total = 0; + round = 1; + } + } + } + + /* Print dummy result to prevent compiler to optimize it away*/ + printf("\n(dummy result: 0x%" PRIx64 ")\n", args->dummy); + + printf("\n"); + + return 0; +} + +static void init_time_global(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + odp_time_t *t2 = gbl_args->t2; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_global(); + + for (i = 0; i < REPEAT_COUNT; i++) + t2[i] = odp_time_global(); + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_global_ns(); +} + +static void init_time_local(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + odp_time_t *t2 = gbl_args->t2; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_local(); + + for (i = 0; i < REPEAT_COUNT; i++) + t2[i] = odp_time_local(); + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_local_ns(); +} + +static void init_cpu_cycles(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + uint64_t *a2 = gbl_args->a2; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_cpu_cycles(); + + for (i = 0; i < REPEAT_COUNT; i++) + a2[i] = odp_cpu_cycles(); +} + +static int time_local(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_local(); + + return i; +} + +static int time_local_strict(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_local_strict(); + + return i; +} + +static int time_local_ns(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_local_ns(); + + return i; +} + +static int time_local_strict_ns(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_local_strict_ns(); + + return i; +} + +static int time_global(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_global(); + + return i; +} + +static int time_global_strict(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_global_strict(); + + return i; +} + +static int time_global_ns(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_global_ns(); + + return i; +} + +static int time_global_strict_ns(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_global_strict_ns(); + + return i; +} + +static int time_diff(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + odp_time_t *t2 = gbl_args->t2; + odp_time_t *t3 = gbl_args->t3; + + for (i = 0; i < REPEAT_COUNT; i++) + t3[i] = odp_time_diff(t2[i], t1[i]); + + return i; +} + +static int time_diff_ns(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + odp_time_t *t2 = gbl_args->t2; + uint64_t res = 0; + + for (i = 0; i < REPEAT_COUNT; i++) + res += odp_time_diff_ns(t2[i], t1[i]); + + gbl_args->dummy += res; + + return i; +} + +static int time_sum(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + odp_time_t *t2 = gbl_args->t2; + odp_time_t *t3 = gbl_args->t3; + + for (i = 0; i < REPEAT_COUNT; i++) + t3[i] = odp_time_sum(t1[i], t2[i]); + + return i; +} + +static int time_to_ns(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + uint64_t res = 0; + + for (i = 0; i < REPEAT_COUNT; i++) + res += odp_time_to_ns(t1[i]); + + gbl_args->dummy += res; + + return i; +} + +static int time_local_from_ns(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_local_from_ns(a1[i]); + + return i; +} + +static int time_global_from_ns(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + t1[i] = odp_time_global_from_ns(a1[i]); + + return i; +} + +static int time_cmp(void) +{ + int i; + odp_time_t *t1 = gbl_args->t1; + odp_time_t *t2 = gbl_args->t2; + int res = 0; + + for (i = 0; i < REPEAT_COUNT; i++) + res += odp_time_cmp(t1[i], t2[i]); + + gbl_args->dummy += res; + + return i; +} + +static int time_local_res(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_local_res(); + + return i; +} + +static int time_global_res(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_time_global_res(); + + return i; +} + +static int cpu_id(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_cpu_id(); + + return i; +} + +static int cpu_count(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_cpu_count(); + + return i; +} + +static int cpu_hz(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_cpu_hz(); + + return i; +} + +static int cpu_hz_max(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_cpu_hz_max(); + + return i; +} + +static int cpu_cycles(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_cpu_cycles(); + + return i; +} + +static int cpu_cycles_diff(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + uint64_t *a2 = gbl_args->a2; + uint64_t res = 0; + + for (i = 0; i < REPEAT_COUNT; i++) + res += odp_cpu_cycles_diff(a2[i], a1[i]); + + gbl_args->dummy += res; + + return i; +} + +static int cpu_cycles_max(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_cpu_cycles_max(); + + return i; +} + +static int cpu_pause(void) +{ + int i; + + for (i = 0; i < REPEAT_COUNT; i++) + odp_cpu_pause(); + + return i; +} + +static int thread_id(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_thread_id(); + + return i; +} + +static int thread_count(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_thread_count(); + + return i; +} + +static int thread_count_max(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = odp_thread_count_max(); + + return i; +} + +static int thread_type(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + + for (i = 0; i < REPEAT_COUNT; i++) + a1[i] = (int)odp_thread_type(); + + return i; +} + +static int be_to_cpu_64(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + uint64_t *a2 = gbl_args->a2; + + for (i = 0; i < REPEAT_COUNT; i++) + a2[i] = odp_be_to_cpu_64(a1[i]); + + return i; +} + +static int be_to_cpu_32(void) +{ + int i; + uint32_t *b1 = gbl_args->b1; + uint32_t *b2 = gbl_args->b2; + + for (i = 0; i < REPEAT_COUNT; i++) + b2[i] = odp_be_to_cpu_32(b1[i]); + + return i; +} + +static int be_to_cpu_16(void) +{ + int i; + uint16_t *c1 = gbl_args->c1; + uint16_t *c2 = gbl_args->c2; + + for (i = 0; i < REPEAT_COUNT; i++) + c2[i] = odp_be_to_cpu_16(c1[i]); + + return i; +} + +static int cpu_to_be_64(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + uint64_t *a2 = gbl_args->a2; + + for (i = 0; i < REPEAT_COUNT; i++) + a2[i] = odp_cpu_to_be_64(a1[i]); + + return i; +} + +static int cpu_to_be_32(void) +{ + int i; + uint32_t *b1 = gbl_args->b1; + uint32_t *b2 = gbl_args->b2; + + for (i = 0; i < REPEAT_COUNT; i++) + b2[i] = odp_cpu_to_be_32(b1[i]); + + return i; +} + +static int cpu_to_be_16(void) +{ + int i; + uint16_t *c1 = gbl_args->c1; + uint16_t *c2 = gbl_args->c2; + + for (i = 0; i < REPEAT_COUNT; i++) + c2[i] = odp_cpu_to_be_16(c1[i]); + + return i; +} + +static int le_to_cpu_64(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + uint64_t *a2 = gbl_args->a2; + + for (i = 0; i < REPEAT_COUNT; i++) + a2[i] = odp_le_to_cpu_64(a1[i]); + + return i; +} + +static int le_to_cpu_32(void) +{ + int i; + uint32_t *b1 = gbl_args->b1; + uint32_t *b2 = gbl_args->b2; + + for (i = 0; i < REPEAT_COUNT; i++) + b2[i] = odp_le_to_cpu_32(b1[i]); + + return i; +} + +static int le_to_cpu_16(void) +{ + int i; + uint16_t *c1 = gbl_args->c1; + uint16_t *c2 = gbl_args->c2; + + for (i = 0; i < REPEAT_COUNT; i++) + c2[i] = odp_le_to_cpu_16(c1[i]); + + return i; +} + +static int cpu_to_le_64(void) +{ + int i; + uint64_t *a1 = gbl_args->a1; + uint64_t *a2 = gbl_args->a2; + + for (i = 0; i < REPEAT_COUNT; i++) + a2[i] = odp_cpu_to_le_64(a1[i]); + + return i; +} + +static int cpu_to_le_32(void) +{ + int i; + uint32_t *b1 = gbl_args->b1; + uint32_t *b2 = gbl_args->b2; + + for (i = 0; i < REPEAT_COUNT; i++) + b2[i] = odp_cpu_to_le_32(b1[i]); + + return i; +} + +static int cpu_to_le_16(void) +{ + int i; + uint16_t *c1 = gbl_args->c1; + uint16_t *c2 = gbl_args->c2; + + for (i = 0; i < REPEAT_COUNT; i++) + c2[i] = odp_cpu_to_le_16(c1[i]); + + return i; +} + +static int mb_release(void) +{ + int i; + + for (i = 0; i < REPEAT_COUNT; i++) + odp_mb_release(); + + return i; +} + +static int mb_acquire(void) +{ + int i; + + for (i = 0; i < REPEAT_COUNT; i++) + odp_mb_acquire(); + + return i; +} + +static int mb_full(void) +{ + int i; + + for (i = 0; i < REPEAT_COUNT; i++) + odp_mb_full(); + + return i; +} + +bench_info_t test_suite[] = { + BENCH_INFO(time_local, NULL, 0, NULL), + BENCH_INFO(time_local_strict, NULL, 0, NULL), + BENCH_INFO(time_local_ns, NULL, 0, NULL), + BENCH_INFO(time_local_strict_ns, NULL, 0, NULL), + BENCH_INFO(time_global, NULL, 0, NULL), + BENCH_INFO(time_global_strict, NULL, 0, NULL), + BENCH_INFO(time_global_ns, NULL, 0, NULL), + BENCH_INFO(time_global_strict_ns, NULL, 0, NULL), + BENCH_INFO(time_diff, init_time_global, 0, "time_diff (global)"), + BENCH_INFO(time_diff, init_time_local, 0, "time_diff (local)"), + BENCH_INFO(time_diff_ns, init_time_global, 0, NULL), + BENCH_INFO(time_sum, init_time_global, 0, NULL), + BENCH_INFO(time_to_ns, init_time_global, 0, NULL), + BENCH_INFO(time_local_from_ns, init_time_global, 0, NULL), + BENCH_INFO(time_global_from_ns, init_time_global, 0, NULL), + BENCH_INFO(time_cmp, init_time_global, 0, NULL), + BENCH_INFO(time_local_res, NULL, 0, NULL), + BENCH_INFO(time_global_res, NULL, 0, NULL), + BENCH_INFO(cpu_id, NULL, 0, NULL), + BENCH_INFO(cpu_count, NULL, 0, NULL), + BENCH_INFO(cpu_hz, NULL, 1, NULL), + BENCH_INFO(cpu_hz_max, NULL, 0, NULL), + BENCH_INFO(cpu_cycles, NULL, 0, NULL), + BENCH_INFO(cpu_cycles_diff, init_cpu_cycles, 0, NULL), + BENCH_INFO(cpu_cycles_max, NULL, 0, NULL), + BENCH_INFO(cpu_pause, NULL, 0, NULL), + BENCH_INFO(thread_id, NULL, 0, NULL), + BENCH_INFO(thread_count, NULL, 0, NULL), + BENCH_INFO(thread_count_max, NULL, 0, NULL), + BENCH_INFO(thread_type, NULL, 0, NULL), + BENCH_INFO(be_to_cpu_64, NULL, 0, NULL), + BENCH_INFO(be_to_cpu_32, NULL, 0, NULL), + BENCH_INFO(be_to_cpu_16, NULL, 0, NULL), + BENCH_INFO(cpu_to_be_64, NULL, 0, NULL), + BENCH_INFO(cpu_to_be_32, NULL, 0, NULL), + BENCH_INFO(cpu_to_be_16, NULL, 0, NULL), + BENCH_INFO(le_to_cpu_64, NULL, 0, NULL), + BENCH_INFO(le_to_cpu_32, NULL, 0, NULL), + BENCH_INFO(le_to_cpu_16, NULL, 0, NULL), + BENCH_INFO(cpu_to_le_64, NULL, 0, NULL), + BENCH_INFO(cpu_to_le_32, NULL, 0, NULL), + BENCH_INFO(cpu_to_le_16, NULL, 0, NULL), + BENCH_INFO(mb_release, NULL, 0, NULL), + BENCH_INFO(mb_acquire, NULL, 0, NULL), + BENCH_INFO(mb_full, NULL, 0, NULL), +}; + +/* Print usage information */ +static void usage(void) +{ + printf("\n" + "ODP miscellaneous API micro benchmarks\n" + "\n" + "Options:\n" + " -t, --time <opt> Time measurement. 0: measure CPU cycles (default), 1: measure time\n" + " -i, --index <idx> Benchmark index to run indefinitely.\n" + " -r, --rounds <num> Run each test case 'num' times (default %u).\n" + " -h, --help Display help and exit.\n\n" + "\n", ROUNDS); +} + +/* Parse command line arguments */ +static int parse_args(int argc, char *argv[]) +{ + int opt; + int long_index; + appl_args_t *appl_args = &gbl_args->appl; + static const struct option longopts[] = { + {"time", required_argument, NULL, 't'}, + {"index", required_argument, NULL, 'i'}, + {"rounds", required_argument, NULL, 'r'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + static const char *shortopts = "t:i:r:h"; + + appl_args->time = 0; /* Measure CPU cycles */ + appl_args->bench_idx = 0; /* Run all benchmarks */ + appl_args->rounds = ROUNDS; + + while (1) { + opt = getopt_long(argc, argv, shortopts, longopts, &long_index); + + if (opt == -1) + break; /* No more options */ + + switch (opt) { + case 't': + appl_args->time = atoi(optarg); + break; + case 'i': + appl_args->bench_idx = atoi(optarg); + break; + case 'r': + appl_args->rounds = atoi(optarg); + break; + case 'h': + usage(); + return 1; + default: + ODPH_ERR("Bad option. Use -h for help.\n"); + return -1; + } + } + + if (appl_args->rounds < 1) { + ODPH_ERR("Invalid test cycle repeat count: %u\n", appl_args->rounds); + return -1; + } + + if (appl_args->bench_idx < 0 || appl_args->bench_idx > gbl_args->num_bench) { + ODPH_ERR("Bad bench index %i\n", appl_args->bench_idx); + return -1; + } + + optind = 1; /* Reset 'extern optind' from the getopt lib */ + + return 0; +} + +/* Print system and application info */ +static void print_info(void) +{ + odp_sys_info_print(); + + printf("\n" + "odp_bench_misc options\n" + "----------------------\n"); + + printf("CPU mask: %s\n", gbl_args->cpumask_str); + printf("Measurement unit: %s\n", gbl_args->appl.time ? "nsec" : "CPU cycles"); + printf("Test rounds: %u\n", gbl_args->appl.rounds); + printf("\n"); +} + +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, i; + odp_shm_t shm; + odp_cpumask_t cpumask, default_mask; + odp_instance_t instance; + odp_init_t init_param; + int ret = 0; + + /* Let helper collect its own arguments (e.g. --odph_proc) */ + argc = odph_parse_options(argc, argv); + if (odph_options(&helper_options)) { + ODPH_ERR("Reading ODP helper options failed\n"); + exit(EXIT_FAILURE); + } + + 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("Global init failed\n"); + exit(EXIT_FAILURE); + } + + /* Init this thread */ + if (odp_init_local(instance, ODP_THREAD_CONTROL)) { + ODPH_ERR("Local init failed\n"); + exit(EXIT_FAILURE); + } + + if (setup_sig_handler()) { + ODPH_ERR("Signal handler setup failed\n"); + exit(EXIT_FAILURE); + } + + /* Reserve memory for args from shared mem */ + shm = odp_shm_reserve("shm_args", sizeof(gbl_args_t), ODP_CACHE_LINE_SIZE, 0); + if (shm == ODP_SHM_INVALID) { + ODPH_ERR("Shared mem reserve failed\n"); + exit(EXIT_FAILURE); + } + + gbl_args = odp_shm_addr(shm); + if (gbl_args == NULL) { + ODPH_ERR("Shared mem alloc failed\n"); + exit(EXIT_FAILURE); + } + + memset(gbl_args, 0, sizeof(gbl_args_t)); + odp_atomic_init_u32(&gbl_args->exit_thread, 0); + + gbl_args->bench = test_suite; + gbl_args->num_bench = sizeof(test_suite) / sizeof(test_suite[0]); + + for (i = 0; i < REPEAT_COUNT; i++) { + gbl_args->t1[i] = ODP_TIME_NULL; + gbl_args->t2[i] = ODP_TIME_NULL; + gbl_args->t3[i] = ODP_TIME_NULL; + gbl_args->a1[i] = i; + gbl_args->a2[i] = i; + gbl_args->b1[i] = i; + gbl_args->b2[i] = i; + gbl_args->c1[i] = i; + gbl_args->c2[i] = i; + } + + /* Parse and store the application arguments */ + ret = parse_args(argc, argv); + if (ret) + goto exit; + + /* Get default worker cpumask */ + if (odp_cpumask_default_worker(&default_mask, 1) != 1) { + ODPH_ERR("Unable to allocate worker thread\n"); + ret = -1; + goto exit; + } + + (void)odp_cpumask_to_str(&default_mask, gbl_args->cpumask_str, + sizeof(gbl_args->cpumask_str)); + + print_info(); + + memset(&worker_thread, 0, sizeof(odph_thread_t)); + + /* Create worker thread */ + cpu = odp_cpumask_first(&default_mask); + + odp_cpumask_zero(&cpumask); + odp_cpumask_set(&cpumask, cpu); + + odph_thread_common_param_init(&thr_common); + thr_common.instance = instance; + thr_common.cpumask = &cpumask; + thr_common.share_param = 1; + + odph_thread_param_init(&thr_param); + thr_param.start = run_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->bench_failed; + +exit: + if (odp_shm_free(shm)) { + ODPH_ERR("Shared mem free failed\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_local()) { + ODPH_ERR("Local term failed\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_global(instance)) { + ODPH_ERR("Global term failed\n"); + exit(EXIT_FAILURE); + } + + if (ret < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/test/performance/odp_bench_packet.c b/test/performance/odp_bench_packet.c index b44e92b72..aaf725b57 100644 --- a/test/performance/odp_bench_packet.c +++ b/test/performance/odp_bench_packet.c @@ -275,7 +275,7 @@ static int run_benchmarks(void *arg) printf("odp_%-26s: %8.1f\n", desc, cycles); j++; - k = 0; + k = 1; tot_cycles = 0; } } diff --git a/test/performance/odp_crypto.c b/test/performance/odp_crypto.c index b381fde31..2f79ae644 100644 --- a/test/performance/odp_crypto.c +++ b/test/performance/odp_crypto.c @@ -810,6 +810,8 @@ run_measure_one(crypto_args_t *cargs, } packets_sent += rc; } else { + odp_crypto_packet_result_t result; + rc = odp_crypto_op(&pkt, &out_pkt, ¶ms, 1); if (rc <= 0) { @@ -820,6 +822,12 @@ run_measure_one(crypto_args_t *cargs, } packets_sent += rc; packets_received++; + if (odp_unlikely(odp_crypto_result(&result, out_pkt) != 0) || + odp_unlikely(!result.ok)) { + ODPH_ERR("Crypto operation failed\n"); + odp_packet_free(out_pkt); + return -1; + } if (cargs->debug_packets) { mem = odp_packet_data(out_pkt); print_mem("Immediately encrypted " @@ -849,8 +857,12 @@ run_measure_one(crypto_args_t *cargs, while (ev != ODP_EVENT_INVALID) { out_pkt = odp_crypto_packet_from_event(ev); - odp_crypto_result(&result, out_pkt); - + if (odp_unlikely(odp_crypto_result(&result, out_pkt) != 0) || + odp_unlikely(!result.ok)) { + ODPH_ERR("Crypto operation failed\n"); + odp_packet_free(out_pkt); + return -1; + } if (cargs->debug_packets) { mem = odp_packet_data(out_pkt); print_mem("Received encrypted packet", diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c index c464ba0d7..50e26b1c9 100644 --- a/test/performance/odp_ipsec.c +++ b/test/performance/odp_ipsec.c @@ -862,7 +862,7 @@ run_measure_one_async(ipsec_args_t *cargs, packets_sent += rc; } else { odp_packet_t pkt_out[max_in_flight]; - uint32_t i = 0; + int i = 0; /* * Dequeue packets until we can enqueue the next burst @@ -895,7 +895,7 @@ run_measure_one_async(ipsec_args_t *cargs, } debug_packets(debug, pkt_out, i); - if (i) + if (i > 0) odp_packet_free_sp(pkt_out, i); } } diff --git a/test/performance/odp_sched_perf.c b/test/performance/odp_sched_perf.c index cd1afdf60..a97686c12 100644 --- a/test/performance/odp_sched_perf.c +++ b/test/performance/odp_sched_perf.c @@ -1375,6 +1375,9 @@ int main(int argc, char **argv) if (create_queues(global)) return -1; + if (global->test_options.verbose) + odp_shm_print_all(); + /* Start workers */ start_workers(global, instance); diff --git a/test/performance/odp_sched_pktio.c b/test/performance/odp_sched_pktio.c index 11be9d367..5cc07d010 100644 --- a/test/performance/odp_sched_pktio.c +++ b/test/performance/odp_sched_pktio.c @@ -173,7 +173,7 @@ static inline void send_packets(test_global_t *test_global, drop = num_pkt - sent; - if (odp_unlikely(drop)) + if (odp_unlikely(drop > 0)) odp_packet_free_multi(&pkt[sent], drop); if (odp_unlikely(test_global->opt.collect_stat)) { @@ -425,6 +425,7 @@ static int worker_thread_timers(void *arg) pktin_queue_context_t *queue_context; odp_timer_t timer; odp_timer_set_t ret; + odp_timer_start_t start_param; worker_arg_t *worker_arg = arg; test_global_t *test_global = worker_arg->test_global_ptr; int worker_id = worker_arg->worker_id; @@ -460,12 +461,17 @@ static int worker_thread_timers(void *arg) src_pktio = queue_context->src_pktio; src_queue = queue_context->src_queue; timer = test_global->timer.timer[src_pktio][src_queue]; + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = tick; + start_param.tmo_ev = ODP_EVENT_INVALID; for (i = 0; i < num; i++) { if (odp_unlikely(odp_event_type(ev[i]) == ODP_EVENT_TIMEOUT)) { tmos++; - ret = odp_timer_set_rel(timer, tick, &ev[i]); + + start_param.tmo_ev = ev[i]; + ret = odp_timer_start(timer, &start_param); if (odp_unlikely(ret != ODP_TIMER_SUCCESS)) { /* Should never happen. Timeout event @@ -487,7 +493,7 @@ static int worker_thread_timers(void *arg) if (tmos == 0) { /* Reset timer with existing timeout event */ - ret = odp_timer_set_rel(timer, tick, NULL); + ret = odp_timer_restart(timer, &start_param); if (odp_unlikely(ret != ODP_TIMER_SUCCESS && ret != ODP_TIMER_FAIL)) { @@ -1318,10 +1324,10 @@ static int create_timers(test_global_t *test_global) static int start_timers(test_global_t *test_global) { int i, j; - odp_event_t event; odp_timeout_t timeout; odp_timer_t timer; odp_timer_set_t ret; + odp_timer_start_t start_param; uint64_t timeout_tick = test_global->timer.timeout_tick; int num_pktio = test_global->opt.num_pktio; int num_queue = test_global->opt.num_pktio_queue; @@ -1335,6 +1341,9 @@ static int start_timers(test_global_t *test_global) timeout_tick += odp_timer_ns_to_tick(test_global->timer.timer_pool, TIMEOUT_OFFSET_NS); + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = timeout_tick; + for (i = 0; i < num_pktio; i++) { for (j = 0; j < num_queue; j++) { timer = test_global->timer.timer[i][j]; @@ -1345,10 +1354,9 @@ static int start_timers(test_global_t *test_global) return -1; } - event = odp_timeout_to_event(timeout); - - ret = odp_timer_set_rel(timer, timeout_tick, &event); + start_param.tmo_ev = odp_timeout_to_event(timeout); + ret = odp_timer_start(timer, &start_param); if (ret != ODP_TIMER_SUCCESS) { printf("Timer set failed\n"); return -1; diff --git a/test/performance/odp_timer_perf.c b/test/performance/odp_timer_perf.c index 998db628e..ccea30a14 100644 --- a/test/performance/odp_timer_perf.c +++ b/test/performance/odp_timer_perf.c @@ -438,6 +438,7 @@ static int set_timers(test_global_t *global) odp_event_t ev; int status; timer_ctx_t *ctx = &global->timer_ctx[i][j]; + odp_timer_start_t start_param; /* Set timers backwards, the last timer is set first */ if (j == 0) @@ -456,9 +457,11 @@ static int set_timers(test_global_t *global) tick_ns = odp_timer_ns_to_tick(tp, nsec); nsec = nsec - period_ns; - status = odp_timer_set_abs(timer, tick_cur + tick_ns, - &ev); + start_param.tick_type = ODP_TIMER_TICK_ABS; + start_param.tick = tick_cur + tick_ns; + start_param.tmo_ev = ev; + status = odp_timer_start(timer, &start_param); if (status != ODP_TIMER_SUCCESS) { ODPH_ERR("Timer set %i/%i (ret %i)\n", i, j, status); return -1; @@ -656,6 +659,7 @@ static int set_cancel_mode_worker(void *arg) odp_timer_t timer; odp_timer_pool_t tp; odp_timeout_t tmo; + odp_timer_start_t start_param; thread_arg_t *thread_arg = arg; test_global_t *global = thread_arg->global; test_options_t *test_options = &global->test_options; @@ -694,7 +698,11 @@ static int set_cancel_mode_worker(void *arg) period_tick = global->timer_pool[i].period_tick; tick = start_tick + j * period_tick; - status = odp_timer_set_rel(timer, tick, &ev); + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = tick; + start_param.tmo_ev = ev; + + status = odp_timer_start(timer, &start_param); num_tmo++; num_set++; @@ -746,7 +754,11 @@ static int set_cancel_mode_worker(void *arg) if (status < 0) continue; - status = odp_timer_set_abs(timer, tick + j * period_tick, &ev); + start_param.tick_type = ODP_TIMER_TICK_ABS; + start_param.tick = tick + j * period_tick; + start_param.tmo_ev = ev; + + status = odp_timer_start(timer, &start_param); num_set++; if (status != ODP_TIMER_SUCCESS) { diff --git a/test/validation/api/classification/odp_classification_common.c b/test/validation/api/classification/odp_classification_common.c index 4c24099a5..fe7677044 100644 --- a/test/validation/api/classification/odp_classification_common.c +++ b/test/validation/api/classification/odp_classification_common.c @@ -399,10 +399,10 @@ odp_packet_t create_packet(cls_packet_info_t pkt_info) vlan_hdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN); vlan_hdr++; } else { + odp_packet_has_vlan_set(pkt, 1); ethhdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN); } /* Default vlan header */ - odp_packet_has_vlan_set(pkt, 1); vlan_hdr->tci = odp_cpu_to_be_16(0); vlan_hdr->type = odp_cpu_to_be_16(eth_type); } else { diff --git a/test/validation/api/crypto/Makefile.am b/test/validation/api/crypto/Makefile.am index cc4d49d60..e438ec8ca 100644 --- a/test/validation/api/crypto/Makefile.am +++ b/test/validation/api/crypto/Makefile.am @@ -5,3 +5,4 @@ crypto_main_SOURCES = \ odp_crypto_test_inp.c \ test_vectors.h \ test_vectors_len.h +PRELDADD += $(LIBPACKET_COMMON) diff --git a/test/validation/api/crypto/odp_crypto_test_inp.c b/test/validation/api/crypto/odp_crypto_test_inp.c index 10f1b5ee2..7d5e50c71 100644 --- a/test/validation/api/crypto/odp_crypto_test_inp.c +++ b/test/validation/api/crypto/odp_crypto_test_inp.c @@ -1,17 +1,20 @@ /* Copyright (c) 2014-2018, Linaro Limited - * Copyright (c) 2021-2022, Nokia + * Copyright (c) 2021-2023, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include <string.h> #include <odp_api.h> #include <odp/helper/odph_api.h> #include <odp_cunit_common.h> +#include <packet_common.h> #include "test_vectors.h" #define PKT_POOL_NUM 64 #define PKT_POOL_LEN (1 * 1024) +#define UAREA_SIZE 8 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) @@ -35,6 +38,7 @@ static void test_defaults(uint8_t fill) odp_crypto_session_param_init(¶m); CU_ASSERT_EQUAL(param.op, ODP_CRYPTO_OP_ENCODE); + CU_ASSERT_EQUAL(param.op_type, ODP_CRYPTO_OP_TYPE_LEGACY); CU_ASSERT_EQUAL(param.auth_cipher_text, false); #if ODP_DEPRECATED_API CU_ASSERT_EQUAL(param.pref_mode, ODP_CRYPTO_SYNC); @@ -45,13 +49,6 @@ static void test_defaults(uint8_t fill) CU_ASSERT_EQUAL(param.auth_alg, ODP_AUTH_ALG_NULL); CU_ASSERT_EQUAL(param.auth_iv_len, 0); CU_ASSERT_EQUAL(param.auth_aad_len, 0); - -#if ODP_DEPRECATED_API - CU_ASSERT_EQUAL(param.cipher_iv.data, NULL); - CU_ASSERT_EQUAL(param.cipher_iv.length, 0); - CU_ASSERT_EQUAL(param.auth_iv.data, NULL); - CU_ASSERT_EQUAL(param.auth_iv.length, 0); -#endif } static void test_default_values(void) @@ -60,53 +57,6 @@ static void test_default_values(void) test_defaults(0xff); } -static int packet_cmp_mem_bits(odp_packet_t pkt, uint32_t offset, - uint8_t *s, uint32_t len) -{ - int rc = -1; - uint32_t len_bytes = ((len + 7) / 8); - uint8_t leftover_bits = len % 8; - uint8_t buf[len_bytes]; - - odp_packet_copy_to_mem(pkt, offset, len_bytes, buf); - - /* Compare till the last full byte */ - rc = memcmp(buf, s, leftover_bits ? len_bytes - 1 : len_bytes); - - if (rc == 0 && leftover_bits) { - /* Do masked comparison for the leftover bits */ - uint8_t mask = 0xff << (8 - leftover_bits); - - rc = !((mask & buf[len_bytes - 1]) == - (mask & s[len_bytes - 1])); - } - - return rc; -} - -static int packet_cmp_mem_bytes(odp_packet_t pkt, uint32_t offset, - uint8_t *s, uint32_t len) -{ - uint8_t buf[len]; - - odp_packet_copy_to_mem(pkt, offset, len, buf); - - return memcmp(buf, s, len); -} - -static int packet_cmp_mem(odp_packet_t pkt, uint32_t offset, - uint8_t *s, uint32_t len, odp_bool_t bit_mode) -{ - int rc = -1; - - if (bit_mode) - rc = packet_cmp_mem_bits(pkt, offset, s, len); - else - rc = packet_cmp_mem_bytes(pkt, offset, s, len); - - return rc; -} - static const char *auth_alg_name(odp_auth_alg_t auth) { switch (auth) { @@ -283,9 +233,12 @@ static int alg_op(odp_packet_t pkt, } #endif -static int alg_packet_op(odp_packet_t pkt, +static int alg_packet_op(odp_packet_t pkt_in, + odp_packet_t *pkt_out, odp_bool_t *ok, odp_crypto_session_t session, + odp_crypto_op_type_t op_type, + int32_t oop_shift, uint8_t *cipher_iv_ptr, uint8_t *auth_iv_ptr, odp_packet_data_range_t *cipher_range, @@ -298,7 +251,13 @@ static int alg_packet_op(odp_packet_t pkt, odp_crypto_packet_result_t result; odp_crypto_packet_op_param_t op_params; odp_event_subtype_t subtype; - odp_packet_t out_pkt = pkt; + odp_packet_t orig_pkt_out; + + if (op_type == ODP_CRYPTO_OP_TYPE_LEGACY) + *pkt_out = pkt_in; + else if (op_type == ODP_CRYPTO_OP_TYPE_BASIC) + *pkt_out = ODP_PACKET_INVALID; + orig_pkt_out = *pkt_out; /* Prepare input/output params */ memset(&op_params, 0, sizeof(op_params)); @@ -306,6 +265,7 @@ static int alg_packet_op(odp_packet_t pkt, op_params.cipher_range = *cipher_range; op_params.auth_range = *auth_range; + op_params.dst_offset_shift = oop_shift; if (cipher_iv_ptr) op_params.cipher_iv_ptr = cipher_iv_ptr; if (auth_iv_ptr) @@ -316,13 +276,18 @@ static int alg_packet_op(odp_packet_t pkt, op_params.hash_result_offset = hash_result_offset; if (suite_context.op_mode == ODP_CRYPTO_SYNC) { - rc = odp_crypto_op(&pkt, &out_pkt, &op_params, 1); + rc = odp_crypto_op(&pkt_in, pkt_out, &op_params, 1); if (rc <= 0) { CU_FAIL("Failed odp_crypto_packet_op()"); return rc; } } else { - rc = odp_crypto_op_enq(&pkt, &pkt, &op_params, 1); + odp_packet_t *out_param = pkt_out; + + if (op_type == ODP_CRYPTO_OP_TYPE_BASIC) + out_param = NULL; + + rc = odp_crypto_op_enq(&pkt_in, out_param, &op_params, 1); if (rc <= 0) { CU_FAIL("Failed odp_crypto_op_enq()"); return rc; @@ -339,33 +304,42 @@ static int alg_packet_op(odp_packet_t pkt, CU_ASSERT(ODP_EVENT_PACKET == odp_event_types(event, &subtype)); CU_ASSERT(ODP_EVENT_PACKET_CRYPTO == subtype); - pkt = odp_crypto_packet_from_event(event); + *pkt_out = odp_crypto_packet_from_event(event); } - CU_ASSERT(out_pkt == pkt); + if (op_type != ODP_CRYPTO_OP_TYPE_BASIC) + CU_ASSERT(*pkt_out == orig_pkt_out); CU_ASSERT(ODP_EVENT_PACKET == - odp_event_type(odp_packet_to_event(pkt))); + odp_event_type(odp_packet_to_event(*pkt_out))); CU_ASSERT(ODP_EVENT_PACKET_CRYPTO == - odp_event_subtype(odp_packet_to_event(pkt))); + odp_event_subtype(odp_packet_to_event(*pkt_out))); CU_ASSERT(ODP_EVENT_PACKET == - odp_event_types(odp_packet_to_event(pkt), &subtype)); + odp_event_types(odp_packet_to_event(*pkt_out), &subtype)); CU_ASSERT(ODP_EVENT_PACKET_CRYPTO == subtype); - CU_ASSERT(odp_packet_subtype(pkt) == ODP_EVENT_PACKET_CRYPTO); + CU_ASSERT(odp_packet_subtype(*pkt_out) == ODP_EVENT_PACKET_CRYPTO); - rc = odp_crypto_result(&result, pkt); + rc = odp_crypto_result(&result, *pkt_out); if (rc < 0) { CU_FAIL("Failed odp_crypto_packet_result()"); return rc; } + CU_ASSERT(rc == 0); + + if (op_type == ODP_CRYPTO_OP_TYPE_OOP && + suite_context.op_mode == ODP_CRYPTO_ASYNC) + CU_ASSERT(result.pkt_in == pkt_in); *ok = result.ok; return 0; } -static int crypto_op(odp_packet_t pkt, +static int crypto_op(odp_packet_t pkt_in, + odp_packet_t *pkt_out, odp_bool_t *ok, odp_crypto_session_t session, + odp_crypto_op_type_t op_type, + int32_t oop_shift, uint8_t *cipher_iv, uint8_t *auth_iv, odp_packet_data_range_t *cipher_range, @@ -375,23 +349,26 @@ static int crypto_op(odp_packet_t pkt, { int rc; - if (!suite_context.packet) + if (!suite_context.packet) { #if ODP_DEPRECATED_API - rc = alg_op(pkt, ok, session, + rc = alg_op(pkt_in, ok, session, cipher_iv, auth_iv, cipher_range, auth_range, aad, hash_result_offset); + *pkt_out = pkt_in; #else rc = -1; #endif - else - rc = alg_packet_op(pkt, ok, session, + } else { + rc = alg_packet_op(pkt_in, pkt_out, ok, session, + op_type, oop_shift, cipher_iv, auth_iv, cipher_range, auth_range, aad, hash_result_offset); + } if (rc < 0) - odp_packet_free(pkt); + odp_packet_free(pkt_in); return rc; } @@ -434,12 +411,8 @@ static void fill_with_pattern(uint8_t *buf, uint32_t len) buf[n] = n; } -/* - * Generate or verify header and trailer bytes - */ -static void do_header_and_trailer(odp_packet_t pkt, - uint32_t header_len, uint32_t trailer_len, - odp_bool_t check) +static void write_header_and_trailer(odp_packet_t pkt, + uint32_t header_len, uint32_t trailer_len) { uint32_t trailer_offset = odp_packet_len(pkt) - trailer_len; uint32_t max_len = header_len > trailer_len ? header_len : trailer_len; @@ -448,172 +421,470 @@ static void do_header_and_trailer(odp_packet_t pkt, fill_with_pattern(buffer, sizeof(buffer)); - if (check) { - CU_ASSERT(!packet_cmp_mem_bytes(pkt, 0, - buffer, header_len)); - CU_ASSERT(!packet_cmp_mem_bytes(pkt, trailer_offset, - buffer, trailer_len)); - } else { - rc = odp_packet_copy_from_mem(pkt, 0, - header_len, buffer); - CU_ASSERT(rc == 0); - rc = odp_packet_copy_from_mem(pkt, trailer_offset, - trailer_len, buffer); - CU_ASSERT(rc == 0); - } + rc = odp_packet_copy_from_mem(pkt, 0, header_len, buffer); + CU_ASSERT(rc == 0); + rc = odp_packet_copy_from_mem(pkt, trailer_offset, trailer_len, buffer); + CU_ASSERT(rc == 0); } -typedef enum crypto_test { - NORMAL_TEST = 0, /**< Plain execution */ - REPEAT_TEST, /**< Rerun without reinitializing the session */ - WRONG_DIGEST_TEST, /**< Check against wrong digest */ - MAX_TEST, /**< Final mark */ -} crypto_test; - typedef struct alg_test_param_t { odp_crypto_session_t session; odp_crypto_op_t op; + odp_crypto_op_type_t op_type; + int32_t oop_shift; odp_cipher_alg_t cipher_alg; odp_auth_alg_t auth_alg; crypto_test_reference_t *ref; uint32_t digest_offset; - odp_bool_t override_iv; odp_bool_t is_bit_mode_cipher; odp_bool_t is_bit_mode_auth; odp_bool_t adjust_segmentation; + odp_bool_t wrong_digest; uint32_t first_seg_len; uint32_t header_len; uint32_t trailer_len; } alg_test_param_t; -static void alg_test_execute(const alg_test_param_t *param) +static void prepare_crypto_ranges(const alg_test_param_t *param, + odp_packet_data_range_t *cipher_range, + odp_packet_data_range_t *auth_range) { - odp_bool_t ok = false; - int iteration; - crypto_test_reference_t *ref = param->ref; - uint32_t reflength = ref_length_in_bytes(ref); odp_packet_data_range_t zero_range = {.offset = 0, .length = 0}; - odp_packet_data_range_t cipher_range; - odp_packet_data_range_t auth_range; - uint8_t *cipher_iv = param->override_iv ? ref->cipher_iv : NULL; - uint8_t *auth_iv = param->override_iv ? ref->auth_iv : NULL; - cipher_range.offset = param->header_len; - cipher_range.length = reflength; - auth_range.offset = param->header_len; - auth_range.length = reflength; + cipher_range->offset = param->header_len; + cipher_range->length = ref_length_in_bytes(param->ref); + auth_range->offset = param->header_len; + auth_range->length = ref_length_in_bytes(param->ref); if (param->is_bit_mode_cipher) { - cipher_range.offset *= 8; - cipher_range.length = ref_length_in_bits(ref); + cipher_range->offset *= 8; + cipher_range->length = ref_length_in_bits(param->ref); } if (param->is_bit_mode_auth) { - auth_range.offset *= 8; - auth_range.length = ref_length_in_bits(ref); + auth_range->offset *= 8; + auth_range->length = ref_length_in_bits(param->ref); } /* * We did not check the bit mode of the null algorithms, so let's * not pass potentially invalid ranges to them. */ if (param->cipher_alg == ODP_CIPHER_ALG_NULL) - cipher_range = zero_range; + *cipher_range = zero_range; if (param->auth_alg == ODP_AUTH_ALG_NULL) - auth_range = zero_range; - for (iteration = NORMAL_TEST; iteration < MAX_TEST; iteration++) { - odp_packet_t pkt; - uint32_t digest_offset = param->digest_offset; - uint32_t pkt_len; + *auth_range = zero_range; +} - /* - * Test detection of wrong digest value in input packet - * only when decoding and using non-null auth algorithm. - */ - if (iteration == WRONG_DIGEST_TEST && - (param->auth_alg == ODP_AUTH_ALG_NULL || - param->op == ODP_CRYPTO_OP_ENCODE)) - continue; +static int prepare_input_packet(const alg_test_param_t *param, + odp_packet_t *pkt_in) +{ + crypto_test_reference_t *ref = param->ref; + uint32_t reflength = ref_length_in_bytes(ref); + odp_packet_t pkt; + uint32_t digest_offset = param->digest_offset; + uint32_t pkt_len; - pkt_len = param->header_len + reflength + param->trailer_len; - if (param->digest_offset == param->header_len + reflength) - pkt_len += ref->digest_length; + pkt_len = param->header_len + reflength + param->trailer_len; + if (param->digest_offset == param->header_len + reflength) + pkt_len += ref->digest_length; - pkt = odp_packet_alloc(suite_context.pool, pkt_len); + pkt = odp_packet_alloc(suite_context.pool, pkt_len); - CU_ASSERT(pkt != ODP_PACKET_INVALID); - if (pkt == ODP_PACKET_INVALID) - continue; + CU_ASSERT(pkt != ODP_PACKET_INVALID); + if (pkt == ODP_PACKET_INVALID) + return -1; - if (param->adjust_segmentation) - adjust_segments(&pkt, param->first_seg_len); - - do_header_and_trailer(pkt, param->header_len, param->trailer_len, false); - - if (param->op == ODP_CRYPTO_OP_ENCODE) { - odp_packet_copy_from_mem(pkt, param->header_len, - reflength, ref->plaintext); - } else { - odp_packet_copy_from_mem(pkt, param->header_len, - reflength, ref->ciphertext); - odp_packet_copy_from_mem(pkt, digest_offset, - ref->digest_length, - ref->digest); - if (iteration == WRONG_DIGEST_TEST) { - uint8_t byte = ~ref->digest[0]; - - odp_packet_copy_from_mem(pkt, digest_offset, - 1, &byte); - } - } + if (param->adjust_segmentation) + adjust_segments(&pkt, param->first_seg_len); - if (crypto_op(pkt, &ok, param->session, - cipher_iv, auth_iv, - &cipher_range, &auth_range, - ref->aad, digest_offset)) - break; + write_header_and_trailer(pkt, param->header_len, param->trailer_len); - if (iteration == WRONG_DIGEST_TEST) { - CU_ASSERT(!ok); - odp_packet_free(pkt); - continue; + if (param->op == ODP_CRYPTO_OP_ENCODE) { + odp_packet_copy_from_mem(pkt, param->header_len, + reflength, ref->plaintext); + } else { + odp_packet_copy_from_mem(pkt, param->header_len, + reflength, ref->ciphertext); + odp_packet_copy_from_mem(pkt, digest_offset, + ref->digest_length, + ref->digest); + if (param->wrong_digest) { + uint8_t byte = ~ref->digest[0]; + + odp_packet_copy_from_mem(pkt, digest_offset, 1, &byte); } + } + *pkt_in = pkt; + return 0; +} - CU_ASSERT(ok); +static void prepare_oop_output_packet(const alg_test_param_t *param, + odp_packet_t *pkt_out, + uint32_t pkt_len) +{ + uint32_t reflength = ref_length_in_bytes(param->ref); + const uint32_t oop_extra_len = 5; + uint32_t trl_len; + uint32_t hdr_len; + uint32_t oop_len; + + oop_len = pkt_len + param->oop_shift + oop_extra_len; + *pkt_out = odp_packet_alloc(suite_context.pool, oop_len); + CU_ASSERT_FATAL(*pkt_out != ODP_PACKET_INVALID); + + uint8_t buf[oop_len]; + + memset(buf, 0x55, sizeof(buf)); + odp_packet_copy_from_mem(*pkt_out, 0, sizeof(buf), buf); + + hdr_len = param->header_len + param->oop_shift; + trl_len = oop_len - hdr_len - reflength; + + write_header_and_trailer(*pkt_out, hdr_len, trl_len); + + /* have different metadata than in the input packet */ + memset(odp_packet_user_area(*pkt_out), 0xab, + odp_packet_user_area_size(*pkt_out)); +} + +static int is_packet_data_equal(odp_packet_t pkt_1, odp_packet_t pkt_2) +{ + uint32_t len = odp_packet_len(pkt_1); + uint8_t buf_1[len]; + uint8_t buf_2[len]; + + if (len != odp_packet_len(pkt_2) || + odp_packet_copy_to_mem(pkt_1, 0, len, buf_1) || + odp_packet_copy_to_mem(pkt_2, 0, len, buf_2)) + return 0; + + return !memcmp(buf_1, buf_2, len); +} + +static int is_in_range(uint32_t offs, uint32_t range_offs, uint32_t range_len) +{ + return offs >= range_offs && offs < range_offs + range_len; +} + +#define MAX_IGNORED_RANGES 3 + +/* + * Output packet parts that we ignore since they have undefined values + */ +typedef struct ignore_t { + uint32_t byte_offset; /* offset to a byte which has bits to be ignored */ + uint32_t byte_mask; /* mask of ignored bits in the byte */ + struct { + uint32_t offset; + uint32_t length; + } ranges[MAX_IGNORED_RANGES]; /* byte ranges to be ignored */ + uint32_t num_ranges; +} ignore_t; + +static void add_ignored_range(ignore_t *ign, uint32_t offs, uint32_t len) +{ + if (len == 0) + return; + CU_ASSERT_FATAL(ign->num_ranges < MAX_IGNORED_RANGES); + ign->ranges[ign->num_ranges].offset = offs; + ign->ranges[ign->num_ranges].length = len; + ign->num_ranges++; +} + +static void clear_ignored_data(const ignore_t *ign, uint8_t *data, uint32_t data_len) +{ + CU_ASSERT_FATAL(ign->byte_offset < data_len); + data[ign->byte_offset] &= ~ign->byte_mask; + + for (uint32_t n = 0; n < ign->num_ranges; n++) { + uint32_t offset = ign->ranges[n].offset; + uint32_t length = ign->ranges[n].length; + + CU_ASSERT(offset + length <= data_len); + memset(data + offset, 0, length); + } +} + +static void prepare_ignore_info(const alg_test_param_t *param, + uint32_t shift, + uint32_t cipher_offset, + uint32_t cipher_len, + uint32_t auth_offset, + uint32_t auth_len, + ignore_t *ignore) +{ + memset(ignore, 0, sizeof(*ignore)); - do_header_and_trailer(pkt, param->header_len, param->trailer_len, true); - - if (param->op == ODP_CRYPTO_OP_ENCODE) { - CU_ASSERT(!packet_cmp_mem(pkt, param->header_len, - ref->ciphertext, - ref->length, - ref->is_length_in_bits)); - CU_ASSERT(!packet_cmp_mem_bytes(pkt, digest_offset, - ref->digest, - ref->digest_length)); - } else { - /* - * Hash result in the packet is left to undefined - * values. Restore it from the plaintext packet - * to make the subsequent comparison work even - * if the hash result is within the auth_range. - */ - odp_packet_copy_from_mem(pkt, digest_offset, - ref->digest_length, - ref->plaintext + - digest_offset - param->header_len); - - CU_ASSERT(!packet_cmp_mem(pkt, param->header_len, - ref->plaintext, - ref->length, - ref->is_length_in_bits)); + /* + * Leftover bits in the last byte of the cipher range of bit mode + * ciphers have undefined values. + */ + if (param->is_bit_mode_cipher && + param->cipher_alg != ODP_CIPHER_ALG_NULL) { + uint8_t leftover_bits = param->ref->length % 8; + + ignore->byte_offset = cipher_offset + cipher_len - 1 + shift; + ignore->byte_mask = ~(0xff << (8 - leftover_bits)); + } + + /* + * In decode sessions the bytes in the hash location have + * undefined values. + */ + if (param->auth_alg != ODP_AUTH_ALG_NULL && + param->op == ODP_CRYPTO_OP_DECODE) { + uint32_t offs = param->digest_offset; + + if (param->op_type != ODP_CRYPTO_OP_TYPE_OOP || + is_in_range(offs, cipher_offset, cipher_len) || + is_in_range(offs, auth_offset, auth_len)) { + add_ignored_range(ignore, + param->digest_offset + shift, + param->ref->digest_length); } + } + + /* Decrypted bytes are undefined if authentication fails. */ + if (param->op == ODP_CRYPTO_OP_DECODE && + param->wrong_digest) { + add_ignored_range(ignore, cipher_offset + shift, cipher_len); + /* In OOP case, auth range may not get copied */ + if (param->op_type == ODP_CRYPTO_OP_TYPE_OOP) + add_ignored_range(ignore, auth_offset + shift, auth_len); + } +} + +/* Add room for bytes that are not included in ref->length */ +#define MAX_EXP_DATA_LEN (MAX_DATA_LEN + 200) + +/* + * Expected packet data + */ +typedef struct expected_t { + uint8_t data[MAX_EXP_DATA_LEN]; + uint32_t len; + ignore_t ignore; +} expected_t; + +static void prepare_expected_data(const alg_test_param_t *param, + const odp_packet_data_range_t *cipher_range, + const odp_packet_data_range_t *auth_range, + odp_packet_t pkt_in, + odp_packet_t pkt_out, + expected_t *ex) +{ + uint32_t digest_offset = param->digest_offset; + uint32_t cipher_offset = cipher_range->offset; + uint32_t cipher_len = cipher_range->length; + uint32_t auth_offset = auth_range->offset; + uint32_t auth_len = auth_range->length; + const int32_t shift = param->op_type == ODP_CRYPTO_OP_TYPE_OOP ? param->oop_shift : 0; + const odp_packet_t base_pkt = param->op_type == ODP_CRYPTO_OP_TYPE_OOP ? pkt_out : pkt_in; + int rc; + + if (param->op == ODP_CRYPTO_OP_ENCODE) + digest_offset += shift; + + if (param->is_bit_mode_cipher) { + cipher_offset /= 8; + cipher_len = (cipher_len + 7) / 8; + } + if (param->is_bit_mode_auth) { + auth_offset /= 8; + auth_len = (auth_len + 7) / 8; + } + if (param->cipher_alg == ODP_CIPHER_ALG_NULL) + cipher_len = 0; + if (param->auth_alg == ODP_AUTH_ALG_NULL || + param->auth_alg == ODP_AUTH_ALG_AES_GCM || + param->auth_alg == ODP_AUTH_ALG_AES_CCM || + param->auth_alg == ODP_AUTH_ALG_CHACHA20_POLY1305) { + /* auth range is ignored with null and AEAD algorithms */ + auth_len = 0; + } + + /* copy all data from base packet */ + ex->len = odp_packet_len(base_pkt); + CU_ASSERT_FATAL(ex->len <= sizeof(ex->data)); + rc = odp_packet_copy_to_mem(base_pkt, 0, ex->len, ex->data); + CU_ASSERT(rc == 0); + + if (param->op_type == ODP_CRYPTO_OP_TYPE_OOP && auth_len > 0) { + /* copy auth range from input packet */ + rc = odp_packet_copy_to_mem(pkt_in, auth_offset, auth_len, + ex->data + auth_offset + shift); + CU_ASSERT(rc == 0); + } + + if (param->op == ODP_CRYPTO_OP_ENCODE) { + /* copy hash first */ + memcpy(ex->data + digest_offset, + param->ref->digest, + param->ref->digest_length); + /* + * Copy ciphertext, possibly overwriting hash. + * The other order (hash overwriting some cipher + * text) does not work in any real use case anyway. + */ + memcpy(ex->data + cipher_offset + shift, + param->ref->ciphertext, + cipher_len); + } else { + memcpy(ex->data + cipher_offset + shift, + param->ref->plaintext, + cipher_len); + } + + prepare_ignore_info(param, shift, + cipher_offset, cipher_len, + auth_offset, auth_len, + &ex->ignore); +} + +static void print_data(const char *title, uint8_t *data, uint32_t len) +{ + static uint64_t limit; + + if (limit++ > 20) + return; + + printf("%s\n", title); + for (uint32_t n = 0; n < len ; n++) { + printf(" %02x", data[n]); + if ((n + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); +} + +static void check_output_packet_data(odp_packet_t pkt, expected_t *ex) +{ + int rc; + uint8_t pkt_data[ex->len]; + + CU_ASSERT(odp_packet_len(pkt) == ex->len); + rc = odp_packet_copy_to_mem(pkt, 0, ex->len, pkt_data); + CU_ASSERT(rc == 0); + + clear_ignored_data(&ex->ignore, pkt_data, sizeof(pkt_data)); + clear_ignored_data(&ex->ignore, ex->data, sizeof(ex->data)); + + if (memcmp(pkt_data, ex->data, ex->len)) { + CU_FAIL("packet data does not match expected data"); + print_data("packet:", pkt_data, ex->len); + print_data("expected:", ex->data, ex->len); + } +} + +static void alg_test_execute(const alg_test_param_t *param) +{ + odp_bool_t ok = false; + odp_packet_data_range_t cipher_range; + odp_packet_data_range_t auth_range; + odp_packet_t pkt; + odp_packet_t pkt_copy = ODP_PACKET_INVALID; + odp_packet_t pkt_out = ODP_PACKET_INVALID; + uint32_t digest_offset = param->digest_offset; + test_packet_md_t md_in, md_out, md_out_orig; + expected_t expected; + + /* + * Test detection of wrong digest value in input packet + * only when decoding and using non-null auth algorithm. + */ + if (param->wrong_digest && + (param->auth_alg == ODP_AUTH_ALG_NULL || + param->op == ODP_CRYPTO_OP_ENCODE)) + return; + + prepare_crypto_ranges(param, &cipher_range, &auth_range); + if (prepare_input_packet(param, &pkt)) + return; + + if (param->op_type == ODP_CRYPTO_OP_TYPE_OOP) { + prepare_oop_output_packet(param, &pkt_out, odp_packet_len(pkt)); + + pkt_copy = odp_packet_copy(pkt, suite_context.pool); + CU_ASSERT_FATAL(pkt_copy != ODP_PACKET_INVALID); + test_packet_get_md(pkt_out, &md_out_orig); + } + + prepare_expected_data(param, &cipher_range, &auth_range, + pkt, pkt_out, &expected); + + if (param->op_type == ODP_CRYPTO_OP_TYPE_OOP && + param->op == ODP_CRYPTO_OP_ENCODE) { + /* + * In this type of sessions digest offset is an offset to the output + * packet, so apply the shift. + */ + digest_offset += param->oop_shift; + } + + test_packet_set_md(pkt); + test_packet_get_md(pkt, &md_in); + + if (crypto_op(pkt, &pkt_out, &ok, param->session, + param->op_type, param->oop_shift, + param->ref->cipher_iv, + param->ref->auth_iv, + &cipher_range, &auth_range, + param->ref->aad, digest_offset)) + return; + + /* + * API is not explicit about whether a failed crypto op + * sets the has_error packet flag or leaves it unchanged. + * Let's allow both behaviours. + */ + test_packet_get_md(pkt_out, &md_out); + if (param->wrong_digest) + md_out.has_error = 0; + + if (param->op_type == ODP_CRYPTO_OP_TYPE_OOP) { + test_packet_md_t md; + + /* check that input packet has not changed */ + CU_ASSERT(is_packet_data_equal(pkt, pkt_copy)); + odp_packet_free(pkt_copy); + test_packet_get_md(pkt, &md); + CU_ASSERT(test_packet_is_md_equal(&md, &md_in)); odp_packet_free(pkt); + + /* check that metadata of output packet has not changed */ + CU_ASSERT(test_packet_is_md_equal(&md_out, &md_out_orig)); + } else { + CU_ASSERT(test_packet_is_md_equal(&md_out, &md_in)); } + + if (param->wrong_digest) { + CU_ASSERT(!ok); + } else { + CU_ASSERT(ok); + } + check_output_packet_data(pkt_out, &expected); + odp_packet_free(pkt_out); } -typedef enum { - PACKET_IV, - OLD_PACKET_IV, - OLD_SESSION_IV, -} iv_test_mode_t; +static void alg_test_op(alg_test_param_t *param) +{ + int32_t oop_shifts[] = {0, 3, 130, -10}; + + for (uint32_t n = 0; n < ARRAY_SIZE(oop_shifts); n++) { + if (oop_shifts[n] != 0 && + param->op_type != ODP_CRYPTO_OP_TYPE_OOP) + continue; + if ((int32_t)param->header_len + oop_shifts[n] < 0) + continue; + param->oop_shift = oop_shifts[n]; + + param->wrong_digest = false; + alg_test_execute(param); + alg_test_execute(param); /* rerun with the same parameters */ + param->wrong_digest = true; + alg_test_execute(param); + } +} + +static int oop_warning_shown; typedef enum { HASH_NO_OVERLAP, @@ -621,10 +892,10 @@ typedef enum { } hash_test_mode_t; static odp_crypto_session_t session_create(odp_crypto_op_t op, + odp_crypto_op_type_t op_type, odp_cipher_alg_t cipher_alg, odp_auth_alg_t auth_alg, crypto_test_reference_t *ref, - iv_test_mode_t iv_mode, hash_test_mode_t hash_mode) { odp_crypto_session_t session = ODP_CRYPTO_SESSION_INVALID; @@ -641,23 +912,6 @@ static odp_crypto_session_t session_create(odp_crypto_op_t op, .data = auth_key_data, .length = ref->auth_key_length }; -#if ODP_DEPRECATED_API - uint8_t cipher_iv_data[ref->cipher_iv_length]; - uint8_t auth_iv_data[ref->auth_iv_length]; - odp_crypto_iv_t cipher_iv = { - .length = ref->cipher_iv_length - }; - odp_crypto_iv_t auth_iv = { - .length = ref->auth_iv_length - }; - - if (iv_mode == OLD_SESSION_IV) { - memcpy(cipher_iv_data, ref->cipher_iv, ref->cipher_iv_length); - memcpy(auth_iv_data, ref->auth_iv, ref->auth_iv_length); - cipher_iv.data = cipher_iv_data; - auth_iv.data = auth_iv_data; - } -#endif memcpy(cipher_key_data, ref->cipher_key, ref->cipher_key_length); memcpy(auth_key_data, ref->auth_key, ref->auth_key_length); @@ -665,6 +919,7 @@ static odp_crypto_session_t session_create(odp_crypto_op_t op, /* Create a crypto session */ odp_crypto_session_param_init(&ses_params); ses_params.op = op; + ses_params.op_type = op_type; ses_params.auth_cipher_text = false; ses_params.op_mode = suite_context.op_mode; #if ODP_DEPRECATED_API @@ -675,15 +930,8 @@ static odp_crypto_session_t session_create(odp_crypto_op_t op, ses_params.compl_queue = suite_context.queue; ses_params.output_pool = suite_context.pool; ses_params.cipher_key = cipher_key; - if (iv_mode == PACKET_IV) { - ses_params.cipher_iv_len = ref->cipher_iv_length; - ses_params.auth_iv_len = ref->auth_iv_length; - } else { -#if ODP_DEPRECATED_API - ses_params.cipher_iv = cipher_iv; - ses_params.auth_iv = auth_iv; -#endif - } + ses_params.cipher_iv_len = ref->cipher_iv_length; + ses_params.auth_iv_len = ref->auth_iv_length; ses_params.auth_key = auth_key; ses_params.auth_digest_len = ref->digest_length; ses_params.auth_aad_len = ref->aad_length; @@ -701,14 +949,21 @@ static odp_crypto_session_t session_create(odp_crypto_op_t op, auth_alg_name(auth_alg)); return ODP_CRYPTO_SESSION_INVALID; } + + /* For now, allow out-of-place sessions not to be supported. */ + if (rc < 0 && status == ODP_CRYPTO_SES_ERR_PARAMS && + op_type == ODP_CRYPTO_OP_TYPE_OOP) { + if (!oop_warning_shown) + printf("\n Skipping ODP_CRYPTO_OP_TYPE_OOP tests\n"); + oop_warning_shown = 1; + return ODP_CRYPTO_SESSION_INVALID; + } + /* * We do not allow ODP_CRYPTO_SES_ERR_ALG_ORDER since we do * not combine individual non-null crypto and auth algorithms * with each other in the tests. Both orders should work when * only one algorithm is used (i.e. the other one is null). - * - * We do not allow ODP_CRYPTO_SES_ERR_PARAMS until needed for - * some ODP implementation. */ CU_ASSERT_FATAL(!rc); CU_ASSERT(status == ODP_CRYPTO_SES_ERR_NONE); @@ -721,23 +976,19 @@ static odp_crypto_session_t session_create(odp_crypto_op_t op, */ memset(cipher_key_data, 0, sizeof(cipher_key_data)); memset(auth_key_data, 0, sizeof(auth_key_data)); -#if ODP_DEPRECATED_API - memset(cipher_iv_data, 0, sizeof(cipher_iv_data)); - memset(auth_iv_data, 0, sizeof(auth_iv_data)); -#endif memset(&ses_params, 0, sizeof(ses_params)); return session; } -static void alg_test(odp_crypto_op_t op, - odp_cipher_alg_t cipher_alg, - odp_auth_alg_t auth_alg, - crypto_test_reference_t *ref, - uint32_t digest_offset, - iv_test_mode_t iv_mode, - odp_bool_t is_bit_mode_cipher, - odp_bool_t is_bit_mode_auth) +static void alg_test_ses(odp_crypto_op_t op, + odp_crypto_op_type_t op_type, + odp_cipher_alg_t cipher_alg, + odp_auth_alg_t auth_alg, + crypto_test_reference_t *ref, + uint32_t digest_offset, + odp_bool_t is_bit_mode_cipher, + odp_bool_t is_bit_mode_auth) { unsigned int initial_num_failures = CU_get_number_of_failures(); const uint32_t reflength = ref_length_in_bytes(ref); @@ -749,22 +1000,22 @@ static void alg_test(odp_crypto_op_t op, uint32_t max_shift; alg_test_param_t test_param; - session = session_create(op, cipher_alg, auth_alg, ref, iv_mode, hash_mode); + session = session_create(op, op_type, cipher_alg, auth_alg, ref, hash_mode); if (session == ODP_CRYPTO_SESSION_INVALID) return; memset(&test_param, 0, sizeof(test_param)); test_param.session = session; test_param.op = op; + test_param.op_type = op_type; test_param.cipher_alg = cipher_alg; test_param.auth_alg = auth_alg; test_param.ref = ref; - test_param.override_iv = (iv_mode != OLD_SESSION_IV); test_param.is_bit_mode_cipher = is_bit_mode_cipher; test_param.is_bit_mode_auth = is_bit_mode_auth; test_param.digest_offset = digest_offset; - alg_test_execute(&test_param); + alg_test_op(&test_param); max_shift = reflength + ref->digest_length; @@ -785,19 +1036,48 @@ static void alg_test(odp_crypto_op_t op, test_param.header_len = 0; test_param.trailer_len = 0; test_param.digest_offset = digest_offset; - alg_test_execute(&test_param); + alg_test_op(&test_param); /* Test partial packet crypto with odd alignment. */ - test_param.header_len = 3; + test_param.header_len = 13; test_param.trailer_len = 32; test_param.digest_offset = test_param.header_len + digest_offset; - alg_test_execute(&test_param); + alg_test_op(&test_param); } rc = odp_crypto_session_destroy(session); CU_ASSERT(!rc); } +static void alg_test(odp_crypto_op_t op, + odp_cipher_alg_t cipher_alg, + odp_auth_alg_t auth_alg, + crypto_test_reference_t *ref, + uint32_t digest_offset, + odp_bool_t is_bit_mode_cipher, + odp_bool_t is_bit_mode_auth) +{ + odp_crypto_op_type_t op_types[] = { + ODP_CRYPTO_OP_TYPE_LEGACY, + ODP_CRYPTO_OP_TYPE_BASIC, + ODP_CRYPTO_OP_TYPE_OOP, + }; + + for (unsigned int n = 0; n < ARRAY_SIZE(op_types); n++) { + if (!suite_context.packet && + op_types[n] != ODP_CRYPTO_OP_TYPE_LEGACY) + continue; + alg_test_ses(op, + op_types[n], + cipher_alg, + auth_alg, + ref, + digest_offset, + is_bit_mode_cipher, + is_bit_mode_auth); + } +} + static odp_bool_t aad_len_ok(const odp_crypto_auth_capability_t *capa, uint32_t len) { if (len < capa->aad_len.min || len > capa->aad_len.max) @@ -843,6 +1123,8 @@ static void check_alg(odp_crypto_op_t op, memset(cipher_tested, 0, sizeof(cipher_tested)); memset(auth_tested, 0, sizeof(auth_tested)); + oop_warning_shown = 0; /* allow OOP-unsupported warning again */ + for (idx = 0; idx < count; idx++) { int cipher_idx = -1, auth_idx = -1; odp_bool_t bit_mode_needed = false; @@ -908,18 +1190,8 @@ static void check_alg(odp_crypto_op_t op, continue; } - /* test with per-packet IV */ alg_test(op, cipher_alg, auth_alg, &ref[idx], digest_offs, - PACKET_IV, is_bit_mode_cipher, is_bit_mode_auth); -#if ODP_DEPRECATED_API - /* test with per-packet IV using the old API*/ - alg_test(op, cipher_alg, auth_alg, &ref[idx], digest_offs, - OLD_PACKET_IV, is_bit_mode_cipher, is_bit_mode_auth); - - /* test with per-session IV */ - alg_test(op, cipher_alg, auth_alg, &ref[idx], digest_offs, - OLD_SESSION_IV, is_bit_mode_cipher, is_bit_mode_auth); -#endif + is_bit_mode_cipher, is_bit_mode_auth); cipher_tested[cipher_idx] = true; auth_tested[auth_idx] = true; @@ -1223,12 +1495,15 @@ static int create_hash_test_reference(odp_auth_alg_t auth, rc = odp_packet_copy_from_mem(pkt, 0, auth_bytes, ref->plaintext); CU_ASSERT(rc == 0); - session = session_create(ODP_CRYPTO_OP_ENCODE, ODP_CIPHER_ALG_NULL, - auth, ref, PACKET_IV, HASH_NO_OVERLAP); + session = session_create(ODP_CRYPTO_OP_ENCODE, + ODP_CRYPTO_OP_TYPE_LEGACY, + ODP_CIPHER_ALG_NULL, + auth, ref, HASH_NO_OVERLAP); if (session == ODP_CRYPTO_SESSION_INVALID) return -1; - rc = crypto_op(pkt, &ok, session, ref->cipher_iv, ref->auth_iv, + rc = crypto_op(pkt, &pkt, &ok, session, ODP_CRYPTO_OP_TYPE_LEGACY, 0, + ref->cipher_iv, ref->auth_iv, &cipher_range, &auth_range, ref->aad, enc_digest_offset); CU_ASSERT(rc == 0); CU_ASSERT(ok); @@ -1243,11 +1518,11 @@ static int create_hash_test_reference(odp_auth_alg_t auth, /* copy the calculated digest in the ciphertext packet in ref */ rc = odp_packet_copy_to_mem(pkt, enc_digest_offset, ref->digest_length, &ref->ciphertext[digest_offset]); + CU_ASSERT(rc == 0); /* copy the calculated digest the digest field in ref */ rc = odp_packet_copy_to_mem(pkt, enc_digest_offset, ref->digest_length, &ref->digest); - CU_ASSERT(rc == 0); odp_packet_free(pkt); @@ -1280,7 +1555,6 @@ static void test_auth_hash_in_auth_range(odp_auth_alg_t auth, auth, &ref, digest_offset, - PACKET_IV, false, capa->bit_mode); @@ -1303,7 +1577,6 @@ static void test_auth_hash_in_auth_range(odp_auth_alg_t auth, auth, &ref, digest_offset, - PACKET_IV, false, capa->bit_mode); } @@ -2502,6 +2775,15 @@ static int crypto_init(odp_instance_t *inst) params.pkt.num = PKT_POOL_NUM; params.type = ODP_POOL_PACKET; + /* + * Let's have a user area so that we can check that its + * content gets copied along with other metadata when needed. + */ + if (pool_capa.pkt.max_uarea_size >= UAREA_SIZE) + params.pkt.uarea_size = UAREA_SIZE; + else + printf("Warning: could not request packet user area\n"); + if (pool_capa.pkt.max_seg_len && PKT_POOL_LEN > pool_capa.pkt.max_seg_len) { fprintf(stderr, "Warning: small packet segment length\n"); diff --git a/test/validation/api/dma/dma.c b/test/validation/api/dma/dma.c index 8eb75b172..f3e967193 100644 --- a/test/validation/api/dma/dma.c +++ b/test/validation/api/dma/dma.c @@ -19,6 +19,7 @@ #define TRAILER 10 #define MULTI 1 #define RESULT 1 +#define USER_DATA 0xdeadbeef typedef struct global_t { odp_dma_capability_t dma_capa; @@ -385,12 +386,13 @@ static int do_transfer_async(odp_dma_t dma, const odp_dma_transfer_param_t *trs_ odp_dma_compl_param_t compl_param; odp_event_t ev; odp_dma_compl_t compl; - int i, ret, done, dummy; + int i, ret, done; + uint32_t user_data = USER_DATA; odp_dma_result_t result; odp_dma_transfer_id_t transfer_id = ODP_DMA_TRANSFER_ID_INVALID; uint64_t wait_ns = 500 * ODP_TIME_MSEC_IN_NS; uint64_t sched_wait = odp_schedule_wait_time(wait_ns); - void *user_ptr = &dummy; + void *user_ptr = &user_data; odp_dma_compl_param_init(&compl_param); compl_param.compl_mode = compl_mode; @@ -452,6 +454,7 @@ static int do_transfer_async(odp_dma_t dma, const odp_dma_transfer_param_t *trs_ CU_ASSERT(done == 1); CU_ASSERT(result.success); CU_ASSERT(result.user_ptr == user_ptr); + CU_ASSERT(user_data == USER_DATA); odp_dma_transfer_id_free(dma, transfer_id); @@ -479,6 +482,7 @@ static int do_transfer_async(odp_dma_t dma, const odp_dma_transfer_param_t *trs_ CU_ASSERT(odp_dma_compl_result(compl, &result) == 0); CU_ASSERT(result.success); CU_ASSERT(result.user_ptr == user_ptr); + CU_ASSERT(user_data == USER_DATA); /* Test also without result struct output */ CU_ASSERT(odp_dma_compl_result(compl, NULL) == 0); diff --git a/test/validation/api/packet/packet.c b/test/validation/api/packet/packet.c index 1ae973d79..c654aa055 100644 --- a/test/validation/api/packet/packet.c +++ b/test/validation/api/packet/packet.c @@ -1,5 +1,5 @@ /* Copyright (c) 2014-2018, Linaro Limited - * Copyright (c) 2019-2022, Nokia + * Copyright (c) 2019-2023, Nokia * Copyright (c) 2020, Marvell * All rights reserved. * @@ -329,7 +329,8 @@ static int packet_suite_term(void) return 0; } -static void packet_set_inflags(odp_packet_t pkt, int val) +/* Set all non-conflicting metadata flags */ +static void packet_set_inflags_common(odp_packet_t pkt, int val) { odp_packet_has_l2_set(pkt, val); odp_packet_has_l3_set(pkt, val); @@ -339,23 +340,37 @@ static void packet_set_inflags(odp_packet_t pkt, int val) odp_packet_has_eth_mcast_set(pkt, val); odp_packet_has_jumbo_set(pkt, val); odp_packet_has_vlan_set(pkt, val); - odp_packet_has_vlan_qinq_set(pkt, val); - odp_packet_has_arp_set(pkt, val); odp_packet_has_ipv4_set(pkt, val); - odp_packet_has_ipv6_set(pkt, val); odp_packet_has_ip_bcast_set(pkt, val); - odp_packet_has_ip_mcast_set(pkt, val); odp_packet_has_ipfrag_set(pkt, val); odp_packet_has_ipopt_set(pkt, val); odp_packet_has_ipsec_set(pkt, val); odp_packet_has_udp_set(pkt, val); - odp_packet_has_tcp_set(pkt, val); - odp_packet_has_sctp_set(pkt, val); - odp_packet_has_icmp_set(pkt, val); odp_packet_user_flag_set(pkt, val); } -static void packet_check_inflags(odp_packet_t pkt, int val) +/* Check all non-conflicting metadata flags */ +static void packet_check_inflags_common(odp_packet_t pkt, int val) +{ + CU_ASSERT(odp_packet_has_l2(pkt) == !!val); + CU_ASSERT(odp_packet_has_l3(pkt) == !!val); + CU_ASSERT(odp_packet_has_l4(pkt) == !!val); + CU_ASSERT(odp_packet_has_eth(pkt) == !!val); + CU_ASSERT(odp_packet_has_eth_bcast(pkt) == !!val); + CU_ASSERT(odp_packet_has_eth_mcast(pkt) == !!val); + CU_ASSERT(odp_packet_has_jumbo(pkt) == !!val); + CU_ASSERT(odp_packet_has_vlan(pkt) == !!val); + CU_ASSERT(odp_packet_has_ipv4(pkt) == !!val); + CU_ASSERT(odp_packet_has_ip_bcast(pkt) == !!val); + CU_ASSERT(odp_packet_has_ipfrag(pkt) == !!val); + CU_ASSERT(odp_packet_has_ipopt(pkt) == !!val); + CU_ASSERT(odp_packet_has_ipsec(pkt) == !!val); + CU_ASSERT(odp_packet_has_udp(pkt) == !!val); + CU_ASSERT(odp_packet_user_flag(pkt) == !!val); +} + +/* Check all metadata flags */ +static void packet_check_inflags_all(odp_packet_t pkt, int val) { CU_ASSERT(odp_packet_has_l2(pkt) == !!val); CU_ASSERT(odp_packet_has_l3(pkt) == !!val); @@ -418,7 +433,7 @@ static void packet_test_alloc_free(void) CU_ASSERT(odp_packet_user_ptr(packet) == NULL); /* Packet flags should be zero */ - packet_check_inflags(packet, 0); + packet_check_inflags_all(packet, 0); /* Pool should have only one packet */ CU_ASSERT_FATAL(odp_packet_alloc(pool, packet_len) @@ -937,10 +952,10 @@ static void packet_test_reset(void) CU_ASSERT(odp_packet_reset(pkt, len) == 0); CU_ASSERT(odp_packet_len(pkt) == len); - packet_set_inflags(pkt, 1); - packet_check_inflags(pkt, 1); + packet_set_inflags_common(pkt, 1); + packet_check_inflags_common(pkt, 1); CU_ASSERT(odp_packet_reset(pkt, len) == 0); - packet_check_inflags(pkt, 0); + packet_check_inflags_all(pkt, 0); CU_ASSERT(odp_packet_reset(pkt, len - 1) == 0); CU_ASSERT(odp_packet_len(pkt) == (len - 1)); @@ -1374,10 +1389,10 @@ static void packet_test_in_flags(void) { odp_packet_t pkt = test_packet; - packet_set_inflags(pkt, 0); - packet_check_inflags(pkt, 0); - packet_set_inflags(pkt, 1); - packet_check_inflags(pkt, 1); + packet_set_inflags_common(pkt, 0); + packet_check_inflags_common(pkt, 0); + packet_set_inflags_common(pkt, 1); + packet_check_inflags_common(pkt, 1); TEST_INFLAG(pkt, has_l2); TEST_INFLAG(pkt, has_l3); @@ -1402,8 +1417,32 @@ static void packet_test_in_flags(void) TEST_INFLAG(pkt, has_icmp); TEST_INFLAG(pkt, user_flag); - packet_set_inflags(pkt, 0); - packet_check_inflags(pkt, 0); + packet_set_inflags_common(pkt, 0); + packet_check_inflags_common(pkt, 0); +} + +static void packet_test_vlan_flags(void) +{ + odp_packet_t pkt = test_packet; + + odp_packet_reset(pkt, odp_packet_len(test_packet)); + + CU_ASSERT(!odp_packet_has_vlan(pkt)); + CU_ASSERT(!odp_packet_has_vlan_qinq(pkt)); + + odp_packet_has_vlan_qinq_set(pkt, 1); + CU_ASSERT(odp_packet_has_vlan(pkt)); + CU_ASSERT(odp_packet_has_vlan_qinq(pkt)); + + odp_packet_has_vlan_qinq_set(pkt, 0); + CU_ASSERT(!odp_packet_has_vlan(pkt)); + CU_ASSERT(!odp_packet_has_vlan_qinq(pkt)); + + odp_packet_has_vlan_set(pkt, 1); + CU_ASSERT(odp_packet_has_vlan(pkt)); + CU_ASSERT(!odp_packet_has_vlan_qinq(pkt)); + + odp_packet_reset(pkt, odp_packet_len(test_packet)); } static void packet_test_error_flags(void) @@ -1628,15 +1667,15 @@ static void packet_test_meta_data_copy(void) pkt = odp_packet_alloc(pool, packet_len); CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); - packet_check_inflags(pkt, 0); + packet_check_inflags_all(pkt, 0); CU_ASSERT(odp_packet_input(pkt) == ODP_PKTIO_INVALID); CU_ASSERT(odp_packet_l3_offset(pkt) == ODP_PACKET_OFFSET_INVALID); CU_ASSERT(odp_packet_l4_offset(pkt) == ODP_PACKET_OFFSET_INVALID); CU_ASSERT(odp_packet_payload_offset(pkt) == ODP_PACKET_OFFSET_INVALID); - packet_set_inflags(pkt, 1); - packet_check_inflags(pkt, 1); + packet_set_inflags_common(pkt, 1); + packet_check_inflags_common(pkt, 1); odp_packet_input_set(pkt, pktio); odp_packet_user_ptr_set(pkt, (void *)(uintptr_t)0xdeadbeef); @@ -3098,17 +3137,31 @@ static void packet_vector_test_alloc_free(void) CU_ASSERT(odp_packet_vector_to_u64(pktv) != odp_packet_vector_to_u64(ODP_PACKET_VECTOR_INVALID)); - /* User flag should be initially zero */ + /* Vector size and user flag should be initially zero */ + CU_ASSERT(odp_packet_vector_size(pktv) == 0); CU_ASSERT(odp_packet_vector_user_flag(pktv) == 0); odp_packet_vector_user_flag_set(pktv, 1); CU_ASSERT(odp_packet_vector_user_flag(pktv) != 0); odp_packet_vector_user_flag_set(pktv, 0); CU_ASSERT(odp_packet_vector_user_flag(pktv) == 0); + /* Included packet should not be freed by odp_packet_vector_free() */ + pkt = odp_packet_alloc(default_pool, default_param.pkt.len); + CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); + + CU_ASSERT(odp_packet_vector_tbl(pktv, &pkts_tbl) == 0); + pkts_tbl[0] = pkt; + odp_packet_vector_size_set(pktv, 1); + /* Free with flag still set, alloc should clear it. */ odp_packet_vector_user_flag_set(pktv, 1); odp_packet_vector_free(pktv); + + /* Check that included packet is still valid */ + CU_ASSERT(odp_packet_is_valid(pkt)); + pktv = odp_packet_vector_alloc(pool); + CU_ASSERT(odp_packet_vector_size(pktv) == 0); CU_ASSERT(odp_packet_vector_user_flag(pktv) == 0); /* Since it was only one buffer pool, more vector packets can't be @@ -3124,10 +3177,7 @@ static void packet_vector_test_alloc_free(void) CU_ASSERT_FATAL(pktv != ODP_PACKET_VECTOR_INVALID); CU_ASSERT(odp_packet_vector_size(pktv) == 0); - /* Free packet vector using odp_event_free() */ - pkt = odp_packet_alloc(default_pool, default_param.pkt.len); - CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); - + /* Free packet vector and included packet using odp_event_free() */ CU_ASSERT(odp_packet_vector_tbl(pktv, &pkts_tbl) == 0); pkts_tbl[0] = pkt; odp_packet_vector_size_set(pktv, 1); @@ -4416,6 +4466,7 @@ odp_testinfo_t packet_suite[] = { ODP_TEST_INFO(packet_test_layer_offsets), ODP_TEST_INFO(packet_test_segment_last), ODP_TEST_INFO(packet_test_in_flags), + ODP_TEST_INFO(packet_test_vlan_flags), ODP_TEST_INFO(packet_test_error_flags), ODP_TEST_INFO(packet_test_add_rem_data), ODP_TEST_INFO(packet_test_meta_data_copy), diff --git a/test/validation/api/pool/pool.c b/test/validation/api/pool/pool.c index e8bf38c9d..cded05650 100644 --- a/test/validation/api/pool/pool.c +++ b/test/validation/api/pool/pool.c @@ -1,6 +1,6 @@ /* Copyright (c) 2014-2018, Linaro Limited * Copyright (c) 2020, Marvell - * Copyright (c) 2020-2022, Nokia + * Copyright (c) 2020-2023, Nokia * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -326,13 +326,19 @@ static void alloc_packet_vector(uint32_t cache_size) num = 0; for (i = 0; i < max_num; i++) { - pkt_vec[num] = odp_packet_vector_alloc(pool); - CU_ASSERT(pkt_vec[num] != ODP_PACKET_VECTOR_INVALID); - CU_ASSERT(odp_packet_vector_valid(pkt_vec[num]) == 1); - CU_ASSERT(odp_event_is_valid(odp_packet_vector_to_event(pkt_vec[num])) == 1); + odp_packet_vector_t pktv = odp_packet_vector_alloc(pool); - if (pkt_vec[num] != ODP_PACKET_VECTOR_INVALID) - num++; + CU_ASSERT(pktv != ODP_PACKET_VECTOR_INVALID); + + if (pktv == ODP_PACKET_VECTOR_INVALID) + continue; + + CU_ASSERT(odp_packet_vector_valid(pktv) == 1); + CU_ASSERT(odp_event_is_valid(odp_packet_vector_to_event(pktv)) == 1); + CU_ASSERT(odp_packet_vector_size(pktv) == 0); + + pkt_vec[num] = pktv; + num++; } for (i = 0; i < num; i++) diff --git a/test/validation/api/system/system.c b/test/validation/api/system/system.c index f0cf48738..a98ebb634 100644 --- a/test/validation/api/system/system.c +++ b/test/validation/api/system/system.c @@ -135,6 +135,7 @@ static void system_test_cpu_cycles_resolution(void) int i; uint64_t res; uint64_t c2, c1, max; + uint64_t test_cycles = odp_cpu_hz() / 100; /* CPU cycles in 10 msec */ max = odp_cpu_cycles_max(); @@ -144,11 +145,16 @@ static void system_test_cpu_cycles_resolution(void) for (i = 0; i < RES_TRY_NUM; i++) { c1 = odp_cpu_cycles(); - odp_time_wait_ns(100 * ODP_TIME_MSEC_IN_NS + i); + odp_time_wait_ns(10 * ODP_TIME_MSEC_IN_NS + i); c2 = odp_cpu_cycles(); - CU_ASSERT(c1 % res == 0); - CU_ASSERT(c2 % res == 0); + /* Diff may be zero with low resolution */ + if (test_cycles && test_cycles > res) { + uint64_t diff = odp_cpu_cycles_diff(c2, c1); + + CU_ASSERT(diff >= res); + } + } } @@ -185,13 +191,11 @@ static void system_test_cpu_cycles_diff(void) tmp = c2 + (max - c1) + res; diff = odp_cpu_cycles_diff(c2, c1); CU_ASSERT(diff == tmp); - CU_ASSERT(diff % res == 0); /* no wrap, revert args */ tmp = c1 - c2; diff = odp_cpu_cycles_diff(c1, c2); CU_ASSERT(diff == tmp); - CU_ASSERT(diff % res == 0); } static void system_test_cpu_cycles_long_period(void) @@ -221,8 +225,6 @@ static void system_test_cpu_cycles_long_period(void) c2 = odp_cpu_cycles(); CU_ASSERT(c2 != c1); - CU_ASSERT(c1 % res == 0); - CU_ASSERT(c2 % res == 0); CU_ASSERT(c1 <= max && c2 <= max); if (c2 > c1) @@ -232,7 +234,6 @@ static void system_test_cpu_cycles_long_period(void) diff = odp_cpu_cycles_diff(c2, c1); CU_ASSERT(diff == tmp); - CU_ASSERT(diff % res == 0); /* wrap is detected and verified */ if (c2 < c1) diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c index 45bfc8264..f285bf8e4 100644 --- a/test/validation/api/time/time.c +++ b/test/validation/api/time/time.c @@ -139,6 +139,7 @@ static void time_test_monotony(void) lns_t2 = odp_time_local_ns(); gns_t2 = odp_time_global_ns(); + count = 0; while (count < BUSY_LOOP_CNT) { count++; }; diff --git a/test/validation/api/timer/timer.c b/test/validation/api/timer/timer.c index 1c0a16349..0e3919b73 100644 --- a/test/validation/api/timer/timer.c +++ b/test/validation/api/timer/timer.c @@ -329,8 +329,10 @@ static void timer_test_capa(void) CU_ASSERT_FATAL(ODP_CLOCK_SRC_0 + 4 == ODP_CLOCK_SRC_4); CU_ASSERT_FATAL(ODP_CLOCK_SRC_0 + 5 == ODP_CLOCK_SRC_5); CU_ASSERT_FATAL(ODP_CLOCK_SRC_5 + 1 == ODP_CLOCK_NUM_SRC); +#if ODP_DEPRECATED_API CU_ASSERT_FATAL(ODP_CLOCK_CPU == ODP_CLOCK_DEFAULT); CU_ASSERT_FATAL(ODP_CLOCK_EXT == ODP_CLOCK_SRC_1); +#endif for (i = 0; i < ODP_CLOCK_NUM_SRC; i++) { clk_src = ODP_CLOCK_SRC_0 + i; @@ -666,6 +668,7 @@ static void timer_pool_max_res(void) odp_queue_param_t queue_param; odp_timer_pool_t tp; odp_timer_t timer; + odp_timer_start_t start_param; odp_pool_param_t pool_param; odp_pool_t pool; odp_queue_t queue; @@ -729,7 +732,11 @@ static void timer_pool_max_res(void) ev = odp_timeout_to_event(tmo); CU_ASSERT_FATAL(ev != ODP_EVENT_INVALID); - ret = odp_timer_set_rel(timer, tick, &ev); + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = tick; + start_param.tmo_ev = ev; + + ret = odp_timer_start(timer, &start_param); CU_ASSERT(ret == ODP_TIMER_SUCCESS); ev = ODP_EVENT_INVALID; @@ -1145,6 +1152,7 @@ static void timer_test_event_type(odp_queue_type_t queue_type, odp_queue_param_t queue_param; odp_timer_pool_param_t timer_param; odp_timer_pool_t timer_pool; + odp_timer_start_t start_param; odp_queue_t queue; odp_timeout_t tmo; odp_buffer_t buf; @@ -1231,7 +1239,11 @@ static void timer_test_event_type(odp_queue_type_t queue_type, timer[i] = odp_timer_alloc(timer_pool, queue, user_ctx); CU_ASSERT_FATAL(timer[i] != ODP_TIMER_INVALID); - ret = odp_timer_set_rel(timer[i], (i + 1) * period_tick, &ev); + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = (i + 1) * period_tick; + start_param.tmo_ev = ev; + + ret = odp_timer_start(timer[i], &start_param); if (ret == ODP_TIMER_TOO_NEAR) ODPH_DBG("Timer set failed. Too near %i.\n", i); @@ -1332,6 +1344,7 @@ static void timer_test_queue_type(odp_queue_type_t queue_type, int priv, int exp odp_queue_param_t queue_param; odp_timer_pool_param_t tparam; odp_timer_pool_t tp; + odp_timer_start_t start_param; odp_queue_t queue; odp_timer_t tim; int i, ret, num_tmo; @@ -1411,7 +1424,12 @@ static void timer_test_queue_type(odp_queue_type_t queue_type, int priv, int exp timer[i] = tim; tick = tick_base + ((i + 1) * period_tick); - ret = odp_timer_set_abs(tim, tick, &ev); + + start_param.tick_type = ODP_TIMER_TICK_ABS; + start_param.tick = tick; + start_param.tmo_ev = ev; + + ret = odp_timer_start(tim, &start_param); target_tick[i] = tick; target_nsec[i] = nsec_base + ((i + 1) * period_ns); @@ -1541,12 +1559,12 @@ static void timer_test_cancel(void) odp_queue_param_t queue_param; odp_timer_capability_t capa; odp_timer_pool_t tp; + odp_timer_start_t start_param; odp_queue_t queue; odp_timer_t tim; odp_event_t ev; odp_timeout_t tmo; odp_timer_set_t rc; - uint64_t tick; int ret; memset(&capa, 0, sizeof(capa)); @@ -1597,9 +1615,11 @@ static void timer_test_cancel(void) if (ev == ODP_EVENT_INVALID) CU_FAIL_FATAL("Failed to allocate timeout"); - tick = odp_timer_ns_to_tick(tp, tparam.max_tmo / 2); + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = odp_timer_ns_to_tick(tp, tparam.max_tmo / 2); + start_param.tmo_ev = ev; - rc = odp_timer_set_rel(tim, tick, &ev); + rc = odp_timer_start(tim, &start_param); if (rc != ODP_TIMER_SUCCESS) CU_FAIL_FATAL("Failed to set timer (relative time)"); @@ -1645,6 +1665,7 @@ static void timer_test_tmo_limit(odp_queue_type_t queue_type, odp_queue_param_t queue_param; odp_timer_pool_param_t timer_param; odp_timer_pool_t timer_pool; + odp_timer_start_t start_param; odp_queue_t queue; odp_timeout_t tmo; odp_event_t ev; @@ -1731,7 +1752,12 @@ static void timer_test_tmo_limit(odp_queue_type_t queue_type, CU_ASSERT(ev != ODP_EVENT_INVALID); t1 = odp_time_local(); - ret = odp_timer_set_rel(timer[i], tmo_tick, &ev); + + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = tmo_tick; + start_param.tmo_ev = ev; + + ret = odp_timer_start(timer[i], &start_param); if (ret == ODP_TIMER_TOO_NEAR) ODPH_DBG("Timer set failed. Too near %i.\n", i); @@ -1943,6 +1969,7 @@ static int worker_entrypoint(void *arg ODP_UNUSED) struct timespec ts; uint32_t nstale; odp_timer_set_t timer_rc; + odp_timer_start_t start_param; odp_timer_pool_t tp = global_mem->tp; odp_pool_t tbp = global_mem->tbp; uint32_t num_timers = global_mem->timers_per_thread; @@ -2008,7 +2035,13 @@ static int worker_entrypoint(void *arg ODP_UNUSED) (rand_r(&seed) % RANGE_MS) * 1000000ULL; tck = odp_timer_current_tick(tp) + odp_timer_ns_to_tick(tp, nsec); - timer_rc = odp_timer_set_abs(tt[i].tim, tck, &tt[i].ev); + + start_param.tick_type = ODP_TIMER_TICK_ABS; + start_param.tick = tck; + start_param.tmo_ev = tt[i].ev; + tt[i].ev = ODP_EVENT_INVALID; + + timer_rc = odp_timer_start(tt[i].tim, &start_param); if (timer_rc == ODP_TIMER_TOO_NEAR) { ODPH_ERR("Missed tick, setting timer\n"); } else if (timer_rc != ODP_TIMER_SUCCESS) { @@ -2058,23 +2091,34 @@ static int worker_entrypoint(void *arg ODP_UNUSED) odp_timer_set_t rc; uint64_t cur_tick; uint64_t tck; + int reset_timer = 0; - if (tt[i].ev != ODP_EVENT_INVALID) + if (tt[i].ev != ODP_EVENT_INVALID) { /* Timer inactive => set */ nset++; - else if (odp_timer_current_tick(tp) >= tt[i].tick) + } else if (odp_timer_current_tick(tp) >= tt[i].tick) { /* Timer just expired. */ goto sleep; - else + } else { /* Timer active => reset */ nreset++; + reset_timer = 1; + } nsec = min_tmo + THREE_POINT_THREE_MSEC + (rand_r(&seed) % RANGE_MS) * 1000000ULL; tck = odp_timer_ns_to_tick(tp, nsec); cur_tick = odp_timer_current_tick(tp); - rc = odp_timer_set_rel(tt[i].tim, tck, &tt[i].ev); + + start_param.tick_type = ODP_TIMER_TICK_REL; + start_param.tick = tck; + start_param.tmo_ev = tt[i].ev; + + if (reset_timer) + rc = odp_timer_restart(tt[i].tim, &start_param); + else + rc = odp_timer_start(tt[i].tim, &start_param); if (rc == ODP_TIMER_TOO_NEAR) { CU_FAIL("Failed to set timer: TOO NEAR"); |