1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk_cunit.h" 37 38 #include "util/dif.c" 39 40 #define DATA_PATTERN(offset) ((uint8_t)(0xAB + (offset))) 41 #define GUARD_SEED 0xCD 42 43 static int 44 ut_data_pattern_generate(struct iovec *iovs, int iovcnt, 45 uint32_t block_size, uint32_t md_size, uint32_t num_blocks) 46 { 47 struct _iov_iter iter; 48 uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i; 49 uint8_t *buf; 50 51 if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) { 52 return -1; 53 } 54 55 offset_blocks = 0; 56 _iov_iter_init(&iter, iovs, iovcnt); 57 data_offset = 0; 58 59 while (offset_blocks < num_blocks) { 60 offset_in_block = 0; 61 while (offset_in_block < block_size) { 62 _iov_iter_get_buf(&iter, (void *)&buf, &buf_len); 63 if (offset_in_block < block_size - md_size) { 64 buf_len = spdk_min(buf_len, 65 block_size - md_size - offset_in_block); 66 for (i = 0; i < buf_len; i++) { 67 buf[i] = DATA_PATTERN(data_offset + i); 68 } 69 data_offset += buf_len; 70 } else { 71 buf_len = spdk_min(buf_len, block_size - offset_in_block); 72 memset(buf, 0, buf_len); 73 } 74 _iov_iter_advance(&iter, buf_len); 75 offset_in_block += buf_len; 76 } 77 offset_blocks++; 78 } 79 80 return 0; 81 } 82 83 static int 84 ut_data_pattern_verify(struct iovec *iovs, int iovcnt, 85 uint32_t block_size, uint32_t md_size, uint32_t num_blocks) 86 { 87 struct _iov_iter iter; 88 uint32_t offset_blocks, offset_in_block, buf_len, data_offset, i; 89 uint8_t *buf; 90 91 if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) { 92 return -1; 93 } 94 95 offset_blocks = 0; 96 _iov_iter_init(&iter, iovs, iovcnt); 97 data_offset = 0; 98 99 while (offset_blocks < num_blocks) { 100 offset_in_block = 0; 101 while (offset_in_block < block_size) { 102 _iov_iter_get_buf(&iter, (void *)&buf, &buf_len); 103 104 if (offset_in_block < block_size - md_size) { 105 buf_len = spdk_min(buf_len, 106 block_size - md_size - offset_in_block); 107 for (i = 0; i < buf_len; i++) { 108 if (buf[i] != DATA_PATTERN(data_offset + i)) { 109 return -1; 110 } 111 } 112 data_offset += buf_len; 113 } else { 114 buf_len = spdk_min(buf_len, block_size - offset_in_block); 115 } 116 _iov_iter_advance(&iter, buf_len); 117 offset_in_block += buf_len; 118 } 119 offset_blocks++; 120 } 121 122 return 0; 123 } 124 125 static void 126 _iov_alloc_buf(struct iovec *iov, uint32_t len) 127 { 128 iov->iov_base = calloc(1, len); 129 iov->iov_len = len; 130 SPDK_CU_ASSERT_FATAL(iov->iov_base != NULL); 131 } 132 133 static void 134 _iov_free_buf(struct iovec *iov) 135 { 136 free(iov->iov_base); 137 } 138 139 static void 140 _dif_generate_and_verify(struct iovec *iov, 141 uint32_t block_size, uint32_t md_size, bool dif_loc, 142 enum spdk_dif_type dif_type, uint32_t dif_flags, 143 uint32_t ref_tag, uint32_t e_ref_tag, 144 uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag, 145 bool expect_pass) 146 { 147 struct spdk_dif_ctx ctx = {}; 148 uint32_t guard_interval; 149 uint16_t guard = 0; 150 int rc; 151 152 rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1); 153 CU_ASSERT(rc == 0); 154 155 guard_interval = _get_guard_interval(block_size, md_size, dif_loc, true); 156 157 ctx.dif_type = dif_type; 158 ctx.dif_flags = dif_flags; 159 ctx.init_ref_tag = ref_tag; 160 ctx.app_tag = app_tag; 161 162 if (dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { 163 guard = spdk_crc16_t10dif(0, iov->iov_base, guard_interval); 164 } 165 166 _dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx); 167 168 ctx.init_ref_tag = e_ref_tag; 169 ctx.apptag_mask = apptag_mask; 170 ctx.app_tag = e_app_tag; 171 172 rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx, NULL); 173 CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0)); 174 175 rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1); 176 CU_ASSERT(rc == 0); 177 } 178 179 static void 180 dif_generate_and_verify_test(void) 181 { 182 struct iovec iov; 183 uint32_t dif_flags; 184 185 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 186 SPDK_DIF_FLAGS_REFTAG_CHECK; 187 188 _iov_alloc_buf(&iov, 4096 + 128); 189 190 /* Positive cases */ 191 192 /* The case that DIF is contained in the first 8 bytes of metadata. */ 193 _dif_generate_and_verify(&iov, 194 4096 + 128, 128, true, 195 SPDK_DIF_TYPE1, dif_flags, 196 22, 22, 197 0x22, 0xFFFF, 0x22, 198 true); 199 200 /* The case that DIF is contained in the last 8 bytes of metadata. */ 201 _dif_generate_and_verify(&iov, 202 4096 + 128, 128, false, 203 SPDK_DIF_TYPE1, dif_flags, 204 22, 22, 205 0x22, 0xFFFF, 0x22, 206 true); 207 208 /* Negative cases */ 209 210 /* Reference tag doesn't match. */ 211 _dif_generate_and_verify(&iov, 212 4096 + 128, 128, false, 213 SPDK_DIF_TYPE1, dif_flags, 214 22, 23, 215 0x22, 0xFFFF, 0x22, 216 false); 217 218 /* Application tag doesn't match. */ 219 _dif_generate_and_verify(&iov, 220 4096 + 128, 128, false, 221 SPDK_DIF_TYPE1, dif_flags, 222 22, 22, 223 0x22, 0xFFFF, 0x23, 224 false); 225 226 _iov_free_buf(&iov); 227 } 228 229 static void 230 dif_disable_check_test(void) 231 { 232 struct iovec iov; 233 uint32_t dif_flags; 234 235 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 236 SPDK_DIF_FLAGS_REFTAG_CHECK; 237 238 _iov_alloc_buf(&iov, 4096 + 128); 239 240 /* The case that DIF check is disabled when the Application Tag is 0xFFFF for 241 * Type 1. DIF check is disabled and pass is expected. 242 */ 243 _dif_generate_and_verify(&iov, 244 4096 + 128, 128, false, 245 SPDK_DIF_TYPE1, dif_flags, 246 22, 22, 247 0xFFFF, 0xFFFF, 0x22, 248 true); 249 250 /* The case that DIF check is not disabled when the Application Tag is 0xFFFF but 251 * the Reference Tag is not 0xFFFFFFFF for Type 3. DIF check is not disabled and 252 * fail is expected. 253 */ 254 _dif_generate_and_verify(&iov, 255 4096 + 128, 128, false, 256 SPDK_DIF_TYPE3, dif_flags, 257 22, 22, 258 0xFFFF, 0xFFFF, 0x22, 259 false); 260 261 /* The case that DIF check is disabled when the Application Tag is 0xFFFF and 262 * the Reference Tag is 0xFFFFFFFF for Type 3. DIF check is disabled and 263 * pass is expected. 264 */ 265 _dif_generate_and_verify(&iov, 266 4096 + 128, 128, false, 267 SPDK_DIF_TYPE3, dif_flags, 268 0xFFFFFFFF, 22, 269 0xFFFF, 0xFFFF, 0x22, 270 true); 271 272 _iov_free_buf(&iov); 273 } 274 275 static void 276 dif_sec_512_md_0_error_test(void) 277 { 278 struct spdk_dif_ctx ctx = {}; 279 int rc; 280 281 /* Metadata size is 0. */ 282 rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0); 283 CU_ASSERT(rc != 0); 284 } 285 286 static void 287 dif_guard_seed_test(void) 288 { 289 struct iovec iov; 290 struct spdk_dif_ctx ctx = {}; 291 struct spdk_dif_error err_blk = {}; 292 struct spdk_dif *dif; 293 uint16_t guard; 294 int rc; 295 296 _iov_alloc_buf(&iov, 512 + 8); 297 298 memset(iov.iov_base, 0, 512 + 8); 299 300 dif = (struct spdk_dif *)(iov.iov_base + 512); 301 302 rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, 303 SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0); 304 CU_ASSERT(rc == 0); 305 306 rc = spdk_dif_generate(&iov, 1, 1, &ctx); 307 CU_ASSERT(rc == 0); 308 309 /* Guard should be zero if the block is all zero and seed is not added. */ 310 guard = from_be16(&dif->guard); 311 CU_ASSERT(guard == 0); 312 313 rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk); 314 CU_ASSERT(rc == 0); 315 316 rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, 317 SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, GUARD_SEED); 318 CU_ASSERT(rc == 0); 319 320 rc = spdk_dif_generate(&iov, 1, 1, &ctx); 321 CU_ASSERT(rc == 0); 322 323 /* Guard should not be zero if the block is all zero but seed is added. */ 324 guard = from_be16(&dif->guard); 325 CU_ASSERT(guard != 0); 326 327 rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk); 328 CU_ASSERT(rc == 0); 329 330 _iov_free_buf(&iov); 331 } 332 333 static void 334 dif_generate_and_verify(struct iovec *iovs, int iovcnt, 335 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 336 bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, 337 uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) 338 { 339 struct spdk_dif_ctx ctx = {}; 340 int rc; 341 342 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks); 343 CU_ASSERT(rc == 0); 344 345 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, 346 init_ref_tag, apptag_mask, app_tag, GUARD_SEED); 347 CU_ASSERT(rc == 0); 348 349 rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); 350 CU_ASSERT(rc == 0); 351 352 rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL); 353 CU_ASSERT(rc == 0); 354 355 rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks); 356 CU_ASSERT(rc == 0); 357 } 358 359 static void 360 dif_disable_sec_512_md_8_single_iov_test(void) 361 { 362 struct iovec iov; 363 364 _iov_alloc_buf(&iov, 512 + 8); 365 366 dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_DISABLE, 0, 0, 0, 0); 367 368 _iov_free_buf(&iov); 369 } 370 371 static void 372 dif_sec_512_md_8_prchk_0_single_iov_test(void) 373 { 374 struct iovec iov; 375 376 _iov_alloc_buf(&iov, 512 + 8); 377 378 dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 379 380 _iov_free_buf(&iov); 381 } 382 383 static void 384 dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test(void) 385 { 386 struct iovec iovs[4]; 387 int i, num_blocks; 388 389 num_blocks = 0; 390 391 for (i = 0; i < 4; i++) { 392 _iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1)); 393 num_blocks += i + 1; 394 } 395 396 dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, 397 0, 22, 0xFFFF, 0x22); 398 399 dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, 400 SPDK_DIF_FLAGS_GUARD_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_APPTAG_CHECK, 22, 0xFFFF, 0x22); 404 405 dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, 406 SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22); 407 408 for (i = 0; i < 4; i++) { 409 _iov_free_buf(&iovs[i]); 410 } 411 } 412 413 static void 414 dif_sec_4096_md_128_prchk_7_multi_iovs_test(void) 415 { 416 struct iovec iovs[4]; 417 int i, num_blocks; 418 uint32_t dif_flags; 419 420 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 421 SPDK_DIF_FLAGS_REFTAG_CHECK; 422 423 num_blocks = 0; 424 425 for (i = 0; i < 4; i++) { 426 _iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1)); 427 num_blocks += i + 1; 428 } 429 430 dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1, 431 dif_flags, 22, 0xFFFF, 0x22); 432 433 dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1, 434 dif_flags, 22, 0xFFFF, 0x22); 435 436 for (i = 0; i < 4; i++) { 437 _iov_free_buf(&iovs[i]); 438 } 439 } 440 441 static void 442 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test(void) 443 { 444 struct iovec iovs[2]; 445 uint32_t dif_flags; 446 447 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 448 SPDK_DIF_FLAGS_REFTAG_CHECK; 449 450 _iov_alloc_buf(&iovs[0], 512); 451 _iov_alloc_buf(&iovs[1], 8); 452 453 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 454 dif_flags, 22, 0xFFFF, 0x22); 455 456 _iov_free_buf(&iovs[0]); 457 _iov_free_buf(&iovs[1]); 458 } 459 460 static void 461 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test(void) 462 { 463 struct iovec iovs[2]; 464 uint32_t dif_flags; 465 466 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 467 SPDK_DIF_FLAGS_REFTAG_CHECK; 468 469 _iov_alloc_buf(&iovs[0], 256); 470 _iov_alloc_buf(&iovs[1], 264); 471 472 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 473 dif_flags, 22, 0xFFFF, 0x22); 474 475 _iov_free_buf(&iovs[0]); 476 _iov_free_buf(&iovs[1]); 477 } 478 479 static void 480 dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test(void) 481 { 482 struct iovec iovs[2]; 483 uint32_t dif_flags; 484 485 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 486 SPDK_DIF_FLAGS_REFTAG_CHECK; 487 488 _iov_alloc_buf(&iovs[0], 513); 489 _iov_alloc_buf(&iovs[1], 7); 490 491 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 492 dif_flags, 22, 0xFFFF, 0x22); 493 494 _iov_free_buf(&iovs[0]); 495 _iov_free_buf(&iovs[1]); 496 } 497 498 static void 499 dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test(void) 500 { 501 struct iovec iovs[2]; 502 uint32_t dif_flags; 503 504 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 505 SPDK_DIF_FLAGS_REFTAG_CHECK; 506 507 _iov_alloc_buf(&iovs[0], 515); 508 _iov_alloc_buf(&iovs[1], 5); 509 510 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 511 dif_flags, 22, 0xFFFF, 0x22); 512 513 _iov_free_buf(&iovs[0]); 514 _iov_free_buf(&iovs[1]); 515 } 516 517 static void 518 dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test(void) 519 { 520 struct iovec iovs[2]; 521 uint32_t dif_flags; 522 523 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 524 SPDK_DIF_FLAGS_REFTAG_CHECK; 525 526 _iov_alloc_buf(&iovs[0], 518); 527 _iov_alloc_buf(&iovs[1], 2); 528 529 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 530 dif_flags, 22, 0xFFFF, 0x22); 531 532 _iov_free_buf(&iovs[0]); 533 _iov_free_buf(&iovs[1]); 534 } 535 536 static void 537 dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test(void) 538 { 539 struct iovec iovs[9]; 540 uint32_t dif_flags; 541 int i; 542 543 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 544 SPDK_DIF_FLAGS_REFTAG_CHECK; 545 546 /* data[0][255:0] */ 547 _iov_alloc_buf(&iovs[0], 256); 548 549 /* data[0][511:256], guard[0][0] */ 550 _iov_alloc_buf(&iovs[1], 256 + 1); 551 552 /* guard[0][1], apptag[0][0] */ 553 _iov_alloc_buf(&iovs[2], 1 + 1); 554 555 /* apptag[0][1], reftag[0][0] */ 556 _iov_alloc_buf(&iovs[3], 1 + 1); 557 558 /* reftag[0][3:1], data[1][255:0] */ 559 _iov_alloc_buf(&iovs[4], 3 + 256); 560 561 /* data[1][511:256], guard[1][0] */ 562 _iov_alloc_buf(&iovs[5], 256 + 1); 563 564 /* guard[1][1], apptag[1][0] */ 565 _iov_alloc_buf(&iovs[6], 1 + 1); 566 567 /* apptag[1][1], reftag[1][0] */ 568 _iov_alloc_buf(&iovs[7], 1 + 1); 569 570 /* reftag[1][3:1] */ 571 _iov_alloc_buf(&iovs[8], 3); 572 573 dif_generate_and_verify(iovs, 9, 512 + 8, 8, 2, false, SPDK_DIF_TYPE1, dif_flags, 574 22, 0xFFFF, 0x22); 575 576 for (i = 0; i < 9; i++) { 577 _iov_free_buf(&iovs[i]); 578 } 579 } 580 581 static void 582 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void) 583 { 584 struct iovec iovs[11]; 585 uint32_t dif_flags; 586 int i; 587 588 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 589 SPDK_DIF_FLAGS_REFTAG_CHECK; 590 591 /* data[0][1000:0] */ 592 _iov_alloc_buf(&iovs[0], 1000); 593 594 /* data[0][3095:1000], guard[0][0] */ 595 _iov_alloc_buf(&iovs[1], 3096 + 1); 596 597 /* guard[0][1], apptag[0][0] */ 598 _iov_alloc_buf(&iovs[2], 1 + 1); 599 600 /* apptag[0][1], reftag[0][0] */ 601 _iov_alloc_buf(&iovs[3], 1 + 1); 602 603 /* reftag[0][3:1], ignore[0][59:0] */ 604 _iov_alloc_buf(&iovs[4], 3 + 60); 605 606 /* ignore[119:60], data[1][3050:0] */ 607 _iov_alloc_buf(&iovs[5], 60 + 3051); 608 609 /* data[1][4095:3050], guard[1][0] */ 610 _iov_alloc_buf(&iovs[6], 1045 + 1); 611 612 /* guard[1][1], apptag[1][0] */ 613 _iov_alloc_buf(&iovs[7], 1 + 1); 614 615 /* apptag[1][1], reftag[1][0] */ 616 _iov_alloc_buf(&iovs[8], 1 + 1); 617 618 /* reftag[1][3:1], ignore[1][9:0] */ 619 _iov_alloc_buf(&iovs[9], 3 + 10); 620 621 /* ignore[1][127:9] */ 622 _iov_alloc_buf(&iovs[10], 118); 623 624 dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags, 625 22, 0xFFFF, 0x22); 626 dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags, 627 22, 0xFFFF, 0x22); 628 629 for (i = 0; i < 11; i++) { 630 _iov_free_buf(&iovs[i]); 631 } 632 } 633 634 static void 635 _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt, 636 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 637 uint32_t inject_flags, bool dif_loc) 638 { 639 struct spdk_dif_ctx ctx = {}; 640 struct spdk_dif_error err_blk = {}; 641 uint32_t inject_offset = 0, dif_flags; 642 int rc; 643 644 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 645 SPDK_DIF_FLAGS_REFTAG_CHECK; 646 647 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks); 648 CU_ASSERT(rc == 0); 649 650 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, 651 SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88, GUARD_SEED); 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 805 rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks); 806 CU_ASSERT(rc == 0); 807 808 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, 809 init_ref_tag, apptag_mask, app_tag, GUARD_SEED); 810 CU_ASSERT(rc == 0); 811 812 rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); 813 CU_ASSERT(rc == 0); 814 815 rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL); 816 CU_ASSERT(rc == 0); 817 818 rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks); 819 CU_ASSERT(rc == 0); 820 } 821 822 static void 823 dif_copy_sec_512_md_8_prchk_0_single_iov(void) 824 { 825 struct iovec iov, bounce_iov; 826 827 _iov_alloc_buf(&iov, 512 * 4); 828 _iov_alloc_buf(&bounce_iov, (512 + 8) * 4); 829 830 dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4, 831 false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 832 dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4, 833 true, SPDK_DIF_TYPE1, 0, 0, 0, 0); 834 835 _iov_free_buf(&iov); 836 _iov_free_buf(&bounce_iov); 837 } 838 839 static void 840 dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void) 841 { 842 struct iovec iovs[4], bounce_iov; 843 int i, num_blocks; 844 845 num_blocks = 0; 846 847 for (i = 0; i < 4; i++) { 848 _iov_alloc_buf(&iovs[i], 512 * (i + 1)); 849 num_blocks += i + 1; 850 } 851 852 _iov_alloc_buf(&bounce_iov, (512 + 8) * num_blocks); 853 854 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, 855 false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22); 856 857 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, 858 false, SPDK_DIF_TYPE1, SPDK_DIF_FLAGS_GUARD_CHECK, 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_APPTAG_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_REFTAG_CHECK, 22, 0xFFFF, 0x22); 865 866 for (i = 0; i < 4; i++) { 867 _iov_free_buf(&iovs[i]); 868 } 869 _iov_free_buf(&bounce_iov); 870 } 871 872 static void 873 dif_copy_sec_4096_md_128_prchk_7_multi_iovs(void) 874 { 875 struct iovec iovs[4], bounce_iov; 876 uint32_t dif_flags; 877 int i, num_blocks; 878 879 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 880 SPDK_DIF_FLAGS_REFTAG_CHECK; 881 882 num_blocks = 0; 883 884 for (i = 0; i < 4; i++) { 885 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 886 num_blocks += i + 1; 887 } 888 889 _iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks); 890 891 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks, 892 false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 893 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks, 894 true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 895 896 for (i = 0; i < 4; i++) { 897 _iov_free_buf(&iovs[i]); 898 } 899 _iov_free_buf(&bounce_iov); 900 } 901 902 static void 903 dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data(void) 904 { 905 struct iovec iovs[2], bounce_iov; 906 uint32_t dif_flags; 907 908 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 909 SPDK_DIF_FLAGS_REFTAG_CHECK; 910 911 _iov_alloc_buf(&iovs[0], 256); 912 _iov_alloc_buf(&iovs[1], 256); 913 914 _iov_alloc_buf(&bounce_iov, 512 + 8); 915 916 dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 512 + 8, 8, 1, 917 false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 918 919 _iov_free_buf(&iovs[0]); 920 _iov_free_buf(&iovs[1]); 921 _iov_free_buf(&bounce_iov); 922 } 923 924 static void 925 dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void) 926 { 927 struct iovec iovs[6], bounce_iov; 928 uint32_t dif_flags; 929 int i; 930 931 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 932 SPDK_DIF_FLAGS_REFTAG_CHECK; 933 934 /* data[0][255:0] */ 935 _iov_alloc_buf(&iovs[0], 256); 936 937 /* data[0][511:256], data[1][255:0] */ 938 _iov_alloc_buf(&iovs[1], 256 + 256); 939 940 /* data[1][382:256] */ 941 _iov_alloc_buf(&iovs[2], 128); 942 943 /* data[1][383] */ 944 _iov_alloc_buf(&iovs[3], 1); 945 946 /* data[1][510:384] */ 947 _iov_alloc_buf(&iovs[4], 126); 948 949 /* data[1][511], data[2][511:0], data[3][511:0] */ 950 _iov_alloc_buf(&iovs[5], 1 + 512 * 2); 951 952 _iov_alloc_buf(&bounce_iov, (512 + 8) * 4); 953 954 dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 512 + 8, 8, 4, 955 true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 956 957 for (i = 0; i < 6; i++) { 958 _iov_free_buf(&iovs[i]); 959 } 960 _iov_free_buf(&bounce_iov); 961 } 962 963 static void 964 _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, 965 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 966 uint32_t inject_flags, bool dif_loc) 967 { 968 struct spdk_dif_ctx ctx = {}; 969 struct spdk_dif_error err_blk = {}; 970 uint32_t inject_offset = 0, dif_flags; 971 int rc; 972 973 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 974 SPDK_DIF_FLAGS_REFTAG_CHECK; 975 976 rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks); 977 CU_ASSERT(rc == 0); 978 979 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags, 980 88, 0xFFFF, 0x88, GUARD_SEED); 981 SPDK_CU_ASSERT_FATAL(rc == 0); 982 983 rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); 984 CU_ASSERT(rc == 0); 985 986 rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset); 987 CU_ASSERT(rc == 0); 988 989 rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, &err_blk); 990 CU_ASSERT(rc != 0); 991 if (inject_flags == SPDK_DIF_DATA_ERROR) { 992 CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); 993 } else { 994 CU_ASSERT(inject_flags == err_blk.err_type); 995 } 996 CU_ASSERT(inject_offset == err_blk.err_offset); 997 } 998 999 static void 1000 dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, 1001 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 1002 uint32_t inject_flags) 1003 { 1004 /* The case that DIF is contained in the first 8 bytes of metadata. */ 1005 _dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov, 1006 block_size, md_size, num_blocks, 1007 inject_flags, true); 1008 1009 /* The case that DIF is contained in the last 8 bytes of metadata. */ 1010 _dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov, 1011 block_size, md_size, num_blocks, 1012 inject_flags, false); 1013 } 1014 1015 static void 1016 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) 1017 { 1018 struct iovec iovs[4], bounce_iov; 1019 int i, num_blocks; 1020 1021 num_blocks = 0; 1022 1023 for (i = 0; i < 4; i++) { 1024 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 1025 num_blocks += i + 1; 1026 } 1027 1028 _iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks); 1029 1030 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1031 num_blocks, SPDK_DIF_GUARD_ERROR); 1032 1033 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1034 num_blocks, SPDK_DIF_APPTAG_ERROR); 1035 1036 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1037 num_blocks, SPDK_DIF_REFTAG_ERROR); 1038 1039 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1040 num_blocks, SPDK_DIF_DATA_ERROR); 1041 1042 for (i = 0; i < 4; i++) { 1043 _iov_free_buf(&iovs[i]); 1044 } 1045 _iov_free_buf(&bounce_iov); 1046 } 1047 1048 static void 1049 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void) 1050 { 1051 struct iovec iovs[4], bounce_iov; 1052 int i; 1053 1054 _iov_alloc_buf(&iovs[0], 2048); 1055 _iov_alloc_buf(&iovs[1], 2048); 1056 _iov_alloc_buf(&iovs[2], 1); 1057 _iov_alloc_buf(&iovs[3], 4095); 1058 1059 _iov_alloc_buf(&bounce_iov, (4096 + 128) * 2); 1060 1061 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1062 2, SPDK_DIF_GUARD_ERROR); 1063 1064 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1065 2, SPDK_DIF_APPTAG_ERROR); 1066 1067 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1068 2, SPDK_DIF_REFTAG_ERROR); 1069 1070 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1071 2, SPDK_DIF_DATA_ERROR); 1072 1073 for (i = 0; i < 4; i++) { 1074 _iov_free_buf(&iovs[i]); 1075 } 1076 _iov_free_buf(&bounce_iov); 1077 } 1078 1079 static void 1080 dix_sec_512_md_0_error(void) 1081 { 1082 struct spdk_dif_ctx ctx; 1083 int rc; 1084 1085 rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0); 1086 CU_ASSERT(rc != 0); 1087 } 1088 1089 static void 1090 dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, 1091 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 1092 bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, 1093 uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) 1094 { 1095 struct spdk_dif_ctx ctx; 1096 int rc; 1097 1098 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks); 1099 CU_ASSERT(rc == 0); 1100 1101 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags, 1102 init_ref_tag, apptag_mask, app_tag, GUARD_SEED); 1103 CU_ASSERT(rc == 0); 1104 1105 rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); 1106 CU_ASSERT(rc == 0); 1107 1108 rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL); 1109 CU_ASSERT(rc == 0); 1110 1111 rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks); 1112 CU_ASSERT(rc == 0); 1113 } 1114 1115 static void 1116 dix_sec_512_md_8_prchk_0_single_iov(void) 1117 { 1118 struct iovec iov, md_iov; 1119 1120 _iov_alloc_buf(&iov, 512 * 4); 1121 _iov_alloc_buf(&md_iov, 8 * 4); 1122 1123 dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 1124 dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0); 1125 1126 _iov_free_buf(&iov); 1127 _iov_free_buf(&md_iov); 1128 } 1129 1130 static void 1131 dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void) 1132 { 1133 struct iovec iovs[4], md_iov; 1134 int i, num_blocks; 1135 1136 num_blocks = 0; 1137 1138 for (i = 0; i < 4; i++) { 1139 _iov_alloc_buf(&iovs[i], 512 * (i + 1)); 1140 num_blocks += i + 1; 1141 } 1142 _iov_alloc_buf(&md_iov, 8 * num_blocks); 1143 1144 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1145 0, 22, 0xFFFF, 0x22); 1146 1147 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1148 SPDK_DIF_FLAGS_GUARD_CHECK, 22, 0xFFFF, 0x22); 1149 1150 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1151 SPDK_DIF_FLAGS_APPTAG_CHECK, 22, 0xFFFF, 0x22); 1152 1153 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1154 SPDK_DIF_FLAGS_REFTAG_CHECK, 22, 0xFFFF, 0x22); 1155 1156 for (i = 0; i < 4; i++) { 1157 _iov_free_buf(&iovs[i]); 1158 } 1159 _iov_free_buf(&md_iov); 1160 } 1161 1162 static void 1163 dix_sec_4096_md_128_prchk_7_multi_iovs(void) 1164 { 1165 struct iovec iovs[4], md_iov; 1166 uint32_t dif_flags; 1167 int i, num_blocks; 1168 1169 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 1170 SPDK_DIF_FLAGS_REFTAG_CHECK; 1171 1172 num_blocks = 0; 1173 1174 for (i = 0; i < 4; i++) { 1175 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 1176 num_blocks += i + 1; 1177 } 1178 _iov_alloc_buf(&md_iov, 128 * num_blocks); 1179 1180 dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1, 1181 dif_flags, 22, 0xFFFF, 0x22); 1182 dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1, 1183 dif_flags, 22, 0xFFFF, 0x22); 1184 1185 for (i = 0; i < 4; i++) { 1186 _iov_free_buf(&iovs[i]); 1187 } 1188 _iov_free_buf(&md_iov); 1189 } 1190 1191 static void 1192 dix_sec_512_md_8_prchk_7_multi_iovs_split_data(void) 1193 { 1194 struct iovec iovs[2], md_iov; 1195 uint32_t dif_flags; 1196 1197 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 1198 SPDK_DIF_FLAGS_REFTAG_CHECK; 1199 1200 _iov_alloc_buf(&iovs[0], 256); 1201 _iov_alloc_buf(&iovs[1], 256); 1202 _iov_alloc_buf(&md_iov, 8); 1203 1204 dix_generate_and_verify(iovs, 2, &md_iov, 512, 8, 1, false, SPDK_DIF_TYPE1, 1205 dif_flags, 22, 0xFFFF, 0x22); 1206 1207 _iov_free_buf(&iovs[0]); 1208 _iov_free_buf(&iovs[1]); 1209 _iov_free_buf(&md_iov); 1210 } 1211 1212 static void 1213 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void) 1214 { 1215 struct iovec iovs[6], md_iov; 1216 uint32_t dif_flags; 1217 int i; 1218 1219 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 1220 SPDK_DIF_FLAGS_REFTAG_CHECK; 1221 1222 /* data[0][255:0] */ 1223 _iov_alloc_buf(&iovs[0], 256); 1224 1225 /* data[0][511:256], data[1][255:0] */ 1226 _iov_alloc_buf(&iovs[1], 256 + 256); 1227 1228 /* data[1][382:256] */ 1229 _iov_alloc_buf(&iovs[2], 128); 1230 1231 /* data[1][383] */ 1232 _iov_alloc_buf(&iovs[3], 1); 1233 1234 /* data[1][510:384] */ 1235 _iov_alloc_buf(&iovs[4], 126); 1236 1237 /* data[1][511], data[2][511:0], data[3][511:0] */ 1238 _iov_alloc_buf(&iovs[5], 1 + 512 * 2); 1239 1240 _iov_alloc_buf(&md_iov, 8 * 4); 1241 1242 dix_generate_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 1243 dif_flags, 22, 0xFFFF, 0x22); 1244 1245 for (i = 0; i < 6; i++) { 1246 _iov_free_buf(&iovs[i]); 1247 } 1248 _iov_free_buf(&md_iov); 1249 } 1250 1251 static void 1252 _dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, 1253 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 1254 uint32_t inject_flags, bool dif_loc) 1255 { 1256 struct spdk_dif_ctx ctx = {}; 1257 struct spdk_dif_error err_blk = {}; 1258 uint32_t inject_offset = 0, dif_flags; 1259 int rc; 1260 1261 dif_flags = SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_APPTAG_CHECK | 1262 SPDK_DIF_FLAGS_REFTAG_CHECK; 1263 1264 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks); 1265 CU_ASSERT(rc == 0); 1266 1267 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags, 1268 88, 0xFFFF, 0x88, GUARD_SEED); 1269 CU_ASSERT(rc == 0); 1270 1271 rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); 1272 CU_ASSERT(rc == 0); 1273 1274 rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset); 1275 CU_ASSERT(rc == 0); 1276 1277 rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, &err_blk); 1278 CU_ASSERT(rc != 0); 1279 1280 if (inject_flags == SPDK_DIF_DATA_ERROR) { 1281 CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); 1282 } else { 1283 CU_ASSERT(inject_flags == err_blk.err_type); 1284 } 1285 CU_ASSERT(inject_offset == err_blk.err_offset); 1286 } 1287 1288 static void 1289 dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, 1290 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 1291 uint32_t inject_flags) 1292 { 1293 /* The case that DIF is contained in the first 8 bytes of metadata. */ 1294 _dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks, 1295 inject_flags, true); 1296 1297 /* The case that DIF is contained in the last 8 bytes of metadata. */ 1298 _dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks, 1299 inject_flags, false); 1300 } 1301 1302 static void 1303 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) 1304 { 1305 struct iovec iovs[4], md_iov; 1306 int i, num_blocks; 1307 1308 num_blocks = 0; 1309 1310 for (i = 0; i < 4; i++) { 1311 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 1312 num_blocks += i + 1; 1313 } 1314 1315 _iov_alloc_buf(&md_iov, 128 * num_blocks); 1316 1317 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_GUARD_ERROR); 1318 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_APPTAG_ERROR); 1319 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_REFTAG_ERROR); 1320 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_DATA_ERROR); 1321 1322 for (i = 0; i < 4; i++) { 1323 _iov_free_buf(&iovs[i]); 1324 } 1325 _iov_free_buf(&md_iov); 1326 } 1327 1328 static void 1329 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void) 1330 { 1331 struct iovec iovs[4], md_iov; 1332 int i; 1333 1334 _iov_alloc_buf(&iovs[0], 2048); 1335 _iov_alloc_buf(&iovs[1], 2048); 1336 _iov_alloc_buf(&iovs[2], 1); 1337 _iov_alloc_buf(&iovs[3], 4095); 1338 1339 _iov_alloc_buf(&md_iov, 128 * 2); 1340 1341 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_GUARD_ERROR); 1342 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_APPTAG_ERROR); 1343 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_REFTAG_ERROR); 1344 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_DATA_ERROR); 1345 1346 for (i = 0; i < 4; i++) { 1347 _iov_free_buf(&iovs[i]); 1348 } 1349 _iov_free_buf(&md_iov); 1350 } 1351 1352 int 1353 main(int argc, char **argv) 1354 { 1355 CU_pSuite suite = NULL; 1356 unsigned int num_failures; 1357 1358 if (CU_initialize_registry() != CUE_SUCCESS) { 1359 return CU_get_error(); 1360 } 1361 1362 suite = CU_add_suite("dif", NULL, NULL); 1363 if (suite == NULL) { 1364 CU_cleanup_registry(); 1365 return CU_get_error(); 1366 } 1367 1368 if ( 1369 CU_add_test(suite, "dif_generate_and_verify_test", dif_generate_and_verify_test) == NULL || 1370 CU_add_test(suite, "dif_disable_check_test", dif_disable_check_test) == NULL || 1371 CU_add_test(suite, "dif_sec_512_md_0_error_test", dif_sec_512_md_0_error_test) == NULL || 1372 CU_add_test(suite, "dif_guard_seed_test", dif_guard_seed_test) == NULL || 1373 CU_add_test(suite, "dif_disable_sec_512_md_8_single_iov_test", 1374 dif_disable_sec_512_md_8_single_iov_test) == NULL || 1375 CU_add_test(suite, "dif_sec_512_md_8_prchk_0_single_iov_test", 1376 dif_sec_512_md_8_prchk_0_single_iov_test) == NULL || 1377 CU_add_test(suite, "dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test", 1378 dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test) == NULL || 1379 CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_test", 1380 dif_sec_4096_md_128_prchk_7_multi_iovs_test) == NULL || 1381 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test", 1382 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test) == NULL || 1383 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test", 1384 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test) == NULL || 1385 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test", 1386 dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test) == NULL || 1387 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test", 1388 dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test) == NULL || 1389 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test", 1390 dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test) == NULL || 1391 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test", 1392 dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test) == NULL || 1393 CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test", 1394 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test) == NULL || 1395 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test", 1396 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL || 1397 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test", 1398 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test) == NULL || 1399 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test", 1400 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test) == NULL || 1401 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test", 1402 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test) == NULL || 1403 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8__multi_iovs_split_apptag_test", 1404 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test) == NULL || 1405 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test", 1406 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test) == NULL || 1407 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_single_iov", 1408 dif_copy_sec_512_md_8_prchk_0_single_iov) == NULL || 1409 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs", 1410 dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL || 1411 CU_add_test(suite, "dif_copy_sec_4096_md_128_prchk_7_multi_iovs", 1412 dif_copy_sec_4096_md_128_prchk_7_multi_iovs) == NULL || 1413 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data", 1414 dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL || 1415 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits", 1416 dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL || 1417 CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test", 1418 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL || 1419 CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test", 1420 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL || 1421 CU_add_test(suite, "dix_sec_512_md_0_error", dix_sec_512_md_0_error) == NULL || 1422 CU_add_test(suite, "dix_sec_512_md_8_prchk_0_single_iov", 1423 dix_sec_512_md_8_prchk_0_single_iov) == NULL || 1424 CU_add_test(suite, "dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs", 1425 dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL || 1426 CU_add_test(suite, "dix_sec_4096_md_128_prchk_7_multi_iovs", 1427 dix_sec_4096_md_128_prchk_7_multi_iovs) == NULL || 1428 CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_split_data", 1429 dix_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL || 1430 CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits", 1431 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL || 1432 CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test", 1433 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL || 1434 CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test", 1435 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL 1436 ) { 1437 CU_cleanup_registry(); 1438 return CU_get_error(); 1439 } 1440 1441 CU_basic_set_mode(CU_BRM_VERBOSE); 1442 1443 CU_basic_run_tests(); 1444 1445 num_failures = CU_get_number_of_failures(); 1446 CU_cleanup_registry(); 1447 1448 return num_failures; 1449 } 1450