1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 Intel Corporation. 3 * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. 4 * All rights reserved. 5 */ 6 7 #include "accel_dpdk_cryptodev.h" 8 9 #include "spdk/accel.h" 10 #include "spdk_internal/accel_module.h" 11 #include "spdk/env.h" 12 #include "spdk/likely.h" 13 #include "spdk/thread.h" 14 #include "spdk/util.h" 15 #include "spdk/log.h" 16 #include "spdk/json.h" 17 #include "spdk_internal/sgl.h" 18 19 #include <rte_bus_vdev.h> 20 #include <rte_crypto.h> 21 #include <rte_cryptodev.h> 22 #include <rte_mbuf_dyn.h> 23 #include <rte_version.h> 24 25 /* The VF spread is the number of queue pairs between virtual functions, we use this to 26 * load balance the QAT device. 27 */ 28 #define ACCEL_DPDK_CRYPTODEV_QAT_VF_SPREAD 32 29 30 /* This controls how many ops will be dequeued from the crypto driver in one run 31 * of the poller. It is mainly a performance knob as it effectively determines how 32 * much work the poller has to do. However even that can vary between crypto drivers 33 * as the ACCEL_DPDK_CRYPTODEV_AESNI_MB driver for example does all the crypto work on dequeue whereas the 34 * QAT driver just dequeues what has been completed already. 35 */ 36 #define ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE 64 37 38 #define ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE (128) 39 40 /* The number of MBUFS we need must be a power of two and to support other small IOs 41 * in addition to the limits mentioned above, we go to the next power of two. It is 42 * big number because it is one mempool for source and destination mbufs. It may 43 * need to be bigger to support multiple crypto drivers at once. 44 */ 45 #define ACCEL_DPDK_CRYPTODEV_NUM_MBUFS 32768 46 #define ACCEL_DPDK_CRYPTODEV_POOL_CACHE_SIZE 256 47 #define ACCEL_DPDK_CRYPTODEV_MAX_CRYPTO_VOLUMES 128 48 #define ACCEL_DPDK_CRYPTODEV_NUM_SESSIONS (2 * ACCEL_DPDK_CRYPTODEV_MAX_CRYPTO_VOLUMES) 49 #define ACCEL_DPDK_CRYPTODEV_SESS_MEMPOOL_CACHE_SIZE 0 50 51 /* This is the max number of IOs we can supply to any crypto device QP at one time. 52 * It can vary between drivers. 53 */ 54 #define ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS 2048 55 56 /* At this moment DPDK descriptors allocation for mlx5 has some issues. We use 512 57 * as a compromise value between performance and the time spent for initialization. */ 58 #define ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS_MLX5 512 59 60 #define ACCEL_DPDK_CRYPTODEV_AESNI_MB_NUM_QP 64 61 62 /* Common for suported devices. */ 63 #define ACCEL_DPDK_CRYPTODEV_DEFAULT_NUM_XFORMS 2 64 #define ACCEL_DPDK_CRYPTODEV_IV_OFFSET (sizeof(struct rte_crypto_op) + \ 65 sizeof(struct rte_crypto_sym_op) + \ 66 (ACCEL_DPDK_CRYPTODEV_DEFAULT_NUM_XFORMS * \ 67 sizeof(struct rte_crypto_sym_xform))) 68 #define ACCEL_DPDK_CRYPTODEV_IV_LENGTH 16 69 #define ACCEL_DPDK_CRYPTODEV_QUEUED_OP_OFFSET (ACCEL_DPDK_CRYPTODEV_IV_OFFSET + ACCEL_DPDK_CRYPTODEV_IV_LENGTH) 70 71 /* Driver names */ 72 #define ACCEL_DPDK_CRYPTODEV_AESNI_MB "crypto_aesni_mb" 73 #define ACCEL_DPDK_CRYPTODEV_QAT "crypto_qat" 74 #define ACCEL_DPDK_CRYPTODEV_QAT_ASYM "crypto_qat_asym" 75 #define ACCEL_DPDK_CRYPTODEV_MLX5 "mlx5_pci" 76 77 /* Supported ciphers */ 78 #define ACCEL_DPDK_CRYPTODEV_AES_CBC "AES_CBC" /* QAT and ACCEL_DPDK_CRYPTODEV_AESNI_MB */ 79 #define ACCEL_DPDK_CRYPTODEV_AES_XTS "AES_XTS" /* QAT and MLX5 */ 80 81 /* Specific to AES_CBC. */ 82 #define ACCEL_DPDK_CRYPTODEV_AES_CBC_KEY_LENGTH 16 83 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_128_BLOCK_KEY_LENGTH 16 /* AES-XTS-128 block key size. */ 84 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_256_BLOCK_KEY_LENGTH 32 /* AES-XTS-256 block key size. */ 85 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_512_BLOCK_KEY_LENGTH 64 /* AES-XTS-512 block key size. */ 86 87 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_TWEAK_KEY_LENGTH 16 /* XTS part key size is always 128 bit. */ 88 89 /* Limit of the max memory len attached to mbuf - rte_pktmbuf_attach_extbuf has uint16_t `buf_len` 90 * parameter, we use closes aligned value 32768 for better performance */ 91 #define ACCEL_DPDK_CRYPTODEV_MAX_MBUF_LEN 32768 92 93 /* Used to store IO context in mbuf */ 94 static const struct rte_mbuf_dynfield rte_mbuf_dynfield_io_context = { 95 .name = "context_accel_dpdk_cryptodev", 96 .size = sizeof(uint64_t), 97 .align = __alignof__(uint64_t), 98 .flags = 0, 99 }; 100 101 struct accel_dpdk_cryptodev_device; 102 103 enum accel_dpdk_cryptodev_driver_type { 104 ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB = 0, 105 ACCEL_DPDK_CRYPTODEV_DRIVER_QAT, 106 ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI, 107 ACCEL_DPDK_CRYPTODEV_DRIVER_LAST 108 }; 109 110 enum accel_dpdk_crypto_dev_cipher_type { 111 ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC, 112 ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS 113 }; 114 115 struct accel_dpdk_cryptodev_qp { 116 struct accel_dpdk_cryptodev_device *device; /* ptr to crypto device */ 117 uint32_t num_enqueued_ops; /* Used to decide whether to poll the qp or not */ 118 uint8_t qp; /* queue identifier */ 119 bool in_use; /* whether this node is in use or not */ 120 uint8_t index; /* used by QAT to load balance placement of qpairs */ 121 TAILQ_ENTRY(accel_dpdk_cryptodev_qp) link; 122 }; 123 124 struct accel_dpdk_cryptodev_device { 125 enum accel_dpdk_cryptodev_driver_type type; 126 struct rte_cryptodev_info cdev_info; /* includes DPDK device friendly name */ 127 uint32_t qp_desc_nr; /* max number of qp descriptors to be enqueued in burst */ 128 uint8_t cdev_id; /* identifier for the device */ 129 TAILQ_HEAD(, accel_dpdk_cryptodev_qp) qpairs; 130 TAILQ_ENTRY(accel_dpdk_cryptodev_device) link; 131 }; 132 133 struct accel_dpdk_cryptodev_key_handle { 134 struct accel_dpdk_cryptodev_device *device; 135 TAILQ_ENTRY(accel_dpdk_cryptodev_key_handle) link; 136 void *session_encrypt; /* encryption session for this key */ 137 void *session_decrypt; /* decryption session for this key */ 138 struct rte_crypto_sym_xform cipher_xform; /* crypto control struct for this key */ 139 }; 140 141 struct accel_dpdk_cryptodev_key_priv { 142 enum accel_dpdk_cryptodev_driver_type driver; 143 enum accel_dpdk_crypto_dev_cipher_type cipher; 144 char *xts_key; 145 TAILQ_HEAD(, accel_dpdk_cryptodev_key_handle) dev_keys; 146 }; 147 148 /* For queueing up crypto operations that we can't submit for some reason */ 149 struct accel_dpdk_cryptodev_queued_op { 150 struct accel_dpdk_cryptodev_qp *qp; 151 struct rte_crypto_op *crypto_op; 152 struct accel_dpdk_cryptodev_task *task; 153 TAILQ_ENTRY(accel_dpdk_cryptodev_queued_op) link; 154 }; 155 #define ACCEL_DPDK_CRYPTODEV_QUEUED_OP_LENGTH (sizeof(struct accel_dpdk_cryptodev_queued_op)) 156 157 /* The crypto channel struct. It is allocated and freed on my behalf by the io channel code. 158 * We store things in here that are needed on per thread basis like the base_channel for this thread, 159 * and the poller for this thread. 160 */ 161 struct accel_dpdk_cryptodev_io_channel { 162 /* completion poller */ 163 struct spdk_poller *poller; 164 /* Array of qpairs for each available device. The specific device will be selected depending on the crypto key */ 165 struct accel_dpdk_cryptodev_qp *device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_LAST]; 166 /* queued for re-submission to CryptoDev. Used when for some reason crypto op was not processed by the driver */ 167 TAILQ_HEAD(, accel_dpdk_cryptodev_queued_op) queued_cry_ops; 168 /* Used to queue tasks when qpair is full. No crypto operation was submitted to the driver by the task */ 169 TAILQ_HEAD(, accel_dpdk_cryptodev_task) queued_tasks; 170 }; 171 172 struct accel_dpdk_cryptodev_task { 173 struct spdk_accel_task base; 174 uint32_t cryop_completed; /* The number of crypto operations completed by HW */ 175 uint32_t cryop_submitted; /* The number of crypto operations submitted to HW */ 176 uint32_t cryop_total; /* Total number of crypto operations in this task */ 177 bool is_failed; 178 bool inplace; 179 TAILQ_ENTRY(accel_dpdk_cryptodev_task) link; 180 }; 181 182 /* Shared mempools between all devices on this system */ 183 static struct rte_mempool *g_session_mp = NULL; 184 static struct rte_mempool *g_session_mp_priv = NULL; 185 static struct rte_mempool *g_mbuf_mp = NULL; /* mbuf mempool */ 186 static int g_mbuf_offset; 187 static struct rte_mempool *g_crypto_op_mp = NULL; /* crypto operations, must be rte* mempool */ 188 189 static struct rte_mbuf_ext_shared_info g_shinfo = {}; /* used by DPDK mbuf macro */ 190 191 static uint8_t g_qat_total_qp = 0; 192 static uint8_t g_next_qat_index; 193 194 static const char *g_driver_names[] = { 195 [ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB] = ACCEL_DPDK_CRYPTODEV_AESNI_MB, 196 [ACCEL_DPDK_CRYPTODEV_DRIVER_QAT] = ACCEL_DPDK_CRYPTODEV_QAT, 197 [ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI] = ACCEL_DPDK_CRYPTODEV_MLX5 198 }; 199 static const char *g_cipher_names[] = { 200 [ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC] = ACCEL_DPDK_CRYPTODEV_AES_CBC, 201 [ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS] = ACCEL_DPDK_CRYPTODEV_AES_XTS, 202 }; 203 204 static enum accel_dpdk_cryptodev_driver_type g_dpdk_cryptodev_driver = 205 ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB; 206 207 /* Global list of all crypto devices */ 208 static TAILQ_HEAD(, accel_dpdk_cryptodev_device) g_crypto_devices = TAILQ_HEAD_INITIALIZER( 209 g_crypto_devices); 210 static pthread_mutex_t g_device_lock = PTHREAD_MUTEX_INITIALIZER; 211 212 static struct spdk_accel_module_if g_accel_dpdk_cryptodev_module; 213 214 static int accel_dpdk_cryptodev_process_task(struct accel_dpdk_cryptodev_io_channel *crypto_ch, 215 struct accel_dpdk_cryptodev_task *task); 216 217 void 218 accel_dpdk_cryptodev_enable(void) 219 { 220 spdk_accel_module_list_add(&g_accel_dpdk_cryptodev_module); 221 } 222 223 int 224 accel_dpdk_cryptodev_set_driver(const char *driver_name) 225 { 226 if (strcmp(driver_name, ACCEL_DPDK_CRYPTODEV_QAT) == 0) { 227 g_dpdk_cryptodev_driver = ACCEL_DPDK_CRYPTODEV_DRIVER_QAT; 228 } else if (strcmp(driver_name, ACCEL_DPDK_CRYPTODEV_AESNI_MB) == 0) { 229 g_dpdk_cryptodev_driver = ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB; 230 } else if (strcmp(driver_name, ACCEL_DPDK_CRYPTODEV_MLX5) == 0) { 231 g_dpdk_cryptodev_driver = ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI; 232 } else { 233 SPDK_ERRLOG("Unsupported driver %s\n", driver_name); 234 return -EINVAL; 235 } 236 237 SPDK_NOTICELOG("Using driver %s\n", driver_name); 238 239 return 0; 240 } 241 242 const char * 243 accel_dpdk_cryptodev_get_driver(void) 244 { 245 return g_driver_names[g_dpdk_cryptodev_driver]; 246 } 247 248 static void 249 cancel_queued_crypto_ops(struct accel_dpdk_cryptodev_io_channel *crypto_ch, 250 struct accel_dpdk_cryptodev_task *task) 251 { 252 struct rte_mbuf *mbufs_to_free[2 * ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE]; 253 struct rte_crypto_op *cancelled_ops[ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE]; 254 struct accel_dpdk_cryptodev_queued_op *op_to_cancel, *tmp_op; 255 struct rte_crypto_op *crypto_op; 256 int num_mbufs = 0, num_dequeued_ops = 0; 257 258 /* Remove all ops from the failed IO. Since we don't know the 259 * order we have to check them all. */ 260 TAILQ_FOREACH_SAFE(op_to_cancel, &crypto_ch->queued_cry_ops, link, tmp_op) { 261 /* Checking if this is our op. One IO contains multiple ops. */ 262 if (task == op_to_cancel->task) { 263 crypto_op = op_to_cancel->crypto_op; 264 TAILQ_REMOVE(&crypto_ch->queued_cry_ops, op_to_cancel, link); 265 266 /* Populating lists for freeing mbufs and ops. */ 267 mbufs_to_free[num_mbufs++] = (void *)crypto_op->sym->m_src; 268 if (crypto_op->sym->m_dst) { 269 mbufs_to_free[num_mbufs++] = (void *)crypto_op->sym->m_dst; 270 } 271 cancelled_ops[num_dequeued_ops++] = crypto_op; 272 } 273 } 274 275 /* Now bulk free both mbufs and crypto operations. */ 276 if (num_dequeued_ops > 0) { 277 rte_mempool_put_bulk(g_crypto_op_mp, (void **)cancelled_ops, 278 num_dequeued_ops); 279 assert(num_mbufs > 0); 280 /* This also releases chained mbufs if any. */ 281 rte_pktmbuf_free_bulk(mbufs_to_free, num_mbufs); 282 } 283 } 284 285 static inline uint16_t 286 accel_dpdk_cryptodev_poll_qp(struct accel_dpdk_cryptodev_qp *qp, 287 struct accel_dpdk_cryptodev_io_channel *crypto_ch) 288 { 289 struct rte_crypto_op *dequeued_ops[ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE]; 290 struct rte_mbuf *mbufs_to_free[2 * ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE]; 291 struct accel_dpdk_cryptodev_task *task; 292 uint32_t num_mbufs = 0; 293 int i; 294 uint16_t num_dequeued_ops; 295 296 /* Each run of the poller will get just what the device has available 297 * at the moment we call it, we don't check again after draining the 298 * first batch. 299 */ 300 num_dequeued_ops = rte_cryptodev_dequeue_burst(qp->device->cdev_id, qp->qp, 301 dequeued_ops, ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE); 302 /* Check if operation was processed successfully */ 303 for (i = 0; i < num_dequeued_ops; i++) { 304 305 /* We don't know the order or association of the crypto ops wrt any 306 * particular task so need to look at each and determine if it's 307 * the last one for it's task or not. 308 */ 309 task = (struct accel_dpdk_cryptodev_task *)*RTE_MBUF_DYNFIELD(dequeued_ops[i]->sym->m_src, 310 g_mbuf_offset, uint64_t *); 311 assert(task != NULL); 312 313 if (dequeued_ops[i]->status != RTE_CRYPTO_OP_STATUS_SUCCESS) { 314 SPDK_ERRLOG("error with op %d status %u\n", i, dequeued_ops[i]->status); 315 /* Update the task status to error, we'll still process the 316 * rest of the crypto ops for this task though so they 317 * aren't left hanging. 318 */ 319 task->is_failed = true; 320 } 321 322 /* Return the associated src and dst mbufs by collecting them into 323 * an array that we can use the bulk API to free after the loop. 324 */ 325 *RTE_MBUF_DYNFIELD(dequeued_ops[i]->sym->m_src, g_mbuf_offset, uint64_t *) = 0; 326 mbufs_to_free[num_mbufs++] = (void *)dequeued_ops[i]->sym->m_src; 327 if (dequeued_ops[i]->sym->m_dst) { 328 mbufs_to_free[num_mbufs++] = (void *)dequeued_ops[i]->sym->m_dst; 329 } 330 331 task->cryop_completed++; 332 if (task->cryop_completed == task->cryop_total) { 333 /* Complete the IO */ 334 spdk_accel_task_complete(&task->base, task->is_failed ? -EINVAL : 0); 335 } else if (task->cryop_completed == task->cryop_submitted) { 336 /* submit remaining crypto ops */ 337 int rc = accel_dpdk_cryptodev_process_task(crypto_ch, task); 338 339 if (spdk_unlikely(rc)) { 340 if (rc == -ENOMEM) { 341 TAILQ_INSERT_TAIL(&crypto_ch->queued_tasks, task, link); 342 continue; 343 } 344 spdk_accel_task_complete(&task->base, rc); 345 } 346 } 347 } 348 349 /* Now bulk free both mbufs and crypto operations. */ 350 if (num_dequeued_ops > 0) { 351 rte_mempool_put_bulk(g_crypto_op_mp, (void **)dequeued_ops, num_dequeued_ops); 352 assert(num_mbufs > 0); 353 /* This also releases chained mbufs if any. */ 354 rte_pktmbuf_free_bulk(mbufs_to_free, num_mbufs); 355 } 356 357 assert(qp->num_enqueued_ops >= num_dequeued_ops); 358 qp->num_enqueued_ops -= num_dequeued_ops; 359 360 return num_dequeued_ops; 361 } 362 363 /* This is the poller for the crypto module. It uses a single API to dequeue whatever is ready at 364 * the device. Then we need to decide if what we've got so far (including previous poller 365 * runs) totals up to one or more complete task */ 366 static int 367 accel_dpdk_cryptodev_poller(void *args) 368 { 369 struct accel_dpdk_cryptodev_io_channel *crypto_ch = args; 370 struct accel_dpdk_cryptodev_qp *qp; 371 struct accel_dpdk_cryptodev_task *task, *task_tmp; 372 struct accel_dpdk_cryptodev_queued_op *op_to_resubmit, *op_to_resubmit_tmp; 373 TAILQ_HEAD(, accel_dpdk_cryptodev_task) queued_tasks_tmp; 374 uint32_t num_dequeued_ops = 0, num_enqueued_ops = 0; 375 uint16_t enqueued; 376 int i, rc; 377 378 for (i = 0; i < ACCEL_DPDK_CRYPTODEV_DRIVER_LAST; i++) { 379 qp = crypto_ch->device_qp[i]; 380 /* Avoid polling "idle" qps since it may affect performance */ 381 if (qp && qp->num_enqueued_ops) { 382 num_dequeued_ops += accel_dpdk_cryptodev_poll_qp(qp, crypto_ch); 383 } 384 } 385 386 /* Check if there are any queued crypto ops to process */ 387 TAILQ_FOREACH_SAFE(op_to_resubmit, &crypto_ch->queued_cry_ops, link, op_to_resubmit_tmp) { 388 task = op_to_resubmit->task; 389 qp = op_to_resubmit->qp; 390 if (qp->num_enqueued_ops == qp->device->qp_desc_nr) { 391 continue; 392 } 393 enqueued = rte_cryptodev_enqueue_burst(qp->device->cdev_id, 394 qp->qp, 395 &op_to_resubmit->crypto_op, 396 1); 397 if (enqueued == 1) { 398 TAILQ_REMOVE(&crypto_ch->queued_cry_ops, op_to_resubmit, link); 399 qp->num_enqueued_ops++; 400 num_enqueued_ops++; 401 } else { 402 if (op_to_resubmit->crypto_op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED) { 403 /* If we couldn't get one, just break and try again later. */ 404 break; 405 } else { 406 /* Something is really wrong with the op. Most probably the 407 * mbuf is broken or the HW is not able to process the request. 408 * Fail the IO and remove its ops from the queued ops list. */ 409 task->is_failed = true; 410 411 cancel_queued_crypto_ops(crypto_ch, task); 412 413 task->cryop_completed++; 414 /* Fail the IO if there is nothing left on device. */ 415 if (task->cryop_completed == task->cryop_submitted) { 416 spdk_accel_task_complete(&task->base, -EFAULT); 417 } 418 } 419 } 420 } 421 422 if (!TAILQ_EMPTY(&crypto_ch->queued_tasks)) { 423 TAILQ_INIT(&queued_tasks_tmp); 424 425 TAILQ_FOREACH_SAFE(task, &crypto_ch->queued_tasks, link, task_tmp) { 426 TAILQ_REMOVE(&crypto_ch->queued_tasks, task, link); 427 rc = accel_dpdk_cryptodev_process_task(crypto_ch, task); 428 if (spdk_unlikely(rc)) { 429 if (rc == -ENOMEM) { 430 TAILQ_INSERT_TAIL(&queued_tasks_tmp, task, link); 431 /* Other queued tasks may belong to other qpairs, 432 * so process the whole list */ 433 continue; 434 } 435 spdk_accel_task_complete(&task->base, rc); 436 } else { 437 num_enqueued_ops++; 438 } 439 } 440 441 TAILQ_SWAP(&crypto_ch->queued_tasks, &queued_tasks_tmp, accel_dpdk_cryptodev_task, link); 442 } 443 444 return !!(num_dequeued_ops + num_enqueued_ops); 445 } 446 447 /* Allocate the new mbuf of @remainder size with data pointed by @addr and attach 448 * it to the @orig_mbuf. */ 449 static inline int 450 accel_dpdk_cryptodev_mbuf_chain_remainder(struct accel_dpdk_cryptodev_task *task, 451 struct rte_mbuf *orig_mbuf, uint8_t *addr, uint64_t *_remainder) 452 { 453 uint64_t phys_addr, phys_len, remainder = *_remainder; 454 struct rte_mbuf *chain_mbuf; 455 int rc; 456 457 phys_len = remainder; 458 phys_addr = spdk_vtophys((void *)addr, &phys_len); 459 if (spdk_unlikely(phys_addr == SPDK_VTOPHYS_ERROR)) { 460 return -EFAULT; 461 } 462 remainder = spdk_min(remainder, phys_len); 463 remainder = spdk_min(remainder, ACCEL_DPDK_CRYPTODEV_MAX_MBUF_LEN); 464 rc = rte_pktmbuf_alloc_bulk(g_mbuf_mp, (struct rte_mbuf **)&chain_mbuf, 1); 465 if (spdk_unlikely(rc)) { 466 return -ENOMEM; 467 } 468 /* Store context in every mbuf as we don't know anything about completion order */ 469 *RTE_MBUF_DYNFIELD(chain_mbuf, g_mbuf_offset, uint64_t *) = (uint64_t)task; 470 rte_pktmbuf_attach_extbuf(chain_mbuf, addr, phys_addr, remainder, &g_shinfo); 471 rte_pktmbuf_append(chain_mbuf, remainder); 472 473 /* Chained buffer is released by rte_pktbuf_free_bulk() automagicaly. */ 474 rte_pktmbuf_chain(orig_mbuf, chain_mbuf); 475 *_remainder = remainder; 476 477 return 0; 478 } 479 480 /* Attach data buffer pointed by @addr to @mbuf. Return utilized len of the 481 * contiguous space that was physically available. */ 482 static inline uint64_t 483 accel_dpdk_cryptodev_mbuf_attach_buf(struct accel_dpdk_cryptodev_task *task, struct rte_mbuf *mbuf, 484 uint8_t *addr, uint32_t len) 485 { 486 uint64_t phys_addr, phys_len; 487 488 /* Store context in every mbuf as we don't know anything about completion order */ 489 *RTE_MBUF_DYNFIELD(mbuf, g_mbuf_offset, uint64_t *) = (uint64_t)task; 490 491 phys_len = len; 492 phys_addr = spdk_vtophys((void *)addr, &phys_len); 493 if (spdk_unlikely(phys_addr == SPDK_VTOPHYS_ERROR || phys_len == 0)) { 494 return 0; 495 } 496 assert(phys_len <= len); 497 phys_len = spdk_min(phys_len, ACCEL_DPDK_CRYPTODEV_MAX_MBUF_LEN); 498 499 /* Set the mbuf elements address and length. */ 500 rte_pktmbuf_attach_extbuf(mbuf, addr, phys_addr, phys_len, &g_shinfo); 501 rte_pktmbuf_append(mbuf, phys_len); 502 503 return phys_len; 504 } 505 506 static inline struct accel_dpdk_cryptodev_key_handle * 507 accel_dpdk_find_key_handle_in_channel(struct accel_dpdk_cryptodev_io_channel *crypto_ch, 508 struct accel_dpdk_cryptodev_key_priv *key) 509 { 510 struct accel_dpdk_cryptodev_key_handle *key_handle; 511 512 if (key->driver == ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI) { 513 /* Crypto key is registered on all available devices while io_channel opens CQ/QP on a single device. 514 * We need to iterate a list of key entries to find a suitable device */ 515 TAILQ_FOREACH(key_handle, &key->dev_keys, link) { 516 if (key_handle->device->cdev_id == 517 crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI]->device->cdev_id) { 518 return key_handle; 519 } 520 } 521 return NULL; 522 } else { 523 return TAILQ_FIRST(&key->dev_keys); 524 } 525 } 526 527 static inline int 528 accel_dpdk_cryptodev_task_alloc_resources(struct rte_mbuf **src_mbufs, struct rte_mbuf **dst_mbufs, 529 struct rte_crypto_op **crypto_ops, int count) 530 { 531 int rc; 532 533 /* Get the number of source mbufs that we need. These will always be 1:1 because we 534 * don't support chaining. The reason we don't is because of our decision to use 535 * LBA as IV, there can be no case where we'd need >1 mbuf per crypto op or the 536 * op would be > 1 LBA. 537 */ 538 rc = rte_pktmbuf_alloc_bulk(g_mbuf_mp, src_mbufs, count); 539 if (rc) { 540 SPDK_ERRLOG("Failed to get src_mbufs!\n"); 541 return -ENOMEM; 542 } 543 544 /* Get the same amount to describe destination. If crypto operation is inline then we don't just skip it */ 545 if (dst_mbufs) { 546 rc = rte_pktmbuf_alloc_bulk(g_mbuf_mp, dst_mbufs, count); 547 if (rc) { 548 SPDK_ERRLOG("Failed to get dst_mbufs!\n"); 549 goto err_free_src; 550 } 551 } 552 553 #ifdef __clang_analyzer__ 554 /* silence scan-build false positive */ 555 SPDK_CLANG_ANALYZER_PREINIT_PTR_ARRAY(crypto_ops, ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE, 556 0x1000); 557 #endif 558 /* Allocate crypto operations. */ 559 SPDK_NOTICELOG("requested %u ops\n", count); 560 rc = rte_crypto_op_bulk_alloc(g_crypto_op_mp, 561 RTE_CRYPTO_OP_TYPE_SYMMETRIC, 562 crypto_ops, count); 563 if (rc < count) { 564 SPDK_ERRLOG("Failed to allocate crypto ops! rc %d\n", rc); 565 goto err_free_ops; 566 } 567 568 return 0; 569 570 err_free_ops: 571 if (rc > 0) { 572 rte_mempool_put_bulk(g_crypto_op_mp, (void **)crypto_ops, rc); 573 } 574 if (dst_mbufs) { 575 /* This also releases chained mbufs if any. */ 576 rte_pktmbuf_free_bulk(dst_mbufs, count); 577 } 578 err_free_src: 579 /* This also releases chained mbufs if any. */ 580 rte_pktmbuf_free_bulk(src_mbufs, count); 581 582 return -ENOMEM; 583 } 584 585 static inline int 586 accel_dpdk_cryptodev_mbuf_add_single_block(struct spdk_iov_sgl *sgl, struct rte_mbuf *mbuf, 587 struct accel_dpdk_cryptodev_task *task) 588 { 589 int rc; 590 uint8_t *buf_addr; 591 uint64_t phys_len; 592 uint64_t remainder; 593 uint64_t buf_len = spdk_min(task->base.block_size, sgl->iov->iov_len - sgl->iov_offset); 594 595 buf_addr = sgl->iov->iov_base + sgl->iov_offset; 596 phys_len = accel_dpdk_cryptodev_mbuf_attach_buf(task, mbuf, buf_addr, buf_len); 597 if (spdk_unlikely(phys_len == 0)) { 598 return -EFAULT; 599 } 600 buf_len = spdk_min(buf_len, phys_len); 601 spdk_iov_sgl_advance(sgl, buf_len); 602 603 /* Handle the case of page boundary. */ 604 assert(task->base.block_size >= buf_len); 605 remainder = task->base.block_size - buf_len; 606 while (remainder) { 607 buf_len = spdk_min(remainder, sgl->iov->iov_len - sgl->iov_offset); 608 buf_addr = sgl->iov->iov_base + sgl->iov_offset; 609 rc = accel_dpdk_cryptodev_mbuf_chain_remainder(task, mbuf, buf_addr, &buf_len); 610 if (spdk_unlikely(rc)) { 611 return rc; 612 } 613 spdk_iov_sgl_advance(sgl, buf_len); 614 remainder -= buf_len; 615 } 616 617 return 0; 618 } 619 620 static inline void 621 accel_dpdk_cryptodev_op_set_iv(struct rte_crypto_op *crypto_op, uint64_t iv) 622 { 623 uint8_t *iv_ptr = rte_crypto_op_ctod_offset(crypto_op, uint8_t *, ACCEL_DPDK_CRYPTODEV_IV_OFFSET); 624 625 /* Set the IV - we use the LBA of the crypto_op */ 626 memset(iv_ptr, 0, ACCEL_DPDK_CRYPTODEV_IV_LENGTH); 627 rte_memcpy(iv_ptr, &iv, sizeof(uint64_t)); 628 } 629 630 static int 631 accel_dpdk_cryptodev_process_task(struct accel_dpdk_cryptodev_io_channel *crypto_ch, 632 struct accel_dpdk_cryptodev_task *task) 633 { 634 uint16_t num_enqueued_ops; 635 uint32_t cryop_cnt; 636 uint32_t crypto_len = task->base.block_size; 637 uint64_t dst_length, total_length; 638 uint32_t sgl_offset; 639 uint32_t qp_capacity; 640 uint64_t iv_start; 641 struct accel_dpdk_cryptodev_queued_op *op_to_queue; 642 uint32_t i, crypto_index; 643 struct rte_crypto_op *crypto_ops[ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE]; 644 struct rte_mbuf *src_mbufs[ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE]; 645 struct rte_mbuf *dst_mbufs[ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE]; 646 void *session; 647 struct accel_dpdk_cryptodev_key_priv *priv; 648 struct accel_dpdk_cryptodev_key_handle *key_handle; 649 struct accel_dpdk_cryptodev_qp *qp; 650 struct accel_dpdk_cryptodev_device *dev; 651 struct spdk_iov_sgl src, dst = {}; 652 int rc; 653 654 if (spdk_unlikely(!task->base.crypto_key || 655 task->base.crypto_key->module_if != &g_accel_dpdk_cryptodev_module)) { 656 return -EINVAL; 657 } 658 659 priv = task->base.crypto_key->priv; 660 assert(priv->driver < ACCEL_DPDK_CRYPTODEV_DRIVER_LAST); 661 662 if (task->cryop_completed) { 663 /* We continue to process remaining blocks */ 664 assert(task->cryop_submitted == task->cryop_completed); 665 assert(task->cryop_total > task->cryop_completed); 666 cryop_cnt = task->cryop_total - task->cryop_completed; 667 sgl_offset = task->cryop_completed * crypto_len; 668 iv_start = task->base.iv + task->cryop_completed; 669 } else { 670 /* That is a new task */ 671 total_length = 0; 672 for (i = 0; i < task->base.s.iovcnt; i++) { 673 total_length += task->base.s.iovs[i].iov_len; 674 } 675 dst_length = 0; 676 for (i = 0; i < task->base.d.iovcnt; i++) { 677 dst_length += task->base.d.iovs[i].iov_len; 678 } 679 680 if (spdk_unlikely(total_length != dst_length || !total_length)) { 681 return -ERANGE; 682 } 683 if (spdk_unlikely(total_length % task->base.block_size != 0)) { 684 return -EINVAL; 685 } 686 687 cryop_cnt = total_length / task->base.block_size; 688 task->cryop_total = cryop_cnt; 689 sgl_offset = 0; 690 iv_start = task->base.iv; 691 } 692 693 /* Limit the number of crypto ops that we can process once */ 694 cryop_cnt = spdk_min(cryop_cnt, ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE); 695 696 qp = crypto_ch->device_qp[priv->driver]; 697 assert(qp); 698 dev = qp->device; 699 assert(dev); 700 assert(dev->qp_desc_nr >= qp->num_enqueued_ops); 701 702 qp_capacity = dev->qp_desc_nr - qp->num_enqueued_ops; 703 cryop_cnt = spdk_min(cryop_cnt, qp_capacity); 704 if (spdk_unlikely(cryop_cnt == 0)) { 705 /* QP is full */ 706 return -ENOMEM; 707 } 708 709 key_handle = accel_dpdk_find_key_handle_in_channel(crypto_ch, priv); 710 if (spdk_unlikely(!key_handle)) { 711 SPDK_ERRLOG("Failed to find a key handle, driver %s, cipher %s\n", g_driver_names[priv->driver], 712 g_cipher_names[priv->cipher]); 713 return -EINVAL; 714 } 715 /* mlx5_pci binds keys to a specific device, we can't use a key with any device */ 716 assert(dev == key_handle->device || priv->driver != ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI); 717 718 if (task->base.op_code == ACCEL_OPC_ENCRYPT) { 719 session = key_handle->session_encrypt; 720 } else if (task->base.op_code == ACCEL_OPC_DECRYPT) { 721 session = key_handle->session_decrypt; 722 } else { 723 return -EINVAL; 724 } 725 726 rc = accel_dpdk_cryptodev_task_alloc_resources(src_mbufs, task->inplace ? NULL : dst_mbufs, 727 crypto_ops, cryop_cnt); 728 if (rc) { 729 return rc; 730 } 731 /* This value is used in the completion callback to determine when the accel task is complete. */ 732 task->cryop_submitted += cryop_cnt; 733 734 /* As we don't support chaining because of a decision to use LBA as IV, construction 735 * of crypto operations is straightforward. We build both the op, the mbuf and the 736 * dst_mbuf in our local arrays by looping through the length of the accel task and 737 * picking off LBA sized blocks of memory from the IOVs as we walk through them. Each 738 * LBA sized chunk of memory will correspond 1:1 to a crypto operation and a single 739 * mbuf per crypto operation. 740 */ 741 spdk_iov_sgl_init(&src, task->base.s.iovs, task->base.s.iovcnt, sgl_offset); 742 if (!task->inplace) { 743 spdk_iov_sgl_init(&dst, task->base.d.iovs, task->base.d.iovcnt, sgl_offset); 744 } 745 746 for (crypto_index = 0; crypto_index < cryop_cnt; crypto_index++) { 747 rc = accel_dpdk_cryptodev_mbuf_add_single_block(&src, src_mbufs[crypto_index], task); 748 if (spdk_unlikely(rc)) { 749 goto err_free_ops; 750 } 751 accel_dpdk_cryptodev_op_set_iv(crypto_ops[crypto_index], iv_start); 752 iv_start++; 753 754 /* Set the data to encrypt/decrypt length */ 755 crypto_ops[crypto_index]->sym->cipher.data.length = crypto_len; 756 crypto_ops[crypto_index]->sym->cipher.data.offset = 0; 757 rte_crypto_op_attach_sym_session(crypto_ops[crypto_index], session); 758 759 /* link the mbuf to the crypto op. */ 760 crypto_ops[crypto_index]->sym->m_src = src_mbufs[crypto_index]; 761 762 if (task->inplace) { 763 crypto_ops[crypto_index]->sym->m_dst = NULL; 764 } else { 765 #ifndef __clang_analyzer__ 766 /* scan-build thinks that dst_mbufs is not initialized */ 767 rc = accel_dpdk_cryptodev_mbuf_add_single_block(&dst, dst_mbufs[crypto_index], task); 768 if (spdk_unlikely(rc)) { 769 goto err_free_ops; 770 } 771 crypto_ops[crypto_index]->sym->m_dst = dst_mbufs[crypto_index]; 772 #endif 773 } 774 } 775 776 /* Enqueue everything we've got but limit by the max number of descriptors we 777 * configured the crypto device for. 778 */ 779 num_enqueued_ops = rte_cryptodev_enqueue_burst(dev->cdev_id, qp->qp, crypto_ops, cryop_cnt); 780 781 qp->num_enqueued_ops += num_enqueued_ops; 782 /* We were unable to enqueue everything but did get some, so need to decide what 783 * to do based on the status of the last op. 784 */ 785 if (num_enqueued_ops < cryop_cnt) { 786 switch (crypto_ops[num_enqueued_ops]->status) { 787 case RTE_CRYPTO_OP_STATUS_NOT_PROCESSED: 788 /* Queue them up on a linked list to be resubmitted via the poller. */ 789 for (crypto_index = num_enqueued_ops; crypto_index < cryop_cnt; crypto_index++) { 790 op_to_queue = (struct accel_dpdk_cryptodev_queued_op *)rte_crypto_op_ctod_offset( 791 crypto_ops[crypto_index], 792 uint8_t *, ACCEL_DPDK_CRYPTODEV_QUEUED_OP_OFFSET); 793 op_to_queue->qp = qp; 794 op_to_queue->crypto_op = crypto_ops[crypto_index]; 795 op_to_queue->task = task; 796 TAILQ_INSERT_TAIL(&crypto_ch->queued_cry_ops, op_to_queue, link); 797 } 798 break; 799 default: 800 /* For all other statuses, mark task as failed so that the poller will pick 801 * the failure up for the overall task status. 802 */ 803 task->is_failed = true; 804 if (num_enqueued_ops == 0) { 805 /* If nothing was enqueued, but the last one wasn't because of 806 * busy, fail it now as the poller won't know anything about it. 807 */ 808 rc = -EINVAL; 809 goto err_free_ops; 810 } 811 break; 812 } 813 } 814 815 return 0; 816 817 /* Error cleanup paths. */ 818 err_free_ops: 819 if (!task->inplace) { 820 /* This also releases chained mbufs if any. */ 821 rte_pktmbuf_free_bulk(dst_mbufs, cryop_cnt); 822 } 823 rte_mempool_put_bulk(g_crypto_op_mp, (void **)crypto_ops, cryop_cnt); 824 /* This also releases chained mbufs if any. */ 825 rte_pktmbuf_free_bulk(src_mbufs, cryop_cnt); 826 return rc; 827 } 828 829 static inline struct accel_dpdk_cryptodev_qp * 830 accel_dpdk_cryptodev_get_next_device_qpair(enum accel_dpdk_cryptodev_driver_type type) 831 { 832 struct accel_dpdk_cryptodev_device *device, *device_tmp; 833 struct accel_dpdk_cryptodev_qp *qpair; 834 835 TAILQ_FOREACH_SAFE(device, &g_crypto_devices, link, device_tmp) { 836 if (device->type != type) { 837 continue; 838 } 839 TAILQ_FOREACH(qpair, &device->qpairs, link) { 840 if (!qpair->in_use) { 841 qpair->in_use = true; 842 return qpair; 843 } 844 } 845 } 846 847 return NULL; 848 } 849 850 /* Helper function for the channel creation callback. 851 * Returns the number of drivers assigned to the channel */ 852 static uint32_t 853 accel_dpdk_cryptodev_assign_device_qps(struct accel_dpdk_cryptodev_io_channel *crypto_ch) 854 { 855 struct accel_dpdk_cryptodev_device *device; 856 struct accel_dpdk_cryptodev_qp *device_qp; 857 uint32_t num_drivers = 0; 858 bool qat_found = false; 859 860 pthread_mutex_lock(&g_device_lock); 861 862 TAILQ_FOREACH(device, &g_crypto_devices, link) { 863 if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT && !qat_found) { 864 /* For some QAT devices, the optimal qp to use is every 32nd as this spreads the 865 * workload out over the multiple virtual functions in the device. For the devices 866 * where this isn't the case, it doesn't hurt. 867 */ 868 TAILQ_FOREACH(device_qp, &device->qpairs, link) { 869 if (device_qp->index != g_next_qat_index) { 870 continue; 871 } 872 if (device_qp->in_use == false) { 873 assert(crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_QAT] == NULL); 874 crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_QAT] = device_qp; 875 device_qp->in_use = true; 876 g_next_qat_index = (g_next_qat_index + ACCEL_DPDK_CRYPTODEV_QAT_VF_SPREAD) % g_qat_total_qp; 877 qat_found = true; 878 num_drivers++; 879 break; 880 } else { 881 /* if the preferred index is used, skip to the next one in this set. */ 882 g_next_qat_index = (g_next_qat_index + 1) % g_qat_total_qp; 883 } 884 } 885 } 886 } 887 888 /* For ACCEL_DPDK_CRYPTODEV_AESNI_MB and MLX5_PCI select devices in round-robin manner */ 889 device_qp = accel_dpdk_cryptodev_get_next_device_qpair(ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB); 890 if (device_qp) { 891 assert(crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB] == NULL); 892 crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB] = device_qp; 893 num_drivers++; 894 } 895 896 device_qp = accel_dpdk_cryptodev_get_next_device_qpair(ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI); 897 if (device_qp) { 898 assert(crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI] == NULL); 899 crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI] = device_qp; 900 num_drivers++; 901 } 902 903 pthread_mutex_unlock(&g_device_lock); 904 905 return num_drivers; 906 } 907 908 static void 909 _accel_dpdk_cryptodev_destroy_cb(void *io_device, void *ctx_buf) 910 { 911 struct accel_dpdk_cryptodev_io_channel *crypto_ch = (struct accel_dpdk_cryptodev_io_channel *) 912 ctx_buf; 913 int i; 914 915 pthread_mutex_lock(&g_device_lock); 916 for (i = 0; i < ACCEL_DPDK_CRYPTODEV_DRIVER_LAST; i++) { 917 if (crypto_ch->device_qp[i]) { 918 crypto_ch->device_qp[i]->in_use = false; 919 } 920 } 921 pthread_mutex_unlock(&g_device_lock); 922 923 spdk_poller_unregister(&crypto_ch->poller); 924 } 925 926 static int 927 _accel_dpdk_cryptodev_create_cb(void *io_device, void *ctx_buf) 928 { 929 struct accel_dpdk_cryptodev_io_channel *crypto_ch = (struct accel_dpdk_cryptodev_io_channel *) 930 ctx_buf; 931 932 crypto_ch->poller = SPDK_POLLER_REGISTER(accel_dpdk_cryptodev_poller, crypto_ch, 0); 933 if (!accel_dpdk_cryptodev_assign_device_qps(crypto_ch)) { 934 SPDK_ERRLOG("No crypto drivers assigned\n"); 935 spdk_poller_unregister(&crypto_ch->poller); 936 return -EINVAL; 937 } 938 939 /* We use this to queue up crypto ops when the device is busy. */ 940 TAILQ_INIT(&crypto_ch->queued_cry_ops); 941 /* We use this to queue tasks when qpair is full or no resources in pools */ 942 TAILQ_INIT(&crypto_ch->queued_tasks); 943 944 return 0; 945 } 946 947 static struct spdk_io_channel * 948 accel_dpdk_cryptodev_get_io_channel(void) 949 { 950 return spdk_get_io_channel(&g_accel_dpdk_cryptodev_module); 951 } 952 953 static size_t 954 accel_dpdk_cryptodev_ctx_size(void) 955 { 956 return sizeof(struct accel_dpdk_cryptodev_task); 957 } 958 959 static bool 960 accel_dpdk_cryptodev_supports_opcode(enum accel_opcode opc) 961 { 962 switch (opc) { 963 case ACCEL_OPC_ENCRYPT: 964 case ACCEL_OPC_DECRYPT: 965 return true; 966 default: 967 return false; 968 } 969 } 970 971 static int 972 accel_dpdk_cryptodev_submit_tasks(struct spdk_io_channel *_ch, struct spdk_accel_task *_task) 973 { 974 struct accel_dpdk_cryptodev_task *task = SPDK_CONTAINEROF(_task, struct accel_dpdk_cryptodev_task, 975 base); 976 struct accel_dpdk_cryptodev_io_channel *ch = spdk_io_channel_get_ctx(_ch); 977 int rc; 978 979 task->cryop_completed = 0; 980 task->cryop_submitted = 0; 981 task->cryop_total = 0; 982 task->inplace = true; 983 task->is_failed = false; 984 985 /* Check if crypto operation is inplace: no destination or source == destination */ 986 if (task->base.s.iovcnt == task->base.d.iovcnt) { 987 if (memcmp(task->base.s.iovs, task->base.d.iovs, sizeof(struct iovec) * task->base.s.iovcnt) != 0) { 988 task->inplace = false; 989 } 990 } else if (task->base.d.iovcnt != 0) { 991 task->inplace = false; 992 } 993 994 rc = accel_dpdk_cryptodev_process_task(ch, task); 995 if (spdk_unlikely(rc == -ENOMEM)) { 996 TAILQ_INSERT_TAIL(&ch->queued_tasks, task, link); 997 rc = 0; 998 } 999 1000 return rc; 1001 } 1002 1003 /* Dummy function used by DPDK to free ext attached buffers to mbufs, we free them ourselves but 1004 * this callback has to be here. */ 1005 static void 1006 shinfo_free_cb(void *arg1, void *arg2) 1007 { 1008 } 1009 1010 static int 1011 accel_dpdk_cryptodev_create(uint8_t index, uint16_t num_lcores) 1012 { 1013 struct rte_cryptodev_qp_conf qp_conf = { 1014 .mp_session = g_session_mp, 1015 #if RTE_VERSION < RTE_VERSION_NUM(22, 11, 0, 0) 1016 .mp_session_private = g_session_mp_priv 1017 #endif 1018 }; 1019 /* Setup queue pairs. */ 1020 struct rte_cryptodev_config conf = { .socket_id = SPDK_ENV_SOCKET_ID_ANY }; 1021 struct accel_dpdk_cryptodev_device *device; 1022 uint8_t j, cdev_id, cdrv_id; 1023 struct accel_dpdk_cryptodev_qp *dev_qp; 1024 int rc; 1025 1026 device = calloc(1, sizeof(*device)); 1027 if (!device) { 1028 return -ENOMEM; 1029 } 1030 1031 /* Get details about this device. */ 1032 rte_cryptodev_info_get(index, &device->cdev_info); 1033 cdrv_id = device->cdev_info.driver_id; 1034 cdev_id = device->cdev_id = index; 1035 1036 if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_QAT) == 0) { 1037 device->qp_desc_nr = ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS; 1038 device->type = ACCEL_DPDK_CRYPTODEV_DRIVER_QAT; 1039 } else if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_AESNI_MB) == 0) { 1040 device->qp_desc_nr = ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS; 1041 device->type = ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB; 1042 } else if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_MLX5) == 0) { 1043 device->qp_desc_nr = ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS_MLX5; 1044 device->type = ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI; 1045 } else if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_QAT_ASYM) == 0) { 1046 /* ACCEL_DPDK_CRYPTODEV_QAT_ASYM devices are not supported at this time. */ 1047 rc = 0; 1048 goto err; 1049 } else { 1050 SPDK_ERRLOG("Failed to start device %u. Invalid driver name \"%s\"\n", 1051 cdev_id, device->cdev_info.driver_name); 1052 rc = -EINVAL; 1053 goto err; 1054 } 1055 1056 /* Before going any further, make sure we have enough resources for this 1057 * device type to function. We need a unique queue pair per core accross each 1058 * device type to remain lockless.... 1059 */ 1060 if ((rte_cryptodev_device_count_by_driver(cdrv_id) * 1061 device->cdev_info.max_nb_queue_pairs) < num_lcores) { 1062 SPDK_ERRLOG("Insufficient unique queue pairs available for %s\n", 1063 device->cdev_info.driver_name); 1064 SPDK_ERRLOG("Either add more crypto devices or decrease core count\n"); 1065 rc = -EINVAL; 1066 goto err; 1067 } 1068 1069 conf.nb_queue_pairs = device->cdev_info.max_nb_queue_pairs; 1070 rc = rte_cryptodev_configure(cdev_id, &conf); 1071 if (rc < 0) { 1072 SPDK_ERRLOG("Failed to configure cryptodev %u: error %d\n", 1073 cdev_id, rc); 1074 rc = -EINVAL; 1075 goto err; 1076 } 1077 1078 /* Pre-setup all potential qpairs now and assign them in the channel 1079 * callback. If we were to create them there, we'd have to stop the 1080 * entire device affecting all other threads that might be using it 1081 * even on other queue pairs. 1082 */ 1083 qp_conf.nb_descriptors = device->qp_desc_nr; 1084 for (j = 0; j < device->cdev_info.max_nb_queue_pairs; j++) { 1085 rc = rte_cryptodev_queue_pair_setup(cdev_id, j, &qp_conf, SOCKET_ID_ANY); 1086 if (rc < 0) { 1087 SPDK_ERRLOG("Failed to setup queue pair %u on " 1088 "cryptodev %u: error %d\n", j, cdev_id, rc); 1089 rc = -EINVAL; 1090 goto err_qp_setup; 1091 } 1092 } 1093 1094 rc = rte_cryptodev_start(cdev_id); 1095 if (rc < 0) { 1096 SPDK_ERRLOG("Failed to start device %u: error %d\n", cdev_id, rc); 1097 rc = -EINVAL; 1098 goto err_dev_start; 1099 } 1100 1101 TAILQ_INIT(&device->qpairs); 1102 /* Build up lists of device/qp combinations per PMD */ 1103 for (j = 0; j < device->cdev_info.max_nb_queue_pairs; j++) { 1104 dev_qp = calloc(1, sizeof(*dev_qp)); 1105 if (!dev_qp) { 1106 rc = -ENOMEM; 1107 goto err_qp_alloc; 1108 } 1109 dev_qp->device = device; 1110 dev_qp->qp = j; 1111 dev_qp->in_use = false; 1112 TAILQ_INSERT_TAIL(&device->qpairs, dev_qp, link); 1113 if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT) { 1114 dev_qp->index = g_qat_total_qp++; 1115 } 1116 } 1117 /* Add to our list of available crypto devices. */ 1118 TAILQ_INSERT_TAIL(&g_crypto_devices, device, link); 1119 1120 return 0; 1121 1122 err_qp_alloc: 1123 TAILQ_FOREACH(dev_qp, &device->qpairs, link) { 1124 if (dev_qp->device->cdev_id != device->cdev_id) { 1125 continue; 1126 } 1127 free(dev_qp); 1128 if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT) { 1129 assert(g_qat_total_qp); 1130 g_qat_total_qp--; 1131 } 1132 } 1133 rte_cryptodev_stop(cdev_id); 1134 err_dev_start: 1135 err_qp_setup: 1136 rte_cryptodev_close(cdev_id); 1137 err: 1138 free(device); 1139 1140 return rc; 1141 } 1142 1143 static void 1144 accel_dpdk_cryptodev_release(struct accel_dpdk_cryptodev_device *device) 1145 { 1146 struct accel_dpdk_cryptodev_qp *dev_qp, *tmp; 1147 1148 assert(device); 1149 1150 TAILQ_FOREACH_SAFE(dev_qp, &device->qpairs, link, tmp) { 1151 free(dev_qp); 1152 } 1153 if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT) { 1154 assert(g_qat_total_qp >= device->cdev_info.max_nb_queue_pairs); 1155 g_qat_total_qp -= device->cdev_info.max_nb_queue_pairs; 1156 } 1157 rte_cryptodev_stop(device->cdev_id); 1158 rte_cryptodev_close(device->cdev_id); 1159 free(device); 1160 } 1161 1162 static int 1163 accel_dpdk_cryptodev_init(void) 1164 { 1165 uint8_t cdev_count; 1166 uint8_t cdev_id; 1167 int i, rc; 1168 struct accel_dpdk_cryptodev_device *device, *tmp_dev; 1169 unsigned int max_sess_size = 0, sess_size; 1170 uint16_t num_lcores = rte_lcore_count(); 1171 char aesni_args[32]; 1172 1173 /* Only the first call via module init should init the crypto drivers. */ 1174 if (g_session_mp != NULL) { 1175 return 0; 1176 } 1177 1178 /* We always init ACCEL_DPDK_CRYPTODEV_AESNI_MB */ 1179 snprintf(aesni_args, sizeof(aesni_args), "max_nb_queue_pairs=%d", 1180 ACCEL_DPDK_CRYPTODEV_AESNI_MB_NUM_QP); 1181 rc = rte_vdev_init(ACCEL_DPDK_CRYPTODEV_AESNI_MB, aesni_args); 1182 if (rc) { 1183 SPDK_NOTICELOG("Failed to create virtual PMD %s: error %d. " 1184 "Possibly %s is not supported by DPDK library. " 1185 "Keep going...\n", ACCEL_DPDK_CRYPTODEV_AESNI_MB, rc, ACCEL_DPDK_CRYPTODEV_AESNI_MB); 1186 } 1187 1188 /* If we have no crypto devices, there's no reason to continue. */ 1189 cdev_count = rte_cryptodev_count(); 1190 SPDK_NOTICELOG("Found crypto devices: %d\n", (int)cdev_count); 1191 if (cdev_count == 0) { 1192 return 0; 1193 } 1194 1195 g_mbuf_offset = rte_mbuf_dynfield_register(&rte_mbuf_dynfield_io_context); 1196 if (g_mbuf_offset < 0) { 1197 SPDK_ERRLOG("error registering dynamic field with DPDK\n"); 1198 return -EINVAL; 1199 } 1200 1201 /* Create global mempools, shared by all devices regardless of type */ 1202 /* First determine max session size, most pools are shared by all the devices, 1203 * so we need to find the global max sessions size. */ 1204 for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) { 1205 sess_size = rte_cryptodev_sym_get_private_session_size(cdev_id); 1206 if (sess_size > max_sess_size) { 1207 max_sess_size = sess_size; 1208 } 1209 } 1210 1211 #if RTE_VERSION < RTE_VERSION_NUM(22, 11, 0, 0) 1212 g_session_mp_priv = rte_mempool_create("dpdk_crypto_ses_mp_priv", 1213 ACCEL_DPDK_CRYPTODEV_NUM_SESSIONS, max_sess_size, ACCEL_DPDK_CRYPTODEV_SESS_MEMPOOL_CACHE_SIZE, 0, 1214 NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0); 1215 if (g_session_mp_priv == NULL) { 1216 SPDK_ERRLOG("Cannot create private session pool max size 0x%x\n", max_sess_size); 1217 return -ENOMEM; 1218 } 1219 1220 /* When session private data mempool allocated, the element size for the session mempool 1221 * should be 0. */ 1222 max_sess_size = 0; 1223 #endif 1224 1225 g_session_mp = rte_cryptodev_sym_session_pool_create("dpdk_crypto_ses_mp", 1226 ACCEL_DPDK_CRYPTODEV_NUM_SESSIONS, max_sess_size, ACCEL_DPDK_CRYPTODEV_SESS_MEMPOOL_CACHE_SIZE, 0, 1227 SOCKET_ID_ANY); 1228 if (g_session_mp == NULL) { 1229 SPDK_ERRLOG("Cannot create session pool max size 0x%x\n", max_sess_size); 1230 rc = -ENOMEM; 1231 goto error_create_session_mp; 1232 } 1233 1234 g_mbuf_mp = rte_pktmbuf_pool_create("dpdk_crypto_mbuf_mp", ACCEL_DPDK_CRYPTODEV_NUM_MBUFS, 1235 ACCEL_DPDK_CRYPTODEV_POOL_CACHE_SIZE, 1236 0, 0, SPDK_ENV_SOCKET_ID_ANY); 1237 if (g_mbuf_mp == NULL) { 1238 SPDK_ERRLOG("Cannot create mbuf pool\n"); 1239 rc = -ENOMEM; 1240 goto error_create_mbuf; 1241 } 1242 1243 /* We use per op private data as suggested by DPDK and to store the IV and 1244 * our own struct for queueing ops. */ 1245 g_crypto_op_mp = rte_crypto_op_pool_create("dpdk_crypto_op_mp", 1246 RTE_CRYPTO_OP_TYPE_SYMMETRIC, ACCEL_DPDK_CRYPTODEV_NUM_MBUFS, ACCEL_DPDK_CRYPTODEV_POOL_CACHE_SIZE, 1247 (ACCEL_DPDK_CRYPTODEV_DEFAULT_NUM_XFORMS * sizeof(struct rte_crypto_sym_xform)) + 1248 ACCEL_DPDK_CRYPTODEV_IV_LENGTH + ACCEL_DPDK_CRYPTODEV_QUEUED_OP_LENGTH, rte_socket_id()); 1249 if (g_crypto_op_mp == NULL) { 1250 SPDK_ERRLOG("Cannot create op pool\n"); 1251 rc = -ENOMEM; 1252 goto error_create_op; 1253 } 1254 1255 /* Init all devices */ 1256 for (i = 0; i < cdev_count; i++) { 1257 rc = accel_dpdk_cryptodev_create(i, num_lcores); 1258 if (rc) { 1259 goto err; 1260 } 1261 } 1262 1263 g_shinfo.free_cb = shinfo_free_cb; 1264 1265 spdk_io_device_register(&g_accel_dpdk_cryptodev_module, _accel_dpdk_cryptodev_create_cb, 1266 _accel_dpdk_cryptodev_destroy_cb, sizeof(struct accel_dpdk_cryptodev_io_channel), 1267 "accel_dpdk_cryptodev"); 1268 1269 return 0; 1270 1271 /* Error cleanup paths. */ 1272 err: 1273 TAILQ_FOREACH_SAFE(device, &g_crypto_devices, link, tmp_dev) { 1274 TAILQ_REMOVE(&g_crypto_devices, device, link); 1275 accel_dpdk_cryptodev_release(device); 1276 } 1277 rte_mempool_free(g_crypto_op_mp); 1278 g_crypto_op_mp = NULL; 1279 error_create_op: 1280 rte_mempool_free(g_mbuf_mp); 1281 g_mbuf_mp = NULL; 1282 error_create_mbuf: 1283 rte_mempool_free(g_session_mp); 1284 g_session_mp = NULL; 1285 error_create_session_mp: 1286 if (g_session_mp_priv != NULL) { 1287 rte_mempool_free(g_session_mp_priv); 1288 g_session_mp_priv = NULL; 1289 } 1290 return rc; 1291 } 1292 1293 static void 1294 accel_dpdk_cryptodev_fini_cb(void *io_device) 1295 { 1296 struct accel_dpdk_cryptodev_device *device, *tmp; 1297 1298 TAILQ_FOREACH_SAFE(device, &g_crypto_devices, link, tmp) { 1299 TAILQ_REMOVE(&g_crypto_devices, device, link); 1300 accel_dpdk_cryptodev_release(device); 1301 } 1302 rte_vdev_uninit(ACCEL_DPDK_CRYPTODEV_AESNI_MB); 1303 1304 rte_mempool_free(g_crypto_op_mp); 1305 rte_mempool_free(g_mbuf_mp); 1306 rte_mempool_free(g_session_mp); 1307 if (g_session_mp_priv != NULL) { 1308 rte_mempool_free(g_session_mp_priv); 1309 } 1310 1311 spdk_accel_module_finish(); 1312 } 1313 1314 /* Called when the entire module is being torn down. */ 1315 static void 1316 accel_dpdk_cryptodev_fini(void *ctx) 1317 { 1318 if (g_crypto_op_mp) { 1319 spdk_io_device_unregister(&g_accel_dpdk_cryptodev_module, accel_dpdk_cryptodev_fini_cb); 1320 } 1321 } 1322 1323 static void 1324 accel_dpdk_cryptodev_key_handle_session_free(struct accel_dpdk_cryptodev_device *device, 1325 void *session) 1326 { 1327 #if RTE_VERSION >= RTE_VERSION_NUM(22, 11, 0, 0) 1328 assert(device != NULL); 1329 1330 rte_cryptodev_sym_session_free(device->cdev_id, session); 1331 #else 1332 rte_cryptodev_sym_session_free(session); 1333 #endif 1334 } 1335 1336 static void * 1337 accel_dpdk_cryptodev_key_handle_session_create(struct accel_dpdk_cryptodev_device *device, 1338 struct rte_crypto_sym_xform *cipher_xform) 1339 { 1340 void *session; 1341 1342 #if RTE_VERSION >= RTE_VERSION_NUM(22, 11, 0, 0) 1343 session = rte_cryptodev_sym_session_create(device->cdev_id, cipher_xform, g_session_mp); 1344 #else 1345 session = rte_cryptodev_sym_session_create(g_session_mp); 1346 if (!session) { 1347 return NULL; 1348 } 1349 1350 if (rte_cryptodev_sym_session_init(device->cdev_id, session, cipher_xform, g_session_mp_priv) < 0) { 1351 accel_dpdk_cryptodev_key_handle_session_free(device, session); 1352 return NULL; 1353 } 1354 #endif 1355 1356 return session; 1357 } 1358 1359 static int 1360 accel_dpdk_cryptodev_key_handle_configure(struct spdk_accel_crypto_key *key, 1361 struct accel_dpdk_cryptodev_key_handle *key_handle) 1362 { 1363 struct accel_dpdk_cryptodev_key_priv *priv = key->priv; 1364 1365 key_handle->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; 1366 key_handle->cipher_xform.cipher.iv.offset = ACCEL_DPDK_CRYPTODEV_IV_OFFSET; 1367 key_handle->cipher_xform.cipher.iv.length = ACCEL_DPDK_CRYPTODEV_IV_LENGTH; 1368 1369 switch (priv->cipher) { 1370 case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC: 1371 key_handle->cipher_xform.cipher.key.data = key->key; 1372 key_handle->cipher_xform.cipher.key.length = key->key_size; 1373 key_handle->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC; 1374 break; 1375 case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS: 1376 key_handle->cipher_xform.cipher.key.data = priv->xts_key; 1377 key_handle->cipher_xform.cipher.key.length = key->key_size + key->key2_size; 1378 key_handle->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_XTS; 1379 break; 1380 default: 1381 SPDK_ERRLOG("Invalid cipher name %s.\n", key->param.cipher); 1382 return -EINVAL; 1383 } 1384 1385 key_handle->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; 1386 key_handle->session_encrypt = accel_dpdk_cryptodev_key_handle_session_create(key_handle->device, 1387 &key_handle->cipher_xform); 1388 if (!key_handle->session_encrypt) { 1389 SPDK_ERRLOG("Failed to init encrypt session\n"); 1390 return -EINVAL; 1391 } 1392 1393 key_handle->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT; 1394 key_handle->session_decrypt = accel_dpdk_cryptodev_key_handle_session_create(key_handle->device, 1395 &key_handle->cipher_xform); 1396 if (!key_handle->session_decrypt) { 1397 SPDK_ERRLOG("Failed to init decrypt session:"); 1398 accel_dpdk_cryptodev_key_handle_session_free(key_handle->device, key_handle->session_encrypt); 1399 return -EINVAL; 1400 } 1401 1402 return 0; 1403 } 1404 1405 static int 1406 accel_dpdk_cryptodev_validate_parameters(enum accel_dpdk_cryptodev_driver_type driver, 1407 enum accel_dpdk_crypto_dev_cipher_type cipher, struct spdk_accel_crypto_key *key) 1408 { 1409 /* Check that all required parameters exist */ 1410 switch (cipher) { 1411 case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC: 1412 if (!key->key || !key->key_size) { 1413 SPDK_ERRLOG("ACCEL_DPDK_CRYPTODEV_AES_CBC requires a key\n"); 1414 return -1; 1415 } 1416 if (key->key2 || key->key2_size) { 1417 SPDK_ERRLOG("ACCEL_DPDK_CRYPTODEV_AES_CBC doesn't use key2\n"); 1418 return -1; 1419 } 1420 break; 1421 case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS: 1422 if (!key->key || !key->key_size || !key->key2 || !key->key2_size) { 1423 SPDK_ERRLOG("ACCEL_DPDK_CRYPTODEV_AES_XTS requires both key and key2\n"); 1424 return -1; 1425 } 1426 break; 1427 default: 1428 return -1; 1429 } 1430 1431 /* Check driver/cipher combinations and key lengths */ 1432 switch (cipher) { 1433 case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC: 1434 if (driver == ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI) { 1435 SPDK_ERRLOG("Driver %s only supports cipher %s\n", 1436 g_driver_names[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI], 1437 g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS]); 1438 return -1; 1439 } 1440 if (key->key_size != ACCEL_DPDK_CRYPTODEV_AES_CBC_KEY_LENGTH) { 1441 SPDK_ERRLOG("Invalid key size %zu for cipher %s, should be %d\n", key->key_size, 1442 g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC], ACCEL_DPDK_CRYPTODEV_AES_CBC_KEY_LENGTH); 1443 return -1; 1444 } 1445 break; 1446 case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS: 1447 switch (driver) { 1448 case ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI: 1449 if (key->key_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_256_BLOCK_KEY_LENGTH && 1450 key->key_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_512_BLOCK_KEY_LENGTH) { 1451 SPDK_ERRLOG("Invalid key size %zu for driver %s, cipher %s, supported %d or %d\n", 1452 key->key_size, g_driver_names[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI], 1453 g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS], 1454 ACCEL_DPDK_CRYPTODEV_AES_XTS_256_BLOCK_KEY_LENGTH, 1455 ACCEL_DPDK_CRYPTODEV_AES_XTS_512_BLOCK_KEY_LENGTH); 1456 return -1; 1457 } 1458 break; 1459 case ACCEL_DPDK_CRYPTODEV_DRIVER_QAT: 1460 case ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB: 1461 if (key->key_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_128_BLOCK_KEY_LENGTH) { 1462 SPDK_ERRLOG("Invalid key size %zu, supported %d\n", key->key_size, 1463 ACCEL_DPDK_CRYPTODEV_AES_XTS_128_BLOCK_KEY_LENGTH); 1464 return -1; 1465 } 1466 break; 1467 default: 1468 SPDK_ERRLOG("Incorrect driver type %d\n", driver); 1469 assert(0); 1470 return -1; 1471 } 1472 if (key->key2_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_TWEAK_KEY_LENGTH) { 1473 SPDK_ERRLOG("Cipher %s requires key2 size %d\n", 1474 g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC], ACCEL_DPDK_CRYPTODEV_AES_XTS_TWEAK_KEY_LENGTH); 1475 return -1; 1476 } 1477 break; 1478 } 1479 1480 return 0; 1481 } 1482 1483 static void 1484 accel_dpdk_cryptodev_key_deinit(struct spdk_accel_crypto_key *key) 1485 { 1486 struct accel_dpdk_cryptodev_key_handle *key_handle, *key_handle_tmp; 1487 struct accel_dpdk_cryptodev_key_priv *priv = key->priv; 1488 1489 TAILQ_FOREACH_SAFE(key_handle, &priv->dev_keys, link, key_handle_tmp) { 1490 accel_dpdk_cryptodev_key_handle_session_free(key_handle->device, key_handle->session_encrypt); 1491 accel_dpdk_cryptodev_key_handle_session_free(key_handle->device, key_handle->session_decrypt); 1492 TAILQ_REMOVE(&priv->dev_keys, key_handle, link); 1493 spdk_memset_s(key_handle, sizeof(*key_handle), 0, sizeof(*key_handle)); 1494 free(key_handle); 1495 } 1496 1497 if (priv->xts_key) { 1498 spdk_memset_s(priv->xts_key, key->key_size + key->key2_size, 0, key->key_size + key->key2_size); 1499 } 1500 free(priv->xts_key); 1501 free(priv); 1502 } 1503 1504 static int 1505 accel_dpdk_cryptodev_key_init(struct spdk_accel_crypto_key *key) 1506 { 1507 struct accel_dpdk_cryptodev_device *device; 1508 struct accel_dpdk_cryptodev_key_priv *priv; 1509 struct accel_dpdk_cryptodev_key_handle *key_handle; 1510 enum accel_dpdk_cryptodev_driver_type driver; 1511 enum accel_dpdk_crypto_dev_cipher_type cipher; 1512 int rc; 1513 1514 if (!key->param.cipher) { 1515 SPDK_ERRLOG("Cipher is missing\n"); 1516 return -EINVAL; 1517 } 1518 1519 if (strcmp(key->param.cipher, ACCEL_DPDK_CRYPTODEV_AES_CBC) == 0) { 1520 cipher = ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC; 1521 } else if (strcmp(key->param.cipher, ACCEL_DPDK_CRYPTODEV_AES_XTS) == 0) { 1522 cipher = ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS; 1523 } else { 1524 SPDK_ERRLOG("Unsupported cipher name %s.\n", key->param.cipher); 1525 return -EINVAL; 1526 } 1527 1528 driver = g_dpdk_cryptodev_driver; 1529 1530 if (accel_dpdk_cryptodev_validate_parameters(driver, cipher, key)) { 1531 return -EINVAL; 1532 } 1533 1534 priv = calloc(1, sizeof(*priv)); 1535 if (!priv) { 1536 SPDK_ERRLOG("Memory allocation failed\n"); 1537 return -ENOMEM; 1538 } 1539 key->priv = priv; 1540 priv->driver = driver; 1541 priv->cipher = cipher; 1542 TAILQ_INIT(&priv->dev_keys); 1543 1544 if (cipher == ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS) { 1545 /* DPDK expects the keys to be concatenated together. */ 1546 priv->xts_key = calloc(key->key_size + key->key2_size + 1, sizeof(char)); 1547 if (!priv->xts_key) { 1548 SPDK_ERRLOG("Memory allocation failed\n"); 1549 accel_dpdk_cryptodev_key_deinit(key); 1550 return -ENOMEM; 1551 } 1552 memcpy(priv->xts_key, key->key, key->key_size); 1553 memcpy(priv->xts_key + key->key_size, key->key2, key->key2_size); 1554 } 1555 1556 pthread_mutex_lock(&g_device_lock); 1557 TAILQ_FOREACH(device, &g_crypto_devices, link) { 1558 if (device->type != driver) { 1559 continue; 1560 } 1561 key_handle = calloc(1, sizeof(*key_handle)); 1562 if (!key_handle) { 1563 pthread_mutex_unlock(&g_device_lock); 1564 accel_dpdk_cryptodev_key_deinit(key); 1565 return -ENOMEM; 1566 } 1567 key_handle->device = device; 1568 TAILQ_INSERT_TAIL(&priv->dev_keys, key_handle, link); 1569 rc = accel_dpdk_cryptodev_key_handle_configure(key, key_handle); 1570 if (rc) { 1571 pthread_mutex_unlock(&g_device_lock); 1572 accel_dpdk_cryptodev_key_deinit(key); 1573 return rc; 1574 } 1575 if (driver != ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI) { 1576 /* For MLX5_PCI we need to register a key on each device since 1577 * the key is bound to a specific Protection Domain, 1578 * so don't break the loop */ 1579 break; 1580 } 1581 } 1582 pthread_mutex_unlock(&g_device_lock); 1583 1584 if (TAILQ_EMPTY(&priv->dev_keys)) { 1585 free(priv); 1586 return -ENODEV; 1587 } 1588 1589 return 0; 1590 } 1591 1592 static void 1593 accel_dpdk_cryptodev_write_config_json(struct spdk_json_write_ctx *w) 1594 { 1595 spdk_json_write_object_begin(w); 1596 spdk_json_write_named_string(w, "method", "dpdk_cryptodev_scan_accel_module"); 1597 spdk_json_write_object_end(w); 1598 1599 spdk_json_write_object_begin(w); 1600 spdk_json_write_named_string(w, "method", "dpdk_cryptodev_set_driver"); 1601 spdk_json_write_named_object_begin(w, "params"); 1602 spdk_json_write_named_string(w, "driver_name", g_driver_names[g_dpdk_cryptodev_driver]); 1603 spdk_json_write_object_end(w); 1604 spdk_json_write_object_end(w); 1605 } 1606 1607 static struct spdk_accel_module_if g_accel_dpdk_cryptodev_module = { 1608 .module_init = accel_dpdk_cryptodev_init, 1609 .module_fini = accel_dpdk_cryptodev_fini, 1610 .write_config_json = accel_dpdk_cryptodev_write_config_json, 1611 .get_ctx_size = accel_dpdk_cryptodev_ctx_size, 1612 .name = "dpdk_cryptodev", 1613 .supports_opcode = accel_dpdk_cryptodev_supports_opcode, 1614 .get_io_channel = accel_dpdk_cryptodev_get_io_channel, 1615 .submit_tasks = accel_dpdk_cryptodev_submit_tasks, 1616 .crypto_key_init = accel_dpdk_cryptodev_key_init, 1617 .crypto_key_deinit = accel_dpdk_cryptodev_key_deinit, 1618 }; 1619