diff --git a/examples/nvme/fio_plugin/fio_plugin.c b/examples/nvme/fio_plugin/fio_plugin.c index c2fbe622f..f78c1a20a 100644 --- a/examples/nvme/fio_plugin/fio_plugin.c +++ b/examples/nvme/fio_plugin/fio_plugin.c @@ -545,7 +545,7 @@ fio_extended_lba_setup_pi(struct spdk_fio_qpair *fio_qpair, struct io_u *io_u) rc = spdk_dif_ctx_init(&fio_req->dif_ctx, extended_lba_size, md_size, true, false, (enum spdk_dif_type)spdk_nvme_ns_get_pi_type(ns), - fio_qpair->io_flags, lba, 0xFFFF, FIO_NVME_PI_APPTAG); + fio_qpair->io_flags, lba, 0xFFFF, FIO_NVME_PI_APPTAG, 0); if (rc != 0) { fprintf(stderr, "Initialization of DIF context failed\n"); return; diff --git a/examples/nvme/perf/perf.c b/examples/nvme/perf/perf.c index 2e6a34d13..972d148f4 100644 --- a/examples/nvme/perf/perf.c +++ b/examples/nvme/perf/perf.c @@ -469,7 +469,7 @@ nvme_submit_io(struct perf_task *task, struct ns_worker_ctx *ns_ctx, rc = spdk_dif_ctx_init(&task->dif_ctx, entry->block_size, entry->md_size, entry->md_interleave, entry->pi_loc, (enum spdk_dif_type)entry->pi_type, entry->io_flags, - lba, 0xFFFF, (uint16_t)entry->io_size_blocks); + lba, 0xFFFF, (uint16_t)entry->io_size_blocks, 0); if (rc != 0) { fprintf(stderr, "Initialization of DIF context failed\n"); exit(1); diff --git a/include/spdk/dif.h b/include/spdk/dif.h index 7f992cc04..14232f0b1 100644 --- a/include/spdk/dif.h +++ b/include/spdk/dif.h @@ -91,6 +91,9 @@ struct spdk_dif_ctx { /* Application tag mask */ uint16_t apptag_mask; + + /* Seed value for guard computation */ + uint16_t guard_seed; }; /** DIF error information */ @@ -124,12 +127,14 @@ struct spdk_dif_error { * starting block address. * \param apptag_mask Application tag mask. * \param app_tag Application tag. + * \param guard_seed Seed value for guard computation. * * \return 0 on success and negated errno otherwise. */ int spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size, bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, - uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag); + uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag, + uint16_t guard_seed); /** * Generate DIF for extended LBA payload. diff --git a/lib/bdev/nvme/bdev_nvme.c b/lib/bdev/nvme/bdev_nvme.c index bb5a6cf83..4fcd33f99 100644 --- a/lib/bdev/nvme/bdev_nvme.c +++ b/lib/bdev/nvme/bdev_nvme.c @@ -1604,7 +1604,7 @@ bdev_nvme_verify_pi_error(struct spdk_bdev_io *bdev_io) rc = spdk_dif_ctx_init(&dif_ctx, bdev->blocklen, bdev->md_len, bdev->md_interleave, bdev->dif_is_head_of_md, bdev->dif_type, bdev->dif_check_flags, - bdev_io->u.bdev.offset_blocks, 0, 0); + bdev_io->u.bdev.offset_blocks, 0, 0, 0); if (rc != 0) { SPDK_ERRLOG("Initialization of DIF context failed\n"); return; diff --git a/lib/util/dif.c b/lib/util/dif.c index e20b14768..f6cf7e54d 100644 --- a/lib/util/dif.c +++ b/lib/util/dif.c @@ -184,7 +184,8 @@ _get_guard_interval(uint32_t block_size, uint32_t md_size, bool dif_loc, bool md int spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_size, bool md_interleave, bool dif_loc, enum spdk_dif_type dif_type, uint32_t dif_flags, - uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag) + uint32_t init_ref_tag, uint16_t apptag_mask, uint16_t app_tag, + uint16_t guard_seed) { if (md_size < sizeof(struct spdk_dif)) { SPDK_ERRLOG("Metadata size is smaller than DIF size.\n"); @@ -216,6 +217,7 @@ spdk_dif_ctx_init(struct spdk_dif_ctx *ctx, uint32_t block_size, uint32_t md_siz ctx->init_ref_tag = init_ref_tag; ctx->apptag_mask = apptag_mask; ctx->app_tag = app_tag; + ctx->guard_seed = guard_seed; return 0; } @@ -266,7 +268,7 @@ dif_generate(struct iovec *iovs, int iovcnt, uint32_t num_blocks, _iov_iter_get_buf(&iter, &buf, NULL); if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { - guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval); + guard = spdk_crc16_t10dif(ctx->guard_seed, buf, ctx->guard_interval); } _dif_generate(buf + ctx->guard_interval, guard, offset_blocks, ctx); @@ -282,10 +284,12 @@ _dif_generate_split(struct _iov_iter *iter, uint32_t offset_blocks, { uint32_t offset_in_block, offset_in_dif, buf_len; void *buf; - uint16_t guard; + uint16_t guard = 0; struct spdk_dif dif = {}; - guard = 0; + if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = ctx->guard_seed; + } offset_in_block = 0; while (offset_in_block < ctx->block_size) { @@ -491,7 +495,7 @@ dif_verify(struct iovec *iovs, int iovcnt, uint32_t num_blocks, _iov_iter_get_buf(&iter, &buf, NULL); if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { - guard = spdk_crc16_t10dif(0, buf, ctx->guard_interval); + guard = spdk_crc16_t10dif(ctx->guard_seed, buf, ctx->guard_interval); } rc = _dif_verify(buf + ctx->guard_interval, guard, offset_blocks, ctx, err_blk); @@ -512,10 +516,12 @@ _dif_verify_split(struct _iov_iter *iter, uint32_t offset_blocks, { uint32_t offset_in_block, offset_in_dif, buf_len; void *buf; - uint16_t guard; + uint16_t guard = 0; struct spdk_dif dif = {}; - guard = 0; + if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = ctx->guard_seed; + } offset_in_block = 0; while (offset_in_block < ctx->block_size) { @@ -610,7 +616,7 @@ dif_generate_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, guard = 0; if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { - guard = spdk_crc16_t10dif_copy(0, dst, src, data_block_size); + guard = spdk_crc16_t10dif_copy(ctx->guard_seed, dst, src, data_block_size); guard = spdk_crc16_t10dif(guard, dst + data_block_size, ctx->guard_interval - data_block_size); } else { @@ -630,14 +636,16 @@ _dif_generate_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter, uint32_t offset_blocks, const struct spdk_dif_ctx *ctx) { uint32_t offset_in_block, src_len, data_block_size; - uint16_t guard; + uint16_t guard = 0; void *src, *dst; _iov_iter_get_buf(dst_iter, &dst, NULL); data_block_size = ctx->block_size - ctx->md_size; - guard = 0; + if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = ctx->guard_seed; + } offset_in_block = 0; while (offset_in_block < data_block_size) { @@ -736,7 +744,7 @@ dif_verify_copy(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov, guard = 0; if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { - guard = spdk_crc16_t10dif_copy(0, dst, src, data_block_size); + guard = spdk_crc16_t10dif_copy(ctx->guard_seed, dst, src, data_block_size); guard = spdk_crc16_t10dif(guard, src + data_block_size, ctx->guard_interval - data_block_size); } else { @@ -762,14 +770,16 @@ _dif_verify_copy_split(struct _iov_iter *src_iter, struct _iov_iter *dst_iter, struct spdk_dif_error *err_blk) { uint32_t offset_in_block, dst_len, data_block_size; - uint16_t guard; + uint16_t guard = 0; void *src, *dst; _iov_iter_get_buf(src_iter, &src, NULL); data_block_size = ctx->block_size - ctx->md_size; - guard = 0; + if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = ctx->guard_seed; + } offset_in_block = 0; while (offset_in_block < data_block_size) { @@ -1015,7 +1025,7 @@ dix_generate(struct iovec *iovs, int iovcnt, struct iovec *md_iov, guard = 0; if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { - guard = spdk_crc16_t10dif(0, data_buf, ctx->block_size); + guard = spdk_crc16_t10dif(ctx->guard_seed, data_buf, ctx->block_size); guard = spdk_crc16_t10dif(guard, md_buf, ctx->guard_interval); } @@ -1032,12 +1042,14 @@ _dix_generate_split(struct _iov_iter *data_iter, struct _iov_iter *md_iter, uint32_t offset_blocks, const struct spdk_dif_ctx *ctx) { uint32_t offset_in_block, data_buf_len; - uint16_t guard; + uint16_t guard = 0; void *data_buf, *md_buf; _iov_iter_get_buf(md_iter, &md_buf, NULL); - guard = 0; + if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = ctx->guard_seed; + } offset_in_block = 0; while (offset_in_block < ctx->block_size) { @@ -1123,7 +1135,7 @@ dix_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, guard = 0; if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { - guard = spdk_crc16_t10dif(0, data_buf, ctx->block_size); + guard = spdk_crc16_t10dif(ctx->guard_seed, data_buf, ctx->block_size); guard = spdk_crc16_t10dif(guard, md_buf, ctx->guard_interval); } @@ -1146,12 +1158,14 @@ _dix_verify_split(struct _iov_iter *data_iter, struct _iov_iter *md_iter, struct spdk_dif_error *err_blk) { uint32_t offset_in_block, data_buf_len; - uint16_t guard; + uint16_t guard = 0; void *data_buf, *md_buf; _iov_iter_get_buf(md_iter, &md_buf, NULL); - guard = 0; + if (ctx->dif_flags & SPDK_DIF_FLAGS_GUARD_CHECK) { + guard = ctx->guard_seed; + } offset_in_block = 0; while (offset_in_block < ctx->block_size) { diff --git a/test/bdev/bdevperf/bdevperf.c b/test/bdev/bdevperf/bdevperf.c index 77338dcca..0906e95ee 100644 --- a/test/bdev/bdevperf/bdevperf.c +++ b/test/bdev/bdevperf/bdevperf.c @@ -506,7 +506,7 @@ bdevperf_generate_dif(struct bdevperf_task *task) spdk_bdev_is_dif_head_of_md(bdev), spdk_bdev_get_dif_type(bdev), target->dif_check_flags, - task->offset_blocks, 0, 0); + task->offset_blocks, 0, 0, 0); if (rc != 0) { fprintf(stderr, "Initialization of DIF context failed\n"); return rc; diff --git a/test/unit/lib/util/dif.c/dif_ut.c b/test/unit/lib/util/dif.c/dif_ut.c index 40ed3b7b3..de8e67408 100644 --- a/test/unit/lib/util/dif.c/dif_ut.c +++ b/test/unit/lib/util/dif.c/dif_ut.c @@ -38,6 +38,7 @@ #include "util/dif.c" #define DATA_PATTERN 0xAB +#define GUARD_SEED 0xCD static int ut_data_pattern_generate(struct iovec *iovs, int iovcnt, @@ -272,10 +273,57 @@ dif_sec_512_md_0_error_test(void) int rc; /* Metadata size is 0. */ - rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); + rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0); CU_ASSERT(rc != 0); } +static void +dif_guard_seed_test(void) +{ + struct iovec iov; + struct spdk_dif_ctx ctx = {}; + struct spdk_dif_error err_blk = {}; + struct spdk_dif *dif; + uint16_t guard; + int rc; + + _iov_alloc_buf(&iov, 512 + 8); + + memset(iov.iov_base, 0, 512 + 8); + + dif = (struct spdk_dif *)(iov.iov_base + 512); + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, 0); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(&iov, 1, 1, &ctx); + CU_ASSERT(rc == 0); + + /* Guard should be zero if the block is all zero and seed is not added. */ + guard = from_be16(&dif->guard); + CU_ASSERT(guard == 0); + + rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + rc = spdk_dif_ctx_init(&ctx, 512 + 8, 8, true, false, SPDK_DIF_TYPE1, + SPDK_DIF_FLAGS_GUARD_CHECK, 0, 0, 0, GUARD_SEED); + CU_ASSERT(rc == 0); + + rc = spdk_dif_generate(&iov, 1, 1, &ctx); + CU_ASSERT(rc == 0); + + /* Guard should not be zero if the block is all zero but seed is added. */ + guard = from_be16(&dif->guard); + CU_ASSERT(guard != 0); + + rc = spdk_dif_verify(&iov, 1, 1, &ctx, &err_blk); + CU_ASSERT(rc == 0); + + _iov_free_buf(&iov); +} + static void dif_generate_and_verify(struct iovec *iovs, int iovcnt, uint32_t block_size, uint32_t md_size, uint32_t num_blocks, @@ -289,7 +337,7 @@ dif_generate_and_verify(struct iovec *iovs, int iovcnt, CU_ASSERT(rc == 0); rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, - init_ref_tag, apptag_mask, app_tag); + init_ref_tag, apptag_mask, app_tag, GUARD_SEED); CU_ASSERT(rc == 0); rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); @@ -594,7 +642,7 @@ _dif_inject_error_and_verify(struct iovec *iovs, int iovcnt, CU_ASSERT(rc == 0); rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, - SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88); + SPDK_DIF_TYPE1, dif_flags, 88, 0xFFFF, 0x88, GUARD_SEED); CU_ASSERT(rc == 0); rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx); @@ -752,7 +800,7 @@ dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov CU_ASSERT(rc == 0); rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, dif_type, dif_flags, - init_ref_tag, apptag_mask, app_tag); + init_ref_tag, apptag_mask, app_tag, GUARD_SEED); CU_ASSERT(rc == 0); rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); @@ -923,7 +971,7 @@ _dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec * CU_ASSERT(rc == 0); rc = spdk_dif_ctx_init(&ctx, block_size, md_size, true, dif_loc, SPDK_DIF_TYPE1, dif_flags, - 88, 0xFFFF, 0x88); + 88, 0xFFFF, 0x88, GUARD_SEED); SPDK_CU_ASSERT_FATAL(rc == 0); rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx); @@ -1028,7 +1076,7 @@ dix_sec_512_md_0_error(void) struct spdk_dif_ctx ctx; int rc; - rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0); + rc = spdk_dif_ctx_init(&ctx, 512, 0, false, false, SPDK_DIF_TYPE1, 0, 0, 0, 0, 0); CU_ASSERT(rc != 0); } @@ -1045,7 +1093,7 @@ dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov, CU_ASSERT(rc == 0); rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, dif_type, dif_flags, - init_ref_tag, apptag_mask, app_tag); + init_ref_tag, apptag_mask, app_tag, GUARD_SEED); CU_ASSERT(rc == 0); rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); @@ -1211,7 +1259,7 @@ _dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_io CU_ASSERT(rc == 0); rc = spdk_dif_ctx_init(&ctx, block_size, md_size, false, dif_loc, SPDK_DIF_TYPE1, dif_flags, - 88, 0xFFFF, 0x88); + 88, 0xFFFF, 0x88, GUARD_SEED); CU_ASSERT(rc == 0); rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx); @@ -1315,6 +1363,7 @@ main(int argc, char **argv) CU_add_test(suite, "dif_generate_and_verify_test", dif_generate_and_verify_test) == NULL || CU_add_test(suite, "dif_disable_check_test", dif_disable_check_test) == NULL || CU_add_test(suite, "dif_sec_512_md_0_error_test", dif_sec_512_md_0_error_test) == NULL || + CU_add_test(suite, "dif_guard_seed_test", dif_guard_seed_test) == NULL || CU_add_test(suite, "dif_disable_sec_512_md_8_single_iov_test", dif_disable_sec_512_md_8_single_iov_test) == NULL || CU_add_test(suite, "dif_sec_512_md_8_prchk_0_single_iov_test",