accel: Add crypto operation support

Add functions to submit encrypt/decrypt operations
Add RPCS to register and dump crypto keys
Software accel module uses isa-l_crypto AEX_XTS
functionality

Signed-off-by: Alexey Marchuk <alexeymar@nvidia.com>
Change-Id: Iecf0e9913edf11ab85171d0fa467a2a62dfff984
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14858
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: <qun.wan@intel.com>
Reviewed-by: Shuhei Matsumoto <smatsumoto@nvidia.com>
This commit is contained in:
Alexey Marchuk 2022-10-04 21:16:21 +02:00 committed by Tomasz Zawadzki
parent d68159b618
commit 2608d129d0
14 changed files with 1033 additions and 20 deletions

View File

@ -6,6 +6,8 @@
New library isa-l-crypto has been added, it is used by accel library in crypto operations.
New functions `spdk_accel_submit_encrypt` and `spdk_accel_submit_decrypt` were added.
### bdev
Both of interleaved and separated metadata are now supported by the malloc bdev module.

View File

@ -442,6 +442,8 @@ Example response:
"framework_monitor_context_switch",
"spdk_kill_instance",
"accel_get_opc_assignments",
"accel_crypto_key_create",
"accel_crypto_keys_get",
"ioat_scan_accel_module",
"dsa_scan_accel_module",
"bdev_virtio_attach_controller",
@ -1776,6 +1778,92 @@ Example response:
}
~~~
### accel_crypto_key_create {#rpc_accel_crypto_key_create}
Create a crypt key which will be used in accel framework
#### Parameters
Name | Optional | Type | Description
-----------|----------| ----------- | -----------------
cipher | Required | string | crypto cipher to use
key | Required | string | Key in **hex** form
key2 | Optional | string | Optional 2nd part of the key or a tweak in **hex** form
name | Required | string | The key name
#### Example
Example request:
~~~json
{
"jsonrpc": "2.0",
"method": "accel_crypto_key_create",
"id": 1,
"params": {
"cipher": "AES_XTS",
"key": "00112233445566778899001122334455",
"key2": "00112233445566778899001122334455",
"name": "super_key"
}
}
~~~
Example response:
~~~json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
~~~
### accel_crypto_keys_get {#rpc_accel_crypto_keys_get}
Get information about existing crypto keys
#### Parameters
Name | Optional | Type | Description
----------------------- |----------| ----------- | -----------------
key_name | Optional | string | If specified, return info about a specific key
#### Example
Example request:
~~~json
{
"jsonrpc": "2.0",
"method": "accel_crypto_keys_get",
"id": 1
}
~~~
Example response:
~~~json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"name": "test_dek",
"cipher": "AES_XTS",
"key": "00112233445566778899001122334455",
"key2": "11223344556677889900112233445500"
},
{
"name": "test_dek2",
"cipher": "AES_XTS",
"key": "11223344556677889900112233445500",
"key2": "22334455667788990011223344550011"
}
]
}
~~~
### dsa_scan_accel_module {#rpc_dsa_scan_accel_module}
Set config and enable dsa accel module offload.

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2020 Intel Corporation.
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES
* All rights reserved.
*/
@ -17,9 +18,19 @@
extern "C" {
#endif
/** Data Encryption Key identifier */
struct spdk_accel_crypto_key;
/* Flags for accel operations */
#define ACCEL_FLAG_PERSISTENT (1 << 0)
struct spdk_accel_crypto_key_create_param {
char *cipher; /**< Cipher to be used for crypto operations */
char *hex_key; /**< Hexlified key */
char *hex_key2; /**< Hexlified key2 */
char *key_name; /**< Key name */
};
enum accel_opcode {
ACCEL_OPC_COPY = 0,
ACCEL_OPC_FILL = 1,
@ -29,7 +40,9 @@ enum accel_opcode {
ACCEL_OPC_COPY_CRC32C = 5,
ACCEL_OPC_COMPRESS = 6,
ACCEL_OPC_DECOMPRESS = 7,
ACCEL_OPC_LAST = 8,
ACCEL_OPC_ENCRYPT = 8,
ACCEL_OPC_DECRYPT = 9,
ACCEL_OPC_LAST = 10,
};
/**
@ -71,6 +84,29 @@ void spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg);
*/
struct spdk_io_channel *spdk_accel_get_io_channel(void);
/**
* Create a crypto key with given parameters. Accel module copies content of \b param structure
*
* \param param Key parameters
* \return 0 on success, negated errno on error
*/
int spdk_accel_crypto_key_create(const struct spdk_accel_crypto_key_create_param *param);
/**
* Destroy a crypto key
*
* \param key Key to destroy
* \return 0 on success, negated errno on error
*/
int spdk_accel_crypto_key_destroy(struct spdk_accel_crypto_key *key);
/**
* Find a crypto key structure by name
* \param name Key name
* \return Crypto key structure or NULL
*/
struct spdk_accel_crypto_key *spdk_accel_crypto_key_get(const char *name);
/**
* Submit a copy request.
*
@ -404,6 +440,67 @@ int spdk_accel_get_buf(struct spdk_io_channel *ch, uint64_t len, void **buf,
void spdk_accel_put_buf(struct spdk_io_channel *ch, void *buf,
struct spdk_memory_domain *domain, void *domain_ctx);
/**
* Build and submit a data encryption request.
*
* This function will build the encryption request and submit it. \b nbytes must be multiple of \b block_size.
* \b iv is used to encrypt the first logical block of size \b block_size. If \b src_iovs describes more than
* one logical block then \b iv will be incremented for each next logical block.
* Data Encryption Key identifier should be created before calling this function using methods specific to the accel
* module being used.
*
* \param ch I/O channel associated with this call
* \param key Data Encryption Key identifier
* \param dst_iovs The io vector array which stores the dst data and len.
* \param dst_iovcnt The size of the destination io vectors.
* \param src_iovs The io vector array which stores the src data and len.
* \param src_iovcnt The size of the source io vectors.
* \param iv Initialization vector (tweak) used for encryption
* \param block_size Logical block size, if src contains more than 1 logical block, subsequent logical blocks will be
* encrypted with incremented \b iv
* \param flags Accel framework flags for operations.
* \param cb_fn Callback function which will be called when the request is complete.
* \param cb_arg Opaque value which will be passed back as the arg parameter in the completion callback.
*
* \return 0 on success, negative errno on failure.
*/
int spdk_accel_submit_encrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
struct iovec *dst_iovs, uint32_t dst_iovcnt,
struct iovec *src_iovs, uint32_t src_iovcnt,
uint64_t iv, uint32_t block_size, int flags,
spdk_accel_completion_cb cb_fn, void *cb_arg);
/**
* Build and submit a data decryption request.
*
* This function will build the decryption request and submit it. \b nbytes must be multiple of \b block_size.
* \b iv is used to decrypt the first logical block of size \b block_size. If \b src_iovs describes more than
* one logical block then \b iv will be incremented for each next logical block.
* Data Encryption Key identifier should be created before calling this function using methods specific to the accel
* module being used.
*
* \param ch I/O channel associated with this call
* \param key Data Encryption Key identifier
* \param dst_iovs The io vector array which stores the dst data and len.
* \param dst_iovcnt The size of the destination io vectors.
* \param src_iovs The io vector array which stores the src data and len.
* \param src_iovcnt The size of the source io vectors.
* \param iv Initialization vector (tweak) used for decryption. Should be the same as \b iv used for encryption of a
* data block
* \param block_size Logical block size, if src contains more than 1 logical block, subsequent logical blocks will be
* decrypted with incremented \b iv
* \param flags Accel framework flags for operations.
* \param cb_fn Callback function which will be called when the request is complete.
* \param cb_arg Opaque value which will be passed back as the arg parameter in the completion callback.
*
* \return 0 on success, negative errno on failure.
*/
int spdk_accel_submit_decrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
struct iovec *dst_iovs, uint32_t dst_iovcnt,
struct iovec *src_iovs, uint32_t src_iovcnt,
uint64_t iv, uint32_t block_size, int flags,
spdk_accel_completion_cb cb_fn, void *cb_arg);
/**
* Return the name of the module assigned to a specific opcode.
*

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2020 Intel Corporation.
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES
* All rights reserved.
*/
@ -12,10 +13,25 @@
#include "spdk/queue.h"
#include "spdk/config.h"
struct spdk_accel_module_if;
struct spdk_accel_task;
void spdk_accel_task_complete(struct spdk_accel_task *task, int status);
/** Some reasonable key length used with strnlen() */
#define SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH (256 + 1)
struct spdk_accel_crypto_key {
void *priv; /**< Module private data */
char *key; /**< Key in binary form */
size_t key_size; /**< Key size in bytes */
char *key2; /**< Key2 in binary form */
size_t key2_size; /**< Key2 size in bytes */
struct spdk_accel_module_if *module_if; /**< Accel module the key belongs to */
struct spdk_accel_crypto_key_create_param param; /**< User input parameters */
TAILQ_ENTRY(spdk_accel_crypto_key) link;
};
struct spdk_accel_task {
struct accel_io_channel *accel_ch;
spdk_accel_completion_cb cb_fn;
@ -45,14 +61,19 @@ struct spdk_accel_task {
void *dst2;
uint32_t seed;
uint64_t fill_pattern;
struct spdk_accel_crypto_key *crypto_key;
};
union {
uint32_t *crc_dst;
uint32_t *output_size;
uint32_t block_size; /* for crypto op */
};
enum accel_opcode op_code;
uint64_t nbytes;
uint64_t nbytes_dst;
union {
uint64_t nbytes_dst; /* for compress op */
uint64_t iv; /* Initialization vector (tweak) for crypto op */
};
int flags;
int status;
TAILQ_ENTRY(spdk_accel_task) link;
@ -89,6 +110,13 @@ struct spdk_accel_module_if {
struct spdk_io_channel *(*get_io_channel)(void);
int (*submit_tasks)(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task);
/**
* Create crypto key function. Module is responsible to fill all necessary parameters in
* \b spdk_accel_crypto_key structure
*/
int (*crypto_key_init)(struct spdk_accel_crypto_key *key);
void (*crypto_key_deinit)(struct spdk_accel_crypto_key *key);
TAILQ_ENTRY(spdk_accel_module_if) tailq;
};

View File

@ -1,5 +1,6 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2015 Intel Corporation.
# Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES
# All rights reserved.
#
@ -17,6 +18,10 @@ ifeq ($(CONFIG_ISAL), y)
LOCAL_SYS_LIBS = -L$(ISAL_DIR)/.libs -lisal
endif
ifeq ($(CONFIG_ISAL_CRYPTO), y)
LOCAL_SYS_LIBS = -L$(ISAL_CRYPTO_DIR)/.libs -lisal_crypto
endif
SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_accel.map)
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

