xref: /spdk/test/unit/lib/util/dif.c/dif_ut.c (revision 0ed85362c8132a2d1927757fbcade66b6660d26a)
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 _dif_sgl sgl;
48 	uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i;
49 	uint8_t *buf;
50 
51 	_dif_sgl_init(&sgl, iovs, iovcnt);
52 
53 	if (!_dif_sgl_is_valid(&sgl, block_size * num_blocks)) {
54 		return -1;
55 	}
56 
57 	offset_blocks = 0;
58 	data_offset = 0;
59 
60 	while (offset_blocks < num_blocks) {
61 		offset_in_block = 0;
62 		while (offset_in_block < block_size) {
63 			_dif_sgl_get_buf(&sgl, (void *)&buf, &buf_len);
64 			if (offset_in_block < block_size - md_size) {
65 				buf_len = spdk_min(buf_len,
66 						   block_size - md_size - offset_in_block);
67 				for (i = 0; i < buf_len; i++) {
68 					buf[i] = DATA_PATTERN(data_offset + i);
69 				}
70 				data_offset += buf_len;
71 			} else {
72 				buf_len = spdk_min(buf_len, block_size - offset_in_block);
73 				memset(buf, 0, buf_len);
74 			}
75 			_dif_sgl_advance(&sgl, buf_len);
76 			offset_in_block += buf_len;
77 		}
78 		offset_blocks++;
79 	}
80 
81 	return 0;
82 }
83 
84 static int
85 ut_data_pattern_verify(struct iovec *iovs, int iovcnt,
86 		       uint32_t block_size, uint32_t md_size, uint32_t num_blocks)
87 {
88 	struct _dif_sgl sgl;
89 	uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i;
90 	uint8_t *buf;
91 
92 	_dif_sgl_init(&sgl, iovs, iovcnt);
93 
94 	if (!_dif_sgl_is_valid(&sgl, block_size * num_blocks)) {
95 		return -1;
96 	}
97 
98 	offset_blocks = 0;
99 	data_offset = 0;
100 
101 	while (offset_blocks < num_blocks) {
102 		offset_in_block = 0;
103 		while (offset_in_block < block_size) {
104 			_dif_sgl_get_buf(&sgl, (void *)&buf, &buf_len);
105 
106 			if (offset_in_block < block_size - md_size) {
107 				buf_len = spdk_min(buf_len,
108 						   block_size - md_size - offset_in_block);
109 				for (i = 0; i < buf_len; i++) {
110 					if (buf[i] != DATA_PATTERN(data_offset + i)) {
111 						return -1;
112 					}
113 				}
114 				data_offset += buf_len;
115 			} else {
116 				buf_len = spdk_min(buf_len, block_size - offset_in_block);
117 			}
118 			_dif_sgl_advance(&sgl, buf_len);
119 			offset_in_block += buf_len;
120 		}
121 		offset_blocks++;
122 	}
123 
124 	return 0;
125 }
126 
127 static void
128 _iov_alloc_buf(struct iovec *iov, uint32_t len)
129 {
130 	iov->iov_base = calloc(1, len);
131 	iov->iov_len = len;
132 	SPDK_CU_ASSERT_FATAL(iov->iov_base != NULL);
133 }
134 
135 static void
136 _iov_free_buf(struct iovec *iov)
137 {
138 	free(iov->iov_base);
139 }
140 
141 static void
142 _iov_set_buf(struct iovec *iov, uint8_t *buf, uint32_t buf_len)
143 {
144 	iov->iov_base = buf;
145 	iov->iov_len = buf_len;
146 }
147 
148 static bool
149 _iov_check(struct iovec *iov, void *iov_base, uint32_t iov_len)
150 {
151 	return (iov->iov_base == iov_base && iov->iov_len == iov_len);
152 }
153 
154 static void
155 _dif_generate_and_verify(struct iovec *iov,
156 			 uint32_t block_size, uint32_t md_size, bool dif_loc,
157 			 enum spdk_dif_type dif_type, uint32_t dif_flags,
158 			 uint32_t ref_tag, uint32_t e_ref_tag,
159 			 uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag,
160 			 bool expect_pass)
161 {
162 	struct spdk_dif_ctx ctx = {};
163 	uint32_t guard_interval;
164 	uint16_t guard = 0;
165 	int rc;
166 
167 	rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1);
168 	CU_ASSERT(rc == 0);
169 
170 	guard_interval = _get_guard_interval(block_size, md_size, dif_loc, true);
171 
172 	ctx.dif_type = dif_type;
173 	ctx.dif_flags = dif_flags;
174 	ctx.init_ref_tag = ref_tag;
175 	ctx.app_tag = app_tag;
176 
177 	if (dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
178 		guard = spdk_crc16_t10dif(0, iov->iov_base, guard_interval);
179 	}
180 
181 	_dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx);
182 
183 	ctx.init_ref_tag = e_ref_tag;
184 	ctx.apptag_mask = apptag_mask;
185 	ctx.app_tag = e_app_tag;
186 
187 	rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx, NULL);
188 	CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0));
189 
190 	rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1);
191 	CU_ASSERT(rc == 0);
192 }
193 
194 static void
195 dif_generate_and_verify_test(void)
196 {
197 	struct iovec iov;
198 	uint32_t dif_flags;
199 
200 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
201 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
202 
203 	_iov_alloc_buf(&iov, 4096 + 128);
204 
205 	/* Positive cases */
206 
207 	/* The case that DIF is contained in the first 8 bytes of metadata. */
208 	_dif_generate_and_verify(&iov,
209 				 4096 + 128, 128, true,
210 				 SPDK_DIF_TYPE1, dif_flags,
211 				 22, 22,
212 				 0x22, 0xFFFF, 0x22,
213 				 true);
214 
215 	/* The case that DIF is contained in the last 8 bytes of metadata. */
216 	_dif_generate_and_verify(&iov,
217 				 4096 + 128, 128, false,
218 				 SPDK_DIF_TYPE1, dif_flags,
219 				 22, 22,
220 				 0x22, 0xFFFF, 0x22,
221 				 true);
222 
223 	/* Negative cases */
224 
225 	/* Reference tag doesn't match. */
226 	_dif_generate_and_verify(&iov,
227 				 4096 + 128, 128, false,
228 				 SPDK_DIF_TYPE1, dif_flags,
229 				 22, 23,
230 				 0x22, 0xFFFF, 0x22,
231 				 false);
232 
233 	/* Application tag doesn't match. */
234 	_dif_generate_and_verify(&iov,
235 				 4096 + 128, 128, false,
236 				 SPDK_DIF_TYPE1, dif_flags,
237 				 22, 22,
238 				 0x22, 0xFFFF, 0x23,
239 				 false);
240 
241 	_iov_free_buf(&iov);
242 }
243 
244 static void
245 dif_disable_check_test(void)
246 {
247 	struct iovec iov;
248 	uint32_t dif_flags;
249 
250 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
251 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
252 
253 	_iov_alloc_buf(&iov, 4096 + 128);
254 
255 	/* The case that DIF check is disabled when the Application Tag is 0xFFFF for
256 	 * Type 1. DIF check is disabled and pass is expected.
257 	 */
258 	_dif_generate_and_verify(&iov,
259 				 4096 + 128, 128, false,
260 				 SPDK_DIF_TYPE1, dif_flags,
261 				 22, 22,
262 				 0xFFFF, 0xFFFF, 0x22,
263 				 true);
264 
265 	/* The case that DIF check is not disabled when the Application Tag is 0xFFFF but
266 	 * the Reference Tag is not 0xFFFFFFFF for Type 3. DIF check is not disabled and
267 	 * fail is expected.
268 	 */
269 	_dif_generate_and_verify(&iov,
270 				 4096 + 128, 128, false,
271 				 SPDK_DIF_TYPE3, dif_flags,
272 				 22, 22,
273 				 0xFFFF, 0xFFFF, 0x22,
274 				 false);
275 
276 	/* The case that DIF check is disabled when the Application Tag is 0xFFFF and
277 	 * the Reference Tag is 0xFFFFFFFF for Type 3. DIF check is disabled and
278 	 * pass is expected.
279 	 */
280 	_dif_generate_and_verify(&iov,
281 				 4096 + 128, 128, false,
282 				 SPDK_DIF_TYPE3, dif_flags,
283 				 0xFFFFFFFF, 22,
284 				 0xFFFF, 0xFFFF, 0x22,
285 				 true);
286 
287 	_iov_free_buf(&iov);
288 }
289 
290 static void
291 dif_sec_512_md_0_error_test(void)
292 {
293 	struct spdk_dif_ctx ctx = {};
294 	int rc;
295 
296 	/* Metadata size is 0. */
297 	rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0, 0);
298 	CU_ASSERT(rc != 0);
299 }
300 
301 static void
302 dif_guard_seed_test(void)
303 {
304 	struct iovec iov;
305 	struct spdk_dif_ctx ctx = {};
306 	struct spdk_dif_error err_blk = {};
307 	struct spdk_dif *dif;
308 	uint16_t guard;
309 	int rc;
310 
311 	_iov_alloc_buf(&iov, 512 + 8);
312 
313 	memset(iov.iov_base, 0, 512 + 8);
314 
315 	dif = (struct spdk_dif *)(iov.iov_base + 512);
316 
317 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
318 			       SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0, 0);
319 	CU_ASSERT(rc == 0);
320 
321 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
322 	CU_ASSERT(rc == 0);
323 
324 	/* Guard should be zero if the block is all zero and seed is not added. */
325 	guard = from_be16(&dif->guard);
326 	CU_ASSERT(guard == 0);
327 
328 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
329 	CU_ASSERT(rc == 0);
330 
331 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
332 			       SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0, GUARD_SEED);
333 	CU_ASSERT(rc == 0);
334 
335 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
336 	CU_ASSERT(rc == 0);
337 
338 	/* Guard should not be zero if the block is all zero but seed is added. */
339 	guard = from_be16(&dif->guard);
340 	CU_ASSERT(guard != 0);
341 
342 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
343 	CU_ASSERT(rc == 0);
344 
345 	_iov_free_buf(&iov);
346 }
347 
348 static void
349 dif_generate_and_verify(struct iovec *iovs, int iovcnt,
350 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
351 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
352 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
353 {
354 	struct spdk_dif_ctx ctx = {};
355 	int rc;
356 
357 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
358 	CU_ASSERT(rc == 0);
359 
360 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
361 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED);
362 	CU_ASSERT(rc == 0);
363 
364 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
365 	CU_ASSERT(rc == 0);
366 
367 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL);
368 	CU_ASSERT(rc == 0);
369 
370 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
371 	CU_ASSERT(rc == 0);
372 }
373 
374 static void
375 dif_disable_sec_512_md_8_single_iov_test(void)
376 {
377 	struct iovec iov;
378 
379 	_iov_alloc_buf(&iov, 512 + 8);
380 
381 	dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_DISABLE, 0, 0, 0, 0);
382 
383 	_iov_free_buf(&iov);
384 }
385 
386 static void
387 dif_sec_512_md_8_prchk_0_single_iov_test(void)
388 {
389 	struct iovec iov;
390 
391 	_iov_alloc_buf(&iov, 512 + 8);
392 
393 	dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
394 
395 	_iov_free_buf(&iov);
396 }
397 
398 static void
399 dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test(void)
400 {
401 	struct iovec iovs[4];
402 	int i, num_blocks;
403 
404 	num_blocks = 0;
405 
406 	for (i = 0; i < 4; i++) {
407 		_iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1));
408 		num_blocks += i + 1;
409 	}
410 
411 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
412 				0, 22, 0xFFFF, 0x22);
413 
414 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
415 				SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22);
416 
417 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
418 				SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22);
419 
420 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
421 				SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22);
422 
423 	for (i = 0; i < 4; i++) {
424 		_iov_free_buf(&iovs[i]);
425 	}
426 }
427 
428 static void
429 dif_sec_4096_md_128_prchk_7_multi_iovs_test(void)
430 {
431 	struct iovec iovs[4];
432 	int i, num_blocks;
433 	uint32_t dif_flags;
434 
435 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
436 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
437 
438 	num_blocks = 0;
439 
440 	for (i = 0; i < 4; i++) {
441 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
442 		num_blocks += i + 1;
443 	}
444 
445 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
446 				dif_flags, 22, 0xFFFF, 0x22);
447 
448 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1,
449 				dif_flags, 22, 0xFFFF, 0x22);
450 
451 	for (i = 0; i < 4; i++) {
452 		_iov_free_buf(&iovs[i]);
453 	}
454 }
455 
456 static void
457 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test(void)
458 {
459 	struct iovec iovs[2];
460 	uint32_t dif_flags;
461 
462 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
463 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
464 
465 	_iov_alloc_buf(&iovs[0], 512);
466 	_iov_alloc_buf(&iovs[1], 8);
467 
468 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
469 				dif_flags, 22, 0xFFFF, 0x22);
470 
471 	_iov_free_buf(&iovs[0]);
472 	_iov_free_buf(&iovs[1]);
473 }
474 
475 static void
476 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test(void)
477 {
478 	struct iovec iovs[2];
479 	uint32_t dif_flags;
480 
481 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
482 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
483 
484 	_iov_alloc_buf(&iovs[0], 256);
485 	_iov_alloc_buf(&iovs[1], 264);
486 
487 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
488 				dif_flags, 22, 0xFFFF, 0x22);
489 
490 	_iov_free_buf(&iovs[0]);
491 	_iov_free_buf(&iovs[1]);
492 }
493 
494 static void
495 dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test(void)
496 {
497 	struct iovec iovs[2];
498 	uint32_t dif_flags;
499 
500 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
501 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
502 
503 	_iov_alloc_buf(&iovs[0], 513);
504 	_iov_alloc_buf(&iovs[1], 7);
505 
506 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
507 				dif_flags, 22, 0xFFFF, 0x22);
508 
509 	_iov_free_buf(&iovs[0]);
510 	_iov_free_buf(&iovs[1]);
511 }
512 
513 static void
514 dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test(void)
515 {
516 	struct iovec iovs[2];
517 	uint32_t dif_flags;
518 
519 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
520 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
521 
522 	_iov_alloc_buf(&iovs[0], 515);
523 	_iov_alloc_buf(&iovs[1], 5);
524 
525 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
526 				dif_flags, 22, 0xFFFF, 0x22);
527 
528 	_iov_free_buf(&iovs[0]);
529 	_iov_free_buf(&iovs[1]);
530 }
531 
532 static void
533 dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test(void)
534 {
535 	struct iovec iovs[2];
536 	uint32_t dif_flags;
537 
538 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
539 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
540 
541 	_iov_alloc_buf(&iovs[0], 518);
542 	_iov_alloc_buf(&iovs[1], 2);
543 
544 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
545 				dif_flags, 22, 0xFFFF, 0x22);
546 
547 	_iov_free_buf(&iovs[0]);
548 	_iov_free_buf(&iovs[1]);
549 }
550 
551 static void
552 dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test(void)
553 {
554 	struct iovec iovs[9];
555 	uint32_t dif_flags;
556 	int i;
557 
558 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
559 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
560 
561 	/* data[0][255:0] */
562 	_iov_alloc_buf(&iovs[0], 256);
563 
564 	/* data[0][511:256], guard[0][0] */
565 	_iov_alloc_buf(&iovs[1], 256 + 1);
566 
567 	/* guard[0][1], apptag[0][0] */
568 	_iov_alloc_buf(&iovs[2], 1 + 1);
569 
570 	/* apptag[0][1], reftag[0][0] */
571 	_iov_alloc_buf(&iovs[3], 1 + 1);
572 
573 	/* reftag[0][3:1], data[1][255:0] */
574 	_iov_alloc_buf(&iovs[4], 3 + 256);
575 
576 	/* data[1][511:256], guard[1][0] */
577 	_iov_alloc_buf(&iovs[5], 256 + 1);
578 
579 	/* guard[1][1], apptag[1][0] */
580 	_iov_alloc_buf(&iovs[6], 1 + 1);
581 
582 	/* apptag[1][1], reftag[1][0] */
583 	_iov_alloc_buf(&iovs[7], 1 + 1);
584 
585 	/* reftag[1][3:1] */
586 	_iov_alloc_buf(&iovs[8], 3);
587 
588 	dif_generate_and_verify(iovs, 9, 512 + 8, 8, 2, false, SPDK_DIF_TYPE1, dif_flags,
589 				22, 0xFFFF, 0x22);
590 
591 	for (i = 0; i < 9; i++) {
592 		_iov_free_buf(&iovs[i]);
593 	}
594 }
595 
596 static void
597 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void)
598 {
599 	struct iovec iovs[11];
600 	uint32_t dif_flags;
601 	int i;
602 
603 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
604 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
605 
606 	/* data[0][1000:0] */
607 	_iov_alloc_buf(&iovs[0], 1000);
608 
609 	/* data[0][3095:1000], guard[0][0] */
610 	_iov_alloc_buf(&iovs[1], 3096 + 1);
611 
612 	/* guard[0][1], apptag[0][0] */
613 	_iov_alloc_buf(&iovs[2], 1 + 1);
614 
615 	/* apptag[0][1], reftag[0][0] */
616 	_iov_alloc_buf(&iovs[3], 1 + 1);
617 
618 	/* reftag[0][3:1], ignore[0][59:0] */
619 	_iov_alloc_buf(&iovs[4], 3 + 60);
620 
621 	/* ignore[119:60], data[1][3050:0] */
622 	_iov_alloc_buf(&iovs[5], 60 + 3051);
623 
624 	/* data[1][4095:3050], guard[1][0] */
625 	_iov_alloc_buf(&iovs[6], 1045 + 1);
626 
627 	/* guard[1][1], apptag[1][0] */
628 	_iov_alloc_buf(&iovs[7], 1 + 1);
629 
630 	/* apptag[1][1], reftag[1][0] */
631 	_iov_alloc_buf(&iovs[8], 1 + 1);
632 
633 	/* reftag[1][3:1], ignore[1][9:0] */
634 	_iov_alloc_buf(&iovs[9], 3 + 10);
635 
636 	/* ignore[1][127:9] */
637 	_iov_alloc_buf(&iovs[10], 118);
638 
639 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
640 				22, 0xFFFF, 0x22);
641 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
642 				22, 0xFFFF, 0x22);
643 
644 	for (i = 0; i < 11; i++) {
645 		_iov_free_buf(&iovs[i]);
646 	}
647 }
648 
649 static void
650 _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
651 			     uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
652 			     uint32_t inject_flags, bool dif_loc)
653 {
654 	struct spdk_dif_ctx ctx = {};
655 	struct spdk_dif_error err_blk = {};
656 	uint32_t inject_offset = 0, dif_flags;
657 	int rc;
658 
659 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
660 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
661 
662 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
663 	CU_ASSERT(rc == 0);
664 
665 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc,
666 			       SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88, 0, GUARD_SEED);
667 	CU_ASSERT(rc == 0);
668 
669 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
670 	CU_ASSERT(rc == 0);
671 
672 	rc = spdk_dif_inject_error(iovs, iovcnt, num_blocks, &ctx, inject_flags, &inject_offset);
673 	CU_ASSERT(rc == 0);
674 
675 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, &err_blk);
676 	CU_ASSERT(rc != 0);
677 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
678 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
679 	} else {
680 		CU_ASSERT(inject_flags == err_blk.err_type);
681 	}
682 	CU_ASSERT(inject_offset == err_blk.err_offset);
683 
684 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
685 	CU_ASSERT((rc == 0 && (inject_flags != SPDK_DIF_DATA_ERROR)) ||
686 		  (rc != 0 && (inject_flags == SPDK_DIF_DATA_ERROR)));
687 }
688 
689 static void
690 dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
691 			    uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
692 			    uint32_t inject_flags)
693 {
694 	/* The case that DIF is contained in the first 8 bytes of metadata. */
695 	_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
696 				     inject_flags, true);
697 
698 	/* The case that DIF is contained in the last 8 bytes of metadata. */
699 	_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
700 				     inject_flags, false);
701 }
702 
703 static void
704 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
705 {
706 	struct iovec iovs[4];
707 	int i, num_blocks;
708 
709 	num_blocks = 0;
710 
711 	for (i = 0; i < 4; i++) {
712 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
713 		num_blocks += i + 1;
714 	}
715 
716 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_GUARD_ERROR);
717 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_APPTAG_ERROR);
718 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_REFTAG_ERROR);
719 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_DATA_ERROR);
720 
721 	for (i = 0; i < 4; i++) {
722 		_iov_free_buf(&iovs[i]);
723 	}
724 }
725 
726 static void
727 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test(void)
728 {
729 	struct iovec iovs[2];
730 
731 	_iov_alloc_buf(&iovs[0], 4096);
732 	_iov_alloc_buf(&iovs[1], 128);
733 
734 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
735 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
736 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
737 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
738 
739 	_iov_free_buf(&iovs[0]);
740 	_iov_free_buf(&iovs[1]);
741 }
742 
743 static void
744 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test(void)
745 {
746 	struct iovec iovs[2];
747 
748 	_iov_alloc_buf(&iovs[0], 2048);
749 	_iov_alloc_buf(&iovs[1], 2048 + 128);
750 
751 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
752 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
753 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
754 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
755 
756 	_iov_free_buf(&iovs[0]);
757 	_iov_free_buf(&iovs[1]);
758 }
759 
760 static void
761 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test(void)
762 {
763 	struct iovec iovs[2];
764 
765 	_iov_alloc_buf(&iovs[0], 4096 + 1);
766 	_iov_alloc_buf(&iovs[1], 127);
767 
768 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
769 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
770 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
771 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
772 
773 	_iov_free_buf(&iovs[0]);
774 	_iov_free_buf(&iovs[1]);
775 }
776 
777 static void
778 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(void)
779 {
780 	struct iovec iovs[2];
781 
782 	_iov_alloc_buf(&iovs[0], 4096 + 3);
783 	_iov_alloc_buf(&iovs[1], 125);
784 
785 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
786 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
787 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
788 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
789 
790 	_iov_free_buf(&iovs[0]);
791 	_iov_free_buf(&iovs[1]);
792 }
793 
794 static void
795 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(void)
796 {
797 	struct iovec iovs[2];
798 
799 	_iov_alloc_buf(&iovs[0], 4096 + 6);
800 	_iov_alloc_buf(&iovs[1], 122);
801 
802 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
803 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
804 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
805 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
806 
807 	_iov_free_buf(&iovs[0]);
808 	_iov_free_buf(&iovs[1]);
809 }
810 
811 static void
812 dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
813 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
814 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
815 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
816 {
817 	struct spdk_dif_ctx ctx = {};
818 	int rc;
819 
820 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
821 	CU_ASSERT(rc == 0);
822 
823 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
824 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED);
825 	CU_ASSERT(rc == 0);
826 
827 	rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
828 	CU_ASSERT(rc == 0);
829 
830 	rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL);
831 	CU_ASSERT(rc == 0);
832 
833 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks);
834 	CU_ASSERT(rc == 0);
835 }
836 
837 static void
838 dif_copy_sec_512_md_8_prchk_0_single_iov(void)
839 {
840 	struct iovec iov, bounce_iov;
841 
842 	_iov_alloc_buf(&iov, 512 * 4);
843 	_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
844 
845 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4,
846 				false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
847 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4,
848 				true, SPDK_DIF_TYPE1, 0, 0, 0, 0);
849 
850 	_iov_free_buf(&iov);
851 	_iov_free_buf(&bounce_iov);
852 }
853 
854 static void
855 dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
856 {
857 	struct iovec iovs[4], bounce_iov;
858 	int i, num_blocks;
859 
860 	num_blocks = 0;
861 
862 	for (i = 0; i < 4; i++) {
863 		_iov_alloc_buf(&iovs[i], 512 * (i + 1));
864 		num_blocks += i + 1;
865 	}
866 
867 	_iov_alloc_buf(&bounce_iov, (512 + 8) * num_blocks);
868 
869 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
870 				false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22);
871 
872 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
873 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22);
874 
875 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
876 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22);
877 
878 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
879 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22);
880 
881 	for (i = 0; i < 4; i++) {
882 		_iov_free_buf(&iovs[i]);
883 	}
884 	_iov_free_buf(&bounce_iov);
885 }
886 
887 static void
888 dif_copy_sec_4096_md_128_prchk_7_multi_iovs(void)
889 {
890 	struct iovec iovs[4], bounce_iov;
891 	uint32_t dif_flags;
892 	int i, num_blocks;
893 
894 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
895 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
896 
897 	num_blocks = 0;
898 
899 	for (i = 0; i < 4; i++) {
900 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
901 		num_blocks += i + 1;
902 	}
903 
904 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
905 
906 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks,
907 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
908 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks,
909 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
910 
911 	for (i = 0; i < 4; i++) {
912 		_iov_free_buf(&iovs[i]);
913 	}
914 	_iov_free_buf(&bounce_iov);
915 }
916 
917 static void
918 dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
919 {
920 	struct iovec iovs[2], bounce_iov;
921 	uint32_t dif_flags;
922 
923 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
924 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
925 
926 	_iov_alloc_buf(&iovs[0], 256);
927 	_iov_alloc_buf(&iovs[1], 256);
928 
929 	_iov_alloc_buf(&bounce_iov, 512 + 8);
930 
931 	dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 512 + 8, 8, 1,
932 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
933 
934 	_iov_free_buf(&iovs[0]);
935 	_iov_free_buf(&iovs[1]);
936 	_iov_free_buf(&bounce_iov);
937 }
938 
939 static void
940 dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
941 {
942 	struct iovec iovs[6], bounce_iov;
943 	uint32_t dif_flags;
944 	int i;
945 
946 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
947 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
948 
949 	/* data[0][255:0] */
950 	_iov_alloc_buf(&iovs[0], 256);
951 
952 	/* data[0][511:256], data[1][255:0] */
953 	_iov_alloc_buf(&iovs[1], 256 + 256);
954 
955 	/* data[1][382:256] */
956 	_iov_alloc_buf(&iovs[2], 128);
957 
958 	/* data[1][383] */
959 	_iov_alloc_buf(&iovs[3], 1);
960 
961 	/* data[1][510:384] */
962 	_iov_alloc_buf(&iovs[4], 126);
963 
964 	/* data[1][511], data[2][511:0], data[3][511:0] */
965 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
966 
967 	_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
968 
969 	dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 512 + 8, 8, 4,
970 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
971 
972 	for (i = 0; i < 6; i++) {
973 		_iov_free_buf(&iovs[i]);
974 	}
975 	_iov_free_buf(&bounce_iov);
976 }
977 
978 static void
979 _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
980 				  uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
981 				  uint32_t inject_flags, bool dif_loc)
982 {
983 	struct spdk_dif_ctx ctx = {};
984 	struct spdk_dif_error err_blk = {};
985 	uint32_t inject_offset = 0, dif_flags;
986 	int rc;
987 
988 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
989 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
990 
991 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
992 	CU_ASSERT(rc == 0);
993 
994 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags,
995 			       88, 0xFFFF, 0x88, 0, GUARD_SEED);
996 	SPDK_CU_ASSERT_FATAL(rc == 0);
997 
998 	rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
999 	CU_ASSERT(rc == 0);
1000 
1001 	rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset);
1002 	CU_ASSERT(rc == 0);
1003 
1004 	rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, &err_blk);
1005 	CU_ASSERT(rc != 0);
1006 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
1007 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
1008 	} else {
1009 		CU_ASSERT(inject_flags == err_blk.err_type);
1010 	}
1011 	CU_ASSERT(inject_offset == err_blk.err_offset);
1012 }
1013 
1014 static void
1015 dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
1016 				 uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1017 				 uint32_t inject_flags)
1018 {
1019 	/* The case that DIF is contained in the first 8 bytes of metadata. */
1020 	_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
1021 					  block_size, md_size, num_blocks,
1022 					  inject_flags, true);
1023 
1024 	/* The case that DIF is contained in the last 8 bytes of metadata. */
1025 	_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
1026 					  block_size, md_size, num_blocks,
1027 					  inject_flags, false);
1028 }
1029 
1030 static void
1031 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
1032 {
1033 	struct iovec iovs[4], bounce_iov;
1034 	int i, num_blocks;
1035 
1036 	num_blocks = 0;
1037 
1038 	for (i = 0; i < 4; i++) {
1039 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1040 		num_blocks += i + 1;
1041 	}
1042 
1043 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
1044 
1045 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1046 					 num_blocks, SPDK_DIF_GUARD_ERROR);
1047 
1048 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1049 					 num_blocks, SPDK_DIF_APPTAG_ERROR);
1050 
1051 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1052 					 num_blocks, SPDK_DIF_REFTAG_ERROR);
1053 
1054 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1055 					 num_blocks, SPDK_DIF_DATA_ERROR);
1056 
1057 	for (i = 0; i < 4; i++) {
1058 		_iov_free_buf(&iovs[i]);
1059 	}
1060 	_iov_free_buf(&bounce_iov);
1061 }
1062 
1063 static void
1064 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
1065 {
1066 	struct iovec iovs[4], bounce_iov;
1067 	int i;
1068 
1069 	_iov_alloc_buf(&iovs[0], 2048);
1070 	_iov_alloc_buf(&iovs[1], 2048);
1071 	_iov_alloc_buf(&iovs[2], 1);
1072 	_iov_alloc_buf(&iovs[3], 4095);
1073 
1074 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * 2);
1075 
1076 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1077 					 2, SPDK_DIF_GUARD_ERROR);
1078 
1079 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1080 					 2, SPDK_DIF_APPTAG_ERROR);
1081 
1082 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1083 					 2, SPDK_DIF_REFTAG_ERROR);
1084 
1085 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
1086 					 2, SPDK_DIF_DATA_ERROR);
1087 
1088 	for (i = 0; i < 4; i++) {
1089 		_iov_free_buf(&iovs[i]);
1090 	}
1091 	_iov_free_buf(&bounce_iov);
1092 }
1093 
1094 static void
1095 dix_sec_512_md_0_error(void)
1096 {
1097 	struct spdk_dif_ctx ctx;
1098 	int rc;
1099 
1100 	rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0, 0);
1101 	CU_ASSERT(rc != 0);
1102 }
1103 
1104 static void
1105 dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
1106 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1107 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
1108 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
1109 {
1110 	struct spdk_dif_ctx ctx;
1111 	int rc;
1112 
1113 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
1114 	CU_ASSERT(rc == 0);
1115 
1116 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
1117 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED);
1118 	CU_ASSERT(rc == 0);
1119 
1120 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
1121 	CU_ASSERT(rc == 0);
1122 
1123 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL);
1124 	CU_ASSERT(rc == 0);
1125 
1126 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks);
1127 	CU_ASSERT(rc == 0);
1128 }
1129 
1130 static void
1131 dix_sec_512_md_8_prchk_0_single_iov(void)
1132 {
1133 	struct iovec iov, md_iov;
1134 
1135 	_iov_alloc_buf(&iov, 512 * 4);
1136 	_iov_alloc_buf(&md_iov, 8 * 4);
1137 
1138 	dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
1139 	dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0);
1140 
1141 	_iov_free_buf(&iov);
1142 	_iov_free_buf(&md_iov);
1143 }
1144 
1145 static void
1146 dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
1147 {
1148 	struct iovec iovs[4], md_iov;
1149 	int i, num_blocks;
1150 
1151 	num_blocks = 0;
1152 
1153 	for (i = 0; i < 4; i++) {
1154 		_iov_alloc_buf(&iovs[i], 512 * (i + 1));
1155 		num_blocks += i + 1;
1156 	}
1157 	_iov_alloc_buf(&md_iov, 8 * num_blocks);
1158 
1159 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1160 				0, 22, 0xFFFF, 0x22);
1161 
1162 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1163 				SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22);
1164 
1165 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1166 				SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22);
1167 
1168 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
1169 				SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22);
1170 
1171 	for (i = 0; i < 4; i++) {
1172 		_iov_free_buf(&iovs[i]);
1173 	}
1174 	_iov_free_buf(&md_iov);
1175 }
1176 
1177 static void
1178 dix_sec_4096_md_128_prchk_7_multi_iovs(void)
1179 {
1180 	struct iovec iovs[4], md_iov;
1181 	uint32_t dif_flags;
1182 	int i, num_blocks;
1183 
1184 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1185 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1186 
1187 	num_blocks = 0;
1188 
1189 	for (i = 0; i < 4; i++) {
1190 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1191 		num_blocks += i + 1;
1192 	}
1193 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
1194 
1195 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
1196 				dif_flags, 22, 0xFFFF, 0x22);
1197 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
1198 				dif_flags, 22, 0xFFFF, 0x22);
1199 
1200 	for (i = 0; i < 4; i++) {
1201 		_iov_free_buf(&iovs[i]);
1202 	}
1203 	_iov_free_buf(&md_iov);
1204 }
1205 
1206 static void
1207 dix_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
1208 {
1209 	struct iovec iovs[2], md_iov;
1210 	uint32_t dif_flags;
1211 
1212 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1213 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1214 
1215 	_iov_alloc_buf(&iovs[0], 256);
1216 	_iov_alloc_buf(&iovs[1], 256);
1217 	_iov_alloc_buf(&md_iov, 8);
1218 
1219 	dix_generate_and_verify(iovs, 2, &md_iov, 512, 8, 1, false, SPDK_DIF_TYPE1,
1220 				dif_flags, 22, 0xFFFF, 0x22);
1221 
1222 	_iov_free_buf(&iovs[0]);
1223 	_iov_free_buf(&iovs[1]);
1224 	_iov_free_buf(&md_iov);
1225 }
1226 
1227 static void
1228 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
1229 {
1230 	struct iovec iovs[6], md_iov;
1231 	uint32_t dif_flags;
1232 	int i;
1233 
1234 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1235 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1236 
1237 	/* data[0][255:0] */
1238 	_iov_alloc_buf(&iovs[0], 256);
1239 
1240 	/* data[0][511:256], data[1][255:0] */
1241 	_iov_alloc_buf(&iovs[1], 256 + 256);
1242 
1243 	/* data[1][382:256] */
1244 	_iov_alloc_buf(&iovs[2], 128);
1245 
1246 	/* data[1][383] */
1247 	_iov_alloc_buf(&iovs[3], 1);
1248 
1249 	/* data[1][510:384] */
1250 	_iov_alloc_buf(&iovs[4], 126);
1251 
1252 	/* data[1][511], data[2][511:0], data[3][511:0] */
1253 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
1254 
1255 	_iov_alloc_buf(&md_iov, 8 * 4);
1256 
1257 	dix_generate_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1,
1258 				dif_flags, 22, 0xFFFF, 0x22);
1259 
1260 	for (i = 0; i < 6; i++) {
1261 		_iov_free_buf(&iovs[i]);
1262 	}
1263 	_iov_free_buf(&md_iov);
1264 }
1265 
1266 static void
1267 _dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
1268 			     uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1269 			     uint32_t inject_flags, bool dif_loc)
1270 {
1271 	struct spdk_dif_ctx ctx = {};
1272 	struct spdk_dif_error err_blk = {};
1273 	uint32_t inject_offset = 0, dif_flags;
1274 	int rc;
1275 
1276 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1277 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1278 
1279 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
1280 	CU_ASSERT(rc == 0);
1281 
1282 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags,
1283 			       88, 0xFFFF, 0x88, 0, GUARD_SEED);
1284 	CU_ASSERT(rc == 0);
1285 
1286 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
1287 	CU_ASSERT(rc == 0);
1288 
1289 	rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset);
1290 	CU_ASSERT(rc == 0);
1291 
1292 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, &err_blk);
1293 	CU_ASSERT(rc != 0);
1294 
1295 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
1296 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
1297 	} else {
1298 		CU_ASSERT(inject_flags == err_blk.err_type);
1299 	}
1300 	CU_ASSERT(inject_offset == err_blk.err_offset);
1301 }
1302 
1303 static void
1304 dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
1305 			    uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1306 			    uint32_t inject_flags)
1307 {
1308 	/* The case that DIF is contained in the first 8 bytes of metadata. */
1309 	_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
1310 				     inject_flags, true);
1311 
1312 	/* The case that DIF is contained in the last 8 bytes of metadata. */
1313 	_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
1314 				     inject_flags, false);
1315 }
1316 
1317 static void
1318 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
1319 {
1320 	struct iovec iovs[4], md_iov;
1321 	int i, num_blocks;
1322 
1323 	num_blocks = 0;
1324 
1325 	for (i = 0; i < 4; i++) {
1326 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1327 		num_blocks += i + 1;
1328 	}
1329 
1330 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
1331 
1332 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_GUARD_ERROR);
1333 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_APPTAG_ERROR);
1334 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_REFTAG_ERROR);
1335 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_DATA_ERROR);
1336 
1337 	for (i = 0; i < 4; i++) {
1338 		_iov_free_buf(&iovs[i]);
1339 	}
1340 	_iov_free_buf(&md_iov);
1341 }
1342 
1343 static void
1344 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
1345 {
1346 	struct iovec iovs[4], md_iov;
1347 	int i;
1348 
1349 	_iov_alloc_buf(&iovs[0], 2048);
1350 	_iov_alloc_buf(&iovs[1], 2048);
1351 	_iov_alloc_buf(&iovs[2], 1);
1352 	_iov_alloc_buf(&iovs[3], 4095);
1353 
1354 	_iov_alloc_buf(&md_iov, 128 * 2);
1355 
1356 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_GUARD_ERROR);
1357 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_APPTAG_ERROR);
1358 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_REFTAG_ERROR);
1359 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_DATA_ERROR);
1360 
1361 	for (i = 0; i < 4; i++) {
1362 		_iov_free_buf(&iovs[i]);
1363 	}
1364 	_iov_free_buf(&md_iov);
1365 }
1366 
1367 static int
1368 ut_readv(uint32_t read_base, uint32_t read_len, struct iovec *iovs, int iovcnt)
1369 {
1370 	int i;
1371 	uint32_t j, offset;
1372 	uint8_t *buf;
1373 
1374 	offset = 0;
1375 	for (i = 0; i < iovcnt; i++) {
1376 		buf = iovs[i].iov_base;
1377 		for (j = 0; j < iovs[i].iov_len; j++, offset++) {
1378 			if (offset >= read_len) {
1379 				return offset;
1380 			}
1381 			buf[j] = DATA_PATTERN(read_base + offset);
1382 		}
1383 	}
1384 
1385 	return offset;
1386 }
1387 
1388 static void
1389 set_md_interleave_iovs_test(void)
1390 {
1391 	struct spdk_dif_ctx ctx = {};
1392 	struct spdk_dif_error err_blk = {};
1393 	struct iovec iov1, iov2, dif_iovs[4] = {};
1394 	uint32_t dif_check_flags, data_len, read_len, data_offset, mapped_len = 0;
1395 	uint8_t *buf1, *buf2;
1396 	int rc;
1397 
1398 	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1399 			  SPDK_DIF_FLAGS_REFTAG_CHECK;
1400 
1401 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
1402 			       dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED);
1403 	CU_ASSERT(rc == 0);
1404 
1405 	/* The first data buffer:
1406 	 * - Create iovec array to Leave a space for metadata for each block
1407 	 * - Split vectored read and so creating iovec array is done before every vectored read.
1408 	 */
1409 	buf1 = calloc(1, (4096 + 128) * 4);
1410 	SPDK_CU_ASSERT_FATAL(buf1 != NULL);
1411 	_iov_set_buf(&iov1, buf1, (4096 + 128) * 4);
1412 
1413 	data_offset = 0;
1414 	data_len = 4096 * 4;
1415 
1416 	/* 1st read */
1417 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1418 					     data_offset, data_len, &mapped_len, &ctx);
1419 	CU_ASSERT(rc == 4);
1420 	CU_ASSERT(mapped_len == 4096 * 4);
1421 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1, 4096) == true);
1422 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1423 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1424 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
1425 
1426 	read_len = ut_readv(data_offset, 1024, dif_iovs, 4);
1427 	CU_ASSERT(read_len == 1024);
1428 
1429 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
1430 	CU_ASSERT(rc == 0);
1431 
1432 	data_offset += read_len;
1433 	data_len -= read_len;
1434 
1435 	/* 2nd read */
1436 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1437 					     data_offset, data_len, &mapped_len, &ctx);
1438 	CU_ASSERT(rc == 4);
1439 	CU_ASSERT(mapped_len == 3072 + 4096 * 3);
1440 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 1024, 3072) == true);
1441 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1442 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1443 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
1444 
1445 	read_len = ut_readv(data_offset, 3071, dif_iovs, 4);
1446 	CU_ASSERT(read_len == 3071);
1447 
1448 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
1449 	CU_ASSERT(rc == 0);
1450 
1451 	data_offset += read_len;
1452 	data_len -= read_len;
1453 
1454 	/* 3rd read */
1455 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1456 					     data_offset, data_len, &mapped_len, &ctx);
1457 	CU_ASSERT(rc == 4);
1458 	CU_ASSERT(mapped_len == 1 + 4096 * 3);
1459 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 4095, 1) == true);
1460 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1461 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1462 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
1463 
1464 	read_len = ut_readv(data_offset, 1 + 4096 * 2 + 512, dif_iovs, 4);
1465 	CU_ASSERT(read_len == 1 + 4096 * 2 + 512);
1466 
1467 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
1468 	CU_ASSERT(rc == 0);
1469 
1470 	data_offset += read_len;
1471 	data_len -= read_len;
1472 
1473 	/* 4th read */
1474 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1475 					     data_offset, data_len, &mapped_len, &ctx);
1476 	CU_ASSERT(rc == 1);
1477 	CU_ASSERT(mapped_len == 3584);
1478 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + (4096 + 128) * 3 + 512, 3584) == true);
1479 
1480 	read_len = ut_readv(data_offset, 3584, dif_iovs, 1);
1481 	CU_ASSERT(read_len == 3584);
1482 
1483 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
1484 	CU_ASSERT(rc == 0);
1485 
1486 	data_offset += read_len;
1487 	CU_ASSERT(data_offset == 4096 * 4);
1488 	data_len -= read_len;
1489 	CU_ASSERT(data_len == 0);
1490 
1491 	/* The second data buffer:
1492 	 * - Set data pattern with a space for metadata for each block.
1493 	 */
1494 	buf2 = calloc(1, (4096 + 128) * 4);
1495 	SPDK_CU_ASSERT_FATAL(buf2 != NULL);
1496 	_iov_set_buf(&iov2, buf2, (4096 + 128) * 4);
1497 
1498 	rc = ut_data_pattern_generate(&iov2, 1, 4096 + 128, 128, 4);
1499 	CU_ASSERT(rc == 0);
1500 	rc = spdk_dif_generate(&iov2, 1, 4, &ctx);
1501 	CU_ASSERT(rc == 0);
1502 
1503 	rc = spdk_dif_verify(&iov1, 1, 4, &ctx, &err_blk);
1504 	CU_ASSERT(rc == 0);
1505 
1506 	rc = spdk_dif_verify(&iov2, 1, 4, &ctx, &err_blk);
1507 	CU_ASSERT(rc == 0);
1508 
1509 	/* Compare the first and the second data buffer by byte. */
1510 	rc = memcmp(buf1, buf2, (4096 + 128) * 4);
1511 	CU_ASSERT(rc == 0);
1512 
1513 	free(buf1);
1514 	free(buf2);
1515 }
1516 
1517 static void
1518 set_md_interleave_iovs_split_test(void)
1519 {
1520 	struct spdk_dif_ctx ctx = {};
1521 	struct spdk_dif_error err_blk = {};
1522 	struct iovec iovs1[7], iovs2[7], dif_iovs[8] = {};
1523 	uint32_t dif_check_flags, data_len, read_len, data_offset, mapped_len = 0;
1524 	int rc, i;
1525 
1526 	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1527 			  SPDK_DIF_FLAGS_REFTAG_CHECK;
1528 
1529 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
1530 			       dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED);
1531 	CU_ASSERT(rc == 0);
1532 
1533 	/* The first SGL data buffer:
1534 	 * - Create iovec array to leave a space for metadata for each block
1535 	 * - Split vectored read and so creating iovec array is done before every vectored read.
1536 	 */
1537 	_iov_alloc_buf(&iovs1[0], 512 + 8 + 128);
1538 	_iov_alloc_buf(&iovs1[1], 128);
1539 	_iov_alloc_buf(&iovs1[2], 256 + 8);
1540 	_iov_alloc_buf(&iovs1[3], 100);
1541 	_iov_alloc_buf(&iovs1[4], 412 + 5);
1542 	_iov_alloc_buf(&iovs1[5], 3 + 300);
1543 	_iov_alloc_buf(&iovs1[6], 212 + 8);
1544 
1545 	data_offset = 0;
1546 	data_len = 512 * 4;
1547 
1548 	/* 1st read */
1549 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
1550 					     data_offset, data_len, &mapped_len, &ctx);
1551 	CU_ASSERT(rc == 8);
1552 	CU_ASSERT(mapped_len == 512 * 4);
1553 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base, 512) == true);
1554 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
1555 	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
1556 	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
1557 	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
1558 	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
1559 	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
1560 	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
1561 
1562 	read_len = ut_readv(data_offset, 128, dif_iovs, 8);
1563 	CU_ASSERT(read_len == 128);
1564 
1565 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
1566 	CU_ASSERT(rc == 0);
1567 
1568 	data_offset += read_len;
1569 	data_len -= read_len;
1570 
1571 	/* 2nd read */
1572 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
1573 					     data_offset, data_len, &mapped_len, &ctx);
1574 	CU_ASSERT(rc == 8);
1575 	CU_ASSERT(mapped_len == 384 + 512 * 3);
1576 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 128, 384) == true);
1577 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
1578 	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
1579 	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
1580 	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
1581 	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
1582 	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
1583 	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
1584 
1585 	read_len = ut_readv(data_offset, 383, dif_iovs, 8);
1586 	CU_ASSERT(read_len == 383);
1587 
1588 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
1589 	CU_ASSERT(rc == 0);
1590 
1591 	data_offset += read_len;
1592 	data_len -= read_len;
1593 
1594 	/* 3rd read */
1595 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
1596 					     data_offset, data_len, &mapped_len, &ctx);
1597 	CU_ASSERT(rc == 8);
1598 	CU_ASSERT(mapped_len == 1 + 512 * 3);
1599 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 511, 1) == true);
1600 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
1601 	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
1602 	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
1603 	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
1604 	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
1605 	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
1606 	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
1607 
1608 	read_len = ut_readv(data_offset, 1 + 512 * 2 + 128, dif_iovs, 8);
1609 	CU_ASSERT(read_len == 1 + 512 * 2 + 128);
1610 
1611 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
1612 	CU_ASSERT(rc == 0);
1613 
1614 	data_offset += read_len;
1615 	data_len -= read_len;
1616 
1617 	/* 4th read */
1618 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
1619 					     data_offset, data_len, &mapped_len, &ctx);
1620 	CU_ASSERT(rc == 2);
1621 	CU_ASSERT(mapped_len == 384);
1622 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[5].iov_base + 3 + 128, 172) == true);
1623 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[6].iov_base, 212) == true);
1624 
1625 	read_len = ut_readv(data_offset, 384, dif_iovs, 8);
1626 	CU_ASSERT(read_len == 384);
1627 
1628 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
1629 	CU_ASSERT(rc == 0);
1630 
1631 	data_offset += read_len;
1632 	CU_ASSERT(data_offset == 512 * 4);
1633 	data_len -= read_len;
1634 	CU_ASSERT(data_len == 0);
1635 
1636 	/* The second SGL data buffer:
1637 	 * - Set data pattern with a space for metadata for each block.
1638 	 */
1639 	_iov_alloc_buf(&iovs2[0], 512 + 8 + 128);
1640 	_iov_alloc_buf(&iovs2[1], 128);
1641 	_iov_alloc_buf(&iovs2[2], 256 + 8);
1642 	_iov_alloc_buf(&iovs2[3], 100);
1643 	_iov_alloc_buf(&iovs2[4], 412 + 5);
1644 	_iov_alloc_buf(&iovs2[5], 3 + 300);
1645 	_iov_alloc_buf(&iovs2[6], 212 + 8);
1646 
1647 	rc = ut_data_pattern_generate(iovs2, 7, 512 + 8, 8, 4);
1648 	CU_ASSERT(rc == 0);
1649 	rc = spdk_dif_generate(iovs2, 7, 4, &ctx);
1650 	CU_ASSERT(rc == 0);
1651 
1652 	rc = spdk_dif_verify(iovs1, 7, 4, &ctx, &err_blk);
1653 	CU_ASSERT(rc == 0);
1654 
1655 	rc = spdk_dif_verify(iovs2, 7, 4, &ctx, &err_blk);
1656 	CU_ASSERT(rc == 0);
1657 
1658 	/* Compare the first and the second SGL data buffer by byte. */
1659 	for (i = 0; i < 7; i++) {
1660 		rc = memcmp(iovs1[i].iov_base, iovs2[i].iov_base,
1661 			    iovs1[i].iov_len);
1662 		CU_ASSERT(rc == 0);
1663 	}
1664 
1665 	for (i = 0; i < 7; i++) {
1666 		_iov_free_buf(&iovs1[i]);
1667 		_iov_free_buf(&iovs2[i]);
1668 	}
1669 }
1670 
1671 static void
1672 dif_generate_stream_test(void)
1673 {
1674 	struct iovec iov;
1675 	struct spdk_dif_ctx ctx;
1676 	struct spdk_dif_error err_blk;
1677 	uint32_t dif_flags;
1678 	int rc;
1679 
1680 	_iov_alloc_buf(&iov, (512 + 8) * 5);
1681 
1682 	rc = ut_data_pattern_generate(&iov, 1, 512 + 8, 8, 5);
1683 	CU_ASSERT(rc == 0);
1684 
1685 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1686 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1687 
1688 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, dif_flags,
1689 			       22, 0xFFFF, 0x22, 0, GUARD_SEED);
1690 	CU_ASSERT(rc == 0);
1691 
1692 	rc = spdk_dif_generate_stream(&iov, 1, 0, 511, &ctx);
1693 	CU_ASSERT(rc == 0);
1694 
1695 	rc = spdk_dif_generate_stream(&iov, 1, 511, 1, &ctx);
1696 	CU_ASSERT(rc == 0);
1697 
1698 	rc = spdk_dif_generate_stream(&iov, 1, 512, 256, &ctx);
1699 	CU_ASSERT(rc == 0);
1700 
1701 	rc = spdk_dif_generate_stream(&iov, 1, 768, 512, &ctx);
1702 	CU_ASSERT(rc == 0);
1703 
1704 	rc = spdk_dif_generate_stream(&iov, 1, 1280, 1024, &ctx);
1705 	CU_ASSERT(rc == 0);
1706 
1707 	rc = spdk_dif_generate_stream(&iov, 1, 2304, 256, &ctx);
1708 	CU_ASSERT(rc == 0);
1709 
1710 	rc = spdk_dif_generate_stream(&iov, 1, 2560, 512, &ctx);
1711 	CU_ASSERT(rc == -ERANGE);
1712 
1713 	rc = spdk_dif_verify(&iov, 1, 5, &ctx, &err_blk);
1714 	CU_ASSERT(rc == 0);
1715 
1716 	rc = ut_data_pattern_verify(&iov, 1, 512 + 8, 8, 5);
1717 	CU_ASSERT(rc == 0);
1718 
1719 	_iov_free_buf(&iov);
1720 }
1721 
1722 static void
1723 set_md_interleave_iovs_alignment_test(void)
1724 {
1725 	struct iovec iovs[3], dif_iovs[5] = {};
1726 	uint32_t mapped_len = 0;
1727 	int rc;
1728 	struct spdk_dif_ctx ctx;
1729 
1730 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
1731 			       0, 0, 0, 0, 0, 0);
1732 	CU_ASSERT(rc == 0);
1733 
1734 	/* The case that buffer size is smaller than necessary. */
1735 	_iov_set_buf(&iovs[0], (uint8_t *)0xDEADBEEF, 1024);
1736 	_iov_set_buf(&iovs[1], (uint8_t *)0xFEEDBEEF, 1024);
1737 	_iov_set_buf(&iovs[2], (uint8_t *)0xC0FFEE, 24);
1738 
1739 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 0, 2048, &mapped_len, &ctx);
1740 	CU_ASSERT(rc == -ERANGE);
1741 
1742 	/* The folllowing are the normal cases. */
1743 	_iov_set_buf(&iovs[2], (uint8_t *)0xC0FFEE, 32);
1744 
1745 	/* data length is less than a data block size. */
1746 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 0, 500, &mapped_len, &ctx);
1747 	CU_ASSERT(rc == 1);
1748 	CU_ASSERT(mapped_len == 500);
1749 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)0xDEADBEEF, 500) == true);
1750 
1751 	/* Pass enough number of iovecs */
1752 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 500, 1000, &mapped_len, &ctx);
1753 	CU_ASSERT(rc == 4);
1754 	CU_ASSERT(mapped_len == 1000);
1755 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xDEADBEEF + 500), 12) == true);
1756 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xDEADBEEF + 520), 504) == true);
1757 	CU_ASSERT(_iov_check(&dif_iovs[2], (void *)0xFEEDBEEF, 8) == true);
1758 	CU_ASSERT(_iov_check(&dif_iovs[3], (void *)(0xFEEDBEEF + 16), 476) == true);
1759 
1760 	/* Pass iovecs smaller than necessary */
1761 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 3, iovs, 3, 500, 1000, &mapped_len, &ctx);
1762 	CU_ASSERT(rc == 3);
1763 	CU_ASSERT(mapped_len == 524);
1764 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xDEADBEEF + 500), 12) == true);
1765 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xDEADBEEF + 520), 504) == true);
1766 	CU_ASSERT(_iov_check(&dif_iovs[2], (void *)0xFEEDBEEF, 8) == true);
1767 
1768 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 1500, 500, &mapped_len, &ctx);
1769 	CU_ASSERT(rc == 2);
1770 	CU_ASSERT(mapped_len == 500);
1771 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xFEEDBEEF + 492), 36) == true);
1772 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xFEEDBEEF + 536), 464) == true);
1773 
1774 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 2000, 48, &mapped_len, &ctx);
1775 	CU_ASSERT(rc == 2);
1776 	CU_ASSERT(mapped_len == 48);
1777 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)0xFEEDBEEF + 1000, 24) == true);
1778 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)0xC0FFEE, 24) ==  true);
1779 }
1780 
1781 static void
1782 _dif_generate_split_test(void)
1783 {
1784 	struct spdk_dif_ctx ctx = {};
1785 	struct iovec iov;
1786 	uint8_t *buf1, *buf2;
1787 	struct _dif_sgl sgl;
1788 	uint16_t guard = 0, prev_guard;
1789 	uint32_t dif_flags;
1790 	int rc;
1791 
1792 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1793 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1794 
1795 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
1796 			       dif_flags, 0, 0, 0, 0, GUARD_SEED);
1797 	CU_ASSERT(rc == 0);
1798 
1799 	buf1 = calloc(1, 4096 + 128);
1800 	SPDK_CU_ASSERT_FATAL(buf1 != NULL);
1801 	_iov_set_buf(&iov, buf1, 4096 + 128);
1802 
1803 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
1804 	CU_ASSERT(rc == 0);
1805 
1806 	_dif_sgl_init(&sgl, &iov, 1);
1807 
1808 	guard = GUARD_SEED;
1809 	prev_guard = GUARD_SEED;
1810 
1811 	guard = _dif_generate_split(&sgl, 0, 1000, guard, 0, &ctx);
1812 	CU_ASSERT(sgl.iov_offset == 1000);
1813 	CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf1, 1000));
1814 
1815 	prev_guard = guard;
1816 
1817 	guard = _dif_generate_split(&sgl, 1000, 3000, guard, 0, &ctx);
1818 	CU_ASSERT(sgl.iov_offset == 4000);
1819 	CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf1 + 1000, 3000));
1820 
1821 	guard = _dif_generate_split(&sgl, 4000, 96 + 128, guard, 0, &ctx);
1822 	CU_ASSERT(guard == GUARD_SEED);
1823 	CU_ASSERT(sgl.iov_offset == 0);
1824 	CU_ASSERT(sgl.iovcnt == 0);
1825 
1826 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
1827 	CU_ASSERT(rc == 0);
1828 
1829 	_dif_sgl_init(&sgl, &iov, 1);
1830 
1831 	rc = dif_verify(&sgl, 1, &ctx, NULL);
1832 	CU_ASSERT(rc == 0);
1833 
1834 	buf2 = calloc(1, 4096 + 128);
1835 	SPDK_CU_ASSERT_FATAL(buf2 != NULL);
1836 	_iov_set_buf(&iov, buf2, 4096 + 128);
1837 
1838 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
1839 	CU_ASSERT(rc == 0);
1840 
1841 	_dif_sgl_init(&sgl, &iov, 1);
1842 
1843 	dif_generate(&sgl, 1, &ctx);
1844 
1845 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
1846 	CU_ASSERT(rc == 0);
1847 
1848 	_dif_sgl_init(&sgl, &iov, 1);
1849 
1850 	rc = dif_verify(&sgl, 1, &ctx, NULL);
1851 	CU_ASSERT(rc == 0);
1852 
1853 	rc = memcmp(buf1, buf2, 4096 + 128);
1854 	CU_ASSERT(rc == 0);
1855 
1856 	free(buf1);
1857 	free(buf2);
1858 }
1859 
1860 static void
1861 set_md_interleave_iovs_multi_segments_test(void)
1862 {
1863 	struct spdk_dif_ctx ctx = {};
1864 	struct spdk_dif_error err_blk = {};
1865 	struct iovec iov1 = {}, iov2 = {}, dif_iovs[4] = {};
1866 	uint32_t dif_check_flags, data_len, read_len, data_offset, read_offset, mapped_len = 0;
1867 	uint8_t *buf1, *buf2;
1868 	int rc;
1869 
1870 	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1871 			  SPDK_DIF_FLAGS_REFTAG_CHECK;
1872 
1873 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
1874 			       dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED);
1875 	CU_ASSERT(rc == 0);
1876 
1877 	/* The first data buffer:
1878 	 * - Data buffer is split into multi data segments
1879 	 * - For each data segment,
1880 	 *  - Create iovec array to Leave a space for metadata for each block
1881 	 *  - Split vectored read and so creating iovec array is done before every vectored read.
1882 	 */
1883 	buf1 = calloc(1, (4096 + 128) * 4);
1884 	SPDK_CU_ASSERT_FATAL(buf1 != NULL);
1885 	_iov_set_buf(&iov1, buf1, (4096 + 128) * 4);
1886 
1887 	/* 1st data segment */
1888 	data_offset = 0;
1889 	data_len = 1024;
1890 
1891 	spdk_dif_ctx_set_data_offset(&ctx, data_offset);
1892 
1893 	read_offset = 0;
1894 
1895 	/* 1st read in 1st data segment */
1896 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1897 					     read_offset, data_len - read_offset,
1898 					     &mapped_len, &ctx);
1899 	CU_ASSERT(rc == 1);
1900 	CU_ASSERT(mapped_len == 1024);
1901 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1, 1024) == true);
1902 
1903 	read_len = ut_readv(data_offset + read_offset, 1024, dif_iovs, 4);
1904 	CU_ASSERT(read_len == 1024);
1905 
1906 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
1907 	CU_ASSERT(rc == 0);
1908 
1909 	read_offset += read_len;
1910 	CU_ASSERT(read_offset == data_len);
1911 
1912 	/* 2nd data segment */
1913 	data_offset += data_len;
1914 	data_len = 3072 + 4096 * 2 + 512;
1915 
1916 	spdk_dif_ctx_set_data_offset(&ctx, data_offset);
1917 	_iov_set_buf(&iov1, buf1 + 1024, 3072 + 128 + (4096 + 128) * 3 + 512);
1918 
1919 	read_offset = 0;
1920 
1921 	/* 1st read in 2nd data segment */
1922 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1923 					     read_offset, data_len - read_offset,
1924 					     &mapped_len, &ctx);
1925 	CU_ASSERT(rc == 4);
1926 	CU_ASSERT(mapped_len == 3072 + 4096 * 2 + 512);
1927 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 1024, 3072) == true);
1928 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1929 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1930 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 512) == true);
1931 
1932 	read_len = ut_readv(data_offset + read_offset, 3071, dif_iovs, 4);
1933 	CU_ASSERT(read_len == 3071);
1934 
1935 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
1936 	CU_ASSERT(rc == 0);
1937 
1938 	read_offset += read_len;
1939 
1940 	/* 2nd read in 2nd data segment */
1941 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1942 					     read_offset, data_len - read_offset,
1943 					     &mapped_len, &ctx);
1944 	CU_ASSERT(rc == 4);
1945 	CU_ASSERT(mapped_len == 1 + 4096 * 2 + 512);
1946 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 4095, 1) == true);
1947 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
1948 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
1949 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 512) == true);
1950 
1951 	read_len = ut_readv(data_offset + read_offset, 1 + 4096 * 2 + 512, dif_iovs, 4);
1952 	CU_ASSERT(read_len == 1 + 4096 * 2 + 512);
1953 
1954 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
1955 	CU_ASSERT(rc == 0);
1956 
1957 	read_offset += read_len;
1958 	CU_ASSERT(read_offset == data_len);
1959 
1960 	/* 3rd data segment */
1961 	data_offset += data_len;
1962 	data_len = 3584;
1963 
1964 	spdk_dif_ctx_set_data_offset(&ctx, data_offset);
1965 	_iov_set_buf(&iov1, buf1 + (4096 + 128) * 3 + 512, 3584 + 128);
1966 
1967 	read_offset = 0;
1968 
1969 	/* 1st read in 3rd data segment */
1970 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
1971 					     read_offset, data_len - read_offset,
1972 					     &mapped_len, &ctx);
1973 	CU_ASSERT(rc == 1);
1974 	CU_ASSERT(mapped_len == 3584);
1975 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + (4096 + 128) * 3 + 512, 3584) == true);
1976 
1977 	read_len = ut_readv(data_offset + read_offset, 3584, dif_iovs, 1);
1978 	CU_ASSERT(read_len == 3584);
1979 
1980 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
1981 	CU_ASSERT(rc == 0);
1982 
1983 	read_offset += read_len;
1984 	CU_ASSERT(read_offset == data_len);
1985 	data_offset += data_len;
1986 	CU_ASSERT(data_offset == 4096 * 4);
1987 
1988 	spdk_dif_ctx_set_data_offset(&ctx, 0);
1989 	_iov_set_buf(&iov1, buf1, (4096 + 128) * 4);
1990 
1991 	/* The second data buffer:
1992 	 * - Set data pattern with a space for metadata for each block.
1993 	 */
1994 	buf2 = calloc(1, (4096 + 128) * 4);
1995 	SPDK_CU_ASSERT_FATAL(buf2 != NULL);
1996 	_iov_set_buf(&iov2, buf2, (4096 + 128) * 4);
1997 
1998 	rc = ut_data_pattern_generate(&iov2, 1, 4096 + 128, 128, 4);
1999 	CU_ASSERT(rc == 0);
2000 
2001 	rc = spdk_dif_generate(&iov2, 1, 4, &ctx);
2002 	CU_ASSERT(rc == 0);
2003 
2004 	rc = spdk_dif_verify(&iov1, 1, 4, &ctx, &err_blk);
2005 	CU_ASSERT(rc == 0);
2006 
2007 	rc = spdk_dif_verify(&iov2, 1, 4, &ctx, &err_blk);
2008 	CU_ASSERT(rc == 0);
2009 
2010 	/* Compare the first and the second data buffer by byte. */
2011 	rc = memcmp(buf1, buf2, (4096 + 128) * 4);
2012 	CU_ASSERT(rc == 0);
2013 
2014 	free(buf1);
2015 	free(buf2);
2016 }
2017 
2018 static void
2019 _dif_verify_split_test(void)
2020 {
2021 	struct spdk_dif_ctx ctx = {};
2022 	struct spdk_dif_error err_blk = {};
2023 	struct iovec iov;
2024 	uint8_t *buf;
2025 	struct _dif_sgl sgl;
2026 	uint16_t guard = 0, prev_guard = 0;
2027 	uint32_t dif_flags;
2028 	int rc;
2029 
2030 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2031 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2032 
2033 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
2034 			       dif_flags, 0, 0, 0, 0, GUARD_SEED);
2035 	CU_ASSERT(rc == 0);
2036 
2037 	buf = calloc(1, 4096 + 128);
2038 	SPDK_CU_ASSERT_FATAL(buf != NULL);
2039 	_iov_set_buf(&iov, buf, 4096 + 128);
2040 
2041 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
2042 	CU_ASSERT(rc == 0);
2043 
2044 	_dif_sgl_init(&sgl, &iov, 1);
2045 
2046 	dif_generate(&sgl, 1, &ctx);
2047 
2048 	_dif_sgl_init(&sgl, &iov, 1);
2049 
2050 	guard = GUARD_SEED;
2051 	prev_guard = GUARD_SEED;
2052 
2053 	rc = _dif_verify_split(&sgl, 0, 1000, &guard, 0, &ctx, &err_blk);
2054 	CU_ASSERT(rc == 0);
2055 	CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf, 1000));
2056 	CU_ASSERT(sgl.iov_offset == 1000);
2057 
2058 	prev_guard = guard;
2059 
2060 	rc = _dif_verify_split(&sgl, 1000, 3000, &guard, 0, &ctx, &err_blk);
2061 	CU_ASSERT(rc == 0);
2062 	CU_ASSERT(guard == spdk_crc16_t10dif(prev_guard, buf + 1000, 3000));
2063 	CU_ASSERT(sgl.iov_offset == 4000);
2064 
2065 	rc = _dif_verify_split(&sgl, 4000, 96 + 128, &guard, 0, &ctx, &err_blk);
2066 	CU_ASSERT(rc == 0);
2067 	CU_ASSERT(guard == GUARD_SEED);
2068 	CU_ASSERT(sgl.iov_offset == 0);
2069 	CU_ASSERT(sgl.iovcnt == 0);
2070 
2071 	_dif_sgl_init(&sgl, &iov, 1);
2072 
2073 	rc = dif_verify(&sgl, 1, &ctx, &err_blk);
2074 	CU_ASSERT(rc == 0);
2075 
2076 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
2077 	CU_ASSERT(rc == 0);
2078 
2079 	free(buf);
2080 }
2081 
2082 static void
2083 dif_verify_stream_multi_segments_test(void)
2084 {
2085 	struct spdk_dif_ctx ctx = {};
2086 	struct spdk_dif_error err_blk = {};
2087 	struct iovec iov = {};
2088 	uint8_t *buf;
2089 	uint32_t dif_flags;
2090 	int rc;
2091 
2092 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2093 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2094 
2095 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
2096 			       dif_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED);
2097 	CU_ASSERT(rc == 0);
2098 
2099 	buf = calloc(1, (4096 + 128) * 4);
2100 	SPDK_CU_ASSERT_FATAL(buf != NULL);
2101 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
2102 
2103 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 4);
2104 	CU_ASSERT(rc == 0);
2105 
2106 	rc = spdk_dif_generate(&iov, 1, 4, &ctx);
2107 	CU_ASSERT(rc == 0);
2108 
2109 	/* 1st data segment */
2110 	_iov_set_buf(&iov, buf, 1024);
2111 	spdk_dif_ctx_set_data_offset(&ctx, 0);
2112 
2113 	rc = spdk_dif_verify_stream(&iov, 1, 0, 1024, &ctx, &err_blk);
2114 	CU_ASSERT(rc == 0);
2115 
2116 	/* 2nd data segment */
2117 	_iov_set_buf(&iov, buf + 1024, (3072 + 128) + (4096 + 128) * 2 + 512);
2118 	spdk_dif_ctx_set_data_offset(&ctx, 1024);
2119 
2120 	rc = spdk_dif_verify_stream(&iov, 1, 0, 3072 + 4096 * 2 + 512, &ctx, &err_blk);
2121 	CU_ASSERT(rc == 0);
2122 
2123 	/* 3rd data segment */
2124 	_iov_set_buf(&iov, buf + (4096 + 128) * 3 + 512, 3584 + 128);
2125 	spdk_dif_ctx_set_data_offset(&ctx, 4096 * 3);
2126 
2127 	rc = spdk_dif_verify_stream(&iov, 1, 0, 3584, &ctx, &err_blk);
2128 	CU_ASSERT(rc == 0);
2129 
2130 	/* verify all data segments once */
2131 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
2132 	spdk_dif_ctx_set_data_offset(&ctx, 0);
2133 
2134 	rc = spdk_dif_verify(&iov, 1, 4, &ctx, &err_blk);
2135 	CU_ASSERT(rc == 0);
2136 
2137 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 4);
2138 	CU_ASSERT(rc == 0);
2139 
2140 	free(buf);
2141 }
2142 
2143 #define UT_CRC32C_XOR	0xffffffffUL
2144 
2145 static void
2146 update_crc32c_test(void)
2147 {
2148 	struct spdk_dif_ctx ctx = {};
2149 	struct iovec iovs[7];
2150 	uint32_t crc32c1, crc32c2, crc32c3, crc32c4;
2151 	uint32_t dif_flags;
2152 	int i, rc;
2153 
2154 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2155 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2156 
2157 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
2158 			       dif_flags, 0, 0, 0, 0, 0);
2159 	CU_ASSERT(rc == 0);
2160 
2161 	/* data[0][255:0] */
2162 	_iov_alloc_buf(&iovs[0], 256);
2163 
2164 	/* data[0][511:256], md[0][0] */
2165 	_iov_alloc_buf(&iovs[1], 256 + 1);
2166 
2167 	/* md[0][4:1] */
2168 	_iov_alloc_buf(&iovs[2], 4);
2169 
2170 	/* md[0][7:5], data[1][122:0] */
2171 	_iov_alloc_buf(&iovs[3], 3 + 123);
2172 
2173 	/* data[1][511:123], md[1][5:0] */
2174 	_iov_alloc_buf(&iovs[4], 389 + 6);
2175 
2176 	/* md[1][7:6], data[2][511:0], md[2][7:0], data[3][431:0] */
2177 	_iov_alloc_buf(&iovs[5], 2 + 512 + 8 + 432);
2178 
2179 	/* data[3][511:432], md[3][7:0] */
2180 	_iov_alloc_buf(&iovs[6], 80 + 8);
2181 
2182 	rc = ut_data_pattern_generate(iovs, 7, 512 + 8, 8, 4);
2183 	CU_ASSERT(rc == 0);
2184 
2185 	crc32c1 = UT_CRC32C_XOR;
2186 
2187 	rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c1, &ctx);
2188 	CU_ASSERT(rc == 0);
2189 
2190 	/* Test if DIF doesn't affect CRC for split case. */
2191 	rc = spdk_dif_generate(iovs, 7, 4, &ctx);
2192 	CU_ASSERT(rc == 0);
2193 
2194 	crc32c2 = UT_CRC32C_XOR;
2195 
2196 	rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c2, &ctx);
2197 	CU_ASSERT(rc == 0);
2198 
2199 	CU_ASSERT(crc32c1 == crc32c2);
2200 
2201 	for (i = 0; i < 7; i++) {
2202 		_iov_free_buf(&iovs[i]);
2203 	}
2204 
2205 	/* Test if CRC is same regardless of splitting. */
2206 	for (i = 0; i < 4; i++) {
2207 		_iov_alloc_buf(&iovs[i], 512 + 8);
2208 	}
2209 
2210 	rc = ut_data_pattern_generate(iovs, 4, 512 + 8, 8, 4);
2211 	CU_ASSERT(rc == 0);
2212 
2213 	crc32c3 = UT_CRC32C_XOR;
2214 
2215 	rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c3, &ctx);
2216 	CU_ASSERT(rc == 0);
2217 
2218 	CU_ASSERT(crc32c1 == crc32c3);
2219 
2220 	/* Test if DIF doesn't affect CRC for non-split case. */
2221 	rc = spdk_dif_generate(iovs, 4, 4, &ctx);
2222 	CU_ASSERT(rc == 0);
2223 
2224 	crc32c4 = UT_CRC32C_XOR;
2225 
2226 	rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c4, &ctx);
2227 	CU_ASSERT(rc == 0);
2228 
2229 	CU_ASSERT(crc32c1 == crc32c4);
2230 
2231 	for (i = 0; i < 4; i++) {
2232 		_iov_free_buf(&iovs[i]);
2233 	}
2234 }
2235 
2236 static void
2237 _dif_update_crc32c_split_test(void)
2238 {
2239 	struct spdk_dif_ctx ctx = {};
2240 	struct iovec iov;
2241 	uint8_t *buf;
2242 	struct _dif_sgl sgl;
2243 	uint32_t dif_flags, crc32c, prev_crc32c;
2244 	int rc;
2245 
2246 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2247 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2248 
2249 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
2250 			       dif_flags, 0, 0, 0, 0, GUARD_SEED);
2251 	CU_ASSERT(rc == 0);
2252 
2253 	buf = calloc(1, 4096 + 128);
2254 	SPDK_CU_ASSERT_FATAL(buf != NULL);
2255 	_iov_set_buf(&iov, buf, 4096 + 128);
2256 
2257 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
2258 	CU_ASSERT(rc == 0);
2259 
2260 	_dif_sgl_init(&sgl, &iov, 1);
2261 
2262 	dif_generate(&sgl, 1, &ctx);
2263 
2264 	_dif_sgl_init(&sgl, &iov, 1);
2265 
2266 	crc32c = _dif_update_crc32c_split(&sgl, 0, 1000, UT_CRC32C_XOR, &ctx);
2267 	CU_ASSERT(crc32c == spdk_crc32c_update(buf, 1000, UT_CRC32C_XOR));
2268 
2269 	prev_crc32c = crc32c;
2270 
2271 	crc32c = _dif_update_crc32c_split(&sgl, 1000, 3000, prev_crc32c, &ctx);
2272 	CU_ASSERT(crc32c == spdk_crc32c_update(buf + 1000, 3000, prev_crc32c));
2273 
2274 	prev_crc32c = crc32c;
2275 
2276 	crc32c = _dif_update_crc32c_split(&sgl, 4000, 96 + 128, prev_crc32c, &ctx);
2277 	CU_ASSERT(crc32c == spdk_crc32c_update(buf + 4000, 96, prev_crc32c));
2278 
2279 	CU_ASSERT(crc32c == spdk_crc32c_update(buf, 4096, UT_CRC32C_XOR));
2280 
2281 	free(buf);
2282 }
2283 
2284 static void
2285 dif_update_crc32c_stream_multi_segments_test(void)
2286 {
2287 	struct spdk_dif_ctx ctx = {};
2288 	struct iovec iov = {};
2289 	uint8_t *buf;
2290 	uint32_t dif_flags, crc32c1, crc32c2;
2291 	int rc;
2292 
2293 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2294 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2295 
2296 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
2297 			       dif_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED);
2298 	CU_ASSERT(rc == 0);
2299 
2300 	buf = calloc(1, (4096 + 128) * 4);
2301 	SPDK_CU_ASSERT_FATAL(buf != NULL);
2302 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
2303 
2304 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 4);
2305 	CU_ASSERT(rc == 0);
2306 
2307 	rc = spdk_dif_generate(&iov, 1, 4, &ctx);
2308 	CU_ASSERT(rc == 0);
2309 
2310 	crc32c1 = UT_CRC32C_XOR;
2311 	crc32c2 = UT_CRC32C_XOR;
2312 
2313 	/* 1st data segment */
2314 	_iov_set_buf(&iov, buf, 1024);
2315 	spdk_dif_ctx_set_data_offset(&ctx, 0);
2316 
2317 	rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 1024, &crc32c1, &ctx);
2318 	CU_ASSERT(rc == 0);
2319 
2320 	/* 2nd data segment */
2321 	_iov_set_buf(&iov, buf + 1024, (3072 + 128) + (4096 + 128) * 2 + 512);
2322 	spdk_dif_ctx_set_data_offset(&ctx, 1024);
2323 
2324 	rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 3072 + 4096 * 2 + 512, &crc32c1, &ctx);
2325 	CU_ASSERT(rc == 0);
2326 
2327 	/* 3rd data segment */
2328 	_iov_set_buf(&iov, buf + (4096 + 128) * 3 + 512, 3584 + 128);
2329 	spdk_dif_ctx_set_data_offset(&ctx, 4096 * 3);
2330 
2331 	rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 3584, &crc32c1, &ctx);
2332 	CU_ASSERT(rc == 0);
2333 
2334 	/* Update CRC32C for all data segments once */
2335 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
2336 	spdk_dif_ctx_set_data_offset(&ctx, 0);
2337 
2338 	rc = spdk_dif_update_crc32c(&iov, 1, 4, &crc32c2, &ctx);
2339 	CU_ASSERT(rc == 0);
2340 
2341 	CU_ASSERT(crc32c1 == crc32c2);
2342 
2343 	free(buf);
2344 }
2345 
2346 static void
2347 get_range_with_md_test(void)
2348 {
2349 	struct spdk_dif_ctx ctx = {};
2350 	uint32_t buf_offset, buf_len;
2351 	int rc;
2352 
2353 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, 0, 0, 0, 0, 0, 0, 0);
2354 	CU_ASSERT(rc == 0);
2355 
2356 	spdk_dif_get_range_with_md(0, 2048, &buf_offset, &buf_len, &ctx);
2357 	CU_ASSERT(buf_offset == 0);
2358 	CU_ASSERT(buf_len == 2048);
2359 
2360 	spdk_dif_get_range_with_md(2048, 4096, &buf_offset, &buf_len, &ctx);
2361 	CU_ASSERT(buf_offset == 2048);
2362 	CU_ASSERT(buf_len == 4096 + 128);
2363 
2364 	spdk_dif_get_range_with_md(4096, 10240, &buf_offset, &buf_len, &ctx);
2365 	CU_ASSERT(buf_offset == 4096 + 128);
2366 	CU_ASSERT(buf_len == 10240 + 256);
2367 
2368 	spdk_dif_get_range_with_md(10240, 2048, &buf_offset, &buf_len, &ctx);
2369 	CU_ASSERT(buf_offset == 10240 + 256);
2370 	CU_ASSERT(buf_len == 2048 + 128);
2371 
2372 	buf_len = spdk_dif_get_length_with_md(6144, &ctx);
2373 	CU_ASSERT(buf_len == 6144 + 128);
2374 }
2375 
2376 static void
2377 dif_generate_remap_and_verify(struct iovec *iovs, int iovcnt,
2378 			      uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
2379 			      bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
2380 			      uint32_t init_ref_tag, uint32_t remapped_init_ref_tag,
2381 			      uint16_t apptag_mask, uint16_t app_tag)
2382 {
2383 	struct spdk_dif_ctx ctx = {};
2384 	int rc;
2385 
2386 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
2387 	CU_ASSERT(rc == 0);
2388 
2389 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
2390 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED);
2391 	CU_ASSERT(rc == 0);
2392 
2393 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
2394 	CU_ASSERT(rc == 0);
2395 
2396 	spdk_dif_ctx_set_remapped_init_ref_tag(&ctx, remapped_init_ref_tag);
2397 
2398 	rc = spdk_dif_remap_ref_tag(iovs, iovcnt, num_blocks, &ctx, NULL);
2399 	CU_ASSERT(rc == 0);
2400 
2401 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
2402 			       remapped_init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED);
2403 	CU_ASSERT(rc == 0);
2404 
2405 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL);
2406 	CU_ASSERT(rc == 0);
2407 
2408 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
2409 	CU_ASSERT(rc == 0);
2410 }
2411 
2412 static void
2413 dif_sec_4096_md_128_prchk_7_multi_iovs_remap_test(void)
2414 {
2415 	struct iovec iovs[4];
2416 	int i, num_blocks;
2417 	uint32_t dif_flags;
2418 
2419 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2420 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2421 
2422 	num_blocks = 0;
2423 
2424 	for (i = 0; i < 4; i++) {
2425 		_iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1));
2426 		num_blocks += i + 1;
2427 	}
2428 
2429 	dif_generate_remap_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
2430 				      dif_flags, 22, 99, 0xFFFF, 0x22);
2431 
2432 	dif_generate_remap_and_verify(iovs, 4, 512 + 8, 8, num_blocks, true, SPDK_DIF_TYPE1,
2433 				      dif_flags, 22, 99, 0xFFFF, 0x22);
2434 
2435 	for (i = 0; i < 4; i++) {
2436 		_iov_free_buf(&iovs[i]);
2437 	}
2438 }
2439 
2440 static void
2441 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test(void)
2442 {
2443 	struct iovec iovs[11];
2444 	uint32_t dif_flags;
2445 	int i;
2446 
2447 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2448 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2449 
2450 	/* data[0][1000:0] */
2451 	_iov_alloc_buf(&iovs[0], 1000);
2452 
2453 	/* data[0][3095:1000], guard[0][0] */
2454 	_iov_alloc_buf(&iovs[1], 3096 + 1);
2455 
2456 	/* guard[0][1], apptag[0][0] */
2457 	_iov_alloc_buf(&iovs[2], 1 + 1);
2458 
2459 	/* apptag[0][1], reftag[0][0] */
2460 	_iov_alloc_buf(&iovs[3], 1 + 1);
2461 
2462 	/* reftag[0][3:1], ignore[0][59:0] */
2463 	_iov_alloc_buf(&iovs[4], 3 + 60);
2464 
2465 	/* ignore[119:60], data[1][3050:0] */
2466 	_iov_alloc_buf(&iovs[5], 60 + 3051);
2467 
2468 	/* data[1][4095:3050], guard[1][0] */
2469 	_iov_alloc_buf(&iovs[6], 1045 + 1);
2470 
2471 	/* guard[1][1], apptag[1][0] */
2472 	_iov_alloc_buf(&iovs[7], 1 + 1);
2473 
2474 	/* apptag[1][1], reftag[1][0] */
2475 	_iov_alloc_buf(&iovs[8], 1 + 1);
2476 
2477 	/* reftag[1][3:1], ignore[1][9:0] */
2478 	_iov_alloc_buf(&iovs[9], 3 + 10);
2479 
2480 	/* ignore[1][127:9] */
2481 	_iov_alloc_buf(&iovs[10], 118);
2482 
2483 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
2484 				      22, 99, 0xFFFF, 0x22);
2485 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
2486 				      22, 99, 0xFFFF, 0x22);
2487 
2488 	for (i = 0; i < 11; i++) {
2489 		_iov_free_buf(&iovs[i]);
2490 	}
2491 }
2492 
2493 static void
2494 dix_generate_remap_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
2495 			      uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
2496 			      bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
2497 			      uint32_t init_ref_tag, uint32_t remapped_init_ref_tag,
2498 			      uint16_t apptag_mask, uint16_t app_tag)
2499 {
2500 	struct spdk_dif_ctx ctx;
2501 	int rc;
2502 
2503 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
2504 	CU_ASSERT(rc == 0);
2505 
2506 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
2507 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED);
2508 	CU_ASSERT(rc == 0);
2509 
2510 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
2511 	CU_ASSERT(rc == 0);
2512 
2513 	spdk_dif_ctx_set_remapped_init_ref_tag(&ctx, remapped_init_ref_tag);
2514 
2515 	rc = spdk_dix_remap_ref_tag(md_iov, num_blocks, &ctx, NULL);
2516 	CU_ASSERT(rc == 0);
2517 
2518 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
2519 			       remapped_init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED);
2520 	CU_ASSERT(rc == 0);
2521 
2522 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL);
2523 	CU_ASSERT(rc == 0);
2524 
2525 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks);
2526 	CU_ASSERT(rc == 0);
2527 }
2528 
2529 static void
2530 dix_sec_4096_md_128_prchk_7_multi_iovs_remap(void)
2531 {
2532 	struct iovec iovs[4], md_iov;
2533 	uint32_t dif_flags;
2534 	int i, num_blocks;
2535 
2536 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2537 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2538 
2539 	num_blocks = 0;
2540 
2541 	for (i = 0; i < 4; i++) {
2542 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
2543 		num_blocks += i + 1;
2544 	}
2545 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
2546 
2547 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2548 				      dif_flags, 22, 99, 0xFFFF, 0x22);
2549 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
2550 				      dif_flags, 22, 99, 0xFFFF, 0x22);
2551 
2552 	for (i = 0; i < 4; i++) {
2553 		_iov_free_buf(&iovs[i]);
2554 	}
2555 	_iov_free_buf(&md_iov);
2556 }
2557 
2558 static void
2559 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits_remap(void)
2560 {
2561 	struct iovec iovs[6], md_iov;
2562 	uint32_t dif_flags;
2563 	int i;
2564 
2565 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2566 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2567 
2568 	/* data[0][255:0] */
2569 	_iov_alloc_buf(&iovs[0], 256);
2570 
2571 	/* data[0][511:256], data[1][255:0] */
2572 	_iov_alloc_buf(&iovs[1], 256 + 256);
2573 
2574 	/* data[1][382:256] */
2575 	_iov_alloc_buf(&iovs[2], 128);
2576 
2577 	/* data[1][383] */
2578 	_iov_alloc_buf(&iovs[3], 1);
2579 
2580 	/* data[1][510:384] */
2581 	_iov_alloc_buf(&iovs[4], 126);
2582 
2583 	/* data[1][511], data[2][511:0], data[3][511:0] */
2584 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
2585 
2586 	_iov_alloc_buf(&md_iov, 8 * 4);
2587 
2588 	dix_generate_remap_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1,
2589 				      dif_flags, 22, 99, 0xFFFF, 0x22);
2590 
2591 	for (i = 0; i < 6; i++) {
2592 		_iov_free_buf(&iovs[i]);
2593 	}
2594 	_iov_free_buf(&md_iov);
2595 }
2596 
2597 int
2598 main(int argc, char **argv)
2599 {
2600 	CU_pSuite	suite = NULL;
2601 	unsigned int	num_failures;
2602 
2603 	CU_set_error_action(CUEA_ABORT);
2604 	CU_initialize_registry();
2605 
2606 	suite = CU_add_suite("dif", NULL, NULL);
2607 
2608 	CU_ADD_TEST(suite, dif_generate_and_verify_test);
2609 	CU_ADD_TEST(suite, dif_disable_check_test);
2610 	CU_ADD_TEST(suite, dif_sec_512_md_0_error_test);
2611 	CU_ADD_TEST(suite, dif_guard_seed_test);
2612 	CU_ADD_TEST(suite, dif_disable_sec_512_md_8_single_iov_test);
2613 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_0_single_iov_test);
2614 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test);
2615 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_test);
2616 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test);
2617 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test);
2618 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test);
2619 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test);
2620 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test);
2621 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test);
2622 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test);
2623 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test);
2624 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test);
2625 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test);
2626 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test);
2627 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test);
2628 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test);
2629 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_0_single_iov);
2630 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs);
2631 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_7_multi_iovs);
2632 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data);
2633 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits);
2634 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test);
2635 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test);
2636 	CU_ADD_TEST(suite, dix_sec_512_md_0_error);
2637 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_0_single_iov);
2638 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs);
2639 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs);
2640 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_split_data);
2641 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits);
2642 	CU_ADD_TEST(suite, dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test);
2643 	CU_ADD_TEST(suite, dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test);
2644 	CU_ADD_TEST(suite, set_md_interleave_iovs_test);
2645 	CU_ADD_TEST(suite, set_md_interleave_iovs_split_test);
2646 	CU_ADD_TEST(suite, dif_generate_stream_test);
2647 	CU_ADD_TEST(suite, set_md_interleave_iovs_alignment_test);
2648 	CU_ADD_TEST(suite, _dif_generate_split_test);
2649 	CU_ADD_TEST(suite, set_md_interleave_iovs_multi_segments_test);
2650 	CU_ADD_TEST(suite, _dif_verify_split_test);
2651 	CU_ADD_TEST(suite, dif_verify_stream_multi_segments_test);
2652 	CU_ADD_TEST(suite, update_crc32c_test);
2653 	CU_ADD_TEST(suite, _dif_update_crc32c_split_test);
2654 	CU_ADD_TEST(suite, dif_update_crc32c_stream_multi_segments_test);
2655 	CU_ADD_TEST(suite, get_range_with_md_test);
2656 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_remap_test);
2657 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test);
2658 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs_remap);
2659 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits_remap);
2660 
2661 	CU_basic_set_mode(CU_BRM_VERBOSE);
2662 
2663 	CU_basic_run_tests();
2664 
2665 	num_failures = CU_get_number_of_failures();
2666 	CU_cleanup_registry();
2667 
2668 	return num_failures;
2669 }
2670