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