View File

@ -18,6 +18,7 @@
#include "spdk/json.h"
#include "spdk/crc32.h"
#include "spdk/util.h"
#include "spdk/hexlify.h"
/* Accelerator Framework: The following provides a top level
* generic API for the accelerator functions defined here. Modules,
@ -46,13 +47,17 @@ static struct spdk_memory_domain *g_accel_domain;
static TAILQ_HEAD(, spdk_accel_module_if) spdk_accel_module_list =
TAILQ_HEAD_INITIALIZER(spdk_accel_module_list);
/* Crypto keyring */
static TAILQ_HEAD(, spdk_accel_crypto_key) g_keyring = TAILQ_HEAD_INITIALIZER(g_keyring);
static struct spdk_spinlock g_keyring_spin;
/* Global array mapping capabilities to modules */
static struct spdk_accel_module_if *g_modules_opc[ACCEL_OPC_LAST] = {};
static char *g_modules_opc_override[ACCEL_OPC_LAST] = {};
static const char *g_opcode_strings[ACCEL_OPC_LAST] = {
"copy", "fill", "dualcast", "compare", "crc32c", "copy_crc32c",
"compress", "decompress"
"compress", "decompress", "encrypt", "decrypt"
};
struct accel_buffer {
@ -191,8 +196,6 @@ _get_task(struct accel_io_channel *accel_ch, spdk_accel_completion_cb cb_fn, voi
return accel_task;
}
/* Accel framework public API for copy function */
int
spdk_accel_submit_copy(struct spdk_io_channel *ch, void *dst, void *src,
@ -526,6 +529,106 @@ spdk_accel_submit_decompress(struct spdk_io_channel *ch, struct iovec *dst_iovs,
return 0;
}
int
spdk_accel_submit_encrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
struct iovec *dst_iovs, uint32_t dst_iovcnt,
struct iovec *src_iovs, uint32_t src_iovcnt,
uint64_t iv, uint32_t block_size, int flags,
spdk_accel_completion_cb cb_fn, void *cb_arg)
{
struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
struct spdk_accel_task *accel_task;
struct spdk_accel_module_if *module = g_modules_opc[ACCEL_OPC_ENCRYPT];
struct spdk_io_channel *module_ch = accel_ch->module_ch[ACCEL_OPC_ENCRYPT];
size_t src_nbytes = 0, dst_nbytes = 0;
uint32_t i;
if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || !block_size)) {
return -EINVAL;
}
for (i = 0; i < src_iovcnt; i++) {
src_nbytes += src_iovs[i].iov_len;
}
for (i = 0; i < dst_iovcnt; i++) {
dst_nbytes += dst_iovs[i].iov_len;
}
if (spdk_unlikely(src_nbytes != dst_nbytes || !src_nbytes)) {
return -ERANGE;
}
if (spdk_unlikely(src_nbytes % block_size != 0)) {
return -EINVAL;
}
accel_task = _get_task(accel_ch, cb_fn, cb_arg);
if (accel_task == NULL) {
return -ENOMEM;
}
accel_task->crypto_key = key;
accel_task->s.iovs = src_iovs;
accel_task->s.iovcnt = src_iovcnt;
accel_task->d.iovs = dst_iovs;
accel_task->d.iovcnt = dst_iovcnt;
accel_task->nbytes = src_nbytes;
accel_task->iv = iv;
accel_task->block_size = block_size;
accel_task->flags = flags;
accel_task->op_code = ACCEL_OPC_ENCRYPT;
return module->submit_tasks(module_ch, accel_task);
}
int
spdk_accel_submit_decrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
struct iovec *dst_iovs, uint32_t dst_iovcnt,
struct iovec *src_iovs, uint32_t src_iovcnt,
uint64_t iv, uint32_t block_size, int flags,
spdk_accel_completion_cb cb_fn, void *cb_arg)
{
struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
struct spdk_accel_task *accel_task;
struct spdk_accel_module_if *module = g_modules_opc[ACCEL_OPC_DECRYPT];
struct spdk_io_channel *module_ch = accel_ch->module_ch[ACCEL_OPC_DECRYPT];
size_t src_nbytes = 0, dst_nbytes = 0;
uint32_t i;
if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || !block_size)) {
return -EINVAL;
}
for (i = 0; i < src_iovcnt; i++) {
src_nbytes += src_iovs[i].iov_len;
}
for (i = 0; i < dst_iovcnt; i++) {
dst_nbytes += dst_iovs[i].iov_len;
}
if (spdk_unlikely(src_nbytes != dst_nbytes || !src_nbytes)) {
return -ERANGE;
}
if (spdk_unlikely(src_nbytes % block_size != 0)) {
return -EINVAL;
}
accel_task = _get_task(accel_ch, cb_fn, cb_arg);
if (accel_task == NULL) {
return -ENOMEM;
}
accel_task->crypto_key = key;
accel_task->s.iovs = src_iovs;
accel_task->s.iovcnt = src_iovcnt;
accel_task->d.iovs = dst_iovs;
accel_task->d.iovcnt = dst_iovcnt;
accel_task->nbytes = src_nbytes;
accel_task->iv = iv;
accel_task->block_size = block_size;
accel_task->flags = flags;
accel_task->op_code = ACCEL_OPC_DECRYPT;
return module->submit_tasks(module_ch, accel_task);
}
static inline struct accel_buffer *
accel_get_buf(struct accel_io_channel *ch, uint64_t len)
{
@ -1036,7 +1139,224 @@ _module_find_by_name(const char *name)
return accel_module;
}
/* Helper function when when accel modules register with the framework. */
static inline struct spdk_accel_crypto_key *
_accel_crypto_key_get(const char *name)
{
struct spdk_accel_crypto_key *key;
assert(spdk_spin_held(&g_keyring_spin));
TAILQ_FOREACH(key, &g_keyring, link) {
if (strcmp(name, key->param.key_name) == 0) {
return key;
}
}
return NULL;
}
static void
accel_crypto_key_free_mem(struct spdk_accel_crypto_key *key)
{
if (key->param.hex_key) {
spdk_memset_s(key->param.hex_key, key->key_size * 2, 0, key->key_size * 2);
free(key->param.hex_key);
}
if (key->param.hex_key2) {
spdk_memset_s(key->param.hex_key2, key->key2_size * 2, 0, key->key2_size * 2);
free(key->param.hex_key2);
}
free(key->param.key_name);
free(key->param.cipher);
if (key->key) {
spdk_memset_s(key->key, key->key_size, 0, key->key_size);
free(key->key);
}
if (key->key2) {
spdk_memset_s(key->key2, key->key2_size, 0, key->key2_size);
free(key->key2);
}
free(key);
}
static void
accel_crypto_key_destroy_unsafe(struct spdk_accel_crypto_key *key)
{
assert(key->module_if);
assert(key->module_if->crypto_key_deinit);
key->module_if->crypto_key_deinit(key);
accel_crypto_key_free_mem(key);
}
/*
* This function mitigates a timing side channel which could be caused by using strcmp()
* Please refer to chapter "Mitigating Information Leakage Based on Variable Timing" in
* the article [1] for more details
* [1] https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/secure-coding/mitigate-timing-side-channel-crypto-implementation.html
*/
static bool
accel_aes_xts_keys_equal(const char *k1, size_t k1_len, const char *k2, size_t k2_len)
{
size_t i;
volatile size_t x = k1_len ^ k2_len;
for (i = 0; ((i < k1_len) & (i < k2_len)); i++) {
x |= k1[i] ^ k2[i];
}
return x == 0;
}
int
spdk_accel_crypto_key_create(const struct spdk_accel_crypto_key_create_param *param)
{
struct spdk_accel_module_if *module;
struct spdk_accel_crypto_key *key;
size_t hex_key_size, hex_key2_size;
int rc;
if (!param || !param->hex_key || !param->cipher || !param->key_name) {
return -EINVAL;
}
if (g_modules_opc[ACCEL_OPC_ENCRYPT] != g_modules_opc[ACCEL_OPC_DECRYPT]) {
/* hardly ever possible, but let's check and warn the user */
SPDK_ERRLOG("Different accel modules are used for encryption and decryption\n");
}
module = g_modules_opc[ACCEL_OPC_ENCRYPT];
if (!module) {
SPDK_ERRLOG("No accel module found assigned for crypto operation\n");
return -ENOENT;
}
if (!module->crypto_key_init) {
SPDK_ERRLOG("Accel module \"%s\" doesn't support crypto operations\n", module->name);
return -ENOTSUP;
}
key = calloc(1, sizeof(*key));
if (!key) {
return -ENOMEM;
}
key->param.key_name = strdup(param->key_name);
if (!key->param.key_name) {
rc = -ENOMEM;
goto error;
}
key->param.cipher = strdup(param->cipher);
if (!key->param.cipher) {
rc = -ENOMEM;
goto error;
}
hex_key_size = strnlen(param->hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
if (hex_key_size == SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH) {
SPDK_ERRLOG("key1 size exceeds max %d\n", SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
rc = -EINVAL;
goto error;
}
key->param.hex_key = strdup(param->hex_key);
if (!key->param.hex_key) {
rc = -ENOMEM;
goto error;
}
key->key_size = hex_key_size / 2;
key->key = spdk_unhexlify(key->param.hex_key);
if (!key->key) {
SPDK_ERRLOG("Failed to unhexlify key1\n");
rc = -EINVAL;
goto error;
}
if (param->hex_key2) {
hex_key2_size = strnlen(param->hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
if (hex_key2_size == SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH) {
SPDK_ERRLOG("key2 size exceeds max %d\n", SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
rc = -EINVAL;
goto error;
}
key->param.hex_key2 = strdup(param->hex_key2);
if (!key->param.hex_key2) {
rc = -ENOMEM;
goto error;
}
key->key2_size = hex_key2_size / 2;
key->key2 = spdk_unhexlify(key->param.hex_key2);
if (!key->key2) {
SPDK_ERRLOG("Failed to unhexlify key2\n");
rc = -EINVAL;
goto error;
}
if (accel_aes_xts_keys_equal(key->key, key->key_size, key->key2, key->key2_size)) {
SPDK_ERRLOG("Identical keys are not secure\n");
rc = -EINVAL;
goto error;
}
}
key->module_if = module;
spdk_spin_lock(&g_keyring_spin);
if (_accel_crypto_key_get(param->key_name)) {
rc = -EEXIST;
} else {
rc = module->crypto_key_init(key);
if (!rc) {
TAILQ_INSERT_TAIL(&g_keyring, key, link);
}
}
spdk_spin_unlock(&g_keyring_spin);
if (rc) {
goto error;
}
return 0;
error:
accel_crypto_key_free_mem(key);
return rc;
}
int
spdk_accel_crypto_key_destroy(struct spdk_accel_crypto_key *key)
{
if (!key || !key->module_if) {
return -EINVAL;
}
spdk_spin_lock(&g_keyring_spin);
if (!_accel_crypto_key_get(key->param.key_name)) {
spdk_spin_unlock(&g_keyring_spin);
return -ENOENT;
}
TAILQ_REMOVE(&g_keyring, key, link);
spdk_spin_unlock(&g_keyring_spin);
accel_crypto_key_destroy_unsafe(key);
return 0;
}
struct spdk_accel_crypto_key *
spdk_accel_crypto_key_get(const char *name)
{
struct spdk_accel_crypto_key *key;
spdk_spin_lock(&g_keyring_spin);
key = _accel_crypto_key_get(name);
spdk_spin_unlock(&g_keyring_spin);
return key;
}
/* Helper function when accel modules register with the framework. */
void
spdk_accel_module_list_add(struct spdk_accel_module_if *accel_module)
{
@ -1048,7 +1368,7 @@ spdk_accel_module_list_add(struct spdk_accel_module_if *accel_module)
/* Make sure that the software module is at the head of the list, this
* will assure that all opcodes are later assigned to software first and
* then udpated to HW modules as they are registered.
* then updated to HW modules as they are registered.
*/
if (strcmp(accel_module->name, "software") == 0) {
TAILQ_INSERT_HEAD(&spdk_accel_module_list, accel_module, tailq);
@ -1178,14 +1498,16 @@ spdk_accel_initialize(void)
return rc;
}
spdk_spin_init(&g_keyring_spin);
g_modules_started = true;
accel_module_initialize();
/* Create our priority global map of opcodes to modules, we populate starting
* with the software module (guaranteed to be first on the list) and then
* updating opcodes with HW modules that have been initilaized.
* updating opcodes with HW modules that have been initialized.
* NOTE: all opcodes must be supported by software in the event that no HW
* modules are initilaized to support the operation.
* modules are initialized to support the operation.
*/
TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) {
for (op = 0; op < ACCEL_OPC_LAST; op++) {
@ -1214,6 +1536,11 @@ spdk_accel_initialize(void)
}
}
if (g_modules_opc[ACCEL_OPC_ENCRYPT] != g_modules_opc[ACCEL_OPC_DECRYPT]) {
SPDK_ERRLOG("Different accel modules are assigned to encrypt and decrypt operations");
return -EINVAL;
}
#ifdef DEBUG
for (op = 0; op < ACCEL_OPC_LAST; op++) {
assert(g_modules_opc[op] != NULL);
@ -1264,6 +1591,59 @@ accel_write_overridden_opc(struct spdk_json_write_ctx *w, const char *opc_str,
spdk_json_write_object_end(w);
}
static void
__accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key)
{
spdk_json_write_named_string(w, "name", key->param.key_name);
spdk_json_write_named_string(w, "cipher", key->param.cipher);
spdk_json_write_named_string(w, "key", key->param.hex_key);
if (key->param.hex_key2) {
spdk_json_write_named_string(w, "key2", key->param.hex_key2);
}
}
void
_accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key)
{
spdk_json_write_object_begin(w);
__accel_crypto_key_dump_param(w, key);
spdk_json_write_object_end(w);
}
static void
_accel_crypto_key_write_config_json(struct spdk_json_write_ctx *w,
struct spdk_accel_crypto_key *key)
{
spdk_json_write_object_begin(w);
spdk_json_write_named_string(w, "method", "accel_crypto_key_create");
spdk_json_write_named_object_begin(w, "params");
__accel_crypto_key_dump_param(w, key);
spdk_json_write_object_end(w);
spdk_json_write_object_end(w);
}
static void
_accel_crypto_keys_write_config_json(struct spdk_json_write_ctx *w, bool full_dump)
{
struct spdk_accel_crypto_key *key;
spdk_spin_lock(&g_keyring_spin);
TAILQ_FOREACH(key, &g_keyring, link) {
if (full_dump) {
_accel_crypto_key_write_config_json(w, key);
} else {
_accel_crypto_key_dump_param(w, key);
}
}
spdk_spin_unlock(&g_keyring_spin);
}
void
_accel_crypto_keys_dump_param(struct spdk_json_write_ctx *w)
{
_accel_crypto_keys_write_config_json(w, false);
}
void
spdk_accel_write_config_json(struct spdk_json_write_ctx *w)
{
@ -1285,6 +1665,9 @@ spdk_accel_write_config_json(struct spdk_json_write_ctx *w)
accel_write_overridden_opc(w, g_opcode_strings[i], g_modules_opc_override[i]);
}
}
_accel_crypto_keys_write_config_json(w, true);
spdk_json_write_array_end(w);
}
@ -1298,6 +1681,7 @@ spdk_accel_module_finish(void)
}
if (!g_accel_module) {
spdk_spin_destroy(&g_keyring_spin);
accel_module_finish_cb();
return;
}
@ -1312,6 +1696,7 @@ spdk_accel_module_finish(void)
void
spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg)
{
struct spdk_accel_crypto_key *key, *key_tmp;
enum accel_opcode op;
assert(cb_fn != NULL);
@ -1319,6 +1704,12 @@ spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg)
g_fini_cb_fn = cb_fn;
g_fini_cb_arg = cb_arg;
spdk_spin_lock(&g_keyring_spin);
TAILQ_FOREACH_SAFE(key, &g_keyring, link, key_tmp) {
accel_crypto_key_destroy_unsafe(key);
}
spdk_spin_unlock(&g_keyring_spin);
for (op = 0; op < ACCEL_OPC_LAST; op++) {
if (g_modules_opc_override[op] != NULL) {
free(g_modules_opc_override[op]);

View File

@ -23,5 +23,8 @@ struct module_info {
typedef void (*_accel_for_each_module_fn)(struct module_info *info);
void _accel_for_each_module(struct module_info *info, _accel_for_each_module_fn fn);
int _accel_get_opc_name(enum accel_opcode opcode, const char **opcode_name);
void _accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key);
void _accel_crypto_keys_dump_param(struct spdk_json_write_ctx *w);
#endif

View File

@ -5,12 +5,14 @@
*/
#include "accel_internal.h"
#include "spdk_internal/accel_module.h"
#include "spdk/rpc.h"
#include "spdk/util.h"
#include "spdk/event.h"
#include "spdk/stdinc.h"
#include "spdk/env.h"
#include "spdk/util.h"
static void
rpc_accel_get_opc_assignments(struct spdk_jsonrpc_request *request,
@ -171,3 +173,102 @@ cleanup:
}
SPDK_RPC_REGISTER("accel_assign_opc", rpc_accel_assign_opc, SPDK_RPC_STARTUP)
struct rpc_accel_crypto_key_create {
struct spdk_accel_crypto_key_create_param param;
};
static const struct spdk_json_object_decoder rpc_accel_dek_create_decoders[] = {
{"cipher", offsetof(struct rpc_accel_crypto_key_create, param.cipher), spdk_json_decode_string},
{"key", offsetof(struct rpc_accel_crypto_key_create, param.hex_key), spdk_json_decode_string},
{"key2", offsetof(struct rpc_accel_crypto_key_create, param.hex_key2), spdk_json_decode_string, true},
{"name", offsetof(struct rpc_accel_crypto_key_create, param.key_name), spdk_json_decode_string},
};
static void
rpc_accel_crypto_key_create(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_accel_crypto_key_create req = {};
size_t key_size;
int rc;
if (spdk_json_decode_object(params, rpc_accel_dek_create_decoders,
SPDK_COUNTOF(rpc_accel_dek_create_decoders),
&req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
"spdk_json_decode_object failed");
goto cleanup;
}
rc = spdk_accel_crypto_key_create(&req.param);
if (rc) {
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"failed to create DEK, rc %d", rc);
} else {
spdk_jsonrpc_send_bool_response(request, true);
}
cleanup:
free(req.param.cipher);
if (req.param.hex_key) {
key_size = strnlen(req.param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
spdk_memset_s(req.param.hex_key, key_size, 0, key_size);
free(req.param.hex_key);
}
if (req.param.hex_key2) {
key_size = strnlen(req.param.hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
spdk_memset_s(req.param.hex_key2, key_size, 0, key_size);
free(req.param.hex_key2);
}
free(req.param.key_name);
}
SPDK_RPC_REGISTER("accel_crypto_key_create", rpc_accel_crypto_key_create, SPDK_RPC_RUNTIME)
struct rpc_accel_crypto_keys_get_ctx {
char *key_name;
};
static const struct spdk_json_object_decoder rpc_accel_crypto_keys_get_decoders[] = {
{"key_name", offsetof(struct rpc_accel_crypto_keys_get_ctx, key_name), spdk_json_decode_string, true},
};
static void
rpc_accel_crypto_keys_get(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params)
{
struct rpc_accel_crypto_keys_get_ctx req = {};
struct spdk_accel_crypto_key *key = NULL;
struct spdk_json_write_ctx *w;
if (params && spdk_json_decode_object(params, rpc_accel_crypto_keys_get_decoders,
SPDK_COUNTOF(rpc_accel_crypto_keys_get_decoders),
&req)) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
"spdk_json_decode_object failed");
free(req.key_name);
return;
}
if (req.key_name) {
key = spdk_accel_crypto_key_get(req.key_name);
free(req.key_name);
if (!key) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "key was not found\n");
return;
}
}
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_array_begin(w);
if (key) {
_accel_crypto_key_dump_param(w, key);
} else {
_accel_crypto_keys_dump_param(w);
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(request, w);
}
SPDK_RPC_REGISTER("accel_crypto_keys_get", rpc_accel_crypto_keys_get, SPDK_RPC_RUNTIME)

