bdev/crypto: optimization: use shared sessions

Initial implmentation had a 1:1 session to crypto op ratio. After
working with a similar concept in CompressDev checked to see if
this was required and apparently it is not.

Saves a decent number of API calls per crypto op and in the poller.
Also saves on mempool usage.  Performance improvement measurement
is WIP.

Change-Id: I73f2355e720a16fd46bc4a02657419f779f07cbb
Signed-off-by: Paul Luse <paul.e.luse@intel.com>
Reviewed-on: https://review.gerrithub.io/433726
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Fiona Trahe <fiona.trahe@intel.com>
This commit is contained in:
Paul Luse 2018-11-17 15:54:03 -07:00 committed by Jim Harris
parent 6177d220fb
commit 3be1436c09
2 changed files with 91 additions and 66 deletions

View File

@ -39,6 +39,7 @@
#include "spdk/io_channel.h"
#include "spdk/bdev_module.h"
#include <rte_config.h>
#include <rte_bus_vdev.h>
#include <rte_crypto.h>
@ -104,7 +105,7 @@ static pthread_mutex_t g_device_qp_lock = PTHREAD_MUTEX_INITIALIZER;
*/
#define NUM_MBUFS 32768
#define POOL_CACHE_SIZE 256
#define NUM_SESSIONS NUM_MBUFS
#define NUM_SESSIONS 1024
#define SESS_MEMPOOL_CACHE_SIZE 256
/* This is the max number of IOs we can supply to any crypto device QP at one time.
@ -151,6 +152,9 @@ struct vbdev_crypto {
struct spdk_bdev crypto_bdev; /* the crypto virtual bdev */
uint8_t *key; /* key per bdev */
char *drv_name; /* name of the crypto device driver */
struct rte_cryptodev_sym_session *session_encrypt; /* encryption session for this bdev */
struct rte_cryptodev_sym_session *session_decrypt; /* decryption session for this bdev */
struct rte_crypto_sym_xform cipher_xform; /* crypto control struct for this bdev */
TAILQ_ENTRY(vbdev_crypto) link;
};
static TAILQ_HEAD(, vbdev_crypto) g_vbdev_crypto = TAILQ_HEAD_INITIALIZER(g_vbdev_crypto);
@ -179,8 +183,6 @@ struct crypto_bdev_io {
int cryop_cnt_remaining; /* counter used when completing crypto ops */
struct crypto_io_channel *crypto_ch; /* need to store for crypto completion handling */
struct vbdev_crypto *crypto_bdev; /* the crypto node struct associated with this IO */
enum rte_crypto_cipher_operation crypto_op; /* the crypto control struct */
struct rte_crypto_sym_xform cipher_xform; /* crypto control struct for this IO */
struct spdk_bdev_io *orig_io; /* the original IO */
struct spdk_bdev_io *read_io; /* the read IO we issued */
@ -240,7 +242,7 @@ vbdev_crypto_init_crypto_drivers(void)
}
}
g_session_mp = spdk_mempool_create("session_mp", NUM_SESSIONS * 2, max_sess_size,
g_session_mp = spdk_mempool_create("session_mp", NUM_SESSIONS, max_sess_size,
SPDK_MEMPOOL_DEFAULT_CACHE_SIZE,
SPDK_ENV_SOCKET_ID_ANY);
if (g_session_mp == NULL) {
@ -497,10 +499,6 @@ crypto_dev_poller(void *args)
/* Complete the IO */
_crypto_operation_complete(bdev_io);
/* Return session */
rte_cryptodev_sym_session_clear(cdev_id, dequeued_ops[i]->sym->session);
rte_cryptodev_sym_session_free(dequeued_ops[i]->sym->session);
}
}
@ -532,7 +530,6 @@ crypto_dev_poller(void *args)
static int
_crypto_operation(struct spdk_bdev_io *bdev_io, enum rte_crypto_cipher_operation crypto_op)
{
struct rte_cryptodev_sym_session *session;
uint16_t num_enqueued_ops = 0;
uint32_t cryop_cnt = bdev_io->u.bdev.num_blocks;
struct crypto_bdev_io *io_ctx = (struct crypto_bdev_io *)bdev_io->driver_ctx;
@ -588,32 +585,6 @@ _crypto_operation(struct spdk_bdev_io *bdev_io, enum rte_crypto_cipher_operation
goto error_get_ops;
}
/* Get sessions. */
session = rte_cryptodev_sym_session_create((struct rte_mempool *)g_session_mp);
if (NULL == session) {
SPDK_ERRLOG("ERROR trying to create crypto session!\n");
rc = -EINVAL;
goto error_session_create;
}
/* Init our session with the desired cipher options. */
io_ctx->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
io_ctx->cipher_xform.cipher.key.data = io_ctx->crypto_bdev->key;
io_ctx->cipher_xform.cipher.op = io_ctx->crypto_op = crypto_op;
io_ctx->cipher_xform.cipher.iv.offset = IV_OFFSET;
io_ctx->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
io_ctx->cipher_xform.cipher.key.length = AES_CBC_KEY_LENGTH;
io_ctx->cipher_xform.cipher.iv.length = AES_CBC_IV_LENGTH;
rc = rte_cryptodev_sym_session_init(cdev_id, session,
&io_ctx->cipher_xform,
(struct rte_mempool *)g_session_mp);
if (rc < 0) {
SPDK_ERRLOG("ERROR trying to init crypto session!\n");
rc = -EINVAL;
goto error_session_init;
}
/* For encryption, we need to prepare a single contiguous buffer as the encryption
* destination, we'll then pass that along for the write after encryption is done.
* This is done to avoiding encrypting the provided write buffer which may be
@ -695,13 +666,25 @@ _crypto_operation(struct spdk_bdev_io *bdev_io, enum rte_crypto_cipher_operation
crypto_ops[crypto_index]->sym->m_dst = dst_mbufs[crypto_index];
en_offset += crypto_len;
dst_mbufs[crypto_index]->next = NULL;
}
/* Attach the crypto session to the operation */
rc = rte_crypto_op_attach_sym_session(crypto_ops[crypto_index], session);
if (rc) {
rc = -EINVAL;
goto error_attach_session;
/* Attach the crypto session to the operation */
rc = rte_crypto_op_attach_sym_session(crypto_ops[crypto_index],
io_ctx->crypto_bdev->session_encrypt);
if (rc) {
rc = -EINVAL;
goto error_attach_session;
}
} else {
/* Attach the crypto session to the operation */
rc = rte_crypto_op_attach_sym_session(crypto_ops[crypto_index],
io_ctx->crypto_bdev->session_decrypt);
if (rc) {
rc = -EINVAL;
goto error_attach_session;
}
}
/* Subtract our running totals for the op in progress and the overall bdev io */
@ -755,10 +738,6 @@ _crypto_operation(struct spdk_bdev_io *bdev_io, enum rte_crypto_cipher_operation
/* Error cleanup paths. */
error_attach_session:
error_get_write_buffer:
error_session_init:
rte_cryptodev_sym_session_clear(cdev_id, session);
rte_cryptodev_sym_session_free(session);
error_session_create:
rte_mempool_put_bulk(g_crypto_op_mp, (void **)crypto_ops, cryop_cnt);
allocated = 0;
error_get_ops:
@ -981,6 +960,8 @@ _device_unregister_cb(void *io_device)
struct vbdev_crypto *crypto_bdev = io_device;
/* Done with this crypto_bdev. */
rte_cryptodev_sym_session_free(crypto_bdev->session_decrypt);
rte_cryptodev_sym_session_free(crypto_bdev->session_encrypt);
free(crypto_bdev->drv_name);
free(crypto_bdev->key);
free(crypto_bdev->crypto_bdev.name);
@ -1422,6 +1403,8 @@ vbdev_crypto_claim(struct spdk_bdev *bdev)
{
struct bdev_names *name;
struct vbdev_crypto *vbdev;
struct vbdev_dev *device;
bool found = false;
int rc = 0;
/* Check our list of names from config versus this bdev and if
@ -1503,12 +1486,75 @@ vbdev_crypto_claim(struct spdk_bdev *bdev)
goto error_claim;
}
/* To init the session we have to get the cryptoDev device ID for this vbdev */
TAILQ_FOREACH(device, &g_vbdev_devs, link) {
if (strcmp(device->cdev_info.driver_name, vbdev->drv_name) == 0) {
found = true;
break;
}
}
if (found == false) {
SPDK_ERRLOG("ERROR can't match crypto device driver to crypto vbdev!\n");
rc = -EINVAL;
goto error_cant_find_devid;
}
/* Get sessions. */
vbdev->session_encrypt = rte_cryptodev_sym_session_create((struct rte_mempool *)g_session_mp);
if (NULL == vbdev->session_encrypt) {
SPDK_ERRLOG("ERROR trying to create crypto session!\n");
rc = -EINVAL;
goto error_session_en_create;
}
vbdev->session_decrypt = rte_cryptodev_sym_session_create((struct rte_mempool *)g_session_mp);
if (NULL == vbdev->session_decrypt) {
SPDK_ERRLOG("ERROR trying to create crypto session!\n");
rc = -EINVAL;
goto error_session_de_create;
}
/* Init our per vbdev xform with the desired cipher options. */
vbdev->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
vbdev->cipher_xform.cipher.key.data = vbdev->key;
vbdev->cipher_xform.cipher.iv.offset = IV_OFFSET;
vbdev->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
vbdev->cipher_xform.cipher.key.length = AES_CBC_KEY_LENGTH;
vbdev->cipher_xform.cipher.iv.length = AES_CBC_IV_LENGTH;
vbdev->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
rc = rte_cryptodev_sym_session_init(device->cdev_id, vbdev->session_encrypt,
&vbdev->cipher_xform,
(struct rte_mempool *)g_session_mp);
if (rc < 0) {
SPDK_ERRLOG("ERROR trying to init encrypt session!\n");
rc = -EINVAL;
goto error_session_init;
}
vbdev->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
rc = rte_cryptodev_sym_session_init(device->cdev_id, vbdev->session_decrypt,
&vbdev->cipher_xform,
(struct rte_mempool *)g_session_mp);
if (rc < 0) {
SPDK_ERRLOG("ERROR trying to init decrypt session!\n");
rc = -EINVAL;
goto error_session_init;
}
SPDK_NOTICELOG("registered io_device for: %s\n", name->vbdev_name);
}
return rc;
/* Error cleanup paths. */
error_session_init:
rte_cryptodev_sym_session_free(vbdev->session_decrypt);
error_session_de_create:
rte_cryptodev_sym_session_free(vbdev->session_encrypt);
error_session_en_create:
error_cant_find_devid:
error_claim:
spdk_bdev_close(vbdev->base_desc);
error_open:

View File

@ -398,20 +398,6 @@ test_error_paths(void)
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
ut_rte_crypto_op_bulk_alloc = 1;
/* test failure of rte_cryptodev_sym_session_create() */
g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
MOCK_SET(rte_cryptodev_sym_session_create, NULL);
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
MOCK_SET(rte_cryptodev_sym_session_create, (struct rte_cryptodev_sym_session *)1);
/* test failure of rte_cryptodev_sym_session_init() */
g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
MOCK_SET(rte_cryptodev_sym_session_init, -1);
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
MOCK_SET(rte_cryptodev_sym_session_init, 0);
/* test failure of rte_crypto_op_attach_sym_session() */
g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
ut_rte_crypto_op_attach_sym_session = -1;
@ -437,7 +423,6 @@ test_simple_write(void)
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
CU_ASSERT(g_io_ctx->cryop_cnt_remaining == 1);
CU_ASSERT(g_io_ctx->crypto_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT);
CU_ASSERT(g_io_ctx->cry_iov.iov_len == 512);
CU_ASSERT(g_io_ctx->cry_iov.iov_base != NULL);
CU_ASSERT(g_io_ctx->cry_offset_blocks == 0);
@ -472,7 +457,6 @@ test_simple_read(void)
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
CU_ASSERT(g_io_ctx->cryop_cnt_remaining == 1);
CU_ASSERT(g_io_ctx->crypto_op == RTE_CRYPTO_CIPHER_OP_DECRYPT);
CU_ASSERT(g_test_crypto_ops[0]->sym->m_src->buf_addr == &test_simple_read);
CU_ASSERT(g_test_crypto_ops[0]->sym->m_src->data_len == 512);
CU_ASSERT(g_test_crypto_ops[0]->sym->m_src->next == NULL);
@ -505,7 +489,6 @@ test_large_rw(void)
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
CU_ASSERT(g_io_ctx->cryop_cnt_remaining == (int)num_blocks);
CU_ASSERT(g_io_ctx->crypto_op == RTE_CRYPTO_CIPHER_OP_DECRYPT);
for (i = 0; i < num_blocks; i++) {
CU_ASSERT(g_test_crypto_ops[i]->sym->m_src->buf_addr == &test_large_rw + (i * block_len));
@ -531,7 +514,6 @@ test_large_rw(void)
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
CU_ASSERT(g_io_ctx->cryop_cnt_remaining == (int)num_blocks);
CU_ASSERT(g_io_ctx->crypto_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT);
for (i = 0; i < num_blocks; i++) {
CU_ASSERT(g_test_crypto_ops[i]->sym->m_src->buf_addr == &test_large_rw + (i * block_len));
@ -578,7 +560,6 @@ test_dev_full(void)
/* this test only completes one of the 2 IOs (in the drain path) */
CU_ASSERT(g_io_ctx->cryop_cnt_remaining == 1);
CU_ASSERT(g_io_ctx->crypto_op == RTE_CRYPTO_CIPHER_OP_DECRYPT);
for (i = 0; i < num_blocks; i++) {
/* One of the src_mbufs was freed because of the device full condition so
@ -622,7 +603,6 @@ test_crazy_rw(void)
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
CU_ASSERT(g_io_ctx->cryop_cnt_remaining == num_blocks);
CU_ASSERT(g_io_ctx->crypto_op == RTE_CRYPTO_CIPHER_OP_DECRYPT);
for (i = 0; i < num_blocks; i++) {
CU_ASSERT(g_test_crypto_ops[i]->sym->m_src->buf_addr == &test_crazy_rw + (i * block_len));
@ -657,7 +637,6 @@ test_crazy_rw(void)
vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
CU_ASSERT(g_io_ctx->cryop_cnt_remaining == num_blocks);
CU_ASSERT(g_io_ctx->crypto_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT);
for (i = 0; i < num_blocks; i++) {
CU_ASSERT(g_test_crypto_ops[i]->sym->m_src->buf_addr == &test_crazy_rw + (i * block_len));