crypto/mlx5: introduce Mellanox crypto driver

Add a new PMD for Mellanox devices- crypto PMD.

The crypto PMD will be supported starting Nvidia ConnectX6 and
BlueField2.

The crypto PMD will add the support of encryption and decryption using
the AES-XTS symmetric algorithm.

The crypto PMD requires rdma-core and uses mlx5 DevX.

This patch adds the PCI probing, basic functions, build files and
log utility.

Signed-off-by: Shiri Kuzin <shirik@nvidia.com>
Acked-by: Matan Azrad <matan@nvidia.com>
Acked-by: Akhil Goyal <gakhil@marvell.com>
This commit is contained in:
Shiri Kuzin 2021-07-20 16:09:30 +03:00 committed by Akhil Goyal
parent 6425d95ad1
commit a7c86884f1
13 changed files with 463 additions and 10 deletions

View File

@ -1102,6 +1102,12 @@ F: drivers/crypto/octeontx2/
F: doc/guides/cryptodevs/octeontx2.rst F: doc/guides/cryptodevs/octeontx2.rst
F: doc/guides/cryptodevs/features/octeontx2.ini F: doc/guides/cryptodevs/features/octeontx2.ini
Mellanox mlx5
M: Matan Azrad <matan@nvidia.com>
F: drivers/crypto/mlx5/
F: doc/guides/cryptodevs/mlx5.rst
F: doc/guides/cryptodevs/features/mlx5.ini
Null Crypto Null Crypto
M: Declan Doherty <declan.doherty@intel.com> M: Declan Doherty <declan.doherty@intel.com>
F: drivers/crypto/null/ F: drivers/crypto/null/

View File

@ -0,0 +1,27 @@
;
; Features of a mlx5 crypto driver.
;
; Refer to default.ini for the full list of available PMD features.
;
[Features]
HW Accelerated = Y
;
; Supported crypto algorithms of a mlx5 crypto driver.
;
[Cipher]
;
; Supported authentication algorithms of a mlx5 crypto driver.
;
[Auth]
;
; Supported AEAD algorithms of a mlx5 crypto driver.
;
[AEAD]
;
; Supported Asymmetric algorithms of a mlx5 crypto driver.
;
[Asymmetric]

View File

@ -23,6 +23,7 @@ Crypto Device Drivers
octeontx octeontx
octeontx2 octeontx2
openssl openssl
mlx5
mvsam mvsam
nitrox nitrox
null null

View File

@ -0,0 +1,65 @@
.. SPDX-License-Identifier: BSD-3-Clause
Copyright (c) 2021 NVIDIA Corporation & Affiliates
.. include:: <isonum.txt>
MLX5 Crypto Driver
==================
The MLX5 crypto driver library
(**librte_crypto_mlx5**) provides support for **Mellanox ConnectX-6**
family adapters.
Overview
--------
The device can provide disk encryption services,
allowing data encryption and decryption towards a disk.
Having all encryption/decryption operations done in a single device
can reduce cost and overheads of the related FIPS certification,
as ConnectX-6 is FIPS 140-2 level-2 ready.
The encryption cipher is AES-XTS of 256/512 bit key size.
MKEY is a memory region object in the hardware,
that holds address translation information and attributes per memory area.
Its ID must be tied to addresses provided to the hardware.
The encryption operations are performed with MKEY read/write transactions,
when the MKEY is configured to perform crypto operations.
The encryption does not require text to be aligned to the AES block size (128b).
The PMD uses ``libibverbs`` and ``libmlx5`` to access the device firmware
or to access the hardware components directly.
There are different levels of objects and bypassing abilities.
To get the best performances:
- Verbs is a complete high-level generic API.
- Direct Verbs is a device-specific API.
- DevX allows to access firmware objects.
Enabling ``librte_crypto_mlx5`` causes DPDK applications
to be linked against libibverbs.
Driver options
--------------
- ``class`` parameter [string]
Select the class of the driver that should probe the device.
`crypto` for the mlx5 crypto driver.
Supported NICs
--------------
* Mellanox\ |reg| ConnectX\ |reg|-6 200G MCX654106A-HCAT (2x200G)
Prerequisites
-------------
- Mellanox OFED version: **5.3**
see :doc:`../../nics/mlx5` guide for more Mellanox OFED details.
- Compilation can be done also with rdma-core v15+.
see :doc:`../../nics/mlx5` guide for more rdma-core details.