View File

@ -1,11 +1,13 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2022 Intel Corporation.
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES
* All rights reserved.
*/
#include "spdk/stdinc.h"
#include "spdk_internal/accel_module.h"
#include "accel_internal.h"
#include "spdk/env.h"
#include "spdk/likely.h"
@ -21,7 +23,16 @@
#ifdef SPDK_CONFIG_ISAL
#include "../isa-l/include/igzip_lib.h"
#ifdef SPDK_CONFIG_ISAL_CRYPTO
#include "../isa-l-crypto/include/aes_xts.h"
#endif
#endif
#define ACCEL_AES_XTS_128_KEY_SIZE 16
#define ACCEL_AES_XTS_256_KEY_SIZE 32
#define ACCEL_AES_XTS "AES_XTS"
/* Per the AES-XTS spec, the size of data unit cannot be bigger than 2^20 blocks, 128b each block */
#define ACCEL_AES_XTS_MAX_BLOCK_SIZE (1 << 24)
struct sw_accel_io_channel {
/* for ISAL */
@ -33,6 +44,19 @@ struct sw_accel_io_channel {
TAILQ_HEAD(, spdk_accel_task) tasks_to_complete;
};
typedef void (*sw_accel_crypto_op)(uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size,
const uint8_t *src, uint8_t *dst);
struct sw_accel_crypto_key_data {
sw_accel_crypto_op encrypt;
sw_accel_crypto_op decrypt;
};
static struct spdk_accel_module_if g_sw_module;
static void sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *_key);
static int sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key);
/* Post SW completions to a list and complete in a poller as we don't want to
* complete them on the caller's stack as they'll likely submit another. */
inline static void
@ -68,6 +92,8 @@ sw_accel_supports_opcode(enum accel_opcode opc)
case ACCEL_OPC_COPY_CRC32C:
case ACCEL_OPC_COMPRESS:
case ACCEL_OPC_DECOMPRESS:
case ACCEL_OPC_ENCRYPT:
case ACCEL_OPC_DECRYPT:
return true;
default:
return false;
@ -230,7 +256,7 @@ _sw_accel_compress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *ac
rc = isal_deflate(&sw_ch->stream);
if (rc) {
SPDK_ERRLOG("isal_deflate retunred error %d.\n", rc);
SPDK_ERRLOG("isal_deflate returned error %d.\n", rc);
}
if (remaining > 0) {
@ -290,7 +316,7 @@ _sw_accel_decompress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *
rc = isal_inflate(&sw_ch->state);
if (rc) {
SPDK_ERRLOG("isal_inflate retunred error %d.\n", rc);
SPDK_ERRLOG("isal_inflate returned error %d.\n", rc);
}
} while (sw_ch->state.block_state < ISAL_BLOCK_FINISH);
@ -303,6 +329,127 @@ _sw_accel_decompress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *
#endif
}
static int
_sw_accel_crypto_operation(struct spdk_accel_task *accel_task, struct spdk_accel_crypto_key *key,
sw_accel_crypto_op op)
{
#ifdef SPDK_CONFIG_ISAL_CRYPTO
uint64_t iv[2];
size_t remaining_len;
uint64_t src_offset = 0, dst_offset = 0;
uint32_t src_iovpos = 0, dst_iovpos = 0, src_iovcnt, dst_iovcnt;
uint32_t block_size, crypto_len, crypto_accum_len = 0;
struct iovec *src_iov, *dst_iov;
uint8_t *src, *dst;
/* iv is 128 bits, since we are using logical block address (64 bits) as iv, fill first 8 bytes with zeroes */
iv[0] = 0;
iv[1] = accel_task->iv;
src_iov = accel_task->s.iovs;
src_iovcnt = accel_task->s.iovcnt;
if (accel_task->d.iovcnt) {
dst_iov = accel_task->d.iovs;
dst_iovcnt = accel_task->d.iovcnt;
} else {
/* inplace operation */
dst_iov = accel_task->s.iovs;
dst_iovcnt = accel_task->s.iovcnt;
}
block_size = accel_task->block_size;
if (!src_iovcnt || !dst_iovcnt || !block_size || !op) {
SPDK_ERRLOG("src_iovcnt %d, dst_iovcnt %d, block_size %d, op %p\n", src_iovcnt, dst_iovcnt,
block_size, op);
return -EINVAL;
}
remaining_len = accel_task->nbytes;
while (remaining_len) {
crypto_len = spdk_min(block_size - crypto_accum_len, src_iov->iov_len - src_offset);
crypto_len = spdk_min(crypto_len, dst_iov->iov_len - dst_offset);
src = (uint8_t *)src_iov->iov_base + src_offset;
dst = (uint8_t *)dst_iov->iov_base + dst_offset;
op((uint8_t *)key->key2, (uint8_t *)key->key, (uint8_t *)iv, crypto_len, src, dst);
src_offset += crypto_len;
dst_offset += crypto_len;
crypto_accum_len += crypto_len;
remaining_len -= crypto_len;
if (crypto_accum_len == block_size) {
/* we can process part of logical block. Once the whole block is processed, increment iv */
crypto_accum_len = 0;
iv[1]++;
}
if (src_offset == src_iov->iov_len) {
src_iov++;
src_iovpos++;
src_offset = 0;
}
if (src_iovpos == src_iovcnt) {
break;
}
if (dst_offset == dst_iov->iov_len) {
dst_iov++;
dst_iovpos++;
dst_offset = 0;
}
if (dst_iovpos == dst_iovcnt) {
break;
}
}
if (remaining_len) {
SPDK_ERRLOG("remaining len %zu\n", remaining_len);
return -EINVAL;
}
return 0;
#else
return -ENOTSUP;
#endif
}
static int
_sw_accel_encrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
{
struct spdk_accel_crypto_key *key;
struct sw_accel_crypto_key_data *key_data;
key = accel_task->crypto_key;
if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) {
return -EINVAL;
}
if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) {
SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n",
ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size);
return -ERANGE;
}
key_data = key->priv;
return _sw_accel_crypto_operation(accel_task, key, key_data->encrypt);
}
static int
_sw_accel_decrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task)
{
struct spdk_accel_crypto_key *key;
struct sw_accel_crypto_key_data *key_data;
key = accel_task->crypto_key;
if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) {
return -EINVAL;
}
if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) {
SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n",
ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size);
return -ERANGE;
}
key_data = key->priv;
return _sw_accel_crypto_operation(accel_task, key, key_data->decrypt);
}
static int
sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task)
{
@ -359,6 +506,12 @@ sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_
case ACCEL_OPC_DECOMPRESS:
rc = _sw_accel_decompress(sw_ch, accel_task);
break;
case ACCEL_OPC_ENCRYPT:
rc = _sw_accel_encrypt(sw_ch, accel_task);
break;
case ACCEL_OPC_DECRYPT:
rc = _sw_accel_decrypt(sw_ch, accel_task);
break;
default:
assert(false);
break;
@ -380,14 +533,16 @@ static void sw_accel_module_fini(void *ctxt);
static size_t sw_accel_module_get_ctx_size(void);
static struct spdk_accel_module_if g_sw_module = {
.module_init = sw_accel_module_init,
.module_fini = sw_accel_module_fini,
.write_config_json = NULL,
.get_ctx_size = sw_accel_module_get_ctx_size,
.module_init = sw_accel_module_init,
.module_fini = sw_accel_module_fini,
.write_config_json = NULL,
.get_ctx_size = sw_accel_module_get_ctx_size,
.name = "software",
.supports_opcode = sw_accel_supports_opcode,
.get_io_channel = sw_accel_get_io_channel,
.submit_tasks = sw_accel_submit_tasks
.submit_tasks = sw_accel_submit_tasks,
.crypto_key_init = sw_accel_crypto_key_init,
.crypto_key_deinit = sw_accel_crypto_key_deinit,
};
static int
@ -477,4 +632,74 @@ sw_accel_module_fini(void *ctxt)
spdk_accel_module_finish();
}
static int
sw_accel_create_aes_xts(struct spdk_accel_crypto_key *key)
{
#ifdef SPDK_CONFIG_ISAL_CRYPTO
struct sw_accel_crypto_key_data *key_data;
if (!key->key || !key->key2) {
SPDK_ERRLOG("key or key2 are missing\n");
return -EINVAL;
}
if (!key->key_size || key->key_size != key->key2_size) {
SPDK_ERRLOG("key size %zu is not equal to key2 size %zu or is 0\n", key->key_size,
key->key2_size);
return -EINVAL;
}
key_data = calloc(1, sizeof(*key_data));
if (!key_data) {
return -ENOMEM;
}
switch (key->key_size) {
case ACCEL_AES_XTS_128_KEY_SIZE:
key_data->encrypt = XTS_AES_128_enc;
key_data->decrypt = XTS_AES_128_dec;
break;
case ACCEL_AES_XTS_256_KEY_SIZE:
key_data->encrypt = XTS_AES_256_enc;
key_data->decrypt = XTS_AES_256_dec;
break;
default:
SPDK_ERRLOG("Incorrect key size %zu, should be %d for AEX_XTS_128 or %d for AES_XTS_256\n",
key->key_size, ACCEL_AES_XTS_128_KEY_SIZE, ACCEL_AES_XTS_256_KEY_SIZE);
free(key_data);
return -EINVAL;
}
key->priv = key_data;
return 0;
#else
return -ENOTSUP;
#endif
}
static int
sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key)
{
if (!key || !key->param.cipher) {
return -EINVAL;
}
if (strcmp(key->param.cipher, ACCEL_AES_XTS) == 0) {
return sw_accel_create_aes_xts(key);
} else {
SPDK_ERRLOG("Only %s cipher is supported\n", ACCEL_AES_XTS);
return -EINVAL;
}
}
static void
sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *key)
{
if (!key || key->module_if != &g_sw_module || !key->priv) {
return;
}
free(key->priv);
}
SPDK_ACCEL_MODULE_REGISTER(sw, &g_sw_module)

