xref: /spdk/test/unit/lib/util/dif.c/dif_ut.c (revision b37db06935181fd0e8f5592a96d860040abaa201)
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_internal/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 uint64_t
127 _generate_guard(uint64_t guard_seed, void *buf, size_t buf_len,
128 		enum spdk_dif_pi_format dif_pi_format)
129 {
130 	uint64_t guard;
131 
132 	if (dif_pi_format == SPDK_DIF_PI_FORMAT_16) {
133 		guard = (uint64_t)spdk_crc16_t10dif((uint16_t)guard_seed, buf, buf_len);
134 	} else if (dif_pi_format == SPDK_DIF_PI_FORMAT_32) {
135 		guard = (uint64_t)spdk_crc32c_nvme(buf, buf_len, guard_seed);
136 	} else {
137 		guard = spdk_crc64_nvme(buf, buf_len, guard_seed);
138 	}
139 
140 	return guard;
141 }
142 
143 static void
144 _dif_generate_and_verify(struct iovec *iov,
145 			 uint32_t block_size, uint32_t md_size, bool dif_loc,
146 			 enum spdk_dif_type dif_type, uint32_t dif_flags,
147 			 enum spdk_dif_pi_format dif_pi_format,
148 			 uint64_t ref_tag, uint64_t e_ref_tag,
149 			 uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag,
150 			 bool expect_pass)
151 {
152 	struct spdk_dif_ctx ctx = {};
153 	uint32_t guard_interval;
154 	uint64_t guard = 0;
155 	int rc;
156 
157 	rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1);
158 	CU_ASSERT(rc == 0);
159 
160 	ctx.dif_pi_format = dif_pi_format;
161 
162 	guard_interval = _get_guard_interval(block_size, md_size, dif_loc, true,
163 					     _dif_size(ctx.dif_pi_format));
164 
165 	ctx.dif_type = dif_type;
166 	ctx.dif_flags = dif_flags;
167 	ctx.init_ref_tag = ref_tag;
168 	ctx.app_tag = app_tag;
169 
170 	if (dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
171 		guard = _generate_guard(0, iov->iov_base, guard_interval, ctx.dif_pi_format);
172 	}
173 	_dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx);
174 
175 	ctx.init_ref_tag = e_ref_tag;
176 	ctx.apptag_mask = apptag_mask;
177 	ctx.app_tag = e_app_tag;
178 
179 	rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx, NULL);
180 	CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0));
181 
182 	rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1);
183 	CU_ASSERT(rc == 0);
184 }
185 
186 static void
187 dif_generate_and_verify_test(void)
188 {
189 	struct iovec iov;
190 	uint32_t dif_flags;
191 
192 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
193 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
194 
195 	_iov_alloc_buf(&iov, 4096 + 128);
196 
197 	/* Positive cases */
198 
199 	/* The case that DIF is contained in the first 8/16 bytes of metadata. */
200 	_dif_generate_and_verify(&iov,
201 				 4096 + 128, 128, true,
202 				 SPDK_DIF_TYPE1, dif_flags,
203 				 SPDK_DIF_PI_FORMAT_16,
204 				 22, 22,
205 				 0x22, 0xFFFF, 0x22,
206 				 true);
207 
208 	_dif_generate_and_verify(&iov,
209 				 4096 + 128, 128, true,
210 				 SPDK_DIF_TYPE1, dif_flags,
211 				 SPDK_DIF_PI_FORMAT_32,
212 				 22, 22,
213 				 0x22, 0xFFFF, 0x22,
214 				 true);
215 
216 	_dif_generate_and_verify(&iov,
217 				 4096 + 128, 128, true,
218 				 SPDK_DIF_TYPE1, dif_flags,
219 				 SPDK_DIF_PI_FORMAT_64,
220 				 22, 22,
221 				 0x22, 0xFFFF, 0x22,
222 				 true);
223 
224 	/* The case that DIF is contained in the last 8/16 bytes of metadata. */
225 	_dif_generate_and_verify(&iov,
226 				 4096 + 128, 128, false,
227 				 SPDK_DIF_TYPE1, dif_flags,
228 				 SPDK_DIF_PI_FORMAT_16,
229 				 22, 22,
230 				 0x22, 0xFFFF, 0x22,
231 				 true);
232 
233 	_dif_generate_and_verify(&iov,
234 				 4096 + 128, 128, false,
235 				 SPDK_DIF_TYPE1, dif_flags,
236 				 SPDK_DIF_PI_FORMAT_32,
237 				 22, 22,
238 				 0x22, 0xFFFF, 0x22,
239 				 true);
240 
241 	_dif_generate_and_verify(&iov,
242 				 4096 + 128, 128, false,
243 				 SPDK_DIF_TYPE1, dif_flags,
244 				 SPDK_DIF_PI_FORMAT_64,
245 				 22, 22,
246 				 0x22, 0xFFFF, 0x22,
247 				 true);
248 
249 	/* Negative cases */
250 
251 	/* Reference tag doesn't match. */
252 	_dif_generate_and_verify(&iov,
253 				 4096 + 128, 128, false,
254 				 SPDK_DIF_TYPE1, dif_flags,
255 				 SPDK_DIF_PI_FORMAT_16,
256 				 22, 23,
257 				 0x22, 0xFFFF, 0x22,
258 				 false);
259 
260 	_dif_generate_and_verify(&iov,
261 				 4096 + 128, 128, false,
262 				 SPDK_DIF_TYPE1, dif_flags,
263 				 SPDK_DIF_PI_FORMAT_32,
264 				 22, 23,
265 				 0x22, 0xFFFF, 0x22,
266 				 false);
267 
268 	_dif_generate_and_verify(&iov,
269 				 4096 + 128, 128, false,
270 				 SPDK_DIF_TYPE1, dif_flags,
271 				 SPDK_DIF_PI_FORMAT_64,
272 				 22, 23,
273 				 0x22, 0xFFFF, 0x22,
274 				 false);
275 
276 	/* Application tag doesn't match. */
277 	_dif_generate_and_verify(&iov,
278 				 4096 + 128, 128, false,
279 				 SPDK_DIF_TYPE1, dif_flags,
280 				 SPDK_DIF_PI_FORMAT_16,
281 				 22, 22,
282 				 0x22, 0xFFFF, 0x23,
283 				 false);
284 
285 	_dif_generate_and_verify(&iov,
286 				 4096 + 128, 128, false,
287 				 SPDK_DIF_TYPE1, dif_flags,
288 				 SPDK_DIF_PI_FORMAT_32,
289 				 22, 22,
290 				 0x22, 0xFFFF, 0x23,
291 				 false);
292 
293 	_dif_generate_and_verify(&iov,
294 				 4096 + 128, 128, false,
295 				 SPDK_DIF_TYPE1, dif_flags,
296 				 SPDK_DIF_PI_FORMAT_64,
297 				 22, 22,
298 				 0x22, 0xFFFF, 0x23,
299 				 false);
300 
301 	_iov_free_buf(&iov);
302 }
303 
304 static void
305 dif_disable_check_test(void)
306 {
307 	struct iovec iov;
308 	uint32_t dif_flags;
309 
310 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
311 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
312 
313 	_iov_alloc_buf(&iov, 4096 + 128);
314 
315 	/* The case that DIF check is disabled when the Application Tag is 0xFFFF for
316 	 * Type 1. DIF check is disabled and pass is expected.
317 	 */
318 	_dif_generate_and_verify(&iov,
319 				 4096 + 128, 128, false,
320 				 SPDK_DIF_TYPE1, dif_flags,
321 				 SPDK_DIF_PI_FORMAT_16,
322 				 22, 22,
323 				 0xFFFF, 0xFFFF, 0x22,
324 				 true);
325 
326 	_dif_generate_and_verify(&iov,
327 				 4096 + 128, 128, false,
328 				 SPDK_DIF_TYPE1, dif_flags,
329 				 SPDK_DIF_PI_FORMAT_32,
330 				 22, 22,
331 				 0xFFFF, 0xFFFF, 0x22,
332 				 true);
333 
334 	_dif_generate_and_verify(&iov,
335 				 4096 + 128, 128, false,
336 				 SPDK_DIF_TYPE1, dif_flags,
337 				 SPDK_DIF_PI_FORMAT_64,
338 				 22, 22,
339 				 0xFFFF, 0xFFFF, 0x22,
340 				 true);
341 
342 	/* The case that DIF check is not disabled when the Application Tag is 0xFFFF but
343 	 * the Reference Tag is not 0xFFFFFFFF for Type 3. DIF check is not disabled and
344 	 * fail is expected.
345 	 */
346 	_dif_generate_and_verify(&iov,
347 				 4096 + 128, 128, false,
348 				 SPDK_DIF_TYPE3, dif_flags,
349 				 SPDK_DIF_PI_FORMAT_16,
350 				 22, 22,
351 				 0xFFFF, 0xFFFF, 0x22,
352 				 false);
353 
354 	_dif_generate_and_verify(&iov,
355 				 4096 + 128, 128, false,
356 				 SPDK_DIF_TYPE3, dif_flags,
357 				 SPDK_DIF_PI_FORMAT_32,
358 				 22, 22,
359 				 0xFFFF, 0xFFFF, 0x22,
360 				 false);
361 
362 	_dif_generate_and_verify(&iov,
363 				 4096 + 128, 128, false,
364 				 SPDK_DIF_TYPE3, dif_flags,
365 				 SPDK_DIF_PI_FORMAT_64,
366 				 22, 22,
367 				 0xFFFF, 0xFFFF, 0x22,
368 				 false);
369 
370 	/* The case that DIF check is disabled when the Application Tag is 0xFFFF and
371 	 * the Reference Tag is 0xFFFFFFFF for Type 3. DIF check is disabled and
372 	 * pass is expected.
373 	 */
374 	_dif_generate_and_verify(&iov,
375 				 4096 + 128, 128, false,
376 				 SPDK_DIF_TYPE3, dif_flags,
377 				 SPDK_DIF_PI_FORMAT_16,
378 				 0xFFFFFFFF, 22,
379 				 0xFFFF, 0xFFFF, 0x22,
380 				 true);
381 
382 	_dif_generate_and_verify(&iov,
383 				 4096 + 128, 128, false,
384 				 SPDK_DIF_TYPE3, dif_flags,
385 				 SPDK_DIF_PI_FORMAT_32,
386 				 0xFFFFFFFFFFFFFFFF, 22,
387 				 0xFFFF, 0xFFFF, 0x22,
388 				 true);
389 
390 	_dif_generate_and_verify(&iov,
391 				 4096 + 128, 128, false,
392 				 SPDK_DIF_TYPE3, dif_flags,
393 				 SPDK_DIF_PI_FORMAT_64,
394 				 0xFFFFFFFFFFFFFFFF, 22,
395 				 0xFFFF, 0xFFFF, 0x22,
396 				 true);
397 
398 	_iov_free_buf(&iov);
399 }
400 
401 static void
402 _dif_generate_and_verify_different_pi_format(uint32_t dif_flags,
403 		enum spdk_dif_pi_format dif_pi_format_1, enum spdk_dif_pi_format dif_pi_format_2)
404 {
405 	struct spdk_dif_ctx ctx_1 = {}, ctx_2 = {};
406 	int rc;
407 	struct spdk_dif_ctx_init_ext_opts dif_opts;
408 	struct iovec iov;
409 	struct spdk_dif_error err_blk = {};
410 	uint8_t expected_err_type = 0;
411 
412 	if (dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) {
413 		expected_err_type = SPDK_DIF_GUARD_ERROR;
414 	} else if (dif_flags & SPDK_DIF_FLAGS_APPTAG_CHECK) {
415 		expected_err_type = SPDK_DIF_APPTAG_ERROR;
416 	} else if (dif_flags & SPDK_DIF_FLAGS_REFTAG_CHECK) {
417 		expected_err_type = SPDK_DIF_REFTAG_ERROR;
418 	} else {
419 		CU_ASSERT(false);
420 	}
421 
422 	CU_ASSERT(dif_pi_format_1 != dif_pi_format_2);
423 
424 	_iov_alloc_buf(&iov, 4096 + 128);
425 
426 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
427 	CU_ASSERT(rc == 0);
428 
429 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
430 	dif_opts.dif_pi_format = dif_pi_format_1;
431 	rc = spdk_dif_ctx_init(&ctx_1, 4096 + 128, 128, true, true, SPDK_DIF_TYPE1, dif_flags,
432 			       12, 0xFFFF, 23, 0, 0, &dif_opts);
433 	CU_ASSERT(rc == 0);
434 
435 	rc = spdk_dif_generate(&iov, 1, 1, &ctx_1);
436 	CU_ASSERT(rc == 0);
437 
438 	dif_opts.dif_pi_format = dif_pi_format_2;
439 	rc = spdk_dif_ctx_init(&ctx_2, 4096 + 128, 128, true, true, SPDK_DIF_TYPE1, dif_flags,
440 			       12, 0xFFFF, 23, 0, 0, &dif_opts);
441 	CU_ASSERT(rc == 0);
442 
443 	rc = spdk_dif_verify(&iov, 1, 1, &ctx_2, &err_blk);
444 	CU_ASSERT(rc != 0);
445 	CU_ASSERT(err_blk.err_type == expected_err_type);
446 
447 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
448 	CU_ASSERT(rc == 0);
449 
450 	_iov_free_buf(&iov);
451 }
452 
453 static void
454 dif_generate_and_verify_different_pi_formats_test(void)
455 {
456 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_GUARD_CHECK,
457 			SPDK_DIF_PI_FORMAT_16, SPDK_DIF_PI_FORMAT_32);
458 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_GUARD_CHECK,
459 			SPDK_DIF_PI_FORMAT_32, SPDK_DIF_PI_FORMAT_16);
460 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_GUARD_CHECK,
461 			SPDK_DIF_PI_FORMAT_16, SPDK_DIF_PI_FORMAT_64);
462 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_GUARD_CHECK,
463 			SPDK_DIF_PI_FORMAT_32, SPDK_DIF_PI_FORMAT_64);
464 
465 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_APPTAG_CHECK,
466 			SPDK_DIF_PI_FORMAT_16, SPDK_DIF_PI_FORMAT_32);
467 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_APPTAG_CHECK,
468 			SPDK_DIF_PI_FORMAT_32, SPDK_DIF_PI_FORMAT_16);
469 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_APPTAG_CHECK,
470 			SPDK_DIF_PI_FORMAT_16, SPDK_DIF_PI_FORMAT_64);
471 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_APPTAG_CHECK,
472 			SPDK_DIF_PI_FORMAT_32, SPDK_DIF_PI_FORMAT_64);
473 
474 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_REFTAG_CHECK,
475 			SPDK_DIF_PI_FORMAT_16, SPDK_DIF_PI_FORMAT_32);
476 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_REFTAG_CHECK,
477 			SPDK_DIF_PI_FORMAT_32, SPDK_DIF_PI_FORMAT_16);
478 	_dif_generate_and_verify_different_pi_format(SPDK_DIF_FLAGS_REFTAG_CHECK,
479 			SPDK_DIF_PI_FORMAT_16, SPDK_DIF_PI_FORMAT_64);
480 	/* The ref tag in 32 and 64 PI formats will partially overlap, so skip the last test */
481 }
482 
483 static void
484 _dif_apptag_mask_test(enum spdk_dif_pi_format dif_pi_format)
485 {
486 	struct spdk_dif_ctx ctx = {};
487 	int rc;
488 	struct spdk_dif_ctx_init_ext_opts dif_opts;
489 	struct iovec iov;
490 	struct spdk_dif_error err_blk = {};
491 	uint32_t dif_flags;
492 
493 	dif_flags = SPDK_DIF_FLAGS_APPTAG_CHECK;
494 
495 	_iov_alloc_buf(&iov, 4096 + 128);
496 
497 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
498 	CU_ASSERT(rc == 0);
499 
500 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
501 	dif_opts.dif_pi_format = dif_pi_format;
502 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, true, SPDK_DIF_TYPE1, dif_flags,
503 			       0, 0xFFFF, 0x1234, 0, 0, &dif_opts);
504 	CU_ASSERT(rc == 0);
505 
506 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
507 	CU_ASSERT(rc == 0);
508 
509 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, true, SPDK_DIF_TYPE1, dif_flags,
510 			       12, 0xFFFF, 0x1256, 0, 0, &dif_opts);
511 	CU_ASSERT(rc == 0);
512 
513 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
514 	CU_ASSERT(rc != 0);
515 	CU_ASSERT(err_blk.err_type == SPDK_DIF_APPTAG_ERROR);
516 
517 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, true, SPDK_DIF_TYPE1, dif_flags,
518 			       12, 0xFF00, 0x1256, 0, 0, &dif_opts);
519 	CU_ASSERT(rc == 0);
520 
521 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
522 	CU_ASSERT(rc == 0);
523 
524 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
525 	CU_ASSERT(rc == 0);
526 
527 	_iov_free_buf(&iov);
528 }
529 
530 static void
531 dif_apptag_mask_test(void)
532 {
533 	_dif_apptag_mask_test(SPDK_DIF_PI_FORMAT_16);
534 	_dif_apptag_mask_test(SPDK_DIF_PI_FORMAT_32);
535 }
536 
537 static void
538 dif_sec_8_md_8_error_test(void)
539 {
540 	struct spdk_dif_ctx ctx = {};
541 	int rc;
542 	struct spdk_dif_ctx_init_ext_opts dif_opts;
543 
544 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
545 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
546 	/* Metadata size is 8 and block size is 8. */
547 	rc = spdk_dif_ctx_init(&ctx, 8, 8, true, false, SPDK_DIF_TYPE1, 0,
548 			       0, 0, 0, 0, 0, &dif_opts);
549 	CU_ASSERT(rc != 0);
550 }
551 
552 static void
553 dif_sec_512_md_0_error_test(void)
554 {
555 	struct spdk_dif_ctx ctx = {};
556 	int rc;
557 	struct spdk_dif_ctx_init_ext_opts dif_opts;
558 
559 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
560 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
561 	/* Metadata size is 0. */
562 	rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0,
563 			       0, 0, 0, 0, 0, &dif_opts);
564 	CU_ASSERT(rc != 0);
565 }
566 
567 static void
568 _dif_sec_512_md_16_error_test(enum spdk_dif_pi_format dif_pi_format)
569 {
570 	struct spdk_dif_ctx ctx = {};
571 	int rc;
572 	struct spdk_dif_ctx_init_ext_opts dif_opts;
573 
574 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
575 	dif_opts.dif_pi_format = dif_pi_format;
576 	/* Metadata size is 16 but block size is 512. */
577 	rc = spdk_dif_ctx_init(&ctx, 512, 16, true, false, SPDK_DIF_TYPE1, 0,
578 			       0, 0, 0, 0, 0, &dif_opts);
579 	CU_ASSERT(rc != 0);
580 }
581 
582 static void
583 dif_sec_512_md_16_error_test(void)
584 {
585 	_dif_sec_512_md_16_error_test(SPDK_DIF_PI_FORMAT_32);
586 	_dif_sec_512_md_16_error_test(SPDK_DIF_PI_FORMAT_64);
587 }
588 
589 static void
590 _dif_sec_4096_md_0_8_error_test(enum spdk_dif_pi_format dif_pi_format)
591 {
592 	struct spdk_dif_ctx ctx = {};
593 	int rc;
594 	struct spdk_dif_ctx_init_ext_opts dif_opts;
595 
596 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
597 	dif_opts.dif_pi_format = dif_pi_format;
598 	/* Metadata size is 0. */
599 	rc = spdk_dif_ctx_init(&ctx, 4096, 0, true, false, SPDK_DIF_TYPE1, 0,
600 			       0, 0, 0, 0, 0, &dif_opts);
601 	CU_ASSERT(rc != 0);
602 
603 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
604 	dif_opts.dif_pi_format = dif_pi_format;
605 	/* Metadata size is 8. */
606 	rc = spdk_dif_ctx_init(&ctx, 4096, 8, true, false, SPDK_DIF_TYPE1, 0,
607 			       0, 0, 0, 0, 0, &dif_opts);
608 	CU_ASSERT(rc != 0);
609 }
610 
611 static void
612 dif_sec_4096_md_0_8_error_test(void)
613 {
614 	_dif_sec_4096_md_0_8_error_test(SPDK_DIF_PI_FORMAT_32);
615 	_dif_sec_4096_md_0_8_error_test(SPDK_DIF_PI_FORMAT_64);
616 }
617 
618 static void
619 _dif_sec_4100_md_128_error_test(enum spdk_dif_pi_format dif_pi_format)
620 {
621 	struct spdk_dif_ctx ctx = {};
622 	int rc;
623 	struct spdk_dif_ctx_init_ext_opts dif_opts;
624 
625 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
626 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_32;
627 	/* Block size is not multiple of 4kB, MD interleave = false */
628 	rc = spdk_dif_ctx_init(&ctx, 4100, 128, false, false, SPDK_DIF_TYPE1, 0,
629 			       0, 0, 0, 0, 0, &dif_opts);
630 	CU_ASSERT(rc != 0);
631 }
632 
633 static void
634 dif_sec_4100_md_128_error_test(void)
635 {
636 	_dif_sec_4100_md_128_error_test(SPDK_DIF_PI_FORMAT_32);
637 	_dif_sec_4100_md_128_error_test(SPDK_DIF_PI_FORMAT_64);
638 }
639 
640 static void
641 _dif_guard_seed_test(uint32_t block_size, uint32_t md_size,
642 		     enum spdk_dif_pi_format dif_pi_format)
643 {
644 	struct iovec iov;
645 	struct spdk_dif_ctx ctx = {};
646 	struct spdk_dif_error err_blk = {};
647 	struct spdk_dif *dif;
648 	uint64_t guard;
649 	int rc;
650 	struct spdk_dif_ctx_init_ext_opts dif_opts;
651 
652 	_iov_alloc_buf(&iov, block_size);
653 
654 	memset(iov.iov_base, 0, block_size);
655 
656 	dif = (struct spdk_dif *)(iov.iov_base + (block_size - md_size));
657 
658 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
659 	dif_opts.dif_pi_format = dif_pi_format;
660 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, true, SPDK_DIF_TYPE1,
661 			       SPDK_DIF_FLAGS_GUARD_CHECK,
662 			       0, 0, 0, 0, 0, &dif_opts);
663 	CU_ASSERT(rc == 0);
664 
665 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
666 	CU_ASSERT(rc == 0);
667 
668 	/* Guard should be zero if the block is all zero and seed is not added. */
669 	guard = _dif_get_guard(dif, ctx.dif_pi_format);
670 	CU_ASSERT(guard == 0);
671 
672 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
673 	CU_ASSERT(rc == 0);
674 
675 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, true, SPDK_DIF_TYPE1,
676 			       SPDK_DIF_FLAGS_GUARD_CHECK,
677 			       0, 0, 0, 0, GUARD_SEED, &dif_opts);
678 	CU_ASSERT(rc == 0);
679 
680 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
681 	CU_ASSERT(rc == 0);
682 
683 	/* Guard should not be zero if the block is all zero but seed is added. */
684 	guard = _dif_get_guard(dif, ctx.dif_pi_format);
685 	CU_ASSERT(guard != 0);
686 
687 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk);
688 	CU_ASSERT(rc == 0);
689 
690 	_iov_free_buf(&iov);
691 }
692 
693 static void
694 dif_guard_seed_test(void)
695 {
696 	_dif_guard_seed_test(512 + 8, 8, SPDK_DIF_PI_FORMAT_16);
697 }
698 
699 static void
700 _dif_guard_value_test(uint32_t block_size, uint32_t md_size,
701 		      enum spdk_dif_pi_format dif_pi_format, struct iovec *iov_input_data,
702 		      uint64_t expected_guard)
703 {
704 	struct spdk_dif_ctx ctx = {};
705 	struct spdk_dif_error err_blk = {};
706 	struct spdk_dif_ctx_init_ext_opts dif_opts;
707 	struct spdk_dif *dif;
708 	int rc;
709 	uint64_t guard;
710 
711 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
712 	dif_opts.dif_pi_format = dif_pi_format;
713 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, true, SPDK_DIF_TYPE1,
714 			       SPDK_DIF_FLAGS_GUARD_CHECK,
715 			       0, 0, 0, 0, 0, &dif_opts);
716 	CU_ASSERT(rc == 0);
717 
718 	dif = (struct spdk_dif *)(iov_input_data->iov_base + (block_size - md_size));
719 
720 	rc = spdk_dif_generate(iov_input_data, 1, 1, &ctx);
721 	CU_ASSERT(rc == 0);
722 
723 	guard = _dif_get_guard(dif, ctx.dif_pi_format);
724 	CU_ASSERT(guard == expected_guard);
725 
726 	rc = spdk_dif_verify(iov_input_data, 1, 1, &ctx, &err_blk);
727 	CU_ASSERT(rc == 0);
728 }
729 
730 static void
731 dif_guard_value_test(void)
732 {
733 	struct iovec iov;
734 	unsigned int i, j;
735 	uint32_t block_size = 4096 + 128;
736 	uint32_t md_size = 128;
737 
738 	_iov_alloc_buf(&iov, block_size);
739 
740 	/* All the expected CRC guard values are compliant with
741 	* the NVM Command Set Specification 1.0c */
742 
743 	/* Input buffer = 0s */
744 	memset(iov.iov_base, 0, block_size);
745 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_32, &iov, 0x98F94189);
746 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_64, &iov, 0x6482D367EB22B64E);
747 
748 	/* Input buffer = 1s */
749 	memset(iov.iov_base, 0xFF, block_size);
750 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_32, &iov, 0x25C1FE13);
751 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_64, &iov, 0xC0DDBA7302ECA3AC);
752 
753 	/* Input buffer = 0x00, 0x01, 0x02, ... */
754 	memset(iov.iov_base, 0, block_size);
755 	j = 0;
756 	for (i = 0; i < block_size - md_size; i++) {
757 		*((uint8_t *)(iov.iov_base) + i) = j;
758 		if (j == 0xFF) {
759 			j = 0;
760 		} else {
761 			j++;
762 		}
763 	}
764 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_32, &iov, 0x9C71FE32);
765 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_64, &iov, 0x3E729F5F6750449C);
766 
767 	/* Input buffer = 0xFF, 0xFE, 0xFD, ... */
768 	memset(iov.iov_base, 0, block_size);
769 	j = 0xFF;
770 	for (i = 0; i < block_size - md_size ; i++) {
771 		*((uint8_t *)(iov.iov_base) + i) = j;
772 		if (j == 0) {
773 			j = 0xFF;
774 		} else {
775 			j--;
776 		}
777 	}
778 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_32, &iov, 0x214941A8);
779 	_dif_guard_value_test(block_size, md_size, SPDK_DIF_PI_FORMAT_64, &iov, 0x9A2DF64B8E9E517E);
780 
781 
782 	_iov_free_buf(&iov);
783 }
784 
785 static void
786 dif_generate_and_verify(struct iovec *iovs, int iovcnt,
787 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
788 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
789 			enum spdk_dif_pi_format dif_pi_format,
790 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag)
791 {
792 	struct spdk_dif_ctx ctx = {};
793 	int rc;
794 	struct spdk_dif_ctx_init_ext_opts dif_opts;
795 
796 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
797 	CU_ASSERT(rc == 0);
798 
799 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
800 	dif_opts.dif_pi_format = dif_pi_format;
801 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
802 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED, &dif_opts);
803 	CU_ASSERT(rc == 0);
804 
805 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
806 	CU_ASSERT(rc == 0);
807 
808 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL);
809 	CU_ASSERT(rc == 0);
810 
811 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
812 	CU_ASSERT(rc == 0);
813 }
814 
815 static void
816 dif_disable_sec_512_md_8_single_iov_test(void)
817 {
818 	struct iovec iov;
819 
820 	_iov_alloc_buf(&iov, 512 + 8);
821 
822 	dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_DISABLE, 0,
823 				SPDK_DIF_PI_FORMAT_16, 0, 0, 0);
824 
825 	_iov_free_buf(&iov);
826 }
827 
828 static void
829 dif_sec_512_md_8_prchk_0_single_iov_test(void)
830 {
831 	struct iovec iov;
832 
833 	_iov_alloc_buf(&iov, 512 + 8);
834 
835 	dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 0,
836 				SPDK_DIF_PI_FORMAT_16, 0, 0, 0);
837 
838 	_iov_free_buf(&iov);
839 }
840 
841 static void
842 dif_sec_4096_md_128_prchk_0_single_iov_test(void)
843 {
844 	struct iovec iov;
845 
846 	_iov_alloc_buf(&iov, 4096 + 128);
847 
848 	dif_generate_and_verify(&iov, 1, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1, 0,
849 				SPDK_DIF_PI_FORMAT_32, 0, 0, 0);
850 	dif_generate_and_verify(&iov, 1, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1, 0,
851 				SPDK_DIF_PI_FORMAT_64, 0, 0, 0);
852 
853 	_iov_free_buf(&iov);
854 }
855 
856 static void
857 dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test(void)
858 {
859 	struct iovec iovs[4];
860 	int i, num_blocks;
861 
862 	num_blocks = 0;
863 
864 	for (i = 0; i < 4; i++) {
865 		_iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1));
866 		num_blocks += i + 1;
867 	}
868 
869 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
870 				0, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
871 
872 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
873 				SPDK_DIF_FLAGS_GUARD_CHECK, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
874 
875 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
876 				SPDK_DIF_FLAGS_APPTAG_CHECK, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
877 
878 	dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
879 				SPDK_DIF_FLAGS_REFTAG_CHECK, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
880 
881 	for (i = 0; i < 4; i++) {
882 		_iov_free_buf(&iovs[i]);
883 	}
884 }
885 
886 static void
887 _dif_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(enum spdk_dif_pi_format dif_pi_format)
888 {
889 	struct iovec iovs[4];
890 	int i, num_blocks;
891 
892 	num_blocks = 0;
893 
894 	for (i = 0; i < 4; i++) {
895 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
896 		num_blocks += i + 1;
897 	}
898 
899 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
900 				0, dif_pi_format, 22, 0xFFFF, 0x22);
901 
902 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
903 				SPDK_DIF_FLAGS_GUARD_CHECK, dif_pi_format, 22, 0xFFFF, 0x22);
904 
905 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
906 				SPDK_DIF_FLAGS_APPTAG_CHECK, dif_pi_format, 22, 0xFFFF, 0x22);
907 
908 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
909 				SPDK_DIF_FLAGS_REFTAG_CHECK, dif_pi_format, 22, 0xFFFF, 0x22);
910 
911 	for (i = 0; i < 4; i++) {
912 		_iov_free_buf(&iovs[i]);
913 	}
914 }
915 
916 static void
917 dif_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(void)
918 {
919 	_dif_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(SPDK_DIF_PI_FORMAT_32);
920 	_dif_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(SPDK_DIF_PI_FORMAT_64);
921 }
922 
923 static void
924 _dif_sec_4096_md_128_prchk_7_multi_iovs_test(enum spdk_dif_pi_format dif_pi_format)
925 {
926 	struct iovec iovs[4];
927 	int i, num_blocks;
928 	uint32_t dif_flags;
929 
930 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
931 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
932 
933 	num_blocks = 0;
934 
935 	for (i = 0; i < 4; i++) {
936 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
937 		num_blocks += i + 1;
938 	}
939 
940 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
941 				dif_flags, dif_pi_format, 22, 0xFFFF, 0x22);
942 
943 	dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1,
944 				dif_flags, dif_pi_format, 22, 0xFFFF, 0x22);
945 
946 	for (i = 0; i < 4; i++) {
947 		_iov_free_buf(&iovs[i]);
948 	}
949 }
950 
951 static void
952 dif_sec_4096_md_128_prchk_7_multi_iovs_test(void)
953 {
954 	_dif_sec_4096_md_128_prchk_7_multi_iovs_test(SPDK_DIF_PI_FORMAT_16);
955 	_dif_sec_4096_md_128_prchk_7_multi_iovs_test(SPDK_DIF_PI_FORMAT_32);
956 	_dif_sec_4096_md_128_prchk_7_multi_iovs_test(SPDK_DIF_PI_FORMAT_64);
957 }
958 
959 static void
960 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test(void)
961 {
962 	struct iovec iovs[2];
963 	uint32_t dif_flags;
964 
965 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
966 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
967 
968 	_iov_alloc_buf(&iovs[0], 512);
969 	_iov_alloc_buf(&iovs[1], 8);
970 
971 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
972 				dif_flags, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
973 
974 	_iov_free_buf(&iovs[0]);
975 	_iov_free_buf(&iovs[1]);
976 }
977 
978 static void
979 dif_sec_4096_md_128_prchk_7_multi_iovs_split_data_and_md_test(void)
980 {
981 	struct iovec iovs[2];
982 	uint32_t dif_flags;
983 
984 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
985 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
986 
987 	_iov_alloc_buf(&iovs[0], 4096);
988 	_iov_alloc_buf(&iovs[1], 128);
989 
990 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
991 				dif_flags, SPDK_DIF_PI_FORMAT_32, 22, 0xFFFF, 0x22);
992 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
993 				dif_flags, SPDK_DIF_PI_FORMAT_64, 22, 0xFFFF, 0x22);
994 
995 	_iov_free_buf(&iovs[0]);
996 	_iov_free_buf(&iovs[1]);
997 }
998 
999 static void
1000 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test(void)
1001 {
1002 	struct iovec iovs[2];
1003 	uint32_t dif_flags;
1004 
1005 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1006 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1007 
1008 	_iov_alloc_buf(&iovs[0], 256);
1009 	_iov_alloc_buf(&iovs[1], 264);
1010 
1011 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
1012 				dif_flags, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
1013 
1014 	_iov_free_buf(&iovs[0]);
1015 	_iov_free_buf(&iovs[1]);
1016 }
1017 
1018 static void
1019 dif_sec_4096_md_128_prchk_7_multi_iovs_split_data_test(void)
1020 {
1021 	struct iovec iovs[2];
1022 	uint32_t dif_flags;
1023 
1024 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1025 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1026 
1027 	_iov_alloc_buf(&iovs[0], 2048);
1028 	_iov_alloc_buf(&iovs[1], 2176);
1029 
1030 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1031 				dif_flags, SPDK_DIF_PI_FORMAT_32, 22, 0xFFFF, 0x22);
1032 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1033 				dif_flags, SPDK_DIF_PI_FORMAT_64, 22, 0xFFFF, 0x22);
1034 
1035 	_iov_free_buf(&iovs[0]);
1036 	_iov_free_buf(&iovs[1]);
1037 }
1038 
1039 static void
1040 dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test(void)
1041 {
1042 	struct iovec iovs[2];
1043 	uint32_t dif_flags;
1044 
1045 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1046 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1047 
1048 	_iov_alloc_buf(&iovs[0], 513);
1049 	_iov_alloc_buf(&iovs[1], 7);
1050 
1051 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
1052 				dif_flags, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
1053 
1054 	_iov_free_buf(&iovs[0]);
1055 	_iov_free_buf(&iovs[1]);
1056 }
1057 
1058 static void
1059 dif_sec_4096_md_128_prchk_7_multi_iovs_split_guard_test(void)
1060 {
1061 	struct iovec iovs[2];
1062 	uint32_t dif_flags;
1063 
1064 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1065 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1066 
1067 	_iov_alloc_buf(&iovs[0], 4097);
1068 	_iov_alloc_buf(&iovs[1], 127);
1069 
1070 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1071 				dif_flags, SPDK_DIF_PI_FORMAT_32, 22, 0xFFFF, 0x22);
1072 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1073 				dif_flags, SPDK_DIF_PI_FORMAT_64, 22, 0xFFFF, 0x22);
1074 
1075 	_iov_free_buf(&iovs[0]);
1076 	_iov_free_buf(&iovs[1]);
1077 }
1078 
1079 static void
1080 dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test(void)
1081 {
1082 	struct iovec iovs[2];
1083 	uint32_t dif_flags;
1084 
1085 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1086 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1087 
1088 	_iov_alloc_buf(&iovs[0], 515);
1089 	_iov_alloc_buf(&iovs[1], 5);
1090 
1091 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
1092 				dif_flags, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
1093 
1094 	_iov_free_buf(&iovs[0]);
1095 	_iov_free_buf(&iovs[1]);
1096 }
1097 
1098 static void
1099 dif_sec_4096_md_128_prchk_7_multi_iovs_split_apptag_test(void)
1100 {
1101 	struct iovec iovs[2];
1102 	uint32_t dif_flags;
1103 
1104 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1105 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1106 
1107 	_iov_alloc_buf(&iovs[0], 4101);
1108 	_iov_alloc_buf(&iovs[1], 123);
1109 
1110 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1111 				dif_flags, SPDK_DIF_PI_FORMAT_32, 22, 0xFFFF, 0x22);
1112 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1113 				dif_flags, SPDK_DIF_PI_FORMAT_64, 22, 0xFFFF, 0x22);
1114 
1115 	_iov_free_buf(&iovs[0]);
1116 	_iov_free_buf(&iovs[1]);
1117 }
1118 
1119 static void
1120 dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test(void)
1121 {
1122 	struct iovec iovs[2];
1123 	uint32_t dif_flags;
1124 
1125 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1126 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1127 
1128 	_iov_alloc_buf(&iovs[0], 518);
1129 	_iov_alloc_buf(&iovs[1], 2);
1130 
1131 	dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
1132 				dif_flags, SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
1133 
1134 	_iov_free_buf(&iovs[0]);
1135 	_iov_free_buf(&iovs[1]);
1136 }
1137 
1138 static void
1139 dif_sec_4096_md_128_prchk_7_multi_iovs_split_reftag_test(void)
1140 {
1141 	struct iovec iovs[2];
1142 	uint32_t dif_flags;
1143 
1144 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1145 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1146 
1147 	_iov_alloc_buf(&iovs[0], 4108);
1148 	_iov_alloc_buf(&iovs[1], 116);
1149 
1150 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1151 				dif_flags, SPDK_DIF_PI_FORMAT_32, 22, 0xFFFF, 0x22);
1152 	dif_generate_and_verify(iovs, 2, 4096 + 128, 128, 1, false, SPDK_DIF_TYPE1,
1153 				dif_flags, SPDK_DIF_PI_FORMAT_64, 22, 0xFFFF, 0x22);
1154 
1155 	_iov_free_buf(&iovs[0]);
1156 	_iov_free_buf(&iovs[1]);
1157 }
1158 
1159 static void
1160 dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test(void)
1161 {
1162 	struct iovec iovs[9];
1163 	uint32_t dif_flags;
1164 	int i;
1165 
1166 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1167 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1168 
1169 	/* data[0][255:0] */
1170 	_iov_alloc_buf(&iovs[0], 256);
1171 
1172 	/* data[0][511:256], guard[0][0] */
1173 	_iov_alloc_buf(&iovs[1], 256 + 1);
1174 
1175 	/* guard[0][1], apptag[0][0] */
1176 	_iov_alloc_buf(&iovs[2], 1 + 1);
1177 
1178 	/* apptag[0][1], reftag[0][0] */
1179 	_iov_alloc_buf(&iovs[3], 1 + 1);
1180 
1181 	/* reftag[0][3:1], data[1][255:0] */
1182 	_iov_alloc_buf(&iovs[4], 3 + 256);
1183 
1184 	/* data[1][511:256], guard[1][0] */
1185 	_iov_alloc_buf(&iovs[5], 256 + 1);
1186 
1187 	/* guard[1][1], apptag[1][0] */
1188 	_iov_alloc_buf(&iovs[6], 1 + 1);
1189 
1190 	/* apptag[1][1], reftag[1][0] */
1191 	_iov_alloc_buf(&iovs[7], 1 + 1);
1192 
1193 	/* reftag[1][3:1] */
1194 	_iov_alloc_buf(&iovs[8], 3);
1195 
1196 	dif_generate_and_verify(iovs, 9, 512 + 8, 8, 2, false, SPDK_DIF_TYPE1, dif_flags,
1197 				SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
1198 
1199 	for (i = 0; i < 9; i++) {
1200 		_iov_free_buf(&iovs[i]);
1201 	}
1202 }
1203 
1204 static void
1205 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void)
1206 {
1207 	struct iovec iovs[11];
1208 	uint32_t dif_flags;
1209 	int i;
1210 
1211 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1212 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1213 
1214 	/* data[0][1000:0] */
1215 	_iov_alloc_buf(&iovs[0], 1000);
1216 
1217 	/* data[0][3095:1000], guard[0][0] */
1218 	_iov_alloc_buf(&iovs[1], 3096 + 1);
1219 
1220 	/* guard[0][1], apptag[0][0] */
1221 	_iov_alloc_buf(&iovs[2], 1 + 1);
1222 
1223 	/* apptag[0][1], reftag[0][0] */
1224 	_iov_alloc_buf(&iovs[3], 1 + 1);
1225 
1226 	/* reftag[0][3:1], ignore[0][59:0] */
1227 	_iov_alloc_buf(&iovs[4], 3 + 60);
1228 
1229 	/* ignore[119:60], data[1][3050:0] */
1230 	_iov_alloc_buf(&iovs[5], 60 + 3051);
1231 
1232 	/* data[1][4095:3050], guard[1][0] */
1233 	_iov_alloc_buf(&iovs[6], 1045 + 1);
1234 
1235 	/* guard[1][1], apptag[1][0] */
1236 	_iov_alloc_buf(&iovs[7], 1 + 1);
1237 
1238 	/* apptag[1][1], reftag[1][0] */
1239 	_iov_alloc_buf(&iovs[8], 1 + 1);
1240 
1241 	/* reftag[1][3:1], ignore[1][9:0] */
1242 	_iov_alloc_buf(&iovs[9], 3 + 10);
1243 
1244 	/* ignore[1][127:9] */
1245 	_iov_alloc_buf(&iovs[10], 118);
1246 
1247 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
1248 				SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
1249 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
1250 				SPDK_DIF_PI_FORMAT_16, 22, 0xFFFF, 0x22);
1251 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
1252 				SPDK_DIF_PI_FORMAT_32, 22, 0xFFFF, 0x22);
1253 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
1254 				SPDK_DIF_PI_FORMAT_32, 22, 0xFFFF, 0x22);
1255 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
1256 				SPDK_DIF_PI_FORMAT_64, 22, 0xFFFF, 0x22);
1257 	dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
1258 				SPDK_DIF_PI_FORMAT_64, 22, 0xFFFF, 0x22);
1259 
1260 	for (i = 0; i < 11; i++) {
1261 		_iov_free_buf(&iovs[i]);
1262 	}
1263 }
1264 
1265 static void
1266 _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
1267 			     uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1268 			     uint32_t inject_flags, bool dif_loc, enum spdk_dif_pi_format dif_pi_format)
1269 {
1270 	struct spdk_dif_ctx ctx = {};
1271 	struct spdk_dif_error err_blk = {};
1272 	uint32_t inject_offset = 0, dif_flags;
1273 	int rc;
1274 	struct spdk_dif_ctx_init_ext_opts dif_opts;
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, md_size, num_blocks);
1280 	CU_ASSERT(rc == 0);
1281 
1282 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
1283 	dif_opts.dif_pi_format = dif_pi_format;
1284 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc,
1285 			       SPDK_DIF_TYPE1, dif_flags,
1286 			       88, 0xFFFF, 0x88, 0, GUARD_SEED, &dif_opts);
1287 	CU_ASSERT(rc == 0);
1288 
1289 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
1290 	CU_ASSERT(rc == 0);
1291 
1292 	rc = spdk_dif_inject_error(iovs, iovcnt, num_blocks, &ctx, inject_flags, &inject_offset);
1293 	CU_ASSERT(rc == 0);
1294 
1295 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, &err_blk);
1296 	CU_ASSERT(rc != 0);
1297 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
1298 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
1299 	} else {
1300 		CU_ASSERT(inject_flags == err_blk.err_type);
1301 	}
1302 	CU_ASSERT(inject_offset == err_blk.err_offset);
1303 
1304 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
1305 	CU_ASSERT((rc == 0 && (inject_flags != SPDK_DIF_DATA_ERROR)) ||
1306 		  (rc != 0 && (inject_flags == SPDK_DIF_DATA_ERROR)));
1307 }
1308 
1309 static void
1310 dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
1311 			    uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1312 			    uint32_t inject_flags, enum spdk_dif_pi_format dif_pi_format)
1313 {
1314 	/* The case that DIF is contained in the first 8/16 bytes of metadata. */
1315 	_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
1316 				     inject_flags, true, dif_pi_format);
1317 
1318 	/* The case that DIF is contained in the last 8/16 bytes of metadata. */
1319 	_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
1320 				     inject_flags, false, dif_pi_format);
1321 }
1322 
1323 static void
1324 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
1325 {
1326 	struct iovec iovs[4];
1327 	int i, num_blocks;
1328 
1329 	num_blocks = 0;
1330 
1331 	for (i = 0; i < 4; i++) {
1332 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
1333 		num_blocks += i + 1;
1334 	}
1335 
1336 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1337 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
1338 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1339 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1340 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1341 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1342 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1343 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
1344 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1345 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
1346 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1347 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1348 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1349 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1350 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1351 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
1352 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1353 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
1354 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1355 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1356 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1357 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1358 	dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks,
1359 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
1360 
1361 	for (i = 0; i < 4; i++) {
1362 		_iov_free_buf(&iovs[i]);
1363 	}
1364 }
1365 
1366 static void
1367 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test(void)
1368 {
1369 	struct iovec iovs[2];
1370 
1371 	_iov_alloc_buf(&iovs[0], 4096);
1372 	_iov_alloc_buf(&iovs[1], 128);
1373 
1374 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1375 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
1376 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1377 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1378 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1379 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1380 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1381 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
1382 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1383 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
1384 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1385 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1386 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1387 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1388 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1389 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
1390 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1391 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
1392 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1393 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1394 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1395 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1396 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1397 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
1398 
1399 
1400 	_iov_free_buf(&iovs[0]);
1401 	_iov_free_buf(&iovs[1]);
1402 }
1403 
1404 static void
1405 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test(void)
1406 {
1407 	struct iovec iovs[2];
1408 
1409 	_iov_alloc_buf(&iovs[0], 2048);
1410 	_iov_alloc_buf(&iovs[1], 2048 + 128);
1411 
1412 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1413 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
1414 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1415 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1416 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1417 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1418 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1419 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
1420 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1421 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
1422 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1423 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1424 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1425 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1426 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1427 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
1428 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1429 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
1430 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1431 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1432 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1433 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1434 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1435 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
1436 
1437 	_iov_free_buf(&iovs[0]);
1438 	_iov_free_buf(&iovs[1]);
1439 }
1440 
1441 static void
1442 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test(void)
1443 {
1444 	struct iovec iovs[2];
1445 
1446 	_iov_alloc_buf(&iovs[0], 4096 + 1);
1447 	_iov_alloc_buf(&iovs[1], 127);
1448 
1449 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1450 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
1451 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1452 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1453 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1454 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1455 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1456 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
1457 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1458 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
1459 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1460 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1461 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1462 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
1463 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1464 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
1465 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1466 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
1467 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1468 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1469 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1470 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
1471 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1472 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
1473 
1474 	_iov_free_buf(&iovs[0]);
1475 	_iov_free_buf(&iovs[1]);
1476 }
1477 
1478 static void
1479 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_pi_16_test(void)
1480 {
1481 	struct iovec iovs[2];
1482 
1483 	_iov_alloc_buf(&iovs[0], 4096 + 3);
1484 	_iov_alloc_buf(&iovs[1], 125);
1485 
1486 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1487 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
1488 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1489 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1490 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1491 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1492 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1493 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
1494 
1495 	_iov_free_buf(&iovs[0]);
1496 	_iov_free_buf(&iovs[1]);
1497 }
1498 
1499 static void
1500 _dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(
1501 	enum spdk_dif_pi_format dif_pi_format)
1502 {
1503 	struct iovec iovs[2];
1504 
1505 	_iov_alloc_buf(&iovs[0], 4096 + 5);
1506 	_iov_alloc_buf(&iovs[1], 123);
1507 
1508 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1509 				    SPDK_DIF_GUARD_ERROR, dif_pi_format);
1510 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1511 				    SPDK_DIF_APPTAG_ERROR, dif_pi_format);
1512 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1513 				    SPDK_DIF_REFTAG_ERROR, dif_pi_format);
1514 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1515 				    SPDK_DIF_DATA_ERROR, dif_pi_format);
1516 
1517 	_iov_free_buf(&iovs[0]);
1518 	_iov_free_buf(&iovs[1]);
1519 }
1520 
1521 static void
1522 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(void)
1523 {
1524 	_dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(SPDK_DIF_PI_FORMAT_32);
1525 	_dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(SPDK_DIF_PI_FORMAT_64);
1526 }
1527 
1528 static void
1529 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_pi_16_test(void)
1530 {
1531 	struct iovec iovs[2];
1532 
1533 	_iov_alloc_buf(&iovs[0], 4096 + 6);
1534 	_iov_alloc_buf(&iovs[1], 122);
1535 
1536 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1537 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
1538 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1539 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1540 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1541 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
1542 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1543 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
1544 
1545 	_iov_free_buf(&iovs[0]);
1546 	_iov_free_buf(&iovs[1]);
1547 }
1548 
1549 static void
1550 _dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(
1551 	enum spdk_dif_pi_format dif_pi_format)
1552 {
1553 	struct iovec iovs[2];
1554 
1555 	_iov_alloc_buf(&iovs[0], 4096 + 9);
1556 	_iov_alloc_buf(&iovs[1], 119);
1557 
1558 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1559 				    SPDK_DIF_GUARD_ERROR, dif_pi_format);
1560 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1561 				    SPDK_DIF_APPTAG_ERROR, dif_pi_format);
1562 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1563 				    SPDK_DIF_REFTAG_ERROR, dif_pi_format);
1564 	dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1,
1565 				    SPDK_DIF_DATA_ERROR, dif_pi_format);
1566 
1567 	_iov_free_buf(&iovs[0]);
1568 	_iov_free_buf(&iovs[1]);
1569 }
1570 
1571 static void
1572 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(void)
1573 {
1574 	_dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(SPDK_DIF_PI_FORMAT_32);
1575 	_dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(SPDK_DIF_PI_FORMAT_64);
1576 }
1577 
1578 static void
1579 dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt,
1580 			struct iovec *bounce_iovs, int bounce_iovcnt,
1581 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
1582 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
1583 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
1584 			enum spdk_dif_pi_format dif_pi_format)
1585 {
1586 	struct spdk_dif_ctx ctx = {};
1587 	int rc;
1588 	struct spdk_dif_ctx_init_ext_opts dif_opts;
1589 
1590 	if (dif_flags & SPDK_DIF_FLAGS_NVME_PRACT) {
1591 		rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
1592 	} else {
1593 		rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
1594 	}
1595 	CU_ASSERT(rc == 0);
1596 
1597 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
1598 	dif_opts.dif_pi_format = dif_pi_format;
1599 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
1600 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED, &dif_opts);
1601 	CU_ASSERT(rc == 0);
1602 
1603 	rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iovs, bounce_iovcnt, num_blocks, &ctx);
1604 	CU_ASSERT(rc == 0);
1605 
1606 	rc = ut_data_pattern_verify(bounce_iovs, bounce_iovcnt, block_size, md_size, num_blocks);
1607 	CU_ASSERT(rc == 0);
1608 
1609 	rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iovs, bounce_iovcnt, num_blocks, &ctx, NULL);
1610 	CU_ASSERT(rc == 0);
1611 
1612 	if (dif_flags & SPDK_DIF_FLAGS_NVME_PRACT) {
1613 		rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
1614 	} else {
1615 		rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks);
1616 	}
1617 	CU_ASSERT(rc == 0);
1618 }
1619 
1620 static void
1621 dif_copy_sec_512_md_8_prchk_0_single_iov(void)
1622 {
1623 	struct iovec iov, bounce_iov;
1624 
1625 	_iov_alloc_buf(&iov, 512 * 4);
1626 	_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
1627 
1628 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 1, 512 + 8, 8, 4,
1629 				false, SPDK_DIF_TYPE1, 0, 0, 0, 0, SPDK_DIF_PI_FORMAT_16);
1630 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 1, 512 + 8, 8, 4,
1631 				true, SPDK_DIF_TYPE1, 0, 0, 0, 0, SPDK_DIF_PI_FORMAT_16);
1632 
1633 	_iov_free_buf(&iov);
1634 	_iov_free_buf(&bounce_iov);
1635 }
1636 
1637 static void
1638 dif_copy_sec_512_md_8_dif_disable_single_iov(void)
1639 {
1640 	struct iovec iov, bounce_iov;
1641 
1642 	_iov_alloc_buf(&iov, 512 * 4);
1643 	_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
1644 
1645 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 1, 512 + 8, 8, 4,
1646 				false, SPDK_DIF_DISABLE, 0, 0, 0, 0, SPDK_DIF_PI_FORMAT_16);
1647 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 1, 512 + 8, 8, 4,
1648 				true, SPDK_DIF_DISABLE, 0, 0, 0, 0, SPDK_DIF_PI_FORMAT_16);
1649 
1650 	_iov_free_buf(&iov);
1651 	_iov_free_buf(&bounce_iov);
1652 }
1653 
1654 static void
1655 _dif_copy_sec_4096_md_128_prchk_0_single_iov_test(
1656 	enum spdk_dif_pi_format dif_pi_format)
1657 {
1658 	struct iovec iov, bounce_iov;
1659 
1660 	_iov_alloc_buf(&iov, 4096 * 4);
1661 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * 4);
1662 
1663 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 1, 4096 + 128, 128, 4,
1664 				false, SPDK_DIF_TYPE1, 0, 0, 0, 0, dif_pi_format);
1665 	dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 1, 4096 + 128, 128, 4,
1666 				true, SPDK_DIF_TYPE1, 0, 0, 0, 0, dif_pi_format);
1667 
1668 	_iov_free_buf(&iov);
1669 	_iov_free_buf(&bounce_iov);
1670 }
1671 
1672 static void
1673 dif_copy_sec_4096_md_128_prchk_0_single_iov_test(void)
1674 {
1675 	_dif_copy_sec_4096_md_128_prchk_0_single_iov_test(SPDK_DIF_PI_FORMAT_32);
1676 	_dif_copy_sec_4096_md_128_prchk_0_single_iov_test(SPDK_DIF_PI_FORMAT_64);
1677 }
1678 
1679 static void
1680 dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
1681 {
1682 	struct iovec iovs[4], bounce_iov;
1683 	int i, num_blocks;
1684 
1685 	num_blocks = 0;
1686 
1687 	for (i = 0; i < 4; i++) {
1688 		_iov_alloc_buf(&iovs[i], 512 * (i + 1));
1689 		num_blocks += i + 1;
1690 	}
1691 
1692 	_iov_alloc_buf(&bounce_iov, (512 + 8) * num_blocks);
1693 
1694 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 512 + 8, 8, num_blocks,
1695 				false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
1696 
1697 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 512 + 8, 8, num_blocks,
1698 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22,
1699 				SPDK_DIF_PI_FORMAT_16);
1700 
1701 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 512 + 8, 8, num_blocks,
1702 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22,
1703 				SPDK_DIF_PI_FORMAT_16);
1704 
1705 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 512 + 8, 8, num_blocks,
1706 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22,
1707 				SPDK_DIF_PI_FORMAT_16);
1708 
1709 	for (i = 0; i < 4; i++) {
1710 		_iov_free_buf(&iovs[i]);
1711 	}
1712 	_iov_free_buf(&bounce_iov);
1713 }
1714 
1715 static void
1716 _dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(
1717 	enum spdk_dif_pi_format dif_pi_format)
1718 {
1719 	struct iovec iovs[4], bounce_iov;
1720 	int i, num_blocks;
1721 
1722 	num_blocks = 0;
1723 
1724 	for (i = 0; i < 4; i++) {
1725 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1726 		num_blocks += i + 1;
1727 	}
1728 
1729 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
1730 
1731 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1732 				false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22, dif_pi_format);
1733 
1734 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1735 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22,
1736 				dif_pi_format);
1737 
1738 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1739 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22,
1740 				dif_pi_format);
1741 
1742 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1743 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22,
1744 				dif_pi_format);
1745 
1746 	for (i = 0; i < 4; i++) {
1747 		_iov_free_buf(&iovs[i]);
1748 	}
1749 	_iov_free_buf(&bounce_iov);
1750 }
1751 
1752 static void
1753 dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(void)
1754 {
1755 	_dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(SPDK_DIF_PI_FORMAT_32);
1756 	_dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(SPDK_DIF_PI_FORMAT_64);
1757 }
1758 
1759 static void
1760 _dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(
1761 	enum spdk_dif_pi_format dif_pi_format)
1762 {
1763 	struct iovec iovs[4], bounce_iovs[2];
1764 	int i, num_blocks;
1765 
1766 	num_blocks = 0;
1767 
1768 	for (i = 0; i < 4; i++) {
1769 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1770 		num_blocks += i + 1;
1771 	}
1772 
1773 	num_blocks = 0;
1774 
1775 	for (i = 0; i < 2; i++) {
1776 		_iov_alloc_buf(&bounce_iovs[i], (4096 + 128) * 2 * (i + 1));
1777 		num_blocks += 2 * (i + 1);
1778 	}
1779 
1780 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1781 				false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22, dif_pi_format);
1782 
1783 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1784 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22,
1785 				dif_pi_format);
1786 
1787 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1788 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22,
1789 				dif_pi_format);
1790 
1791 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1792 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22,
1793 				dif_pi_format);
1794 
1795 	for (i = 0; i < 4; i++) {
1796 		_iov_free_buf(&iovs[i]);
1797 	}
1798 
1799 	for (i = 0; i < 2; i++) {
1800 		_iov_free_buf(&bounce_iovs[i]);
1801 	}
1802 }
1803 
1804 static void
1805 dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(void)
1806 {
1807 	_dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(SPDK_DIF_PI_FORMAT_32);
1808 	_dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(SPDK_DIF_PI_FORMAT_64);
1809 }
1810 
1811 static void
1812 _nvme_pract_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(
1813 	enum spdk_dif_pi_format dif_pi_format)
1814 {
1815 	struct iovec iovs[4], bounce_iovs[2];
1816 	int i, num_blocks;
1817 
1818 	num_blocks = 0;
1819 
1820 	for (i = 0; i < 4; i++) {
1821 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
1822 		num_blocks += i + 1;
1823 	}
1824 
1825 	num_blocks = 0;
1826 
1827 	for (i = 0; i < 2; i++) {
1828 		_iov_alloc_buf(&bounce_iovs[i], (4096 + 128) * 2 * (i + 1));
1829 		num_blocks += 2 * (i + 1);
1830 	}
1831 
1832 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1833 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_NVME_PRACT,
1834 				22, 0xFFFF, 0x22, dif_pi_format);
1835 
1836 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1837 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_NVME_PRACT,
1838 				22, 0xFFFF, 0x22, dif_pi_format);
1839 
1840 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1841 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_NVME_PRACT,
1842 				22, 0xFFFF, 0x22, dif_pi_format);
1843 
1844 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1845 				false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK | SPDK_DIF_FLAGS_NVME_PRACT,
1846 				22, 0xFFFF, 0x22, dif_pi_format);
1847 
1848 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1849 				true, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_NVME_PRACT,
1850 				22, 0xFFFF, 0x22, dif_pi_format);
1851 
1852 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1853 				true, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_NVME_PRACT,
1854 				22, 0xFFFF, 0x22, dif_pi_format);
1855 
1856 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1857 				true, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_NVME_PRACT,
1858 				22, 0xFFFF, 0x22, dif_pi_format);
1859 
1860 	dif_copy_gen_and_verify(iovs, 4, bounce_iovs, 2, 4096 + 128, 128, num_blocks,
1861 				true, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_REFTAG_CHECK | SPDK_DIF_FLAGS_NVME_PRACT,
1862 				22, 0xFFFF, 0x22, dif_pi_format);
1863 
1864 	for (i = 0; i < 4; i++) {
1865 		_iov_free_buf(&iovs[i]);
1866 	}
1867 
1868 	for (i = 0; i < 2; i++) {
1869 		_iov_free_buf(&bounce_iovs[i]);
1870 	}
1871 }
1872 
1873 static void
1874 nvme_pract_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(void)
1875 {
1876 	_nvme_pract_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(SPDK_DIF_PI_FORMAT_32);
1877 	_nvme_pract_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test(SPDK_DIF_PI_FORMAT_64);
1878 }
1879 
1880 static void
1881 dif_copy_sec_4096_md_128_prchk_7_multi_iovs(void)
1882 {
1883 	struct iovec iovs[4], bounce_iov;
1884 	uint32_t dif_flags;
1885 	int i, num_blocks;
1886 
1887 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1888 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1889 
1890 	num_blocks = 0;
1891 
1892 	for (i = 0; i < 4; i++) {
1893 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
1894 		num_blocks += i + 1;
1895 	}
1896 
1897 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
1898 
1899 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1900 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
1901 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1902 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
1903 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1904 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
1905 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1906 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
1907 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1908 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
1909 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, num_blocks,
1910 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
1911 
1912 	for (i = 0; i < 4; i++) {
1913 		_iov_free_buf(&iovs[i]);
1914 	}
1915 	_iov_free_buf(&bounce_iov);
1916 }
1917 
1918 static void
1919 dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
1920 {
1921 	struct iovec iovs[2], bounce_iov;
1922 	uint32_t dif_flags;
1923 
1924 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1925 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1926 
1927 	_iov_alloc_buf(&iovs[0], 256);
1928 	_iov_alloc_buf(&iovs[1], 256);
1929 
1930 	_iov_alloc_buf(&bounce_iov, 512 + 8);
1931 
1932 	dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 1, 512 + 8, 8, 1,
1933 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
1934 
1935 	_iov_free_buf(&iovs[0]);
1936 	_iov_free_buf(&iovs[1]);
1937 	_iov_free_buf(&bounce_iov);
1938 }
1939 
1940 static void
1941 dif_copy_sec_4096_md_128_prchk_7_multi_iovs_split_data_test(void)
1942 {
1943 	struct iovec iovs[2], bounce_iov;
1944 	uint32_t dif_flags;
1945 
1946 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1947 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1948 
1949 	_iov_alloc_buf(&iovs[0], 2048);
1950 	_iov_alloc_buf(&iovs[1], 2048);
1951 
1952 	_iov_alloc_buf(&bounce_iov, 4096 + 128);
1953 
1954 	dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 1, 4096 + 128, 128, 1,
1955 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
1956 	dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 1, 4096 + 128, 128, 1,
1957 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
1958 
1959 	_iov_free_buf(&iovs[0]);
1960 	_iov_free_buf(&iovs[1]);
1961 	_iov_free_buf(&bounce_iov);
1962 }
1963 
1964 static void
1965 dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
1966 {
1967 	struct iovec iovs[6], bounce_iov;
1968 	uint32_t dif_flags;
1969 	int i;
1970 
1971 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
1972 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
1973 
1974 	/* data[0][255:0] */
1975 	_iov_alloc_buf(&iovs[0], 256);
1976 
1977 	/* data[0][511:256], data[1][255:0] */
1978 	_iov_alloc_buf(&iovs[1], 256 + 256);
1979 
1980 	/* data[1][382:256] */
1981 	_iov_alloc_buf(&iovs[2], 128);
1982 
1983 	/* data[1][383] */
1984 	_iov_alloc_buf(&iovs[3], 1);
1985 
1986 	/* data[1][510:384] */
1987 	_iov_alloc_buf(&iovs[4], 126);
1988 
1989 	/* data[1][511], data[2][511:0], data[3][511:0] */
1990 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
1991 
1992 	_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
1993 
1994 	dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 1, 512 + 8, 8, 4,
1995 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
1996 
1997 	for (i = 0; i < 6; i++) {
1998 		_iov_free_buf(&iovs[i]);
1999 	}
2000 	_iov_free_buf(&bounce_iov);
2001 }
2002 
2003 static void
2004 dif_copy_sec_512_md_8_prchk_7_multi_bounce_iovs_complex_splits(void)
2005 {
2006 	struct iovec iovs[6], bounce_iovs[7];
2007 	uint32_t dif_flags;
2008 	int i;
2009 
2010 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2011 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2012 
2013 	/* src_data[0][255:0] */
2014 	_iov_alloc_buf(&iovs[0], 256);
2015 
2016 	/* src_data[0][511:256], src_data[1][255:0] */
2017 	_iov_alloc_buf(&iovs[1], 256 + 256);
2018 
2019 	/* src_data[1][382:256] */
2020 	_iov_alloc_buf(&iovs[2], 128);
2021 
2022 	/* src_data[1][383] */
2023 	_iov_alloc_buf(&iovs[3], 1);
2024 
2025 	/* src_data[1][510:384] */
2026 	_iov_alloc_buf(&iovs[4], 126);
2027 
2028 	/* src_data[1][511], src_data[2][511:0], src_data[3][511:0] */
2029 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
2030 
2031 	/* dst_data[0][516:0] */
2032 	_iov_alloc_buf(&bounce_iovs[0], 517);
2033 
2034 	/* dst_data[0][519:517], dst_data[1][260:0] */
2035 	_iov_alloc_buf(&bounce_iovs[1], 3 + 261);
2036 
2037 	/* dst_data[1][399:261] */
2038 	_iov_alloc_buf(&bounce_iovs[2], 139);
2039 
2040 	/* dst_data[1][511:400] */
2041 	_iov_alloc_buf(&bounce_iovs[3], 112);
2042 
2043 	/* dst_data[1][515:512] */
2044 	_iov_alloc_buf(&bounce_iovs[4], 4);
2045 
2046 	/* dst_data[1][519:516], dst_data[2][11:0] */
2047 	_iov_alloc_buf(&bounce_iovs[5], 21);
2048 
2049 	/* dst_data[1][519:12], dst_data[2][519:0], dst_data[3][519:0] */
2050 	_iov_alloc_buf(&bounce_iovs[6], 507 + 520 + 520);
2051 
2052 	dif_copy_gen_and_verify(iovs, 6, bounce_iovs, 7, 512 + 8, 8, 4,
2053 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2054 
2055 	for (i = 0; i < 6; i++) {
2056 		_iov_free_buf(&iovs[i]);
2057 	}
2058 
2059 	for (i = 0; i < 7; i++) {
2060 		_iov_free_buf(&bounce_iovs[i]);
2061 	}
2062 }
2063 
2064 static void
2065 dif_copy_sec_512_md_8_dif_disable_multi_bounce_iovs_complex_splits(void)
2066 {
2067 	struct iovec iovs[6], bounce_iovs[7];
2068 	int i;
2069 
2070 	/*
2071 	 * src_data is made of 4 blocks and its block size is 512.
2072 	 * dst_data is made of 4 blocks and its block size is 520.
2073 	 *
2074 	 * The first dimension of src_data[][] and dst_data[][] represents the
2075 	 * number of blocks, and the second dimension represents the bytes range.
2076 	 *
2077 	 * Test the case these data is split with arbitrary boundary.
2078 	 */
2079 
2080 	/* src_data[0][255:0] */
2081 	_iov_alloc_buf(&iovs[0], 256);
2082 
2083 	/* src_data[0][511:256], src_data[1][255:0] */
2084 	_iov_alloc_buf(&iovs[1], 256 + 256);
2085 
2086 	/* src_data[1][382:256] */
2087 	_iov_alloc_buf(&iovs[2], 128);
2088 
2089 	/* src_data[1][383] */
2090 	_iov_alloc_buf(&iovs[3], 1);
2091 
2092 	/* src_data[1][510:384] */
2093 	_iov_alloc_buf(&iovs[4], 126);
2094 
2095 	/* src_data[1][511], src_data[2][511:0], src_data[3][511:0] */
2096 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
2097 
2098 	/* dst_data[0][516:0] */
2099 	_iov_alloc_buf(&bounce_iovs[0], 517);
2100 
2101 	/* dst_data[0][519:517], dst_data[1][260:0] */
2102 	_iov_alloc_buf(&bounce_iovs[1], 3 + 261);
2103 
2104 	/* dst_data[1][399:261] */
2105 	_iov_alloc_buf(&bounce_iovs[2], 139);
2106 
2107 	/* dst_data[1][511:400] */
2108 	_iov_alloc_buf(&bounce_iovs[3], 112);
2109 
2110 	/* dst_data[1][515:512] */
2111 	_iov_alloc_buf(&bounce_iovs[4], 4);
2112 
2113 	/* dst_data[1][519:516], dst_data[2][11:0] */
2114 	_iov_alloc_buf(&bounce_iovs[5], 21);
2115 
2116 	/* dst_data[1][519:12], dst_data[2][519:0], dst_data[3][519:0] */
2117 	_iov_alloc_buf(&bounce_iovs[6], 507 + 520 + 520);
2118 
2119 	dif_copy_gen_and_verify(iovs, 6, bounce_iovs, 7, 512 + 8, 8, 4,
2120 				true, SPDK_DIF_DISABLE, 0, 0, 0, 0, SPDK_DIF_PI_FORMAT_16);
2121 
2122 	for (i = 0; i < 6; i++) {
2123 		_iov_free_buf(&iovs[i]);
2124 	}
2125 
2126 	for (i = 0; i < 7; i++) {
2127 		_iov_free_buf(&bounce_iovs[i]);
2128 	}
2129 }
2130 
2131 static void
2132 dif_copy_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void)
2133 {
2134 	struct iovec iovs[6], bounce_iov;
2135 	uint32_t dif_flags;
2136 	int i;
2137 
2138 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2139 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2140 
2141 	/* data[0][2047:0] */
2142 	_iov_alloc_buf(&iovs[0], 2048);
2143 
2144 	/* data[0][4095:2048], data[1][2047:0] */
2145 	_iov_alloc_buf(&iovs[1], 2048 + 2048);
2146 
2147 	/* data[1][3071:2048] */
2148 	_iov_alloc_buf(&iovs[2], 1024);
2149 
2150 	/* data[1][3072] */
2151 	_iov_alloc_buf(&iovs[3], 1);
2152 
2153 	/* data[1][4094:3073] */
2154 	_iov_alloc_buf(&iovs[4], 1022);
2155 
2156 	/* data[1][4095], data[2][4095:0], data[3][4095:0] */
2157 	_iov_alloc_buf(&iovs[5], 1 + 4096 * 2);
2158 
2159 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * 4);
2160 
2161 	dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 1, 4096 + 128, 128, 4,
2162 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
2163 	dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 1, 4096 + 128, 128, 4,
2164 				true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
2165 
2166 	for (i = 0; i < 6; i++) {
2167 		_iov_free_buf(&iovs[i]);
2168 	}
2169 	_iov_free_buf(&bounce_iov);
2170 }
2171 
2172 static void
2173 nvme_pract_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void)
2174 {
2175 	struct iovec iovs[4], bounce_iov;
2176 	uint32_t dif_flags;
2177 	int i;
2178 
2179 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2180 		    SPDK_DIF_FLAGS_REFTAG_CHECK | SPDK_DIF_FLAGS_NVME_PRACT;
2181 
2182 	/* data[0][2047:0] */
2183 	_iov_alloc_buf(&iovs[0], 2048);
2184 
2185 	/* data[0][4223:2048], data[1][4220:0] */
2186 	_iov_alloc_buf(&iovs[1], 2176 + 4221);
2187 
2188 	/* data[1][4223:4221] data[2][4210:0] */
2189 	_iov_alloc_buf(&iovs[2], 3 + 4211);
2190 
2191 	/* data[2][4223:4211], data[3][4223:0] */
2192 	_iov_alloc_buf(&iovs[3], 13 + 4224);
2193 
2194 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * 4);
2195 
2196 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, 4,
2197 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
2198 	dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 1, 4096 + 128, 128, 4,
2199 				false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
2200 
2201 	for (i = 0; i < 4; i++) {
2202 		_iov_free_buf(&iovs[i]);
2203 	}
2204 	_iov_free_buf(&bounce_iov);
2205 }
2206 
2207 static void
2208 _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
2209 				  uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
2210 				  uint32_t inject_flags, bool dif_loc, enum spdk_dif_pi_format dif_pi_format)
2211 {
2212 	struct spdk_dif_ctx ctx = {};
2213 	struct spdk_dif_error err_blk = {};
2214 	uint32_t inject_offset = 0, dif_flags;
2215 	int rc;
2216 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2217 
2218 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2219 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2220 
2221 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
2222 	CU_ASSERT(rc == 0);
2223 
2224 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2225 	dif_opts.dif_pi_format = dif_pi_format;
2226 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags,
2227 			       88, 0xFFFF, 0x88, 0, GUARD_SEED, &dif_opts);
2228 	SPDK_CU_ASSERT_FATAL(rc == 0);
2229 
2230 	rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, 1, num_blocks, &ctx);
2231 	CU_ASSERT(rc == 0);
2232 
2233 	rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset);
2234 	CU_ASSERT(rc == 0);
2235 
2236 	rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, 1, num_blocks, &ctx, &err_blk);
2237 	CU_ASSERT(rc != 0);
2238 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
2239 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
2240 	} else {
2241 		CU_ASSERT(inject_flags == err_blk.err_type);
2242 	}
2243 	CU_ASSERT(inject_offset == err_blk.err_offset);
2244 }
2245 
2246 static void
2247 dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
2248 				 uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
2249 				 uint32_t inject_flags, enum spdk_dif_pi_format dif_pi_format)
2250 {
2251 	/* The case that DIF is contained in the first 8/16 bytes of metadata. */
2252 	_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
2253 					  block_size, md_size, num_blocks,
2254 					  inject_flags, true, dif_pi_format);
2255 
2256 	/* The case that DIF is contained in the last 8/16 bytes of metadata. */
2257 	_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
2258 					  block_size, md_size, num_blocks,
2259 					  inject_flags, false, dif_pi_format);
2260 }
2261 
2262 static void
2263 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
2264 {
2265 	struct iovec iovs[4], bounce_iov;
2266 	int i, num_blocks;
2267 
2268 	num_blocks = 0;
2269 
2270 	for (i = 0; i < 4; i++) {
2271 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
2272 		num_blocks += i + 1;
2273 	}
2274 
2275 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
2276 
2277 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2278 					 num_blocks, SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
2279 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2280 					 num_blocks, SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2281 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2282 					 num_blocks, SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2283 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2284 					 num_blocks, SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
2285 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2286 					 num_blocks, SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
2287 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2288 					 num_blocks, SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2289 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2290 					 num_blocks, SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2291 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2292 					 num_blocks, SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
2293 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2294 					 num_blocks, SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
2295 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2296 					 num_blocks, SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2297 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2298 					 num_blocks, SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2299 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2300 					 num_blocks, SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
2301 
2302 	for (i = 0; i < 4; i++) {
2303 		_iov_free_buf(&iovs[i]);
2304 	}
2305 	_iov_free_buf(&bounce_iov);
2306 }
2307 
2308 static void
2309 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
2310 {
2311 	struct iovec iovs[4], bounce_iov;
2312 	int i;
2313 
2314 	_iov_alloc_buf(&iovs[0], 2048);
2315 	_iov_alloc_buf(&iovs[1], 2048);
2316 	_iov_alloc_buf(&iovs[2], 1);
2317 	_iov_alloc_buf(&iovs[3], 4095);
2318 
2319 	_iov_alloc_buf(&bounce_iov, (4096 + 128) * 2);
2320 
2321 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2322 					 2, SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
2323 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2324 					 2, SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2325 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2326 					 2, SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2327 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2328 					 2, SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
2329 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2330 					 2, SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
2331 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2332 					 2, SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2333 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2334 					 2, SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2335 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2336 					 2, SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
2337 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2338 					 2, SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
2339 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2340 					 2, SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2341 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2342 					 2, SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2343 	dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
2344 					 2, SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
2345 
2346 	for (i = 0; i < 4; i++) {
2347 		_iov_free_buf(&iovs[i]);
2348 	}
2349 	_iov_free_buf(&bounce_iov);
2350 }
2351 
2352 static void
2353 dix_sec_0_md_8_error(void)
2354 {
2355 	struct spdk_dif_ctx ctx;
2356 	int rc;
2357 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2358 
2359 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2360 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
2361 	rc = spdk_dif_ctx_init(&ctx, 0, 8, false, false, SPDK_DIF_TYPE1, 0,
2362 			       0, 0, 0, 0, 0, &dif_opts);
2363 	CU_ASSERT(rc != 0);
2364 }
2365 
2366 static void
2367 dix_sec_512_md_0_error(void)
2368 {
2369 	struct spdk_dif_ctx ctx;
2370 	int rc;
2371 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2372 
2373 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2374 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
2375 	rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0,
2376 			       0, 0, 0, 0, 0, &dif_opts);
2377 	CU_ASSERT(rc != 0);
2378 }
2379 
2380 static void
2381 _dix_sec_512_md_16_error(enum spdk_dif_pi_format dif_pi_format)
2382 {
2383 	struct spdk_dif_ctx ctx;
2384 	int rc;
2385 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2386 
2387 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2388 	dif_opts.dif_pi_format = dif_pi_format;
2389 	rc = spdk_dif_ctx_init(&ctx, 512, 16, false, false, SPDK_DIF_TYPE1, 0,
2390 			       0, 0, 0, 0, 0, &dif_opts);
2391 	CU_ASSERT(rc != 0);
2392 }
2393 
2394 static void
2395 dix_sec_512_md_16_error(void)
2396 {
2397 	_dix_sec_512_md_16_error(SPDK_DIF_PI_FORMAT_32);
2398 	_dix_sec_512_md_16_error(SPDK_DIF_PI_FORMAT_64);
2399 }
2400 
2401 static void
2402 _dix_sec_4096_md_0_8_error(enum spdk_dif_pi_format dif_pi_format)
2403 {
2404 	struct spdk_dif_ctx ctx = {};
2405 	int rc;
2406 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2407 
2408 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2409 	dif_opts.dif_pi_format = dif_pi_format;
2410 	/* Metadata size is 0. */
2411 	rc = spdk_dif_ctx_init(&ctx, 4096, 0, true, false, SPDK_DIF_TYPE1, 0,
2412 			       0, 0, 0, 0, 0, &dif_opts);
2413 	CU_ASSERT(rc != 0);
2414 
2415 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2416 	dif_opts.dif_pi_format = dif_pi_format;
2417 	/* Metadata size is 0. */
2418 	rc = spdk_dif_ctx_init(&ctx, 4096, 8, true, false, SPDK_DIF_TYPE1, 0,
2419 			       0, 0, 0, 0, 0, &dif_opts);
2420 	CU_ASSERT(rc != 0);
2421 }
2422 
2423 static void
2424 dix_sec_4096_md_0_8_error(void)
2425 {
2426 	_dix_sec_4096_md_0_8_error(SPDK_DIF_PI_FORMAT_32);
2427 	_dix_sec_4096_md_0_8_error(SPDK_DIF_PI_FORMAT_64);
2428 }
2429 
2430 static void
2431 dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
2432 			uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
2433 			bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
2434 			uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag,
2435 			enum spdk_dif_pi_format dif_pi_format)
2436 {
2437 	struct spdk_dif_ctx ctx;
2438 	int rc;
2439 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2440 
2441 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
2442 	CU_ASSERT(rc == 0);
2443 
2444 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2445 	dif_opts.dif_pi_format = dif_pi_format;
2446 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
2447 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED, &dif_opts);
2448 	CU_ASSERT(rc == 0);
2449 
2450 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
2451 	CU_ASSERT(rc == 0);
2452 
2453 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL);
2454 	CU_ASSERT(rc == 0);
2455 
2456 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks);
2457 	CU_ASSERT(rc == 0);
2458 }
2459 
2460 static void
2461 dix_sec_512_md_8_prchk_0_single_iov(void)
2462 {
2463 	struct iovec iov, md_iov;
2464 
2465 	_iov_alloc_buf(&iov, 512 * 4);
2466 	_iov_alloc_buf(&md_iov, 8 * 4);
2467 
2468 	dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0,
2469 				SPDK_DIF_PI_FORMAT_16);
2470 	dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0,
2471 				SPDK_DIF_PI_FORMAT_16);
2472 
2473 	_iov_free_buf(&iov);
2474 	_iov_free_buf(&md_iov);
2475 }
2476 
2477 static void
2478 _dix_sec_4096_md_128_prchk_0_single_iov_test(
2479 	enum spdk_dif_pi_format dif_pi_format)
2480 {
2481 	struct iovec iov, md_iov;
2482 
2483 	_iov_alloc_buf(&iov, 4096 * 4);
2484 	_iov_alloc_buf(&md_iov, 128 * 4);
2485 
2486 	dix_generate_and_verify(&iov, 1, &md_iov, 4096, 128, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0,
2487 				dif_pi_format);
2488 	dix_generate_and_verify(&iov, 1, &md_iov, 4096, 128, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0,
2489 				dif_pi_format);
2490 
2491 	_iov_free_buf(&iov);
2492 	_iov_free_buf(&md_iov);
2493 }
2494 
2495 static void
2496 dix_sec_4096_md_128_prchk_0_single_iov_test(void)
2497 {
2498 	_dix_sec_4096_md_128_prchk_0_single_iov_test(SPDK_DIF_PI_FORMAT_32);
2499 	_dix_sec_4096_md_128_prchk_0_single_iov_test(SPDK_DIF_PI_FORMAT_64);
2500 }
2501 
2502 static void
2503 dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
2504 {
2505 	struct iovec iovs[4], md_iov;
2506 	int i, num_blocks;
2507 
2508 	num_blocks = 0;
2509 
2510 	for (i = 0; i < 4; i++) {
2511 		_iov_alloc_buf(&iovs[i], 512 * (i + 1));
2512 		num_blocks += i + 1;
2513 	}
2514 	_iov_alloc_buf(&md_iov, 8 * num_blocks);
2515 
2516 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
2517 				0, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2518 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
2519 				SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2520 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
2521 				SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2522 	dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
2523 				SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2524 
2525 	for (i = 0; i < 4; i++) {
2526 		_iov_free_buf(&iovs[i]);
2527 	}
2528 	_iov_free_buf(&md_iov);
2529 }
2530 
2531 static void
2532 _dix_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(
2533 	enum spdk_dif_pi_format dif_pi_format)
2534 {
2535 	struct iovec iovs[4], md_iov;
2536 	int i, num_blocks;
2537 
2538 	num_blocks = 0;
2539 
2540 	for (i = 0; i < 4; i++) {
2541 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
2542 		num_blocks += i + 1;
2543 	}
2544 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
2545 
2546 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2547 				0, 22, 0xFFFF, 0x22, dif_pi_format);
2548 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2549 				SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22, dif_pi_format);
2550 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2551 				SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22, dif_pi_format);
2552 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2553 				SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22, dif_pi_format);
2554 
2555 	for (i = 0; i < 4; i++) {
2556 		_iov_free_buf(&iovs[i]);
2557 	}
2558 	_iov_free_buf(&md_iov);
2559 }
2560 
2561 static void
2562 dix_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(void)
2563 {
2564 	_dix_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(SPDK_DIF_PI_FORMAT_32);
2565 	_dix_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test(SPDK_DIF_PI_FORMAT_64);
2566 }
2567 
2568 /* TODO start here */
2569 
2570 static void
2571 dix_sec_4096_md_128_prchk_7_multi_iovs(void)
2572 {
2573 	struct iovec iovs[4], md_iov;
2574 	uint32_t dif_flags;
2575 	int i, num_blocks;
2576 
2577 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2578 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2579 
2580 	num_blocks = 0;
2581 
2582 	for (i = 0; i < 4; i++) {
2583 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
2584 		num_blocks += i + 1;
2585 	}
2586 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
2587 
2588 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2589 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2590 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
2591 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2592 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2593 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
2594 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
2595 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
2596 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
2597 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
2598 	dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
2599 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
2600 
2601 	for (i = 0; i < 4; i++) {
2602 		_iov_free_buf(&iovs[i]);
2603 	}
2604 	_iov_free_buf(&md_iov);
2605 }
2606 
2607 static void
2608 dix_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
2609 {
2610 	struct iovec iovs[2], md_iov;
2611 	uint32_t dif_flags;
2612 
2613 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2614 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2615 
2616 	_iov_alloc_buf(&iovs[0], 256);
2617 	_iov_alloc_buf(&iovs[1], 256);
2618 	_iov_alloc_buf(&md_iov, 8);
2619 
2620 	dix_generate_and_verify(iovs, 2, &md_iov, 512, 8, 1, false, SPDK_DIF_TYPE1,
2621 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2622 
2623 	_iov_free_buf(&iovs[0]);
2624 	_iov_free_buf(&iovs[1]);
2625 	_iov_free_buf(&md_iov);
2626 }
2627 
2628 static void
2629 dix_sec_4096_md_128_prchk_7_multi_iovs_split_data_test(void)
2630 {
2631 	struct iovec iovs[2], md_iov;
2632 	uint32_t dif_flags;
2633 
2634 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2635 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2636 
2637 	_iov_alloc_buf(&iovs[0], 2048);
2638 	_iov_alloc_buf(&iovs[1], 2048);
2639 	_iov_alloc_buf(&md_iov, 128);
2640 
2641 	dix_generate_and_verify(iovs, 2, &md_iov, 4096, 128, 1, false, SPDK_DIF_TYPE1,
2642 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
2643 	dix_generate_and_verify(iovs, 2, &md_iov, 4096, 128, 1, false, SPDK_DIF_TYPE1,
2644 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
2645 
2646 	_iov_free_buf(&iovs[0]);
2647 	_iov_free_buf(&iovs[1]);
2648 	_iov_free_buf(&md_iov);
2649 }
2650 
2651 static void
2652 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
2653 {
2654 	struct iovec iovs[6], md_iov;
2655 	uint32_t dif_flags;
2656 	int i;
2657 
2658 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2659 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2660 
2661 	/* data[0][255:0] */
2662 	_iov_alloc_buf(&iovs[0], 256);
2663 
2664 	/* data[0][511:256], data[1][255:0] */
2665 	_iov_alloc_buf(&iovs[1], 256 + 256);
2666 
2667 	/* data[1][382:256] */
2668 	_iov_alloc_buf(&iovs[2], 128);
2669 
2670 	/* data[1][383] */
2671 	_iov_alloc_buf(&iovs[3], 1);
2672 
2673 	/* data[1][510:384] */
2674 	_iov_alloc_buf(&iovs[4], 126);
2675 
2676 	/* data[1][511], data[2][511:0], data[3][511:0] */
2677 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
2678 
2679 	_iov_alloc_buf(&md_iov, 8 * 4);
2680 
2681 	dix_generate_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1,
2682 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
2683 
2684 	for (i = 0; i < 6; i++) {
2685 		_iov_free_buf(&iovs[i]);
2686 	}
2687 	_iov_free_buf(&md_iov);
2688 }
2689 
2690 static void
2691 dix_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void)
2692 {
2693 	struct iovec iovs[6], md_iov;
2694 	uint32_t dif_flags;
2695 	int i;
2696 
2697 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2698 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2699 
2700 	/* data[0][2047:0] */
2701 	_iov_alloc_buf(&iovs[0], 2048);
2702 
2703 	/* data[0][4095:2048], data[1][2047:0] */
2704 	_iov_alloc_buf(&iovs[1], 2048 + 2048);
2705 
2706 	/* data[1][3071:2048] */
2707 	_iov_alloc_buf(&iovs[2], 1024);
2708 
2709 	/* data[1][3072] */
2710 	_iov_alloc_buf(&iovs[3], 1);
2711 
2712 	/* data[1][4094:3073] */
2713 	_iov_alloc_buf(&iovs[4], 1022);
2714 
2715 	/* data[1][4095], data[2][4095:0], data[3][4095:0] */
2716 	_iov_alloc_buf(&iovs[5], 1 + 4096 * 2);
2717 
2718 	_iov_alloc_buf(&md_iov, 128 * 4);
2719 
2720 	dix_generate_and_verify(iovs, 6, &md_iov, 4096, 128, 4, false, SPDK_DIF_TYPE1,
2721 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
2722 	dix_generate_and_verify(iovs, 6, &md_iov, 4096, 128, 4, false, SPDK_DIF_TYPE1,
2723 				dif_flags, 22, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
2724 
2725 	for (i = 0; i < 6; i++) {
2726 		_iov_free_buf(&iovs[i]);
2727 	}
2728 	_iov_free_buf(&md_iov);
2729 }
2730 
2731 static void
2732 _dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
2733 			     uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
2734 			     uint32_t inject_flags, bool dif_loc, enum spdk_dif_pi_format dif_pi_format)
2735 {
2736 	struct spdk_dif_ctx ctx = {};
2737 	struct spdk_dif_error err_blk = {};
2738 	uint32_t inject_offset = 0, dif_flags;
2739 	int rc;
2740 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2741 
2742 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2743 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
2744 
2745 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
2746 	CU_ASSERT(rc == 0);
2747 
2748 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2749 	dif_opts.dif_pi_format = dif_pi_format;
2750 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags,
2751 			       88, 0xFFFF, 0x88, 0, GUARD_SEED, &dif_opts);
2752 	CU_ASSERT(rc == 0);
2753 
2754 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
2755 	CU_ASSERT(rc == 0);
2756 
2757 	rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset);
2758 	CU_ASSERT(rc == 0);
2759 
2760 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, &err_blk);
2761 	CU_ASSERT(rc != 0);
2762 
2763 	if (inject_flags == SPDK_DIF_DATA_ERROR) {
2764 		CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
2765 	} else {
2766 		CU_ASSERT(inject_flags == err_blk.err_type);
2767 	}
2768 	CU_ASSERT(inject_offset == err_blk.err_offset);
2769 }
2770 
2771 static void
2772 dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
2773 			    uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
2774 			    uint32_t inject_flags, enum spdk_dif_pi_format dif_pi_format)
2775 {
2776 	/* The case that DIF is contained in the first 8/16 bytes of metadata. */
2777 	_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
2778 				     inject_flags, true, dif_pi_format);
2779 
2780 	/* The case that DIF is contained in the last 8/16 bytes of metadata. */
2781 	_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
2782 				     inject_flags, false, dif_pi_format);
2783 }
2784 
2785 static void
2786 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
2787 {
2788 	struct iovec iovs[4], md_iov;
2789 	int i, num_blocks;
2790 
2791 	num_blocks = 0;
2792 
2793 	for (i = 0; i < 4; i++) {
2794 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
2795 		num_blocks += i + 1;
2796 	}
2797 
2798 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
2799 
2800 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2801 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
2802 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2803 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2804 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2805 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2806 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2807 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
2808 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2809 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
2810 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2811 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2812 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2813 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2814 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2815 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
2816 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2817 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
2818 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2819 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2820 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2821 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2822 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks,
2823 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
2824 
2825 	for (i = 0; i < 4; i++) {
2826 		_iov_free_buf(&iovs[i]);
2827 	}
2828 	_iov_free_buf(&md_iov);
2829 }
2830 
2831 static void
2832 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
2833 {
2834 	struct iovec iovs[4], md_iov;
2835 	int i;
2836 
2837 	_iov_alloc_buf(&iovs[0], 2048);
2838 	_iov_alloc_buf(&iovs[1], 2048);
2839 	_iov_alloc_buf(&iovs[2], 1);
2840 	_iov_alloc_buf(&iovs[3], 4095);
2841 
2842 	_iov_alloc_buf(&md_iov, 128 * 2);
2843 
2844 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2845 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_16);
2846 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2847 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2848 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2849 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_16);
2850 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2851 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_16);
2852 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2853 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_32);
2854 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2855 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2856 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2857 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_32);
2858 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2859 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_32);
2860 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2861 				    SPDK_DIF_GUARD_ERROR, SPDK_DIF_PI_FORMAT_64);
2862 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2863 				    SPDK_DIF_APPTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2864 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2865 				    SPDK_DIF_REFTAG_ERROR, SPDK_DIF_PI_FORMAT_64);
2866 	dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2,
2867 				    SPDK_DIF_DATA_ERROR, SPDK_DIF_PI_FORMAT_64);
2868 
2869 	for (i = 0; i < 4; i++) {
2870 		_iov_free_buf(&iovs[i]);
2871 	}
2872 	_iov_free_buf(&md_iov);
2873 }
2874 
2875 static int
2876 ut_readv(uint32_t read_base, uint32_t read_len, struct iovec *iovs, int iovcnt)
2877 {
2878 	int i;
2879 	uint32_t j, offset;
2880 	uint8_t *buf;
2881 
2882 	offset = 0;
2883 	for (i = 0; i < iovcnt; i++) {
2884 		buf = iovs[i].iov_base;
2885 		for (j = 0; j < iovs[i].iov_len; j++, offset++) {
2886 			if (offset >= read_len) {
2887 				return offset;
2888 			}
2889 			buf[j] = DATA_PATTERN(read_base + offset);
2890 		}
2891 	}
2892 
2893 	return offset;
2894 }
2895 
2896 static void
2897 _set_md_interleave_iovs_test(enum spdk_dif_pi_format dif_pi_format)
2898 {
2899 	struct spdk_dif_ctx ctx = {};
2900 	struct spdk_dif_error err_blk = {};
2901 	struct iovec iov1, iov2, dif_iovs[4] = {};
2902 	uint32_t dif_check_flags, data_len, read_len, data_offset, mapped_len = 0;
2903 	uint8_t *buf1, *buf2;
2904 	int rc;
2905 	struct spdk_dif_ctx_init_ext_opts dif_opts;
2906 
2907 	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
2908 			  SPDK_DIF_FLAGS_REFTAG_CHECK;
2909 
2910 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
2911 	dif_opts.dif_pi_format = dif_pi_format;
2912 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
2913 			       dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED, &dif_opts);
2914 	CU_ASSERT(rc == 0);
2915 
2916 	/* The first data buffer:
2917 	 * - Create iovec array to Leave a space for metadata for each block
2918 	 * - Split vectored read and so creating iovec array is done before every vectored read.
2919 	 */
2920 	buf1 = calloc(1, (4096 + 128) * 4);
2921 	SPDK_CU_ASSERT_FATAL(buf1 != NULL);
2922 	_iov_set_buf(&iov1, buf1, (4096 + 128) * 4);
2923 
2924 	data_offset = 0;
2925 	data_len = 4096 * 4;
2926 
2927 	/* 1st read */
2928 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
2929 					     data_offset, data_len, &mapped_len, &ctx);
2930 	CU_ASSERT(rc == 4);
2931 	CU_ASSERT(mapped_len == 4096 * 4);
2932 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1, 4096) == true);
2933 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
2934 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
2935 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
2936 
2937 	read_len = ut_readv(data_offset, 1024, dif_iovs, 4);
2938 	CU_ASSERT(read_len == 1024);
2939 
2940 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
2941 	CU_ASSERT(rc == 0);
2942 
2943 	data_offset += read_len;
2944 	data_len -= read_len;
2945 
2946 	/* 2nd read */
2947 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
2948 					     data_offset, data_len, &mapped_len, &ctx);
2949 	CU_ASSERT(rc == 4);
2950 	CU_ASSERT(mapped_len == 3072 + 4096 * 3);
2951 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 1024, 3072) == true);
2952 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
2953 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
2954 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
2955 
2956 	read_len = ut_readv(data_offset, 3071, dif_iovs, 4);
2957 	CU_ASSERT(read_len == 3071);
2958 
2959 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
2960 	CU_ASSERT(rc == 0);
2961 
2962 	data_offset += read_len;
2963 	data_len -= read_len;
2964 
2965 	/* 3rd read */
2966 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
2967 					     data_offset, data_len, &mapped_len, &ctx);
2968 	CU_ASSERT(rc == 4);
2969 	CU_ASSERT(mapped_len == 1 + 4096 * 3);
2970 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 4095, 1) == true);
2971 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
2972 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
2973 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 4096) == true);
2974 
2975 	read_len = ut_readv(data_offset, 1 + 4096 * 2 + 512, dif_iovs, 4);
2976 	CU_ASSERT(read_len == 1 + 4096 * 2 + 512);
2977 
2978 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
2979 	CU_ASSERT(rc == 0);
2980 
2981 	data_offset += read_len;
2982 	data_len -= read_len;
2983 
2984 	/* 4th read */
2985 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
2986 					     data_offset, data_len, &mapped_len, &ctx);
2987 	CU_ASSERT(rc == 1);
2988 	CU_ASSERT(mapped_len == 3584);
2989 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + (4096 + 128) * 3 + 512, 3584) == true);
2990 
2991 	read_len = ut_readv(data_offset, 3584, dif_iovs, 1);
2992 	CU_ASSERT(read_len == 3584);
2993 
2994 	rc = spdk_dif_generate_stream(&iov1, 1, data_offset, read_len, &ctx);
2995 	CU_ASSERT(rc == 0);
2996 
2997 	data_offset += read_len;
2998 	CU_ASSERT(data_offset == 4096 * 4);
2999 	data_len -= read_len;
3000 	CU_ASSERT(data_len == 0);
3001 
3002 	/* The second data buffer:
3003 	 * - Set data pattern with a space for metadata for each block.
3004 	 */
3005 	buf2 = calloc(1, (4096 + 128) * 4);
3006 	SPDK_CU_ASSERT_FATAL(buf2 != NULL);
3007 	_iov_set_buf(&iov2, buf2, (4096 + 128) * 4);
3008 
3009 	rc = ut_data_pattern_generate(&iov2, 1, 4096 + 128, 128, 4);
3010 	CU_ASSERT(rc == 0);
3011 	rc = spdk_dif_generate(&iov2, 1, 4, &ctx);
3012 	CU_ASSERT(rc == 0);
3013 
3014 	rc = spdk_dif_verify(&iov1, 1, 4, &ctx, &err_blk);
3015 	CU_ASSERT(rc == 0);
3016 
3017 	rc = spdk_dif_verify(&iov2, 1, 4, &ctx, &err_blk);
3018 	CU_ASSERT(rc == 0);
3019 
3020 	/* Compare the first and the second data buffer by byte. */
3021 	rc = memcmp(buf1, buf2, (4096 + 128) * 4);
3022 	CU_ASSERT(rc == 0);
3023 
3024 	free(buf1);
3025 	free(buf2);
3026 }
3027 
3028 static void
3029 set_md_interleave_iovs_test(void)
3030 {
3031 	_set_md_interleave_iovs_test(SPDK_DIF_PI_FORMAT_16);
3032 	_set_md_interleave_iovs_test(SPDK_DIF_PI_FORMAT_32);
3033 	_set_md_interleave_iovs_test(SPDK_DIF_PI_FORMAT_64);
3034 }
3035 
3036 static void
3037 set_md_interleave_iovs_split_test(void)
3038 {
3039 	struct spdk_dif_ctx ctx = {};
3040 	struct spdk_dif_error err_blk = {};
3041 	struct iovec iovs1[7], iovs2[7], dif_iovs[8] = {};
3042 	uint32_t dif_check_flags, data_len, read_len, data_offset, mapped_len = 0;
3043 	int rc, i;
3044 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3045 
3046 	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3047 			  SPDK_DIF_FLAGS_REFTAG_CHECK;
3048 
3049 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3050 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
3051 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
3052 			       dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED, &dif_opts);
3053 	CU_ASSERT(rc == 0);
3054 
3055 	/* The first SGL data buffer:
3056 	 * - Create iovec array to leave a space for metadata for each block
3057 	 * - Split vectored read and so creating iovec array is done before every vectored read.
3058 	 */
3059 	_iov_alloc_buf(&iovs1[0], 512 + 8 + 128);
3060 	_iov_alloc_buf(&iovs1[1], 128);
3061 	_iov_alloc_buf(&iovs1[2], 256 + 8);
3062 	_iov_alloc_buf(&iovs1[3], 100);
3063 	_iov_alloc_buf(&iovs1[4], 412 + 5);
3064 	_iov_alloc_buf(&iovs1[5], 3 + 300);
3065 	_iov_alloc_buf(&iovs1[6], 212 + 8);
3066 
3067 	data_offset = 0;
3068 	data_len = 512 * 4;
3069 
3070 	/* 1st read */
3071 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
3072 					     data_offset, data_len, &mapped_len, &ctx);
3073 	CU_ASSERT(rc == 8);
3074 	CU_ASSERT(mapped_len == 512 * 4);
3075 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base, 512) == true);
3076 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
3077 	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
3078 	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
3079 	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
3080 	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
3081 	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
3082 	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
3083 
3084 	read_len = ut_readv(data_offset, 128, dif_iovs, 8);
3085 	CU_ASSERT(read_len == 128);
3086 
3087 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
3088 	CU_ASSERT(rc == 0);
3089 
3090 	data_offset += read_len;
3091 	data_len -= read_len;
3092 
3093 	/* 2nd read */
3094 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
3095 					     data_offset, data_len, &mapped_len, &ctx);
3096 	CU_ASSERT(rc == 8);
3097 	CU_ASSERT(mapped_len == 384 + 512 * 3);
3098 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 128, 384) == true);
3099 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
3100 	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
3101 	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
3102 	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
3103 	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
3104 	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
3105 	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
3106 
3107 	read_len = ut_readv(data_offset, 383, dif_iovs, 8);
3108 	CU_ASSERT(read_len == 383);
3109 
3110 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
3111 	CU_ASSERT(rc == 0);
3112 
3113 	data_offset += read_len;
3114 	data_len -= read_len;
3115 
3116 	/* 3rd read */
3117 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
3118 					     data_offset, data_len, &mapped_len, &ctx);
3119 	CU_ASSERT(rc == 8);
3120 	CU_ASSERT(mapped_len == 1 + 512 * 3);
3121 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[0].iov_base + 511, 1) == true);
3122 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[0].iov_base + 512 + 8, 128) == true);
3123 	CU_ASSERT(_iov_check(&dif_iovs[2], iovs1[1].iov_base, 128) == true);
3124 	CU_ASSERT(_iov_check(&dif_iovs[3], iovs1[2].iov_base, 256) == true);
3125 	CU_ASSERT(_iov_check(&dif_iovs[4], iovs1[3].iov_base, 100) == true);
3126 	CU_ASSERT(_iov_check(&dif_iovs[5], iovs1[4].iov_base, 412) == true);
3127 	CU_ASSERT(_iov_check(&dif_iovs[6], iovs1[5].iov_base + 3, 300) == true);
3128 	CU_ASSERT(_iov_check(&dif_iovs[7], iovs1[6].iov_base, 212) == true);
3129 
3130 	read_len = ut_readv(data_offset, 1 + 512 * 2 + 128, dif_iovs, 8);
3131 	CU_ASSERT(read_len == 1 + 512 * 2 + 128);
3132 
3133 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
3134 	CU_ASSERT(rc == 0);
3135 
3136 	data_offset += read_len;
3137 	data_len -= read_len;
3138 
3139 	/* 4th read */
3140 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 8, iovs1, 7,
3141 					     data_offset, data_len, &mapped_len, &ctx);
3142 	CU_ASSERT(rc == 2);
3143 	CU_ASSERT(mapped_len == 384);
3144 	CU_ASSERT(_iov_check(&dif_iovs[0], iovs1[5].iov_base + 3 + 128, 172) == true);
3145 	CU_ASSERT(_iov_check(&dif_iovs[1], iovs1[6].iov_base, 212) == true);
3146 
3147 	read_len = ut_readv(data_offset, 384, dif_iovs, 8);
3148 	CU_ASSERT(read_len == 384);
3149 
3150 	rc = spdk_dif_generate_stream(iovs1, 7, data_offset, read_len, &ctx);
3151 	CU_ASSERT(rc == 0);
3152 
3153 	data_offset += read_len;
3154 	CU_ASSERT(data_offset == 512 * 4);
3155 	data_len -= read_len;
3156 	CU_ASSERT(data_len == 0);
3157 
3158 	/* The second SGL data buffer:
3159 	 * - Set data pattern with a space for metadata for each block.
3160 	 */
3161 	_iov_alloc_buf(&iovs2[0], 512 + 8 + 128);
3162 	_iov_alloc_buf(&iovs2[1], 128);
3163 	_iov_alloc_buf(&iovs2[2], 256 + 8);
3164 	_iov_alloc_buf(&iovs2[3], 100);
3165 	_iov_alloc_buf(&iovs2[4], 412 + 5);
3166 	_iov_alloc_buf(&iovs2[5], 3 + 300);
3167 	_iov_alloc_buf(&iovs2[6], 212 + 8);
3168 
3169 	rc = ut_data_pattern_generate(iovs2, 7, 512 + 8, 8, 4);
3170 	CU_ASSERT(rc == 0);
3171 	rc = spdk_dif_generate(iovs2, 7, 4, &ctx);
3172 	CU_ASSERT(rc == 0);
3173 
3174 	rc = spdk_dif_verify(iovs1, 7, 4, &ctx, &err_blk);
3175 	CU_ASSERT(rc == 0);
3176 
3177 	rc = spdk_dif_verify(iovs2, 7, 4, &ctx, &err_blk);
3178 	CU_ASSERT(rc == 0);
3179 
3180 	/* Compare the first and the second SGL data buffer by byte. */
3181 	for (i = 0; i < 7; i++) {
3182 		rc = memcmp(iovs1[i].iov_base, iovs2[i].iov_base,
3183 			    iovs1[i].iov_len);
3184 		CU_ASSERT(rc == 0);
3185 	}
3186 
3187 	for (i = 0; i < 7; i++) {
3188 		_iov_free_buf(&iovs1[i]);
3189 		_iov_free_buf(&iovs2[i]);
3190 	}
3191 }
3192 
3193 static void
3194 dif_generate_stream_pi_16_test(void)
3195 {
3196 	struct iovec iov;
3197 	struct spdk_dif_ctx ctx;
3198 	struct spdk_dif_error err_blk;
3199 	uint32_t dif_flags;
3200 	int rc;
3201 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3202 
3203 	_iov_alloc_buf(&iov, (512 + 8) * 5);
3204 
3205 	rc = ut_data_pattern_generate(&iov, 1, 512 + 8, 8, 5);
3206 	CU_ASSERT(rc == 0);
3207 
3208 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3209 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3210 
3211 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3212 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
3213 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, dif_flags,
3214 			       22, 0xFFFF, 0x22, 0, GUARD_SEED, &dif_opts);
3215 	CU_ASSERT(rc == 0);
3216 
3217 	rc = spdk_dif_generate_stream(&iov, 1, 0, 511, &ctx);
3218 	CU_ASSERT(rc == 0);
3219 
3220 	rc = spdk_dif_generate_stream(&iov, 1, 511, 1, &ctx);
3221 	CU_ASSERT(rc == 0);
3222 
3223 	rc = spdk_dif_generate_stream(&iov, 1, 512, 256, &ctx);
3224 	CU_ASSERT(rc == 0);
3225 
3226 	rc = spdk_dif_generate_stream(&iov, 1, 768, 512, &ctx);
3227 	CU_ASSERT(rc == 0);
3228 
3229 	rc = spdk_dif_generate_stream(&iov, 1, 1280, 1024, &ctx);
3230 	CU_ASSERT(rc == 0);
3231 
3232 	rc = spdk_dif_generate_stream(&iov, 1, 2304, 256, &ctx);
3233 	CU_ASSERT(rc == 0);
3234 
3235 	rc = spdk_dif_generate_stream(&iov, 1, 2560, 512, &ctx);
3236 	CU_ASSERT(rc == -ERANGE);
3237 
3238 	rc = spdk_dif_verify(&iov, 1, 5, &ctx, &err_blk);
3239 	CU_ASSERT(rc == 0);
3240 
3241 	rc = ut_data_pattern_verify(&iov, 1, 512 + 8, 8, 5);
3242 	CU_ASSERT(rc == 0);
3243 
3244 	_iov_free_buf(&iov);
3245 }
3246 
3247 static void
3248 _dif_generate_stream_test(enum spdk_dif_pi_format dif_pi_format)
3249 {
3250 	struct iovec iov;
3251 	struct spdk_dif_ctx ctx;
3252 	struct spdk_dif_error err_blk;
3253 	uint32_t dif_flags;
3254 	int rc;
3255 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3256 
3257 	_iov_alloc_buf(&iov, (4096 + 128) * 5);
3258 
3259 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 5);
3260 	CU_ASSERT(rc == 0);
3261 
3262 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3263 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3264 
3265 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3266 	dif_opts.dif_pi_format = dif_pi_format;
3267 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1, dif_flags,
3268 			       22, 0xFFFF, 0x22, 0, GUARD_SEED, &dif_opts);
3269 	CU_ASSERT(rc == 0);
3270 
3271 	rc = spdk_dif_generate_stream(&iov, 1, 0, 4095, &ctx);
3272 	CU_ASSERT(rc == 0);
3273 
3274 	rc = spdk_dif_generate_stream(&iov, 1, 4095, 1, &ctx);
3275 	CU_ASSERT(rc == 0);
3276 
3277 	rc = spdk_dif_generate_stream(&iov, 1, 4096, 2048, &ctx);
3278 	CU_ASSERT(rc == 0);
3279 
3280 	rc = spdk_dif_generate_stream(&iov, 1, 6144, 4096, &ctx);
3281 	CU_ASSERT(rc == 0);
3282 
3283 	rc = spdk_dif_generate_stream(&iov, 1, 10240, 8192, &ctx);
3284 	CU_ASSERT(rc == 0);
3285 
3286 	rc = spdk_dif_generate_stream(&iov, 1, 18432, 2048, &ctx);
3287 	CU_ASSERT(rc == 0);
3288 
3289 	rc = spdk_dif_generate_stream(&iov, 1, 20480, 4096, &ctx);
3290 	CU_ASSERT(rc == -ERANGE);
3291 
3292 	rc = spdk_dif_verify(&iov, 1, 5, &ctx, &err_blk);
3293 	CU_ASSERT(rc == 0);
3294 
3295 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 5);
3296 	CU_ASSERT(rc == 0);
3297 
3298 	_iov_free_buf(&iov);
3299 }
3300 
3301 static void
3302 dif_generate_stream_test(void)
3303 {
3304 	_dif_generate_stream_test(SPDK_DIF_PI_FORMAT_32);
3305 	_dif_generate_stream_test(SPDK_DIF_PI_FORMAT_64);
3306 }
3307 
3308 static void
3309 set_md_interleave_iovs_alignment_test(void)
3310 {
3311 	struct iovec iovs[3], dif_iovs[5] = {};
3312 	uint32_t mapped_len = 0;
3313 	int rc;
3314 	struct spdk_dif_ctx ctx;
3315 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3316 
3317 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3318 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
3319 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
3320 			       0, 0, 0, 0, 0, 0, &dif_opts);
3321 	CU_ASSERT(rc == 0);
3322 
3323 	/* The case that buffer size is smaller than necessary. */
3324 	_iov_set_buf(&iovs[0], (uint8_t *)0xDEADBEEF, 1024);
3325 	_iov_set_buf(&iovs[1], (uint8_t *)0xFEEDBEEF, 1024);
3326 	_iov_set_buf(&iovs[2], (uint8_t *)0xC0FFEE, 24);
3327 
3328 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 0, 2048, &mapped_len, &ctx);
3329 	CU_ASSERT(rc == -ERANGE);
3330 
3331 	/* The following are the normal cases. */
3332 	_iov_set_buf(&iovs[2], (uint8_t *)0xC0FFEE, 32);
3333 
3334 	/* data length is less than a data block size. */
3335 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 0, 500, &mapped_len, &ctx);
3336 	CU_ASSERT(rc == 1);
3337 	CU_ASSERT(mapped_len == 500);
3338 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)0xDEADBEEF, 500) == true);
3339 
3340 	/* Pass enough number of iovecs */
3341 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 500, 1000, &mapped_len, &ctx);
3342 	CU_ASSERT(rc == 4);
3343 	CU_ASSERT(mapped_len == 1000);
3344 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xDEADBEEF + 500), 12) == true);
3345 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xDEADBEEF + 520), 504) == true);
3346 	CU_ASSERT(_iov_check(&dif_iovs[2], (void *)0xFEEDBEEF, 8) == true);
3347 	CU_ASSERT(_iov_check(&dif_iovs[3], (void *)(0xFEEDBEEF + 16), 476) == true);
3348 
3349 	/* Pass iovecs smaller than necessary */
3350 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 3, iovs, 3, 500, 1000, &mapped_len, &ctx);
3351 	CU_ASSERT(rc == 3);
3352 	CU_ASSERT(mapped_len == 524);
3353 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xDEADBEEF + 500), 12) == true);
3354 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xDEADBEEF + 520), 504) == true);
3355 	CU_ASSERT(_iov_check(&dif_iovs[2], (void *)0xFEEDBEEF, 8) == true);
3356 
3357 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 1500, 500, &mapped_len, &ctx);
3358 	CU_ASSERT(rc == 2);
3359 	CU_ASSERT(mapped_len == 500);
3360 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)(0xFEEDBEEF + 492), 36) == true);
3361 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)(0xFEEDBEEF + 536), 464) == true);
3362 
3363 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 5, iovs, 3, 2000, 48, &mapped_len, &ctx);
3364 	CU_ASSERT(rc == 2);
3365 	CU_ASSERT(mapped_len == 48);
3366 	CU_ASSERT(_iov_check(&dif_iovs[0], (void *)0xFEEDBEEF + 1000, 24) == true);
3367 	CU_ASSERT(_iov_check(&dif_iovs[1], (void *)0xC0FFEE, 24) ==  true);
3368 }
3369 
3370 static void
3371 _dif_generate_split_test(enum spdk_dif_pi_format dif_pi_format)
3372 {
3373 	struct spdk_dif_ctx ctx = {};
3374 	struct iovec iov;
3375 	uint8_t *buf1, *buf2;
3376 	struct _dif_sgl sgl;
3377 	uint64_t guard = 0, prev_guard;
3378 	uint32_t dif_flags;
3379 	int rc;
3380 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3381 
3382 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3383 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3384 
3385 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3386 	dif_opts.dif_pi_format = dif_pi_format;
3387 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
3388 			       dif_flags, 0, 0, 0, 0, GUARD_SEED, &dif_opts);
3389 	CU_ASSERT(rc == 0);
3390 
3391 	buf1 = calloc(1, 4096 + 128);
3392 	SPDK_CU_ASSERT_FATAL(buf1 != NULL);
3393 	_iov_set_buf(&iov, buf1, 4096 + 128);
3394 
3395 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
3396 	CU_ASSERT(rc == 0);
3397 
3398 	_dif_sgl_init(&sgl, &iov, 1);
3399 
3400 	guard = GUARD_SEED;
3401 	prev_guard = GUARD_SEED;
3402 
3403 	guard = _dif_generate_split(&sgl, 0, 1000, guard, 0, &ctx);
3404 	CU_ASSERT(sgl.iov_offset == 1000);
3405 	CU_ASSERT(guard == _generate_guard(prev_guard, buf1, 1000, dif_pi_format));
3406 
3407 	prev_guard = guard;
3408 
3409 	guard = _dif_generate_split(&sgl, 1000, 3000, guard, 0, &ctx);
3410 	CU_ASSERT(sgl.iov_offset == 4000);
3411 	CU_ASSERT(guard == _generate_guard(prev_guard, buf1 + 1000, 3000, dif_pi_format));
3412 
3413 	guard = _dif_generate_split(&sgl, 4000, 96 + 128, guard, 0, &ctx);
3414 	CU_ASSERT(guard == GUARD_SEED);
3415 	CU_ASSERT(sgl.iov_offset == 0);
3416 	CU_ASSERT(sgl.iovcnt == 0);
3417 
3418 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
3419 	CU_ASSERT(rc == 0);
3420 
3421 	_dif_sgl_init(&sgl, &iov, 1);
3422 
3423 	rc = dif_verify(&sgl, 1, &ctx, NULL);
3424 	CU_ASSERT(rc == 0);
3425 
3426 	buf2 = calloc(1, 4096 + 128);
3427 	SPDK_CU_ASSERT_FATAL(buf2 != NULL);
3428 	_iov_set_buf(&iov, buf2, 4096 + 128);
3429 
3430 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
3431 	CU_ASSERT(rc == 0);
3432 
3433 	_dif_sgl_init(&sgl, &iov, 1);
3434 
3435 	dif_generate(&sgl, 1, &ctx);
3436 
3437 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
3438 	CU_ASSERT(rc == 0);
3439 
3440 	_dif_sgl_init(&sgl, &iov, 1);
3441 
3442 	rc = dif_verify(&sgl, 1, &ctx, NULL);
3443 	CU_ASSERT(rc == 0);
3444 
3445 	rc = memcmp(buf1, buf2, 4096 + 128);
3446 	CU_ASSERT(rc == 0);
3447 
3448 	free(buf1);
3449 	free(buf2);
3450 }
3451 
3452 static void
3453 dif_generate_split_test(void)
3454 {
3455 	_dif_generate_split_test(SPDK_DIF_PI_FORMAT_16);
3456 	_dif_generate_split_test(SPDK_DIF_PI_FORMAT_32);
3457 	_dif_generate_split_test(SPDK_DIF_PI_FORMAT_64);
3458 }
3459 
3460 static void
3461 _set_md_interleave_iovs_multi_segments_test(enum spdk_dif_pi_format dif_pi_format)
3462 {
3463 	struct spdk_dif_ctx ctx = {};
3464 	struct spdk_dif_error err_blk = {};
3465 	struct iovec iov1 = {}, iov2 = {}, dif_iovs[4] = {};
3466 	uint32_t dif_check_flags, data_len, read_len, data_offset, read_offset, mapped_len = 0;
3467 	uint8_t *buf1, *buf2;
3468 	int rc;
3469 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3470 
3471 	dif_check_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3472 			  SPDK_DIF_FLAGS_REFTAG_CHECK;
3473 
3474 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3475 	dif_opts.dif_pi_format = dif_pi_format;
3476 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
3477 			       dif_check_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED, &dif_opts);
3478 	CU_ASSERT(rc == 0);
3479 
3480 	/* The first data buffer:
3481 	 * - Data buffer is split into multi data segments
3482 	 * - For each data segment,
3483 	 *  - Create iovec array to Leave a space for metadata for each block
3484 	 *  - Split vectored read and so creating iovec array is done before every vectored read.
3485 	 */
3486 	buf1 = calloc(1, (4096 + 128) * 4);
3487 	SPDK_CU_ASSERT_FATAL(buf1 != NULL);
3488 	_iov_set_buf(&iov1, buf1, (4096 + 128) * 4);
3489 
3490 	/* 1st data segment */
3491 	data_offset = 0;
3492 	data_len = 1024;
3493 
3494 	spdk_dif_ctx_set_data_offset(&ctx, data_offset);
3495 
3496 	read_offset = 0;
3497 
3498 	/* 1st read in 1st data segment */
3499 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
3500 					     read_offset, data_len - read_offset,
3501 					     &mapped_len, &ctx);
3502 	CU_ASSERT(rc == 1);
3503 	CU_ASSERT(mapped_len == 1024);
3504 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1, 1024) == true);
3505 
3506 	read_len = ut_readv(data_offset + read_offset, 1024, dif_iovs, 4);
3507 	CU_ASSERT(read_len == 1024);
3508 
3509 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
3510 	CU_ASSERT(rc == 0);
3511 
3512 	read_offset += read_len;
3513 	CU_ASSERT(read_offset == data_len);
3514 
3515 	/* 2nd data segment */
3516 	data_offset += data_len;
3517 	data_len = 3072 + 4096 * 2 + 512;
3518 
3519 	spdk_dif_ctx_set_data_offset(&ctx, data_offset);
3520 	_iov_set_buf(&iov1, buf1 + 1024, 3072 + 128 + (4096 + 128) * 3 + 512);
3521 
3522 	read_offset = 0;
3523 
3524 	/* 1st read in 2nd data segment */
3525 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
3526 					     read_offset, data_len - read_offset,
3527 					     &mapped_len, &ctx);
3528 	CU_ASSERT(rc == 4);
3529 	CU_ASSERT(mapped_len == 3072 + 4096 * 2 + 512);
3530 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 1024, 3072) == true);
3531 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
3532 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
3533 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 512) == true);
3534 
3535 	read_len = ut_readv(data_offset + read_offset, 3071, dif_iovs, 4);
3536 	CU_ASSERT(read_len == 3071);
3537 
3538 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
3539 	CU_ASSERT(rc == 0);
3540 
3541 	read_offset += read_len;
3542 
3543 	/* 2nd read in 2nd data segment */
3544 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
3545 					     read_offset, data_len - read_offset,
3546 					     &mapped_len, &ctx);
3547 	CU_ASSERT(rc == 4);
3548 	CU_ASSERT(mapped_len == 1 + 4096 * 2 + 512);
3549 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + 4095, 1) == true);
3550 	CU_ASSERT(_iov_check(&dif_iovs[1], buf1 + 4096 + 128, 4096) == true);
3551 	CU_ASSERT(_iov_check(&dif_iovs[2], buf1 + (4096 + 128) * 2, 4096) == true);
3552 	CU_ASSERT(_iov_check(&dif_iovs[3], buf1 + (4096 + 128) * 3, 512) == true);
3553 
3554 	read_len = ut_readv(data_offset + read_offset, 1 + 4096 * 2 + 512, dif_iovs, 4);
3555 	CU_ASSERT(read_len == 1 + 4096 * 2 + 512);
3556 
3557 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
3558 	CU_ASSERT(rc == 0);
3559 
3560 	read_offset += read_len;
3561 	CU_ASSERT(read_offset == data_len);
3562 
3563 	/* 3rd data segment */
3564 	data_offset += data_len;
3565 	data_len = 3584;
3566 
3567 	spdk_dif_ctx_set_data_offset(&ctx, data_offset);
3568 	_iov_set_buf(&iov1, buf1 + (4096 + 128) * 3 + 512, 3584 + 128);
3569 
3570 	read_offset = 0;
3571 
3572 	/* 1st read in 3rd data segment */
3573 	rc = spdk_dif_set_md_interleave_iovs(dif_iovs, 4, &iov1, 1,
3574 					     read_offset, data_len - read_offset,
3575 					     &mapped_len, &ctx);
3576 	CU_ASSERT(rc == 1);
3577 	CU_ASSERT(mapped_len == 3584);
3578 	CU_ASSERT(_iov_check(&dif_iovs[0], buf1 + (4096 + 128) * 3 + 512, 3584) == true);
3579 
3580 	read_len = ut_readv(data_offset + read_offset, 3584, dif_iovs, 1);
3581 	CU_ASSERT(read_len == 3584);
3582 
3583 	rc = spdk_dif_generate_stream(&iov1, 1, read_offset, read_len, &ctx);
3584 	CU_ASSERT(rc == 0);
3585 
3586 	read_offset += read_len;
3587 	CU_ASSERT(read_offset == data_len);
3588 	data_offset += data_len;
3589 	CU_ASSERT(data_offset == 4096 * 4);
3590 
3591 	spdk_dif_ctx_set_data_offset(&ctx, 0);
3592 	_iov_set_buf(&iov1, buf1, (4096 + 128) * 4);
3593 
3594 	/* The second data buffer:
3595 	 * - Set data pattern with a space for metadata for each block.
3596 	 */
3597 	buf2 = calloc(1, (4096 + 128) * 4);
3598 	SPDK_CU_ASSERT_FATAL(buf2 != NULL);
3599 	_iov_set_buf(&iov2, buf2, (4096 + 128) * 4);
3600 
3601 	rc = ut_data_pattern_generate(&iov2, 1, 4096 + 128, 128, 4);
3602 	CU_ASSERT(rc == 0);
3603 
3604 	rc = spdk_dif_generate(&iov2, 1, 4, &ctx);
3605 	CU_ASSERT(rc == 0);
3606 
3607 	rc = spdk_dif_verify(&iov1, 1, 4, &ctx, &err_blk);
3608 	CU_ASSERT(rc == 0);
3609 
3610 	rc = spdk_dif_verify(&iov2, 1, 4, &ctx, &err_blk);
3611 	CU_ASSERT(rc == 0);
3612 
3613 	/* Compare the first and the second data buffer by byte. */
3614 	rc = memcmp(buf1, buf2, (4096 + 128) * 4);
3615 	CU_ASSERT(rc == 0);
3616 
3617 	free(buf1);
3618 	free(buf2);
3619 }
3620 
3621 static void
3622 set_md_interleave_iovs_multi_segments_test(void)
3623 {
3624 	_set_md_interleave_iovs_multi_segments_test(SPDK_DIF_PI_FORMAT_16);
3625 	_set_md_interleave_iovs_multi_segments_test(SPDK_DIF_PI_FORMAT_32);
3626 	_set_md_interleave_iovs_multi_segments_test(SPDK_DIF_PI_FORMAT_64);
3627 }
3628 
3629 static void
3630 _dif_verify_split_test(enum spdk_dif_pi_format dif_pi_format)
3631 {
3632 	struct spdk_dif_ctx ctx = {};
3633 	struct spdk_dif_error err_blk = {};
3634 	struct iovec iov;
3635 	uint8_t *buf;
3636 	struct _dif_sgl sgl;
3637 	uint64_t guard = 0, prev_guard = 0;
3638 	uint32_t dif_flags;
3639 	int rc;
3640 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3641 
3642 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3643 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3644 
3645 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3646 	dif_opts.dif_pi_format = dif_pi_format;
3647 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
3648 			       dif_flags, 0, 0, 0, 0, GUARD_SEED, &dif_opts);
3649 	CU_ASSERT(rc == 0);
3650 
3651 	buf = calloc(1, 4096 + 128);
3652 	SPDK_CU_ASSERT_FATAL(buf != NULL);
3653 	_iov_set_buf(&iov, buf, 4096 + 128);
3654 
3655 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
3656 	CU_ASSERT(rc == 0);
3657 
3658 	_dif_sgl_init(&sgl, &iov, 1);
3659 
3660 	dif_generate(&sgl, 1, &ctx);
3661 
3662 	_dif_sgl_init(&sgl, &iov, 1);
3663 
3664 	guard = GUARD_SEED;
3665 	prev_guard = GUARD_SEED;
3666 
3667 	rc = _dif_verify_split(&sgl, 0, 1000, &guard, 0, &ctx, &err_blk);
3668 	CU_ASSERT(rc == 0);
3669 	CU_ASSERT(guard == _generate_guard(prev_guard, buf, 1000, dif_pi_format));
3670 	CU_ASSERT(sgl.iov_offset == 1000);
3671 
3672 	prev_guard = guard;
3673 
3674 	rc = _dif_verify_split(&sgl, 1000, 3000, &guard, 0, &ctx, &err_blk);
3675 	CU_ASSERT(rc == 0);
3676 	CU_ASSERT(guard == _generate_guard(prev_guard, buf + 1000, 3000, dif_pi_format));
3677 	CU_ASSERT(sgl.iov_offset == 4000);
3678 
3679 	rc = _dif_verify_split(&sgl, 4000, 96 + 128, &guard, 0, &ctx, &err_blk);
3680 	CU_ASSERT(rc == 0);
3681 	CU_ASSERT(guard == GUARD_SEED);
3682 	CU_ASSERT(sgl.iov_offset == 0);
3683 	CU_ASSERT(sgl.iovcnt == 0);
3684 
3685 	_dif_sgl_init(&sgl, &iov, 1);
3686 
3687 	rc = dif_verify(&sgl, 1, &ctx, &err_blk);
3688 	CU_ASSERT(rc == 0);
3689 
3690 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 1);
3691 	CU_ASSERT(rc == 0);
3692 
3693 	free(buf);
3694 }
3695 
3696 static void
3697 dif_verify_split_test(void)
3698 {
3699 	_dif_verify_split_test(SPDK_DIF_PI_FORMAT_16);
3700 	_dif_verify_split_test(SPDK_DIF_PI_FORMAT_32);
3701 	_dif_verify_split_test(SPDK_DIF_PI_FORMAT_64);
3702 }
3703 
3704 static void
3705 _dif_verify_stream_multi_segments_test(enum spdk_dif_pi_format dif_pi_format)
3706 {
3707 	struct spdk_dif_ctx ctx = {};
3708 	struct spdk_dif_error err_blk = {};
3709 	struct iovec iov = {};
3710 	uint8_t *buf;
3711 	uint32_t dif_flags;
3712 	int rc;
3713 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3714 
3715 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3716 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3717 
3718 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3719 	dif_opts.dif_pi_format = dif_pi_format;
3720 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
3721 			       dif_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED, &dif_opts);
3722 	CU_ASSERT(rc == 0);
3723 
3724 	buf = calloc(1, (4096 + 128) * 4);
3725 	SPDK_CU_ASSERT_FATAL(buf != NULL);
3726 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
3727 
3728 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 4);
3729 	CU_ASSERT(rc == 0);
3730 
3731 	rc = spdk_dif_generate(&iov, 1, 4, &ctx);
3732 	CU_ASSERT(rc == 0);
3733 
3734 	/* 1st data segment */
3735 	_iov_set_buf(&iov, buf, 1024);
3736 	spdk_dif_ctx_set_data_offset(&ctx, 0);
3737 
3738 	rc = spdk_dif_verify_stream(&iov, 1, 0, 1024, &ctx, &err_blk);
3739 	CU_ASSERT(rc == 0);
3740 
3741 	/* 2nd data segment */
3742 	_iov_set_buf(&iov, buf + 1024, (3072 + 128) + (4096 + 128) * 2 + 512);
3743 	spdk_dif_ctx_set_data_offset(&ctx, 1024);
3744 
3745 	rc = spdk_dif_verify_stream(&iov, 1, 0, 3072 + 4096 * 2 + 512, &ctx, &err_blk);
3746 	CU_ASSERT(rc == 0);
3747 
3748 	/* 3rd data segment */
3749 	_iov_set_buf(&iov, buf + (4096 + 128) * 3 + 512, 3584 + 128);
3750 	spdk_dif_ctx_set_data_offset(&ctx, 4096 * 3);
3751 
3752 	rc = spdk_dif_verify_stream(&iov, 1, 0, 3584, &ctx, &err_blk);
3753 	CU_ASSERT(rc == 0);
3754 
3755 	/* verify all data segments once */
3756 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
3757 	spdk_dif_ctx_set_data_offset(&ctx, 0);
3758 
3759 	rc = spdk_dif_verify(&iov, 1, 4, &ctx, &err_blk);
3760 	CU_ASSERT(rc == 0);
3761 
3762 	rc = ut_data_pattern_verify(&iov, 1, 4096 + 128, 128, 4);
3763 	CU_ASSERT(rc == 0);
3764 
3765 	free(buf);
3766 }
3767 
3768 static void
3769 dif_verify_stream_multi_segments_test(void)
3770 {
3771 	_dif_verify_stream_multi_segments_test(SPDK_DIF_PI_FORMAT_16);
3772 	_dif_verify_stream_multi_segments_test(SPDK_DIF_PI_FORMAT_32);
3773 	_dif_verify_stream_multi_segments_test(SPDK_DIF_PI_FORMAT_64);
3774 }
3775 
3776 #define UT_CRC32C_XOR	0xffffffffUL
3777 
3778 static void
3779 update_crc32c_pi_16_test(void)
3780 {
3781 	struct spdk_dif_ctx ctx = {};
3782 	struct iovec iovs[7];
3783 	uint32_t crc32c1, crc32c2, crc32c3, crc32c4;
3784 	uint32_t dif_flags;
3785 	int i, rc;
3786 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3787 
3788 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3789 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3790 
3791 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3792 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
3793 	rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1,
3794 			       dif_flags, 0, 0, 0, 0, 0, &dif_opts);
3795 	CU_ASSERT(rc == 0);
3796 
3797 	/* data[0][255:0] */
3798 	_iov_alloc_buf(&iovs[0], 256);
3799 
3800 	/* data[0][511:256], md[0][0] */
3801 	_iov_alloc_buf(&iovs[1], 256 + 1);
3802 
3803 	/* md[0][4:1] */
3804 	_iov_alloc_buf(&iovs[2], 4);
3805 
3806 	/* md[0][7:5], data[1][122:0] */
3807 	_iov_alloc_buf(&iovs[3], 3 + 123);
3808 
3809 	/* data[1][511:123], md[1][5:0] */
3810 	_iov_alloc_buf(&iovs[4], 389 + 6);
3811 
3812 	/* md[1][7:6], data[2][511:0], md[2][7:0], data[3][431:0] */
3813 	_iov_alloc_buf(&iovs[5], 2 + 512 + 8 + 432);
3814 
3815 	/* data[3][511:432], md[3][7:0] */
3816 	_iov_alloc_buf(&iovs[6], 80 + 8);
3817 
3818 	rc = ut_data_pattern_generate(iovs, 7, 512 + 8, 8, 4);
3819 	CU_ASSERT(rc == 0);
3820 
3821 	crc32c1 = UT_CRC32C_XOR;
3822 
3823 	rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c1, &ctx);
3824 	CU_ASSERT(rc == 0);
3825 
3826 	/* Test if DIF doesn't affect CRC for split case. */
3827 	rc = spdk_dif_generate(iovs, 7, 4, &ctx);
3828 	CU_ASSERT(rc == 0);
3829 
3830 	crc32c2 = UT_CRC32C_XOR;
3831 
3832 	rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c2, &ctx);
3833 	CU_ASSERT(rc == 0);
3834 
3835 	CU_ASSERT(crc32c1 == crc32c2);
3836 
3837 	for (i = 0; i < 7; i++) {
3838 		_iov_free_buf(&iovs[i]);
3839 	}
3840 
3841 	/* Test if CRC is same regardless of splitting. */
3842 	for (i = 0; i < 4; i++) {
3843 		_iov_alloc_buf(&iovs[i], 512 + 8);
3844 	}
3845 
3846 	rc = ut_data_pattern_generate(iovs, 4, 512 + 8, 8, 4);
3847 	CU_ASSERT(rc == 0);
3848 
3849 	crc32c3 = UT_CRC32C_XOR;
3850 
3851 	rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c3, &ctx);
3852 	CU_ASSERT(rc == 0);
3853 
3854 	CU_ASSERT(crc32c1 == crc32c3);
3855 
3856 	/* Test if DIF doesn't affect CRC for non-split case. */
3857 	rc = spdk_dif_generate(iovs, 4, 4, &ctx);
3858 	CU_ASSERT(rc == 0);
3859 
3860 	crc32c4 = UT_CRC32C_XOR;
3861 
3862 	rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c4, &ctx);
3863 	CU_ASSERT(rc == 0);
3864 
3865 	CU_ASSERT(crc32c1 == crc32c4);
3866 
3867 	for (i = 0; i < 4; i++) {
3868 		_iov_free_buf(&iovs[i]);
3869 	}
3870 }
3871 
3872 static void
3873 _update_crc32c_test(enum spdk_dif_pi_format dif_pi_format)
3874 {
3875 	struct spdk_dif_ctx ctx = {};
3876 	struct iovec iovs[7];
3877 	uint32_t crc32c1, crc32c2, crc32c3, crc32c4;
3878 	uint32_t dif_flags;
3879 	int i, rc;
3880 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3881 
3882 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3883 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3884 
3885 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3886 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_32;
3887 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
3888 			       dif_flags, 0, 0, 0, 0, 0, &dif_opts);
3889 	CU_ASSERT(rc == 0);
3890 
3891 	/* data[0][2047:0] */
3892 	_iov_alloc_buf(&iovs[0], 2048);
3893 
3894 	/* data[0][4095:2048], md[0][0] */
3895 	_iov_alloc_buf(&iovs[1], 2048 + 1);
3896 
3897 	/* md[0][4:1] */
3898 	_iov_alloc_buf(&iovs[2], 4);
3899 
3900 	/* md[0][127:5], data[1][122:0] */
3901 	_iov_alloc_buf(&iovs[3], 123 + 123);
3902 
3903 	/* data[1][4095:123], md[1][5:0] */
3904 	_iov_alloc_buf(&iovs[4], 3973 + 6);
3905 
3906 	/* md[1][127:6], data[2][4095:0], md[2][127:0], data[3][431:0] */
3907 	_iov_alloc_buf(&iovs[5], 122 + 4096 + 128 + 432);
3908 
3909 	/* data[3][511:432], md[3][127:0] */
3910 	_iov_alloc_buf(&iovs[6], 3665 + 128);
3911 
3912 	rc = ut_data_pattern_generate(iovs, 7, 4096 + 128, 128, 4);
3913 	CU_ASSERT(rc == 0);
3914 
3915 	crc32c1 = UT_CRC32C_XOR;
3916 
3917 	rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c1, &ctx);
3918 	CU_ASSERT(rc == 0);
3919 
3920 	/* Test if DIF doesn't affect CRC for split case. */
3921 	rc = spdk_dif_generate(iovs, 7, 4, &ctx);
3922 	CU_ASSERT(rc == 0);
3923 
3924 	crc32c2 = UT_CRC32C_XOR;
3925 
3926 	rc = spdk_dif_update_crc32c(iovs, 7, 4, &crc32c2, &ctx);
3927 	CU_ASSERT(rc == 0);
3928 
3929 	CU_ASSERT(crc32c1 == crc32c2);
3930 
3931 	for (i = 0; i < 7; i++) {
3932 		_iov_free_buf(&iovs[i]);
3933 	}
3934 
3935 	/* Test if CRC is same regardless of splitting. */
3936 	for (i = 0; i < 4; i++) {
3937 		_iov_alloc_buf(&iovs[i], 4096 + 128);
3938 	}
3939 
3940 	rc = ut_data_pattern_generate(iovs, 4, 4096 + 128, 128, 4);
3941 	CU_ASSERT(rc == 0);
3942 
3943 	crc32c3 = UT_CRC32C_XOR;
3944 
3945 	rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c3, &ctx);
3946 	CU_ASSERT(rc == 0);
3947 
3948 	CU_ASSERT(crc32c1 == crc32c3);
3949 
3950 	/* Test if DIF doesn't affect CRC for non-split case. */
3951 	rc = spdk_dif_generate(iovs, 4, 4, &ctx);
3952 	CU_ASSERT(rc == 0);
3953 
3954 	crc32c4 = UT_CRC32C_XOR;
3955 
3956 	rc = spdk_dif_update_crc32c(iovs, 4, 4, &crc32c4, &ctx);
3957 	CU_ASSERT(rc == 0);
3958 
3959 	CU_ASSERT(crc32c1 == crc32c4);
3960 
3961 	for (i = 0; i < 4; i++) {
3962 		_iov_free_buf(&iovs[i]);
3963 	}
3964 }
3965 
3966 static void
3967 update_crc32c_test(void)
3968 {
3969 	_update_crc32c_test(SPDK_DIF_PI_FORMAT_32);
3970 	_update_crc32c_test(SPDK_DIF_PI_FORMAT_64);
3971 }
3972 
3973 static void
3974 _dif_update_crc32c_split_test(enum spdk_dif_pi_format dif_pi_format)
3975 {
3976 	struct spdk_dif_ctx ctx = {};
3977 	struct iovec iov;
3978 	uint8_t *buf;
3979 	struct _dif_sgl sgl;
3980 	uint32_t dif_flags, crc32c, prev_crc32c;
3981 	int rc;
3982 	struct spdk_dif_ctx_init_ext_opts dif_opts;
3983 
3984 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
3985 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
3986 
3987 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
3988 	dif_opts.dif_pi_format = dif_pi_format;
3989 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
3990 			       dif_flags, 0, 0, 0, 0, GUARD_SEED, &dif_opts);
3991 	CU_ASSERT(rc == 0);
3992 
3993 	buf = calloc(1, 4096 + 128);
3994 	SPDK_CU_ASSERT_FATAL(buf != NULL);
3995 	_iov_set_buf(&iov, buf, 4096 + 128);
3996 
3997 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 1);
3998 	CU_ASSERT(rc == 0);
3999 
4000 	_dif_sgl_init(&sgl, &iov, 1);
4001 
4002 	dif_generate(&sgl, 1, &ctx);
4003 
4004 	_dif_sgl_init(&sgl, &iov, 1);
4005 
4006 	crc32c = _dif_update_crc32c_split(&sgl, 0, 1000, UT_CRC32C_XOR, &ctx);
4007 	CU_ASSERT(crc32c == spdk_crc32c_update(buf, 1000, UT_CRC32C_XOR));
4008 
4009 	prev_crc32c = crc32c;
4010 
4011 	crc32c = _dif_update_crc32c_split(&sgl, 1000, 3000, prev_crc32c, &ctx);
4012 	CU_ASSERT(crc32c == spdk_crc32c_update(buf + 1000, 3000, prev_crc32c));
4013 
4014 	prev_crc32c = crc32c;
4015 
4016 	crc32c = _dif_update_crc32c_split(&sgl, 4000, 96 + 128, prev_crc32c, &ctx);
4017 	CU_ASSERT(crc32c == spdk_crc32c_update(buf + 4000, 96, prev_crc32c));
4018 
4019 	CU_ASSERT(crc32c == spdk_crc32c_update(buf, 4096, UT_CRC32C_XOR));
4020 
4021 	free(buf);
4022 }
4023 
4024 static void
4025 dif_update_crc32c_split_test(void)
4026 {
4027 	_dif_update_crc32c_split_test(SPDK_DIF_PI_FORMAT_16);
4028 	_dif_update_crc32c_split_test(SPDK_DIF_PI_FORMAT_32);
4029 	_dif_update_crc32c_split_test(SPDK_DIF_PI_FORMAT_64);
4030 }
4031 
4032 static void
4033 _dif_update_crc32c_stream_multi_segments_test(enum spdk_dif_pi_format dif_pi_format)
4034 {
4035 	struct spdk_dif_ctx ctx = {};
4036 	struct iovec iov = {};
4037 	uint8_t *buf;
4038 	uint32_t dif_flags, crc32c1, crc32c2;
4039 	int rc;
4040 	struct spdk_dif_ctx_init_ext_opts dif_opts;
4041 
4042 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
4043 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
4044 
4045 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
4046 	dif_opts.dif_pi_format = dif_pi_format;
4047 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, SPDK_DIF_TYPE1,
4048 			       dif_flags, 22, 0xFFFF, 0x22, 0, GUARD_SEED, &dif_opts);
4049 	CU_ASSERT(rc == 0);
4050 
4051 	buf = calloc(1, (4096 + 128) * 4);
4052 	SPDK_CU_ASSERT_FATAL(buf != NULL);
4053 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
4054 
4055 	rc = ut_data_pattern_generate(&iov, 1, 4096 + 128, 128, 4);
4056 	CU_ASSERT(rc == 0);
4057 
4058 	rc = spdk_dif_generate(&iov, 1, 4, &ctx);
4059 	CU_ASSERT(rc == 0);
4060 
4061 	crc32c1 = UT_CRC32C_XOR;
4062 	crc32c2 = UT_CRC32C_XOR;
4063 
4064 	/* 1st data segment */
4065 	_iov_set_buf(&iov, buf, 1024);
4066 	spdk_dif_ctx_set_data_offset(&ctx, 0);
4067 
4068 	rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 1024, &crc32c1, &ctx);
4069 	CU_ASSERT(rc == 0);
4070 
4071 	/* 2nd data segment */
4072 	_iov_set_buf(&iov, buf + 1024, (3072 + 128) + (4096 + 128) * 2 + 512);
4073 	spdk_dif_ctx_set_data_offset(&ctx, 1024);
4074 
4075 	rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 3072 + 4096 * 2 + 512, &crc32c1, &ctx);
4076 	CU_ASSERT(rc == 0);
4077 
4078 	/* 3rd data segment */
4079 	_iov_set_buf(&iov, buf + (4096 + 128) * 3 + 512, 3584 + 128);
4080 	spdk_dif_ctx_set_data_offset(&ctx, 4096 * 3);
4081 
4082 	rc = spdk_dif_update_crc32c_stream(&iov, 1, 0, 3584, &crc32c1, &ctx);
4083 	CU_ASSERT(rc == 0);
4084 
4085 	/* Update CRC32C for all data segments once */
4086 	_iov_set_buf(&iov, buf, (4096 + 128) * 4);
4087 	spdk_dif_ctx_set_data_offset(&ctx, 0);
4088 
4089 	rc = spdk_dif_update_crc32c(&iov, 1, 4, &crc32c2, &ctx);
4090 	CU_ASSERT(rc == 0);
4091 
4092 	CU_ASSERT(crc32c1 == crc32c2);
4093 
4094 	free(buf);
4095 }
4096 
4097 static void
4098 dif_update_crc32c_stream_multi_segments_test(void)
4099 {
4100 	_dif_update_crc32c_stream_multi_segments_test(SPDK_DIF_PI_FORMAT_16);
4101 	_dif_update_crc32c_stream_multi_segments_test(SPDK_DIF_PI_FORMAT_32);
4102 	_dif_update_crc32c_stream_multi_segments_test(SPDK_DIF_PI_FORMAT_64);
4103 }
4104 
4105 static void
4106 get_range_with_md_test(void)
4107 {
4108 	struct spdk_dif_ctx ctx = {};
4109 	uint32_t buf_offset, buf_len;
4110 	int rc;
4111 	struct spdk_dif_ctx_init_ext_opts dif_opts;
4112 
4113 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
4114 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
4115 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, false, 0, 0,
4116 			       0, 0, 0, 0, 0, &dif_opts);
4117 	CU_ASSERT(rc == 0);
4118 
4119 	spdk_dif_get_range_with_md(0, 2048, &buf_offset, &buf_len, &ctx);
4120 	CU_ASSERT(buf_offset == 0);
4121 	CU_ASSERT(buf_len == 2048);
4122 
4123 	spdk_dif_get_range_with_md(2048, 4096, &buf_offset, &buf_len, &ctx);
4124 	CU_ASSERT(buf_offset == 2048);
4125 	CU_ASSERT(buf_len == 4096 + 128);
4126 
4127 	spdk_dif_get_range_with_md(4096, 10240, &buf_offset, &buf_len, &ctx);
4128 	CU_ASSERT(buf_offset == 4096 + 128);
4129 	CU_ASSERT(buf_len == 10240 + 256);
4130 
4131 	spdk_dif_get_range_with_md(10240, 2048, &buf_offset, &buf_len, &ctx);
4132 	CU_ASSERT(buf_offset == 10240 + 256);
4133 	CU_ASSERT(buf_len == 2048 + 128);
4134 
4135 	buf_len = spdk_dif_get_length_with_md(6144, &ctx);
4136 	CU_ASSERT(buf_len == 6144 + 128);
4137 }
4138 
4139 static void
4140 dif_generate_remap_and_verify(struct iovec *iovs, int iovcnt,
4141 			      uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
4142 			      bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
4143 			      uint32_t init_ref_tag, uint32_t remapped_init_ref_tag,
4144 			      uint16_t apptag_mask, uint16_t app_tag,
4145 			      enum spdk_dif_pi_format dif_pi_format)
4146 {
4147 	struct spdk_dif_ctx ctx = {};
4148 	int rc;
4149 	struct spdk_dif_ctx_init_ext_opts dif_opts;
4150 
4151 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
4152 	CU_ASSERT(rc == 0);
4153 
4154 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
4155 	dif_opts.dif_pi_format = dif_pi_format;
4156 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
4157 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED, &dif_opts);
4158 	CU_ASSERT(rc == 0);
4159 
4160 	rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
4161 	CU_ASSERT(rc == 0);
4162 
4163 	spdk_dif_ctx_set_remapped_init_ref_tag(&ctx, remapped_init_ref_tag);
4164 
4165 	rc = spdk_dif_remap_ref_tag(iovs, iovcnt, num_blocks, &ctx, NULL, true);
4166 	CU_ASSERT(rc == 0);
4167 
4168 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags,
4169 			       remapped_init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED, &dif_opts);
4170 	CU_ASSERT(rc == 0);
4171 
4172 	rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL);
4173 	CU_ASSERT(rc == 0);
4174 
4175 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
4176 	CU_ASSERT(rc == 0);
4177 }
4178 
4179 static void
4180 dif_sec_512_md_8_prchk_7_multi_iovs_remap_pi_16_test(void)
4181 {
4182 	struct iovec iovs[4];
4183 	int i, num_blocks;
4184 	uint32_t dif_flags;
4185 
4186 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
4187 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
4188 
4189 	num_blocks = 0;
4190 
4191 	for (i = 0; i < 4; i++) {
4192 		_iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1));
4193 		num_blocks += i + 1;
4194 	}
4195 
4196 	dif_generate_remap_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
4197 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
4198 
4199 	dif_generate_remap_and_verify(iovs, 4, 512 + 8, 8, num_blocks, true, SPDK_DIF_TYPE1,
4200 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
4201 
4202 	for (i = 0; i < 4; i++) {
4203 		_iov_free_buf(&iovs[i]);
4204 	}
4205 }
4206 
4207 static void
4208 dif_sec_4096_md_128_prchk_7_multi_iovs_remap_test(void)
4209 {
4210 	struct iovec iovs[4];
4211 	int i, num_blocks;
4212 	uint32_t dif_flags;
4213 
4214 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
4215 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
4216 
4217 	num_blocks = 0;
4218 
4219 	for (i = 0; i < 4; i++) {
4220 		_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
4221 		num_blocks += i + 1;
4222 	}
4223 
4224 	dif_generate_remap_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
4225 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
4226 	dif_generate_remap_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1,
4227 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
4228 	dif_generate_remap_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
4229 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
4230 	dif_generate_remap_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1,
4231 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
4232 
4233 	for (i = 0; i < 4; i++) {
4234 		_iov_free_buf(&iovs[i]);
4235 	}
4236 }
4237 
4238 static void
4239 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test(void)
4240 {
4241 	struct iovec iovs[11];
4242 	uint32_t dif_flags;
4243 	int i;
4244 
4245 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
4246 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
4247 
4248 	/* data[0][1000:0] */
4249 	_iov_alloc_buf(&iovs[0], 1000);
4250 
4251 	/* data[0][3095:1000], guard[0][0] */
4252 	_iov_alloc_buf(&iovs[1], 3096 + 1);
4253 
4254 	/* guard[0][1], apptag[0][0] */
4255 	_iov_alloc_buf(&iovs[2], 1 + 1);
4256 
4257 	/* apptag[0][1], reftag[0][0] */
4258 	_iov_alloc_buf(&iovs[3], 1 + 1);
4259 
4260 	/* reftag[0][3:1], ignore[0][59:0] */
4261 	_iov_alloc_buf(&iovs[4], 3 + 60);
4262 
4263 	/* ignore[119:60], data[1][3050:0] */
4264 	_iov_alloc_buf(&iovs[5], 60 + 3051);
4265 
4266 	/* data[1][4095:3050], guard[1][0] */
4267 	_iov_alloc_buf(&iovs[6], 1045 + 1);
4268 
4269 	/* guard[1][1], apptag[1][0] */
4270 	_iov_alloc_buf(&iovs[7], 1 + 1);
4271 
4272 	/* apptag[1][1], reftag[1][0] */
4273 	_iov_alloc_buf(&iovs[8], 1 + 1);
4274 
4275 	/* reftag[1][3:1], ignore[1][9:0] */
4276 	_iov_alloc_buf(&iovs[9], 3 + 10);
4277 
4278 	/* ignore[1][127:9] */
4279 	_iov_alloc_buf(&iovs[10], 118);
4280 
4281 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
4282 				      22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
4283 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
4284 				      22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
4285 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
4286 				      22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
4287 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
4288 				      22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
4289 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
4290 				      22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
4291 	dif_generate_remap_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
4292 				      22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
4293 
4294 	for (i = 0; i < 11; i++) {
4295 		_iov_free_buf(&iovs[i]);
4296 	}
4297 }
4298 
4299 static void
4300 dix_generate_remap_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
4301 			      uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
4302 			      bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags,
4303 			      uint32_t init_ref_tag, uint32_t remapped_init_ref_tag,
4304 			      uint16_t apptag_mask, uint16_t app_tag,
4305 			      enum spdk_dif_pi_format dif_pi_format)
4306 {
4307 	struct spdk_dif_ctx ctx;
4308 	int rc;
4309 	struct spdk_dif_ctx_init_ext_opts dif_opts;
4310 
4311 	rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
4312 	CU_ASSERT(rc == 0);
4313 
4314 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
4315 	dif_opts.dif_pi_format = dif_pi_format;
4316 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
4317 			       init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED, &dif_opts);
4318 	CU_ASSERT(rc == 0);
4319 
4320 	rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
4321 	CU_ASSERT(rc == 0);
4322 
4323 	spdk_dif_ctx_set_remapped_init_ref_tag(&ctx, remapped_init_ref_tag);
4324 
4325 	rc = spdk_dix_remap_ref_tag(md_iov, num_blocks, &ctx, NULL, true);
4326 	CU_ASSERT(rc == 0);
4327 
4328 	rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags,
4329 			       remapped_init_ref_tag, apptag_mask, app_tag, 0, GUARD_SEED, &dif_opts);
4330 	CU_ASSERT(rc == 0);
4331 
4332 	rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL);
4333 	CU_ASSERT(rc == 0);
4334 
4335 	rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks);
4336 	CU_ASSERT(rc == 0);
4337 }
4338 
4339 static void
4340 dix_sec_4096_md_128_prchk_7_multi_iovs_remap(void)
4341 {
4342 	struct iovec iovs[4], md_iov;
4343 	uint32_t dif_flags;
4344 	int i, num_blocks;
4345 
4346 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
4347 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
4348 
4349 	num_blocks = 0;
4350 
4351 	for (i = 0; i < 4; i++) {
4352 		_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
4353 		num_blocks += i + 1;
4354 	}
4355 	_iov_alloc_buf(&md_iov, 128 * num_blocks);
4356 
4357 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
4358 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
4359 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
4360 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
4361 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
4362 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
4363 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
4364 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
4365 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
4366 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
4367 	dix_generate_remap_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
4368 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
4369 
4370 	for (i = 0; i < 4; i++) {
4371 		_iov_free_buf(&iovs[i]);
4372 	}
4373 	_iov_free_buf(&md_iov);
4374 }
4375 
4376 static void
4377 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits_remap_pi_16_test(void)
4378 {
4379 	struct iovec iovs[6], md_iov;
4380 	uint32_t dif_flags;
4381 	int i;
4382 
4383 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
4384 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
4385 
4386 	/* data[0][255:0] */
4387 	_iov_alloc_buf(&iovs[0], 256);
4388 
4389 	/* data[0][511:256], data[1][255:0] */
4390 	_iov_alloc_buf(&iovs[1], 256 + 256);
4391 
4392 	/* data[1][382:256] */
4393 	_iov_alloc_buf(&iovs[2], 128);
4394 
4395 	/* data[1][383] */
4396 	_iov_alloc_buf(&iovs[3], 1);
4397 
4398 	/* data[1][510:384] */
4399 	_iov_alloc_buf(&iovs[4], 126);
4400 
4401 	/* data[1][511], data[2][511:0], data[3][511:0] */
4402 	_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
4403 
4404 	_iov_alloc_buf(&md_iov, 8 * 4);
4405 
4406 	dix_generate_remap_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1,
4407 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_16);
4408 
4409 	for (i = 0; i < 6; i++) {
4410 		_iov_free_buf(&iovs[i]);
4411 	}
4412 	_iov_free_buf(&md_iov);
4413 }
4414 
4415 static void
4416 dix_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test(void)
4417 {
4418 	struct iovec iovs[6], md_iov;
4419 	uint32_t dif_flags;
4420 	int i;
4421 
4422 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK |
4423 		    SPDK_DIF_FLAGS_REFTAG_CHECK;
4424 
4425 	/* data[0][2047:0] */
4426 	_iov_alloc_buf(&iovs[0], 2048);
4427 
4428 	/* data[0][4095:2048], data[1][2047:0] */
4429 	_iov_alloc_buf(&iovs[1], 2048 + 2048);
4430 
4431 	/* data[1][3071:2048] */
4432 	_iov_alloc_buf(&iovs[2], 1024);
4433 
4434 	/* data[1][3072] */
4435 	_iov_alloc_buf(&iovs[3], 1);
4436 
4437 	/* data[1][4094:3073] */
4438 	_iov_alloc_buf(&iovs[4], 1022);
4439 
4440 	/* data[1][4095], data[2][4095:0], data[3][4095:0] */
4441 	_iov_alloc_buf(&iovs[5], 1 + 4096 * 2);
4442 
4443 	_iov_alloc_buf(&md_iov, 128 * 4);
4444 
4445 	dix_generate_remap_and_verify(iovs, 6, &md_iov, 4096, 128, 4, false, SPDK_DIF_TYPE1,
4446 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_32);
4447 	dix_generate_remap_and_verify(iovs, 6, &md_iov, 4096, 128, 4, false, SPDK_DIF_TYPE1,
4448 				      dif_flags, 22, 99, 0xFFFF, 0x22, SPDK_DIF_PI_FORMAT_64);
4449 
4450 	for (i = 0; i < 6; i++) {
4451 		_iov_free_buf(&iovs[i]);
4452 	}
4453 	_iov_free_buf(&md_iov);
4454 }
4455 
4456 static void
4457 dif_generate_and_verify_unmap_test(void)
4458 {
4459 	struct iovec iov;
4460 	struct spdk_dif_ctx ctx = {};
4461 	int rc;
4462 	struct spdk_dif_ctx_init_ext_opts dif_opts;
4463 	uint32_t dif_flags;
4464 	struct spdk_dif *dif;
4465 
4466 	_iov_alloc_buf(&iov, 4096 + 128);
4467 
4468 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
4469 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
4470 	dif = (struct spdk_dif *)(iov.iov_base + 4096);
4471 
4472 	/* Case 1 for TYPE1 */
4473 	memset(iov.iov_base, 0, 4096 + 128);
4474 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK;
4475 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, true, SPDK_DIF_TYPE1, dif_flags,
4476 			       0x100, 0xFFFF, SPDK_DIF_APPTAG_IGNORE, 0, 0, &dif_opts);
4477 	CU_ASSERT(rc == 0);
4478 
4479 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
4480 	CU_ASSERT(rc == 0);
4481 
4482 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, NULL);
4483 	CU_ASSERT(rc == 0);
4484 
4485 	CU_ASSERT(_dif_get_apptag(dif, ctx.dif_pi_format) == SPDK_DIF_APPTAG_IGNORE);
4486 	CU_ASSERT(_dif_get_reftag(dif, ctx.dif_pi_format) == 0x100);
4487 
4488 	/* Case 2 for TYPE3 */
4489 	memset(iov.iov_base, 0, 4096 + 128);
4490 
4491 	dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK;
4492 	rc = spdk_dif_ctx_init(&ctx, 4096 + 128, 128, true, true, SPDK_DIF_TYPE3, dif_flags,
4493 			       SPDK_DIF_REFTAG_IGNORE, 0xFFFF, SPDK_DIF_APPTAG_IGNORE, 0, 0, &dif_opts);
4494 	CU_ASSERT(rc == 0);
4495 
4496 	rc = spdk_dif_generate(&iov, 1, 1, &ctx);
4497 	CU_ASSERT(rc == 0);
4498 
4499 	rc = spdk_dif_verify(&iov, 1, 1, &ctx, NULL);
4500 	CU_ASSERT(rc == 0);
4501 
4502 	CU_ASSERT(_dif_get_apptag(dif, ctx.dif_pi_format) == SPDK_DIF_APPTAG_IGNORE);
4503 	CU_ASSERT(_dif_get_reftag(dif, ctx.dif_pi_format) == REFTAG_MASK_16);
4504 
4505 	_iov_free_buf(&iov);
4506 }
4507 
4508 static void
4509 dif_pi_format_check_test(void)
4510 {
4511 	CU_ASSERT(_dif_pi_format_is_valid(SPDK_DIF_PI_FORMAT_16) == true);
4512 	CU_ASSERT(_dif_pi_format_is_valid(SPDK_DIF_PI_FORMAT_32) == true);
4513 	CU_ASSERT(_dif_pi_format_is_valid(SPDK_DIF_PI_FORMAT_64) == true);
4514 	CU_ASSERT(_dif_pi_format_is_valid(SPDK_DIF_PI_FORMAT_64 + 1) == false);
4515 }
4516 
4517 static void
4518 dif_type_check_test(void)
4519 {
4520 	CU_ASSERT(_dif_type_is_valid(SPDK_DIF_DISABLE) == true);
4521 	CU_ASSERT(_dif_type_is_valid(SPDK_DIF_TYPE1) == true);
4522 	CU_ASSERT(_dif_type_is_valid(SPDK_DIF_TYPE2) == true);
4523 	CU_ASSERT(_dif_type_is_valid(SPDK_DIF_TYPE3) == true);
4524 	CU_ASSERT(_dif_type_is_valid(SPDK_DIF_TYPE3 + 1) == false);
4525 }
4526 
4527 int
4528 main(int argc, char **argv)
4529 {
4530 	CU_pSuite	suite = NULL;
4531 	unsigned int	num_failures;
4532 
4533 	CU_initialize_registry();
4534 
4535 	suite = CU_add_suite("dif", NULL, NULL);
4536 
4537 	CU_ADD_TEST(suite, dif_generate_and_verify_test);
4538 	CU_ADD_TEST(suite, dif_disable_check_test);
4539 	CU_ADD_TEST(suite, dif_generate_and_verify_different_pi_formats_test);
4540 	CU_ADD_TEST(suite, dif_apptag_mask_test);
4541 	CU_ADD_TEST(suite, dif_sec_8_md_8_error_test);
4542 	CU_ADD_TEST(suite, dif_sec_512_md_0_error_test);
4543 	CU_ADD_TEST(suite, dif_sec_512_md_16_error_test);
4544 	CU_ADD_TEST(suite, dif_sec_4096_md_0_8_error_test);
4545 	CU_ADD_TEST(suite, dif_sec_4100_md_128_error_test);
4546 	CU_ADD_TEST(suite, dif_guard_seed_test);
4547 	CU_ADD_TEST(suite, dif_guard_value_test);
4548 	CU_ADD_TEST(suite, dif_disable_sec_512_md_8_single_iov_test);
4549 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_0_single_iov_test);
4550 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_0_single_iov_test);
4551 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test);
4552 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test);
4553 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_test);
4554 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test);
4555 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_split_data_and_md_test);
4556 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test);
4557 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_split_data_test);
4558 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test);
4559 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_split_guard_test);
4560 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test);
4561 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_split_apptag_test);
4562 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test);
4563 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_split_reftag_test);
4564 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test);
4565 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test);
4566 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test);
4567 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test);
4568 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test);
4569 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test);
4570 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_pi_16_test);
4571 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test);
4572 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_pi_16_test);
4573 	CU_ADD_TEST(suite, dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test);
4574 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_0_single_iov);
4575 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_dif_disable_single_iov);
4576 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_0_single_iov_test);
4577 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs);
4578 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test);
4579 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test);
4580 	CU_ADD_TEST(suite, nvme_pract_sec_4096_md_128_prchk_0_1_2_4_multi_bounce_iovs_test);
4581 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_7_multi_iovs);
4582 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data);
4583 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_7_multi_iovs_split_data_test);
4584 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits);
4585 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_prchk_7_multi_bounce_iovs_complex_splits);
4586 	CU_ADD_TEST(suite, dif_copy_sec_512_md_8_dif_disable_multi_bounce_iovs_complex_splits);
4587 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test);
4588 	CU_ADD_TEST(suite, nvme_pract_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test);
4589 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test);
4590 	CU_ADD_TEST(suite, dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test);
4591 	CU_ADD_TEST(suite, dix_sec_0_md_8_error);
4592 	CU_ADD_TEST(suite, dix_sec_512_md_0_error);
4593 	CU_ADD_TEST(suite, dix_sec_512_md_16_error);
4594 	CU_ADD_TEST(suite, dix_sec_4096_md_0_8_error);
4595 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_0_single_iov);
4596 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_0_single_iov_test);
4597 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs);
4598 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_0_1_2_4_multi_iovs_test);
4599 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs);
4600 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_split_data);
4601 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs_split_data_test);
4602 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits);
4603 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test);
4604 	CU_ADD_TEST(suite, dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test);
4605 	CU_ADD_TEST(suite, dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test);
4606 	CU_ADD_TEST(suite, set_md_interleave_iovs_test);
4607 	CU_ADD_TEST(suite, set_md_interleave_iovs_split_test);
4608 	CU_ADD_TEST(suite, dif_generate_stream_pi_16_test);
4609 	CU_ADD_TEST(suite, dif_generate_stream_test);
4610 	CU_ADD_TEST(suite, set_md_interleave_iovs_alignment_test);
4611 	CU_ADD_TEST(suite, dif_generate_split_test);
4612 	CU_ADD_TEST(suite, set_md_interleave_iovs_multi_segments_test);
4613 	CU_ADD_TEST(suite, dif_verify_split_test);
4614 	CU_ADD_TEST(suite, dif_verify_stream_multi_segments_test);
4615 	CU_ADD_TEST(suite, update_crc32c_pi_16_test);
4616 	CU_ADD_TEST(suite, update_crc32c_test);
4617 	CU_ADD_TEST(suite, dif_update_crc32c_split_test);
4618 	CU_ADD_TEST(suite, dif_update_crc32c_stream_multi_segments_test);
4619 	CU_ADD_TEST(suite, get_range_with_md_test);
4620 	CU_ADD_TEST(suite, dif_sec_512_md_8_prchk_7_multi_iovs_remap_pi_16_test);
4621 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_remap_test);
4622 	CU_ADD_TEST(suite, dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test);
4623 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs_remap);
4624 	CU_ADD_TEST(suite, dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits_remap_pi_16_test);
4625 	CU_ADD_TEST(suite, dix_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_remap_test);
4626 	CU_ADD_TEST(suite, dif_generate_and_verify_unmap_test);
4627 	CU_ADD_TEST(suite, dif_pi_format_check_test);
4628 	CU_ADD_TEST(suite, dif_type_check_test);
4629 
4630 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
4631 
4632 	CU_cleanup_registry();
4633 
4634 	return num_failures;
4635 }
4636