87cf4c6cca
The function rte_malloc_virt2phy() is renamed to rte_malloc_virt2iova(). The deprecated name is kept as an alias to avoid breaking the API. Signed-off-by: Thomas Monjalon <thomas@monjalon.net> Acked-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
621 lines
15 KiB
C
621 lines
15 KiB
C
/*-
|
|
* BSD LICENSE
|
|
*
|
|
* Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#ifdef RTE_EXEC_ENV_BSDAPP
|
|
#define _WITH_GETLINE
|
|
#endif
|
|
#include <stdio.h>
|
|
|
|
#include <rte_malloc.h>
|
|
|
|
#include "cperf_options.h"
|
|
#include "cperf_test_vectors.h"
|
|
#include "cperf_test_vector_parsing.h"
|
|
|
|
int
|
|
free_test_vector(struct cperf_test_vector *vector, struct cperf_options *opts)
|
|
{
|
|
if (vector == NULL || opts == NULL)
|
|
return -1;
|
|
|
|
rte_free(vector->cipher_iv.data);
|
|
rte_free(vector->auth_iv.data);
|
|
rte_free(vector->aad.data);
|
|
rte_free(vector->digest.data);
|
|
|
|
if (opts->test_file != NULL) {
|
|
rte_free(vector->plaintext.data);
|
|
rte_free(vector->cipher_key.data);
|
|
rte_free(vector->auth_key.data);
|
|
rte_free(vector->ciphertext.data);
|
|
}
|
|
|
|
rte_free(vector);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
show_test_vector(struct cperf_test_vector *test_vector)
|
|
{
|
|
const uint8_t wrap = 32;
|
|
uint32_t i;
|
|
|
|
if (test_vector == NULL)
|
|
return;
|
|
|
|
if (test_vector->plaintext.data) {
|
|
printf("\nplaintext =\n");
|
|
for (i = 0; i < test_vector->plaintext.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == test_vector->plaintext.length - 1)
|
|
printf("0x%02x",
|
|
test_vector->plaintext.data[i]);
|
|
else
|
|
printf("0x%02x, ",
|
|
test_vector->plaintext.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->cipher_key.data) {
|
|
printf("\ncipher_key =\n");
|
|
for (i = 0; i < test_vector->cipher_key.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->cipher_key.length - 1))
|
|
printf("0x%02x",
|
|
test_vector->cipher_key.data[i]);
|
|
else
|
|
printf("0x%02x, ",
|
|
test_vector->cipher_key.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->auth_key.data) {
|
|
printf("\nauth_key =\n");
|
|
for (i = 0; i < test_vector->auth_key.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->auth_key.length - 1))
|
|
printf("0x%02x", test_vector->auth_key.data[i]);
|
|
else
|
|
printf("0x%02x, ",
|
|
test_vector->auth_key.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->aead_key.data) {
|
|
printf("\naead_key =\n");
|
|
for (i = 0; i < test_vector->aead_key.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->aead_key.length - 1))
|
|
printf("0x%02x", test_vector->aead_key.data[i]);
|
|
else
|
|
printf("0x%02x, ",
|
|
test_vector->aead_key.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->cipher_iv.data) {
|
|
printf("\ncipher_iv =\n");
|
|
for (i = 0; i < test_vector->cipher_iv.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->cipher_iv.length - 1))
|
|
printf("0x%02x", test_vector->cipher_iv.data[i]);
|
|
else
|
|
printf("0x%02x, ", test_vector->cipher_iv.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->auth_iv.data) {
|
|
printf("\nauth_iv =\n");
|
|
for (i = 0; i < test_vector->auth_iv.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->auth_iv.length - 1))
|
|
printf("0x%02x", test_vector->auth_iv.data[i]);
|
|
else
|
|
printf("0x%02x, ", test_vector->auth_iv.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->aead_iv.data) {
|
|
printf("\naead_iv =\n");
|
|
for (i = 0; i < test_vector->aead_iv.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->aead_iv.length - 1))
|
|
printf("0x%02x", test_vector->aead_iv.data[i]);
|
|
else
|
|
printf("0x%02x, ", test_vector->aead_iv.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->ciphertext.data) {
|
|
printf("\nciphertext =\n");
|
|
for (i = 0; i < test_vector->ciphertext.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == test_vector->ciphertext.length - 1)
|
|
printf("0x%02x",
|
|
test_vector->ciphertext.data[i]);
|
|
else
|
|
printf("0x%02x, ",
|
|
test_vector->ciphertext.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->aad.data) {
|
|
printf("\naad =\n");
|
|
for (i = 0; i < test_vector->aad.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->aad.length - 1))
|
|
printf("0x%02x", test_vector->aad.data[i]);
|
|
else
|
|
printf("0x%02x, ", test_vector->aad.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
if (test_vector->digest.data) {
|
|
printf("\ndigest =\n");
|
|
for (i = 0; i < test_vector->digest.length; ++i) {
|
|
if ((i % wrap == 0) && (i != 0))
|
|
printf("\n");
|
|
if (i == (uint32_t)(test_vector->digest.length - 1))
|
|
printf("0x%02x", test_vector->digest.data[i]);
|
|
else
|
|
printf("0x%02x, ", test_vector->digest.data[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
/* trim leading and trailing spaces */
|
|
static char *
|
|
trim_space(char *str)
|
|
{
|
|
char *start, *end;
|
|
|
|
for (start = str; *start; start++) {
|
|
if (!isspace((unsigned char) start[0]))
|
|
break;
|
|
}
|
|
|
|
for (end = start + strlen(start); end > start + 1; end--) {
|
|
if (!isspace((unsigned char) end[-1]))
|
|
break;
|
|
}
|
|
|
|
*end = 0;
|
|
|
|
/* Shift from "start" to the beginning of the string */
|
|
if (start > str)
|
|
memmove(str, start, (end - start) + 1);
|
|
|
|
return str;
|
|
}
|
|
|
|
/* tokenization test values separated by a comma */
|
|
static int
|
|
parse_values(char *tokens, uint8_t **data, uint32_t *data_length)
|
|
{
|
|
uint32_t n_tokens;
|
|
uint32_t data_size = 32;
|
|
|
|
uint8_t *values, *values_resized;
|
|
char *tok, *error = NULL;
|
|
|
|
tok = strtok(tokens, CPERF_VALUE_DELIMITER);
|
|
if (tok == NULL)
|
|
return -1;
|
|
|
|
values = (uint8_t *) rte_zmalloc(NULL, sizeof(uint8_t) * data_size, 0);
|
|
if (values == NULL)
|
|
return -1;
|
|
|
|
n_tokens = 0;
|
|
while (tok != NULL) {
|
|
values_resized = NULL;
|
|
|
|
if (n_tokens >= data_size) {
|
|
data_size *= 2;
|
|
|
|
values_resized = (uint8_t *) rte_realloc(values,
|
|
sizeof(uint8_t) * data_size, 0);
|
|
if (values_resized == NULL) {
|
|
rte_free(values);
|
|
return -1;
|
|
}
|
|
values = values_resized;
|
|
}
|
|
|
|
values[n_tokens] = (uint8_t) strtoul(tok, &error, 0);
|
|
if ((error == NULL) || (*error != '\0')) {
|
|
printf("Failed with convert '%s'\n", tok);
|
|
rte_free(values);
|
|
return -1;
|
|
}
|
|
|
|
tok = strtok(NULL, CPERF_VALUE_DELIMITER);
|
|
if (tok == NULL)
|
|
break;
|
|
|
|
n_tokens++;
|
|
}
|
|
|
|
values_resized = (uint8_t *) rte_realloc(values,
|
|
sizeof(uint8_t) * (n_tokens + 1), 0);
|
|
|
|
if (values_resized == NULL) {
|
|
rte_free(values);
|
|
return -1;
|
|
}
|
|
|
|
*data = values_resized;
|
|
*data_length = n_tokens + 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* checks the type of key and assigns data */
|
|
static int
|
|
parse_entry(char *entry, struct cperf_test_vector *vector,
|
|
struct cperf_options *opts, uint8_t tc_found)
|
|
{
|
|
int status;
|
|
uint32_t data_length;
|
|
|
|
uint8_t *data = NULL;
|
|
char *token, *key_token;
|
|
|
|
if (entry == NULL) {
|
|
printf("Expected entry value\n");
|
|
return -1;
|
|
}
|
|
|
|
/* get key */
|
|
token = strtok(entry, CPERF_ENTRY_DELIMITER);
|
|
key_token = token;
|
|
/* get values for key */
|
|
token = strtok(NULL, CPERF_ENTRY_DELIMITER);
|
|
|
|
if (key_token == NULL || token == NULL) {
|
|
printf("Expected 'key = values' but was '%.40s'..\n", entry);
|
|
return -1;
|
|
}
|
|
|
|
status = parse_values(token, &data, &data_length);
|
|
if (status)
|
|
return -1;
|
|
|
|
/* compare keys */
|
|
if (strstr(key_token, "plaintext")) {
|
|
rte_free(vector->plaintext.data);
|
|
vector->plaintext.data = data;
|
|
if (tc_found)
|
|
vector->plaintext.length = data_length;
|
|
else {
|
|
if (opts->max_buffer_size > data_length) {
|
|
printf("Global plaintext shorter than "
|
|
"buffer_sz\n");
|
|
return -1;
|
|
}
|
|
vector->plaintext.length = opts->max_buffer_size;
|
|
}
|
|
|
|
} else if (strstr(key_token, "cipher_key")) {
|
|
rte_free(vector->cipher_key.data);
|
|
vector->cipher_key.data = data;
|
|
if (tc_found)
|
|
vector->cipher_key.length = data_length;
|
|
else {
|
|
if (opts->cipher_key_sz > data_length) {
|
|
printf("Global cipher_key shorter than "
|
|
"cipher_key_sz\n");
|
|
return -1;
|
|
}
|
|
vector->cipher_key.length = opts->cipher_key_sz;
|
|
}
|
|
|
|
} else if (strstr(key_token, "auth_key")) {
|
|
rte_free(vector->auth_key.data);
|
|
vector->auth_key.data = data;
|
|
if (tc_found)
|
|
vector->auth_key.length = data_length;
|
|
else {
|
|
if (opts->auth_key_sz > data_length) {
|
|
printf("Global auth_key shorter than "
|
|
"auth_key_sz\n");
|
|
return -1;
|
|
}
|
|
vector->auth_key.length = opts->auth_key_sz;
|
|
}
|
|
|
|
} else if (strstr(key_token, "aead_key")) {
|
|
rte_free(vector->aead_key.data);
|
|
vector->aead_key.data = data;
|
|
if (tc_found)
|
|
vector->aead_key.length = data_length;
|
|
else {
|
|
if (opts->aead_key_sz > data_length) {
|
|
printf("Global aead_key shorter than "
|
|
"aead_key_sz\n");
|
|
return -1;
|
|
}
|
|
vector->aead_key.length = opts->aead_key_sz;
|
|
}
|
|
|
|
} else if (strstr(key_token, "cipher_iv")) {
|
|
rte_free(vector->cipher_iv.data);
|
|
vector->cipher_iv.data = data;
|
|
if (tc_found)
|
|
vector->cipher_iv.length = data_length;
|
|
else {
|
|
if (opts->cipher_iv_sz > data_length) {
|
|
printf("Global cipher iv shorter than "
|
|
"cipher_iv_sz\n");
|
|
return -1;
|
|
}
|
|
vector->cipher_iv.length = opts->cipher_iv_sz;
|
|
}
|
|
|
|
} else if (strstr(key_token, "auth_iv")) {
|
|
rte_free(vector->auth_iv.data);
|
|
vector->auth_iv.data = data;
|
|
if (tc_found)
|
|
vector->auth_iv.length = data_length;
|
|
else {
|
|
if (opts->auth_iv_sz > data_length) {
|
|
printf("Global auth iv shorter than "
|
|
"auth_iv_sz\n");
|
|
return -1;
|
|
}
|
|
vector->auth_iv.length = opts->auth_iv_sz;
|
|
}
|
|
|
|
} else if (strstr(key_token, "aead_iv")) {
|
|
rte_free(vector->aead_iv.data);
|
|
vector->aead_iv.data = data;
|
|
if (tc_found)
|
|
vector->aead_iv.length = data_length;
|
|
else {
|
|
if (opts->aead_iv_sz > data_length) {
|
|
printf("Global aead iv shorter than "
|
|
"aead_iv_sz\n");
|
|
return -1;
|
|
}
|
|
vector->aead_iv.length = opts->aead_iv_sz;
|
|
}
|
|
|
|
} else if (strstr(key_token, "ciphertext")) {
|
|
rte_free(vector->ciphertext.data);
|
|
vector->ciphertext.data = data;
|
|
if (tc_found)
|
|
vector->ciphertext.length = data_length;
|
|
else {
|
|
if (opts->max_buffer_size > data_length) {
|
|
printf("Global ciphertext shorter than "
|
|
"buffer_sz\n");
|
|
return -1;
|
|
}
|
|
vector->ciphertext.length = opts->max_buffer_size;
|
|
}
|
|
|
|
} else if (strstr(key_token, "aad")) {
|
|
rte_free(vector->aad.data);
|
|
vector->aad.data = data;
|
|
vector->aad.phys_addr = rte_malloc_virt2iova(vector->aad.data);
|
|
if (tc_found)
|
|
vector->aad.length = data_length;
|
|
else {
|
|
if (opts->aead_aad_sz > data_length) {
|
|
printf("Global aad shorter than "
|
|
"aead_aad_sz\n");
|
|
return -1;
|
|
}
|
|
vector->aad.length = opts->aead_aad_sz;
|
|
}
|
|
|
|
} else if (strstr(key_token, "digest")) {
|
|
rte_free(vector->digest.data);
|
|
vector->digest.data = data;
|
|
vector->digest.phys_addr = rte_malloc_virt2iova(
|
|
vector->digest.data);
|
|
if (tc_found)
|
|
vector->digest.length = data_length;
|
|
else {
|
|
if (opts->digest_sz > data_length) {
|
|
printf("Global digest shorter than "
|
|
"digest_sz\n");
|
|
return -1;
|
|
}
|
|
vector->digest.length = opts->digest_sz;
|
|
}
|
|
} else {
|
|
printf("Not valid key: '%s'\n", trim_space(key_token));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* searches in the file for test keys and values */
|
|
static int
|
|
parse_file(struct cperf_test_vector *vector, struct cperf_options *opts)
|
|
{
|
|
uint8_t tc_found = 0;
|
|
uint8_t tc_data_start = 0;
|
|
ssize_t read;
|
|
size_t len = 0;
|
|
int status = 0;
|
|
|
|
FILE *fp;
|
|
char *line = NULL;
|
|
char *entry = NULL;
|
|
|
|
fp = fopen(opts->test_file, "r");
|
|
if (fp == NULL) {
|
|
printf("File %s does not exists\n", opts->test_file);
|
|
return -1;
|
|
}
|
|
|
|
while ((read = getline(&line, &len, fp)) != -1) {
|
|
|
|
/* ignore comments and new lines */
|
|
if (line[0] == '#' || line[0] == '/' || line[0] == '\n'
|
|
|| line[0] == '\r' || line[0] == ' ')
|
|
continue;
|
|
|
|
trim_space(line);
|
|
|
|
/* next test case is started */
|
|
if (line[0] == '[' && line[strlen(line) - 1] == ']' && tc_found)
|
|
break;
|
|
/* test case section started, end of global data */
|
|
else if (line[0] == '[' && line[strlen(line) - 1] == ']')
|
|
tc_data_start = 1;
|
|
|
|
/* test name unspecified, end after global data */
|
|
if (tc_data_start && opts->test_name == NULL)
|
|
break;
|
|
/* searching for a suitable test */
|
|
else if (tc_data_start && tc_found == 0) {
|
|
if (!strcmp(line, opts->test_name)) {
|
|
tc_found = 1;
|
|
continue;
|
|
} else
|
|
continue;
|
|
}
|
|
|
|
/* buffer for multiline */
|
|
entry = (char *) rte_realloc(entry,
|
|
sizeof(char) * strlen(line) + 1, 0);
|
|
if (entry == NULL)
|
|
return -1;
|
|
|
|
memset(entry, 0, strlen(line) + 1);
|
|
strncpy(entry, line, strlen(line));
|
|
|
|
/* check if entry ends with , or = */
|
|
if (entry[strlen(entry) - 1] == ','
|
|
|| entry[strlen(entry) - 1] == '=') {
|
|
while ((read = getline(&line, &len, fp)) != -1) {
|
|
trim_space(line);
|
|
|
|
/* extend entry about length of new line */
|
|
char *entry_extended = (char *) rte_realloc(
|
|
entry, sizeof(char)
|
|
* (strlen(line) + strlen(entry))
|
|
+ 1, 0);
|
|
|
|
if (entry_extended == NULL)
|
|
goto err;
|
|
entry = entry_extended;
|
|
|
|
strncat(entry, line, strlen(line));
|
|
|
|
if (entry[strlen(entry) - 1] != ',')
|
|
break;
|
|
}
|
|
}
|
|
status = parse_entry(entry, vector, opts, tc_found);
|
|
if (status) {
|
|
printf("An error occurred while parsing!\n");
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
if (tc_found == 0 && opts->test_name != NULL) {
|
|
printf("Not found '%s' case in test file\n", opts->test_name);
|
|
goto err;
|
|
}
|
|
|
|
fclose(fp);
|
|
free(line);
|
|
rte_free(entry);
|
|
|
|
return 0;
|
|
|
|
err:
|
|
if (fp)
|
|
fclose(fp);
|
|
if (line)
|
|
free(line);
|
|
if (entry)
|
|
rte_free(entry);
|
|
|
|
return -1;
|
|
}
|
|
|
|
struct cperf_test_vector*
|
|
cperf_test_vector_get_from_file(struct cperf_options *opts)
|
|
{
|
|
int status;
|
|
struct cperf_test_vector *test_vector = NULL;
|
|
|
|
if (opts == NULL || opts->test_file == NULL)
|
|
return test_vector;
|
|
|
|
test_vector = (struct cperf_test_vector *) rte_zmalloc(NULL,
|
|
sizeof(struct cperf_test_vector), 0);
|
|
if (test_vector == NULL)
|
|
return test_vector;
|
|
|
|
/* filling the vector with data from a file */
|
|
status = parse_file(test_vector, opts);
|
|
if (status) {
|
|
free_test_vector(test_vector, opts);
|
|
return NULL;
|
|
}
|
|
|
|
/* other values not included in the file */
|
|
test_vector->data.cipher_offset = 0;
|
|
test_vector->data.cipher_length = opts->max_buffer_size;
|
|
|
|
test_vector->data.auth_offset = 0;
|
|
test_vector->data.auth_length = opts->max_buffer_size;
|
|
|
|
return test_vector;
|
|
}
|