View File

@ -15,6 +15,8 @@
spdk_accel_submit_copy_crc32cv;
spdk_accel_submit_compress;
spdk_accel_submit_decompress;
spdk_accel_submit_encrypt;
spdk_accel_submit_decrypt;
spdk_accel_get_opc_module_name;
spdk_accel_assign_opc;
spdk_accel_write_config_json;
@ -26,6 +28,9 @@
spdk_accel_sequence_reverse;
spdk_accel_get_buf;
spdk_accel_put_buf;
spdk_accel_crypto_key_create;
spdk_accel_crypto_key_destroy;
spdk_accel_crypto_key_get;
# functions needed by modules
spdk_accel_module_list_add;

View File

@ -31,3 +31,37 @@ def accel_assign_opc(client, opname, module):
}
return client.call('accel_assign_opc', params)
def accel_crypto_key_create(client, cipher, key, key2, name):
"""Create Data Encryption Key Identifier.
Args:
cipher: cipher
key: key
key2: key2
name: key name
"""
params = {
'cipher': cipher,
'key': key,
'name': name,
}
if key2 is not None:
params['key2'] = key2
return client.call('accel_crypto_key_create', params)
def accel_crypto_keys_get(client, key_name):
"""Get a list of the crypto keys.
Args:
key_name: Get information about a specific key
"""
params = {}
if key_name is not None:
params['key_name'] = key_name
return client.call('accel_crypto_keys_get', params)

