cfe3aeb170
We had some inconsistencies between functions prototypes and actual definitions. Let's avoid this by only adding the experimental tag to the prototypes. Tests with gcc and clang show it is enough. git grep -l __rte_experimental |grep \.c$ |while read file; do sed -i -e '/^__rte_experimental$/d' $file; sed -i -e 's/ *__rte_experimental//' $file; sed -i -e 's/__rte_experimental *//' $file; done Signed-off-by: David Marchand <david.marchand@redhat.com> Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> Acked-by: Neil Horman <nhorman@tuxdriver.com>
1739 lines
40 KiB
C
1739 lines
40 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2015-2017 Intel Corporation
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/queue.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
#include <stdint.h>
|
|
#include <inttypes.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include <rte_byteorder.h>
|
|
#include <rte_log.h>
|
|
#include <rte_debug.h>
|
|
#include <rte_dev.h>
|
|
#include <rte_interrupts.h>
|
|
#include <rte_memory.h>
|
|
#include <rte_memcpy.h>
|
|
#include <rte_memzone.h>
|
|
#include <rte_launch.h>
|
|
#include <rte_tailq.h>
|
|
#include <rte_eal.h>
|
|
#include <rte_per_lcore.h>
|
|
#include <rte_lcore.h>
|
|
#include <rte_atomic.h>
|
|
#include <rte_branch_prediction.h>
|
|
#include <rte_common.h>
|
|
#include <rte_mempool.h>
|
|
#include <rte_malloc.h>
|
|
#include <rte_mbuf.h>
|
|
#include <rte_errno.h>
|
|
#include <rte_spinlock.h>
|
|
#include <rte_string_fns.h>
|
|
|
|
#include "rte_crypto.h"
|
|
#include "rte_cryptodev.h"
|
|
#include "rte_cryptodev_pmd.h"
|
|
|
|
static uint8_t nb_drivers;
|
|
|
|
static struct rte_cryptodev rte_crypto_devices[RTE_CRYPTO_MAX_DEVS];
|
|
|
|
struct rte_cryptodev *rte_cryptodevs = rte_crypto_devices;
|
|
|
|
static struct rte_cryptodev_global cryptodev_globals = {
|
|
.devs = rte_crypto_devices,
|
|
.data = { NULL },
|
|
.nb_devs = 0,
|
|
.max_devs = RTE_CRYPTO_MAX_DEVS
|
|
};
|
|
|
|
/* spinlock for crypto device callbacks */
|
|
static rte_spinlock_t rte_cryptodev_cb_lock = RTE_SPINLOCK_INITIALIZER;
|
|
|
|
|
|
/**
|
|
* The user application callback description.
|
|
*
|
|
* It contains callback address to be registered by user application,
|
|
* the pointer to the parameters for callback, and the event type.
|
|
*/
|
|
struct rte_cryptodev_callback {
|
|
TAILQ_ENTRY(rte_cryptodev_callback) next; /**< Callbacks list */
|
|
rte_cryptodev_cb_fn cb_fn; /**< Callback address */
|
|
void *cb_arg; /**< Parameter for callback */
|
|
enum rte_cryptodev_event_type event; /**< Interrupt event type */
|
|
uint32_t active; /**< Callback is executing */
|
|
};
|
|
|
|
/**
|
|
* The crypto cipher algorithm strings identifiers.
|
|
* It could be used in application command line.
|
|
*/
|
|
const char *
|
|
rte_crypto_cipher_algorithm_strings[] = {
|
|
[RTE_CRYPTO_CIPHER_3DES_CBC] = "3des-cbc",
|
|
[RTE_CRYPTO_CIPHER_3DES_ECB] = "3des-ecb",
|
|
[RTE_CRYPTO_CIPHER_3DES_CTR] = "3des-ctr",
|
|
|
|
[RTE_CRYPTO_CIPHER_AES_CBC] = "aes-cbc",
|
|
[RTE_CRYPTO_CIPHER_AES_CTR] = "aes-ctr",
|
|
[RTE_CRYPTO_CIPHER_AES_DOCSISBPI] = "aes-docsisbpi",
|
|
[RTE_CRYPTO_CIPHER_AES_ECB] = "aes-ecb",
|
|
[RTE_CRYPTO_CIPHER_AES_F8] = "aes-f8",
|
|
[RTE_CRYPTO_CIPHER_AES_XTS] = "aes-xts",
|
|
|
|
[RTE_CRYPTO_CIPHER_ARC4] = "arc4",
|
|
|
|
[RTE_CRYPTO_CIPHER_DES_CBC] = "des-cbc",
|
|
[RTE_CRYPTO_CIPHER_DES_DOCSISBPI] = "des-docsisbpi",
|
|
|
|
[RTE_CRYPTO_CIPHER_NULL] = "null",
|
|
|
|
[RTE_CRYPTO_CIPHER_KASUMI_F8] = "kasumi-f8",
|
|
[RTE_CRYPTO_CIPHER_SNOW3G_UEA2] = "snow3g-uea2",
|
|
[RTE_CRYPTO_CIPHER_ZUC_EEA3] = "zuc-eea3"
|
|
};
|
|
|
|
/**
|
|
* The crypto cipher operation strings identifiers.
|
|
* It could be used in application command line.
|
|
*/
|
|
const char *
|
|
rte_crypto_cipher_operation_strings[] = {
|
|
[RTE_CRYPTO_CIPHER_OP_ENCRYPT] = "encrypt",
|
|
[RTE_CRYPTO_CIPHER_OP_DECRYPT] = "decrypt"
|
|
};
|
|
|
|
/**
|
|
* The crypto auth algorithm strings identifiers.
|
|
* It could be used in application command line.
|
|
*/
|
|
const char *
|
|
rte_crypto_auth_algorithm_strings[] = {
|
|
[RTE_CRYPTO_AUTH_AES_CBC_MAC] = "aes-cbc-mac",
|
|
[RTE_CRYPTO_AUTH_AES_CMAC] = "aes-cmac",
|
|
[RTE_CRYPTO_AUTH_AES_GMAC] = "aes-gmac",
|
|
[RTE_CRYPTO_AUTH_AES_XCBC_MAC] = "aes-xcbc-mac",
|
|
|
|
[RTE_CRYPTO_AUTH_MD5] = "md5",
|
|
[RTE_CRYPTO_AUTH_MD5_HMAC] = "md5-hmac",
|
|
|
|
[RTE_CRYPTO_AUTH_NULL] = "null",
|
|
|
|
[RTE_CRYPTO_AUTH_SHA1] = "sha1",
|
|
[RTE_CRYPTO_AUTH_SHA1_HMAC] = "sha1-hmac",
|
|
|
|
[RTE_CRYPTO_AUTH_SHA224] = "sha2-224",
|
|
[RTE_CRYPTO_AUTH_SHA224_HMAC] = "sha2-224-hmac",
|
|
[RTE_CRYPTO_AUTH_SHA256] = "sha2-256",
|
|
[RTE_CRYPTO_AUTH_SHA256_HMAC] = "sha2-256-hmac",
|
|
[RTE_CRYPTO_AUTH_SHA384] = "sha2-384",
|
|
[RTE_CRYPTO_AUTH_SHA384_HMAC] = "sha2-384-hmac",
|
|
[RTE_CRYPTO_AUTH_SHA512] = "sha2-512",
|
|
[RTE_CRYPTO_AUTH_SHA512_HMAC] = "sha2-512-hmac",
|
|
|
|
[RTE_CRYPTO_AUTH_KASUMI_F9] = "kasumi-f9",
|
|
[RTE_CRYPTO_AUTH_SNOW3G_UIA2] = "snow3g-uia2",
|
|
[RTE_CRYPTO_AUTH_ZUC_EIA3] = "zuc-eia3"
|
|
};
|
|
|
|
/**
|
|
* The crypto AEAD algorithm strings identifiers.
|
|
* It could be used in application command line.
|
|
*/
|
|
const char *
|
|
rte_crypto_aead_algorithm_strings[] = {
|
|
[RTE_CRYPTO_AEAD_AES_CCM] = "aes-ccm",
|
|
[RTE_CRYPTO_AEAD_AES_GCM] = "aes-gcm",
|
|
};
|
|
|
|
/**
|
|
* The crypto AEAD operation strings identifiers.
|
|
* It could be used in application command line.
|
|
*/
|
|
const char *
|
|
rte_crypto_aead_operation_strings[] = {
|
|
[RTE_CRYPTO_AEAD_OP_ENCRYPT] = "encrypt",
|
|
[RTE_CRYPTO_AEAD_OP_DECRYPT] = "decrypt"
|
|
};
|
|
|
|
/**
|
|
* Asymmetric crypto transform operation strings identifiers.
|
|
*/
|
|
const char *rte_crypto_asym_xform_strings[] = {
|
|
[RTE_CRYPTO_ASYM_XFORM_NONE] = "none",
|
|
[RTE_CRYPTO_ASYM_XFORM_RSA] = "rsa",
|
|
[RTE_CRYPTO_ASYM_XFORM_MODEX] = "modexp",
|
|
[RTE_CRYPTO_ASYM_XFORM_MODINV] = "modinv",
|
|
[RTE_CRYPTO_ASYM_XFORM_DH] = "dh",
|
|
[RTE_CRYPTO_ASYM_XFORM_DSA] = "dsa",
|
|
};
|
|
|
|
/**
|
|
* Asymmetric crypto operation strings identifiers.
|
|
*/
|
|
const char *rte_crypto_asym_op_strings[] = {
|
|
[RTE_CRYPTO_ASYM_OP_ENCRYPT] = "encrypt",
|
|
[RTE_CRYPTO_ASYM_OP_DECRYPT] = "decrypt",
|
|
[RTE_CRYPTO_ASYM_OP_SIGN] = "sign",
|
|
[RTE_CRYPTO_ASYM_OP_VERIFY] = "verify",
|
|
[RTE_CRYPTO_ASYM_OP_PRIVATE_KEY_GENERATE] = "priv_key_generate",
|
|
[RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE] = "pub_key_generate",
|
|
[RTE_CRYPTO_ASYM_OP_SHARED_SECRET_COMPUTE] = "sharedsecret_compute",
|
|
};
|
|
|
|
/**
|
|
* The private data structure stored in the session mempool private data.
|
|
*/
|
|
struct rte_cryptodev_sym_session_pool_private_data {
|
|
uint16_t nb_drivers;
|
|
/**< number of elements in sess_data array */
|
|
uint16_t user_data_sz;
|
|
/**< session user data will be placed after sess_data */
|
|
};
|
|
|
|
int
|
|
rte_cryptodev_get_cipher_algo_enum(enum rte_crypto_cipher_algorithm *algo_enum,
|
|
const char *algo_string)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 1; i < RTE_DIM(rte_crypto_cipher_algorithm_strings); i++) {
|
|
if (strcmp(algo_string, rte_crypto_cipher_algorithm_strings[i]) == 0) {
|
|
*algo_enum = (enum rte_crypto_cipher_algorithm) i;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* Invalid string */
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_get_auth_algo_enum(enum rte_crypto_auth_algorithm *algo_enum,
|
|
const char *algo_string)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 1; i < RTE_DIM(rte_crypto_auth_algorithm_strings); i++) {
|
|
if (strcmp(algo_string, rte_crypto_auth_algorithm_strings[i]) == 0) {
|
|
*algo_enum = (enum rte_crypto_auth_algorithm) i;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* Invalid string */
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_get_aead_algo_enum(enum rte_crypto_aead_algorithm *algo_enum,
|
|
const char *algo_string)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 1; i < RTE_DIM(rte_crypto_aead_algorithm_strings); i++) {
|
|
if (strcmp(algo_string, rte_crypto_aead_algorithm_strings[i]) == 0) {
|
|
*algo_enum = (enum rte_crypto_aead_algorithm) i;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* Invalid string */
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_asym_get_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,
|
|
const char *xform_string)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 1; i < RTE_DIM(rte_crypto_asym_xform_strings); i++) {
|
|
if (strcmp(xform_string,
|
|
rte_crypto_asym_xform_strings[i]) == 0) {
|
|
*xform_enum = (enum rte_crypto_asym_xform_type) i;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* Invalid string */
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* The crypto auth operation strings identifiers.
|
|
* It could be used in application command line.
|
|
*/
|
|
const char *
|
|
rte_crypto_auth_operation_strings[] = {
|
|
[RTE_CRYPTO_AUTH_OP_VERIFY] = "verify",
|
|
[RTE_CRYPTO_AUTH_OP_GENERATE] = "generate"
|
|
};
|
|
|
|
const struct rte_cryptodev_symmetric_capability *
|
|
rte_cryptodev_sym_capability_get(uint8_t dev_id,
|
|
const struct rte_cryptodev_sym_capability_idx *idx)
|
|
{
|
|
const struct rte_cryptodev_capabilities *capability;
|
|
struct rte_cryptodev_info dev_info;
|
|
int i = 0;
|
|
|
|
rte_cryptodev_info_get(dev_id, &dev_info);
|
|
|
|
while ((capability = &dev_info.capabilities[i++])->op !=
|
|
RTE_CRYPTO_OP_TYPE_UNDEFINED) {
|
|
if (capability->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC)
|
|
continue;
|
|
|
|
if (capability->sym.xform_type != idx->type)
|
|
continue;
|
|
|
|
if (idx->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
|
|
capability->sym.auth.algo == idx->algo.auth)
|
|
return &capability->sym;
|
|
|
|
if (idx->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
|
|
capability->sym.cipher.algo == idx->algo.cipher)
|
|
return &capability->sym;
|
|
|
|
if (idx->type == RTE_CRYPTO_SYM_XFORM_AEAD &&
|
|
capability->sym.aead.algo == idx->algo.aead)
|
|
return &capability->sym;
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
static int
|
|
param_range_check(uint16_t size, const struct rte_crypto_param_range *range)
|
|
{
|
|
unsigned int next_size;
|
|
|
|
/* Check lower/upper bounds */
|
|
if (size < range->min)
|
|
return -1;
|
|
|
|
if (size > range->max)
|
|
return -1;
|
|
|
|
/* If range is actually only one value, size is correct */
|
|
if (range->increment == 0)
|
|
return 0;
|
|
|
|
/* Check if value is one of the supported sizes */
|
|
for (next_size = range->min; next_size <= range->max;
|
|
next_size += range->increment)
|
|
if (size == next_size)
|
|
return 0;
|
|
|
|
return -1;
|
|
}
|
|
|
|
const struct rte_cryptodev_asymmetric_xform_capability *
|
|
rte_cryptodev_asym_capability_get(uint8_t dev_id,
|
|
const struct rte_cryptodev_asym_capability_idx *idx)
|
|
{
|
|
const struct rte_cryptodev_capabilities *capability;
|
|
struct rte_cryptodev_info dev_info;
|
|
unsigned int i = 0;
|
|
|
|
memset(&dev_info, 0, sizeof(struct rte_cryptodev_info));
|
|
rte_cryptodev_info_get(dev_id, &dev_info);
|
|
|
|
while ((capability = &dev_info.capabilities[i++])->op !=
|
|
RTE_CRYPTO_OP_TYPE_UNDEFINED) {
|
|
if (capability->op != RTE_CRYPTO_OP_TYPE_ASYMMETRIC)
|
|
continue;
|
|
|
|
if (capability->asym.xform_capa.xform_type == idx->type)
|
|
return &capability->asym.xform_capa;
|
|
}
|
|
return NULL;
|
|
};
|
|
|
|
int
|
|
rte_cryptodev_sym_capability_check_cipher(
|
|
const struct rte_cryptodev_symmetric_capability *capability,
|
|
uint16_t key_size, uint16_t iv_size)
|
|
{
|
|
if (param_range_check(key_size, &capability->cipher.key_size) != 0)
|
|
return -1;
|
|
|
|
if (param_range_check(iv_size, &capability->cipher.iv_size) != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_sym_capability_check_auth(
|
|
const struct rte_cryptodev_symmetric_capability *capability,
|
|
uint16_t key_size, uint16_t digest_size, uint16_t iv_size)
|
|
{
|
|
if (param_range_check(key_size, &capability->auth.key_size) != 0)
|
|
return -1;
|
|
|
|
if (param_range_check(digest_size, &capability->auth.digest_size) != 0)
|
|
return -1;
|
|
|
|
if (param_range_check(iv_size, &capability->auth.iv_size) != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_sym_capability_check_aead(
|
|
const struct rte_cryptodev_symmetric_capability *capability,
|
|
uint16_t key_size, uint16_t digest_size, uint16_t aad_size,
|
|
uint16_t iv_size)
|
|
{
|
|
if (param_range_check(key_size, &capability->aead.key_size) != 0)
|
|
return -1;
|
|
|
|
if (param_range_check(digest_size, &capability->aead.digest_size) != 0)
|
|
return -1;
|
|
|
|
if (param_range_check(aad_size, &capability->aead.aad_size) != 0)
|
|
return -1;
|
|
|
|
if (param_range_check(iv_size, &capability->aead.iv_size) != 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
int
|
|
rte_cryptodev_asym_xform_capability_check_optype(
|
|
const struct rte_cryptodev_asymmetric_xform_capability *capability,
|
|
enum rte_crypto_asym_op_type op_type)
|
|
{
|
|
if (capability->op_types & (1 << op_type))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_asym_xform_capability_check_modlen(
|
|
const struct rte_cryptodev_asymmetric_xform_capability *capability,
|
|
uint16_t modlen)
|
|
{
|
|
/* no need to check for limits, if min or max = 0 */
|
|
if (capability->modlen.min != 0) {
|
|
if (modlen < capability->modlen.min)
|
|
return -1;
|
|
}
|
|
|
|
if (capability->modlen.max != 0) {
|
|
if (modlen > capability->modlen.max)
|
|
return -1;
|
|
}
|
|
|
|
/* in any case, check if given modlen is module increment */
|
|
if (capability->modlen.increment != 0) {
|
|
if (modlen % (capability->modlen.increment))
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
const char *
|
|
rte_cryptodev_get_feature_name(uint64_t flag)
|
|
{
|
|
switch (flag) {
|
|
case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
|
|
return "SYMMETRIC_CRYPTO";
|
|
case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
|
|
return "ASYMMETRIC_CRYPTO";
|
|
case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
|
|
return "SYM_OPERATION_CHAINING";
|
|
case RTE_CRYPTODEV_FF_CPU_SSE:
|
|
return "CPU_SSE";
|
|
case RTE_CRYPTODEV_FF_CPU_AVX:
|
|
return "CPU_AVX";
|
|
case RTE_CRYPTODEV_FF_CPU_AVX2:
|
|
return "CPU_AVX2";
|
|
case RTE_CRYPTODEV_FF_CPU_AVX512:
|
|
return "CPU_AVX512";
|
|
case RTE_CRYPTODEV_FF_CPU_AESNI:
|
|
return "CPU_AESNI";
|
|
case RTE_CRYPTODEV_FF_HW_ACCELERATED:
|
|
return "HW_ACCELERATED";
|
|
case RTE_CRYPTODEV_FF_IN_PLACE_SGL:
|
|
return "IN_PLACE_SGL";
|
|
case RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT:
|
|
return "OOP_SGL_IN_SGL_OUT";
|
|
case RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT:
|
|
return "OOP_SGL_IN_LB_OUT";
|
|
case RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT:
|
|
return "OOP_LB_IN_SGL_OUT";
|
|
case RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT:
|
|
return "OOP_LB_IN_LB_OUT";
|
|
case RTE_CRYPTODEV_FF_CPU_NEON:
|
|
return "CPU_NEON";
|
|
case RTE_CRYPTODEV_FF_CPU_ARM_CE:
|
|
return "CPU_ARM_CE";
|
|
case RTE_CRYPTODEV_FF_SECURITY:
|
|
return "SECURITY_PROTOCOL";
|
|
case RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP:
|
|
return "RSA_PRIV_OP_KEY_EXP";
|
|
case RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT:
|
|
return "RSA_PRIV_OP_KEY_QT";
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
struct rte_cryptodev *
|
|
rte_cryptodev_pmd_get_dev(uint8_t dev_id)
|
|
{
|
|
return &cryptodev_globals.devs[dev_id];
|
|
}
|
|
|
|
struct rte_cryptodev *
|
|
rte_cryptodev_pmd_get_named_dev(const char *name)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
unsigned int i;
|
|
|
|
if (name == NULL)
|
|
return NULL;
|
|
|
|
for (i = 0; i < cryptodev_globals.max_devs; i++) {
|
|
dev = &cryptodev_globals.devs[i];
|
|
|
|
if ((dev->attached == RTE_CRYPTODEV_ATTACHED) &&
|
|
(strcmp(dev->data->name, name) == 0))
|
|
return dev;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
unsigned int
|
|
rte_cryptodev_pmd_is_valid_dev(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev = NULL;
|
|
|
|
if (dev_id >= cryptodev_globals.nb_devs)
|
|
return 0;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
if (dev->attached != RTE_CRYPTODEV_ATTACHED)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
int
|
|
rte_cryptodev_get_dev_id(const char *name)
|
|
{
|
|
unsigned i;
|
|
|
|
if (name == NULL)
|
|
return -1;
|
|
|
|
for (i = 0; i < cryptodev_globals.nb_devs; i++)
|
|
if ((strcmp(cryptodev_globals.devs[i].data->name, name)
|
|
== 0) &&
|
|
(cryptodev_globals.devs[i].attached ==
|
|
RTE_CRYPTODEV_ATTACHED))
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
uint8_t
|
|
rte_cryptodev_count(void)
|
|
{
|
|
return cryptodev_globals.nb_devs;
|
|
}
|
|
|
|
uint8_t
|
|
rte_cryptodev_device_count_by_driver(uint8_t driver_id)
|
|
{
|
|
uint8_t i, dev_count = 0;
|
|
|
|
for (i = 0; i < cryptodev_globals.max_devs; i++)
|
|
if (cryptodev_globals.devs[i].driver_id == driver_id &&
|
|
cryptodev_globals.devs[i].attached ==
|
|
RTE_CRYPTODEV_ATTACHED)
|
|
dev_count++;
|
|
|
|
return dev_count;
|
|
}
|
|
|
|
uint8_t
|
|
rte_cryptodev_devices_get(const char *driver_name, uint8_t *devices,
|
|
uint8_t nb_devices)
|
|
{
|
|
uint8_t i, count = 0;
|
|
struct rte_cryptodev *devs = cryptodev_globals.devs;
|
|
uint8_t max_devs = cryptodev_globals.max_devs;
|
|
|
|
for (i = 0; i < max_devs && count < nb_devices; i++) {
|
|
|
|
if (devs[i].attached == RTE_CRYPTODEV_ATTACHED) {
|
|
int cmp;
|
|
|
|
cmp = strncmp(devs[i].device->driver->name,
|
|
driver_name,
|
|
strlen(driver_name) + 1);
|
|
|
|
if (cmp == 0)
|
|
devices[count++] = devs[i].data->dev_id;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
void *
|
|
rte_cryptodev_get_sec_ctx(uint8_t dev_id)
|
|
{
|
|
if (rte_crypto_devices[dev_id].feature_flags &
|
|
RTE_CRYPTODEV_FF_SECURITY)
|
|
return rte_crypto_devices[dev_id].security_ctx;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_socket_id(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
|
|
return -1;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
return dev->data->socket_id;
|
|
}
|
|
|
|
static inline int
|
|
rte_cryptodev_data_alloc(uint8_t dev_id, struct rte_cryptodev_data **data,
|
|
int socket_id)
|
|
{
|
|
char mz_name[RTE_CRYPTODEV_NAME_MAX_LEN];
|
|
const struct rte_memzone *mz;
|
|
int n;
|
|
|
|
/* generate memzone name */
|
|
n = snprintf(mz_name, sizeof(mz_name), "rte_cryptodev_data_%u", dev_id);
|
|
if (n >= (int)sizeof(mz_name))
|
|
return -EINVAL;
|
|
|
|
if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
|
|
mz = rte_memzone_reserve(mz_name,
|
|
sizeof(struct rte_cryptodev_data),
|
|
socket_id, 0);
|
|
} else
|
|
mz = rte_memzone_lookup(mz_name);
|
|
|
|
if (mz == NULL)
|
|
return -ENOMEM;
|
|
|
|
*data = mz->addr;
|
|
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
|
|
memset(*data, 0, sizeof(struct rte_cryptodev_data));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint8_t
|
|
rte_cryptodev_find_free_device_index(void)
|
|
{
|
|
uint8_t dev_id;
|
|
|
|
for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
|
|
if (rte_crypto_devices[dev_id].attached ==
|
|
RTE_CRYPTODEV_DETACHED)
|
|
return dev_id;
|
|
}
|
|
return RTE_CRYPTO_MAX_DEVS;
|
|
}
|
|
|
|
struct rte_cryptodev *
|
|
rte_cryptodev_pmd_allocate(const char *name, int socket_id)
|
|
{
|
|
struct rte_cryptodev *cryptodev;
|
|
uint8_t dev_id;
|
|
|
|
if (rte_cryptodev_pmd_get_named_dev(name) != NULL) {
|
|
CDEV_LOG_ERR("Crypto device with name %s already "
|
|
"allocated!", name);
|
|
return NULL;
|
|
}
|
|
|
|
dev_id = rte_cryptodev_find_free_device_index();
|
|
if (dev_id == RTE_CRYPTO_MAX_DEVS) {
|
|
CDEV_LOG_ERR("Reached maximum number of crypto devices");
|
|
return NULL;
|
|
}
|
|
|
|
cryptodev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (cryptodev->data == NULL) {
|
|
struct rte_cryptodev_data *cryptodev_data =
|
|
cryptodev_globals.data[dev_id];
|
|
|
|
int retval = rte_cryptodev_data_alloc(dev_id, &cryptodev_data,
|
|
socket_id);
|
|
|
|
if (retval < 0 || cryptodev_data == NULL)
|
|
return NULL;
|
|
|
|
cryptodev->data = cryptodev_data;
|
|
|
|
strlcpy(cryptodev->data->name, name,
|
|
RTE_CRYPTODEV_NAME_MAX_LEN);
|
|
|
|
cryptodev->data->dev_id = dev_id;
|
|
cryptodev->data->socket_id = socket_id;
|
|
cryptodev->data->dev_started = 0;
|
|
|
|
/* init user callbacks */
|
|
TAILQ_INIT(&(cryptodev->link_intr_cbs));
|
|
|
|
cryptodev->attached = RTE_CRYPTODEV_ATTACHED;
|
|
|
|
cryptodev_globals.nb_devs++;
|
|
}
|
|
|
|
return cryptodev;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_pmd_release_device(struct rte_cryptodev *cryptodev)
|
|
{
|
|
int ret;
|
|
|
|
if (cryptodev == NULL)
|
|
return -EINVAL;
|
|
|
|
/* Close device only if device operations have been set */
|
|
if (cryptodev->dev_ops) {
|
|
ret = rte_cryptodev_close(cryptodev->data->dev_id);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
cryptodev->attached = RTE_CRYPTODEV_DETACHED;
|
|
cryptodev_globals.nb_devs--;
|
|
return 0;
|
|
}
|
|
|
|
uint16_t
|
|
rte_cryptodev_queue_pair_count(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
return dev->data->nb_queue_pairs;
|
|
}
|
|
|
|
static int
|
|
rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,
|
|
int socket_id)
|
|
{
|
|
struct rte_cryptodev_info dev_info;
|
|
void **qp;
|
|
unsigned i;
|
|
|
|
if ((dev == NULL) || (nb_qpairs < 1)) {
|
|
CDEV_LOG_ERR("invalid param: dev %p, nb_queues %u",
|
|
dev, nb_qpairs);
|
|
return -EINVAL;
|
|
}
|
|
|
|
CDEV_LOG_DEBUG("Setup %d queues pairs on device %u",
|
|
nb_qpairs, dev->data->dev_id);
|
|
|
|
memset(&dev_info, 0, sizeof(struct rte_cryptodev_info));
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
|
|
(*dev->dev_ops->dev_infos_get)(dev, &dev_info);
|
|
|
|
if (nb_qpairs > (dev_info.max_nb_queue_pairs)) {
|
|
CDEV_LOG_ERR("Invalid num queue_pairs (%u) for dev %u",
|
|
nb_qpairs, dev->data->dev_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (dev->data->queue_pairs == NULL) { /* first time configuration */
|
|
dev->data->queue_pairs = rte_zmalloc_socket(
|
|
"cryptodev->queue_pairs",
|
|
sizeof(dev->data->queue_pairs[0]) * nb_qpairs,
|
|
RTE_CACHE_LINE_SIZE, socket_id);
|
|
|
|
if (dev->data->queue_pairs == NULL) {
|
|
dev->data->nb_queue_pairs = 0;
|
|
CDEV_LOG_ERR("failed to get memory for qp meta data, "
|
|
"nb_queues %u",
|
|
nb_qpairs);
|
|
return -(ENOMEM);
|
|
}
|
|
} else { /* re-configure */
|
|
int ret;
|
|
uint16_t old_nb_queues = dev->data->nb_queue_pairs;
|
|
|
|
qp = dev->data->queue_pairs;
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release,
|
|
-ENOTSUP);
|
|
|
|
for (i = nb_qpairs; i < old_nb_queues; i++) {
|
|
ret = (*dev->dev_ops->queue_pair_release)(dev, i);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
qp = rte_realloc(qp, sizeof(qp[0]) * nb_qpairs,
|
|
RTE_CACHE_LINE_SIZE);
|
|
if (qp == NULL) {
|
|
CDEV_LOG_ERR("failed to realloc qp meta data,"
|
|
" nb_queues %u", nb_qpairs);
|
|
return -(ENOMEM);
|
|
}
|
|
|
|
if (nb_qpairs > old_nb_queues) {
|
|
uint16_t new_qs = nb_qpairs - old_nb_queues;
|
|
|
|
memset(qp + old_nb_queues, 0,
|
|
sizeof(qp[0]) * new_qs);
|
|
}
|
|
|
|
dev->data->queue_pairs = qp;
|
|
|
|
}
|
|
dev->data->nb_queue_pairs = nb_qpairs;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_configure(uint8_t dev_id, struct rte_cryptodev_config *config)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
int diag;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
|
|
if (dev->data->dev_started) {
|
|
CDEV_LOG_ERR(
|
|
"device %d must be stopped to allow configuration", dev_id);
|
|
return -EBUSY;
|
|
}
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
|
|
|
|
/* Setup new number of queue pairs and reconfigure device. */
|
|
diag = rte_cryptodev_queue_pairs_config(dev, config->nb_queue_pairs,
|
|
config->socket_id);
|
|
if (diag != 0) {
|
|
CDEV_LOG_ERR("dev%d rte_crypto_dev_queue_pairs_config = %d",
|
|
dev_id, diag);
|
|
return diag;
|
|
}
|
|
|
|
return (*dev->dev_ops->dev_configure)(dev, config);
|
|
}
|
|
|
|
|
|
int
|
|
rte_cryptodev_start(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
int diag;
|
|
|
|
CDEV_LOG_DEBUG("Start dev_id=%" PRIu8, dev_id);
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
|
|
|
|
if (dev->data->dev_started != 0) {
|
|
CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already started",
|
|
dev_id);
|
|
return 0;
|
|
}
|
|
|
|
diag = (*dev->dev_ops->dev_start)(dev);
|
|
if (diag == 0)
|
|
dev->data->dev_started = 1;
|
|
else
|
|
return diag;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
rte_cryptodev_stop(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
|
|
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
|
|
|
|
if (dev->data->dev_started == 0) {
|
|
CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already stopped",
|
|
dev_id);
|
|
return;
|
|
}
|
|
|
|
(*dev->dev_ops->dev_stop)(dev);
|
|
dev->data->dev_started = 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_close(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
int retval;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return -1;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
|
|
/* Device must be stopped before it can be closed */
|
|
if (dev->data->dev_started == 1) {
|
|
CDEV_LOG_ERR("Device %u must be stopped before closing",
|
|
dev_id);
|
|
return -EBUSY;
|
|
}
|
|
|
|
/* We can't close the device if there are outstanding sessions in use */
|
|
if (dev->data->session_pool != NULL) {
|
|
if (!rte_mempool_full(dev->data->session_pool)) {
|
|
CDEV_LOG_ERR("dev_id=%u close failed, session mempool "
|
|
"has sessions still in use, free "
|
|
"all sessions before calling close",
|
|
(unsigned)dev_id);
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
|
|
retval = (*dev->dev_ops->dev_close)(dev);
|
|
|
|
if (retval < 0)
|
|
return retval;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
|
|
const struct rte_cryptodev_qp_conf *qp_conf, int socket_id)
|
|
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
if (queue_pair_id >= dev->data->nb_queue_pairs) {
|
|
CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (!qp_conf) {
|
|
CDEV_LOG_ERR("qp_conf cannot be NULL\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if ((qp_conf->mp_session && !qp_conf->mp_session_private) ||
|
|
(!qp_conf->mp_session && qp_conf->mp_session_private)) {
|
|
CDEV_LOG_ERR("Invalid mempools\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (qp_conf->mp_session) {
|
|
struct rte_cryptodev_sym_session_pool_private_data *pool_priv;
|
|
uint32_t obj_size = qp_conf->mp_session->elt_size;
|
|
uint32_t obj_priv_size = qp_conf->mp_session_private->elt_size;
|
|
struct rte_cryptodev_sym_session s = {0};
|
|
|
|
pool_priv = rte_mempool_get_priv(qp_conf->mp_session);
|
|
if (!pool_priv || qp_conf->mp_session->private_data_size <
|
|
sizeof(*pool_priv)) {
|
|
CDEV_LOG_ERR("Invalid mempool\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
s.nb_drivers = pool_priv->nb_drivers;
|
|
s.user_data_sz = pool_priv->user_data_sz;
|
|
|
|
if ((rte_cryptodev_sym_get_existing_header_session_size(&s) >
|
|
obj_size) || (s.nb_drivers <= dev->driver_id) ||
|
|
rte_cryptodev_sym_get_private_session_size(dev_id) >
|
|
obj_priv_size) {
|
|
CDEV_LOG_ERR("Invalid mempool\n");
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
if (dev->data->dev_started) {
|
|
CDEV_LOG_ERR(
|
|
"device %d must be stopped to allow configuration", dev_id);
|
|
return -EBUSY;
|
|
}
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_setup, -ENOTSUP);
|
|
|
|
return (*dev->dev_ops->queue_pair_setup)(dev, queue_pair_id, qp_conf,
|
|
socket_id);
|
|
}
|
|
|
|
|
|
int
|
|
rte_cryptodev_stats_get(uint8_t dev_id, struct rte_cryptodev_stats *stats)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
|
|
return -ENODEV;
|
|
}
|
|
|
|
if (stats == NULL) {
|
|
CDEV_LOG_ERR("Invalid stats ptr");
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
memset(stats, 0, sizeof(*stats));
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP);
|
|
(*dev->dev_ops->stats_get)(dev, stats);
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
rte_cryptodev_stats_reset(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
|
|
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
|
|
(*dev->dev_ops->stats_reset)(dev);
|
|
}
|
|
|
|
|
|
void
|
|
rte_cryptodev_info_get(uint8_t dev_id, struct rte_cryptodev_info *dev_info)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
if (dev_id >= cryptodev_globals.nb_devs) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
|
|
return;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
|
|
memset(dev_info, 0, sizeof(struct rte_cryptodev_info));
|
|
|
|
RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
|
|
(*dev->dev_ops->dev_infos_get)(dev, dev_info);
|
|
|
|
dev_info->driver_name = dev->device->driver->name;
|
|
dev_info->device = dev->device;
|
|
}
|
|
|
|
|
|
int
|
|
rte_cryptodev_callback_register(uint8_t dev_id,
|
|
enum rte_cryptodev_event_type event,
|
|
rte_cryptodev_cb_fn cb_fn, void *cb_arg)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
struct rte_cryptodev_callback *user_cb;
|
|
|
|
if (!cb_fn)
|
|
return -EINVAL;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
rte_spinlock_lock(&rte_cryptodev_cb_lock);
|
|
|
|
TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) {
|
|
if (user_cb->cb_fn == cb_fn &&
|
|
user_cb->cb_arg == cb_arg &&
|
|
user_cb->event == event) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* create a new callback. */
|
|
if (user_cb == NULL) {
|
|
user_cb = rte_zmalloc("INTR_USER_CALLBACK",
|
|
sizeof(struct rte_cryptodev_callback), 0);
|
|
if (user_cb != NULL) {
|
|
user_cb->cb_fn = cb_fn;
|
|
user_cb->cb_arg = cb_arg;
|
|
user_cb->event = event;
|
|
TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next);
|
|
}
|
|
}
|
|
|
|
rte_spinlock_unlock(&rte_cryptodev_cb_lock);
|
|
return (user_cb == NULL) ? -ENOMEM : 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_callback_unregister(uint8_t dev_id,
|
|
enum rte_cryptodev_event_type event,
|
|
rte_cryptodev_cb_fn cb_fn, void *cb_arg)
|
|
{
|
|
int ret;
|
|
struct rte_cryptodev *dev;
|
|
struct rte_cryptodev_callback *cb, *next;
|
|
|
|
if (!cb_fn)
|
|
return -EINVAL;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
|
CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
dev = &rte_crypto_devices[dev_id];
|
|
rte_spinlock_lock(&rte_cryptodev_cb_lock);
|
|
|
|
ret = 0;
|
|
for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) {
|
|
|
|
next = TAILQ_NEXT(cb, next);
|
|
|
|
if (cb->cb_fn != cb_fn || cb->event != event ||
|
|
(cb->cb_arg != (void *)-1 &&
|
|
cb->cb_arg != cb_arg))
|
|
continue;
|
|
|
|
/*
|
|
* if this callback is not executing right now,
|
|
* then remove it.
|
|
*/
|
|
if (cb->active == 0) {
|
|
TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next);
|
|
rte_free(cb);
|
|
} else {
|
|
ret = -EAGAIN;
|
|
}
|
|
}
|
|
|
|
rte_spinlock_unlock(&rte_cryptodev_cb_lock);
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
rte_cryptodev_pmd_callback_process(struct rte_cryptodev *dev,
|
|
enum rte_cryptodev_event_type event)
|
|
{
|
|
struct rte_cryptodev_callback *cb_lst;
|
|
struct rte_cryptodev_callback dev_cb;
|
|
|
|
rte_spinlock_lock(&rte_cryptodev_cb_lock);
|
|
TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
|
|
if (cb_lst->cb_fn == NULL || cb_lst->event != event)
|
|
continue;
|
|
dev_cb = *cb_lst;
|
|
cb_lst->active = 1;
|
|
rte_spinlock_unlock(&rte_cryptodev_cb_lock);
|
|
dev_cb.cb_fn(dev->data->dev_id, dev_cb.event,
|
|
dev_cb.cb_arg);
|
|
rte_spinlock_lock(&rte_cryptodev_cb_lock);
|
|
cb_lst->active = 0;
|
|
}
|
|
rte_spinlock_unlock(&rte_cryptodev_cb_lock);
|
|
}
|
|
|
|
|
|
int
|
|
rte_cryptodev_sym_session_init(uint8_t dev_id,
|
|
struct rte_cryptodev_sym_session *sess,
|
|
struct rte_crypto_sym_xform *xforms,
|
|
struct rte_mempool *mp)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
uint32_t sess_priv_sz = rte_cryptodev_sym_get_private_session_size(
|
|
dev_id);
|
|
uint8_t index;
|
|
int ret;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (sess == NULL || xforms == NULL || dev == NULL)
|
|
return -EINVAL;
|
|
|
|
if (mp->elt_size < sess_priv_sz)
|
|
return -EINVAL;
|
|
|
|
index = dev->driver_id;
|
|
if (index >= sess->nb_drivers)
|
|
return -EINVAL;
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->sym_session_configure, -ENOTSUP);
|
|
|
|
if (sess->sess_data[index].refcnt == 0) {
|
|
ret = dev->dev_ops->sym_session_configure(dev, xforms,
|
|
sess, mp);
|
|
if (ret < 0) {
|
|
CDEV_LOG_ERR(
|
|
"dev_id %d failed to configure session details",
|
|
dev_id);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
sess->sess_data[index].refcnt++;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_asym_session_init(uint8_t dev_id,
|
|
struct rte_cryptodev_asym_session *sess,
|
|
struct rte_crypto_asym_xform *xforms,
|
|
struct rte_mempool *mp)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
uint8_t index;
|
|
int ret;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (sess == NULL || xforms == NULL || dev == NULL)
|
|
return -EINVAL;
|
|
|
|
index = dev->driver_id;
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_session_configure,
|
|
-ENOTSUP);
|
|
|
|
if (sess->sess_private_data[index] == NULL) {
|
|
ret = dev->dev_ops->asym_session_configure(dev,
|
|
xforms,
|
|
sess, mp);
|
|
if (ret < 0) {
|
|
CDEV_LOG_ERR(
|
|
"dev_id %d failed to configure session details",
|
|
dev_id);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct rte_mempool *
|
|
rte_cryptodev_sym_session_pool_create(const char *name, uint32_t nb_elts,
|
|
uint32_t elt_size, uint32_t cache_size, uint16_t user_data_size,
|
|
int socket_id)
|
|
{
|
|
struct rte_mempool *mp;
|
|
struct rte_cryptodev_sym_session_pool_private_data *pool_priv;
|
|
uint32_t obj_sz;
|
|
|
|
obj_sz = rte_cryptodev_sym_get_header_session_size() + user_data_size;
|
|
if (obj_sz > elt_size)
|
|
CDEV_LOG_INFO("elt_size %u is expanded to %u\n", elt_size,
|
|
obj_sz);
|
|
else
|
|
obj_sz = elt_size;
|
|
|
|
mp = rte_mempool_create(name, nb_elts, obj_sz, cache_size,
|
|
(uint32_t)(sizeof(*pool_priv)),
|
|
NULL, NULL, NULL, NULL,
|
|
socket_id, 0);
|
|
if (mp == NULL) {
|
|
CDEV_LOG_ERR("%s(name=%s) failed, rte_errno=%d\n",
|
|
__func__, name, rte_errno);
|
|
return NULL;
|
|
}
|
|
|
|
pool_priv = rte_mempool_get_priv(mp);
|
|
if (!pool_priv) {
|
|
CDEV_LOG_ERR("%s(name=%s) failed to get private data\n",
|
|
__func__, name);
|
|
rte_mempool_free(mp);
|
|
return NULL;
|
|
}
|
|
|
|
pool_priv->nb_drivers = nb_drivers;
|
|
pool_priv->user_data_sz = user_data_size;
|
|
|
|
return mp;
|
|
}
|
|
|
|
static unsigned int
|
|
rte_cryptodev_sym_session_data_size(struct rte_cryptodev_sym_session *sess)
|
|
{
|
|
return (sizeof(sess->sess_data[0]) * sess->nb_drivers) +
|
|
sess->user_data_sz;
|
|
}
|
|
|
|
struct rte_cryptodev_sym_session *
|
|
rte_cryptodev_sym_session_create(struct rte_mempool *mp)
|
|
{
|
|
struct rte_cryptodev_sym_session *sess;
|
|
struct rte_cryptodev_sym_session_pool_private_data *pool_priv;
|
|
|
|
if (!mp) {
|
|
CDEV_LOG_ERR("Invalid mempool\n");
|
|
return NULL;
|
|
}
|
|
|
|
pool_priv = rte_mempool_get_priv(mp);
|
|
|
|
if (!pool_priv || mp->private_data_size < sizeof(*pool_priv)) {
|
|
CDEV_LOG_ERR("Invalid mempool\n");
|
|
return NULL;
|
|
}
|
|
|
|
/* Allocate a session structure from the session pool */
|
|
if (rte_mempool_get(mp, (void **)&sess)) {
|
|
CDEV_LOG_ERR("couldn't get object from session mempool");
|
|
return NULL;
|
|
}
|
|
|
|
sess->nb_drivers = pool_priv->nb_drivers;
|
|
sess->user_data_sz = pool_priv->user_data_sz;
|
|
sess->opaque_data = 0;
|
|
|
|
/* Clear device session pointer.
|
|
* Include the flag indicating presence of user data
|
|
*/
|
|
memset(sess->sess_data, 0,
|
|
rte_cryptodev_sym_session_data_size(sess));
|
|
|
|
return sess;
|
|
}
|
|
|
|
struct rte_cryptodev_asym_session *
|
|
rte_cryptodev_asym_session_create(struct rte_mempool *mp)
|
|
{
|
|
struct rte_cryptodev_asym_session *sess;
|
|
|
|
/* Allocate a session structure from the session pool */
|
|
if (rte_mempool_get(mp, (void **)&sess)) {
|
|
CDEV_LOG_ERR("couldn't get object from session mempool");
|
|
return NULL;
|
|
}
|
|
|
|
/* Clear device session pointer.
|
|
* Include the flag indicating presence of private data
|
|
*/
|
|
memset(sess, 0, (sizeof(void *) * nb_drivers) + sizeof(uint8_t));
|
|
|
|
return sess;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_sym_session_clear(uint8_t dev_id,
|
|
struct rte_cryptodev_sym_session *sess)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
uint8_t driver_id;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (dev == NULL || sess == NULL)
|
|
return -EINVAL;
|
|
|
|
driver_id = dev->driver_id;
|
|
if (sess->sess_data[driver_id].refcnt == 0)
|
|
return 0;
|
|
if (--sess->sess_data[driver_id].refcnt != 0)
|
|
return -EBUSY;
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->sym_session_clear, -ENOTSUP);
|
|
|
|
dev->dev_ops->sym_session_clear(dev, sess);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_asym_session_clear(uint8_t dev_id,
|
|
struct rte_cryptodev_asym_session *sess)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (dev == NULL || sess == NULL)
|
|
return -EINVAL;
|
|
|
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_session_clear, -ENOTSUP);
|
|
|
|
dev->dev_ops->asym_session_clear(dev, sess);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess)
|
|
{
|
|
uint8_t i;
|
|
struct rte_mempool *sess_mp;
|
|
|
|
if (sess == NULL)
|
|
return -EINVAL;
|
|
|
|
/* Check that all device private data has been freed */
|
|
for (i = 0; i < sess->nb_drivers; i++) {
|
|
if (sess->sess_data[i].refcnt != 0)
|
|
return -EBUSY;
|
|
}
|
|
|
|
/* Return session to mempool */
|
|
sess_mp = rte_mempool_from_obj(sess);
|
|
rte_mempool_put(sess_mp, sess);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess)
|
|
{
|
|
uint8_t i;
|
|
void *sess_priv;
|
|
struct rte_mempool *sess_mp;
|
|
|
|
if (sess == NULL)
|
|
return -EINVAL;
|
|
|
|
/* Check that all device private data has been freed */
|
|
for (i = 0; i < nb_drivers; i++) {
|
|
sess_priv = get_asym_session_private_data(sess, i);
|
|
if (sess_priv != NULL)
|
|
return -EBUSY;
|
|
}
|
|
|
|
/* Return session to mempool */
|
|
sess_mp = rte_mempool_from_obj(sess);
|
|
rte_mempool_put(sess_mp, sess);
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned int
|
|
rte_cryptodev_sym_get_header_session_size(void)
|
|
{
|
|
/*
|
|
* Header contains pointers to the private data of all registered
|
|
* drivers and all necessary information to ensure safely clear
|
|
* or free al session.
|
|
*/
|
|
struct rte_cryptodev_sym_session s = {0};
|
|
|
|
s.nb_drivers = nb_drivers;
|
|
|
|
return (unsigned int)(sizeof(s) +
|
|
rte_cryptodev_sym_session_data_size(&s));
|
|
}
|
|
|
|
unsigned int
|
|
rte_cryptodev_sym_get_existing_header_session_size(
|
|
struct rte_cryptodev_sym_session *sess)
|
|
{
|
|
if (!sess)
|
|
return 0;
|
|
else
|
|
return (unsigned int)(sizeof(*sess) +
|
|
rte_cryptodev_sym_session_data_size(sess));
|
|
}
|
|
|
|
unsigned int
|
|
rte_cryptodev_asym_get_header_session_size(void)
|
|
{
|
|
/*
|
|
* Header contains pointers to the private data
|
|
* of all registered drivers, and a flag which
|
|
* indicates presence of private data
|
|
*/
|
|
return ((sizeof(void *) * nb_drivers) + sizeof(uint8_t));
|
|
}
|
|
|
|
unsigned int
|
|
rte_cryptodev_sym_get_private_session_size(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
unsigned int priv_sess_size;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
|
|
return 0;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (*dev->dev_ops->sym_session_get_size == NULL)
|
|
return 0;
|
|
|
|
priv_sess_size = (*dev->dev_ops->sym_session_get_size)(dev);
|
|
|
|
return priv_sess_size;
|
|
}
|
|
|
|
unsigned int
|
|
rte_cryptodev_asym_get_private_session_size(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev;
|
|
unsigned int header_size = sizeof(void *) * nb_drivers;
|
|
unsigned int priv_sess_size;
|
|
|
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
|
|
return 0;
|
|
|
|
dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (*dev->dev_ops->asym_session_get_size == NULL)
|
|
return 0;
|
|
|
|
priv_sess_size = (*dev->dev_ops->asym_session_get_size)(dev);
|
|
if (priv_sess_size < header_size)
|
|
return header_size;
|
|
|
|
return priv_sess_size;
|
|
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_sym_session_set_user_data(
|
|
struct rte_cryptodev_sym_session *sess,
|
|
void *data,
|
|
uint16_t size)
|
|
{
|
|
if (sess == NULL)
|
|
return -EINVAL;
|
|
|
|
if (sess->user_data_sz < size)
|
|
return -ENOMEM;
|
|
|
|
rte_memcpy(sess->sess_data + sess->nb_drivers, data, size);
|
|
return 0;
|
|
}
|
|
|
|
void *
|
|
rte_cryptodev_sym_session_get_user_data(
|
|
struct rte_cryptodev_sym_session *sess)
|
|
{
|
|
if (sess == NULL || sess->user_data_sz == 0)
|
|
return NULL;
|
|
|
|
return (void *)(sess->sess_data + sess->nb_drivers);
|
|
}
|
|
|
|
/** Initialise rte_crypto_op mempool element */
|
|
static void
|
|
rte_crypto_op_init(struct rte_mempool *mempool,
|
|
void *opaque_arg,
|
|
void *_op_data,
|
|
__rte_unused unsigned i)
|
|
{
|
|
struct rte_crypto_op *op = _op_data;
|
|
enum rte_crypto_op_type type = *(enum rte_crypto_op_type *)opaque_arg;
|
|
|
|
memset(_op_data, 0, mempool->elt_size);
|
|
|
|
__rte_crypto_op_reset(op, type);
|
|
|
|
op->phys_addr = rte_mem_virt2iova(_op_data);
|
|
op->mempool = mempool;
|
|
}
|
|
|
|
|
|
struct rte_mempool *
|
|
rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
|
|
unsigned nb_elts, unsigned cache_size, uint16_t priv_size,
|
|
int socket_id)
|
|
{
|
|
struct rte_crypto_op_pool_private *priv;
|
|
|
|
unsigned elt_size = sizeof(struct rte_crypto_op) +
|
|
priv_size;
|
|
|
|
if (type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
|
|
elt_size += sizeof(struct rte_crypto_sym_op);
|
|
} else if (type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
|
|
elt_size += sizeof(struct rte_crypto_asym_op);
|
|
} else if (type == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
|
|
elt_size += RTE_MAX(sizeof(struct rte_crypto_sym_op),
|
|
sizeof(struct rte_crypto_asym_op));
|
|
} else {
|
|
CDEV_LOG_ERR("Invalid op_type\n");
|
|
return NULL;
|
|
}
|
|
|
|
/* lookup mempool in case already allocated */
|
|
struct rte_mempool *mp = rte_mempool_lookup(name);
|
|
|
|
if (mp != NULL) {
|
|
priv = (struct rte_crypto_op_pool_private *)
|
|
rte_mempool_get_priv(mp);
|
|
|
|
if (mp->elt_size != elt_size ||
|
|
mp->cache_size < cache_size ||
|
|
mp->size < nb_elts ||
|
|
priv->priv_size < priv_size) {
|
|
mp = NULL;
|
|
CDEV_LOG_ERR("Mempool %s already exists but with "
|
|
"incompatible parameters", name);
|
|
return NULL;
|
|
}
|
|
return mp;
|
|
}
|
|
|
|
mp = rte_mempool_create(
|
|
name,
|
|
nb_elts,
|
|
elt_size,
|
|
cache_size,
|
|
sizeof(struct rte_crypto_op_pool_private),
|
|
NULL,
|
|
NULL,
|
|
rte_crypto_op_init,
|
|
&type,
|
|
socket_id,
|
|
0);
|
|
|
|
if (mp == NULL) {
|
|
CDEV_LOG_ERR("Failed to create mempool %s", name);
|
|
return NULL;
|
|
}
|
|
|
|
priv = (struct rte_crypto_op_pool_private *)
|
|
rte_mempool_get_priv(mp);
|
|
|
|
priv->priv_size = priv_size;
|
|
priv->type = type;
|
|
|
|
return mp;
|
|
}
|
|
|
|
int
|
|
rte_cryptodev_pmd_create_dev_name(char *name, const char *dev_name_prefix)
|
|
{
|
|
struct rte_cryptodev *dev = NULL;
|
|
uint32_t i = 0;
|
|
|
|
if (name == NULL)
|
|
return -EINVAL;
|
|
|
|
for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++) {
|
|
int ret = snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN,
|
|
"%s_%u", dev_name_prefix, i);
|
|
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
dev = rte_cryptodev_pmd_get_named_dev(name);
|
|
if (!dev)
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
TAILQ_HEAD(cryptodev_driver_list, cryptodev_driver);
|
|
|
|
static struct cryptodev_driver_list cryptodev_driver_list =
|
|
TAILQ_HEAD_INITIALIZER(cryptodev_driver_list);
|
|
|
|
int
|
|
rte_cryptodev_driver_id_get(const char *name)
|
|
{
|
|
struct cryptodev_driver *driver;
|
|
const char *driver_name;
|
|
|
|
if (name == NULL) {
|
|
RTE_LOG(DEBUG, CRYPTODEV, "name pointer NULL");
|
|
return -1;
|
|
}
|
|
|
|
TAILQ_FOREACH(driver, &cryptodev_driver_list, next) {
|
|
driver_name = driver->driver->name;
|
|
if (strncmp(driver_name, name, strlen(driver_name) + 1) == 0)
|
|
return driver->id;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
const char *
|
|
rte_cryptodev_name_get(uint8_t dev_id)
|
|
{
|
|
struct rte_cryptodev *dev = rte_cryptodev_pmd_get_dev(dev_id);
|
|
|
|
if (dev == NULL)
|
|
return NULL;
|
|
|
|
return dev->data->name;
|
|
}
|
|
|
|
const char *
|
|
rte_cryptodev_driver_name_get(uint8_t driver_id)
|
|
{
|
|
struct cryptodev_driver *driver;
|
|
|
|
TAILQ_FOREACH(driver, &cryptodev_driver_list, next)
|
|
if (driver->id == driver_id)
|
|
return driver->driver->name;
|
|
return NULL;
|
|
}
|
|
|
|
uint8_t
|
|
rte_cryptodev_allocate_driver(struct cryptodev_driver *crypto_drv,
|
|
const struct rte_driver *drv)
|
|
{
|
|
crypto_drv->driver = drv;
|
|
crypto_drv->id = nb_drivers;
|
|
|
|
TAILQ_INSERT_TAIL(&cryptodev_driver_list, crypto_drv, next);
|
|
|
|
return nb_drivers++;
|
|
}
|