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