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