From patchwork Thu Sep 11 01:10:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: vkamensky X-Patchwork-Id: 37224 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oi0-f71.google.com (mail-oi0-f71.google.com [209.85.218.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 4B14920293 for ; Thu, 11 Sep 2014 01:11:32 +0000 (UTC) Received: by mail-oi0-f71.google.com with SMTP id e131sf35632483oig.10 for ; Wed, 10 Sep 2014 18:11:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:subject:precedence:list-id:list-unsubscribe:list-archive :list-post:list-help:list-subscribe:mime-version:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=T4nuqouNew7JBFPQHhcTYky8Gaa3ks2Un7QF47MYK/g=; b=SKhIT4jI13Kp45VruYTczX9ToRe9+rwS/z/4qrC0EVnVQsmx3/l22vyLQytXRTF38A 2KVpNKIzVgHHNP71JvDQegGeS0cBmJ8mcy7kWIlAZf6lZcpHeN6z/iqASmZjm3nmuDvq 7/ON/RE32Yt/GoMaIyCo/mY8EWJZRwuFQN0slg1mRH93I8gAieGS0BtIaqFbC1Rp7VeC m8wRrktfDmH2UHVc74RTVmxDzVfz24e4aHke1kjImFPEEcqOM3ywbU3ETbV4Nx1C3ygf TR7aXNWlE09A82gxV9gvFSJ1ByKcooAIaS90u0bHJmPPQbfzRcUJZgO8Oy27VxT6okEy IfNw== X-Gm-Message-State: ALoCoQnEVC2slfmnSyTpYVvsS8lpsqx4YgnyYI3je8sd/0xPq34Mnxo4Z4RUatYMZoG4Xds3B0PV X-Received: by 10.50.85.42 with SMTP id e10mr2834842igz.0.1410397891873; Wed, 10 Sep 2014 18:11:31 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.107.182 with SMTP id h51ls2940868qgf.80.gmail; Wed, 10 Sep 2014 18:11:31 -0700 (PDT) X-Received: by 10.52.83.227 with SMTP id t3mr31559001vdy.20.1410397891743; Wed, 10 Sep 2014 18:11:31 -0700 (PDT) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by mx.google.com with ESMTPS id k3si7657423vdq.67.2014.09.10.18.11.31 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 10 Sep 2014 18:11:31 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.173 as permitted sender) client-ip=209.85.220.173; Received: by mail-vc0-f173.google.com with SMTP id le20so5437471vcb.32 for ; Wed, 10 Sep 2014 18:11:31 -0700 (PDT) X-Received: by 10.221.23.66 with SMTP id qz2mr14419079vcb.46.1410397891594; Wed, 10 Sep 2014 18:11:31 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp517410vcb; Wed, 10 Sep 2014 18:11:30 -0700 (PDT) X-Received: by 10.224.161.11 with SMTP id p11mr17781523qax.40.1410397890788; Wed, 10 Sep 2014 18:11:30 -0700 (PDT) Received: from ip-10-141-164-156.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id p5si20727665qah.13.2014.09.10.18.11.30 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 10 Sep 2014 18:11:30 -0700 (PDT) Received-SPF: none (google.com: lng-odp-bounces@lists.linaro.org does not designate permitted sender hosts) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-141-164-156.ec2.internal) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1XRsv2-0000VX-S6; Thu, 11 Sep 2014 01:11:28 +0000 Received: from mail-pa0-f46.google.com ([209.85.220.46]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1XRsuf-0000TU-Qs for lng-odp@lists.linaro.org; Thu, 11 Sep 2014 01:11:06 +0000 Received: by mail-pa0-f46.google.com with SMTP id kq14so5758212pab.19 for ; Wed, 10 Sep 2014 18:11:00 -0700 (PDT) X-Received: by 10.70.52.74 with SMTP id r10mr24624101pdo.12.1410397860228; Wed, 10 Sep 2014 18:11:00 -0700 (PDT) Received: from kamensky-w530.cisco.com.net ([24.6.79.41]) by mx.google.com with ESMTPSA id ju4sm15614063pbc.6.2014.09.10.18.10.58 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 Sep 2014 18:10:59 -0700 (PDT) From: Victor Kamensky To: lng-odp@lists.linaro.org Date: Wed, 10 Sep 2014 18:10:27 -0700 Message-Id: <1410397827-2758-6-git-send-email-victor.kamensky@linaro.org> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1410397827-2758-1-git-send-email-victor.kamensky@linaro.org> References: <1410397827-2758-1-git-send-email-victor.kamensky@linaro.org> X-Topics: crypto patch Subject: [lng-odp] [PATCH 5/5] example: test program that measures speed of ODP crypto operations X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Errors-To: lng-odp-bounces@lists.linaro.org Sender: lng-odp-bounces@lists.linaro.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: victor.kamensky@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.173 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Sample test code that measures speed of ODP crypto operations. o measures operation elapsed, cpu time, and throughput o supports multiple algorithms o supports multiple payload sizes o support synch and async crypto operation modes Signed-off-by: Victor Kamensky --- configure.ac | 1 + example/Makefile.am | 2 +- example/cspeed/Makefile.am | 6 + example/cspeed/odp_cspeed.c | 918 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 926 insertions(+), 1 deletion(-) create mode 100644 example/cspeed/Makefile.am create mode 100644 example/cspeed/odp_cspeed.c diff --git a/configure.ac b/configure.ac index b1fc859..0592334 100644 --- a/configure.ac +++ b/configure.ac @@ -153,6 +153,7 @@ AC_CONFIG_FILES([Makefile platform/linux-keystone2/Makefile platform/linux-dpdk/Makefile example/Makefile + example/cspeed/Makefile example/generator/Makefile example/l2fwd/Makefile example/odp_example/Makefile diff --git a/example/Makefile.am b/example/Makefile.am index 01a3305..d7fb80a 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -1 +1 @@ -SUBDIRS = generator l2fwd odp_example packet packet_netmap timer +SUBDIRS = cspeed generator l2fwd odp_example packet packet_netmap timer diff --git a/example/cspeed/Makefile.am b/example/cspeed/Makefile.am new file mode 100644 index 0000000..9b0b2ee --- /dev/null +++ b/example/cspeed/Makefile.am @@ -0,0 +1,6 @@ +include $(top_srcdir)/example/Makefile.inc + +bin_PROGRAMS = odp_cspeed +odp_cspeed_LDFLAGS = $(AM_LDFLAGS) -static + +dist_odp_cspeed_SOURCES = odp_cspeed.c diff --git a/example/cspeed/odp_cspeed.c b/example/cspeed/odp_cspeed.c new file mode 100644 index 0000000..8e59180 --- /dev/null +++ b/example/cspeed/odp_cspeed.c @@ -0,0 +1,918 @@ +/* Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif /* _GNU_SOURCE */ + +#include +#include +#include +#include +#include +#include + +#include + + +#define cspeed_error(fmt, ...) \ + fprintf(stderr, "%s:%d:%s(): " 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 */ +} cspeed_alg_config_t; + + +/** + * Parsed command line cspeed 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; + + /** + * Maxiumum 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 core to run on. Currently is not used. + */ + int core_count; + + /** + * Number of iteration to repeat crypto operation to get good + * average number. Specified through -i or --terations option. + * Default is 10000. + */ + int iteration_count; + + /** + * Maxium 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_size; + + /** + * Pointer to selected algorithm to test. If NULL all available + * alogorthims are tested. Name of algorithm is passed through + * -a or --algorithm option. + */ + cspeed_alg_config_t *alg_config; +} cspeed_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; +} cspeed_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[], cspeed_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 cspeed_alg_config_t algs_config[] = { + { + .name = "3des-cbs-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-cbs-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 cspeed_alg_config_t * +find_config_by_name(const char *name) { + unsigned int i; + cspeed_alg_config_t *ret = NULL; + + for (i = 0; i < sizeof(algs_config)/sizeof(cspeed_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(cspeed_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(cspeed_args_t *cargs, + unsigned int payload_size, + cspeed_alg_config_t *config, + cspeed_run_result_t *result) +{ + unsigned int throughput; + throughput = (1000000.0 / result->elapsed) * payload_size / 1024; + printf(REPORT_LINE, + config->name, cargs->iteration_count, payload_size, + result->elapsed, result->rusage_self, result->rusage_thread, + throughput); +} + + +/** + * Print piece of memory with given size. + */ +static void +print_memory (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, + cspeed_alg_config_t *config) +{ + odp_crypto_session_params_t params; + enum odp_crypto_ses_create_err ses_create_rc; + odp_buffer_pool_t pkt_pool; + odp_queue_t out_queue; + + int rc = 0; + + memcpy(¶ms, &config->session, sizeof(odp_crypto_session_params_t)); + params.op = ODP_CRYPTO_OP_ENCODE; + params.pref_mode = ODP_CRYPTO_SYNC; + + if (!rc) { + /* Lookup the packet pool */ + pkt_pool = odp_buffer_pool_lookup("packet_pool"); + if (pkt_pool == ODP_BUFFER_POOL_INVALID) { + cspeed_error("Error: 'packet_pool' buffer pull not found\n"); + rc = -1; + } else { + params.output_pool = pkt_pool; + } + } + + + if (!rc) { + out_queue = odp_queue_lookup("crypto-out"); + if (out_queue == ODP_QUEUE_INVALID) { + cspeed_error("Error: 'crypto-out' queue not found\n"); + rc = -1; + } else { + params.compl_queue = out_queue; + } + /* + * Uncomment below for generic implementation if inline + * encryption is desired. Note ks2 implementation cannot + * deal with that. + */ + /* params.compl_queue = ODP_QUEUE_INVALID; */ + } + + if (!rc) { + /* + * Prefered synchronous session create for now, but it could be + * ignored by implementation + */ + if (odp_crypto_session_create(¶ms, session, + &ses_create_rc)) { + cspeed_error("Error: ODP crypto session create failed.\n"); + rc = -1; + } + } + + + return rc; +} + + +/** + * Run measurement iterations for given config and payload size. + * Result of run returned in 'result' out parameter. + */ +static int +run_measure_one(cspeed_args_t *cargs, + cspeed_alg_config_t *config, + odp_crypto_session_t *session, + unsigned int payload_size, + cspeed_run_result_t *result) +{ + odp_crypto_op_params_t params; + + odp_buffer_pool_t pkt_pool; + odp_queue_t out_queue; + odp_packet_t pkt; + odp_buffer_t buf; + + bool posted = 0; + int rc = 0; + + + if (!rc) { + /* Lookup the packet pool */ + pkt_pool = odp_buffer_pool_lookup("packet_pool"); + if (pkt_pool == ODP_BUFFER_POOL_INVALID) { + cspeed_error("Error: pkt_pool not found\n"); + rc = -1; + } + } + + if (!rc) { + out_queue = odp_queue_lookup("crypto-out"); + if (out_queue == ODP_QUEUE_INVALID) { + cspeed_error("Error: 'crypto-out' queue not found\n"); + rc = -1; + } + } + + if (!rc) { + buf = odp_buffer_alloc(pkt_pool); + if (buf == ODP_BUFFER_INVALID) { + cspeed_error("Error: failed to allocate buffer\n"); + rc = -1; + } else { + pkt = odp_packet_from_buffer(buf); + odp_packet_set_len(pkt, payload_size); + { + void *mem = odp_packet_start(pkt); + memset(mem, 1, payload_size); + } + } + } + + if (!rc) { + 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_size; + /* + * Uncomment following line if hash itself have + * to be encrypted. Note ks2 cannot do that + */ + /* params.cipher_range.length += config->hash_adjust; */ + params.auth_range.offset = 0; + params.auth_range.length = payload_size; + params.hash_result_offset = payload_size; + + 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; + + 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. + */ + if (!cargs->in_place) { + buf = odp_buffer_alloc(pkt_pool); + if (buf == ODP_BUFFER_INVALID) { + cspeed_error("Error: failed to allocate buffer\n"); + rc = -1; + } else { + pkt = odp_packet_from_buffer(buf); + odp_packet_set_len(pkt, payload_size); + { + void *mem = + odp_packet_start(pkt); + memset(mem, 1, payload_size); + } + } + } + + params.pkt = pkt; + params.out_pkt = cargs->in_place ? pkt : + ODP_PACKET_INVALID; + } + + + if (cargs->debug_packets) { + mem = odp_packet_start(params.pkt); + print_memory("Packet before encryption:", + mem, payload_size); + } + + rc = odp_crypto_operation(¶ms, &posted, + odp_buffer_from_packet(pkt)); + if (rc) { + cspeed_error("Error: failed odp_crypto_operation: rc = %d\n", rc); + } else { + packets_sent++; + } + } + + if (!posted) { + if (cargs->debug_packets) { + mem = odp_packet_start(params.out_pkt); + print_memory("Imediately encrypted packet", + mem, payload_size + config->hash_adjust); + } + if (!cargs->in_place) { + if (cargs->reuse_packet) { + params.pkt = params.out_pkt; + params.out_pkt = ODP_PACKET_INVALID; + } else { + odp_buffer_free(params.out_pkt); + } + } + } else { + odp_buffer_t completion; + odp_packet_t out_pkt; + + completion = odp_queue_deq(out_queue); + + while (completion != ODP_BUFFER_INVALID) { + out_pkt = odp_crypto_get_operation_compl_packet(completion); + + if (cargs->debug_packets) { + mem = odp_packet_start(out_pkt); + print_memory("Receieved encrypted packet", + mem, payload_size + config->hash_adjust); + } + if (!cargs->in_place) { + if (cargs->reuse_packet) { + params.pkt = out_pkt; + params.out_pkt = ODP_PACKET_INVALID; + } else { + odp_buffer_free(out_pkt); + } + } + packets_received++; + + completion = 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(cspeed_args_t *cargs, + cspeed_alg_config_t *config) +{ + cspeed_run_result_t result; + odp_crypto_session_t session; + int rc = 0; + + if (create_session_from_config(&session, config)) { + rc = -1; + } + + if (!rc) { + if (cargs->payload_size) { + rc = run_measure_one(cargs, config, &session, + cargs->payload_size, &result); + if (!rc){ + print_result_header(); + print_result(cargs, cargs->payload_size, + 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; + } else { + print_result(cargs, payloads[i], + config, &result); + } + } + } + } + + + // destroy session + if (session != ODP_CRYPTO_SESSION_INVALID) { + odp_crypto_session_destroy(session); + } + return rc; +} + + +int main(int argc, char *argv[]) +{ + int thr_id; + cspeed_args_t cargs; + odp_buffer_pool_t pool; + odp_queue_t out_queue; + void *pool_base; + + /* Init ODP before calling anything else */ + if (odp_init_global()) { + cspeed_error("Error: ODP global init failed.\n"); + exit(EXIT_FAILURE); + } + + /* Parse and store the application arguments */ + parse_args(argc, argv, &cargs); + + /* Init this thread */ + thr_id = odp_thread_create(0); + odp_init_local(thr_id); + + /* Create packet pool */ + pool_base = odp_shm_reserve("shm_packet_pool", + SHM_PKT_POOL_SIZE, ODP_CACHE_LINE_SIZE); + if (pool_base == NULL) { + cspeed_error("Error: packet pool mem alloc failed.\n"); + exit(EXIT_FAILURE); + } + + pool = odp_buffer_pool_create("packet_pool", pool_base, + SHM_PKT_POOL_SIZE, + SHM_PKT_POOL_BUF_SIZE, + ODP_CACHE_LINE_SIZE, + ODP_BUFFER_TYPE_PACKET); + if (pool == ODP_BUFFER_POOL_INVALID) { + cspeed_error("Error: packet pool create failed.\n"); + exit(EXIT_FAILURE); + } + /* odp_buffer_pool_print(pool); */ + + out_queue = odp_queue_create("crypto-out",ODP_QUEUE_TYPE_POLL, NULL); + if (out_queue == ODP_QUEUE_INVALID) { + cspeed_error("Can't create out crypto queue\n"); + exit(EXIT_FAILURE); + } + + if (cargs.alg_config) { + run_measure_one_config(&cargs, cargs.alg_config); + } else { + unsigned int i; + for (i = 0; + i < sizeof(algs_config)/sizeof(cspeed_alg_config_t); + i++) { + run_measure_one_config(&cargs, algs_config + i); + } + } + + return 0; +} + + +static void parse_args(int argc, char *argv[], cspeed_args_t *cargs) +{ + int opt; + int long_index; + static struct option longopts[] = { + {"algorithm", optional_argument, NULL, 'a'}, + {"count", optional_argument, NULL, 'c'}, + {"debug", no_argument, NULL, 'd'}, + {"flight", optional_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, /* return 'h' */ + {"iterations", optional_argument, NULL, 'i'}, + {"inplace", no_argument, NULL, 'n'}, + {"payload", optional_argument, NULL, 'p'}, + {"sessions", optional_argument, NULL, 'm'}, + {"reuse", no_argument, NULL, 'r'}, + {NULL, 0, NULL, 0} + }; + + cargs->in_place = 0; + cargs->in_flight = 1; + cargs->debug_packets = 0; + cargs->core_count = 1; + cargs->iteration_count = 10000; + cargs->payload_size = 0; + cargs->alg_config = NULL; + + while (1) { + opt = getopt_long(argc, argv, "+a:c:df:hi:m:np:r", + 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 'c': + cargs->core_count = atoi(optarg); + break; + 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 'p': + cargs->payload_size = atoi(optarg); + break; + case 'r': + cargs->reuse_packet = 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->in_flight > 1) && cargs->in_place) { + printf("-f (in flight > 1) and -n (in place) 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 Specify algorithm name (default all)\n" + " Supported values are:\n", + progname, progname); + + print_config_names(" "); + printf(" -c, --count Core count. (NOT used)\n" + " -d, --debug Enable dump of processed packets.\n" + " -f, --flight Max number of packet processed in parallel (default 1)\n" + " -i, --iterations Number of iterations.\n" + " -n, --inplace Encrypt on place (ks2 does not support this).\n" + " -p, --payload Payload size.\n" + " -r, --reuse Output encrypted packet is passed as input\n" + " to next encrypt iteration.\n" + " -h, --help Display help and exit.\n" + "\n"); +}