xref: /spdk/test/unit/lib/util/dif.c/dif_ut.c (revision bb488d2829a9b7863daab45917dd2174905cc0ae)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk_cunit.h"
37 
38 #include "util/dif.c"
39 
40 #define DATA_PATTERN(offset)	((uint8_t)(0xAB + (offset)))
41 #define GUARD_SEED		0xCD
42 
43 static int
44 ut_data_pattern_generate(struct iovec *iovs, int iovcnt,
45 			 uint32_t block_size, uint32_t md_size, uint32_t num_blocks)
46 {
47 	struct _iov_iter iter;
48 	uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i;
49 	uint8_t *buf;
50 
51 	if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) {
52 		return -1;
53 	}
54 
55 	offset_blocks = 0;
56 	_iov_iter_init(&iter, iovs, iovcnt);
57 	data_offset = 0;
58 
59 	while (offset_blocks < num_blocks) {
60 		offset_in_block = 0;
61 		while (offset_in_block < block_size) {
62 			_iov_iter_get_buf(&iter, (void *)&buf, &buf_len);
63 			if (offset_in_block < block_size - md_size) {
64 				buf_len = spdk_min(buf_len,
65 						   block_size - md_size - offset_in_block);
66 				for (i = 0; i < buf_len; i++) {
67 					buf[i] = DATA_PATTERN(data_offset + i);
68 				}
69 				data_offset += buf_len;
70 			} else {
71 				buf_len = spdk_min(buf_len, block_size - offset_in_block);
72 				memset(buf, 0, buf_len);
73 			}
74 			_iov_iter_advance(&iter, buf_len);
75 			offset_in_block += buf_len;
76 		}
77 		offset_blocks++;
78 	}
79 
80 	return 0;
81 }
82 
83 static int
84 ut_data_pattern_verify(struct iovec *iovs, int iovcnt,
85 		       uint32_t block_size, uint32_t md_size, uint32_t num_blocks)
86 {
87 	struct _iov_iter iter;
88 	uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i;
89 	uint8_t *buf;
90 
91 	if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) {
92 		return -1;
93 	}
94 
95 	offset_blocks = 0;
96 	_iov_iter_init(&iter, iovs, iovcnt);
97 	data_offset = 0;
98 
99 	while (offset_blocks < num_blocks) {
100 		offset_in_block = 0;
101 		while (offset_in_block < block_size) {
102 			_iov_iter_get_buf(&iter, (void *)&buf, &buf_len);
103 
104 			if (offset_in_block < block_size - md_size) {
105 				buf_len = spdk_min(buf_len,
106 						   block_size - md_size - offset_in_block);
107 				for (i = 0; i < buf_len; i++) {
108 					if (buf[i] != DATA_PATTERN(data_offset + i)) {
109 						return -1;
110 					}
111 				}
112 				data_offset += buf_len;
113 			} else {
114 				buf_len = spdk_min(buf_len, block_size - offset_in_block);
115 			}
116 			_iov_iter_advance(&iter, buf_len);
117 			offset_in_block += buf_len;
118 		}
119 		offset_blocks++;
120 	}
121 
122 	return 0;
123 }
124 
125 static void
126 _iov_alloc_buf(struct iovec *iov, uint32_t len)
127 {
128 	iov->iov_base = calloc(1, len);
129 	iov->iov_len = len;
130 	SPDK_CU_ASSERT_FATAL(iov->iov_base != NULL);
131 }
132 
133 static void
134 _iov_free_buf(struct iovec *iov)
135 {
136 	free(iov->iov_base);
137 }
138 
139 static void
140 _iov_set_buf(struct iovec *iov, uint8_t *buf, uint32_t buf_len)
141 {
142 	iov->iov_base = buf;
143 	iov->iov_len = buf_len;
144 }
145 
146 static bool
147 _iov_check(struct iovec *iov, void *iov_base, uint32_t iov_len)
148 {
149 	return (iov->iov_base == iov_base && iov->iov_len == iov_len);
150 }
151 
152 static void
153 _dif_generate_and_verify(struct iovec *iov,
154 			 uint32_t block_size, uint32_t md_size, bool dif_loc,
155 			 enum spdk_dif_type dif_type, uint32_t dif_flags,
156 			 uint32_t ref_tag, uint32_t e_ref_tag,
157 			 uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag,
158 			 bool expect_pass)
159 {
160 	struct spdk_dif_ctx ctx = {};
161 	uint32_t guard_interval;
162 	uint16_t guard = 0;
163 	int rc;
164 
165 	rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1);
166 	CU_ASSERT(rc == 0);
167 
168 	guard_interval = _get_guard_interval(block_size, md_size, dif_loc, true);
169 
170 	ctx.dif_type = dif_type;
171 	ctx.dif_flags = dif_flags;
172 	ctx.init_ref_tag = ref_tag;
173 	ctx.app_tag = app_tag;
174 
175 	if (dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
176 		guard = spdk_crc16_t10dif(0, iov->iov_base, guard_interval);
177 	}
178 
179 	_dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx);
180 
181 	ctx.init_ref_tag = e_ref_tag;
182 	ctx.apptag_mask = apptag_mask;
183 	ctx.app_tag = e_app_tag;
184 
185 	rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx, NULL);
186 	CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0));
187 
188 	rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1);
189 	CU_ASSERT(rc == 0);
190 }
191 
192 static void
193 dif_generate_and_verify_test(void)
194 {
195 	struct iovec iov;
196 	uint32_t dif_flags;
197 
198 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
199 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
200 
201 	_iov_alloc_buf(&iov, 4096 + 128);
202 
203 	/* Positive cases */
204 
205 	/* The case that DIF is contained in the first 8 bytes of metadata. */
206 	_dif_generate_and_verify(&iov,
207 				 4096 + 128, 128, true,
208 				 SPDK_DIF_TYPE1, dif_flags,
209 				 22, 22,
210 				 0x22, 0xFFFF, 0x22,
211 				 true);
212 
213 	/* The case that DIF is contained in the last 8 bytes of metadata. */
214 	_dif_generate_and_verify(&iov,
215 				 4096 + 128, 128, false,
216 				 SPDK_DIF_TYPE1, dif_flags,
217 				 22, 22,
218 				 0x22, 0xFFFF, 0x22,
219 				 true);
220 
221 	/* Negative cases */
222 
223 	/* Reference tag doesn't match. */
224 	_dif_generate_and_verify(&iov,
225 				 4096 + 128, 128, false,
226 				 SPDK_DIF_TYPE1, dif_flags,
227 				 22, 23,
228 				 0x22, 0xFFFF, 0x22,
229 				 false);
230 
231 	/* Application tag doesn't match. */
232 	_dif_generate_and_verify(&iov,
233 				 4096 + 128, 128, false,
234 				 SPDK_DIF_TYPE1, dif_flags,
235 				 22, 22,
236 				 0x22, 0xFFFF, 0x23,
237 				 false);
238 
239 	_iov_free_buf(&iov);
240 }
241 
242 static void
243 dif_disable_check_test(void)
244 {
245 	struct iovec iov;
246 	uint32_t dif_flags;
247 
248 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
249 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
250 
251 	_iov_alloc_buf(&iov, 4096 + 128);
252 
253 	/* The case that DIF check is disabled when the Application Tag is 0xFFFF for
254 	 * Type 1. DIF check is disabled and pass is expected.
255 	 */
256 	_dif_generate_and_verify(&iov,
257 				 4096 + 128, 128, false,
258 				 SPDK_DIF_TYPE1, dif_flags,
259 				 22, 22,
260 				 0xFFFF, 0xFFFF, 0x22,
261 				 true);
262 
263 	/* The case that DIF check is not disabled when the Application Tag is 0xFFFF but
264 	 * the Reference Tag is not 0xFFFFFFFF for Type 3. DIF check is not disabled and
265 	 * fail is expected.
266 	 */
267 	_dif_generate_and_verify(&iov,
268 				 4096 + 128, 128, false,
269 				 SPDK_DIF_TYPE3, dif_flags,
270 				 22, 22,
271 				 0xFFFF, 0xFFFF, 0x22,
272 				 false);
273 
274 	/* The case that DIF check is disabled when the Application Tag is 0xFFFF and
275 	 * the Reference Tag is 0xFFFFFFFF for Type 3. DIF check is disabled and
276 	 * pass is expected.
277 	 */
278 	_dif_generate_and_verify(&iov,
279 				 4096 + 128, 128, false,
280 				 SPDK_DIF_TYPE3, dif_flags,
281 				 0xFFFFFFFF, 22,
282 				 0xFFFF, 0xFFFF, 0x22,
283 				 true);
284 
285 	_iov_free_buf(&iov);
286 }
287 
288 static void
289 dif_sec_512_md_0_error_test(void)
290 {
291 	struct spdk_dif_ctx ctx = {};
292 	int rc;
293 
294 	/* Metadata size is 0. */
295 	rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0);
296 	CU_ASSERT(rc != 0);
297 }
298 
299 static void
300 dif_guard_seed_test(void)
301 {
302 	struct iovec iov;
303 	struct spdk_dif_ctx ctx = {};
304 	struct spdk_dif_error err_blk = {};
305 	struct spdk_dif *dif;
306 	uint16_t guard;
307 	int rc;
308 
309 	_iov_alloc_buf(&iov, 512 + 8);
310 
311 	memset(iov.iov_base, 0, 512 + 8);
312 
313 	dif = (struct spdk_dif *)(iov.iov_base + 512);
314 
315 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
316 			       SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0);
317 	CU_ASSERT(rc == 0);
318 
319 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
320 	CU_ASSERT(rc == 0);
321 
322 	/* Guard should be zero if the block is all zero and seed is not added. */
323 	guard = from_be16(&dif->guard);
324 	CU_ASSERT(guard == 0);
325 
326 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
327 	CU_ASSERT(rc == 0);
328 
329 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
330 			       SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, GUARD_SEED);
331 	CU_ASSERT(rc == 0);
332 
333 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
334 	CU_ASSERT(rc == 0);
335 
336 	/* Guard should not be zero if the block is all zero but seed is added. */
337 	guard = from_be16(&dif->guard);
338 	CU_ASSERT(guard != 0);
339 
340 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
341 	CU_ASSERT(rc == 0);
342 
343 	_iov_free_buf(&iov);
344 }
345 
346 static void
347 dif_generate_and_verify(struct iovec *iovs, int iovcnt,
348 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
349 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
350 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
351 {
352 	struct spdk_dif_ctx ctx = {};
353 	int rc;
354 
355 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
356 	CU_ASSERT(rc == 0);
357 
358 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
359 			       init_ref_tag, apptag_mask, app_tag, GUARD_SEED);
360 	CU_ASSERT(rc == 0);
361 
362 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
363 	CU_ASSERT(rc == 0);
364 
365 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL);
366 	CU_ASSERT(rc == 0);
367 
368 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
369 	CU_ASSERT(rc == 0);
370 }
371 
372 static void
373 dif_disable_sec_512_md_8_single_iov_test(void)
374 {
375 	struct iovec iov;
376 
377 	_iov_alloc_buf(&iov, 512 + 8);
378 
379 	dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_DISABLE, 0, 0, 0, 0);
380 
381 	_iov_free_buf(&iov);
382 }
383 
384 static void
385 dif_sec_512_md_8_prchk_0_single_iov_test(void)
386 {
387 	struct iovec iov;
388 
389 	_iov_alloc_buf(&iov, 512 + 8);
390 
391 	dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
392 
393 	_iov_free_buf(&iov);
394 }
395 
396 static void
397 dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test(void)
398 {
399 	struct iovec iovs[4];
400 	int i, num_blocks;
401 
402 	num_blocks = 0;
403 
404 	for (i = 0; i < 4; i++) {
405 		_iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1));
406 		num_blocks += i + 1;
407 	}
408 
409 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
410 				0, 22, 0xFFFF, 0x22);
411 
412 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
413 				SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22);
414 
415 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
416 				SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22);
417 
418 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
419 				SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22);
420 
421 	for (i = 0; i < 4; i++) {
422 		_iov_free_buf(&iovs[i]);
423 	}
424 }
425 
426 static void
427 dif_sec_4096_md_128_prchk_7_multi_iovs_test(void)
428 {
429 	struct iovec iovs[4];
430 	int i, num_blocks;
431 	uint32_t dif_flags;
432 
433 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
434 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
435 
436 	num_blocks = 0;
437 
438 	for (i = 0; i < 4; i++) {
439 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
440 		num_blocks += i + 1;
441 	}
442 
443 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
444 				dif_flags, 22, 0xFFFF, 0x22);
445 
446 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1,
447 				dif_flags, 22, 0xFFFF, 0x22);
448 
449 	for (i = 0; i < 4; i++) {
450 		_iov_free_buf(&iovs[i]);
451 	}
452 }
453 
454 static void
455 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test(void)
456 {
457 	struct iovec iovs[2];
458 	uint32_t dif_flags;
459 
460 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
461 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
462 
463 	_iov_alloc_buf(&iovs[0], 512);
464 	_iov_alloc_buf(&iovs[1], 8);
465 
466 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
467 				dif_flags, 22, 0xFFFF, 0x22);
468 
469 	_iov_free_buf(&iovs[0]);
470 	_iov_free_buf(&iovs[1]);
471 }
472 
473 static void
474 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test(void)
475 {
476 	struct iovec iovs[2];
477 	uint32_t dif_flags;
478 
479 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
480 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
481 
482 	_iov_alloc_buf(&iovs[0], 256);
483 	_iov_alloc_buf(&iovs[1], 264);
484 
485 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
486 				dif_flags, 22, 0xFFFF, 0x22);
487 
488 	_iov_free_buf(&iovs[0]);
489 	_iov_free_buf(&iovs[1]);
490 }
491 
492 static void
493 dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test(void)
494 {
495 	struct iovec iovs[2];
496 	uint32_t dif_flags;
497 
498 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
499 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
500 
501 	_iov_alloc_buf(&iovs[0], 513);
502 	_iov_alloc_buf(&iovs[1], 7);
503 
504 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
505 				dif_flags, 22, 0xFFFF, 0x22);
506 
507 	_iov_free_buf(&iovs[0]);
508 	_iov_free_buf(&iovs[1]);
509 }
510 
511 static void
512 dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test(void)
513 {
514 	struct iovec iovs[2];
515 	uint32_t dif_flags;
516 
517 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
518 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
519 
520 	_iov_alloc_buf(&iovs[0], 515);
521 	_iov_alloc_buf(&iovs[1], 5);
522 
523 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
524 				dif_flags, 22, 0xFFFF, 0x22);
525 
526 	_iov_free_buf(&iovs[0]);
527 	_iov_free_buf(&iovs[1]);
528 }
529 
530 static void
531 dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test(void)
532 {
533 	struct iovec iovs[2];
534 	uint32_t dif_flags;
535 
536 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
537 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
538 
539 	_iov_alloc_buf(&iovs[0], 518);
540 	_iov_alloc_buf(&iovs[1], 2);
541 
542 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
543 				dif_flags, 22, 0xFFFF, 0x22);
544 
545 	_iov_free_buf(&iovs[0]);
546 	_iov_free_buf(&iovs[1]);
547 }
548 
549 static void
550 dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test(void)
551 {
552 	struct iovec iovs[9];
553 	uint32_t dif_flags;
554 	int i;
555 
556 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
557 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
558 
559 	/* data[0][255:0] */
560 	_iov_alloc_buf(&iovs[0], 256);
561 
562 	/* data[0][511:256], guard[0][0] */
563 	_iov_alloc_buf(&iovs[1], 256 + 1);
564 
565 	/* guard[0][1], apptag[0][0] */
566 	_iov_alloc_buf(&iovs[2], 1 + 1);
567 
568 	/* apptag[0][1], reftag[0][0] */
569 	_iov_alloc_buf(&iovs[3], 1 + 1);
570 
571 	/* reftag[0][3:1], data[1][255:0] */
572 	_iov_alloc_buf(&iovs[4], 3 + 256);
573 
574 	/* data[1][511:256], guard[1][0] */
575 	_iov_alloc_buf(&iovs[5], 256 + 1);
576 
577 	/* guard[1][1], apptag[1][0] */
578 	_iov_alloc_buf(&iovs[6], 1 + 1);
579 
580 	/* apptag[1][1], reftag[1][0] */
581 	_iov_alloc_buf(&iovs[7], 1 + 1);
582 
583 	/* reftag[1][3:1] */
584 	_iov_alloc_buf(&iovs[8], 3);
585 
586 	dif_generate_and_verify(iovs, 9, 512 + 8, 8, 2, false, SPDK_DIF_TYPE1, dif_flags,
587 				22, 0xFFFF, 0x22);
588 
589 	for (i = 0; i < 9; i++) {
590 		_iov_free_buf(&iovs[i]);
591 	}
592 }
593 
594 static void
595 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void)
596 {
597 	struct iovec iovs[11];
598 	uint32_t dif_flags;
599 	int i;
600 
601 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
602 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
603 
604 	/* data[0][1000:0] */
605 	_iov_alloc_buf(&iovs[0], 1000);
606 
607 	/* data[0][3095:1000], guard[0][0] */
608 	_iov_alloc_buf(&iovs[1], 3096 + 1);
609 
610 	/* guard[0][1], apptag[0][0] */
611 	_iov_alloc_buf(&iovs[2], 1 + 1);
612 
613 	/* apptag[0][1], reftag[0][0] */
614 	_iov_alloc_buf(&iovs[3], 1 + 1);
615 
616 	/* reftag[0][3:1], ignore[0][59:0] */
617 	_iov_alloc_buf(&iovs[4], 3 + 60);
618 
619 	/* ignore[119:60], data[1][3050:0] */
620 	_iov_alloc_buf(&iovs[5], 60 + 3051);
621 
622 	/* data[1][4095:3050], guard[1][0] */
623 	_iov_alloc_buf(&iovs[6], 1045 + 1);
624 
625 	/* guard[1][1], apptag[1][0] */
626 	_iov_alloc_buf(&iovs[7], 1 + 1);
627 
628 	/* apptag[1][1], reftag[1][0] */
629 	_iov_alloc_buf(&iovs[8], 1 + 1);
630 
631 	/* reftag[1][3:1], ignore[1][9:0] */
632 	_iov_alloc_buf(&iovs[9], 3 + 10);
633 
634 	/* ignore[1][127:9] */
635 	_iov_alloc_buf(&iovs[10], 118);
636 
637 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
638 				22, 0xFFFF, 0x22);
639 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
640 				22, 0xFFFF, 0x22);
641 
642 	for (i = 0; i < 11; i++) {
643 		_iov_free_buf(&iovs[i]);
644 	}
645 }
646 
647 static void
648 _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
649 			     uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
650 			     uint32_t inject_flags, bool dif_loc)
651 {
652 	struct spdk_dif_ctx ctx = {};
653 	struct spdk_dif_error err_blk = {};
654 	uint32_t inject_offset = 0, dif_flags;
655 	int rc;
656 
657 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
658 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
659 
660 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
661 	CU_ASSERT(rc == 0);
662 
663 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc,
664 			       SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88, GUARD_SEED);
665 	CU_ASSERT(rc == 0);
666 
667 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
668 	CU_ASSERT(rc == 0);
669 
670 	rc = spdk_dif_inject_error(iovs, iovcnt, num_blocks, &ctx, inject_flags, &inject_offset);
671 	CU_ASSERT(rc == 0);
672 
673 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, &err_blk);
674 	CU_ASSERT(rc != 0);
675 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
676 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
677 	} else {
678 		CU_ASSERT(inject_flags == err_blk.err_type);
679 	}
680 	CU_ASSERT(inject_offset == err_blk.err_offset);
681 
682 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
683 	CU_ASSERT((rc == 0 && (inject_flags != SPDK_DIF_DATA_ERROR)) ||
684 		  (rc != 0 && (inject_flags == SPDK_DIF_DATA_ERROR)));
685 }
686 
687 static void
688 dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
689 			    uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
690 			    uint32_t inject_flags)
691 {
692 	/* The case that DIF is contained in the first 8 bytes of metadata. */
693 	_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
694 				     inject_flags, true);
695 
696 	/* The case that DIF is contained in the last 8 bytes of metadata. */
697 	_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
698 				     inject_flags, false);
699 }
700 
701 static void
702 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
703 {
704 	struct iovec iovs[4];
705 	int i, num_blocks;
706 
707 	num_blocks = 0;
708 
709 	for (i = 0; i < 4; i++) {
710 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
711 		num_blocks += i + 1;
712 	}
713 
714 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_GUARD_ERROR);
715 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_APPTAG_ERROR);
716 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_REFTAG_ERROR);
717 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_DATA_ERROR);
718 
719 	for (i = 0; i < 4; i++) {
720 		_iov_free_buf(&iovs[i]);
721 	}
722 }
723 
724 static void
725 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test(void)
726 {
727 	struct iovec iovs[2];
728 
729 	_iov_alloc_buf(&iovs[0], 4096);
730 	_iov_alloc_buf(&iovs[1], 128);
731 
732 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
733 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
734 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
735 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
736 
737 	_iov_free_buf(&iovs[0]);
738 	_iov_free_buf(&iovs[1]);
739 }
740 
741 static void
742 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test(void)
743 {
744 	struct iovec iovs[2];
745 
746 	_iov_alloc_buf(&iovs[0], 2048);
747 	_iov_alloc_buf(&iovs[1], 2048 + 128);
748 
749 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
750 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
751 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
752 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
753 
754 	_iov_free_buf(&iovs[0]);
755 	_iov_free_buf(&iovs[1]);
756 }
757 
758 static void
759 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test(void)
760 {
761 	struct iovec iovs[2];
762 
763 	_iov_alloc_buf(&iovs[0], 4096 + 1);
764 	_iov_alloc_buf(&iovs[1], 127);
765 
766 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
767 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
768 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
769 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
770 
771 	_iov_free_buf(&iovs[0]);
772 	_iov_free_buf(&iovs[1]);
773 }
774 
775 static void
776 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(void)
777 {
778 	struct iovec iovs[2];
779 
780 	_iov_alloc_buf(&iovs[0], 4096 + 3);
781 	_iov_alloc_buf(&iovs[1], 125);
782 
783 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
784 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
785 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
786 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
787 
788 	_iov_free_buf(&iovs[0]);
789 	_iov_free_buf(&iovs[1]);
790 }
791 
792 static void
793 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(void)
794 {
795 	struct iovec iovs[2];
796 
797 	_iov_alloc_buf(&iovs[0], 4096 + 6);
798 	_iov_alloc_buf(&iovs[1], 122);
799 
800 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
801 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
802 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
803 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
804 
805 	_iov_free_buf(&iovs[0]);
806 	_iov_free_buf(&iovs[1]);
807 }
808 
809 static void
810 dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
811 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
812 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
813 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
814 {
815 	struct spdk_dif_ctx ctx = {};
816 	int rc;
817 
818 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
819 	CU_ASSERT(rc == 0);
820 
821 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
822 			       init_ref_tag, apptag_mask, app_tag, GUARD_SEED);
823 	CU_ASSERT(rc == 0);
824 
825 	rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
826 	CU_ASSERT(rc == 0);
827 
828 	rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL);
829 	CU_ASSERT(rc == 0);
830 
831 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks);
832 	CU_ASSERT(rc == 0);
833 }
834 
835 static void
836 dif_copy_sec_512_md_8_prchk_0_single_iov(void)
837 {
838 	struct iovec iov, bounce_iov;
839 
840 	_iov_alloc_buf(&iov, 512 * 4);
841 	_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
842 
843 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4,
844 				false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
845 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4,
846 				true, SPDK_DIF_TYPE1, 0, 0, 0, 0);
847 
848 	_iov_free_buf(&iov);
849 	_iov_free_buf(&bounce_iov);
850 }
851 
852 static void
853 dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
854 {
855 	struct iovec iovs[4], bounce_iov;
856 	int i, num_blocks;
857 
858 	num_blocks = 0;
859 
860 	for (i = 0; i < 4; i++) {
861 		_iov_alloc_buf(&iovs[i], 512 * (i + 1));
862 		num_blocks += i + 1;
863 	}
864 
865 	_iov_alloc_buf(&bounce_iov, (512 + 8) * num_blocks);
866 
867 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
868 				false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22);
869 
870 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
871 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22);
872 
873 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
874 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22);
875 
876 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
877 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22);
878 
879 	for (i = 0; i < 4; i++) {
880 		_iov_free_buf(&iovs[i]);
881 	}
882 	_iov_free_buf(&bounce_iov);
883 }
884 
885 static void
886 dif_copy_sec_4096_md_128_prchk_7_multi_iovs(void)
887 {
888 	struct iovec iovs[4], bounce_iov;
889 	uint32_t dif_flags;
890 	int i, num_blocks;
891 
892 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
893 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
894 
895 	num_blocks = 0;
896 
897 	for (i = 0; i < 4; i++) {
898 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
899 		num_blocks += i + 1;
900 	}
901 
902 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
903 
904 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks,
905 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
906 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks,
907 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
908 
909 	for (i = 0; i < 4; i++) {
910 		_iov_free_buf(&iovs[i]);
911 	}
912 	_iov_free_buf(&bounce_iov);
913 }
914 
915 static void
916 dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
917 {
918 	struct iovec iovs[2], bounce_iov;
919 	uint32_t dif_flags;
920 
921 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
922 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
923 
924 	_iov_alloc_buf(&iovs[0], 256);
925 	_iov_alloc_buf(&iovs[1], 256);
926 
927 	_iov_alloc_buf(&bounce_iov, 512 + 8);
928 
929 	dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 512 + 8, 8, 1,
930 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
931 
932 	_iov_free_buf(&iovs[0]);
933 	_iov_free_buf(&iovs[1]);
934 	_iov_free_buf(&bounce_iov);
935 }
936 
937 static void
938 dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
939 {
940 	struct iovec iovs[6], bounce_iov;
941 	uint32_t dif_flags;
942 	int i;
943 
944 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
945 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
946 
947 	/* data[0][255:0] */
948 	_iov_alloc_buf(&iovs[0], 256);
949 
950 	/* data[0][511:256], data[1][255:0] */
951 	_iov_alloc_buf(&iovs[1], 256 + 256);
952 
953 	/* data[1][382:256] */
954 	_iov_alloc_buf(&iovs[2], 128);
955 
956 	/* data[1][383] */
957 	_iov_alloc_buf(&iovs[3], 1);
958 
959 	/* data[1][510:384] */
960 	_iov_alloc_buf(&iovs[4], 126);
961 
962 	/* data[1][511], data[2][511:0], data[3][511:0] */
963 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
964 
965 	_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
966 
967 	dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 512 + 8, 8, 4,
968 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
969 
970 	for (i = 0; i < 6; i++) {
971 		_iov_free_buf(&iovs[i]);
972 	}
973 	_iov_free_buf(&bounce_iov);
974 }
975 
976 static void
977 _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
978 				  uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
979 				  uint32_t inject_flags, bool dif_loc)
980 {
981 	struct spdk_dif_ctx ctx = {};
982 	struct spdk_dif_error err_blk = {};
983 	uint32_t inject_offset = 0, dif_flags;
984 	int rc;
985 
986 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
987 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
988 
989 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
990 	CU_ASSERT(rc == 0);
991 
992 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags,
993 			       88, 0xFFFF, 0x88, GUARD_SEED);
994 	SPDK_CU_ASSERT_FATAL(rc == 0);
995 
996 	rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
997 	CU_ASSERT(rc == 0);
998 
999 	rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset);
1000 	CU_ASSERT(rc == 0);
1001 
1002 	rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, &err_blk);
1003 	CU_ASSERT(rc != 0);
1004 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
1005 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
1006 	} else {
1007 		CU_ASSERT(inject_flags == err_blk.err_type);
1008 	}
1009 	CU_ASSERT(inject_offset == err_blk.err_offset);
1010 }
1011 
1012 static void
1013 dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
1014 				 uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1015 				 uint32_t inject_flags)
1016 {
1017 	/* The case that DIF is contained in the first 8 bytes of metadata. */
1018 	_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
1019 					  block_size, md_size, num_blocks,
1020 					  inject_flags, true);
1021 
1022 	/* The case that DIF is contained in the last 8 bytes of metadata. */
1023 	_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
1024 					  block_size, md_size, num_blocks,
1025 					  inject_flags, false);
1026 }
1027 
1028 static void
1029 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
1030 {
1031 	struct iovec iovs[4], bounce_iov;
1032 	int i, num_blocks;
1033 
1034 	num_blocks = 0;
1035 
1036 	for (i = 0; i < 4; i++) {
1037 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1038 		num_blocks += i + 1;
1039 	}
1040 
1041 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
1042 
1043 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1044 					 num_blocks, SPDK_DIF_GUARD_ERROR);
1045 
1046 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1047 					 num_blocks, SPDK_DIF_APPTAG_ERROR);
1048 
1049 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1050 					 num_blocks, SPDK_DIF_REFTAG_ERROR);
1051 
1052 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1053 					 num_blocks, SPDK_DIF_DATA_ERROR);
1054 
1055 	for (i = 0; i < 4; i++) {
1056 		_iov_free_buf(&iovs[i]);
1057 	}
1058 	_iov_free_buf(&bounce_iov);
1059 }
1060 
1061 static void
1062 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
1063 {
1064 	struct iovec iovs[4], bounce_iov;
1065 	int i;
1066 
1067 	_iov_alloc_buf(&iovs[0], 2048);
1068 	_iov_alloc_buf(&iovs[1], 2048);
1069 	_iov_alloc_buf(&iovs[2], 1);
1070 	_iov_alloc_buf(&iovs[3], 4095);
1071 
1072 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * 2);
1073 
1074 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1075 					 2, SPDK_DIF_GUARD_ERROR);
1076 
1077 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1078 					 2, SPDK_DIF_APPTAG_ERROR);
1079 
1080 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1081 					 2, SPDK_DIF_REFTAG_ERROR);
1082 
1083 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1084 					 2, SPDK_DIF_DATA_ERROR);
1085 
1086 	for (i = 0; i < 4; i++) {
1087 		_iov_free_buf(&iovs[i]);
1088 	}
1089 	_iov_free_buf(&bounce_iov);
1090 }
1091 
1092 static void
1093 dix_sec_512_md_0_error(void)
1094 {
1095 	struct spdk_dif_ctx ctx;
1096 	int rc;
1097 
1098 	rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0);
1099 	CU_ASSERT(rc != 0);
1100 }
1101 
1102 static void
1103 dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
1104 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1105 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
1106 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
1107 {
1108 	struct spdk_dif_ctx ctx;
1109 	int rc;
1110 
1111 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
1112 	CU_ASSERT(rc == 0);
1113 
1114 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
1115 			       init_ref_tag, apptag_mask, app_tag, GUARD_SEED);
1116 	CU_ASSERT(rc == 0);
1117 
1118 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
1119 	CU_ASSERT(rc == 0);
1120 
1121 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL);
1122 	CU_ASSERT(rc == 0);
1123 
1124 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks);
1125 	CU_ASSERT(rc == 0);
1126 }
1127 
1128 static void
1129 dix_sec_512_md_8_prchk_0_single_iov(void)
1130 {
1131 	struct iovec iov, md_iov;
1132 
1133 	_iov_alloc_buf(&iov, 512 * 4);
1134 	_iov_alloc_buf(&md_iov, 8 * 4);
1135 
1136 	dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
1137 	dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0);
1138 
1139 	_iov_free_buf(&iov);
1140 	_iov_free_buf(&md_iov);
1141 }
1142 
1143 static void
1144 dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
1145 {
1146 	struct iovec iovs[4], md_iov;
1147 	int i, num_blocks;
1148 
1149 	num_blocks = 0;
1150 
1151 	for (i = 0; i < 4; i++) {
1152 		_iov_alloc_buf(&iovs[i], 512 * (i + 1));
1153 		num_blocks += i + 1;
1154 	}
1155 	_iov_alloc_buf(&md_iov, 8 * num_blocks);
1156 
1157 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1158 				0, 22, 0xFFFF, 0x22);
1159 
1160 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1161 				SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22);
1162 
1163 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1164 				SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22);
1165 
1166 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1167 				SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22);
1168 
1169 	for (i = 0; i < 4; i++) {
1170 		_iov_free_buf(&iovs[i]);
1171 	}
1172 	_iov_free_buf(&md_iov);
1173 }
1174 
1175 static void
1176 dix_sec_4096_md_128_prchk_7_multi_iovs(void)
1177 {
1178 	struct iovec iovs[4], md_iov;
1179 	uint32_t dif_flags;
1180 	int i, num_blocks;
1181 
1182 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1183 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1184 
1185 	num_blocks = 0;
1186 
1187 	for (i = 0; i < 4; i++) {
1188 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1189 		num_blocks += i + 1;
1190 	}
1191 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
1192 
1193 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
1194 				dif_flags, 22, 0xFFFF, 0x22);
1195 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
1196 				dif_flags, 22, 0xFFFF, 0x22);
1197 
1198 	for (i = 0; i < 4; i++) {
1199 		_iov_free_buf(&iovs[i]);
1200 	}
1201 	_iov_free_buf(&md_iov);
1202 }
1203 
1204 static void
1205 dix_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
1206 {
1207 	struct iovec iovs[2], md_iov;
1208 	uint32_t dif_flags;
1209 
1210 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1211 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1212 
1213 	_iov_alloc_buf(&iovs[0], 256);
1214 	_iov_alloc_buf(&iovs[1], 256);
1215 	_iov_alloc_buf(&md_iov, 8);
1216 
1217 	dix_generate_and_verify(iovs, 2, &md_iov, 512, 8, 1, false, SPDK_DIF_TYPE1,
1218 				dif_flags, 22, 0xFFFF, 0x22);
1219 
1220 	_iov_free_buf(&iovs[0]);
1221 	_iov_free_buf(&iovs[1]);
1222 	_iov_free_buf(&md_iov);
1223 }
1224 
1225 static void
1226 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
1227 {
1228 	struct iovec iovs[6], md_iov;
1229 	uint32_t dif_flags;
1230 	int i;
1231 
1232 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1233 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1234 
1235 	/* data[0][255:0] */
1236 	_iov_alloc_buf(&iovs[0], 256);
1237 
1238 	/* data[0][511:256], data[1][255:0] */
1239 	_iov_alloc_buf(&iovs[1], 256 + 256);
1240 
1241 	/* data[1][382:256] */
1242 	_iov_alloc_buf(&iovs[2], 128);
1243 
1244 	/* data[1][383] */
1245 	_iov_alloc_buf(&iovs[3], 1);
1246 
1247 	/* data[1][510:384] */
1248 	_iov_alloc_buf(&iovs[4], 126);
1249 
1250 	/* data[1][511], data[2][511:0], data[3][511:0] */
1251 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
1252 
1253 	_iov_alloc_buf(&md_iov, 8 * 4);
1254 
1255 	dix_generate_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1,
1256 				dif_flags, 22, 0xFFFF, 0x22);
1257 
1258 	for (i = 0; i < 6; i++) {
1259 		_iov_free_buf(&iovs[i]);
1260 	}
1261 	_iov_free_buf(&md_iov);
1262 }
1263 
1264 static void
1265 _dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
1266 			     uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1267 			     uint32_t inject_flags, bool dif_loc)
1268 {
1269 	struct spdk_dif_ctx ctx = {};
1270 	struct spdk_dif_error err_blk = {};
1271 	uint32_t inject_offset = 0, dif_flags;
1272 	int rc;
1273 
1274 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1275 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1276 
1277 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
1278 	CU_ASSERT(rc == 0);
1279 
1280 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags,
1281 			       88, 0xFFFF, 0x88, GUARD_SEED);
1282 	CU_ASSERT(rc == 0);
1283 
1284 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
1285 	CU_ASSERT(rc == 0);
1286 
1287 	rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset);
1288 	CU_ASSERT(rc == 0);
1289 
1290 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, &err_blk);
1291 	CU_ASSERT(rc != 0);
1292 
1293 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
1294 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
1295 	} else {
1296 		CU_ASSERT(inject_flags == err_blk.err_type);
1297 	}
1298 	CU_ASSERT(inject_offset == err_blk.err_offset);
1299 }
1300 
1301 static void
1302 dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
1303 			    uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1304 			    uint32_t inject_flags)
1305 {
1306 	/* The case that DIF is contained in the first 8 bytes of metadata. */
1307 	_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
1308 				     inject_flags, true);
1309 
1310 	/* The case that DIF is contained in the last 8 bytes of metadata. */
1311 	_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
1312 				     inject_flags, false);
1313 }
1314 
1315 static void
1316 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
1317 {
1318 	struct iovec iovs[4], md_iov;
1319 	int i, num_blocks;
1320 
1321 	num_blocks = 0;
1322 
1323 	for (i = 0; i < 4; i++) {
1324 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1325 		num_blocks += i + 1;
1326 	}
1327 
1328 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
1329 
1330 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_GUARD_ERROR);
1331 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_APPTAG_ERROR);
1332 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_REFTAG_ERROR);
1333 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_DATA_ERROR);
1334 
1335 	for (i = 0; i < 4; i++) {
1336 		_iov_free_buf(&iovs[i]);
1337 	}
1338 	_iov_free_buf(&md_iov);
1339 }
1340 
1341 static void
1342 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
1343 {
1344 	struct iovec iovs[4], md_iov;
1345 	int i;
1346 
1347 	_iov_alloc_buf(&iovs[0], 2048);
1348 	_iov_alloc_buf(&iovs[1], 2048);
1349 	_iov_alloc_buf(&iovs[2], 1);
1350 	_iov_alloc_buf(&iovs[3], 4095);
1351 
1352 	_iov_alloc_buf(&md_iov, 128 * 2);
1353 
1354 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_GUARD_ERROR);
1355 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_APPTAG_ERROR);
1356 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_REFTAG_ERROR);
1357 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_DATA_ERROR);
1358 
1359 	for (i = 0; i < 4; i++) {
1360 		_iov_free_buf(&iovs[i]);
1361 	}
1362 	_iov_free_buf(&md_iov);
1363 }
1364 
1365 static int
1366 ut_readv(uint32_t read_base, uint32_t read_len, struct iovec *iovs, int iovcnt)
1367 {
1368 	int i;
1369 	uint32_t j, offset;
1370 	uint8_t *buf;
1371 
1372 	offset = 0;
1373 	for (i = 0; i < iovcnt; i++) {
1374 		buf = iovs[i].iov_base;
1375 		for (j = 0; j < iovs[i].iov_len; j++, offset++) {
1376 			if (offset >= read_len) {
1377 				return offset;
1378 			}
1379 			buf[j] = DATA_PATTERN(read_base + offset);
1380 		}
1381 	}
1382 
1383 	return offset;
1384 }
1385 
1386 static void
1387 set_md_interleave_iovs_test(void)
1388 {
1389 	struct spdk_dif_ctx ctx = {};
1390 	struct spdk_dif_error err_blk = {};
1391 	struct iovec iov1, iov2, dif_iovs[4];
1392 	uint32_t dif_check_flags, mapped_len = 0, read_base = 0;
1393 	uint8_t *buf1, *buf2;
1394 	int rc;
1395 
1396 	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1397 			  SPDK_DIF_FLAGS_REFTAG_CHECK;
1398 
1399 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
1400 			       dif_check_flags, 22, 0xFFFF, 0x22, GUARD_SEED);
1401 	CU_ASSERT(rc == 0);
1402 
1403 	/* The first data buffer:
1404 	 * - Create iovec array to Leave a space for metadata for each block
1405 	 * - Split vectored read and so creating iovec array is done before every vectored read.
1406 	 */
1407 	buf1 = calloc(1, (4096 + 128) * 4);
1408 	SPDK_CU_ASSERT_FATAL(buf1 != NULL);
1409 	_iov_set_buf(&iov1, buf1, (4096 + 128) * 4);
1410 
1411 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4,
1412 					     0, 4096 * 4, &mapped_len, &ctx);
1413 	CU_ASSERT(rc == 4);
1414 	CU_ASSERT(mapped_len == 4096 * 4);
1415 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1, 4096) == true);
1416 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1417 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1418 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
1419 
1420 	read_base = ut_readv(0, 1024, dif_iovs, 4);
1421 	CU_ASSERT(read_base == 1024);
1422 
1423 	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 0, 1024, &ctx);
1424 	CU_ASSERT(rc == 0);
1425 
1426 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4,
1427 					     read_base, 4096 * 4, &mapped_len, &ctx);
1428 	CU_ASSERT(rc == 4);
1429 	CU_ASSERT(mapped_len == 3072 + 4096 * 3);
1430 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 1024, 3072) == true);
1431 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1432 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1433 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
1434 
1435 	read_base += ut_readv(read_base, 3071, dif_iovs, 4);
1436 	CU_ASSERT(read_base == 4095);
1437 
1438 	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 1024, 3071, &ctx);
1439 	CU_ASSERT(rc == 0);
1440 
1441 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4,
1442 					     read_base, 4096 * 4, &mapped_len, &ctx);
1443 	CU_ASSERT(rc == 4);
1444 	CU_ASSERT(mapped_len == 1 + 4096 * 3);
1445 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 4095, 1) == true);
1446 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1447 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1448 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
1449 
1450 	read_base += ut_readv(read_base, 1 + 4096 * 2 + 512, dif_iovs, 4);
1451 	CU_ASSERT(read_base == 4096 * 3 + 512);
1452 
1453 	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 4095, 1 + 4096 * 2 + 512, &ctx);
1454 	CU_ASSERT(rc == 0);
1455 
1456 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, buf1, (4096 + 128) * 4,
1457 					     read_base, 4096 * 4, &mapped_len, &ctx);
1458 	CU_ASSERT(rc == 1);
1459 	CU_ASSERT(mapped_len == 3584);
1460 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + (4096 + 128) * 3 + 512, 3584) == true);
1461 
1462 	read_base += ut_readv(read_base, 3584, dif_iovs, 1);
1463 	CU_ASSERT(read_base == 4096 * 4);
1464 
1465 	rc = spdk_dif_generate_stream(buf1, (4096 + 128) * 4, 4096 * 3 + 512, 3584, &ctx);
1466 	CU_ASSERT(rc == 0);
1467 
1468 	/* The second data buffer:
1469 	 * - Set data pattern with a space for metadata for each block.
1470 	 */
1471 	buf2 = calloc(1, (4096 + 128) * 4);
1472 	SPDK_CU_ASSERT_FATAL(buf2 != NULL);
1473 	_iov_set_buf(&iov2, buf2, (4096 + 128) * 4);
1474 
1475 	rc = ut_data_pattern_generate(&iov2, 1, 4096 + 128, 128, 4);
1476 	CU_ASSERT(rc == 0);
1477 	rc = spdk_dif_generate(&iov2, 1, 4, &ctx);
1478 	CU_ASSERT(rc == 0);
1479 
1480 	rc = spdk_dif_verify(&iov1, 1, 4, &ctx, &err_blk);
1481 	CU_ASSERT(rc == 0);
1482 
1483 	rc = spdk_dif_verify(&iov2, 1, 4, &ctx, &err_blk);
1484 	CU_ASSERT(rc == 0);
1485 
1486 	/* Compare the first and the second data buffer by byte. */
1487 	rc = memcmp(buf1, buf2, (4096 + 128) * 4);
1488 	CU_ASSERT(rc == 0);
1489 
1490 	free(buf1);
1491 	free(buf2);
1492 }
1493 
1494 static void
1495 dif_generate_stream_test(void)
1496 {
1497 	struct iovec iov;
1498 	struct spdk_dif_ctx ctx;
1499 	struct spdk_dif_error err_blk;
1500 	uint32_t dif_flags;
1501 	int rc;
1502 
1503 	_iov_alloc_buf(&iov, (512 + 8) * 5);
1504 
1505 	rc = ut_data_pattern_generate(&iov, 1, 512, 8, 5);
1506 	CU_ASSERT(rc == 0);
1507 
1508 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1509 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1510 
1511 	rc = spdk_dif_ctx_init(&ctx, 512, 8, true, false, SPDK_DIF_TYPE1, dif_flags,
1512 			       22, 0xFFFF, 0x22, GUARD_SEED);
1513 	CU_ASSERT(rc == 0);
1514 
1515 	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 0, 511, &ctx);
1516 	CU_ASSERT(rc == 0);
1517 
1518 	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 511, 1, &ctx);
1519 	CU_ASSERT(rc == 0);
1520 
1521 	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 512, 256, &ctx);
1522 	CU_ASSERT(rc == 0);
1523 
1524 	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 768, 512, &ctx);
1525 	CU_ASSERT(rc == 0);
1526 
1527 	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 1280, 1024, &ctx);
1528 	CU_ASSERT(rc == 0);
1529 
1530 	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 2304, 256, &ctx);
1531 	CU_ASSERT(rc == 0);
1532 
1533 	rc = spdk_dif_generate_stream(iov.iov_base, (512 + 8) * 5, 2560, 512, &ctx);
1534 	CU_ASSERT(rc == -ERANGE);
1535 
1536 	rc = spdk_dif_verify(&iov, 1, 5, &ctx, &err_blk);
1537 	CU_ASSERT(rc == 0);
1538 
1539 	rc = ut_data_pattern_verify(&iov, 1, 512, 8, 5);
1540 	CU_ASSERT(rc == 0);
1541 
1542 	_iov_free_buf(&iov);
1543 }
1544 
1545 int
1546 main(int argc, char **argv)
1547 {
1548 	CU_pSuite	suite = NULL;
1549 	unsigned int	num_failures;
1550 
1551 	if (CU_initialize_registry() != CUE_SUCCESS) {
1552 		return CU_get_error();
1553 	}
1554 
1555 	suite = CU_add_suite("dif", NULL, NULL);
1556 	if (suite == NULL) {
1557 		CU_cleanup_registry();
1558 		return CU_get_error();
1559 	}
1560 
1561 	if (
1562 		CU_add_test(suite, "dif_generate_and_verify_test", dif_generate_and_verify_test) == NULL ||
1563 		CU_add_test(suite, "dif_disable_check_test", dif_disable_check_test) == NULL ||
1564 		CU_add_test(suite, "dif_sec_512_md_0_error_test", dif_sec_512_md_0_error_test) == NULL ||
1565 		CU_add_test(suite, "dif_guard_seed_test", dif_guard_seed_test) == NULL ||
1566 		CU_add_test(suite, "dif_disable_sec_512_md_8_single_iov_test",
1567 			    dif_disable_sec_512_md_8_single_iov_test) == NULL ||
1568 		CU_add_test(suite, "dif_sec_512_md_8_prchk_0_single_iov_test",
1569 			    dif_sec_512_md_8_prchk_0_single_iov_test) == NULL ||
1570 		CU_add_test(suite, "dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test",
1571 			    dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test) == NULL ||
1572 		CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_test",
1573 			    dif_sec_4096_md_128_prchk_7_multi_iovs_test) == NULL ||
1574 		CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test",
1575 			    dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test) == NULL ||
1576 		CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test",
1577 			    dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test) == NULL ||
1578 		CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test",
1579 			    dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test) == NULL ||
1580 		CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test",
1581 			    dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test) == NULL ||
1582 		CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test",
1583 			    dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test) == NULL ||
1584 		CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test",
1585 			    dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test) == NULL ||
1586 		CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test",
1587 			    dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test) == NULL ||
1588 		CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
1589 			    dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
1590 		CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test",
1591 			    dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test) == NULL ||
1592 		CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test",
1593 			    dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test) == NULL ||
1594 		CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test",
1595 			    dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test) == NULL ||
1596 		CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8__multi_iovs_split_apptag_test",
1597 			    dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test) == NULL ||
1598 		CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test",
1599 			    dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test) == NULL ||
1600 		CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_single_iov",
1601 			    dif_copy_sec_512_md_8_prchk_0_single_iov) == NULL ||
1602 		CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs",
1603 			    dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL ||
1604 		CU_add_test(suite, "dif_copy_sec_4096_md_128_prchk_7_multi_iovs",
1605 			    dif_copy_sec_4096_md_128_prchk_7_multi_iovs) == NULL ||
1606 		CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data",
1607 			    dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL ||
1608 		CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits",
1609 			    dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL ||
1610 		CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
1611 			    dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
1612 		CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test",
1613 			    dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL ||
1614 		CU_add_test(suite, "dix_sec_512_md_0_error", dix_sec_512_md_0_error) == NULL ||
1615 		CU_add_test(suite, "dix_sec_512_md_8_prchk_0_single_iov",
1616 			    dix_sec_512_md_8_prchk_0_single_iov) == NULL ||
1617 		CU_add_test(suite, "dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs",
1618 			    dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL ||
1619 		CU_add_test(suite, "dix_sec_4096_md_128_prchk_7_multi_iovs",
1620 			    dix_sec_4096_md_128_prchk_7_multi_iovs) == NULL ||
1621 		CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_split_data",
1622 			    dix_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL ||
1623 		CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits",
1624 			    dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL ||
1625 		CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
1626 			    dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
1627 		CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test",
1628 			    dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL ||
1629 		CU_add_test(suite, "set_md_interleave_iovs_test", set_md_interleave_iovs_test) == NULL ||
1630 		CU_add_test(suite, "dif_generate_stream_test", dif_generate_stream_test) == NULL
1631 	) {
1632 		CU_cleanup_registry();
1633 		return CU_get_error();
1634 	}
1635 
1636 	CU_basic_set_mode(CU_BRM_VERBOSE);
1637 
1638 	CU_basic_run_tests();
1639 
1640 	num_failures = CU_get_number_of_failures();
1641 	CU_cleanup_registry();
1642 
1643 	return num_failures;
1644 }
1645