xref: /spdk/module/accel/dpdk_cryptodev/accel_dpdk_cryptodev.c (revision a1dfa7ec92a6c49538482c8bb73f0b1ce040441f)
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