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