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