API Reference Manual  1.45.1
odp_crypto.c

Performance test application for crypto APIs

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2015-2018 Linaro Limited
* Copyright (c) 2023 Nokia
*/
#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_api.h>
#include <odp/helper/odph_api.h>
#define POOL_NUM_PKT 64
#define AAD_LEN 8 /* typical AAD length used in IPsec when ESN is not in use */
#define MAX_AUTH_DIGEST_LEN 32 /* maximum MAC length in bytes */
static uint8_t test_aad[AAD_LEN] = "01234567";
static uint8_t test_iv[16] = "0123456789abcdef";
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_key20[20] = { 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14,
};
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
};
static uint8_t test_key32[32] = { 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19,
0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
0x1f, 0x20,
};
static uint8_t test_key64[64] = { 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19,
0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x4b, 0x2c, 0x2d,
0x2e, 0x2f, 0x30, 0x31, 0x32,
0x33, 0x34, 0x55, 0x36, 0x37,
0x38, 0x39, 0x5a, 0x3b, 0x3c,
0x3d, 0x3e, 0x5f, 0x40,
};
typedef struct {
const char *name;
int cipher_in_bit_mode;
int auth_in_bit_mode;
} crypto_alg_config_t;
typedef struct {
int debug_packets;
int in_place;
int reuse_packet;
int in_flight;
int iteration_count;
int max_sessions;
int payload_length;
crypto_alg_config_t *alg_config;
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 {
double elapsed;
double rusage_self;
double rusage_thread;
} crypto_run_result_t;
typedef struct {
struct timeval tv;
struct rusage ru_self;
struct rusage ru_thread;
} time_record_t;
/* Arguments for one test run */
typedef struct test_run_arg_t {
crypto_args_t crypto_args;
crypto_alg_config_t *crypto_alg_config;
} test_run_arg_t;
static void parse_args(int argc, char *argv[], crypto_args_t *cargs);
static void usage(char *progname);
static unsigned int payloads[] = {
16,
64,
256,
1024,
8192,
16384
};
static unsigned num_payloads;
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)
},
.cipher_iv_len = 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)
},
.cipher_iv_len = 8,
.auth_alg = ODP_AUTH_ALG_MD5_HMAC,
.auth_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.auth_digest_len = 12,
},
},
{
.name = "null-hmac-md5-96",
.session = {
.cipher_alg = ODP_CIPHER_ALG_NULL,
.auth_alg = ODP_AUTH_ALG_MD5_HMAC,
.auth_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.auth_digest_len = 12,
},
},
{
.name = "aes-cbc-null",
.session = {
.cipher_alg = ODP_CIPHER_ALG_AES_CBC,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_alg = ODP_AUTH_ALG_NULL
},
},
{
.name = "aes-cbc-hmac-sha1-96",
.session = {
.cipher_alg = ODP_CIPHER_ALG_AES_CBC,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_key = {
.data = test_key20,
.length = sizeof(test_key20)
},
.auth_digest_len = 12,
},
},
{
.name = "null-hmac-sha1-96",
.session = {
.cipher_alg = ODP_CIPHER_ALG_NULL,
.auth_key = {
.data = test_key20,
.length = sizeof(test_key20)
},
.auth_digest_len = 12,
},
},
{
.name = "aes-ctr-null",
.session = {
.cipher_alg = ODP_CIPHER_ALG_AES_CTR,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_alg = ODP_AUTH_ALG_NULL
},
},
{
.name = "aes-ctr-hmac-sha1-96",
.session = {
.cipher_alg = ODP_CIPHER_ALG_AES_CTR,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_key = {
.data = test_key20,
.length = sizeof(test_key20)
},
.auth_digest_len = 12,
},
},
{
.name = "null-hmac-sha256-128",
.session = {
.cipher_alg = ODP_CIPHER_ALG_NULL,
.auth_key = {
.data = test_key32,
.length = sizeof(test_key32)
},
.auth_digest_len = 16,
},
},
{
.name = "null-hmac-sha512-256",
.session = {
.cipher_alg = ODP_CIPHER_ALG_NULL,
.auth_key = {
.data = test_key64,
.length = sizeof(test_key64)
},
.auth_digest_len = 32,
},
},
{
.name = "null-aes-gmac",
.session = {
.cipher_alg = ODP_CIPHER_ALG_NULL,
.auth_alg = ODP_AUTH_ALG_AES_GMAC,
.auth_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.auth_iv_len = 12,
.auth_digest_len = 16,
},
},
{
.name = "aes-gcm",
.session = {
.cipher_alg = ODP_CIPHER_ALG_AES_GCM,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 12,
.auth_alg = ODP_AUTH_ALG_AES_GCM,
.auth_digest_len = 16,
.auth_aad_len = AAD_LEN,
},
},
{
.name = "aes-ccm",
.session = {
.cipher_alg = ODP_CIPHER_ALG_AES_CCM,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 11,
.auth_alg = ODP_AUTH_ALG_AES_CCM,
.auth_digest_len = 16,
.auth_aad_len = AAD_LEN,
},
},
{
.name = "chacha20-poly1305",
.session = {
.cipher_key = {
.data = test_key32,
.length = sizeof(test_key32)
},
.cipher_iv_len = 12,
.auth_digest_len = 16,
.auth_aad_len = AAD_LEN,
},
},
{
.name = "zuc-eea3",
.session = {
.cipher_alg = ODP_CIPHER_ALG_ZUC_EEA3,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_alg = ODP_AUTH_ALG_NULL,
},
},
{
.name = "zuc-eia3",
.session = {
.cipher_alg = ODP_CIPHER_ALG_NULL,
.auth_alg = ODP_AUTH_ALG_ZUC_EIA3,
.auth_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.auth_iv_len = 16,
.auth_digest_len = 4,
},
},
{
.name = "zuc-eea3-zuc-eia3",
.session = {
.cipher_alg = ODP_CIPHER_ALG_ZUC_EEA3,
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_alg = ODP_AUTH_ALG_ZUC_EIA3,
.auth_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.auth_iv_len = 16,
.auth_digest_len = 4,
},
},
{
.name = "snow3g-uea2",
.session = {
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_alg = ODP_AUTH_ALG_NULL,
},
},
{
.name = "snow3g-uia2",
.session = {
.cipher_alg = ODP_CIPHER_ALG_NULL,
.auth_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.auth_iv_len = 16,
.auth_digest_len = 4,
},
},
{
.name = "snow3g-uea2-snow3g-uia2",
.session = {
.cipher_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.cipher_iv_len = 16,
.auth_key = {
.data = test_key16,
.length = sizeof(test_key16)
},
.auth_iv_len = 16,
.auth_digest_len = 4,
},
},
};
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 < ODPH_ARRAY_SIZE(algs_config); i++) {
if (strcmp(algs_config[i].name, name) == 0) {
ret = algs_config + i;
break;
}
}
return ret;
}
static void
print_config_names(const char *prefix) {
unsigned int i;
for (i = 0; i < ODPH_ARRAY_SIZE(algs_config); i++)
printf("%s %s\n", prefix, algs_config[i].name);
}
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);
}
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;
}
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);
}
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);
}
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 "%30.30s %15s %15s %15s %15s %15s %15s\n"
#define REPORT_LINE "%30.30s %15d %15d %15.3f %15.3f %15.3f %15d\n"
static void
print_result_header(void)
{
printf(REPORT_HEADER,
"algorithm", "avg over #", "payload (bytes)", "elapsed (us)",
"rusg self (us)", "rusg thrd (us)", "throughput (Kb)");
}
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);
}
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");
}
static int
create_session_from_config(odp_crypto_session_t *session,
crypto_alg_config_t *config,
crypto_args_t *cargs)
{
odp_pool_t pkt_pool;
odp_queue_t out_queue;
memcpy(&params, &config->session, sizeof(odp_crypto_session_param_t));
params.auth_cipher_text = true;
/* Lookup the packet pool */
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
ODPH_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) {
ODPH_ERR("crypto-out queue not found\n");
return -1;
}
params.compl_queue = out_queue;
} else {
}
if (odp_crypto_session_create(&params, session,
&ses_create_rc)) {
switch (ses_create_rc) {
printf(" requested algorithm combination not supported\n");
return 1;
printf(" requested algorithm order not supported\n");
return 1;
printf(" requested session parameters not supported\n");
return 1;
default:
break;
}
ODPH_ERR("crypto session create failed.\n");
return -1;
}
return 0;
}
make_packet(odp_pool_t pkt_pool, unsigned int payload_length)
{
pkt = odp_packet_alloc(pkt_pool, payload_length);
if (pkt == ODP_PACKET_INVALID) {
ODPH_ERR("failed to allocate buffer\n");
return pkt;
}
void *mem = odp_packet_data(pkt);
memset(mem, 1, payload_length);
return pkt;
}
static int
run_measure_one(crypto_args_t *cargs,
crypto_alg_config_t *config,
unsigned int payload_length,
crypto_run_result_t *result)
{
odp_pool_t pkt_pool;
odp_queue_t out_queue;
int rc = 0;
uint32_t packet_len = payload_length + MAX_AUTH_DIGEST_LEN;
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
ODPH_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) {
ODPH_ERR("crypto-out queue not found\n");
return -1;
}
}
if (cargs->reuse_packet) {
pkt = make_packet(pkt_pool, packet_len);
if (ODP_PACKET_INVALID == pkt)
return -1;
}
time_record_t start, end;
int packets_sent = 0;
int packets_received = 0;
/* Initialize parameters block */
memset(&params, 0, sizeof(params));
params.session = *session;
params.cipher_iv_ptr = test_iv;
params.auth_iv_ptr = test_iv;
params.aad_ptr = test_aad;
params.cipher_range.offset = 0;
params.cipher_range.length = config->cipher_in_bit_mode ? payload_length * 8
: payload_length;
params.auth_range.offset = 0;
params.auth_range.length = config->auth_in_bit_mode ? payload_length * 8
: payload_length;
params.hash_result_offset = payload_length;
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)) {
odp_packet_t out_pkt;
if (!cargs->reuse_packet) {
pkt = make_packet(pkt_pool, packet_len);
if (ODP_PACKET_INVALID == pkt)
return -1;
}
out_pkt = cargs->in_place ? pkt : ODP_PACKET_INVALID;
if (cargs->debug_packets) {
mem = odp_packet_data(pkt);
print_mem("Packet before encryption:",
mem, payload_length);
}
if (cargs->schedule || cargs->poll) {
rc = odp_crypto_op_enq(&pkt, &out_pkt,
&params, 1);
if (rc <= 0) {
ODPH_ERR("failed odp_crypto_packet_op_enq: rc = %d\n", rc);
if (!cargs->reuse_packet)
break;
}
packets_sent += rc;
} else {
rc = odp_crypto_op(&pkt, &out_pkt,
&params, 1);
if (rc <= 0) {
ODPH_ERR("failed odp_crypto_packet_op: rc = %d\n", rc);
if (!cargs->reuse_packet)
break;
}
packets_sent += rc;
packets_received++;
if (odp_unlikely(odp_crypto_result(NULL, out_pkt) != 0)) {
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 "
"packet",
mem,
payload_length +
config->session.
auth_digest_len);
}
if (cargs->reuse_packet)
pkt = out_pkt;
else
odp_packet_free(out_pkt);
}
}
if (cargs->schedule || cargs->poll) {
odp_packet_t out_pkt;
if (cargs->schedule)
ev = odp_schedule(NULL,
else
ev = odp_queue_deq(out_queue);
while (ev != ODP_EVENT_INVALID) {
if (odp_unlikely(odp_crypto_result(NULL, out_pkt) != 0)) {
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",
mem,
payload_length +
config->
session.auth_digest_len);
}
if (cargs->reuse_packet)
pkt = out_pkt;
else
odp_packet_free(out_pkt);
packets_received++;
if (cargs->schedule)
ev = odp_schedule(NULL,
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;
}
if (cargs->reuse_packet)
return rc < 0 ? rc : 0;
}
static int check_cipher_alg(const odp_crypto_capability_t *capa,
{
switch (alg) {
if (capa->ciphers.bit.null)
return 0;
break;
if (capa->ciphers.bit.des)
return 0;
break;
if (capa->ciphers.bit.trides_cbc)
return 0;
break;
if (capa->ciphers.bit.aes_cbc)
return 0;
break;
if (capa->ciphers.bit.aes_ctr)
return 0;
break;
if (capa->ciphers.bit.aes_gcm)
return 0;
break;
if (capa->ciphers.bit.aes_ccm)
return 0;
break;
return 0;
break;
if (capa->ciphers.bit.zuc_eea3)
return 0;
break;
if (capa->ciphers.bit.snow3g_uea2)
return 0;
break;
default:
break;
}
return -1;
}
static int check_auth_alg(const odp_crypto_capability_t *capa,
{
switch (alg) {
if (capa->auths.bit.null)
return 0;
break;
if (capa->auths.bit.md5_hmac)
return 0;
break;
if (capa->auths.bit.sha1_hmac)
return 0;
break;
if (capa->auths.bit.sha256_hmac)
return 0;
break;
if (capa->auths.bit.sha384_hmac)
return 0;
break;
if (capa->auths.bit.sha512_hmac)
return 0;
break;
if (capa->auths.bit.aes_gcm)
return 0;
break;
if (capa->auths.bit.aes_gmac)
return 0;
break;
if (capa->auths.bit.aes_ccm)
return 0;
break;
return 0;
break;
if (capa->auths.bit.zuc_eia3)
return 0;
break;
if (capa->auths.bit.snow3g_uia2)
return 0;
break;
default:
break;
}
return -1;
}
static int check_cipher_params(const odp_crypto_capability_t *crypto_capa,
int *bit_mode)
{
int num, rc;
if (check_cipher_alg(crypto_capa, param->cipher_alg))
return 1;
num = odp_crypto_cipher_capability(param->cipher_alg, NULL, 0);
if (num <= 0)
return 1;
rc = odp_crypto_cipher_capability(param->cipher_alg, cipher_capa, num);
if (rc < num)
num = rc;
for (int n = 0; n < num; n++) {
odp_crypto_cipher_capability_t *capa = &cipher_capa[n];
if (capa->key_len != param->cipher_key.length ||
capa->iv_len != param->cipher_iv_len)
continue;
*bit_mode = capa->bit_mode;
return 0;
}
return 1;
}
static int aad_len_ok(const odp_crypto_auth_capability_t *capa, uint32_t len)
{
if (len < capa->aad_len.min || len > capa->aad_len.max)
return 0;
if (len == capa->aad_len.min)
return 1;
if (capa->aad_len.inc == 0)
return 0;
return ((len - capa->aad_len.min) % capa->aad_len.inc) == 0;
}
static int check_auth_params(const odp_crypto_capability_t *crypto_capa,
int *bit_mode)
{
int num, rc;
if (param->auth_digest_len > MAX_AUTH_DIGEST_LEN) {
ODPH_ERR("MAX_AUTH_DIGEST_LEN too low\n");
return 1;
}
if (check_auth_alg(crypto_capa, param->auth_alg))
return 1;
num = odp_crypto_auth_capability(param->auth_alg, NULL, 0);
if (num <= 0)
return 1;
rc = odp_crypto_auth_capability(param->auth_alg, auth_capa, num);
if (rc < num)
num = rc;
for (int n = 0; n < num; n++) {
odp_crypto_auth_capability_t *capa = &auth_capa[n];
if (capa->digest_len != param->auth_digest_len ||
capa->key_len != param->auth_key.length ||
capa->iv_len != param->auth_iv_len)
continue;
if (!aad_len_ok(capa, param->auth_aad_len))
continue;
*bit_mode = capa->bit_mode;
return 0;
}
return 1;
}
static int run_measure_one_config(test_run_arg_t *arg)
{
crypto_run_result_t result;
crypto_args_t *cargs = &arg->crypto_args;
crypto_alg_config_t *config = arg->crypto_alg_config;
odp_crypto_capability_t crypto_capa = arg->crypto_capa;
int rc = 0;
printf("\n");
if (check_cipher_params(&crypto_capa, &config->session,
&config->cipher_in_bit_mode)) {
printf(" Cipher algorithm not supported\n");
rc = 1;
}
if (check_auth_params(&crypto_capa, &config->session,
&config->auth_in_bit_mode)) {
printf(" Auth algorithm not supported\n");
rc = 1;
}
#if ODP_VERSION_API >= ODP_VERSION_API_NUM(1, 42, 0)
/* Bit mode ciphers can now be used in byte mode. */
config->cipher_in_bit_mode = 0;
config->auth_in_bit_mode = 0;
#endif
if (rc == 0)
rc = create_session_from_config(&session, config, cargs);
if (rc) {
printf(" => %s skipped\n", config->name);
return rc > 0 ? 0 : -1;
}
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 i;
print_result_header();
for (i = 0; i < num_payloads; i++) {
rc = run_measure_one(cargs, config, &session,
payloads[i], &result);
if (rc)
break;
print_result(cargs, payloads[i],
config, &result);
}
}
return rc;
}
static int run_thr_func(void *arg)
{
run_measure_one_config((test_run_arg_t *)arg);
return 0;
}
int main(int argc, char *argv[])
{
crypto_args_t cargs;
odp_pool_t pool;
test_run_arg_t test_run_arg;
odp_cpumask_t cpumask;
char cpumaskstr[ODP_CPUMASK_STR_SIZE];
int num_workers = 1;
odph_helper_options_t helper_options;
odph_thread_t thread_tbl[num_workers];
odph_thread_common_param_t thr_common;
odph_thread_param_t thr_param;
odp_instance_t instance;
odp_init_t init_param;
uint32_t max_seg_len;
uint32_t i;
/* 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;
memset(&cargs, 0, sizeof(cargs));
/* Parse and store the application arguments */
parse_args(argc, argv, &cargs);
/* Init ODP before calling anything else */
if (odp_init_global(&instance, &init_param, NULL)) {
ODPH_ERR("ODP global init failed.\n");
exit(EXIT_FAILURE);
}
/* Init this thread */
memset(&crypto_capa, 0, sizeof(crypto_capa));
if (odp_crypto_capability(&crypto_capa)) {
ODPH_ERR("Crypto capability request failed.\n");
exit(EXIT_FAILURE);
}
if (cargs.schedule && crypto_capa.queue_type_sched == 0) {
ODPH_ERR("scheduled type completion queue not supported.\n");
exit(EXIT_FAILURE);
}
if (cargs.poll && crypto_capa.queue_type_plain == 0) {
ODPH_ERR("plain type completion queue not supported.\n");
exit(EXIT_FAILURE);
}
if (odp_pool_capability(&pool_capa)) {
ODPH_ERR("Pool capability request failed.\n");
exit(EXIT_FAILURE);
}
max_seg_len = pool_capa.pkt.max_seg_len;
for (i = 0; i < ODPH_ARRAY_SIZE(payloads); i++) {
if (payloads[i] + MAX_AUTH_DIGEST_LEN > max_seg_len)
break;
}
num_payloads = i;
/* Create packet pool */
params.pkt.seg_len = max_seg_len;
params.pkt.len = max_seg_len;
params.pkt.num = POOL_NUM_PKT;
pool = odp_pool_create("packet_pool", &params);
if (pool == ODP_POOL_INVALID) {
ODPH_ERR("packet pool create failed.\n");
exit(EXIT_FAILURE);
}
if (cargs.schedule) {
out_queue = odp_queue_create("crypto-out", &qparam);
} else if (cargs.poll) {
out_queue = odp_queue_create("crypto-out", &qparam);
}
if (cargs.schedule || cargs.poll) {
if (out_queue == ODP_QUEUE_INVALID) {
ODPH_ERR("crypto-out queue create failed.\n");
exit(EXIT_FAILURE);
}
}
if (cargs.schedule) {
printf("Run in async scheduled mode\n");
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");
}
test_run_arg.crypto_args = cargs;
test_run_arg.crypto_alg_config = cargs.alg_config;
test_run_arg.crypto_capa = crypto_capa;
if (cargs.alg_config) {
odph_thread_common_param_init(&thr_common);
thr_common.instance = instance;
thr_common.cpumask = &cpumask;
thr_common.share_param = 1;
if (cargs.schedule) {
odph_thread_param_init(&thr_param);
thr_param.start = run_thr_func;
thr_param.arg = &test_run_arg;
thr_param.thr_type = ODP_THREAD_WORKER;
memset(thread_tbl, 0, sizeof(thread_tbl));
odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers);
odph_thread_join(thread_tbl, num_workers);
} else {
run_measure_one_config(&test_run_arg);
}
} else {
for (i = 0; i < ODPH_ARRAY_SIZE(algs_config); i++) {
test_run_arg.crypto_alg_config = algs_config + i;
run_measure_one_config(&test_run_arg);
}
}
if (cargs.schedule || cargs.poll)
odp_queue_destroy(out_queue);
if (odp_pool_destroy(pool)) {
ODPH_ERR("Error: pool destroy\n");
exit(EXIT_FAILURE);
}
if (odp_term_local()) {
ODPH_ERR("Error: term local\n");
exit(EXIT_FAILURE);
}
if (odp_term_global(instance)) {
ODPH_ERR("Error: term global\n");
exit(EXIT_FAILURE);
}
return 0;
}
static void parse_args(int argc, char *argv[], crypto_args_t *cargs)
{
int opt;
int long_index;
static const 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}
};
static const char *shortopts = "+a:c:df:hi:m:nl:spr";
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, shortopts, 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);
}
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 '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);
}
}
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");
}
#define odp_unlikely(x)
Branch unlikely taken.
Definition: spec/hints.h:64
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int odp_cpumask_first(const odp_cpumask_t *mask)
Find first set CPU in mask.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
int odp_crypto_cipher_capability(odp_cipher_alg_t cipher, odp_crypto_cipher_capability_t capa[], int num)
Query supported cipher algorithm capabilities.
odp_cipher_alg_t
Crypto API cipher algorithm.
int odp_crypto_capability(odp_crypto_capability_t *capa)
Query crypto capabilities.
void odp_crypto_session_param_init(odp_crypto_session_param_t *param)
Initialize crypto session parameters.
uint64_t odp_crypto_session_t
Crypto API opaque session handle.
int odp_crypto_session_create(const odp_crypto_session_param_t *param, odp_crypto_session_t *session, odp_crypto_ses_create_err_t *status)
Crypto session creation.
int odp_crypto_result(odp_crypto_packet_result_t *result, odp_packet_t packet)
Get crypto operation results from a crypto processed packet.
int odp_crypto_session_destroy(odp_crypto_session_t session)
Crypto session destroy.
int odp_crypto_op(const odp_packet_t pkt_in[], odp_packet_t pkt_out[], const odp_crypto_packet_op_param_t param[], int num_pkt)
Crypto packet operation.
odp_auth_alg_t
Crypto API authentication algorithm.
odp_crypto_ses_create_err_t
Crypto API session creation return code.
odp_packet_t odp_crypto_packet_from_event(odp_event_t ev)
Return crypto processed packet that is associated with event.
int odp_crypto_op_enq(const odp_packet_t pkt_in[], const odp_packet_t pkt_out[], const odp_crypto_packet_op_param_t param[], int num_pkt)
Crypto packet operation.
int odp_crypto_auth_capability(odp_auth_alg_t auth, odp_crypto_auth_capability_t capa[], int num)
Query supported authentication algorithm capabilities.
@ ODP_CIPHER_ALG_SNOW3G_UEA2
Confidentiality UEA2 algorithm (128-EEA1)
@ ODP_CIPHER_ALG_AES_CCM
AES-CCM.
@ ODP_CIPHER_ALG_AES_CTR
AES with counter mode.
@ ODP_CIPHER_ALG_CHACHA20_POLY1305
ChaCha20-Poly1305.
@ ODP_CIPHER_ALG_AES_CBC
AES with cipher block chaining.
@ ODP_CIPHER_ALG_AES_GCM
AES-GCM.
@ ODP_CIPHER_ALG_3DES_CBC
Triple DES with cipher block chaining.
@ ODP_CIPHER_ALG_DES
DES.
@ ODP_CIPHER_ALG_NULL
No cipher algorithm specified.
@ ODP_CIPHER_ALG_ZUC_EEA3
ZUC based confidentiality algorithm.
@ ODP_AUTH_ALG_SHA384_HMAC
HMAC-SHA-384.
@ ODP_AUTH_ALG_CHACHA20_POLY1305
ChaCha20-Poly1305 AEAD.
@ ODP_AUTH_ALG_NULL
No authentication algorithm specified.
@ ODP_AUTH_ALG_MD5_HMAC
HMAC-MD5.
@ ODP_AUTH_ALG_SHA512_HMAC
HMAC-SHA-512.
@ ODP_AUTH_ALG_SHA1_HMAC
HMAC-SHA-1.
@ ODP_AUTH_ALG_SHA256_HMAC
HMAC-SHA-256.
@ ODP_AUTH_ALG_SNOW3G_UIA2
Integrity UIA2 algorithm (128-EIA1)
@ ODP_AUTH_ALG_AES_GMAC
AES-GMAC.
@ ODP_AUTH_ALG_AES_GCM
AES-GCM.
@ ODP_AUTH_ALG_AES_CCM
AES-CCM.
@ ODP_AUTH_ALG_ZUC_EIA3
ZUC-based integrity algorithm.
@ ODP_CRYPTO_SES_ERR_ALG_COMBO
Unsupported combination of algorithms.
@ ODP_CRYPTO_SES_ERR_ALG_ORDER
Unsupported order of cipher and auth.
@ ODP_CRYPTO_SES_ERR_PARAMS
Unsupported combination of session creation parameters.
@ ODP_CRYPTO_OP_ENCODE
Encrypt and/or compute authentication ICV.
@ ODP_CRYPTO_SYNC
Synchronous, return results immediately.
@ ODP_CRYPTO_ASYNC
Asynchronous, return results via posted event.
#define ODP_EVENT_INVALID
Invalid event.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
void * odp_packet_data(odp_packet_t pkt)
Packet data pointer.
odp_packet_t odp_packet_alloc(odp_pool_t pool, uint32_t len)
Allocate a packet from a packet pool.
void odp_packet_free(odp_packet_t pkt)
Free packet.
#define ODP_PACKET_INVALID
Invalid packet.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
int odp_pool_capability(odp_pool_capability_t *capa)
Query pool capabilities.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
void odp_pool_print(odp_pool_t pool)
Print pool info.
odp_pool_t odp_pool_lookup(const char *name)
Find a pool by name.
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_PACKET
Packet pool.
odp_queue_t odp_queue_lookup(const char *name)
Find a queue by name.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
#define ODP_QUEUE_INVALID
Invalid queue.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
odp_queue_t odp_queue_create(const char *name, const odp_queue_param_t *param)
Queue create.
int odp_queue_destroy(odp_queue_t queue)
Destroy ODP queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
@ ODP_QUEUE_TYPE_PLAIN
Plain queue.
#define ODP_SCHED_SYNC_PARALLEL
Parallel scheduled queues.
#define ODP_SCHED_NO_WAIT
Do not wait.
int odp_schedule_default_prio(void)
Default scheduling priority level.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
odp_event_t odp_schedule(odp_queue_t *from, uint64_t wait)
Schedule an event.
#define ODP_SCHED_GROUP_ALL
Group of all threads.
void odp_sys_info_print(void)
Print system info.
@ ODP_THREAD_WORKER
Worker thread.
The OpenDataPlane API.
Authentication algorithm capabilities.
uint32_t min
Minimum AAD length in bytes.
uint32_t max
Maximum AAD length in bytes.
odp_bool_t bit_mode
Auth algorithm supports bit mode.
uint32_t inc
Increment of supported lengths between min and max (in bytes)
uint32_t digest_len
Digest length in bytes.
struct odp_crypto_auth_capability_t::@29 aad_len
Additional Authenticated Data (AAD) lengths.
uint32_t key_len
Key length in bytes.
uint32_t iv_len
IV length in bytes.
odp_bool_t queue_type_sched
Scheduled crypto completion queue support.
odp_crypto_cipher_algos_t ciphers
Supported cipher algorithms.
odp_bool_t queue_type_plain
Plain crypto completion queue support.
odp_crypto_auth_algos_t auths
Supported authentication algorithms.
Cipher algorithm capabilities.
odp_bool_t bit_mode
Cipher supports bit mode.
uint32_t key_len
Key length in bytes.
uint32_t iv_len
IV length in bytes.
uint32_t length
Key length in bytes.
Crypto packet API per packet operation parameters.
uint32_t hash_result_offset
Offset from start of packet for hash result.
const uint8_t * aad_ptr
Pointer to AAD.
const uint8_t * cipher_iv_ptr
IV pointer for cipher.
const uint8_t * auth_iv_ptr
IV pointer for authentication.
odp_packet_data_range_t cipher_range
Data range to be ciphered.
odp_crypto_session_t session
Session handle from creation.
odp_packet_data_range_t auth_range
Data range to be authenticated.
Crypto API session creation parameters.
odp_bool_t auth_cipher_text
Authenticate cipher vs.
odp_crypto_key_t auth_key
Authentication key.
uint32_t auth_aad_len
Additional Authenticated Data (AAD) length in bytes.
odp_crypto_key_t cipher_key
Cipher key.
odp_queue_t compl_queue
Async mode completion event queue.
odp_pool_t output_pool
Output pool.
uint32_t cipher_iv_len
Cipher IV length.
uint32_t auth_digest_len
Authentication digest length in bytes.
odp_auth_alg_t auth_alg
Authentication algorithm.
odp_crypto_op_mode_t op_mode
Operation mode when using packet interface: sync or async.
odp_cipher_alg_t cipher_alg
Cipher algorithm.
uint32_t auth_iv_len
Authentication IV length.
odp_crypto_op_t op
Encode vs.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
uint32_t offset
Offset from beginning of packet.
uint32_t length
Length of data to operate on.
struct odp_pool_capability_t::@119 pkt
Packet pool capabilities
uint32_t max_seg_len
Maximum packet segment data length in bytes.
Pool parameters.
uint32_t num
Number of buffers in the pool.
odp_pool_type_t type
Pool type.
struct odp_pool_param_t::@123 pkt
Parameters for packet pools.
uint32_t len
Minimum length of 'num' packets.
uint32_t seg_len
Minimum number of packet data bytes that can be stored in the first segment of a newly allocated pack...
ODP Queue parameters.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
odp_schedule_group_t group
Thread group.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
uint32_t null
ODP_AUTH_ALG_NULL.
uint32_t sha1_hmac
ODP_AUTH_ALG_SHA1_HMAC.
uint32_t sha512_hmac
ODP_AUTH_ALG_SHA512_HMAC.
uint32_t zuc_eia3
ODP_AUTH_ALG_ZUC_EIA3.
uint32_t snow3g_uia2
ODP_AUTH_ALG_SNOW3G_UIA2.
uint32_t aes_gmac
ODP_AUTH_ALG_AES_GMAC.
uint32_t aes_gcm
ODP_AUTH_ALG_AES_GCM.
uint32_t md5_hmac
ODP_AUTH_ALG_MD5_HMAC.
struct odp_crypto_auth_algos_t::@28 bit
Authentication algorithms.
uint32_t sha384_hmac
ODP_AUTH_ALG_SHA384_HMAC.
uint32_t sha256_hmac
ODP_AUTH_ALG_SHA256_HMAC.
uint32_t chacha20_poly1305
ODP_AUTH_ALG_CHACHA20_POLY1305.
uint32_t aes_ccm
ODP_AUTH_ALG_AES_CCM.
uint32_t aes_gcm
ODP_CIPHER_ALG_AES_GCM.
uint32_t trides_cbc
ODP_CIPHER_ALG_3DES_CBC.
uint32_t aes_ctr
ODP_CIPHER_ALG_AES_CTR.
struct odp_crypto_cipher_algos_t::@27 bit
Cipher algorithms.
uint32_t aes_cbc
ODP_CIPHER_ALG_AES_CBC.
uint32_t des
ODP_CIPHER_ALG_DES.
uint32_t zuc_eea3
ODP_CIPHER_ALG_ZUC_EEA3.
uint32_t null
ODP_CIPHER_ALG_NULL.
uint32_t chacha20_poly1305
ODP_CIPHER_ALG_CHACHA20_POLY1305.
uint32_t snow3g_uea2
ODP_CIPHER_ALG_SNOW3G_UEA2.
uint32_t aes_ccm
ODP_CIPHER_ALG_AES_CCM.