xref: /spdk/test/unit/lib/bdev/crypto.c/crypto_ut.c (revision 8da5783b52e9adce5a564997cd6e4a393831fdd5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES.
4  *   All rights reserved.
5  */
6 
7 #include "spdk_cunit.h"
8 
9 #include "common/lib/ut_multithread.c"
10 #include "spdk_internal/mock.h"
11 #include "thread/thread_internal.h"
12 #include "unit/lib/json_mock.c"
13 
14 #include <rte_crypto.h>
15 #include <rte_cryptodev.h>
16 #include <rte_version.h>
17 
18 unsigned ut_rte_crypto_op_bulk_alloc;
19 int ut_rte_crypto_op_attach_sym_session = 0;
20 #define MOCK_INFO_GET_1QP_AESNI 0
21 #define MOCK_INFO_GET_1QP_QAT 1
22 #define MOCK_INFO_GET_1QP_MLX5 2
23 #define MOCK_INFO_GET_1QP_BOGUS_PMD 3
24 int ut_rte_cryptodev_info_get = 0;
25 bool ut_rte_cryptodev_info_get_mocked = false;
26 
27 #include "bdev/crypto/vbdev_crypto.c"
28 
29 /* SPDK stubs */
30 DEFINE_STUB(spdk_bdev_queue_io_wait, int, (struct spdk_bdev *bdev, struct spdk_io_channel *ch,
31 		struct spdk_bdev_io_wait_entry *entry), 0);
32 DEFINE_STUB_V(spdk_bdev_module_list_add, (struct spdk_bdev_module *bdev_module));
33 DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *g_bdev_io));
34 DEFINE_STUB_V(spdk_bdev_io_put_aux_buf, (struct spdk_bdev_io *bdev_io, void *aux_buf));
35 DEFINE_STUB(spdk_bdev_io_type_supported, bool, (struct spdk_bdev *bdev,
36 		enum spdk_bdev_io_type io_type), 0);
37 DEFINE_STUB_V(spdk_bdev_module_release_bdev, (struct spdk_bdev *bdev));
38 DEFINE_STUB_V(spdk_bdev_close, (struct spdk_bdev_desc *desc));
39 DEFINE_STUB(spdk_bdev_get_name, const char *, (const struct spdk_bdev *bdev), 0);
40 DEFINE_STUB(spdk_bdev_get_buf_align, size_t, (const struct spdk_bdev *bdev), 64);
41 DEFINE_STUB(spdk_bdev_get_io_channel, struct spdk_io_channel *, (struct spdk_bdev_desc *desc), 0);
42 DEFINE_STUB_V(spdk_bdev_unregister, (struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn,
43 				     void *cb_arg));
44 DEFINE_STUB(spdk_bdev_unregister_by_name, int, (const char *bdev_name,
45 		struct spdk_bdev_module *module,
46 		spdk_bdev_unregister_cb cb_fn, void *cb_arg), 0);
47 DEFINE_STUB(spdk_bdev_open_ext, int, (const char *bdev_name, bool write,
48 				      spdk_bdev_event_cb_t event_cb,
49 				      void *event_ctx, struct spdk_bdev_desc **_desc), 0);
50 DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *, (struct spdk_bdev_desc *desc), NULL);
51 DEFINE_STUB(spdk_bdev_module_claim_bdev, int, (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
52 		struct spdk_bdev_module *module), 0);
53 DEFINE_STUB_V(spdk_bdev_module_examine_done, (struct spdk_bdev_module *module));
54 DEFINE_STUB(spdk_bdev_register, int, (struct spdk_bdev *vbdev), 0);
55 DEFINE_STUB_V(spdk_bdev_destruct_done, (struct spdk_bdev *bdev, int bdeverrno));
56 
57 DEFINE_STUB(spdk_accel_crypto_key_destroy, int, (struct spdk_accel_crypto_key *key), 0);
58 
59 /* global vars and setup/cleanup functions used for all test functions */
60 struct spdk_bdev_io *g_bdev_io;
61 struct crypto_bdev_io *g_io_ctx;
62 struct crypto_io_channel *g_crypto_ch;
63 struct spdk_io_channel *g_io_ch;
64 struct vbdev_crypto g_crypto_bdev;
65 struct vbdev_crypto_opts g_crypto_bdev_opts;
66 
67 void
68 spdk_bdev_io_get_aux_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_aux_buf_cb cb)
69 {
70 	cb(g_io_ch, g_bdev_io, (void *)0xDEADBEEF);
71 }
72 
73 void
74 spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, uint64_t len)
75 {
76 	cb(g_io_ch, g_bdev_io, true);
77 }
78 
79 struct ut_vbdev_crypto_bdev_cpl_args {
80 	spdk_bdev_io_completion_cb cb_fn;
81 	struct spdk_bdev_io *bdev_io;
82 	void *cb_arg;
83 	bool result;
84 };
85 
86 static void
87 _ut_vbdev_crypto_bdev_cpl(void *arg)
88 {
89 	struct ut_vbdev_crypto_bdev_cpl_args *cpl_args = arg;
90 
91 	cpl_args->cb_fn(cpl_args->bdev_io, cpl_args->result, cpl_args->cb_arg);
92 	free(cpl_args);
93 }
94 
95 static void
96 ut_vbdev_crypto_bdev_cpl(spdk_bdev_io_completion_cb cb_fn, struct spdk_bdev_io *bdev_io,
97 			 bool result, void *cb_arg)
98 {
99 	struct ut_vbdev_crypto_bdev_cpl_args *cpl_args = calloc(1, sizeof(*cpl_args));
100 
101 	SPDK_CU_ASSERT_FATAL(cpl_args);
102 	cpl_args->cb_fn = cb_fn;
103 	cpl_args->bdev_io = bdev_io;
104 	cpl_args->result = result;
105 	cpl_args->cb_arg = cb_arg;
106 
107 	spdk_thread_send_msg(spdk_get_thread(), _ut_vbdev_crypto_bdev_cpl, cpl_args);
108 }
109 
110 /* Mock these functions to call the callback and then return the value we require */
111 DEFINE_RETURN_MOCK(spdk_bdev_readv_blocks, int);
112 int
113 spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
114 		       struct iovec *iov, int iovcnt,
115 		       uint64_t offset_blocks, uint64_t num_blocks,
116 		       spdk_bdev_io_completion_cb cb, void *cb_arg)
117 {
118 	HANDLE_RETURN_MOCK(spdk_bdev_readv_blocks);
119 	ut_vbdev_crypto_bdev_cpl(cb, g_bdev_io, !ut_spdk_bdev_readv_blocks, cb_arg);
120 	return 0;
121 }
122 
123 DEFINE_RETURN_MOCK(spdk_bdev_writev_blocks, int);
124 int
125 spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
126 			struct iovec *iov, int iovcnt,
127 			uint64_t offset_blocks, uint64_t num_blocks,
128 			spdk_bdev_io_completion_cb cb, void *cb_arg)
129 {
130 	HANDLE_RETURN_MOCK(spdk_bdev_writev_blocks);
131 	ut_vbdev_crypto_bdev_cpl(cb, g_bdev_io, !ut_spdk_bdev_writev_blocks, cb_arg);
132 	return 0;
133 }
134 
135 DEFINE_RETURN_MOCK(spdk_bdev_unmap_blocks, int);
136 int
137 spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
138 		       uint64_t offset_blocks, uint64_t num_blocks,
139 		       spdk_bdev_io_completion_cb cb, void *cb_arg)
140 {
141 	HANDLE_RETURN_MOCK(spdk_bdev_unmap_blocks);
142 	ut_vbdev_crypto_bdev_cpl(cb, g_bdev_io, !ut_spdk_bdev_unmap_blocks, cb_arg);
143 	return 0;
144 }
145 
146 DEFINE_RETURN_MOCK(spdk_bdev_flush_blocks, int);
147 int
148 spdk_bdev_flush_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
149 		       uint64_t offset_blocks, uint64_t num_blocks, spdk_bdev_io_completion_cb cb,
150 		       void *cb_arg)
151 {
152 	HANDLE_RETURN_MOCK(spdk_bdev_flush_blocks);
153 	ut_vbdev_crypto_bdev_cpl(cb, g_bdev_io, !ut_spdk_bdev_flush_blocks, cb_arg);
154 	return 0;
155 }
156 
157 DEFINE_RETURN_MOCK(spdk_bdev_reset, int);
158 int
159 spdk_bdev_reset(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
160 		spdk_bdev_io_completion_cb cb, void *cb_arg)
161 {
162 	HANDLE_RETURN_MOCK(spdk_bdev_reset);
163 	ut_vbdev_crypto_bdev_cpl(cb, g_bdev_io, !ut_spdk_bdev_reset, cb_arg);
164 	return 0;
165 }
166 
167 bool g_completion_called = false;
168 void
169 spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status)
170 {
171 	bdev_io->internal.status = status;
172 	g_completion_called = true;
173 }
174 
175 struct ut_vbdev_crypto_accel_cpl_args {
176 	spdk_accel_completion_cb cb_fn;
177 	void *cb_arg;
178 	int rc;
179 };
180 
181 static void
182 _vbdev_crypto_ut_accel_cpl(void *arg)
183 {
184 	struct ut_vbdev_crypto_accel_cpl_args *cpl_args = arg;
185 
186 	cpl_args->cb_fn(cpl_args->cb_arg, cpl_args->rc);
187 	free(cpl_args);
188 }
189 
190 static void
191 vbdev_crypto_ut_accel_cpl(spdk_accel_completion_cb cb_fn, void *cb_arg, int rc)
192 {
193 	struct ut_vbdev_crypto_accel_cpl_args *cpl_args = calloc(1, sizeof(*cpl_args));
194 
195 	SPDK_CU_ASSERT_FATAL(cpl_args);
196 	cpl_args->cb_fn = cb_fn;
197 	cpl_args->cb_arg = cb_arg;
198 	cpl_args->rc = rc;
199 
200 	spdk_thread_send_msg(spdk_get_thread(), _vbdev_crypto_ut_accel_cpl, cpl_args);
201 }
202 
203 DEFINE_RETURN_MOCK(spdk_accel_submit_encrypt, int);
204 int ut_spdk_accel_submit_encrypt_cb_rc = 0;
205 int
206 spdk_accel_submit_encrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
207 			  struct iovec *dst_iovs, uint32_t dst_iovcnt,
208 			  struct iovec *src_iovs, uint32_t src_iovcnt,
209 			  uint64_t iv, uint32_t block_size, int flags,
210 			  spdk_accel_completion_cb cb_fn, void *cb_arg)
211 {
212 	HANDLE_RETURN_MOCK(spdk_accel_submit_encrypt);
213 	/* We must not call cb_fn immediately */
214 	vbdev_crypto_ut_accel_cpl(cb_fn, cb_arg, ut_spdk_accel_submit_encrypt_cb_rc);
215 
216 	return 0;
217 }
218 
219 int ut_spdk_accel_submit_decrypt_cb_rc;
220 DEFINE_RETURN_MOCK(spdk_accel_submit_decrypt, int);
221 int
222 spdk_accel_submit_decrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
223 			  struct iovec *dst_iovs, uint32_t dst_iovcnt,
224 			  struct iovec *src_iovs, uint32_t src_iovcnt,
225 			  uint64_t iv, uint32_t block_size, int flags,
226 			  spdk_accel_completion_cb cb_fn, void *cb_arg)
227 {
228 	HANDLE_RETURN_MOCK(spdk_accel_submit_decrypt);
229 	/* We must not call cb_fn immediately */
230 	vbdev_crypto_ut_accel_cpl(cb_fn, cb_arg, ut_spdk_accel_submit_decrypt_cb_rc);
231 
232 	return 0;
233 }
234 
235 struct spdk_io_channel *spdk_accel_get_io_channel(void)
236 {
237 	return (struct spdk_io_channel *)0xfeedbeef;
238 }
239 
240 /* Global setup for all tests that share a bunch of preparation... */
241 static int
242 test_setup(void)
243 {
244 	/* Prepare essential variables for test routines */
245 	g_bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct crypto_bdev_io));
246 	g_bdev_io->u.bdev.iovs = calloc(1, sizeof(struct iovec) * 128);
247 	g_bdev_io->bdev = &g_crypto_bdev.crypto_bdev;
248 	g_io_ch = calloc(1, sizeof(struct spdk_io_channel) + sizeof(struct crypto_io_channel));
249 	g_crypto_ch = (struct crypto_io_channel *)spdk_io_channel_get_ctx(g_io_ch);
250 	g_io_ctx = (struct crypto_bdev_io *)g_bdev_io->driver_ctx;
251 	memset(&g_crypto_bdev, 0, sizeof(struct vbdev_crypto));
252 	memset(&g_crypto_bdev_opts, 0, sizeof(struct vbdev_crypto_opts));
253 	g_crypto_bdev.crypto_bdev.blocklen = 512;
254 	g_io_ctx->crypto_ch = g_crypto_ch;
255 	g_io_ctx->crypto_bdev = &g_crypto_bdev;
256 	g_io_ctx->crypto_bdev->opts = &g_crypto_bdev_opts;
257 	TAILQ_INIT(&g_crypto_ch->in_accel_fw);
258 
259 	return 0;
260 }
261 
262 /* Global teardown for all tests */
263 static int
264 test_cleanup(void)
265 {
266 	free(g_bdev_io->u.bdev.iovs);
267 	free(g_bdev_io);
268 	free(g_io_ch);
269 	return 0;
270 }
271 
272 static void
273 test_error_paths(void)
274 {
275 	g_crypto_bdev.crypto_bdev.blocklen = 512;
276 
277 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
278 	g_bdev_io->u.bdev.iovcnt = 1;
279 	g_bdev_io->u.bdev.num_blocks = 1;
280 	g_bdev_io->u.bdev.iovs[0].iov_len = 512;
281 	g_bdev_io->u.bdev.iovs[0].iov_base = (void *)0xDEADBEEF;
282 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
283 
284 	/* test error returned by accel fw */
285 	MOCK_SET(spdk_accel_submit_encrypt, -ENOMEM);
286 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
287 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
288 	CU_ASSERT(g_io_ctx->bdev_io_wait.bdev == &g_crypto_bdev.crypto_bdev);
289 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_fn == vbdev_crypto_resubmit_io);
290 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_arg == g_bdev_io);
291 	CU_ASSERT(g_io_ctx->resubmit_state == CRYPTO_IO_NEW);
292 	memset(&g_io_ctx->bdev_io_wait, 0, sizeof(g_io_ctx->bdev_io_wait));
293 
294 	MOCK_SET(spdk_accel_submit_encrypt, -EINVAL);
295 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
296 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
297 	MOCK_CLEAR(spdk_accel_submit_encrypt);
298 
299 	/* Test error returned in accel cpl cb */
300 	ut_spdk_accel_submit_encrypt_cb_rc = -EINVAL;
301 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
302 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
303 	poll_threads();
304 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
305 	ut_spdk_accel_submit_encrypt_cb_rc = 0;
306 
307 	/* Test error returned from bdev */
308 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
309 	MOCK_SET(spdk_bdev_writev_blocks, -ENOMEM);
310 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
311 	poll_threads();
312 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
313 	CU_ASSERT(g_io_ctx->bdev_io_wait.bdev == &g_crypto_bdev.crypto_bdev);
314 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_fn == vbdev_crypto_resubmit_io);
315 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_arg == g_bdev_io);
316 	CU_ASSERT(g_io_ctx->resubmit_state == CRYPTO_IO_ENCRYPT_DONE);
317 	memset(&g_io_ctx->bdev_io_wait, 0, sizeof(g_io_ctx->bdev_io_wait));
318 	MOCK_CLEAR(spdk_bdev_readv_blocks);
319 
320 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
321 	MOCK_SET(spdk_bdev_writev_blocks, -EINVAL);
322 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
323 	poll_threads();
324 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
325 	MOCK_CLEAR(spdk_bdev_writev_blocks);
326 
327 	/* Test error returned in bdev cpl */
328 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
329 	ut_spdk_bdev_writev_blocks = -EINVAL;
330 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
331 	poll_threads();
332 	poll_threads();
333 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
334 	ut_spdk_bdev_writev_blocks = 0;
335 
336 	/* the same for read path */
337 	/* Test error returned from bdev */
338 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_READ;
339 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
340 
341 	MOCK_SET(spdk_bdev_readv_blocks, -ENOMEM);
342 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
343 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
344 	CU_ASSERT(g_io_ctx->bdev_io_wait.bdev == &g_crypto_bdev.crypto_bdev);
345 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_fn == vbdev_crypto_resubmit_io);
346 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_arg == g_bdev_io);
347 	CU_ASSERT(g_io_ctx->resubmit_state == CRYPTO_IO_NEW);
348 	memset(&g_io_ctx->bdev_io_wait, 0, sizeof(g_io_ctx->bdev_io_wait));
349 	MOCK_CLEAR(spdk_bdev_readv_blocks);
350 
351 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
352 	MOCK_SET(spdk_bdev_readv_blocks, -EINVAL);
353 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
354 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
355 	MOCK_CLEAR(spdk_bdev_readv_blocks);
356 
357 	/* Test error returned in bdev cpl */
358 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
359 	ut_spdk_bdev_readv_blocks = -EINVAL;
360 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
361 	poll_threads();
362 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
363 	ut_spdk_bdev_readv_blocks = 0;
364 
365 	/* test error returned by accel fw */
366 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
367 	MOCK_SET(spdk_accel_submit_decrypt, -ENOMEM);
368 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
369 	poll_threads();
370 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
371 	CU_ASSERT(g_io_ctx->bdev_io_wait.bdev == &g_crypto_bdev.crypto_bdev);
372 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_fn == vbdev_crypto_resubmit_io);
373 	CU_ASSERT(g_io_ctx->bdev_io_wait.cb_arg == g_bdev_io);
374 	CU_ASSERT(g_io_ctx->resubmit_state == CRYPTO_IO_READ_DONE);
375 	memset(&g_io_ctx->bdev_io_wait, 0, sizeof(g_io_ctx->bdev_io_wait));
376 	MOCK_CLEAR(spdk_accel_submit_decrypt);
377 
378 	/* test error returned in accel cpl */
379 	ut_spdk_accel_submit_decrypt_cb_rc = -EINVAL;
380 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
381 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
382 	poll_threads();
383 	poll_threads();
384 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
385 	ut_spdk_accel_submit_decrypt_cb_rc = 0;
386 
387 }
388 
389 static void
390 test_simple_write(void)
391 {
392 	/* Single element block size write */
393 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
394 	g_bdev_io->u.bdev.iovcnt = 1;
395 	g_bdev_io->u.bdev.num_blocks = 1;
396 	g_bdev_io->u.bdev.offset_blocks = 0;
397 	g_bdev_io->u.bdev.iovs[0].iov_len = 512;
398 	g_bdev_io->u.bdev.iovs[0].iov_base = &test_simple_write;
399 	g_crypto_bdev.crypto_bdev.blocklen = 512;
400 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
401 
402 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
403 	/* 1st poll to trigger accel completions, 2nd for bdev */
404 	poll_threads();
405 	poll_threads();
406 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
407 	CU_ASSERT(g_io_ctx->aux_buf_iov.iov_len == 512);
408 	CU_ASSERT(g_io_ctx->aux_buf_iov.iov_base != NULL);
409 	CU_ASSERT(g_io_ctx->aux_offset_blocks == 0);
410 	CU_ASSERT(g_io_ctx->aux_num_blocks == 1);
411 }
412 
413 static void
414 test_simple_read(void)
415 {
416 	/* Single element block size read */
417 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
418 	g_bdev_io->u.bdev.iovcnt = 1;
419 	g_bdev_io->u.bdev.num_blocks = 1;
420 	g_bdev_io->u.bdev.iovs[0].iov_len = 512;
421 	g_bdev_io->u.bdev.iovs[0].iov_base = &test_simple_read;
422 	g_crypto_bdev.crypto_bdev.blocklen = 512;
423 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_READ;
424 
425 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
426 	/* 1st poll to trigger dev completions, 2nd for accel */
427 	poll_threads();
428 	poll_threads();
429 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
430 }
431 
432 static void
433 test_passthru(void)
434 {
435 	/* Make sure these follow our completion callback, test success & fail. */
436 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_UNMAP;
437 	MOCK_CLEAR(spdk_bdev_unmap_blocks);
438 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
439 	poll_threads();
440 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
441 	MOCK_SET(spdk_bdev_unmap_blocks, -EINVAL);
442 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
443 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
444 	MOCK_CLEAR(spdk_bdev_unmap_blocks);
445 
446 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_FLUSH;
447 	MOCK_CLEAR(spdk_bdev_flush_blocks);
448 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
449 	poll_threads();
450 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
451 	MOCK_SET(spdk_bdev_flush_blocks, -EINVAL);
452 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
453 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
454 	MOCK_CLEAR(spdk_bdev_flush_blocks);
455 
456 	/* We should never get a WZ command, we report that we don't support it. */
457 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE_ZEROES;
458 	vbdev_crypto_submit_request(g_io_ch, g_bdev_io);
459 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
460 }
461 
462 static void
463 test_reset(void)
464 {
465 	/* TODO: There are a few different ways to do this given that
466 	 * the code uses spdk_for_each_channel() to implement reset
467 	 * handling. Submitting w/o UT for this function for now and
468 	 * will follow up with something shortly.
469 	 */
470 }
471 
472 static void
473 test_crypto_op_complete(void)
474 {
475 	/* Make sure completion code respects failure. */
476 	g_completion_called = false;
477 	_crypto_operation_complete(g_bdev_io, -1);
478 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
479 	CU_ASSERT(g_completion_called == true);
480 
481 	/* Test read completion. */
482 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
483 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_READ;
484 	g_completion_called = false;
485 	_crypto_operation_complete(g_bdev_io, 0);
486 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
487 	CU_ASSERT(g_completion_called == true);
488 
489 	/* Test write completion success. */
490 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
491 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
492 	g_completion_called = false;
493 	MOCK_CLEAR(spdk_bdev_writev_blocks);
494 	_crypto_operation_complete(g_bdev_io, 0);
495 	poll_threads();
496 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS);
497 	CU_ASSERT(g_completion_called == true);
498 
499 	/* Test write completion failed. */
500 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
501 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_WRITE;
502 	g_completion_called = false;
503 	MOCK_SET(spdk_bdev_writev_blocks, -EINVAL);
504 	_crypto_operation_complete(g_bdev_io, 0);
505 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
506 	CU_ASSERT(g_completion_called == true);
507 	MOCK_CLEAR(spdk_bdev_writev_blocks);
508 
509 	/* Test bogus type for this completion. */
510 	g_bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
511 	g_bdev_io->type = SPDK_BDEV_IO_TYPE_RESET;
512 	g_completion_called = false;
513 	_crypto_operation_complete(g_bdev_io, 0);
514 	CU_ASSERT(g_bdev_io->internal.status == SPDK_BDEV_IO_STATUS_FAILED);
515 	CU_ASSERT(g_completion_called == true);
516 }
517 
518 static void
519 test_supported_io(void)
520 {
521 	void *ctx = NULL;
522 	bool rc = true;
523 
524 	/* Make sure we always report false to WZ, we need the bdev layer to
525 	 * send real 0's so we can encrypt/decrypt them.
526 	 */
527 	rc = vbdev_crypto_io_type_supported(ctx, SPDK_BDEV_IO_TYPE_WRITE_ZEROES);
528 	CU_ASSERT(rc == false);
529 }
530 int
531 main(int argc, char **argv)
532 {
533 	CU_pSuite	suite = NULL;
534 	unsigned int	num_failures;
535 
536 	CU_set_error_action(CUEA_ABORT);
537 	CU_initialize_registry();
538 
539 	suite = CU_add_suite("crypto", test_setup, test_cleanup);
540 	CU_ADD_TEST(suite, test_error_paths);
541 	CU_ADD_TEST(suite, test_simple_write);
542 	CU_ADD_TEST(suite, test_simple_read);
543 	CU_ADD_TEST(suite, test_passthru);
544 	CU_ADD_TEST(suite, test_crypto_op_complete);
545 	CU_ADD_TEST(suite, test_supported_io);
546 	CU_ADD_TEST(suite, test_reset);
547 
548 	allocate_threads(1);
549 	set_thread(0);
550 
551 	CU_basic_set_mode(CU_BRM_VERBOSE);
552 	CU_basic_run_tests();
553 
554 	free_threads();
555 
556 	num_failures = CU_get_number_of_failures();
557 	CU_cleanup_registry();
558 	return num_failures;
559 }
560