View File

@ -2792,6 +2792,28 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
p.add_argument('-m', '--module', help='name of module')
p.set_defaults(func=accel_assign_opc)
def accel_crypto_key_create(args):
print_dict(rpc.accel.accel_crypto_key_create(args.client,
cipher=args.cipher,
key=args.key,
key2=args.key2,
name=args.name))
p = subparsers.add_parser('accel_crypto_key_create', help='Create encryption key')
p.add_argument('-c', '--cipher', help='cipher', required=True, type=str)
p.add_argument('-k', '--key', help='key', required=True, type=str)
p.add_argument('-e', '--key2', help='key2', required=False, type=str)
p.add_argument('-n', '--name', help='key name', required=True, type=str)
p.set_defaults(func=accel_crypto_key_create)
def accel_crypto_keys_get(args):
print_dict(rpc.accel.accel_crypto_keys_get(args.client,
key_name=args.key_name))
p = subparsers.add_parser('accel_crypto_keys_get', help='Get a list of the crypto keys')
p.add_argument('-k', '--key-name', help='Get information about a specific key', type=str)
p.set_defaults(func=accel_crypto_keys_get)
# ioat
def ioat_scan_accel_module(args):
rpc.ioat.ioat_scan_accel_module(args.client)

View File

@ -1,5 +1,6 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2020 Intel Corporation.
# Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES
# All rights reserved.
#
@ -13,22 +14,22 @@ SYS_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs --stat
# Shows how to compile both an external bdev and an external application against the SPDK combined shared object and dpdk shared objects.
bdev_shared_combo:
$(CC) $(COMMON_CFLAGS) -L../passthru -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c -lpassthru_external \
-lspdk $(DPDK_LIB) -Wl,--no-whole-archive
-lspdk $(DPDK_LIB) -Wl,--no-whole-archive $(SYS_LIB)
# Shows how to compile both an external bdev and an external application against the SPDK individual shared objects and dpdk shared objects.
bdev_shared_iso:
$(CC) $(COMMON_CFLAGS) -L../passthru -Wl,--no-as-needed -o hello_bdev ./hello_bdev.c \
-lpassthru_external $(SPDK_EVENT_LIB) \
$(DPDK_LIB)
$(DPDK_LIB) $(SYS_LIB)
# Shows how to compile an external application against the SPDK combined shared object and dpdk shared objects.
alone_shared_combo:
$(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c -lspdk $(DPDK_LIB)
$(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c -lspdk $(DPDK_LIB) $(SYS_LIB)
# Shows how to compile an external application against the SPDK individual shared objects and dpdk shared objects.
alone_shared_iso:
$(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c \
$(SPDK_EVENT_LIB) $(DPDK_LIB)
$(SPDK_EVENT_LIB) $(DPDK_LIB) $(SYS_LIB)
# Shows how to compile an external application against the SPDK archives.
alone_static:

View File

@ -24,6 +24,17 @@ DEFINE_STUB(spdk_memory_domain_create, int,
struct spdk_memory_domain_ctx *ctx, const char *id), 0);
DEFINE_STUB_V(spdk_memory_domain_destroy, (struct spdk_memory_domain *domain));
#ifdef SPDK_CONFIG_ISAL
DEFINE_STUB_V(XTS_AES_128_enc, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size,
const uint8_t *src, uint8_t *dst));
DEFINE_STUB_V(XTS_AES_128_dec, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size,
const uint8_t *src, uint8_t *dst));
DEFINE_STUB_V(XTS_AES_256_enc, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size,
const uint8_t *src, uint8_t *dst));
DEFINE_STUB_V(XTS_AES_256_dec, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size,
const uint8_t *src, uint8_t *dst));
#endif
/* global vars and setup/cleanup functions used for all test functions */
struct spdk_accel_module_if g_module = {};
struct spdk_io_channel *g_ch = NULL;