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