module/accel: Add mlx5 accel module
The mlx5 accel module supports crypto operations. Data buffer is split into `block_size` chunks and each chunk is enrypted individually. mlx5 library contains some utility functions that will later be used by other libraries, this lib will be exntended later. Signed-off-by: Alexey Marchuk <alexeymar@nvidia.com> Change-Id: Iacdd8caaade477277d5a95cfd53e9910e280a73b Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15420 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
13f97e6737
commit
a1dfa7ec92
@ -11,6 +11,9 @@ New functions `spdk_accel_submit_encrypt` and `spdk_accel_submit_decrypt` were a
|
||||
New accel module `dpdk_cryptodev` has been added. It uses DPDK crypto PMD and support encrypt and
|
||||
decrypt operations. New RPC `dpdk_cryptodev_scan_accel_module` has been added to enable this accel module.
|
||||
|
||||
New accel module `mlx5` was added. It implements crypto operations, enabled when SPDK is configured with
|
||||
RDMA provider is mlx5_dv and crypto support.
|
||||
|
||||
### bdev
|
||||
|
||||
Added RPCs bdev_nvme_start_mdns_discovery, bdev_nvme_get_mdns_discovery_info and
|
||||
|
16
configure
vendored
16
configure
vendored
@ -874,12 +874,16 @@ than or equal to 4.14 will see significantly reduced performance.
|
||||
fi
|
||||
|
||||
if [ "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]; then
|
||||
if ! echo -e '#include <spdk/stdinc.h>\n' \
|
||||
'#include <infiniband/mlx5dv.h>\n' \
|
||||
'#include <rdma/rdma_cma.h>\n' \
|
||||
'int main(void) { return rdma_establish(NULL) || ' \
|
||||
'!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE; }\n' \
|
||||
| "${BUILD_CMD[@]}" -lmlx5 -I${rootdir}/include -c - 2> /dev/null; then
|
||||
MLX5_DV_BUILD_BUILD_CMD="
|
||||
#include <infiniband/mlx5dv.h>\n
|
||||
#include <rdma/rdma_cma.h>\n
|
||||
int main(void) { return rdma_establish(NULL) ||\n
|
||||
!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE"
|
||||
if [ "${CONFIG[CRYPTO]}" = "y" ]; then
|
||||
MLX5_DV_BUILD_BUILD_CMD+="|| !!MLX5DV_CRYPTO_ENGINES_CAP_AES_XTS_SINGLE_BLOCK"
|
||||
fi
|
||||
MLX5_DV_BUILD_BUILD_CMD+=";}"
|
||||
if ! echo -e $MLX5_DV_BUILD_BUILD_CMD | "${BUILD_CMD[@]}" -lmlx5 -I${rootdir}/include -c -; then
|
||||
echo "mlx5_dv provider is not supported"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -450,6 +450,7 @@ Example response:
|
||||
"dpdk_cryptodev_scan_accel_module",
|
||||
"dpdk_cryptodev_set_driver",
|
||||
"dpdk_cryptodev_get_driver",
|
||||
"mlx5_scan_accel_module",
|
||||
"bdev_virtio_attach_controller",
|
||||
"bdev_virtio_scsi_get_devices",
|
||||
"bdev_virtio_detach_controller",
|
||||
@ -2132,6 +2133,43 @@ Example response:
|
||||
}
|
||||
~~~
|
||||
|
||||
### mlx5_scan_accel_module {#rpc_mlx5_scan_accel_module}
|
||||
|
||||
Enable mlx5 accel offload
|
||||
|
||||
#### Parameters
|
||||
|
||||
Name | Optional | Type | Description
|
||||
----------------------- | -------- |--------| -----------
|
||||
qp_size | Optional | number | qpair size
|
||||
num_requests | Optional | number | Size of the shared requests pool
|
||||
|
||||
#### Example
|
||||
|
||||
Example request:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "mlx5_scan_accel_module",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"qp_size": 256,
|
||||
"num_requests": 2047
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
Example response:
|
||||
|
||||
~~~json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": true
|
||||
}
|
||||
~~~
|
||||
|
||||
## Block Device Abstraction Layer {#jsonrpc_components_bdev}
|
||||
|
||||
### bdev_set_options {#rpc_bdev_set_options}
|
||||
|
69
include/spdk_internal/mlx5.h
Normal file
69
include/spdk_internal/mlx5.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef SPDK_MLX5_H
|
||||
#define SPDK_MLX5_H
|
||||
|
||||
#include <infiniband/mlx5dv.h>
|
||||
|
||||
struct spdk_mlx5_crypto_dek;
|
||||
struct spdk_mlx5_crypto_keytag;
|
||||
|
||||
struct spdk_mlx5_crypto_dek_create_attr {
|
||||
/* Data Encryption Key in binary form */
|
||||
char *dek;
|
||||
/* Length of the dek */
|
||||
size_t dek_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a NULL terminated array of devices which support crypto operation on Nvidia NICs
|
||||
*
|
||||
* \param dev_num The size of the array or 0
|
||||
* \return Array of contexts. This array must be released with \b spdk_mlx5_crypto_devs_release
|
||||
*/
|
||||
struct ibv_context **spdk_mlx5_crypto_devs_get(int *dev_num);
|
||||
|
||||
/**
|
||||
* Releases array of devices allocated by \b spdk_mlx5_crypto_devs_get
|
||||
*
|
||||
* \param rdma_devs Array of device to be released
|
||||
*/
|
||||
void spdk_mlx5_crypto_devs_release(struct ibv_context **rdma_devs);
|
||||
|
||||
/**
|
||||
* Create a keytag which contains DEKs per each crypto device in the system
|
||||
*
|
||||
* \param attr Crypto attributes
|
||||
* \param out Keytag
|
||||
* \return 0 on success, negated errno of failure
|
||||
*/
|
||||
int spdk_mlx5_crypto_keytag_create(struct spdk_mlx5_crypto_dek_create_attr *attr,
|
||||
struct spdk_mlx5_crypto_keytag **out);
|
||||
|
||||
/**
|
||||
* Destroy a keytag created using \b spdk_mlx5_crypto_keytag_create
|
||||
*
|
||||
* \param keytag Keytag pointer
|
||||
*/
|
||||
void spdk_mlx5_crypto_keytag_destroy(struct spdk_mlx5_crypto_keytag *keytag);
|
||||
|
||||
/**
|
||||
* Fills attributes used to register UMR with crypto operation
|
||||
*
|
||||
* \param attr_out Configured UMR attributes
|
||||
* \param keytag Keytag with DEKs
|
||||
* \param pd Protection Domain which is going to be used to register UMR. This function will find a DEK in \b keytag with the same PD
|
||||
* \param block_size Logical block size
|
||||
* \param iv Initialization vector or tweak. Usually that is logical block address
|
||||
* \param encrypt_on_tx If set, memory data will be encrypted during TX and wire data will be decrypted during RX. If not set, memory data will be decrypted during TX and wire data will be encrypted during RX.
|
||||
* \return 0 on success, negated errno on failure
|
||||
*/
|
||||
int spdk_mlx5_crypto_set_attr(struct mlx5dv_crypto_attr *attr_out,
|
||||
struct spdk_mlx5_crypto_keytag *keytag, struct ibv_pd *pd,
|
||||
uint32_t block_size, uint64_t iv, bool encrypt_on_tx);
|
||||
|
||||
|
||||
#endif /* SPDK_MLX5_H */
|
@ -22,6 +22,9 @@ DIRS-$(CONFIG_VBDEV_COMPRESS) += reduce
|
||||
DIRS-$(CONFIG_RDMA) += rdma
|
||||
DIRS-$(CONFIG_VFIO_USER) += vfu_tgt
|
||||
|
||||
ifeq ($(CONFIG_RDMA_PROV),mlx5_dv)
|
||||
DIRS-y += mlx5
|
||||
endif
|
||||
# If CONFIG_ENV is pointing at a directory in lib, build it.
|
||||
# Out-of-tree env implementations must be built separately by the user.
|
||||
ENV_NAME := $(notdir $(CONFIG_ENV))
|
||||
|
19
lib/mlx5/Makefile
Normal file
19
lib/mlx5/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES.
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
SO_VER := 1
|
||||
SO_MINOR := 0
|
||||
|
||||
C_SRCS = mlx5_crypto.c
|
||||
LIBNAME = mlx5
|
||||
|
||||
LOCAL_SYS_LIBS += -lmlx5 -libverbs -lrdmacm
|
||||
|
||||
SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_mlx5.map)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
345
lib/mlx5/mlx5_crypto.c
Normal file
345
lib/mlx5/mlx5_crypto.c
Normal file
@ -0,0 +1,345 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <rdma/rdma_cma.h>
|
||||
#include <infiniband/verbs.h>
|
||||
#include <infiniband/mlx5dv.h>
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk/queue.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/likely.h"
|
||||
#include "spdk/util.h"
|
||||
#include "spdk_internal/mlx5.h"
|
||||
#include "spdk_internal/rdma.h"
|
||||
|
||||
#define MLX5_VENDOR_ID_MELLANOX 0x2c9
|
||||
|
||||
/* Plaintext key sizes */
|
||||
/* 64b keytag */
|
||||
#define SPDK_MLX5_AES_XTS_KEYTAG_SIZE 8
|
||||
/* key1_128b + key2_128b */
|
||||
#define SPDK_MLX5_AES_XTS_128_DEK_BYTES 32
|
||||
/* key1_256b + key2_256b */
|
||||
#define SPDK_MLX5_AES_XTS_256_DEK_BYTES 64
|
||||
/* key1_128b + key2_128b + 64b_keytag */
|
||||
#define SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG (SPDK_MLX5_AES_XTS_128_DEK_BYTES + SPDK_MLX5_AES_XTS_KEYTAG_SIZE)
|
||||
/* key1_256b + key2_256b + 64b_keytag */
|
||||
#define SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG (SPDK_MLX5_AES_XTS_256_DEK_BYTES + SPDK_MLX5_AES_XTS_KEYTAG_SIZE)
|
||||
|
||||
struct spdk_mlx5_crypto_dek {
|
||||
struct mlx5dv_dek *dek_obj;
|
||||
struct ibv_pd *pd;
|
||||
struct ibv_context *context;
|
||||
};
|
||||
|
||||
struct spdk_mlx5_crypto_keytag {
|
||||
struct spdk_mlx5_crypto_dek *deks;
|
||||
uint32_t deks_num;
|
||||
bool has_keytag;
|
||||
char keytag[8];
|
||||
};
|
||||
|
||||
struct ibv_context **
|
||||
spdk_mlx5_crypto_devs_get(int *dev_num)
|
||||
{
|
||||
struct ibv_context **rdma_devs, **rdma_devs_out = NULL, *dev;
|
||||
struct ibv_device_attr dev_attr;
|
||||
struct mlx5dv_context dv_dev_attr;
|
||||
int num_rdma_devs = 0, i, rc;
|
||||
int num_crypto_devs = 0;
|
||||
|
||||
/* query all devices, save mlx5 with crypto support */
|
||||
rdma_devs = rdma_get_devices(&num_rdma_devs);
|
||||
if (!rdma_devs || !num_rdma_devs) {
|
||||
*dev_num = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rdma_devs_out = calloc(num_rdma_devs + 1, sizeof(*rdma_devs_out));
|
||||
if (!rdma_devs_out) {
|
||||
SPDK_ERRLOG("Memory allocation failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_rdma_devs; i++) {
|
||||
dev = rdma_devs[i];
|
||||
|
||||
rc = ibv_query_device(dev, &dev_attr);
|
||||
if (rc) {
|
||||
SPDK_ERRLOG("Failed to query dev %s, skipping\n", dev->device->name);
|
||||
continue;
|
||||
}
|
||||
if (dev_attr.vendor_id != MLX5_VENDOR_ID_MELLANOX) {
|
||||
SPDK_DEBUGLOG(mlx5, "dev %s is not Mellanox device, skipping\n", dev->device->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&dv_dev_attr, 0, sizeof(dv_dev_attr));
|
||||
dv_dev_attr.comp_mask |= MLX5DV_CONTEXT_MASK_CRYPTO_OFFLOAD;
|
||||
rc = mlx5dv_query_device(dev, &dv_dev_attr);
|
||||
if (rc) {
|
||||
SPDK_ERRLOG("Failed to query mlx5 dev %s, skipping\n", dev->device->name);
|
||||
continue;
|
||||
}
|
||||
if (!(dv_dev_attr.crypto_caps.flags & MLX5DV_CRYPTO_CAPS_CRYPTO)) {
|
||||
SPDK_DEBUGLOG(mlx5, "dev %s crypto engine doesn't support crypto, skipping\n", dev->device->name);
|
||||
continue;
|
||||
}
|
||||
if (!(dv_dev_attr.crypto_caps.crypto_engines & (MLX5DV_CRYPTO_ENGINES_CAP_AES_XTS |
|
||||
MLX5DV_CRYPTO_ENGINES_CAP_AES_XTS_SINGLE_BLOCK))) {
|
||||
SPDK_DEBUGLOG(mlx5, "dev %s crypto engine doesn't support AES_XTS, skipping\n", dev->device->name);
|
||||
continue;
|
||||
}
|
||||
if (dv_dev_attr.crypto_caps.wrapped_import_method &
|
||||
MLX5DV_CRYPTO_WRAPPED_IMPORT_METHOD_CAP_AES_XTS) {
|
||||
SPDK_WARNLOG("dev %s uses wrapped import method (0x%x) which is not supported by mlx5 accel module\n",
|
||||
dev->device->name, dv_dev_attr.crypto_caps.wrapped_import_method);
|
||||
continue;
|
||||
}
|
||||
|
||||
SPDK_NOTICELOG("Crypto dev %s\n", dev->device->name);
|
||||
rdma_devs_out[num_crypto_devs++] = dev;
|
||||
}
|
||||
|
||||
if (!num_crypto_devs) {
|
||||
SPDK_DEBUGLOG(mlx5, "Found no mlx5 crypto devices\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rdma_free_devices(rdma_devs);
|
||||
*dev_num = num_crypto_devs;
|
||||
|
||||
return rdma_devs_out;
|
||||
|
||||
err_out:
|
||||
free(rdma_devs_out);
|
||||
rdma_free_devices(rdma_devs);
|
||||
*dev_num = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_mlx5_crypto_devs_release(struct ibv_context **rdma_devs)
|
||||
{
|
||||
if (rdma_devs) {
|
||||
free(rdma_devs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_mlx5_crypto_keytag_destroy(struct spdk_mlx5_crypto_keytag *keytag)
|
||||
{
|
||||
struct spdk_mlx5_crypto_dek *dek;
|
||||
uint32_t i;
|
||||
|
||||
if (!keytag) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < keytag->deks_num; i++) {
|
||||
dek = &keytag->deks[i];
|
||||
if (dek->dek_obj) {
|
||||
mlx5dv_dek_destroy(dek->dek_obj);
|
||||
}
|
||||
if (dek->pd) {
|
||||
spdk_rdma_put_pd(dek->pd);
|
||||
}
|
||||
}
|
||||
spdk_memset_s(keytag->keytag, sizeof(keytag->keytag), 0, sizeof(keytag->keytag));
|
||||
free(keytag->deks);
|
||||
free(keytag);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_mlx5_crypto_keytag_create(struct spdk_mlx5_crypto_dek_create_attr *attr,
|
||||
struct spdk_mlx5_crypto_keytag **out)
|
||||
{
|
||||
struct spdk_mlx5_crypto_dek *dek;
|
||||
struct spdk_mlx5_crypto_keytag *keytag;
|
||||
struct ibv_context **devs;
|
||||
struct mlx5dv_dek_init_attr init_attr = {};
|
||||
struct mlx5dv_dek_attr query_attr;
|
||||
int num_devs = 0, i, rc;
|
||||
bool has_keytag;
|
||||
|
||||
|
||||
if (!attr || !attr->dek) {
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (attr->dek_len) {
|
||||
case SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG:
|
||||
init_attr.key_size = MLX5DV_CRYPTO_KEY_SIZE_128;
|
||||
has_keytag = true;
|
||||
SPDK_DEBUGLOG(mlx5, "128b AES_XTS with keytag\n");
|
||||
break;
|
||||
case SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG:
|
||||
init_attr.key_size = MLX5DV_CRYPTO_KEY_SIZE_256;
|
||||
has_keytag = true;
|
||||
SPDK_DEBUGLOG(mlx5, "256b AES_XTS with keytag\n");
|
||||
break;
|
||||
case SPDK_MLX5_AES_XTS_128_DEK_BYTES:
|
||||
init_attr.key_size = MLX5DV_CRYPTO_KEY_SIZE_128;
|
||||
has_keytag = false;
|
||||
SPDK_DEBUGLOG(mlx5, "128b AES_XTS\n");
|
||||
break;
|
||||
case SPDK_MLX5_AES_XTS_256_DEK_BYTES:
|
||||
init_attr.key_size = MLX5DV_CRYPTO_KEY_SIZE_256;
|
||||
has_keytag = false;
|
||||
SPDK_DEBUGLOG(mlx5, "256b AES_XTS\n");
|
||||
break;
|
||||
default:
|
||||
SPDK_ERRLOG("Invalid key length %zu. The following keys are supported:\n"
|
||||
"128b key + key2, %u bytes;\n"
|
||||
"256b key + key2, %u bytes\n"
|
||||
"128b key + key2 + keytag, %u bytes\n"
|
||||
"256b lye + key2 + keytag, %u bytes\n",
|
||||
attr->dek_len, SPDK_MLX5_AES_XTS_128_DEK_BYTES, MLX5DV_CRYPTO_KEY_SIZE_256,
|
||||
SPDK_MLX5_AES_XTS_128_DEK_BYTES_WITH_KEYTAG, SPDK_MLX5_AES_XTS_256_DEK_BYTES_WITH_KEYTAG);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
devs = spdk_mlx5_crypto_devs_get(&num_devs);
|
||||
if (!devs || !num_devs) {
|
||||
SPDK_DEBUGLOG(mlx5, "No crypto devices found\n");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
keytag = calloc(1, sizeof(*keytag));
|
||||
if (!keytag) {
|
||||
SPDK_ERRLOG("Memory allocation failed\n");
|
||||
spdk_mlx5_crypto_devs_release(devs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
keytag->deks = calloc(num_devs, sizeof(struct spdk_mlx5_crypto_dek));
|
||||
if (!keytag->deks) {
|
||||
SPDK_ERRLOG("Memory allocation failed\n");
|
||||
spdk_mlx5_crypto_devs_release(devs);
|
||||
free(keytag);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_devs; i++) {
|
||||
keytag->deks_num++;
|
||||
dek = &keytag->deks[i];
|
||||
dek->pd = spdk_rdma_get_pd(devs[i]);
|
||||
if (!dek->pd) {
|
||||
SPDK_ERRLOG("Failed to get PD on device %s\n", devs[i]->device->name);
|
||||
rc = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
dek->context = devs[i];
|
||||
|
||||
init_attr.pd = dek->pd;
|
||||
init_attr.has_keytag = has_keytag;
|
||||
init_attr.key_purpose = MLX5DV_CRYPTO_KEY_PURPOSE_AES_XTS;
|
||||
init_attr.comp_mask = MLX5DV_DEK_INIT_ATTR_CRYPTO_LOGIN;
|
||||
init_attr.crypto_login = NULL;
|
||||
memcpy(init_attr.key, attr->dek, attr->dek_len);
|
||||
|
||||
dek->dek_obj = mlx5dv_dek_create(dek->context, &init_attr);
|
||||
spdk_memset_s(init_attr.key, sizeof(init_attr.key), 0, sizeof(init_attr.key));
|
||||
if (!dek->dek_obj) {
|
||||
SPDK_ERRLOG("mlx5dv_dek_create failed on dev %s, errno %d\n", dek->context->device->name, errno);
|
||||
rc = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
memset(&query_attr, 0, sizeof(query_attr));
|
||||
rc = mlx5dv_dek_query(dek->dek_obj, &query_attr);
|
||||
if (rc) {
|
||||
SPDK_ERRLOG("Failed to query DEK on dev %s, rc %d\n", dek->context->device->name, rc);
|
||||
goto err_out;
|
||||
}
|
||||
if (query_attr.state != MLX5DV_DEK_STATE_READY) {
|
||||
SPDK_ERRLOG("DEK on dev %s state %d\n", dek->context->device->name, query_attr.state);
|
||||
rc = -EINVAL;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_keytag) {
|
||||
/* Save keytag, it will be used to configure crypto MKEY */
|
||||
keytag->has_keytag = true;
|
||||
memcpy(keytag->keytag, attr->dek + attr->dek_len - SPDK_MLX5_AES_XTS_KEYTAG_SIZE,
|
||||
SPDK_MLX5_AES_XTS_KEYTAG_SIZE);
|
||||
}
|
||||
|
||||
spdk_mlx5_crypto_devs_release(devs);
|
||||
*out = keytag;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
spdk_mlx5_crypto_keytag_destroy(keytag);
|
||||
spdk_mlx5_crypto_devs_release(devs);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline struct spdk_mlx5_crypto_dek *
|
||||
mlx5_crypto_get_dek_by_pd(struct spdk_mlx5_crypto_keytag *keytag, struct ibv_pd *pd)
|
||||
{
|
||||
struct spdk_mlx5_crypto_dek *dek;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < keytag->deks_num; i++) {
|
||||
dek = &keytag->deks[i];
|
||||
if (dek->pd == pd) {
|
||||
return dek;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_mlx5_crypto_set_attr(struct mlx5dv_crypto_attr *attr_out,
|
||||
struct spdk_mlx5_crypto_keytag *keytag, struct ibv_pd *pd,
|
||||
uint32_t block_size, uint64_t iv, bool encrypt_on_tx)
|
||||
{
|
||||
struct spdk_mlx5_crypto_dek *dek;
|
||||
enum mlx5dv_block_size bs;
|
||||
|
||||
dek = mlx5_crypto_get_dek_by_pd(keytag, pd);
|
||||
if (spdk_unlikely(!dek)) {
|
||||
SPDK_ERRLOG("No DEK for pd %p (dev %s)\n", pd, pd->context->device->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (block_size) {
|
||||
case 512:
|
||||
bs = MLX5DV_BLOCK_SIZE_512;
|
||||
break;
|
||||
case 520:
|
||||
bs = MLX5DV_BLOCK_SIZE_520;
|
||||
break;
|
||||
case 4048:
|
||||
bs = MLX5DV_BLOCK_SIZE_4048;
|
||||
break;
|
||||
case 4096:
|
||||
bs = MLX5DV_BLOCK_SIZE_4096;
|
||||
break;
|
||||
case 4160:
|
||||
bs = MLX5DV_BLOCK_SIZE_4160;
|
||||
break;
|
||||
default:
|
||||
SPDK_ERRLOG("Unsupported block size %u\n", block_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(attr_out, 0, sizeof(*attr_out));
|
||||
attr_out->dek = dek->dek_obj;
|
||||
attr_out->crypto_standard = MLX5DV_CRYPTO_STANDARD_AES_XTS;
|
||||
attr_out->data_unit_size = bs;
|
||||
attr_out->encrypt_on_tx = encrypt_on_tx;
|
||||
memcpy(attr_out->initial_tweak, &iv, sizeof(iv));
|
||||
if (keytag->has_keytag) {
|
||||
memcpy(attr_out->keytag, keytag->keytag, sizeof(keytag->keytag));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(mlx5)
|
11
lib/mlx5/spdk_mlx5.map
Normal file
11
lib/mlx5/spdk_mlx5.map
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
global:
|
||||
|
||||
spdk_mlx5_crypto_devs_get;
|
||||
spdk_mlx5_crypto_devs_release;
|
||||
spdk_mlx5_crypto_keytag_create;
|
||||
spdk_mlx5_crypto_keytag_destroy;
|
||||
spdk_mlx5_crypto_set_attr;
|
||||
|
||||
local: *;
|
||||
};
|
@ -70,6 +70,9 @@ DEPDIRS-nvmf := accel log sock util nvme thread $(JSON_LIBS) trace bdev
|
||||
ifeq ($(CONFIG_RDMA),y)
|
||||
DEPDIRS-nvmf += rdma
|
||||
endif
|
||||
ifeq ($(CONFIG_RDMA_PROV),mlx5_dv)
|
||||
DEPDIRS-mlx5 = log rdma util
|
||||
endif
|
||||
DEPDIRS-scsi := log util thread $(JSON_LIBS) trace bdev
|
||||
|
||||
DEPDIRS-iscsi := log sock util conf thread $(JSON_LIBS) trace scsi
|
||||
@ -100,6 +103,10 @@ DEPDIRS-accel_iaa := log idxd thread $(JSON_LIBS) accel trace
|
||||
DEPDIRS-accel_dpdk_cryptodev := log thread $(JSON_LIBS) accel
|
||||
DEPDIRS-accel_dpdk_compressdev := log thread $(JSON_LIBS) accel util
|
||||
|
||||
ifeq ($(CONFIG_RDMA_PROV),mlx5_dv)
|
||||
DEPDIRS-accel_mlx5 := accel thread log mlx5 rdma util
|
||||
endif
|
||||
|
||||
# module/env_dpdk
|
||||
DEPDIRS-env_dpdk_rpc := log $(JSON_LIBS)
|
||||
|
||||
|
@ -108,6 +108,10 @@ ifeq ($(CONFIG_DPDK_COMPRESSDEV),y)
|
||||
ACCEL_MODULES_LIST += accel_dpdk_compressdev
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RDMA_PROV)|$(CONFIG_CRYPTO),mlx5_dv|y)
|
||||
ACCEL_MODULES_LIST += accel_mlx5
|
||||
endif
|
||||
|
||||
SCHEDULER_MODULES_LIST = scheduler_dynamic
|
||||
ifeq (y,$(DPDK_POWER))
|
||||
SCHEDULER_MODULES_LIST += env_dpdk scheduler_dpdk_governor scheduler_gscheduler
|
||||
|
@ -12,6 +12,9 @@ DIRS-$(CONFIG_DPDK_COMPRESSDEV) += dpdk_compressdev
|
||||
DIRS-$(CONFIG_IDXD) += dsa
|
||||
DIRS-$(CONFIG_IDXD) += iaa
|
||||
DIRS-$(CONFIG_CRYPTO) += dpdk_cryptodev
|
||||
ifeq ($(CONFIG_RDMA_PROV)|$(CONFIG_CRYPTO),mlx5_dv|y)
|
||||
DIRS-y += mlx5
|
||||
endif
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
|
19
module/accel/mlx5/Makefile
Normal file
19
module/accel/mlx5/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
SO_VER := 1
|
||||
SO_MINOR := 0
|
||||
|
||||
LIBNAME = accel_mlx5
|
||||
C_SRCS = accel_mlx5.c accel_mlx5_rpc.c
|
||||
|
||||
SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map
|
||||
|
||||
LOCAL_SYS_LIBS += -libverbs -lmlx5
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
1182
module/accel/mlx5/accel_mlx5.c
Normal file
1182
module/accel/mlx5/accel_mlx5.c
Normal file
File diff suppressed because it is too large
Load Diff
15
module/accel/mlx5/accel_mlx5.h
Normal file
15
module/accel/mlx5/accel_mlx5.h
Normal file
@ -0,0 +1,15 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
|
||||
struct accel_mlx5_attr {
|
||||
/* The number of entries in qp submission/receive queue */
|
||||
uint16_t qp_size;
|
||||
/* The number of requests in the global pool */
|
||||
uint32_t num_requests;
|
||||
};
|
||||
|
||||
void accel_mlx5_get_default_attr(struct accel_mlx5_attr *attr);
|
||||
int accel_mlx5_enable(struct accel_mlx5_attr *attr);
|
43
module/accel/mlx5/accel_mlx5_rpc.c
Normal file
43
module/accel/mlx5/accel_mlx5_rpc.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "spdk/rpc.h"
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/log.h"
|
||||
|
||||
#include "accel_mlx5.h"
|
||||
|
||||
static const struct spdk_json_object_decoder rpc_mlx5_module_decoder[] = {
|
||||
{"qp_size", offsetof(struct accel_mlx5_attr, qp_size), spdk_json_decode_uint16, true},
|
||||
{"num_requests", offsetof(struct accel_mlx5_attr, num_requests), spdk_json_decode_uint32, true},
|
||||
};
|
||||
|
||||
static void
|
||||
rpc_mlx5_scan_accel_module(struct spdk_jsonrpc_request *request,
|
||||
const struct spdk_json_val *params)
|
||||
{
|
||||
struct accel_mlx5_attr attr;
|
||||
int rc;
|
||||
|
||||
accel_mlx5_get_default_attr(&attr);
|
||||
|
||||
if (params != NULL) {
|
||||
if (spdk_json_decode_object(params, rpc_mlx5_module_decoder,
|
||||
SPDK_COUNTOF(rpc_mlx5_module_decoder),
|
||||
&attr)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object() failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
|
||||
"spdk_json_decode_object failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rc = accel_mlx5_enable(&attr);
|
||||
if (rc) {
|
||||
spdk_jsonrpc_send_error_response_fmt(request, rc, "mlx5 scan failed with %d\n", rc);
|
||||
} else {
|
||||
spdk_jsonrpc_send_bool_response(request, true);
|
||||
}
|
||||
}
|
||||
SPDK_RPC_REGISTER("mlx5_scan_accel_module", rpc_mlx5_scan_accel_module, SPDK_RPC_STARTUP)
|
@ -33,6 +33,7 @@ from . import sock
|
||||
from . import vfio_user
|
||||
from . import iobuf
|
||||
from . import dpdk_cryptodev
|
||||
from . import mlx5
|
||||
from . import client as rpc_client
|
||||
|
||||
|
||||
|
21
python/spdk/rpc/mlx5.py
Normal file
21
python/spdk/rpc/mlx5.py
Normal file
@ -0,0 +1,21 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
|
||||
# All rights reserved.
|
||||
|
||||
from spdk.rpc.helpers import deprecated_alias
|
||||
|
||||
|
||||
def mlx5_scan_accel_module(client, qp_size=None, num_requests=None):
|
||||
"""Enable mlx5 accel module. Scans all mlx5 devices which can perform needed operations
|
||||
|
||||
Args:
|
||||
qp_size: Qpair size. (optional)
|
||||
num_requests: size of a global requests pool per mlx5 device (optional)
|
||||
"""
|
||||
params = {}
|
||||
|
||||
if qp_size is not None:
|
||||
params['qp_size'] = qp_size
|
||||
if num_requests is not None:
|
||||
params['num_requests'] = num_requests
|
||||
return client.call('mlx5_scan_accel_module', params)
|
@ -2908,6 +2908,17 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p = subparsers.add_parser('dpdk_cryptodev_get_driver', help='Get the DPDK cryptodev driver')
|
||||
p.set_defaults(func=dpdk_cryptodev_get_driver)
|
||||
|
||||
# mlx5
|
||||
def mlx5_scan_accel_module(args):
|
||||
rpc.mlx5.mlx5_scan_accel_module(args.client,
|
||||
qp_size=args.qp_size,
|
||||
num_requests=args.num_requests)
|
||||
|
||||
p = subparsers.add_parser('mlx5_scan_accel_module', help='Enable mlx5 accel module.')
|
||||
p.add_argument('-q', '--qp-size', type=int, help='QP size')
|
||||
p.add_argument('-r', '--num-requests', type=int, help='Size of the shared requests pool')
|
||||
p.set_defaults(func=mlx5_scan_accel_module)
|
||||
|
||||
# opal
|
||||
def bdev_nvme_opal_init(args):
|
||||
rpc.nvme.bdev_nvme_opal_init(args.client,
|
||||
|
@ -56,3 +56,8 @@ module/bdev/daos/bdev_daos_rpc
|
||||
# Not configured to test xNVMe bdev
|
||||
module/bdev/xnvme/bdev_xnvme
|
||||
module/bdev/xnvme/bdev_xnvme_rpc
|
||||
|
||||
# Not configured to test mlx5 accel module & crypto lib
|
||||
module/accel/mlx5/accel_mlx5
|
||||
module/accel/mlx5/accel_mlx5_rpc
|
||||
lib/mlx5/mlx5_crypto
|
||||
|
Loading…
Reference in New Issue
Block a user