On Mon, Jan 4, 2016 at 1:34 AM, Alexandru Badicioiu < [email protected]> wrote:
> Using time API makes the performance test OS independent but it makes the > actual results dependent also on the time API implementation. This could be > an issue especially when comparing crypto performances of different > platforms. > How is that? A ns is a ns no matter how it's implemented. > > Alex > > On 30 December 2015 at 16:59, Maxim Uvarov <[email protected]> > wrote: > >> Alex, I think after 1.6 time api will be there and it's better to reuse >> for performance test. >> >> Maxim. >> >> >> On 12/17/2015 12:55, [email protected] wrote: >> >>> From: Alexandru Badicioiu <alexandru.badicioiu at linaro.org> >>> >>> Measures the time required to launch and get the result >>> of ODP crypto operations in async and sync API mode with >>> configurable payload size, crypto algorithms and iteration >>> number. >>> Both asynchronous scheduled and polled are supported. >>> In scheduled mode a separate worker thread is used to >>> get the crypto completion events. >>> Output packet can be reused as the input of the next >>> operation or a new packet can be allocated for each >>> operation. >>> Based on a previous work : >>> https://lists.linaro.org/pipermail/lng-odp/2014-September/003251.html. >>> >>> Signed-off-by: Alexandru Badicioiu <[email protected]> >>> --- >>> >>> v1 >>> --- >>> - replaced cspeed with crypto >>> - removed unused parameter core_count >>> v2 >>> -- >>> - alphabetical order in Makefile.am >>> - replaced pool params memset with init call >>> v3 >>> -- >>> - rebased to latest master >>> >>> --- >>> test/performance/Makefile.am | 5 +- >>> test/performance/odp_crypto.c | 937 >>> ++++++++++++++++++++++++++++++++++++++++++ >>> 2 files changed, 941 insertions(+), 1 deletion(-) >>> create mode 100644 test/performance/odp_crypto.c >>> >>> diff --git a/test/performance/Makefile.am b/test/performance/Makefile.am >>> index 721615b..78374cd 100644 >>> --- a/test/performance/Makefile.am >>> +++ b/test/performance/Makefile.am >>> @@ -2,7 +2,7 @@ include $(top_srcdir)/test/Makefile.inc >>> TESTS_ENVIRONMENT += TEST_DIR=${builddir} >>> -EXECUTABLES = odp_atomic$(EXEEXT) odp_pktio_perf$(EXEEXT) >>> +EXECUTABLES = odp_atomic$(EXEEXT) odp_crypto$(EXEEXT) >>> odp_pktio_perf$(EXEEXT) >>> COMPILE_ONLY = odp_l2fwd$(EXEEXT) \ >>> odp_scheduling$(EXEEXT) >>> @@ -18,6 +18,8 @@ bin_PROGRAMS = $(EXECUTABLES) $(COMPILE_ONLY) >>> odp_atomic_LDFLAGS = $(AM_LDFLAGS) -static >>> odp_atomic_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test >>> +odp_crypto_LDFLAGS = $(AM_LDFLAGS) -static >>> +odp_crypto_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test >>> odp_scheduling_LDFLAGS = $(AM_LDFLAGS) -static >>> odp_scheduling_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/test >>> @@ -25,6 +27,7 @@ noinst_HEADERS = \ >>> $(top_srcdir)/test/test_debug.h >>> dist_odp_atomic_SOURCES = odp_atomic.c >>> +dist_odp_crypto_SOURCES = odp_crypto.c >>> dist_odp_scheduling_SOURCES = odp_scheduling.c >>> dist_odp_pktio_perf_SOURCES = odp_pktio_perf.c >>> diff --git a/test/performance/odp_crypto.c >>> b/test/performance/odp_crypto.c >>> new file mode 100644 >>> index 0000000..0596b17 >>> --- /dev/null >>> +++ b/test/performance/odp_crypto.c >>> @@ -0,0 +1,937 @@ >>> +/* Copyright (c) 2015, Linaro Limited >>> + * All rights reserved. >>> + * >>> + * SPDX-License-Identifier: BSD-3-Clause >>> + */ >>> + >>> +#ifndef _GNU_SOURCE >>> +#define _GNU_SOURCE >>> +#endif /* _GNU_SOURCE */ >>> + >>> +#include <stdlib.h> >>> +#include <string.h> >>> +#include <getopt.h> >>> +#include <unistd.h> >>> +#include <stdio.h> >>> +#include <sys/time.h> >>> +#include <sys/resource.h> >>> + >>> +#include <odp.h> >>> +#include <odp/helper/linux.h> >>> + >>> +#define app_err(fmt, ...) \ >>> + fprintf(stderr, "%s:%d:%s(): Error: " fmt, __FILE__, \ >>> + __LINE__, __func__, ##__VA_ARGS__) >>> + >>> +/** @def SHM_PKT_POOL_SIZE >>> + * @brief Size of the shared memory block >>> + */ >>> +#define SHM_PKT_POOL_SIZE (512 * 2048 * 2) >>> + >>> +/** @def SHM_PKT_POOL_BUF_SIZE >>> + * @brief Buffer size of the packet pool buffer >>> + */ >>> +#define SHM_PKT_POOL_BUF_SIZE (1024 * 32) >>> + >>> +static uint8_t test_iv[8] = "01234567"; >>> + >>> +static uint8_t test_key16[16] = { 0x01, 0x02, 0x03, 0x04, 0x05, >>> + 0x06, 0x07, 0x08, 0x09, 0x0a, >>> + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, >>> + 0x10, >>> +}; >>> + >>> +static uint8_t test_key24[24] = { 0x01, 0x02, 0x03, 0x04, 0x05, >>> + 0x06, 0x07, 0x08, 0x09, 0x0a, >>> + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, >>> + 0x10, 0x11, 0x12, 0x13, 0x14, >>> + 0x15, 0x16, 0x17, 0x18 >>> +}; >>> + >>> +/** >>> + * Structure that holds template for session create call >>> + * for different algorithms supported by test >>> + */ >>> +typedef struct { >>> + const char *name; /**< Algorithm name */ >>> + odp_crypto_session_params_t session; /**< Prefilled crypto >>> session params */ >>> + unsigned int hash_adjust; /**< Size of hash */ >>> +} crypto_alg_config_t; >>> + >>> +/** >>> + * Parsed command line crypto arguments. Describes test configuration. >>> + */ >>> +typedef struct { >>> + /** >>> + * If non zero prints content of packets. Enabled by -d or >>> + * --debug option. >>> + */ >>> + int debug_packets; >>> + >>> + /** >>> + * If non zero Try to run crypto operation in place. Note some >>> + * implementation may not support such mode. Enabled by -n or >>> + * --inplace option. >>> + */ >>> + int in_place; >>> + >>> + /** >>> + * If non zeor output of previous operation taken as input for >>> + * next encrypt operations. Enabled by -r or --reuse option. >>> + */ >>> + int reuse_packet; >>> + >>> + /** >>> + * Maximum number of outstanding encryption requests. Note code >>> + * poll for results over queue and if nothing is available it can >>> + * submit more encryption requests up to maximum number >>> specified by >>> + * this option. Specified through -f or --flight option. >>> + */ >>> + int in_flight; >>> + >>> + /** >>> + * Number of iteration to repeat crypto operation to get good >>> + * average number. Specified through -i or --terations option. >>> + * Default is 10000. >>> + */ >>> + int iteration_count; >>> + >>> + /** >>> + * Maximum sessions. Currently is not used. >>> + */ >>> + int max_sessions; >>> + >>> + /** >>> + * Payload size to test. If 0 set of predefined payload sizes >>> + * is tested. Specified through -p or --payload option. >>> + */ >>> + int payload_length; >>> + >>> + /** >>> + * Pointer to selected algorithm to test. If NULL all available >>> + * alogorthims are tested. Name of algorithm is passed through >>> + * -a or --algorithm option. >>> + */ >>> + crypto_alg_config_t *alg_config; >>> + >>> + /** >>> + * Use scheduler to get completion events from crypto operation. >>> + * Specified through -s argument. >>> + * */ >>> + int schedule; >>> + >>> + /* >>> + * Poll completion queue for crypto completion events. >>> + * Specified through -p argument. >>> + */ >>> + int poll; >>> +} crypto_args_t; >>> + >>> +/* >>> + * Helper structure that holds averages for test of one algorithm >>> + * for given payload size. >>> + */ >>> +typedef struct { >>> + /** >>> + * Elapsed time for one crypto operation. >>> + */ >>> + double elapsed; >>> + >>> + /** >>> + * CPU time spent pre one crypto operation by whole process >>> + * i.e include current and all other threads in process. >>> + * It is filled with 'getrusage(RUSAGE_SELF, ...)' call. >>> + */ >>> + double rusage_self; >>> + >>> + /** >>> + * CPU time spent per one crypto operation by current thread >>> + * only. It is filled with 'getrusage(RUSAGE_THREAD, ...)' >>> + * call. >>> + */ >>> + double rusage_thread; >>> +} crypto_run_result_t; >>> + >>> +/** >>> + * Structure holds one snap to misc times of current process. >>> + */ >>> +typedef struct { >>> + struct timeval tv; /**< Elapsed time */ >>> + struct rusage ru_self; /**< Rusage value for whole process */ >>> + struct rusage ru_thread; /**< Rusage value for current thread */ >>> +} time_record_t; >>> + >>> +static void parse_args(int argc, char *argv[], crypto_args_t *cargs); >>> +static void usage(char *progname); >>> + >>> +/** >>> + * Set of predefined payloads. Make sure that maximum payload >>> + * size is not bigger than SHM_PKT_POOL_BUF_SIZE. May relax when >>> + * implementation start support segmented buffers/packets. >>> + */ >>> +static unsigned int payloads[] = { >>> + 16, >>> + 64, >>> + 256, >>> + 1024, >>> + 8192, >>> + 16384 >>> +}; >>> + >>> +/** >>> + * Set of known algorithms to test >>> + */ >>> +static crypto_alg_config_t algs_config[] = { >>> + { >>> + .name = "3des-cbc-null", >>> + .session = { >>> + .cipher_alg = ODP_CIPHER_ALG_3DES_CBC, >>> + .cipher_key = { >>> + .data = test_key24, >>> + .length = sizeof(test_key24) >>> + }, >>> + .iv = { >>> + .data = test_iv, >>> + .length = 8, >>> + }, >>> + .auth_alg = ODP_AUTH_ALG_NULL >>> + }, >>> + }, >>> + { >>> + .name = "3des-cbc-hmac-md5-96", >>> + .session = { >>> + .cipher_alg = ODP_CIPHER_ALG_3DES_CBC, >>> + .cipher_key = { >>> + .data = test_key24, >>> + .length = sizeof(test_key24) >>> + }, >>> + .iv = { >>> + .data = test_iv, >>> + .length = 8, >>> + }, >>> + .auth_alg = ODP_AUTH_ALG_MD5_96, >>> + .auth_key = { >>> + .data = test_key16, >>> + .length = sizeof(test_key16) >>> + } >>> + }, >>> + .hash_adjust = 12 >>> + }, >>> + { >>> + .name = "null-hmac-md5-96", >>> + .session = { >>> + .cipher_alg = ODP_CIPHER_ALG_NULL, >>> + .auth_alg = ODP_AUTH_ALG_MD5_96, >>> + .auth_key = { >>> + .data = test_key16, >>> + .length = sizeof(test_key16) >>> + } >>> + }, >>> + .hash_adjust = 12 >>> + }, >>> +}; >>> + >>> +/** >>> + * Find corresponding config for given name. Returns NULL >>> + * if config for given name is not found. >>> + */ >>> +static crypto_alg_config_t * >>> +find_config_by_name(const char *name) { >>> + unsigned int i; >>> + crypto_alg_config_t *ret = NULL; >>> + >>> + for (i = 0; i < (sizeof(algs_config) / >>> sizeof(crypto_alg_config_t)); >>> + i++) { >>> + if (strcmp(algs_config[i].name, name) == 0) { >>> + ret = algs_config + i; >>> + break; >>> + } >>> + } >>> + return ret; >>> +} >>> + >>> +/** >>> + * Helper function that prints list of algorithms that this >>> + * test understands. >>> + */ >>> +static void >>> +print_config_names(const char *prefix) { >>> + unsigned int i; >>> + >>> + for (i = 0; i < (sizeof(algs_config) / >>> sizeof(crypto_alg_config_t)); >>> + i++) { >>> + printf("%s %s\n", prefix, algs_config[i].name); >>> + } >>> +} >>> + >>> +/** >>> + * Snap current time values and put them into 'rec'. >>> + */ >>> +static void >>> +fill_time_record(time_record_t *rec) >>> +{ >>> + gettimeofday(&rec->tv, NULL); >>> + getrusage(RUSAGE_SELF, &rec->ru_self); >>> + getrusage(RUSAGE_THREAD, &rec->ru_thread); >>> +} >>> + >>> +/** >>> + * Calculated CPU time difference for given two rusage structures. >>> + * Note it adds user space and system time together. >>> + */ >>> +static unsigned long long >>> +get_rusage_diff(struct rusage *start, struct rusage *end) >>> +{ >>> + unsigned long long rusage_diff; >>> + unsigned long long rusage_start; >>> + unsigned long long rusage_end; >>> + >>> + rusage_start = (start->ru_utime.tv_sec * 1000000) + >>> + (start->ru_utime.tv_usec); >>> + rusage_start += (start->ru_stime.tv_sec * 1000000) + >>> + (start->ru_stime.tv_usec); >>> + >>> + rusage_end = (end->ru_utime.tv_sec * 1000000) + >>> + (end->ru_utime.tv_usec); >>> + rusage_end += (end->ru_stime.tv_sec * 1000000) + >>> + (end->ru_stime.tv_usec); >>> + >>> + rusage_diff = rusage_end - rusage_start; >>> + >>> + return rusage_diff; >>> +} >>> + >>> +/** >>> + * Get diff for RUSAGE_SELF (whole process) between two time snap >>> + * records. >>> + */ >>> +static unsigned long long >>> +get_rusage_self_diff(time_record_t *start, time_record_t *end) >>> +{ >>> + return get_rusage_diff(&start->ru_self, &end->ru_self); >>> +} >>> + >>> +/** >>> + * Get diff for RUSAGE_THREAD (current thread only) between two >>> + * time snap records. >>> + */ >>> +static unsigned long long >>> +get_rusage_thread_diff(time_record_t *start, time_record_t *end) >>> +{ >>> + return get_rusage_diff(&start->ru_thread, &end->ru_thread); >>> +} >>> + >>> +/** >>> + * Get diff of elapsed time between two time snap records >>> + */ >>> +static unsigned long long >>> +get_elapsed_usec(time_record_t *start, time_record_t *end) >>> +{ >>> + unsigned long long s; >>> + unsigned long long e; >>> + >>> + s = (start->tv.tv_sec * 1000000) + >>> + (start->tv.tv_usec); >>> + e = (end->tv.tv_sec * 1000000) + >>> + (end->tv.tv_usec); >>> + >>> + return e - s; >>> +} >>> + >>> +#define REPORT_HEADER "\n%30.30s %15s %15s %15s %15s %15s %15s\n" >>> +#define REPORT_LINE "%30.30s %15d %15d %15.3f %15.3f %15.3f >>> %15d\n" >>> + >>> +/** >>> + * Print header line for our report. >>> + */ >>> +static void >>> +print_result_header(void) >>> +{ >>> + printf(REPORT_HEADER, >>> + "algorithm", "avg over #", "payload (bytes)", "elapsed >>> (us)", >>> + "rusg self (us)", "rusg thrd (us)", "throughput (Kb)"); >>> +} >>> + >>> +/** >>> + * Print one line of our report. >>> + */ >>> +static void >>> +print_result(crypto_args_t *cargs, >>> + unsigned int payload_length, >>> + crypto_alg_config_t *config, >>> + crypto_run_result_t *result) >>> +{ >>> + unsigned int throughput; >>> + >>> + throughput = (1000000.0 / result->elapsed) * payload_length / >>> 1024; >>> + printf(REPORT_LINE, >>> + config->name, cargs->iteration_count, payload_length, >>> + result->elapsed, result->rusage_self, >>> result->rusage_thread, >>> + throughput); >>> +} >>> + >>> +/** >>> + * Print piece of memory with given size. >>> + */ >>> +static void >>> +print_mem(const char *msg, >>> + const unsigned char *ptr, >>> + unsigned int len) >>> +{ >>> + unsigned i, j; >>> + char c; >>> + char line[81]; >>> + char *p; >>> + >>> + if (msg) >>> + printf("\n%s (bytes size = %d)", msg, len); >>> + >>> + for (i = 0; i < len; i += 16) { >>> + p = line; >>> + sprintf(p, "\n%04x ", i); p += 8; >>> + >>> + for (j = 0; j < 16; j++) { >>> + if (i + j == len) >>> + break; >>> + >>> + sprintf(p, " %02x", (ptr)[i + j]); p += 3; >>> + } >>> + >>> + for (; j < 16; j++) { >>> + sprintf(p, " "); p += 3; >>> + } >>> + >>> + sprintf(p, " "); p += 3; >>> + >>> + for (j = 0; j < 16; j++) { >>> + if (i + j == len) >>> + break; >>> + c = (ptr)[i + j]; >>> + *p++ = (' ' <= c && c <= '~') ? c : '.'; >>> + } >>> + >>> + *p = '\0'; >>> + printf("%s", line); >>> + } >>> + printf("\n"); >>> +} >>> + >>> +/** >>> + * Create ODP crypto session for given config. >>> + */ >>> +static int >>> +create_session_from_config(odp_crypto_session_t *session, >>> + crypto_alg_config_t *config, >>> + crypto_args_t *cargs) >>> +{ >>> + odp_crypto_session_params_t params; >>> + odp_crypto_ses_create_err_t ses_create_rc; >>> + odp_pool_t pkt_pool; >>> + odp_queue_t out_queue; >>> + >>> + memcpy(¶ms, &config->session, >>> sizeof(odp_crypto_session_params_t)); >>> + params.op = ODP_CRYPTO_OP_ENCODE; >>> + params.pref_mode = ODP_CRYPTO_SYNC; >>> + >>> + /* Lookup the packet pool */ >>> + pkt_pool = odp_pool_lookup("packet_pool"); >>> + if (pkt_pool == ODP_POOL_INVALID) { >>> + app_err("packet_pool pool not found\n"); >>> + return -1; >>> + } >>> + params.output_pool = pkt_pool; >>> + >>> + if (cargs->schedule || cargs->poll) { >>> + out_queue = odp_queue_lookup("crypto-out"); >>> + if (out_queue == ODP_QUEUE_INVALID) { >>> + app_err("crypto-out queue not found\n"); >>> + return -1; >>> + } >>> + params.compl_queue = out_queue; >>> + >>> + } else { >>> + params.compl_queue = ODP_QUEUE_INVALID; >>> + } >>> + if (odp_crypto_session_create(¶ms, session, >>> + &ses_create_rc)) { >>> + app_err("crypto session create failed.\n"); >>> + return -1; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +/** >>> + * Run measurement iterations for given config and payload size. >>> + * Result of run returned in 'result' out parameter. >>> + */ >>> +static int >>> +run_measure_one(crypto_args_t *cargs, >>> + crypto_alg_config_t *config, >>> + odp_crypto_session_t *session, >>> + unsigned int payload_length, >>> + crypto_run_result_t *result) >>> +{ >>> + odp_crypto_op_params_t params; >>> + >>> + odp_pool_t pkt_pool; >>> + odp_queue_t out_queue; >>> + odp_packet_t pkt; >>> + int rc = 0; >>> + >>> + odp_bool_t posted = 0; >>> + >>> + pkt_pool = odp_pool_lookup("packet_pool"); >>> + if (pkt_pool == ODP_POOL_INVALID) { >>> + app_err("pkt_pool not found\n"); >>> + return -1; >>> + } >>> + >>> + out_queue = odp_queue_lookup("crypto-out"); >>> + if (cargs->schedule || cargs->poll) { >>> + if (out_queue == ODP_QUEUE_INVALID) { >>> + app_err("crypto-out queue not found\n"); >>> + return -1; >>> + } >>> + } >>> + >>> + pkt = odp_packet_alloc(pkt_pool, payload_length); >>> + if (pkt == ODP_PACKET_INVALID) { >>> + app_err("failed to allocate buffer\n"); >>> + return -1; >>> + } >>> + >>> + void *mem = odp_packet_data(pkt); >>> + >>> + memset(mem, 1, payload_length); >>> + >>> + time_record_t start, end; >>> + int packets_sent = 0; >>> + int packets_received = 0; >>> + >>> + /* Initialize parameters block */ >>> + memset(¶ms, 0, sizeof(params)); >>> + params.session = *session; >>> + >>> + params.cipher_range.offset = 0; >>> + params.cipher_range.length = payload_length; >>> + >>> + params.auth_range.offset = 0; >>> + params.auth_range.length = payload_length; >>> + params.hash_result_offset = payload_length; >>> + >>> + if (cargs->reuse_packet) { >>> + params.pkt = pkt; >>> + params.out_pkt = cargs->in_place ? pkt : >>> + ODP_PACKET_INVALID; >>> + } >>> + >>> + fill_time_record(&start); >>> + >>> + while ((packets_sent < cargs->iteration_count) || >>> + (packets_received < cargs->iteration_count)) { >>> + void *mem; >>> + odp_crypto_op_result_t result; >>> + >>> + if ((packets_sent < cargs->iteration_count) && >>> + (packets_sent - packets_received < >>> + cargs->in_flight)) { >>> + if (!cargs->reuse_packet) { >>> + /* >>> + * For in place test we use just one >>> + * statically allocated buffer. >>> + * For now in place test we have to >>> + * allocate and initialize packet >>> + * every time. >>> + * Note we leaked one packet here. >>> + */ >>> + pkt = odp_packet_alloc(pkt_pool, >>> + payload_length); >>> + if (pkt == ODP_PACKET_INVALID) { >>> + app_err("failed to allocate >>> buffer\n"); >>> + rc = -1; >>> + } else { >>> + void *mem = odp_packet_data(pkt); >>> + >>> + memset(mem, 1, payload_length); >>> + } >>> + params.pkt = pkt; >>> + params.out_pkt = cargs->in_place ? pkt : >>> + ODP_PACKET_INVALID; >>> + } >>> + >>> + if (cargs->debug_packets) { >>> + mem = odp_packet_data(params.pkt); >>> + print_mem("Packet before encryption:", >>> + mem, payload_length); >>> + } >>> + >>> + rc = odp_crypto_operation(¶ms, &posted, >>> + &result); >>> + if (rc) >>> + app_err("failed odp_crypto_operation: rc >>> = %d\n", >>> + rc); >>> + else >>> + packets_sent++; >>> + } >>> + >>> + if (!posted) { >>> + packets_received++; >>> + if (cargs->debug_packets) { >>> + mem = odp_packet_data(params.out_pkt); >>> + print_mem("Imediately encrypted packet", >>> mem, >>> + payload_length + >>> + config->hash_adjust); >>> + } >>> + if (!cargs->in_place) { >>> + if (cargs->reuse_packet) { >>> + params.pkt = params.out_pkt; >>> + params.out_pkt = >>> ODP_PACKET_INVALID; >>> + } else { >>> + odp_packet_free(params.out_pkt); >>> + } >>> + } >>> + } else { >>> + odp_event_t ev; >>> + odp_crypto_compl_t compl; >>> + odp_crypto_op_result_t result; >>> + odp_packet_t out_pkt; >>> + >>> + if (cargs->schedule) >>> + ev = odp_schedule(NULL, >>> + ODP_SCHED_NO_WAIT); >>> + else >>> + ev = odp_queue_deq(out_queue); >>> + >>> + while (ev != ODP_EVENT_INVALID) { >>> + compl = odp_crypto_compl_from_event(ev); >>> + odp_crypto_compl_result(compl, &result); >>> + odp_crypto_compl_free(compl); >>> + out_pkt = result.pkt; >>> + >>> + if (cargs->debug_packets) { >>> + mem = odp_packet_data(out_pkt); >>> + print_mem("Receieved encrypted >>> packet", >>> + mem, >>> + payload_length + >>> + config->hash_adjust); >>> + } >>> + if (cargs->reuse_packet) { >>> + params.pkt = out_pkt; >>> + params.out_pkt = >>> ODP_PACKET_INVALID; >>> + } else { >>> + odp_packet_free(out_pkt); >>> + } >>> + packets_received++; >>> + if (cargs->schedule) >>> + ev = odp_schedule(NULL, >>> + >>> ODP_SCHED_NO_WAIT); >>> + else >>> + ev = odp_queue_deq(out_queue); >>> + }; >>> + } >>> + } >>> + >>> + fill_time_record(&end); >>> + >>> + { >>> + double count; >>> + >>> + count = get_elapsed_usec(&start, &end); >>> + result->elapsed = count / >>> + cargs->iteration_count; >>> + >>> + count = get_rusage_self_diff(&start, &end); >>> + result->rusage_self = count / >>> + cargs->iteration_count; >>> + >>> + count = get_rusage_thread_diff(&start, &end); >>> + result->rusage_thread = count / >>> + cargs->iteration_count; >>> + } >>> + >>> + return rc; >>> +} >>> + >>> +/** >>> + * Process one algorithm. Note if paload size is specicified it is >>> + * only one run. Or iterate over set of predefined payloads. >>> + */ >>> +static int >>> +run_measure_one_config(crypto_args_t *cargs, >>> + crypto_alg_config_t *config) >>> +{ >>> + crypto_run_result_t result; >>> + odp_crypto_session_t session; >>> + int rc = 0; >>> + >>> + if (create_session_from_config(&session, config, cargs)) >>> + rc = -1; >>> + >>> + if (!rc) { >>> + if (cargs->payload_length) { >>> + rc = run_measure_one(cargs, config, &session, >>> + cargs->payload_length, >>> &result); >>> + if (!rc) { >>> + print_result_header(); >>> + print_result(cargs, >>> cargs->payload_length, >>> + config, &result); >>> + } >>> + } else { >>> + unsigned int i; >>> + >>> + print_result_header(); >>> + for (i = 0; >>> + i < (sizeof(payloads) / sizeof(unsigned >>> int)); >>> + i++) { >>> + rc = run_measure_one(cargs, config, >>> &session, >>> + payloads[i], >>> &result); >>> + if (rc) >>> + break; >>> + print_result(cargs, payloads[i], >>> + config, &result); >>> + } >>> + } >>> + } >>> + >>> + if (session != ODP_CRYPTO_SESSION_INVALID) >>> + odp_crypto_session_destroy(session); >>> + return rc; >>> +} >>> + >>> +typedef struct thr_arg { >>> + crypto_args_t crypto_args; >>> + crypto_alg_config_t *crypto_alg_config; >>> +} thr_arg_t; >>> + >>> +static void *run_thr_func(void *arg) >>> +{ >>> + thr_arg_t *thr_args = (thr_arg_t *)arg; >>> + >>> + run_measure_one_config(&thr_args->crypto_args, >>> + thr_args->crypto_alg_config); >>> + return NULL; >>> +} >>> + >>> +int main(int argc, char *argv[]) >>> +{ >>> + crypto_args_t cargs; >>> + odp_pool_t pool; >>> + odp_queue_param_t qparam; >>> + odp_pool_param_t params; >>> + odph_linux_pthread_t thr; >>> + odp_queue_t out_queue = ODP_QUEUE_INVALID; >>> + thr_arg_t thr_arg; >>> + int num_workers = 1; >>> + odp_cpumask_t cpumask; >>> + char cpumaskstr[ODP_CPUMASK_STR_SIZE]; >>> + >>> + /* Parse and store the application arguments */ >>> + parse_args(argc, argv, &cargs); >>> + >>> + /* Init ODP before calling anything else */ >>> + if (odp_init_global(NULL, NULL)) { >>> + app_err("ODP global init failed.\n"); >>> + exit(EXIT_FAILURE); >>> + } >>> + >>> + /* Init this thread */ >>> + odp_init_local(ODP_THREAD_WORKER); >>> + >>> + /* Create packet pool */ >>> + odp_pool_param_init(¶ms); >>> + params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; >>> + params.pkt.len = SHM_PKT_POOL_BUF_SIZE; >>> + params.pkt.num = SHM_PKT_POOL_SIZE / SHM_PKT_POOL_BUF_SIZE; >>> + params.type = ODP_POOL_PACKET; >>> + pool = odp_pool_create("packet_pool", ¶ms); >>> + >>> + if (pool == ODP_POOL_INVALID) { >>> + app_err("packet pool create failed.\n"); >>> + exit(EXIT_FAILURE); >>> + } >>> + odp_pool_print(pool); >>> + >>> + if (cargs.schedule) { >>> + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; >>> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >>> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >>> + out_queue = odp_queue_create("crypto-out", >>> + ODP_QUEUE_TYPE_SCHED, >>> &qparam); >>> + } else if (cargs.poll) { >>> + out_queue = odp_queue_create("crypto-out", >>> + ODP_QUEUE_TYPE_POLL, NULL); >>> + } >>> + if (cargs.schedule || cargs.poll) { >>> + if (out_queue == ODP_QUEUE_INVALID) { >>> + app_err("crypto-out queue create failed.\n"); >>> + exit(EXIT_FAILURE); >>> + } >>> + } >>> + >>> + if (cargs.schedule) { >>> + printf("Run in async scheduled mode\n"); >>> + >>> + thr_arg.crypto_args = cargs; >>> + thr_arg.crypto_alg_config = cargs.alg_config; >>> + num_workers = odp_cpumask_default_worker(&cpumask, >>> + num_workers); >>> + (void)odp_cpumask_to_str(&cpumask, cpumaskstr, >>> + sizeof(cpumaskstr)); >>> + printf("num worker threads: %i\n", >>> + num_workers); >>> + printf("first CPU: %i\n", >>> + odp_cpumask_first(&cpumask)); >>> + printf("cpu mask: %s\n", >>> + cpumaskstr); >>> + } else if (cargs.poll) { >>> + printf("Run in async poll mode\n"); >>> + } else { >>> + printf("Run in sync mode\n"); >>> + } >>> + >>> + if (cargs.alg_config) { >>> + if (cargs.schedule) { >>> + odph_linux_pthread_create(&thr, &cpumask, >>> + run_thr_func, >>> + &thr_arg, >>> + ODP_THREAD_WORKER); >>> + odph_linux_pthread_join(&thr, num_workers); >>> + } else { >>> + run_measure_one_config(&cargs, cargs.alg_config); >>> + } >>> + } else { >>> + unsigned int i; >>> + >>> + for (i = 0; >>> + i < (sizeof(algs_config) / >>> sizeof(crypto_alg_config_t)); >>> + i++) { >>> + run_measure_one_config(&cargs, algs_config + i); >>> + } >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +static void parse_args(int argc, char *argv[], crypto_args_t *cargs) >>> +{ >>> + int opt; >>> + int long_index; >>> + static struct option longopts[] = { >>> + {"algorithm", optional_argument, NULL, 'a'}, >>> + {"debug", no_argument, NULL, 'd'}, >>> + {"flight", optional_argument, NULL, 'f'}, >>> + {"help", no_argument, NULL, 'h'}, >>> + {"iterations", optional_argument, NULL, 'i'}, >>> + {"inplace", no_argument, NULL, 'n'}, >>> + {"payload", optional_argument, NULL, 'l'}, >>> + {"sessions", optional_argument, NULL, 'm'}, >>> + {"reuse", no_argument, NULL, 'r'}, >>> + {"poll", no_argument, NULL, 'p'}, >>> + {"schedule", no_argument, NULL, 's'}, >>> + {NULL, 0, NULL, 0} >>> + }; >>> + >>> + cargs->in_place = 0; >>> + cargs->in_flight = 1; >>> + cargs->debug_packets = 0; >>> + cargs->iteration_count = 10000; >>> + cargs->payload_length = 0; >>> + cargs->alg_config = NULL; >>> + cargs->reuse_packet = 0; >>> + cargs->schedule = 0; >>> + >>> + while (1) { >>> + opt = getopt_long(argc, argv, "+a:c:df:hi:m:nl:spr", >>> + longopts, &long_index); >>> + >>> + if (opt == -1) >>> + break; /* No more options */ >>> + >>> + switch (opt) { >>> + case 'a': >>> + cargs->alg_config = find_config_by_name(optarg); >>> + if (!cargs->alg_config) { >>> + printf("cannot test crypto '%s' >>> configuration\n", >>> + optarg); >>> + usage(argv[0]); >>> + exit(-1); >>> + } >>> + case 'd': >>> + cargs->debug_packets = 1; >>> + break; >>> + case 'i': >>> + cargs->iteration_count = atoi(optarg); >>> + break; >>> + case 'f': >>> + cargs->in_flight = atoi(optarg); >>> + break; >>> + case 'h': >>> + usage(argv[0]); >>> + exit(EXIT_SUCCESS); >>> + break; >>> + case 'm': >>> + cargs->max_sessions = atoi(optarg); >>> + break; >>> + case 'n': >>> + cargs->in_place = 1; >>> + break; >>> + case 'l': >>> + cargs->payload_length = atoi(optarg); >>> + break; >>> + case 'r': >>> + cargs->reuse_packet = 1; >>> + break; >>> + case 's': >>> + cargs->schedule = 1; >>> + break; >>> + case 'p': >>> + cargs->poll = 1; >>> + break; >>> + default: >>> + break; >>> + } >>> + } >>> + >>> + optind = 1; /* reset 'extern optind' from the getopt >>> lib */ >>> + >>> + if ((cargs->in_flight > 1) && cargs->reuse_packet) { >>> + printf("-f (in flight > 1) and -r (reuse packet) options >>> are not compatible\n"); >>> + usage(argv[0]); >>> + exit(-1); >>> + } >>> + if (cargs->schedule && cargs->poll) { >>> + printf("-s (schedule) and -p (poll) options are not >>> compatible\n"); >>> + usage(argv[0]); >>> + exit(-1); >>> + } >>> +} >>> + >>> +/** >>> + * Prinf usage information >>> + */ >>> +static void usage(char *progname) >>> +{ >>> + printf("\n" >>> + "Usage: %s OPTIONS\n" >>> + " E.g. %s -i 100000\n" >>> + "\n" >>> + "OpenDataPlane crypto speed measure.\n" >>> + "Optional OPTIONS\n" >>> + " -a, --algorithm <name> Specify algorithm name (default >>> all)\n" >>> + " Supported values are:\n", >>> + progname, progname); >>> + >>> + print_config_names(" "); >>> + printf(" -d, --debug Enable dump of processed >>> packets.\n" >>> + " -f, --flight <number> Max number of packet processed >>> in parallel (default 1)\n" >>> + " -i, --iterations <number> Number of iterations.\n" >>> + " -n, --inplace Encrypt on place.\n" >>> + " -l, --payload Payload length.\n" >>> + " -r, --reuse Output encrypted packet is passed >>> as input\n" >>> + " to next encrypt iteration.\n" >>> + " -s, --schedule Use scheduler for completion >>> events.\n" >>> + " -p, --poll Poll completion queue for >>> completion events.\n" >>> + " -h, --help Display help and exit.\n" >>> + "\n"); >>> +} >>> >> >> _______________________________________________ >> lng-odp mailing list >> [email protected] >> https://lists.linaro.org/mailman/listinfo/lng-odp >> > > > _______________________________________________ > lng-odp mailing list > [email protected] > https://lists.linaro.org/mailman/listinfo/lng-odp > >
_______________________________________________ lng-odp mailing list [email protected] https://lists.linaro.org/mailman/listinfo/lng-odp