View File

@ -216,6 +216,7 @@ enum mlx5_class {
MLX5_CLASS_VDPA = RTE_BIT64(1), MLX5_CLASS_VDPA = RTE_BIT64(1),
MLX5_CLASS_REGEX = RTE_BIT64(2), MLX5_CLASS_REGEX = RTE_BIT64(2),
MLX5_CLASS_COMPRESS = RTE_BIT64(3), MLX5_CLASS_COMPRESS = RTE_BIT64(3),
MLX5_CLASS_CRYPTO = RTE_BIT64(4),
}; };
#define MLX5_DBR_SIZE RTE_CACHE_LINE_SIZE #define MLX5_DBR_SIZE RTE_CACHE_LINE_SIZE

View File

@ -31,6 +31,7 @@ static const struct {
{ .name = "net", .driver_class = MLX5_CLASS_NET }, { .name = "net", .driver_class = MLX5_CLASS_NET },
{ .name = "regex", .driver_class = MLX5_CLASS_REGEX }, { .name = "regex", .driver_class = MLX5_CLASS_REGEX },
{ .name = "compress", .driver_class = MLX5_CLASS_COMPRESS }, { .name = "compress", .driver_class = MLX5_CLASS_COMPRESS },
{ .name = "crypto", .driver_class = MLX5_CLASS_CRYPTO },
}; };
static const unsigned int mlx5_class_combinations[] = { static const unsigned int mlx5_class_combinations[] = {
@ -38,13 +39,26 @@ static const unsigned int mlx5_class_combinations[] = {
MLX5_CLASS_VDPA, MLX5_CLASS_VDPA,
MLX5_CLASS_REGEX, MLX5_CLASS_REGEX,
MLX5_CLASS_COMPRESS, MLX5_CLASS_COMPRESS,
MLX5_CLASS_CRYPTO,
MLX5_CLASS_NET | MLX5_CLASS_REGEX, MLX5_CLASS_NET | MLX5_CLASS_REGEX,
MLX5_CLASS_VDPA | MLX5_CLASS_REGEX, MLX5_CLASS_VDPA | MLX5_CLASS_REGEX,
MLX5_CLASS_NET | MLX5_CLASS_COMPRESS, MLX5_CLASS_NET | MLX5_CLASS_COMPRESS,
MLX5_CLASS_VDPA | MLX5_CLASS_COMPRESS, MLX5_CLASS_VDPA | MLX5_CLASS_COMPRESS,
MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS, MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS,
MLX5_CLASS_NET | MLX5_CLASS_CRYPTO,
MLX5_CLASS_VDPA | MLX5_CLASS_CRYPTO,
MLX5_CLASS_REGEX | MLX5_CLASS_CRYPTO,
MLX5_CLASS_COMPRESS | MLX5_CLASS_CRYPTO,
MLX5_CLASS_NET | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS, MLX5_CLASS_NET | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS,
MLX5_CLASS_VDPA | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS, MLX5_CLASS_VDPA | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS,
MLX5_CLASS_NET | MLX5_CLASS_REGEX | MLX5_CLASS_CRYPTO,
MLX5_CLASS_VDPA | MLX5_CLASS_REGEX | MLX5_CLASS_CRYPTO,
MLX5_CLASS_NET | MLX5_CLASS_COMPRESS | MLX5_CLASS_CRYPTO,
MLX5_CLASS_VDPA | MLX5_CLASS_COMPRESS | MLX5_CLASS_CRYPTO,
MLX5_CLASS_NET | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS |
MLX5_CLASS_CRYPTO,
MLX5_CLASS_VDPA | MLX5_CLASS_REGEX | MLX5_CLASS_COMPRESS |
MLX5_CLASS_CRYPTO,
/* New class combination should be added here. */ /* New class combination should be added here. */
}; };

View File

@ -9,17 +9,18 @@
* @file * @file
* *
* RTE Mellanox PCI Driver Interface * RTE Mellanox PCI Driver Interface
* Mellanox ConnectX PCI device supports multiple class: net,vdpa,regex and * Mellanox ConnectX PCI device supports multiple class: net,vdpa,regex,compress
* compress devices. This layer enables creating such multiple class of devices * and crypto devices. This layer enables creating such multiple class of
* on a single PCI device by allowing to bind multiple class specific device * devices on a single PCI device by allowing to bind multiple class specific
* driver to attach to mlx5_pci driver. * device driver to attach to mlx5_pci driver.
* *
* ----------- ------------ ------------- ---------------- * -------- -------- --------- ------------ ----------
* | mlx5 | | mlx5 | | mlx5 | | mlx5 | * | mlx5 | | mlx5 | | mlx5 | | mlx5 | | mlx5 |
* | net pmd | | vdpa pmd | | regex pmd | | compress pmd | * | net | | vdpa | | regex | | compress | | crypto |
* ----------- ------------ ------------- ---------------- * | pmd | | pmd | | pmd | | pmd | | pmd |
* \ \ / / * -------- -------- --------- ------------ ----------
* \ \ / / * \ \ | / /
* \ \ | / /
* \ \_--------------_/ / * \ \_--------------_/ /
* \_______________| mlx5 |_______________/ * \_______________| mlx5 |_______________/
* | pci common | * | pci common |

View File

@ -16,6 +16,7 @@ drivers = [
'dpaa_sec', 'dpaa_sec',
'dpaa2_sec', 'dpaa2_sec',
'kasumi', 'kasumi',
'mlx5',
'mvsam', 'mvsam',
'nitrox', 'nitrox',
'null', 'null',

View File

@ -0,0 +1,27 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2021 NVIDIA Corporation & Affiliates
if not is_linux
build = false
reason = 'only supported on Linux'
subdir_done()
endif
fmt_name = 'mlx5_crypto'
deps += ['common_mlx5', 'eal', 'cryptodev']
sources = files(
'mlx5_crypto.c',
)
cflags_options = [
'-std=c11',
'-Wno-strict-prototypes',
'-D_BSD_SOURCE',
'-D_DEFAULT_SOURCE',
'-D_XOPEN_SOURCE=600',
]
foreach option:cflags_options
if cc.has_argument(option)
cflags += option
endif
endforeach

View File

@ -0,0 +1,263 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#include <rte_malloc.h>
#include <rte_errno.h>
#include <rte_log.h>
#include <rte_pci.h>
#include <mlx5_glue.h>
#include <mlx5_common.h>
#include <mlx5_common_pci.h>
#include <mlx5_devx_cmds.h>
#include <mlx5_common_os.h>
#include "mlx5_crypto_utils.h"
#include "mlx5_crypto.h"
#define MLX5_CRYPTO_DRIVER_NAME crypto_mlx5
#define MLX5_CRYPTO_LOG_NAME pmd.crypto.mlx5
#define MLX5_CRYPTO_FEATURE_FLAGS \
RTE_CRYPTODEV_FF_HW_ACCELERATED
TAILQ_HEAD(mlx5_crypto_privs, mlx5_crypto_priv) mlx5_crypto_priv_list =
TAILQ_HEAD_INITIALIZER(mlx5_crypto_priv_list);
static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
int mlx5_crypto_logtype;
uint8_t mlx5_crypto_driver_id;
static const char mlx5_crypto_drv_name[] = RTE_STR(MLX5_CRYPTO_DRIVER_NAME);
static const struct rte_driver mlx5_drv = {
.name = mlx5_crypto_drv_name,
.alias = mlx5_crypto_drv_name
};
static struct cryptodev_driver mlx5_cryptodev_driver;
static struct rte_cryptodev_ops mlx5_crypto_ops = {
.dev_configure = NULL,
.dev_start = NULL,
.dev_stop = NULL,
.dev_close = NULL,
.dev_infos_get = NULL,
.stats_get = NULL,
.stats_reset = NULL,
.queue_pair_setup = NULL,
.queue_pair_release = NULL,
.sym_session_get_size = NULL,
.sym_session_configure = NULL,
.sym_session_clear = NULL,
.sym_get_raw_dp_ctx_size = NULL,
.sym_configure_raw_dp_ctx = NULL,
};
static void
mlx5_crypto_hw_global_release(struct mlx5_crypto_priv *priv)
{
if (priv->pd != NULL) {
claim_zero(mlx5_glue->dealloc_pd(priv->pd));
priv->pd = NULL;
}
if (priv->uar != NULL) {
mlx5_glue->devx_free_uar(priv->uar);
priv->uar = NULL;
}
}
static int
mlx5_crypto_pd_create(struct mlx5_crypto_priv *priv)
{
#ifdef HAVE_IBV_FLOW_DV_SUPPORT
struct mlx5dv_obj obj;
struct mlx5dv_pd pd_info;
int ret;
priv->pd = mlx5_glue->alloc_pd(priv->ctx);
if (priv->pd == NULL) {
DRV_LOG(ERR, "Failed to allocate PD.");
return errno ? -errno : -ENOMEM;
}
obj.pd.in = priv->pd;
obj.pd.out = &pd_info;
ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD);
if (ret != 0) {
DRV_LOG(ERR, "Fail to get PD object info.");
mlx5_glue->dealloc_pd(priv->pd);
priv->pd = NULL;
return -errno;
}
priv->pdn = pd_info.pdn;
return 0;
#else
(void)priv;
DRV_LOG(ERR, "Cannot get pdn - no DV support.");
return -ENOTSUP;
#endif /* HAVE_IBV_FLOW_DV_SUPPORT */
}
static int
mlx5_crypto_hw_global_prepare(struct mlx5_crypto_priv *priv)
{
if (mlx5_crypto_pd_create(priv) != 0)
return -1;
priv->uar = mlx5_devx_alloc_uar(priv->ctx, -1);
if (priv->uar == NULL || mlx5_os_get_devx_uar_reg_addr(priv->uar) ==
NULL) {
rte_errno = errno;
claim_zero(mlx5_glue->dealloc_pd(priv->pd));
DRV_LOG(ERR, "Failed to allocate UAR.");
return -1;
}
return 0;
}
/**
* DPDK callback to register a PCI device.
*
* This function spawns crypto device out of a given PCI device.
*
* @param[in] pci_drv
* PCI driver structure (mlx5_crypto_driver).
* @param[in] pci_dev
* PCI device information.
*
* @return
* 0 on success, 1 to skip this driver, a negative errno value otherwise
* and rte_errno is set.
*/
static int
mlx5_crypto_pci_probe(struct rte_pci_driver *pci_drv,
struct rte_pci_device *pci_dev)
{
struct ibv_device *ibv;
struct rte_cryptodev *crypto_dev;
struct ibv_context *ctx;
struct mlx5_crypto_priv *priv;
struct mlx5_hca_attr attr = { 0 };
struct rte_cryptodev_pmd_init_params init_params = {
.name = "",
.private_data_size = sizeof(struct mlx5_crypto_priv),
.socket_id = pci_dev->device.numa_node,
.max_nb_queue_pairs =
RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS,
};
RTE_SET_USED(pci_drv);
if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
DRV_LOG(ERR, "Non-primary process type is not supported.");
rte_errno = ENOTSUP;
return -rte_errno;
}
ibv = mlx5_os_get_ibv_device(&pci_dev->addr);
if (ibv == NULL) {
DRV_LOG(ERR, "No matching IB device for PCI slot "
PCI_PRI_FMT ".", pci_dev->addr.domain,
pci_dev->addr.bus, pci_dev->addr.devid,
pci_dev->addr.function);
return -rte_errno;
}
DRV_LOG(INFO, "PCI information matches for device \"%s\".", ibv->name);
ctx = mlx5_glue->dv_open_device(ibv);
if (ctx == NULL) {
DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name);
rte_errno = ENODEV;
return -rte_errno;
}
if (mlx5_devx_cmd_query_hca_attr(ctx, &attr) != 0 ||
attr.crypto == 0 || attr.aes_xts == 0) {
DRV_LOG(ERR, "Not enough capabilities to support crypto "
"operations, maybe old FW/OFED version?");
claim_zero(mlx5_glue->close_device(ctx));
rte_errno = ENOTSUP;
return -ENOTSUP;
}
crypto_dev = rte_cryptodev_pmd_create(ibv->name, &pci_dev->device,
&init_params);
if (crypto_dev == NULL) {
DRV_LOG(ERR, "Failed to create device \"%s\".", ibv->name);
claim_zero(mlx5_glue->close_device(ctx));
return -ENODEV;
}
DRV_LOG(INFO,
"Crypto device %s was created successfully.", ibv->name);
crypto_dev->dev_ops = &mlx5_crypto_ops;
crypto_dev->dequeue_burst = NULL;
crypto_dev->enqueue_burst = NULL;
crypto_dev->feature_flags = MLX5_CRYPTO_FEATURE_FLAGS;
crypto_dev->driver_id = mlx5_crypto_driver_id;
priv = crypto_dev->data->dev_private;
priv->ctx = ctx;
priv->pci_dev = pci_dev;
priv->crypto_dev = crypto_dev;
if (mlx5_crypto_hw_global_prepare(priv) != 0) {
rte_cryptodev_pmd_destroy(priv->crypto_dev);
claim_zero(mlx5_glue->close_device(priv->ctx));
return -1;
}
pthread_mutex_lock(&priv_list_lock);
TAILQ_INSERT_TAIL(&mlx5_crypto_priv_list, priv, next);
pthread_mutex_unlock(&priv_list_lock);
return 0;
}
static int
mlx5_crypto_pci_remove(struct rte_pci_device *pdev)
{
struct mlx5_crypto_priv *priv = NULL;
pthread_mutex_lock(&priv_list_lock);
TAILQ_FOREACH(priv, &mlx5_crypto_priv_list, next)
if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
break;
if (priv)
TAILQ_REMOVE(&mlx5_crypto_priv_list, priv, next);
pthread_mutex_unlock(&priv_list_lock);
if (priv) {
mlx5_crypto_hw_global_release(priv);
rte_cryptodev_pmd_destroy(priv->crypto_dev);
claim_zero(mlx5_glue->close_device(priv->ctx));
}
return 0;
}
static const struct rte_pci_id mlx5_crypto_pci_id_map[] = {
{
RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX,
PCI_DEVICE_ID_MELLANOX_CONNECTX6)
},
{
.vendor_id = 0
}
};
static struct mlx5_pci_driver mlx5_crypto_driver = {
.driver_class = MLX5_CLASS_CRYPTO,
.pci_driver = {
.driver = {
.name = RTE_STR(MLX5_CRYPTO_DRIVER_NAME),
},
.id_table = mlx5_crypto_pci_id_map,
.probe = mlx5_crypto_pci_probe,
.remove = mlx5_crypto_pci_remove,
.drv_flags = 0,
},
};
RTE_INIT(rte_mlx5_crypto_init)
{
mlx5_common_init();
if (mlx5_glue != NULL)
mlx5_pci_driver_register(&mlx5_crypto_driver);
}
RTE_PMD_REGISTER_CRYPTO_DRIVER(mlx5_cryptodev_driver, mlx5_drv,
mlx5_crypto_driver_id);
RTE_LOG_REGISTER_DEFAULT(mlx5_crypto_logtype, NOTICE)
RTE_PMD_EXPORT_NAME(MLX5_CRYPTO_DRIVER_NAME, __COUNTER__);
RTE_PMD_REGISTER_PCI_TABLE(MLX5_CRYPTO_DRIVER_NAME, mlx5_crypto_pci_id_map);
RTE_PMD_REGISTER_KMOD_DEP(MLX5_CRYPTO_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib");

View File

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#ifndef MLX5_CRYPTO_H_
#define MLX5_CRYPTO_H_
#include <stdbool.h>
#include <rte_cryptodev.h>
#include <rte_cryptodev_pmd.h>
#include <mlx5_common_utils.h>
struct mlx5_crypto_priv {
TAILQ_ENTRY(mlx5_crypto_priv) next;
struct ibv_context *ctx; /* Device context. */
struct rte_pci_device *pci_dev;
struct rte_cryptodev *crypto_dev;
void *uar; /* User Access Region. */
uint32_t pdn; /* Protection Domain number. */
struct ibv_pd *pd;
};
#endif /* MLX5_CRYPTO_H_ */

View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#ifndef RTE_PMD_MLX5_CRYPTO_UTILS_H_
#define RTE_PMD_MLX5_CRYPTO_UTILS_H_
#include <mlx5_common.h>
extern int mlx5_crypto_logtype;
#define MLX5_CRYPTO_LOG_PREFIX "mlx5_crypto"
/* Generic printf()-like logging macro with automatic line feed. */
#define DRV_LOG(level, ...) \
PMD_DRV_LOG_(level, mlx5_crypto_logtype, MLX5_CRYPTO_LOG_PREFIX, \
__VA_ARGS__ PMD_DRV_LOG_STRIP PMD_DRV_LOG_OPAREN, \
PMD_DRV_LOG_CPAREN)
#endif /* RTE_PMD_MLX5_CRYPTO_UTILS_H_ */

View File

@ -0,0 +1,3 @@
DPDK_21 {
local: *;
};