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 0xAB 41 42 static int 43 ut_data_pattern_generate(struct iovec *iovs, int iovcnt, 44 uint32_t block_size, uint32_t md_size, uint32_t num_blocks) 45 { 46 struct _iov_iter iter; 47 uint32_t offset_blocks, offset_in_block, buf_len; 48 void *buf; 49 50 if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) { 51 return -1; 52 } 53 54 offset_blocks = 0; 55 _iov_iter_init(&iter, iovs, iovcnt); 56 57 while (offset_blocks < num_blocks) { 58 offset_in_block = 0; 59 while (offset_in_block < block_size) { 60 _iov_iter_get_buf(&iter, &buf, &buf_len); 61 if (offset_in_block < block_size - md_size) { 62 buf_len = spdk_min(buf_len, 63 block_size - md_size - offset_in_block); 64 memset(buf, DATA_PATTERN, buf_len); 65 } else { 66 buf_len = spdk_min(buf_len, block_size - offset_in_block); 67 memset(buf, 0, buf_len); 68 } 69 _iov_iter_advance(&iter, buf_len); 70 offset_in_block += buf_len; 71 } 72 offset_blocks++; 73 } 74 75 return 0; 76 } 77 78 static int 79 ut_data_pattern_verify(struct iovec *iovs, int iovcnt, 80 uint32_t block_size, uint32_t md_size, uint32_t num_blocks) 81 { 82 struct _iov_iter iter; 83 uint32_t offset_blocks, offset_in_block, buf_len, i; 84 uint8_t *buf; 85 86 if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) { 87 return -1; 88 } 89 90 offset_blocks = 0; 91 _iov_iter_init(&iter, iovs, iovcnt); 92 93 while (offset_blocks < num_blocks) { 94 offset_in_block = 0; 95 while (offset_in_block < block_size) { 96 _iov_iter_get_buf(&iter, (void *)&buf, &buf_len); 97 98 if (offset_in_block < block_size - md_size) { 99 buf_len = spdk_min(buf_len, 100 block_size - md_size - offset_in_block); 101 for (i = 0; i < buf_len; i++) { 102 if (buf[i] != DATA_PATTERN) { 103 return -1; 104 } 105 } 106 } else { 107 buf_len = spdk_min(buf_len, block_size - offset_in_block); 108 } 109 _iov_iter_advance(&iter, buf_len); 110 offset_in_block += buf_len; 111 } 112 offset_blocks++; 113 } 114 115 return 0; 116 } 117 118 static void 119 _iov_alloc_buf(struct iovec *iov, uint32_t len) 120 { 121 iov->iov_base = calloc(1, len); 122 iov->iov_len = len; 123 SPDK_CU_ASSERT_FATAL(iov->iov_base != NULL); 124 } 125 126 static void 127 _iov_free_buf(struct iovec *iov) 128 { 129 free(iov->iov_base); 130 } 131 132 static void 133 _dif_generate_and_verify(struct iovec *iov, 134 uint32_t block_size, uint32_t md_size, bool dif_loc, 135 enum spdk_dif_type dif_type, uint32_t dif_flags, 136 uint32_t ref_tag, uint32_t e_ref_tag, 137 uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag, 138 bool expect_pass) 139 { 140 struct spdk_dif_ctx ctx = {}; 141 uint32_t guard_interval; 142 uint16_t guard = 0; 143 int rc; 144 145 rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1); 146 CU_ASSERT(rc == 0); 147 148 guard_interval = _get_guard_interval(block_size, md_size, dif_loc, true); 149 150 ctx.dif_type = dif_type; 151 ctx.dif_flags = dif_flags; 152 ctx.init_ref_tag = ref_tag; 153 ctx.app_tag = app_tag; 154 155 if (dif_flags & SPDK_DIF_GUARD_CHECK) { 156 guard = spdk_crc16_t10dif(0, iov->iov_base, guard_interval); 157 } 158 159 _dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx); 160 161 ctx.init_ref_tag = e_ref_tag; 162 ctx.apptag_mask = apptag_mask; 163 ctx.app_tag = e_app_tag; 164 165 rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx, NULL); 166 CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0)); 167 168 rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1); 169 CU_ASSERT(rc == 0); 170 } 171 172 static void 173 dif_generate_and_verify_test(void) 174 { 175 struct iovec iov; 176 uint32_t dif_flags; 177 178 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 179 180 _iov_alloc_buf(&iov, 4096 + 128); 181 182 /* Positive cases */ 183 184 /* The case that DIF is contained in the first 8 bytes of metadata. */ 185 _dif_generate_and_verify(&iov, 186 4096 + 128, 128, true, 187 SPDK_DIF_TYPE1, dif_flags, 188 22, 22, 189 0x22, 0xFFFF, 0x22, 190 true); 191 192 /* The case that DIF is contained in the last 8 bytes of metadata. */ 193 _dif_generate_and_verify(&iov, 194 4096 + 128, 128, false, 195 SPDK_DIF_TYPE1, dif_flags, 196 22, 22, 197 0x22, 0xFFFF, 0x22, 198 true); 199 200 /* Negative cases */ 201 202 /* Reference tag doesn't match. */ 203 _dif_generate_and_verify(&iov, 204 4096 + 128, 128, false, 205 SPDK_DIF_TYPE1, dif_flags, 206 22, 23, 207 0x22, 0xFFFF, 0x22, 208 false); 209 210 /* Application tag doesn't match. */ 211 _dif_generate_and_verify(&iov, 212 4096 + 128, 128, false, 213 SPDK_DIF_TYPE1, dif_flags, 214 22, 22, 215 0x22, 0xFFFF, 0x23, 216 false); 217 218 _iov_free_buf(&iov); 219 } 220 221 static void 222 dif_disable_check_test(void) 223 { 224 struct iovec iov; 225 uint32_t dif_flags; 226 227 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 228 229 _iov_alloc_buf(&iov, 4096 + 128); 230 231 /* The case that DIF check is disabled when the Application Tag is 0xFFFF for 232 * Type 1. DIF check is disabled and pass is expected. 233 */ 234 _dif_generate_and_verify(&iov, 235 4096 + 128, 128, false, 236 SPDK_DIF_TYPE1, dif_flags, 237 22, 22, 238 0xFFFF, 0xFFFF, 0x22, 239 true); 240 241 /* The case that DIF check is not disabled when the Application Tag is 0xFFFF but 242 * the Reference Tag is not 0xFFFFFFFF for Type 3. DIF check is not disabled and 243 * fail is expected. 244 */ 245 _dif_generate_and_verify(&iov, 246 4096 + 128, 128, false, 247 SPDK_DIF_TYPE3, dif_flags, 248 22, 22, 249 0xFFFF, 0xFFFF, 0x22, 250 false); 251 252 /* The case that DIF check is disabled when the Application Tag is 0xFFFF and 253 * the Reference Tag is 0xFFFFFFFF for Type 3. DIF check is disabled and 254 * pass is expected. 255 */ 256 _dif_generate_and_verify(&iov, 257 4096 + 128, 128, false, 258 SPDK_DIF_TYPE3, dif_flags, 259 0xFFFFFFFF, 22, 260 0xFFFF, 0xFFFF, 0x22, 261 true); 262 263 _iov_free_buf(&iov); 264 } 265 266 static void 267 dif_sec_512_md_0_error_test(void) 268 { 269 struct spdk_dif_ctx ctx = {}; 270 int rc; 271 272 /* Metadata size is 0. */ 273 rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 274 CU_ASSERT(rc != 0); 275 } 276 277 static void 278 dif_generate_and_verify(struct iovec *iovs, int iovcnt, 279 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 280 bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, 281 uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) 282 { 283 struct spdk_dif_ctx ctx = {}; 284 int rc; 285 286 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks); 287 CU_ASSERT(rc == 0); 288 289 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, 290 init_ref_tag, apptag_mask, app_tag); 291 CU_ASSERT(rc == 0); 292 293 rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); 294 CU_ASSERT(rc == 0); 295 296 rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL); 297 CU_ASSERT(rc == 0); 298 299 rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks); 300 CU_ASSERT(rc == 0); 301 } 302 303 static void 304 dif_disable_sec_512_md_8_single_iov_test(void) 305 { 306 struct iovec iov; 307 308 _iov_alloc_buf(&iov, (512 + 8) * 4); 309 310 dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_DISABLE, 0, 0, 0, 0); 311 312 _iov_free_buf(&iov); 313 } 314 315 static void 316 dif_sec_512_md_8_prchk_0_single_iov_test(void) 317 { 318 struct iovec iov; 319 320 _iov_alloc_buf(&iov, (512 + 8) * 4); 321 322 dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 323 324 _iov_free_buf(&iov); 325 } 326 327 static void 328 dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test(void) 329 { 330 struct iovec iovs[4]; 331 int i, num_blocks; 332 333 num_blocks = 0; 334 335 for (i = 0; i < 4; i++) { 336 _iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1)); 337 num_blocks += i + 1; 338 } 339 340 dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, 341 0, 22, 0xFFFF, 0x22); 342 343 dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, 344 SPDK_DIF_GUARD_CHECK, 22, 0xFFFF, 0x22); 345 346 dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, 347 SPDK_DIF_APPTAG_CHECK, 22, 0xFFFF, 0x22); 348 349 dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1, 350 SPDK_DIF_REFTAG_CHECK, 22, 0xFFFF, 0x22); 351 352 for (i = 0; i < 4; i++) { 353 _iov_free_buf(&iovs[i]); 354 } 355 } 356 357 static void 358 dif_sec_4096_md_128_prchk_7_multi_iovs_test(void) 359 { 360 struct iovec iovs[4]; 361 int i, num_blocks; 362 uint32_t dif_flags; 363 364 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 365 366 num_blocks = 0; 367 368 for (i = 0; i < 4; i++) { 369 _iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1)); 370 num_blocks += i + 1; 371 } 372 373 dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1, 374 dif_flags, 22, 0xFFFF, 0x22); 375 376 dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1, 377 dif_flags, 22, 0xFFFF, 0x22); 378 379 for (i = 0; i < 4; i++) { 380 _iov_free_buf(&iovs[i]); 381 } 382 } 383 384 static void 385 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test(void) 386 { 387 struct iovec iovs[2]; 388 uint32_t dif_flags; 389 390 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 391 392 _iov_alloc_buf(&iovs[0], 512); 393 _iov_alloc_buf(&iovs[1], 8); 394 395 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 396 dif_flags, 22, 0xFFFF, 0x22); 397 398 _iov_free_buf(&iovs[0]); 399 _iov_free_buf(&iovs[1]); 400 } 401 402 static void 403 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test(void) 404 { 405 struct iovec iovs[2]; 406 uint32_t dif_flags; 407 408 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 409 410 _iov_alloc_buf(&iovs[0], 256); 411 _iov_alloc_buf(&iovs[1], 264); 412 413 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 414 dif_flags, 22, 0xFFFF, 0x22); 415 416 _iov_free_buf(&iovs[0]); 417 _iov_free_buf(&iovs[1]); 418 } 419 420 static void 421 dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test(void) 422 { 423 struct iovec iovs[2]; 424 uint32_t dif_flags; 425 426 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 427 428 _iov_alloc_buf(&iovs[0], 513); 429 _iov_alloc_buf(&iovs[1], 7); 430 431 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 432 dif_flags, 22, 0xFFFF, 0x22); 433 434 _iov_free_buf(&iovs[0]); 435 _iov_free_buf(&iovs[1]); 436 } 437 438 static void 439 dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test(void) 440 { 441 struct iovec iovs[2]; 442 uint32_t dif_flags; 443 444 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 445 446 _iov_alloc_buf(&iovs[0], 515); 447 _iov_alloc_buf(&iovs[1], 5); 448 449 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 450 dif_flags, 22, 0xFFFF, 0x22); 451 452 _iov_free_buf(&iovs[0]); 453 _iov_free_buf(&iovs[1]); 454 } 455 456 static void 457 dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test(void) 458 { 459 struct iovec iovs[2]; 460 uint32_t dif_flags; 461 462 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 463 464 _iov_alloc_buf(&iovs[0], 518); 465 _iov_alloc_buf(&iovs[1], 2); 466 467 dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 468 dif_flags, 22, 0xFFFF, 0x22); 469 470 _iov_free_buf(&iovs[0]); 471 _iov_free_buf(&iovs[1]); 472 } 473 474 static void 475 dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test(void) 476 { 477 struct iovec iovs[9]; 478 uint32_t dif_flags; 479 int i; 480 481 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 482 483 /* data[0][255:0] */ 484 _iov_alloc_buf(&iovs[0], 256); 485 486 /* data[0][511:256], guard[0][0] */ 487 _iov_alloc_buf(&iovs[1], 256 + 1); 488 489 /* guard[0][1], apptag[0][0] */ 490 _iov_alloc_buf(&iovs[2], 1 + 1); 491 492 /* apptag[0][1], reftag[0][0] */ 493 _iov_alloc_buf(&iovs[3], 1 + 1); 494 495 /* reftag[0][3:1], data[1][255:0] */ 496 _iov_alloc_buf(&iovs[4], 3 + 256); 497 498 /* data[1][511:256], guard[1][0] */ 499 _iov_alloc_buf(&iovs[5], 256 + 1); 500 501 /* guard[1][1], apptag[1][0] */ 502 _iov_alloc_buf(&iovs[6], 1 + 1); 503 504 /* apptag[1][1], reftag[1][0] */ 505 _iov_alloc_buf(&iovs[7], 1 + 1); 506 507 /* reftag[1][3:1] */ 508 _iov_alloc_buf(&iovs[8], 3); 509 510 dif_generate_and_verify(iovs, 9, 512 + 8, 8, 2, false, SPDK_DIF_TYPE1, dif_flags, 511 22, 0xFFFF, 0x22); 512 513 for (i = 0; i < 9; i++) { 514 _iov_free_buf(&iovs[i]); 515 } 516 } 517 518 static void 519 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void) 520 { 521 struct iovec iovs[11]; 522 uint32_t dif_flags; 523 int i; 524 525 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 526 527 /* data[0][1000:0] */ 528 _iov_alloc_buf(&iovs[0], 1000); 529 530 /* data[0][3095:1000], guard[0][0] */ 531 _iov_alloc_buf(&iovs[1], 3096 + 1); 532 533 /* guard[0][1], apptag[0][0] */ 534 _iov_alloc_buf(&iovs[2], 1 + 1); 535 536 /* apptag[0][1], reftag[0][0] */ 537 _iov_alloc_buf(&iovs[3], 1 + 1); 538 539 /* reftag[0][3:1], ignore[0][59:0] */ 540 _iov_alloc_buf(&iovs[4], 3 + 60); 541 542 /* ignore[119:60], data[1][3050:0] */ 543 _iov_alloc_buf(&iovs[5], 60 + 3051); 544 545 /* data[1][4095:3050], guard[1][0] */ 546 _iov_alloc_buf(&iovs[6], 1045 + 1); 547 548 /* guard[1][1], apptag[1][0] */ 549 _iov_alloc_buf(&iovs[7], 1 + 1); 550 551 /* apptag[1][1], reftag[1][0] */ 552 _iov_alloc_buf(&iovs[8], 1 + 1); 553 554 /* reftag[1][3:1], ignore[1][9:0] */ 555 _iov_alloc_buf(&iovs[9], 3 + 10); 556 557 /* ignore[1][127:9] */ 558 _iov_alloc_buf(&iovs[10], 118); 559 560 dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags, 561 22, 0xFFFF, 0x22); 562 dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags, 563 22, 0xFFFF, 0x22); 564 565 for (i = 0; i < 11; i++) { 566 _iov_free_buf(&iovs[i]); 567 } 568 } 569 570 static void 571 _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt, 572 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 573 uint32_t inject_flags, bool dif_loc) 574 { 575 struct spdk_dif_ctx ctx = {}; 576 struct spdk_dif_error err_blk = {}; 577 uint32_t inject_offset = 0, dif_flags; 578 int rc; 579 580 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 581 582 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks); 583 CU_ASSERT(rc == 0); 584 585 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, 586 SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88); 587 CU_ASSERT(rc == 0); 588 589 rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); 590 CU_ASSERT(rc == 0); 591 592 rc = spdk_dif_inject_error(iovs, iovcnt, num_blocks, &ctx, inject_flags, &inject_offset); 593 CU_ASSERT(rc == 0); 594 595 rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, &err_blk); 596 CU_ASSERT(rc != 0); 597 if (inject_flags == SPDK_DIF_DATA_ERROR) { 598 CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); 599 } else { 600 CU_ASSERT(inject_flags == err_blk.err_type); 601 } 602 CU_ASSERT(inject_offset == err_blk.err_offset); 603 604 rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks); 605 CU_ASSERT((rc == 0 && (inject_flags != SPDK_DIF_DATA_ERROR)) || 606 (rc != 0 && (inject_flags == SPDK_DIF_DATA_ERROR))); 607 } 608 609 static void 610 dif_inject_error_and_verify(struct iovec *iovs, int iovcnt, 611 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 612 uint32_t inject_flags) 613 { 614 /* The case that DIF is contained in the first 8 bytes of metadata. */ 615 _dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks, 616 inject_flags, true); 617 618 /* The case that DIF is contained in the last 8 bytes of metadata. */ 619 _dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks, 620 inject_flags, false); 621 } 622 623 static void 624 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) 625 { 626 struct iovec iovs[4]; 627 int i, num_blocks; 628 629 num_blocks = 0; 630 631 for (i = 0; i < 4; i++) { 632 _iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1)); 633 num_blocks += i + 1; 634 } 635 636 dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_GUARD_ERROR); 637 dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_APPTAG_ERROR); 638 dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_REFTAG_ERROR); 639 dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_DATA_ERROR); 640 641 for (i = 0; i < 4; i++) { 642 _iov_free_buf(&iovs[i]); 643 } 644 } 645 646 static void 647 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test(void) 648 { 649 struct iovec iovs[2]; 650 651 _iov_alloc_buf(&iovs[0], 4096); 652 _iov_alloc_buf(&iovs[1], 128); 653 654 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); 655 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); 656 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); 657 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); 658 659 _iov_free_buf(&iovs[0]); 660 _iov_free_buf(&iovs[1]); 661 } 662 663 static void 664 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test(void) 665 { 666 struct iovec iovs[2]; 667 668 _iov_alloc_buf(&iovs[0], 2048); 669 _iov_alloc_buf(&iovs[1], 2048 + 128); 670 671 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); 672 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); 673 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); 674 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); 675 676 _iov_free_buf(&iovs[0]); 677 _iov_free_buf(&iovs[1]); 678 } 679 680 static void 681 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test(void) 682 { 683 struct iovec iovs[2]; 684 685 _iov_alloc_buf(&iovs[0], 4096 + 1); 686 _iov_alloc_buf(&iovs[1], 127); 687 688 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); 689 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); 690 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); 691 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); 692 693 _iov_free_buf(&iovs[0]); 694 _iov_free_buf(&iovs[1]); 695 } 696 697 static void 698 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(void) 699 { 700 struct iovec iovs[2]; 701 702 _iov_alloc_buf(&iovs[0], 4096 + 3); 703 _iov_alloc_buf(&iovs[1], 125); 704 705 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); 706 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); 707 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); 708 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); 709 710 _iov_free_buf(&iovs[0]); 711 _iov_free_buf(&iovs[1]); 712 } 713 714 static void 715 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(void) 716 { 717 struct iovec iovs[2]; 718 719 _iov_alloc_buf(&iovs[0], 4096 + 6); 720 _iov_alloc_buf(&iovs[1], 122); 721 722 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR); 723 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR); 724 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR); 725 dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR); 726 727 _iov_free_buf(&iovs[0]); 728 _iov_free_buf(&iovs[1]); 729 } 730 731 static void 732 dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, 733 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 734 bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, 735 uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) 736 { 737 struct spdk_dif_ctx ctx = {}; 738 int rc; 739 740 rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks); 741 CU_ASSERT(rc == 0); 742 743 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, 744 init_ref_tag, apptag_mask, app_tag); 745 CU_ASSERT(rc == 0); 746 747 rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); 748 CU_ASSERT(rc == 0); 749 750 rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL); 751 CU_ASSERT(rc == 0); 752 753 rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks); 754 CU_ASSERT(rc == 0); 755 } 756 757 static void 758 dif_copy_sec_512_md_8_prchk_0_single_iov(void) 759 { 760 struct iovec iov, bounce_iov; 761 762 _iov_alloc_buf(&iov, 512 * 4); 763 _iov_alloc_buf(&bounce_iov, (512 + 8) * 4); 764 765 dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4, 766 false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 767 dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4, 768 true, SPDK_DIF_TYPE1, 0, 0, 0, 0); 769 770 _iov_free_buf(&iov); 771 _iov_free_buf(&bounce_iov); 772 } 773 774 static void 775 dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void) 776 { 777 struct iovec iovs[4], bounce_iov; 778 int i, num_blocks; 779 780 num_blocks = 0; 781 782 for (i = 0; i < 4; i++) { 783 _iov_alloc_buf(&iovs[i], 512 * (i + 1)); 784 num_blocks += i + 1; 785 } 786 787 _iov_alloc_buf(&bounce_iov, (512 + 8) * num_blocks); 788 789 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, 790 false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22); 791 792 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, 793 false, SPDK_DIF_TYPE1, SPDK_DIF_GUARD_CHECK, 22, 0xFFFF, 0x22); 794 795 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, 796 false, SPDK_DIF_TYPE1, SPDK_DIF_APPTAG_CHECK, 22, 0xFFFF, 0x22); 797 798 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks, 799 false, SPDK_DIF_TYPE1, SPDK_DIF_REFTAG_CHECK, 22, 0xFFFF, 0x22); 800 801 for (i = 0; i < 4; i++) { 802 _iov_free_buf(&iovs[i]); 803 } 804 _iov_free_buf(&bounce_iov); 805 } 806 807 static void 808 dif_copy_sec_4096_md_128_prchk_7_multi_iovs(void) 809 { 810 struct iovec iovs[4], bounce_iov; 811 uint32_t dif_flags; 812 int i, num_blocks; 813 814 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 815 816 num_blocks = 0; 817 818 for (i = 0; i < 4; i++) { 819 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 820 num_blocks += i + 1; 821 } 822 823 _iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks); 824 825 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks, 826 false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 827 dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks, 828 true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 829 830 for (i = 0; i < 4; i++) { 831 _iov_free_buf(&iovs[i]); 832 } 833 _iov_free_buf(&bounce_iov); 834 } 835 836 static void 837 dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data(void) 838 { 839 struct iovec iovs[2], bounce_iov; 840 uint32_t dif_flags; 841 842 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 843 844 _iov_alloc_buf(&iovs[0], 256); 845 _iov_alloc_buf(&iovs[1], 256); 846 847 _iov_alloc_buf(&bounce_iov, 512 + 8); 848 849 dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 512 + 8, 8, 1, 850 false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 851 852 _iov_free_buf(&iovs[0]); 853 _iov_free_buf(&iovs[1]); 854 _iov_free_buf(&bounce_iov); 855 } 856 857 static void 858 dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void) 859 { 860 struct iovec iovs[6], bounce_iov; 861 uint32_t dif_flags; 862 int i; 863 864 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 865 866 /* data[0][255:0] */ 867 _iov_alloc_buf(&iovs[0], 256); 868 869 /* data[0][511:256], data[1][255:0] */ 870 _iov_alloc_buf(&iovs[1], 256 + 256); 871 872 /* data[1][382:256] */ 873 _iov_alloc_buf(&iovs[2], 128); 874 875 /* data[1][383] */ 876 _iov_alloc_buf(&iovs[3], 1); 877 878 /* data[1][510:384] */ 879 _iov_alloc_buf(&iovs[4], 126); 880 881 /* data[1][511], data[2][511:0], data[3][511:0] */ 882 _iov_alloc_buf(&iovs[5], 1 + 512 * 2); 883 884 _iov_alloc_buf(&bounce_iov, (512 + 8) * 4); 885 886 dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 512 + 8, 8, 4, 887 true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22); 888 889 for (i = 0; i < 6; i++) { 890 _iov_free_buf(&iovs[i]); 891 } 892 _iov_free_buf(&bounce_iov); 893 } 894 895 static void 896 _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, 897 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 898 uint32_t inject_flags, bool dif_loc) 899 { 900 struct spdk_dif_ctx ctx = {}; 901 struct spdk_dif_error err_blk = {}; 902 uint32_t inject_offset = 0, dif_flags; 903 int rc; 904 905 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 906 907 rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks); 908 CU_ASSERT(rc == 0); 909 910 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags, 911 88, 0xFFFF, 0x88); 912 SPDK_CU_ASSERT_FATAL(rc == 0); 913 914 rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); 915 CU_ASSERT(rc == 0); 916 917 rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset); 918 CU_ASSERT(rc == 0); 919 920 rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, &err_blk); 921 CU_ASSERT(rc != 0); 922 if (inject_flags == SPDK_DIF_DATA_ERROR) { 923 CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); 924 } else { 925 CU_ASSERT(inject_flags == err_blk.err_type); 926 } 927 CU_ASSERT(inject_offset == err_blk.err_offset); 928 } 929 930 static void 931 dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, 932 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 933 uint32_t inject_flags) 934 { 935 /* The case that DIF is contained in the first 8 bytes of metadata. */ 936 _dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov, 937 block_size, md_size, num_blocks, 938 inject_flags, true); 939 940 /* The case that DIF is contained in the last 8 bytes of metadata. */ 941 _dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov, 942 block_size, md_size, num_blocks, 943 inject_flags, false); 944 } 945 946 static void 947 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) 948 { 949 struct iovec iovs[4], bounce_iov; 950 int i, num_blocks; 951 952 num_blocks = 0; 953 954 for (i = 0; i < 4; i++) { 955 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 956 num_blocks += i + 1; 957 } 958 959 _iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks); 960 961 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 962 num_blocks, SPDK_DIF_GUARD_ERROR); 963 964 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 965 num_blocks, SPDK_DIF_APPTAG_ERROR); 966 967 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 968 num_blocks, SPDK_DIF_REFTAG_ERROR); 969 970 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 971 num_blocks, SPDK_DIF_DATA_ERROR); 972 973 for (i = 0; i < 4; i++) { 974 _iov_free_buf(&iovs[i]); 975 } 976 _iov_free_buf(&bounce_iov); 977 } 978 979 static void 980 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void) 981 { 982 struct iovec iovs[4], bounce_iov; 983 int i; 984 985 _iov_alloc_buf(&iovs[0], 2048); 986 _iov_alloc_buf(&iovs[1], 2048); 987 _iov_alloc_buf(&iovs[2], 1); 988 _iov_alloc_buf(&iovs[3], 4095); 989 990 _iov_alloc_buf(&bounce_iov, (4096 + 128) * 2); 991 992 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 993 2, SPDK_DIF_GUARD_ERROR); 994 995 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 996 2, SPDK_DIF_APPTAG_ERROR); 997 998 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 999 2, SPDK_DIF_REFTAG_ERROR); 1000 1001 dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, 1002 2, SPDK_DIF_DATA_ERROR); 1003 1004 for (i = 0; i < 4; i++) { 1005 _iov_free_buf(&iovs[i]); 1006 } 1007 _iov_free_buf(&bounce_iov); 1008 } 1009 1010 static void 1011 dix_sec_512_md_0_error(void) 1012 { 1013 struct spdk_dif_ctx ctx; 1014 int rc; 1015 1016 rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 1017 CU_ASSERT(rc != 0); 1018 } 1019 1020 static void 1021 dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, 1022 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 1023 bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, 1024 uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) 1025 { 1026 struct spdk_dif_ctx ctx; 1027 int rc; 1028 1029 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks); 1030 CU_ASSERT(rc == 0); 1031 1032 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags, 1033 init_ref_tag, apptag_mask, app_tag); 1034 CU_ASSERT(rc == 0); 1035 1036 rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); 1037 CU_ASSERT(rc == 0); 1038 1039 rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL); 1040 CU_ASSERT(rc == 0); 1041 1042 rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks); 1043 CU_ASSERT(rc == 0); 1044 } 1045 1046 static void 1047 dix_sec_512_md_8_prchk_0_single_iov(void) 1048 { 1049 struct iovec iov, md_iov; 1050 1051 _iov_alloc_buf(&iov, 512 * 4); 1052 _iov_alloc_buf(&md_iov, 8 * 4); 1053 1054 dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); 1055 dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0); 1056 1057 _iov_free_buf(&iov); 1058 _iov_free_buf(&md_iov); 1059 } 1060 1061 static void 1062 dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void) 1063 { 1064 struct iovec iovs[4], md_iov; 1065 int i, num_blocks; 1066 1067 num_blocks = 0; 1068 1069 for (i = 0; i < 4; i++) { 1070 _iov_alloc_buf(&iovs[i], 512 * (i + 1)); 1071 num_blocks += i + 1; 1072 } 1073 _iov_alloc_buf(&md_iov, 8 * num_blocks); 1074 1075 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1076 0, 22, 0xFFFF, 0x22); 1077 1078 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1079 SPDK_DIF_GUARD_CHECK, 22, 0xFFFF, 0x22); 1080 1081 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1082 SPDK_DIF_APPTAG_CHECK, 22, 0xFFFF, 0x22); 1083 1084 dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1, 1085 SPDK_DIF_REFTAG_CHECK, 22, 0xFFFF, 0x22); 1086 1087 for (i = 0; i < 4; i++) { 1088 _iov_free_buf(&iovs[i]); 1089 } 1090 _iov_free_buf(&md_iov); 1091 } 1092 1093 static void 1094 dix_sec_4096_md_128_prchk_7_multi_iovs(void) 1095 { 1096 struct iovec iovs[4], md_iov; 1097 uint32_t dif_flags; 1098 int i, num_blocks; 1099 1100 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 1101 1102 num_blocks = 0; 1103 1104 for (i = 0; i < 4; i++) { 1105 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 1106 num_blocks += i + 1; 1107 } 1108 _iov_alloc_buf(&md_iov, 128 * num_blocks); 1109 1110 dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1, 1111 dif_flags, 22, 0xFFFF, 0x22); 1112 dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1, 1113 dif_flags, 22, 0xFFFF, 0x22); 1114 1115 for (i = 0; i < 4; i++) { 1116 _iov_free_buf(&iovs[i]); 1117 } 1118 _iov_free_buf(&md_iov); 1119 } 1120 1121 static void 1122 dix_sec_512_md_8_prchk_7_multi_iovs_split_data(void) 1123 { 1124 struct iovec iovs[2], md_iov; 1125 uint32_t dif_flags; 1126 1127 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 1128 1129 _iov_alloc_buf(&iovs[0], 256); 1130 _iov_alloc_buf(&iovs[1], 256); 1131 _iov_alloc_buf(&md_iov, 8); 1132 1133 dix_generate_and_verify(iovs, 2, &md_iov, 512, 8, 1, false, SPDK_DIF_TYPE1, 1134 dif_flags, 22, 0xFFFF, 0x22); 1135 1136 _iov_free_buf(&iovs[0]); 1137 _iov_free_buf(&iovs[1]); 1138 _iov_free_buf(&md_iov); 1139 } 1140 1141 static void 1142 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void) 1143 { 1144 struct iovec iovs[6], md_iov; 1145 uint32_t dif_flags; 1146 int i; 1147 1148 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 1149 1150 /* data[0][255:0] */ 1151 _iov_alloc_buf(&iovs[0], 256); 1152 1153 /* data[0][511:256], data[1][255:0] */ 1154 _iov_alloc_buf(&iovs[1], 256 + 256); 1155 1156 /* data[1][382:256] */ 1157 _iov_alloc_buf(&iovs[2], 128); 1158 1159 /* data[1][383] */ 1160 _iov_alloc_buf(&iovs[3], 1); 1161 1162 /* data[1][510:384] */ 1163 _iov_alloc_buf(&iovs[4], 126); 1164 1165 /* data[1][511], data[2][511:0], data[3][511:0] */ 1166 _iov_alloc_buf(&iovs[5], 1 + 512 * 2); 1167 1168 _iov_alloc_buf(&md_iov, 8 * 4); 1169 1170 dix_generate_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 1171 dif_flags, 22, 0xFFFF, 0x22); 1172 1173 for (i = 0; i < 6; i++) { 1174 _iov_free_buf(&iovs[i]); 1175 } 1176 _iov_free_buf(&md_iov); 1177 } 1178 1179 static void 1180 _dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, 1181 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 1182 uint32_t inject_flags, bool dif_loc) 1183 { 1184 struct spdk_dif_ctx ctx = {}; 1185 struct spdk_dif_error err_blk = {}; 1186 uint32_t inject_offset = 0, dif_flags; 1187 int rc; 1188 1189 dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK; 1190 1191 rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks); 1192 CU_ASSERT(rc == 0); 1193 1194 rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags, 1195 88, 0xFFFF, 0x88); 1196 CU_ASSERT(rc == 0); 1197 1198 rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); 1199 CU_ASSERT(rc == 0); 1200 1201 rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset); 1202 CU_ASSERT(rc == 0); 1203 1204 rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, &err_blk); 1205 CU_ASSERT(rc != 0); 1206 1207 if (inject_flags == SPDK_DIF_DATA_ERROR) { 1208 CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type); 1209 } else { 1210 CU_ASSERT(inject_flags == err_blk.err_type); 1211 } 1212 CU_ASSERT(inject_offset == err_blk.err_offset); 1213 } 1214 1215 static void 1216 dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, 1217 uint32_t block_size, uint32_t md_size, uint32_t num_blocks, 1218 uint32_t inject_flags) 1219 { 1220 /* The case that DIF is contained in the first 8 bytes of metadata. */ 1221 _dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks, 1222 inject_flags, true); 1223 1224 /* The case that DIF is contained in the last 8 bytes of metadata. */ 1225 _dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks, 1226 inject_flags, false); 1227 } 1228 1229 static void 1230 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void) 1231 { 1232 struct iovec iovs[4], md_iov; 1233 int i, num_blocks; 1234 1235 num_blocks = 0; 1236 1237 for (i = 0; i < 4; i++) { 1238 _iov_alloc_buf(&iovs[i], 4096 * (i + 1)); 1239 num_blocks += i + 1; 1240 } 1241 1242 _iov_alloc_buf(&md_iov, 128 * num_blocks); 1243 1244 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_GUARD_ERROR); 1245 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_APPTAG_ERROR); 1246 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_REFTAG_ERROR); 1247 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_DATA_ERROR); 1248 1249 for (i = 0; i < 4; i++) { 1250 _iov_free_buf(&iovs[i]); 1251 } 1252 _iov_free_buf(&md_iov); 1253 } 1254 1255 static void 1256 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void) 1257 { 1258 struct iovec iovs[4], md_iov; 1259 int i; 1260 1261 _iov_alloc_buf(&iovs[0], 2048); 1262 _iov_alloc_buf(&iovs[1], 2048); 1263 _iov_alloc_buf(&iovs[2], 1); 1264 _iov_alloc_buf(&iovs[3], 4095); 1265 1266 _iov_alloc_buf(&md_iov, 128 * 2); 1267 1268 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_GUARD_ERROR); 1269 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_APPTAG_ERROR); 1270 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_REFTAG_ERROR); 1271 dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_DATA_ERROR); 1272 1273 for (i = 0; i < 4; i++) { 1274 _iov_free_buf(&iovs[i]); 1275 } 1276 _iov_free_buf(&md_iov); 1277 } 1278 1279 int 1280 main(int argc, char **argv) 1281 { 1282 CU_pSuite suite = NULL; 1283 unsigned int num_failures; 1284 1285 if (CU_initialize_registry() != CUE_SUCCESS) { 1286 return CU_get_error(); 1287 } 1288 1289 suite = CU_add_suite("dif", NULL, NULL); 1290 if (suite == NULL) { 1291 CU_cleanup_registry(); 1292 return CU_get_error(); 1293 } 1294 1295 if ( 1296 CU_add_test(suite, "dif_generate_and_verify_test", dif_generate_and_verify_test) == NULL || 1297 CU_add_test(suite, "dif_disable_check_test", dif_disable_check_test) == NULL || 1298 CU_add_test(suite, "dif_sec_512_md_0_error_test", dif_sec_512_md_0_error_test) == NULL || 1299 CU_add_test(suite, "dif_disable_sec_512_md_8_single_iov_test", 1300 dif_disable_sec_512_md_8_single_iov_test) == NULL || 1301 CU_add_test(suite, "dif_sec_512_md_8_prchk_0_single_iov_test", 1302 dif_sec_512_md_8_prchk_0_single_iov_test) == NULL || 1303 CU_add_test(suite, "dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test", 1304 dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test) == NULL || 1305 CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_test", 1306 dif_sec_4096_md_128_prchk_7_multi_iovs_test) == NULL || 1307 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test", 1308 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test) == NULL || 1309 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test", 1310 dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test) == NULL || 1311 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test", 1312 dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test) == NULL || 1313 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test", 1314 dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test) == NULL || 1315 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test", 1316 dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test) == NULL || 1317 CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test", 1318 dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test) == NULL || 1319 CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test", 1320 dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test) == NULL || 1321 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test", 1322 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL || 1323 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test", 1324 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test) == NULL || 1325 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test", 1326 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test) == NULL || 1327 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test", 1328 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test) == NULL || 1329 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8__multi_iovs_split_apptag_test", 1330 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test) == NULL || 1331 CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test", 1332 dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test) == NULL || 1333 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_single_iov", 1334 dif_copy_sec_512_md_8_prchk_0_single_iov) == NULL || 1335 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs", 1336 dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL || 1337 CU_add_test(suite, "dif_copy_sec_4096_md_128_prchk_7_multi_iovs", 1338 dif_copy_sec_4096_md_128_prchk_7_multi_iovs) == NULL || 1339 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data", 1340 dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL || 1341 CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits", 1342 dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL || 1343 CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test", 1344 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL || 1345 CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test", 1346 dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL || 1347 CU_add_test(suite, "dix_sec_512_md_0_error", dix_sec_512_md_0_error) == NULL || 1348 CU_add_test(suite, "dix_sec_512_md_8_prchk_0_single_iov", 1349 dix_sec_512_md_8_prchk_0_single_iov) == NULL || 1350 CU_add_test(suite, "dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs", 1351 dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL || 1352 CU_add_test(suite, "dix_sec_4096_md_128_prchk_7_multi_iovs", 1353 dix_sec_4096_md_128_prchk_7_multi_iovs) == NULL || 1354 CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_split_data", 1355 dix_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL || 1356 CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits", 1357 dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL || 1358 CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test", 1359 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL || 1360 CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test", 1361 dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL 1362 ) { 1363 CU_cleanup_registry(); 1364 return CU_get_error(); 1365 } 1366 1367 CU_basic_set_mode(CU_BRM_VERBOSE); 1368 1369 CU_basic_run_tests(); 1370 1371 num_failures = CU_get_number_of_failures(); 1372 CU_cleanup_registry(); 1373 1374 return num_failures; 1375 } 1376