bdev/crypto: Use accel framework
All DPDK related code is removed, handling of RESET command was sligthly updated. Handling of -ENOMEM was updated for cases when accel API returns -ENOMEM Crypto tests in blockdev.sh were extended with more crypto_bdevs to verify NOMEM cases - that failed with original vbdev_crypto implementation Signed-off-by: Alexey Marchuk <alexeymar@nvidia.com> Change-Id: If1feba2449bee852c6c4daca4b3406414db6fded Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14860 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
c1e9ed6d4c
commit
13f97e6737
@ -23,6 +23,8 @@ Protection information is now supported by the malloc bdev module.
|
||||
|
||||
A new API `spkd_bdev_part_submit_request_ext` was added to specify a custom completion callback.
|
||||
|
||||
vbdev_crypto is updated to use accel framework instead of DPDK PMDs.
|
||||
|
||||
### scheduler
|
||||
|
||||
Changing scheduler from dynamic back to static is no longer possible,
|
||||
|
@ -335,6 +335,7 @@ if [ $SPDK_RUN_FUNCTIONAL_TEST -eq 1 ]; then
|
||||
|
||||
if [ $SPDK_TEST_CRYPTO -eq 1 ]; then
|
||||
run_test "blockdev_crypto_aesni" ./test/bdev/blockdev.sh "crypto_aesni"
|
||||
run_test "blockdev_crypto_sw" ./test/bdev/blockdev.sh "crypto_sw"
|
||||
# Proceed with the test only if QAT devices are in place
|
||||
if [[ $(lspci -d:37c8) ]]; then
|
||||
run_test "blockdev_crypto_qat" ./test/bdev/blockdev.sh "crypto_qat"
|
||||
|
76
doc/bdev.md
76
doc/bdev.md
@ -162,12 +162,23 @@ all volumes, if used it will return the name or an error that the device does no
|
||||
## Crypto Virtual Bdev Module {#bdev_config_crypto}
|
||||
|
||||
The crypto virtual bdev module can be configured to provide at rest data encryption
|
||||
for any underlying bdev. The module relies on the DPDK CryptoDev Framework to provide
|
||||
all cryptographic functionality. The framework provides support for many different software
|
||||
only cryptographic modules as well hardware assisted support for the Intel QAT board and
|
||||
NVIDIA crypto enabled NICs.
|
||||
The framework also provides support for cipher, hash, authentication and AEAD functions.
|
||||
At this time the SPDK virtual bdev module supports cipher only as follows:
|
||||
for any underlying bdev. The module relies on the SPDK Accel Framework to provide
|
||||
all cryptographic functionality.
|
||||
One of the accel modules, dpdk_cryptodev is implemented with the DPDK CryptoDev API,
|
||||
it provides support for many different software only cryptographic modules as well hardware
|
||||
assisted support for the Intel QAT board and NVIDIA crypto enabled NICs.
|
||||
|
||||
For reads, the buffer provided to the crypto block device will be used as the destination buffer
|
||||
for unencrypted data. For writes, however, a temporary scratch buffer is used as the
|
||||
destination buffer for encryption which is then passed on to the underlying bdev as the
|
||||
write buffer. This is done to avoid encrypting the data in the original source buffer which
|
||||
may cause problems in some use cases.
|
||||
|
||||
Below is information about accel modules which support crypto operations:
|
||||
|
||||
### dpdk_cryptodev accel module
|
||||
|
||||
Supports the following ciphers:
|
||||
|
||||
- AESN-NI Multi Buffer Crypto Poll Mode Driver: RTE_CRYPTO_CIPHER_AES128_CBC
|
||||
- Intel(R) QuickAssist (QAT) Crypto Poll Mode Driver: RTE_CRYPTO_CIPHER_AES128_CBC,
|
||||
@ -181,38 +192,61 @@ the crypto module break up all I/O into crypto operations of a size equal to the
|
||||
size of the underlying bdev. For example, a 4K I/O to a bdev with a 512B block size,
|
||||
would result in 8 cryptographic operations.
|
||||
|
||||
For reads, the buffer provided to the crypto module will be used as the destination buffer
|
||||
for unencrypted data. For writes, however, a temporary scratch buffer is used as the
|
||||
destination buffer for encryption which is then passed on to the underlying bdev as the
|
||||
write buffer. This is done to avoid encrypting the data in the original source buffer which
|
||||
may cause problems in some use cases.
|
||||
### SW accel module
|
||||
|
||||
Example command
|
||||
Supports the following ciphers:
|
||||
|
||||
`rpc.py bdev_crypto_create NVMe1n1 CryNvmeA crypto_aesni_mb 01234567891234560123456789123456`
|
||||
- AES_XTS cipher with 128 or 256 bit keys implemented with ISA-L_crypto
|
||||
|
||||
This command will create a crypto vbdev called 'CryNvmeA' on top of the NVMe bdev
|
||||
'NVMe1n1' and will use the DPDK software driver 'crypto_aesni_mb' and the key
|
||||
'01234567891234560123456789123456'.
|
||||
### General workflow
|
||||
|
||||
- Set desired accel module to perform crypto operations, that can be done with `accel_assign_opc` RPC command
|
||||
- Create a named crypto key using `accel_crypto_key_create` RPC command. The key will use the assigned accel
|
||||
module. Set of parameters and supported ciphers may be different in each accel module.
|
||||
- Create virtual crypto block device providing the base block device name and the crypto key name
|
||||
using `bdev_crypto_create` RPC command
|
||||
|
||||
#### Example
|
||||
|
||||
Example command which uses dpdk_cryptodev accel module
|
||||
```
|
||||
# start SPDK application with `--wait-for-rpc` parameter
|
||||
rpc.py dpdk_cryptodev_scan_accel_module
|
||||
rpc.py dpdk_cryptodev_set_driver crypto_aesni_mb
|
||||
rpc.py accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
rpc.py accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
rpc.py framework_start_init
|
||||
rpc.py accel_crypto_key_create -c AES_CBC -k 01234567891234560123456789123456 -n key_aesni_cbc_1
|
||||
rpc.py bdev_crypto_create NVMe1n1 CryNvmeA -n key_aesni_cbc_1
|
||||
```
|
||||
|
||||
These commands will create a crypto vbdev called 'CryNvmeA' on top of the NVMe bdev
|
||||
'NVMe1n1' and will use a key named `key_aesni_cbc_1`. The key will work with the accel module which
|
||||
has been assigned for encrypt operations, in this example it will be the dpdk_cryptodev.
|
||||
|
||||
### Crypto key format
|
||||
|
||||
Please make sure the keys are provided in hexlified format. This means string passed to
|
||||
rpc.py must be twice as long than the key length in binary form.
|
||||
|
||||
Example command
|
||||
#### Example command
|
||||
|
||||
`rpc.py bdev_crypto_create -c AES_XTS -k2 7859243a027411e581e0c40a35c8228f NVMe1n1 CryNvmeA mlx5_pci d16a2f3a9e9f5b32daefacd7f5984f4578add84425be4a0baa489b9de8884b09`
|
||||
`rpc.py accel_crypto_key_create -c AES_XTS -k2 7859243a027411e581e0c40a35c8228f -k d16a2f3a9e9f5b32daefacd7f5984f4578add84425be4a0baa489b9de8884b09 -n sample_key`
|
||||
|
||||
This command will create a crypto vbdev called 'CryNvmeA' on top of the NVMe bdev
|
||||
'NVMe1n1' and will use the DPDK software driver 'mlx5_pci', the AES key
|
||||
This command will create a key called `sample_key`, the AES key
|
||||
'd16a2f3a9e9f5b32daefacd7f5984f4578add84425be4a0baa489b9de8884b09' and the XTS key
|
||||
'7859243a027411e581e0c40a35c8228f'. In other words, the compound AES_XTS key to be used is
|
||||
'd16a2f3a9e9f5b32daefacd7f5984f4578add84425be4a0baa489b9de8884b097859243a027411e581e0c40a35c8228f'
|
||||
|
||||
### Delete the virtual crypto block device
|
||||
|
||||
To remove the vbdev use the bdev_crypto_delete command.
|
||||
|
||||
`rpc.py bdev_crypto_delete CryNvmeA`
|
||||
|
||||
The MLX5 driver works with crypto enabled Nvidia NICs and requires special configuration of
|
||||
### dpdk_cryptodev mlx5_pci driver configuration
|
||||
|
||||
The mlx5_pci driver works with crypto enabled Nvidia NICs and requires special configuration of
|
||||
DPDK environment to enable crypto function. It can be done via SPDK event library by configuring
|
||||
`env_context` member of `spdk_app_opts` structure or by passing corresponding CLI arguments in
|
||||
the following form: `--allow=BDF,class=crypto,wcs_file=/full/path/to/wrapped/credentials`, e.g.
|
||||
|
@ -443,6 +443,7 @@ Example response:
|
||||
"spdk_kill_instance",
|
||||
"accel_get_opc_assignments",
|
||||
"accel_crypto_key_create",
|
||||
"accel_crypto_key_destroy",
|
||||
"accel_crypto_keys_get",
|
||||
"ioat_scan_accel_module",
|
||||
"dsa_scan_accel_module",
|
||||
@ -1783,7 +1784,7 @@ Example response:
|
||||
|
||||
### accel_crypto_key_create {#rpc_accel_crypto_key_create}
|
||||
|
||||
Create a crypt key which will be used in accel framework
|
||||
Create a crypto key which will be used in accel framework
|
||||
|
||||
#### Parameters
|
||||
|
||||
@ -1822,6 +1823,41 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
### accel_crypto_key_destroy {#rpc_accel_crypto_key_destroy}
|
||||
|
||||
Destroy a crypto key. The user is responsible for ensuring that the deleted key is not used by acceleration modules.
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
-----------|----------| ----------- | -----------------
|
||||
name | Required | string | The key name
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "accel_crypto_key_destroy",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"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
|
||||
@ -2039,7 +2075,7 @@ Set the DPDK cryptodev driver
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- |----------|--------| -----------
|
||||
driver_name | Required | string | The driver, can be one of crypto_aesni_mb, crypto_qat or mlx5_pci
|
||||
crypto_pmd | Required | string | The driver, can be one of crypto_aesni_mb, crypto_qat or mlx5_pci
|
||||
|
||||
#### Example
|
||||
|
||||
@ -2051,7 +2087,7 @@ Example request:
|
||||
"method": "dpdk_cryptodev_set_driver",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"driver_name": "crypto_aesni_mb"
|
||||
"crypto_pmd": "crypto_aesni_mb"
|
||||
}
|
||||
}
|
||||
~~~
|
||||
@ -2693,13 +2729,15 @@ Create a new crypto bdev on a given base bdev.
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- | ----------- | -----------
|
||||
----------------------- |----------| ----------- | -----------
|
||||
base_bdev_name | Required | string | Name of the base bdev
|
||||
name | Required | string | Name of the crypto vbdev to create
|
||||
crypto_pmd | Required | string | Name of the crypto device driver
|
||||
key | Required | string | Key in hex form
|
||||
cipher | Required | string | Cipher to use, AES_CBC or AES_XTS (QAT and MLX5)
|
||||
key2 | Required | string | 2nd key in hex form only required for cipher AES_XTS
|
||||
crypto_pmd | Optional | string | Name of the crypto device driver. Obsolete, see accel_crypto_key_create
|
||||
key | Optional | string | Key in hex form. Obsolete, see accel_crypto_key_create
|
||||
cipher | Optional | string | Cipher to use, AES_CBC or AES_XTS (QAT and MLX5). Obsolete, see accel_crypto_key_create
|
||||
key2 | Optional | string | 2nd key in hex form only required for cipher AET_XTS. Obsolete, see accel_crypto_key_create
|
||||
key_name | Optional | string | Name of the key created with accel_crypto_key_create
|
||||
module | Optional | string | Name of the accel module which is used to create a key (if no key_name specified)
|
||||
|
||||
Both key and key2 must be passed in the hexlified form. For example, 256bit AES key may look like this:
|
||||
afd9477abf50254219ccb75965fbe39f23ebead5676e292582a0a67f66b88215
|
||||
|
@ -230,7 +230,7 @@ struct rpc_accel_crypto_keys_get_ctx {
|
||||
};
|
||||
|
||||
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},
|
||||
{"key_name", offsetof(struct rpc_accel_crypto_keys_get_ctx, key_name), spdk_json_decode_string},
|
||||
};
|
||||
|
||||
static void
|
||||
@ -272,3 +272,44 @@ rpc_accel_crypto_keys_get(struct spdk_jsonrpc_request *request,
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
}
|
||||
SPDK_RPC_REGISTER("accel_crypto_keys_get", rpc_accel_crypto_keys_get, SPDK_RPC_RUNTIME)
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_accel_crypto_key_destroy_decoders[] = {
|
||||
{"key_name", offsetof(struct rpc_accel_crypto_keys_get_ctx, key_name), spdk_json_decode_string, true},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_accel_crypto_key_destroy(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;
|
||||
int rc;
|
||||
|
||||
if (params && spdk_json_decode_object(params, rpc_accel_crypto_key_destroy_decoders,
|
||||
SPDK_COUNTOF(rpc_accel_crypto_key_destroy_decoders),
|
||||
&req)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
free(req.key_name);
|
||||
return;
|
||||
}
|
||||
|
||||
key = spdk_accel_crypto_key_get(req.key_name);
|
||||
if (!key) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"No key object found");
|
||||
free(req.key_name);
|
||||
return;
|
||||
|
||||
}
|
||||
rc = spdk_accel_crypto_key_destroy(key);
|
||||
if (rc) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Failed to destroy key, rc %d\n", rc);
|
||||
} else {
|
||||
spdk_jsonrpc_send_bool_response(request, true);
|
||||
}
|
||||
|
||||
free(req.key_name);
|
||||
}
|
||||
SPDK_RPC_REGISTER("accel_crypto_key_destroy", rpc_accel_crypto_key_destroy, SPDK_RPC_RUNTIME)
|
||||
|
@ -127,7 +127,7 @@ DEPDIRS-bdev_split := $(BDEV_DEPS)
|
||||
|
||||
DEPDIRS-bdev_aio := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_compress := $(BDEV_DEPS_THREAD) reduce
|
||||
DEPDIRS-bdev_crypto := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_crypto := $(BDEV_DEPS_THREAD) accel
|
||||
DEPDIRS-bdev_delay := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_iscsi := $(BDEV_DEPS_THREAD)
|
||||
DEPDIRS-bdev_malloc := $(BDEV_DEPS_THREAD) accel
|
||||
|
@ -601,6 +601,7 @@ accel_dpdk_cryptodev_mbuf_add_single_block(struct spdk_iov_sgl *sgl, struct rte_
|
||||
spdk_iov_sgl_advance(sgl, buf_len);
|
||||
|
||||
/* Handle the case of page boundary. */
|
||||
assert(task->base.block_size >= buf_len);
|
||||
remainder = task->base.block_size - buf_len;
|
||||
while (remainder) {
|
||||
buf_len = spdk_min(remainder, sgl->iov->iov_len - sgl->iov_offset);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,43 +12,19 @@
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/accel.h"
|
||||
#include "spdk_internal/accel_module.h"
|
||||
|
||||
#include "spdk/bdev.h"
|
||||
|
||||
#define AESNI_MB "crypto_aesni_mb"
|
||||
#define QAT "crypto_qat"
|
||||
#define QAT_ASYM "crypto_qat_asym"
|
||||
#define MLX5 "mlx5_pci"
|
||||
#define BDEV_CRYPTO_DEFAULT_CIPHER "AES_CBC" /* QAT and AESNI_MB */
|
||||
|
||||
/* Supported ciphers */
|
||||
#define AES_CBC "AES_CBC" /* QAT and AESNI_MB */
|
||||
#define AES_XTS "AES_XTS" /* QAT and MLX5 */
|
||||
|
||||
/* Specific to AES_CBC. */
|
||||
#define AES_CBC_KEY_LENGTH 16
|
||||
|
||||
#define AES_XTS_128_BLOCK_KEY_LENGTH 16 /* AES-XTS-128 block key size. */
|
||||
#define AES_XTS_256_BLOCK_KEY_LENGTH 32 /* AES-XTS-256 block key size. */
|
||||
#define AES_XTS_512_BLOCK_KEY_LENGTH 64 /* AES-XTS-512 block key size. */
|
||||
|
||||
#define AES_XTS_TWEAK_KEY_LENGTH 16 /* XTS part key size is always 128 bit. */
|
||||
|
||||
/* Structure to hold crypto options for crypto pmd setup. */
|
||||
/* Structure to hold crypto options */
|
||||
struct vbdev_crypto_opts {
|
||||
char *vbdev_name; /* name of the vbdev to create */
|
||||
char *bdev_name; /* base bdev name */
|
||||
|
||||
char *drv_name; /* name of the crypto device driver */
|
||||
char *cipher; /* AES_CBC or AES_XTS */
|
||||
|
||||
/* Note, for dev/test we allow use of key in the config file, for production
|
||||
* use, you must use an RPC to specify the key for security reasons.
|
||||
*/
|
||||
uint8_t *key; /* key per bdev */
|
||||
uint8_t key_size; /* key size */
|
||||
uint8_t *key2; /* key #2 for AES_XTS, per bdev */
|
||||
uint8_t key2_size; /* key #2 size */
|
||||
uint8_t *xts_key; /* key + key 2 */
|
||||
struct spdk_accel_crypto_key *key; /* crypto key */
|
||||
bool key_owner; /* If wet to true then the key was created by RPC and needs to be destroyed */
|
||||
};
|
||||
|
||||
typedef void (*spdk_delete_crypto_complete)(void *cb_arg, int bdeverrno);
|
||||
|
@ -9,14 +9,15 @@
|
||||
|
||||
#include "spdk/hexlify.h"
|
||||
|
||||
/* Reasonable bdev name length + cipher's name len */
|
||||
#define MAX_KEY_NAME_LEN 128
|
||||
|
||||
/* Structure to hold the parameters for this RPC method. */
|
||||
struct rpc_construct_crypto {
|
||||
char *base_bdev_name;
|
||||
char *name;
|
||||
char *crypto_pmd;
|
||||
char *key;
|
||||
char *cipher;
|
||||
char *key2;
|
||||
struct spdk_accel_crypto_key_create_param param;
|
||||
};
|
||||
|
||||
/* Free the allocated memory resource after the RPC handling. */
|
||||
@ -26,192 +27,54 @@ free_rpc_construct_crypto(struct rpc_construct_crypto *r)
|
||||
free(r->base_bdev_name);
|
||||
free(r->name);
|
||||
free(r->crypto_pmd);
|
||||
free(r->key);
|
||||
free(r->cipher);
|
||||
free(r->key2);
|
||||
free(r->param.cipher);
|
||||
if (r->param.hex_key) {
|
||||
memset(r->param.hex_key, 0, strnlen(r->param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH));
|
||||
free(r->param.hex_key);
|
||||
}
|
||||
if (r->param.hex_key2) {
|
||||
memset(r->param.hex_key2, 0, strnlen(r->param.hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH));
|
||||
free(r->param.hex_key2);
|
||||
}
|
||||
free(r->param.key_name);
|
||||
}
|
||||
|
||||
/* Structure to decode the input parameters for this RPC method. */
|
||||
static const struct spdk_json_object_decoder rpc_construct_crypto_decoders[] = {
|
||||
{"base_bdev_name", offsetof(struct rpc_construct_crypto, base_bdev_name), spdk_json_decode_string},
|
||||
{"name", offsetof(struct rpc_construct_crypto, name), spdk_json_decode_string},
|
||||
{"crypto_pmd", offsetof(struct rpc_construct_crypto, crypto_pmd), spdk_json_decode_string},
|
||||
{"key", offsetof(struct rpc_construct_crypto, key), spdk_json_decode_string},
|
||||
{"cipher", offsetof(struct rpc_construct_crypto, cipher), spdk_json_decode_string, true},
|
||||
{"key2", offsetof(struct rpc_construct_crypto, key2), spdk_json_decode_string, true},
|
||||
{"crypto_pmd", offsetof(struct rpc_construct_crypto, crypto_pmd), spdk_json_decode_string, true},
|
||||
{"key", offsetof(struct rpc_construct_crypto, param.hex_key), spdk_json_decode_string, true},
|
||||
{"cipher", offsetof(struct rpc_construct_crypto, param.cipher), spdk_json_decode_string, true},
|
||||
{"key2", offsetof(struct rpc_construct_crypto, param.hex_key2), spdk_json_decode_string, true},
|
||||
{"key_name", offsetof(struct rpc_construct_crypto, param.key_name), spdk_json_decode_string, true},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create crypto opts from rpc @req. Validate req fields and populate the
|
||||
* correspoending fields in @opts.
|
||||
*
|
||||
* \param rpc Pointer to the rpc req.
|
||||
* \param request Pointer to json request.
|
||||
* \return Allocated and populated crypto opts or NULL on failure.
|
||||
*/
|
||||
static struct vbdev_crypto_opts *
|
||||
create_crypto_opts(struct rpc_construct_crypto *rpc,
|
||||
struct spdk_jsonrpc_request *request)
|
||||
create_crypto_opts(struct rpc_construct_crypto *rpc, struct spdk_accel_crypto_key *key,
|
||||
bool key_owner)
|
||||
{
|
||||
struct vbdev_crypto_opts *opts;
|
||||
int key_size, key2_size;
|
||||
struct vbdev_crypto_opts *opts = calloc(1, sizeof(*opts));
|
||||
|
||||
if (strcmp(rpc->crypto_pmd, AESNI_MB) == 0 && strcmp(rpc->cipher, AES_XTS) == 0) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid cipher. AES_XTS is not available on AESNI_MB.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(rpc->crypto_pmd, MLX5) == 0 && strcmp(rpc->cipher, AES_XTS) != 0) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid cipher. %s is not available on MLX5.",
|
||||
rpc->cipher);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(rpc->cipher, AES_XTS) == 0 && rpc->key2 == NULL) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid key. A 2nd key is needed for AES_XTS.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strcmp(rpc->cipher, AES_CBC) == 0 && rpc->key2 != NULL) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid key. A 2nd key is needed only for AES_XTS.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opts = calloc(1, sizeof(struct vbdev_crypto_opts));
|
||||
if (!opts) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Failed to allocate memory for crypto_opts.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opts->bdev_name = strdup(rpc->base_bdev_name);
|
||||
if (!opts->bdev_name) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Failed to allocate memory for bdev_name.");
|
||||
goto error_alloc_bname;
|
||||
free_crypto_opts(opts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opts->vbdev_name = strdup(rpc->name);
|
||||
if (!opts->vbdev_name) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Failed to allocate memory for vbdev_name.");
|
||||
goto error_alloc_vname;
|
||||
free_crypto_opts(opts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
opts->drv_name = strdup(rpc->crypto_pmd);
|
||||
if (!opts->drv_name) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Failed to allocate memory for drv_name.");
|
||||
goto error_alloc_dname;
|
||||
}
|
||||
opts->key = key;
|
||||
opts->key_owner = key_owner;
|
||||
|
||||
if (strcmp(opts->drv_name, MLX5) == 0) {
|
||||
/* Only AES-XTS supported. */
|
||||
|
||||
/* We cannot use strlen() after spdk_unhexlify() because of possible \0 chars
|
||||
* used in the key. Hexlified version of key is twice as longer. */
|
||||
key_size = strnlen(rpc->key, (AES_XTS_512_BLOCK_KEY_LENGTH * 2) + 1);
|
||||
if (key_size != AES_XTS_256_BLOCK_KEY_LENGTH * 2 &&
|
||||
key_size != AES_XTS_512_BLOCK_KEY_LENGTH * 2) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid AES_XTS key string length for mlx5: %d. "
|
||||
"Supported sizes in hex form: %d or %d.",
|
||||
key_size, AES_XTS_256_BLOCK_KEY_LENGTH * 2,
|
||||
AES_XTS_512_BLOCK_KEY_LENGTH * 2);
|
||||
goto error_invalid_key;
|
||||
}
|
||||
} else {
|
||||
if (strncmp(rpc->cipher, AES_XTS, sizeof(AES_XTS)) == 0) {
|
||||
/* AES_XTS for qat uses 128bit key. */
|
||||
key_size = strnlen(rpc->key, (AES_XTS_128_BLOCK_KEY_LENGTH * 2) + 1);
|
||||
if (key_size != AES_XTS_128_BLOCK_KEY_LENGTH * 2) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid AES_XTS key string length: %d. "
|
||||
"Supported size in hex form: %d.",
|
||||
key_size, AES_XTS_128_BLOCK_KEY_LENGTH * 2);
|
||||
goto error_invalid_key;
|
||||
}
|
||||
} else {
|
||||
key_size = strnlen(rpc->key, (AES_CBC_KEY_LENGTH * 2) + 1);
|
||||
if (key_size != AES_CBC_KEY_LENGTH * 2) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid AES_CBC key string length: %d. "
|
||||
"Supported size in hex form: %d.",
|
||||
key_size, AES_CBC_KEY_LENGTH * 2);
|
||||
goto error_invalid_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
opts->key = spdk_unhexlify(rpc->key);
|
||||
if (!opts->key) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Failed to unhexlify key.");
|
||||
goto error_alloc_key;
|
||||
}
|
||||
opts->key_size = key_size / 2;
|
||||
|
||||
if (strncmp(rpc->cipher, AES_XTS, sizeof(AES_XTS)) == 0) {
|
||||
opts->cipher = AES_XTS;
|
||||
assert(rpc->key2);
|
||||
key2_size = strnlen(rpc->key2, (AES_XTS_TWEAK_KEY_LENGTH * 2) + 1);
|
||||
if (key2_size != AES_XTS_TWEAK_KEY_LENGTH * 2) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid AES_XTS key2 length %d. "
|
||||
"Supported size in hex form: %d.",
|
||||
key2_size, AES_XTS_TWEAK_KEY_LENGTH * 2);
|
||||
goto error_invalid_key2;
|
||||
}
|
||||
opts->key2 = spdk_unhexlify(rpc->key2);
|
||||
if (!opts->key2) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Failed to unhexlify key2.");
|
||||
goto error_alloc_key2;
|
||||
}
|
||||
opts->key2_size = key2_size / 2;
|
||||
|
||||
/* DPDK expects the keys to be concatenated together. */
|
||||
opts->xts_key = calloc(1, opts->key_size + opts->key2_size + 1);
|
||||
if (opts->xts_key == NULL) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Failed to allocate memory for XTS key.");
|
||||
goto error_alloc_xts;
|
||||
}
|
||||
memcpy(opts->xts_key, opts->key, opts->key_size);
|
||||
memcpy(opts->xts_key + opts->key_size, opts->key2, opts->key2_size);
|
||||
} else if (strncmp(rpc->cipher, AES_CBC, sizeof(AES_CBC)) == 0) {
|
||||
opts->cipher = AES_CBC;
|
||||
} else {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Invalid param. Cipher %s is not supported.",
|
||||
rpc->cipher);
|
||||
goto error_cipher;
|
||||
}
|
||||
return opts;
|
||||
|
||||
/* Error cleanup paths. */
|
||||
error_cipher:
|
||||
error_alloc_xts:
|
||||
error_alloc_key2:
|
||||
error_invalid_key2:
|
||||
if (opts->key) {
|
||||
memset(opts->key, 0, opts->key_size);
|
||||
free(opts->key);
|
||||
}
|
||||
opts->key_size = 0;
|
||||
error_alloc_key:
|
||||
error_invalid_key:
|
||||
free(opts->drv_name);
|
||||
error_alloc_dname:
|
||||
free(opts->vbdev_name);
|
||||
error_alloc_vname:
|
||||
free(opts->bdev_name);
|
||||
error_alloc_bname:
|
||||
free(opts);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Decode the parameters for this RPC method and properly construct the crypto
|
||||
@ -221,30 +84,92 @@ static void
|
||||
rpc_bdev_crypto_create(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct rpc_construct_crypto req = {NULL};
|
||||
struct vbdev_crypto_opts *crypto_opts;
|
||||
struct rpc_construct_crypto req = {};
|
||||
struct vbdev_crypto_opts *crypto_opts = NULL;
|
||||
struct spdk_json_write_ctx *w;
|
||||
int rc;
|
||||
struct spdk_accel_crypto_key *key = NULL;
|
||||
struct spdk_accel_crypto_key *created_key = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (spdk_json_decode_object(params, rpc_construct_crypto_decoders,
|
||||
SPDK_COUNTOF(rpc_construct_crypto_decoders),
|
||||
&req)) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
|
||||
"Failed to decode crypto disk create parameters.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (req.cipher == NULL) {
|
||||
req.cipher = strdup(AES_CBC);
|
||||
if (req.cipher == NULL) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Unable to allocate memory for req.cipher");
|
||||
goto cleanup;
|
||||
if (!req.name) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"crypto_bdev name is missing");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (req.param.key_name) {
|
||||
/* New config version */
|
||||
key = spdk_accel_crypto_key_get(req.param.key_name);
|
||||
if (key) {
|
||||
if (req.param.hex_key || req.param.cipher || req.crypto_pmd) {
|
||||
SPDK_NOTICELOG("Key name specified, other parameters are ignored\n");
|
||||
}
|
||||
SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
|
||||
}
|
||||
}
|
||||
|
||||
crypto_opts = create_crypto_opts(&req, request);
|
||||
if (crypto_opts == NULL) {
|
||||
/* No key_name. Support legacy configuration */
|
||||
if (!key) {
|
||||
if (req.param.key_name) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Key was not found");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (req.param.cipher == NULL) {
|
||||
req.param.cipher = strdup(BDEV_CRYPTO_DEFAULT_CIPHER);
|
||||
if (req.param.cipher == NULL) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Unable to allocate memory for req.cipher");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (req.crypto_pmd) {
|
||||
SPDK_WARNLOG("\"crypto_pmd\" parameters is obsolete and ignored\n");
|
||||
}
|
||||
|
||||
req.param.key_name = calloc(1, MAX_KEY_NAME_LEN);
|
||||
if (!req.param.key_name) {
|
||||
/* The new API requires key name. Create it as pmd_name + cipher */
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Unable to allocate memory for key_name");
|
||||
goto cleanup;
|
||||
}
|
||||
snprintf(req.param.key_name, MAX_KEY_NAME_LEN, "%s_%s", req.name, req.param.cipher);
|
||||
|
||||
/* Try to find a key with generated name, we may be loading from a json config where crypto_bdev had no key_name parameter */
|
||||
key = spdk_accel_crypto_key_get(req.param.key_name);
|
||||
if (key) {
|
||||
SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
|
||||
} else {
|
||||
rc = spdk_accel_crypto_key_create(&req.param);
|
||||
if (!rc) {
|
||||
key = spdk_accel_crypto_key_get(req.param.key_name);
|
||||
created_key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
/* We haven't found an existing key or were not able to create a new one */
|
||||
SPDK_ERRLOG("No key was found\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"No key was found");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
crypto_opts = create_crypto_opts(&req, key, created_key != NULL);
|
||||
if (!crypto_opts) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Memory allocation failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -258,7 +183,11 @@ rpc_bdev_crypto_create(struct spdk_jsonrpc_request *request,
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
spdk_json_write_string(w, req.name);
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
|
||||
cleanup:
|
||||
if (rc && created_key) {
|
||||
spdk_accel_crypto_key_destroy(created_key);
|
||||
}
|
||||
free_rpc_construct_crypto(&req);
|
||||
}
|
||||
SPDK_RPC_REGISTER("bdev_crypto_create", rpc_bdev_crypto_create, SPDK_RPC_RUNTIME)
|
||||
|
@ -54,6 +54,19 @@ def accel_crypto_key_create(client, cipher, key, key2, name):
|
||||
return client.call('accel_crypto_key_create', params)
|
||||
|
||||
|
||||
def accel_crypto_key_destroy(client, name):
|
||||
"""Destroy Data Encryption Key.
|
||||
|
||||
Args:
|
||||
name: key name
|
||||
"""
|
||||
params = {
|
||||
'name': name
|
||||
}
|
||||
|
||||
return client.call('accel_crypto_key_destroy', params)
|
||||
|
||||
|
||||
def accel_crypto_keys_get(client, key_name):
|
||||
"""Get a list of the crypto keys.
|
||||
|
||||
|
@ -104,23 +104,33 @@ def bdev_compress_get_orphans(client, name=None):
|
||||
return client.call('bdev_compress_get_orphans', params)
|
||||
|
||||
|
||||
def bdev_crypto_create(client, base_bdev_name, name, crypto_pmd, key, cipher=None, key2=None):
|
||||
def bdev_crypto_create(client, base_bdev_name, name, crypto_pmd=None, key=None, cipher=None, key2=None, key_name=None):
|
||||
"""Construct a crypto virtual block device.
|
||||
|
||||
Args:
|
||||
base_bdev_name: name of the underlying base bdev
|
||||
name: name for the crypto vbdev
|
||||
crypto_pmd: name of of the DPDK crypto driver to use
|
||||
crypto_pmd: name of the DPDK crypto driver to use
|
||||
key: key
|
||||
cipher: crypto algorithm to use
|
||||
key2: Optional second part of the key
|
||||
key_name: The key name to use in crypto operations
|
||||
|
||||
Returns:
|
||||
Name of created virtual block device.
|
||||
"""
|
||||
params = {'base_bdev_name': base_bdev_name, 'name': name, 'crypto_pmd': crypto_pmd, 'key': key}
|
||||
if cipher:
|
||||
params['cipher'] = cipher
|
||||
if key2:
|
||||
params = {'base_bdev_name': base_bdev_name, 'name': name}
|
||||
|
||||
if crypto_pmd is not None:
|
||||
params['crypto_pmd'] = crypto_pmd
|
||||
if key is not None:
|
||||
params['key'] = key
|
||||
if key2 is not None:
|
||||
params['key2'] = key2
|
||||
if cipher is not None:
|
||||
params['cipher'] = cipher
|
||||
if key_name is not None:
|
||||
params['key_name'] = key_name
|
||||
return client.call('bdev_crypto_create', params)
|
||||
|
||||
|
||||
|
@ -23,10 +23,8 @@ class CryptoEngineBdev(crypto.CryptoEngine):
|
||||
|
||||
def init(self, client, params):
|
||||
super().init(client, params)
|
||||
driver = params.get('driver')
|
||||
if driver is None:
|
||||
raise ValueError('Crypto driver must be configured for bdev_crypto')
|
||||
self._driver = driver
|
||||
# _driver can be None
|
||||
self._driver = params.get('driver')
|
||||
|
||||
def setup(self, volume_id, key, cipher, key2=None):
|
||||
try:
|
||||
@ -37,9 +35,10 @@ class CryptoEngineBdev(crypto.CryptoEngine):
|
||||
'Invalid volume crypto configuration: bad cipher')
|
||||
params = {'base_bdev_name': volume_id,
|
||||
'name': str(uuid.uuid4()),
|
||||
'crypto_pmd': self._driver,
|
||||
'key': key,
|
||||
'cipher': cipher}
|
||||
if self._driver is not None:
|
||||
params['crypto_pmd'] = self._driver
|
||||
if key2 is not None:
|
||||
params['key2'] = key2
|
||||
log.info('Creating crypto bdev: {} on volume: {}'.format(
|
||||
@ -72,19 +71,26 @@ class CryptoEngineBdev(crypto.CryptoEngine):
|
||||
if key is None:
|
||||
return
|
||||
params = crypto_bdev['driver_specific']['crypto']
|
||||
crypto_key = self._get_crypto_key(params['key_name'])
|
||||
if crypto_key is None:
|
||||
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'No key object found')
|
||||
cipher = self._ciphers.get(cipher)
|
||||
if cipher is None:
|
||||
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'Invalid volume crypto configuration: bad cipher')
|
||||
if params['cipher'].lower() != cipher.lower():
|
||||
if crypto_key['cipher'].lower() != cipher.lower():
|
||||
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'Invalid volume crypto configuration: bad cipher')
|
||||
if params['key'].lower() != key.lower():
|
||||
if crypto_key['key'].lower() != key.lower():
|
||||
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'Invalid volume crypto configuration: bad key')
|
||||
if key2 is not None and params.get('key2', '').lower() != key2.lower():
|
||||
if key2 is not None and crypto_key.get('key2', '').lower() != key2.lower():
|
||||
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'Invalid volume crypto configuration: bad key2')
|
||||
if crypto_key['name'].lower() != params['key_name'].lower():
|
||||
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||
'Invalid volume crypto configuration: key name does not match')
|
||||
|
||||
def _get_crypto_bdev(self, volume_id):
|
||||
try:
|
||||
@ -106,6 +112,16 @@ class CryptoEngineBdev(crypto.CryptoEngine):
|
||||
raise crypto.CryptoException(grpc.StatusCode.INTERNAL,
|
||||
f'Failed to get bdev_crypto for volume: {volume_id}')
|
||||
|
||||
def _get_crypto_key(self, key_name):
|
||||
try:
|
||||
with self._client() as client:
|
||||
_keys = client.call('accel_crypto_keys_get', {'key_name': key_name})
|
||||
if _keys is not None:
|
||||
return _keys[0]
|
||||
return None
|
||||
except JSONRPCException:
|
||||
pass
|
||||
|
||||
def get_crypto_bdev(self, volume_id):
|
||||
bdev = self._get_crypto_bdev(volume_id)
|
||||
if bdev is not None:
|
||||
|
@ -277,14 +277,16 @@ if __name__ == "__main__":
|
||||
crypto_pmd=args.crypto_pmd,
|
||||
key=args.key,
|
||||
cipher=args.cipher,
|
||||
key2=args.key2))
|
||||
key2=args.key2,
|
||||
key_name=args.key_name))
|
||||
p = subparsers.add_parser('bdev_crypto_create', help='Add a crypto vbdev')
|
||||
p.add_argument('base_bdev_name', help="Name of the base bdev")
|
||||
p.add_argument('name', help="Name of the crypto vbdev")
|
||||
p.add_argument('crypto_pmd', help="Name of the crypto device driver")
|
||||
p.add_argument('key', help="Key")
|
||||
p.add_argument('-c', '--cipher', help="cipher to use, AES_CBC or AES_XTS (QAT only)")
|
||||
p.add_argument('-k2', '--key2', help="2nd key for cipher AES_XTS", default=None)
|
||||
p.add_argument('-p', '--crypto-pmd', help="Name of the crypto device driver. Obsolete, see dpdk_cryptodev_set_driver", required=False)
|
||||
p.add_argument('-k', '--key', help="Key. Obsolete, see accel_crypto_key_create", required=False)
|
||||
p.add_argument('-c', '--cipher', help="cipher to use. Obsolete, see accel_crypto_key_create", required=False)
|
||||
p.add_argument('-k2', '--key2', help="2nd key for cipher AES_XTS. Obsolete, see accel_crypto_key_create", default=None)
|
||||
p.add_argument('-n', '--key-name', help="Key name to use, see accel_crypto_key_create", required=False)
|
||||
p.set_defaults(func=bdev_crypto_create)
|
||||
|
||||
def bdev_crypto_delete(args):
|
||||
@ -2835,6 +2837,14 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument('-n', '--name', help='key name', required=True, type=str)
|
||||
p.set_defaults(func=accel_crypto_key_create)
|
||||
|
||||
def accel_crypto_key_destroy(args):
|
||||
print_dict(rpc.accel.accel_crypto_key_destroy(args.client,
|
||||
name=args.name))
|
||||
|
||||
p = subparsers.add_parser('accel_crypto_key_destroy', help='Destroy encryption key')
|
||||
p.add_argument('-n', '--name', help='key name', required=True, type=str)
|
||||
p.set_defaults(func=accel_crypto_key_destroy)
|
||||
|
||||
def accel_crypto_keys_get(args):
|
||||
print_dict(rpc.accel.accel_crypto_keys_get(args.client,
|
||||
key_name=args.key_name))
|
||||
|
@ -48,7 +48,7 @@ function cleanup() {
|
||||
}
|
||||
|
||||
function start_spdk_tgt() {
|
||||
"$SPDK_BIN_DIR/spdk_tgt" "$env_ctx" &
|
||||
"$SPDK_BIN_DIR/spdk_tgt" "$env_ctx" "$wait_for_rpc" &
|
||||
spdk_tgt_pid=$!
|
||||
trap 'killprocess "$spdk_tgt_pid"; exit 1' SIGINT SIGTERM EXIT
|
||||
waitforlisten "$spdk_tgt_pid"
|
||||
@ -137,10 +137,23 @@ function setup_gpt_conf() {
|
||||
function setup_crypto_aesni_conf() {
|
||||
# Malloc0 and Malloc1 use AESNI
|
||||
"$rpc_py" <<- RPC
|
||||
bdev_malloc_create -b Malloc0 16 512
|
||||
bdev_malloc_create -b Malloc1 16 512
|
||||
bdev_crypto_create Malloc0 crypto_ram crypto_aesni_mb 01234567891234560123456789123456
|
||||
bdev_crypto_create Malloc1 crypto_ram2 crypto_aesni_mb 90123456789123459012345678912345
|
||||
dpdk_cryptodev_scan_accel_module
|
||||
dpdk_cryptodev_set_driver -d crypto_aesni_mb
|
||||
accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
framework_start_init
|
||||
accel_crypto_key_create -c AES_CBC -k 01234567891234560123456789123456 -n test_dek_aesni_cbc_1
|
||||
accel_crypto_key_create -c AES_CBC -k 12345678912345601234567891234560 -n test_dek_aesni_cbc_2
|
||||
accel_crypto_key_create -c AES_CBC -k 23456789123456012345678912345601 -n test_dek_aesni_cbc_3
|
||||
accel_crypto_key_create -c AES_CBC -k 34567891234560123456789123456012 -n test_dek_aesni_cbc_4
|
||||
bdev_malloc_create -b Malloc0 32 512
|
||||
bdev_malloc_create -b Malloc1 32 512
|
||||
bdev_malloc_create -b Malloc2 32 4096
|
||||
bdev_malloc_create -b Malloc3 32 4096
|
||||
bdev_crypto_create Malloc0 crypto_ram -n test_dek_aesni_cbc_1
|
||||
bdev_crypto_create Malloc1 crypto_ram2 -n test_dek_aesni_cbc_2
|
||||
bdev_crypto_create Malloc2 crypto_ram3 -n test_dek_aesni_cbc_3
|
||||
bdev_crypto_create Malloc3 crypto_ram4 -n test_dek_aesni_cbc_4
|
||||
RPC
|
||||
}
|
||||
|
||||
@ -148,10 +161,36 @@ function setup_crypto_qat_conf() {
|
||||
# Malloc0 will use QAT AES_CBC
|
||||
# Malloc1 will use QAT AES_XTS
|
||||
"$rpc_py" <<- RPC
|
||||
dpdk_cryptodev_scan_accel_module
|
||||
dpdk_cryptodev_set_driver -d crypto_qat
|
||||
accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
framework_start_init
|
||||
accel_crypto_key_create -c AES_CBC -k 01234567891234560123456789123456 -n test_dek_qat_cbc
|
||||
accel_crypto_key_create -c AES_XTS -k 00112233445566778899001122334455 -e 12345678912345601234567891234560 -n test_dek_qat_xts
|
||||
accel_crypto_key_create -c AES_CBC -k 23456789123456012345678912345601 -n test_dek_qat_cbc2
|
||||
accel_crypto_key_create -c AES_XTS -k 22334455667788990011223344550011 -e 34567891234560123456789123456012 -n test_dek_qat_xts2
|
||||
bdev_malloc_create -b Malloc0 32 512
|
||||
bdev_malloc_create -b Malloc1 32 512
|
||||
bdev_malloc_create -b Malloc2 32 4096
|
||||
bdev_malloc_create -b Malloc3 32 4096
|
||||
bdev_crypto_create Malloc0 crypto_ram -n test_dek_qat_cbc
|
||||
bdev_crypto_create Malloc1 crypto_ram1 -n test_dek_qat_xts
|
||||
bdev_crypto_create Malloc2 crypto_ram2 -n test_dek_qat_cbc2
|
||||
bdev_crypto_create Malloc3 crypto_ram3 -n test_dek_qat_xts2
|
||||
bdev_get_bdevs -b Malloc1
|
||||
RPC
|
||||
}
|
||||
|
||||
function setup_crypto_sw_conf() {
|
||||
"$rpc_py" <<- RPC
|
||||
framework_start_init
|
||||
bdev_malloc_create -b Malloc0 16 512
|
||||
bdev_malloc_create -b Malloc1 16 512
|
||||
bdev_crypto_create Malloc0 crypto_ram crypto_qat 01234567891234560123456789123456
|
||||
bdev_crypto_create -c AES_XTS -k2 01234567891234560123456789123456 Malloc1 crypto_ram3 crypto_qat 01234567891234560123456789123456
|
||||
bdev_malloc_create -b Malloc1 16 4096
|
||||
accel_crypto_key_create -c AES_XTS -k 00112233445566778899001122334455 -e 11223344556677889900112233445500 -n test_dek_sw
|
||||
accel_crypto_key_create -c AES_XTS -k 22334455667788990011223344550011 -e 33445566778899001122334455001122 -n test_dek_sw2
|
||||
bdev_crypto_create Malloc0 crypto_ram -n test_dek_sw
|
||||
bdev_crypto_create Malloc1 crypto_ram2 -n test_dek_sw2
|
||||
bdev_get_bdevs -b Malloc1
|
||||
RPC
|
||||
}
|
||||
@ -182,8 +221,13 @@ function setup_crypto_mlx5_conf() {
|
||||
|
||||
# Malloc0 will use MLX5 AES_XTS
|
||||
"$rpc_py" <<- RPC
|
||||
dpdk_cryptodev_scan_accel_module
|
||||
dpdk_cryptodev_set_driver -d mlx5_pci
|
||||
accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
framework_start_init
|
||||
bdev_malloc_create -b Malloc0 16 512
|
||||
bdev_crypto_create -c AES_XTS -k2 $tweak_key Malloc0 crypto_ram4 mlx5_pci $block_key
|
||||
bdev_crypto_create Malloc0 crypto_ram4 -k $block_key -c AES_XTS -k2 $tweak_key
|
||||
bdev_get_bdevs -b Malloc0
|
||||
RPC
|
||||
}
|
||||
@ -570,6 +614,7 @@ crypto_device=$2
|
||||
wcs_file=$3
|
||||
dek=$4
|
||||
env_ctx=""
|
||||
wait_for_rpc=""
|
||||
if [ -n "$crypto_device" ] && [ -n "$wcs_file" ]; then
|
||||
# We need full path here since fio perf test does 'pushd' to the test dir
|
||||
# and crypto login of fio plugin test can fail.
|
||||
@ -581,6 +626,9 @@ if [ -n "$crypto_device" ] && [ -n "$wcs_file" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ $test_type == crypto_* ]]; then
|
||||
wait_for_rpc="--wait-for-rpc"
|
||||
fi
|
||||
start_spdk_tgt
|
||||
case "$test_type" in
|
||||
bdev)
|
||||
@ -598,6 +646,9 @@ case "$test_type" in
|
||||
crypto_qat)
|
||||
setup_crypto_qat_conf
|
||||
;;
|
||||
crypto_sw)
|
||||
setup_crypto_sw_conf
|
||||
;;
|
||||
crypto_mlx5)
|
||||
setup_crypto_mlx5_conf $dek
|
||||
;;
|
||||
@ -627,6 +678,7 @@ esac
|
||||
# Generate json config and use it throughout all the tests
|
||||
cat <<- CONF > "$conf_file"
|
||||
{"subsystems":[
|
||||
$("$rpc_py" save_subsystem_config -n accel),
|
||||
$("$rpc_py" save_subsystem_config -n bdev)
|
||||
]}
|
||||
CONF
|
||||
|
@ -41,6 +41,10 @@ def filter_methods(do_remove_global_rpcs):
|
||||
'sock_impl_set_options',
|
||||
'sock_set_default_impl',
|
||||
'framework_set_scheduler',
|
||||
'accel_crypto_key_create',
|
||||
'accel_assign_opc',
|
||||
'dpdk_cryptodev_scan_accel_module',
|
||||
'dpdk_cryptodev_set_driver',
|
||||
]
|
||||
|
||||
data = json.loads(sys.stdin.read())
|
||||
|
@ -143,6 +143,18 @@ function json_config_test_shutdown_app() {
|
||||
echo "SPDK $app shutdown done"
|
||||
}
|
||||
|
||||
function create_accel_config() {
|
||||
timing_enter "${FUNCNAME[0]}"
|
||||
|
||||
if [[ $SPDK_TEST_CRYPTO -eq 1 ]]; then
|
||||
tgt_rpc dpdk_cryptodev_scan_accel_module
|
||||
tgt_rpc accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
tgt_rpc accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
fi
|
||||
|
||||
timing_exit "${FUNCNAME[0]}"
|
||||
}
|
||||
|
||||
function create_bdev_subsystem_config() {
|
||||
timing_enter "${FUNCNAME[0]}"
|
||||
|
||||
@ -206,7 +218,7 @@ function create_bdev_subsystem_config() {
|
||||
local crypto_driver=crypto_qat
|
||||
fi
|
||||
|
||||
tgt_rpc bdev_crypto_create MallocForCryptoBdev CryptoMallocBdev $crypto_driver 01234567891234560123456789123456
|
||||
tgt_rpc bdev_crypto_create MallocForCryptoBdev CryptoMallocBdev -p $crypto_driver -k 01234567891234560123456789123456
|
||||
expected_notifications+=(
|
||||
bdev_register:MallocForCryptoBdev
|
||||
bdev_register:CryptoMallocBdev
|
||||
@ -324,6 +336,8 @@ function json_config_test_init() {
|
||||
|
||||
#TODO: global subsystem params
|
||||
|
||||
create_accel_config
|
||||
|
||||
# Load nvme configuration. The load_config will issue framework_start_init automatically
|
||||
(
|
||||
$rootdir/scripts/gen_nvme.sh --json-with-subsystems
|
||||
|
@ -144,9 +144,18 @@ verify_crypto_volume() {
|
||||
|
||||
trap "cleanup; exit 1" SIGINT SIGTERM EXIT
|
||||
|
||||
"$rootdir/build/bin/spdk_tgt" -m 0x1 &
|
||||
"$rootdir/build/bin/spdk_tgt" -m 0x1 --wait-for-rpc &
|
||||
hostpid=$!
|
||||
|
||||
waitforlisten $hostpid
|
||||
|
||||
# Configure host with accel crypto parameters
|
||||
$rpc_py dpdk_cryptodev_scan_accel_module
|
||||
rpc_cmd dpdk_cryptodev_set_driver -d crypto_aesni_mb
|
||||
$rpc_py accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
$rpc_py accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
$rpc_py framework_start_init
|
||||
|
||||
"$rootdir/build/bin/spdk_tgt" -r "$tgtsock" -m 0x2 &
|
||||
tgtpid=$!
|
||||
|
||||
@ -158,8 +167,6 @@ $rootdir/scripts/sma.py -c <(
|
||||
- name: 'nvmf_tcp'
|
||||
crypto:
|
||||
name: 'bdev_crypto'
|
||||
params:
|
||||
driver: 'crypto_aesni_mb'
|
||||
CONFIG
|
||||
) &
|
||||
smapid=$!
|
||||
@ -202,7 +209,10 @@ attach_volume $device $uuid AES_CBC $key0
|
||||
verify_crypto_volume $localnqn $uuid
|
||||
# Check that it's using correct key
|
||||
crypto_bdev=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")')
|
||||
[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev") == "$key0" ]]
|
||||
key_name=$(jq -r '.driver_specific.crypto.key_name' <<< "$crypto_bdev")
|
||||
key_obj=$(rpc_cmd accel_crypto_keys_get -k $key_name)
|
||||
[[ $(jq -r '.[0].key' <<< "$key_obj") == "$key0" ]]
|
||||
[[ $(jq -r '.[0].cipher' <<< "$key_obj") == "AES_CBC" ]]
|
||||
|
||||
# Attach the same volume again
|
||||
attach_volume $device $uuid AES_CBC $key0
|
||||
@ -213,7 +223,10 @@ attach_volume $device $uuid AES_CBC $key0
|
||||
verify_crypto_volume $localnqn $uuid
|
||||
crypto_bdev2=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")')
|
||||
[[ $(jq -r '.name' <<< "$crypto_bdev") == $(jq -r '.name' <<< "$crypto_bdev2") ]]
|
||||
[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev2") == "$key0" ]]
|
||||
key_name=$(jq -r '.driver_specific.crypto.key_name' <<< "$crypto_bdev2")
|
||||
key_obj=$(rpc_cmd accel_crypto_keys_get -k $key_name)
|
||||
[[ $(jq -r '.[0].key' <<< "$key_obj") == "$key0" ]]
|
||||
[[ $(jq -r '.[0].cipher' <<< "$key_obj") == "AES_CBC" ]]
|
||||
|
||||
# Try to do attach it again, but this time use a different crypto algorithm
|
||||
NOT attach_volume $device $uuid AES_XTS $key0
|
||||
|
@ -125,10 +125,17 @@ vm_run $vm_no
|
||||
vm_wait_for_boot 300 $vm_no
|
||||
|
||||
# Start SPDK
|
||||
$rootdir/build/bin/spdk_tgt &
|
||||
$rootdir/build/bin/spdk_tgt --wait-for-rpc &
|
||||
tgtpid=$!
|
||||
waitforlisten $tgtpid
|
||||
|
||||
# Configure accel crypto module & operations
|
||||
rpc_cmd dpdk_cryptodev_scan_accel_module
|
||||
rpc_cmd dpdk_cryptodev_set_driver -d crypto_aesni_mb
|
||||
rpc_cmd accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
rpc_cmd accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
rpc_cmd framework_start_init
|
||||
|
||||
# Prepare the target
|
||||
rpc_cmd bdev_null_create null0 100 4096
|
||||
rpc_cmd bdev_null_create null1 100 4096
|
||||
@ -148,8 +155,6 @@ $rootdir/scripts/sma.py -c <(
|
||||
qmp_port: 10005
|
||||
crypto:
|
||||
name: 'bdev_crypto'
|
||||
params:
|
||||
driver: 'crypto_aesni_mb'
|
||||
EOF
|
||||
) &
|
||||
smapid=$!
|
||||
@ -304,7 +309,10 @@ ns_bdev=$(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[
|
||||
crypto_bdev=$(rpc_cmd bdev_get_bdevs -b "$ns_bdev" | jq -r '.[] | select(.product_name == "crypto")')
|
||||
[[ $(rpc_cmd bdev_get_bdevs | jq -r '[.[] | select(.product_name == "crypto")] | length') -eq 1 ]]
|
||||
|
||||
[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev") == "$key0" ]]
|
||||
key_name=$(jq -r '.driver_specific.crypto.key_name' <<< "$crypto_bdev")
|
||||
key_obj=$(rpc_cmd accel_crypto_keys_get -k $key_name)
|
||||
[[ $(jq -r '.[0].key' <<< "$key_obj") == "$key0" ]]
|
||||
[[ $(jq -r '.[0].cipher' <<< "$key_obj") == "AES_CBC" ]]
|
||||
|
||||
detach_volume "$device0" "$uuid0"
|
||||
delete_device "$device0"
|
||||
|
@ -58,9 +58,18 @@ vm_run $vm_no
|
||||
vm_wait_for_boot 300 $vm_no
|
||||
timing_exit setup_vm
|
||||
|
||||
$rootdir/build/bin/vhost -S /var/tmp -m 0x3 &
|
||||
$rootdir/build/bin/vhost -S /var/tmp -m 0x3 --wait-for-rpc &
|
||||
vhostpid=$!
|
||||
|
||||
waitforlisten $vhostpid
|
||||
|
||||
# Configure accel crypto module & operations
|
||||
rpc_cmd dpdk_cryptodev_scan_accel_module
|
||||
rpc_cmd dpdk_cryptodev_set_driver -d crypto_aesni_mb
|
||||
rpc_cmd accel_assign_opc -o encrypt -m dpdk_cryptodev
|
||||
rpc_cmd accel_assign_opc -o decrypt -m dpdk_cryptodev
|
||||
rpc_cmd framework_start_init
|
||||
|
||||
$rootdir/scripts/sma.py -c <(
|
||||
cat <<- EOF
|
||||
address: 127.0.0.1
|
||||
@ -77,8 +86,6 @@ $rootdir/scripts/sma.py -c <(
|
||||
qmp_port: 9090
|
||||
crypto:
|
||||
name: 'bdev_crypto'
|
||||
params:
|
||||
driver: 'crypto_aesni_mb'
|
||||
EOF
|
||||
) &
|
||||
smapid=$!
|
||||
@ -191,8 +198,11 @@ devid0=$(
|
||||
bdev=$(rpc_cmd vhost_get_controllers | jq -r '.[].backend_specific.block.bdev')
|
||||
|
||||
crypto_bdev=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")')
|
||||
[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev") == "$key0" ]]
|
||||
[[ $(jq -r '.driver_specific.crypto.name' <<< "$crypto_bdev") == "$bdev" ]]
|
||||
key_name=$(jq -r '.driver_specific.crypto.key_name' <<< "$crypto_bdev")
|
||||
key_obj=$(rpc_cmd accel_crypto_keys_get -k $key_name)
|
||||
[[ $(jq -r '.[0].key' <<< "$key_obj") == "$key0" ]]
|
||||
[[ $(jq -r '.[0].cipher' <<< "$key_obj") == "AES_CBC" ]]
|
||||
|
||||
# Delete crypto device and check if it's gone
|
||||
delete_device $devid0
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user