For separate metadata payload, Introduce a struct to collect DIF error information and pass the reference to the struct to bit-flip error injection and verification. This change will make logging of DIF error and comparison between injection and verification possible for separate metadata payload. Merging this patch to the previous is possible but add this as a separate patch to reduce the patch size. Change-Id: Ifce2130e902bc090cbe205fa8df12559739ced57 Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-on: https://review.gerrithub.io/c/435097 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
1376 lines
40 KiB
C
1376 lines
40 KiB
C
/*-
|
|
* BSD LICENSE
|
|
*
|
|
* Copyright (c) Intel Corporation.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "spdk/stdinc.h"
|
|
|
|
#include "spdk_cunit.h"
|
|
|
|
#include "util/dif.c"
|
|
|
|
#define DATA_PATTERN 0xAB
|
|
|
|
static int
|
|
ut_data_pattern_generate(struct iovec *iovs, int iovcnt,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks)
|
|
{
|
|
struct _iov_iter iter;
|
|
uint32_t offset_blocks, offset_in_block, buf_len;
|
|
void *buf;
|
|
|
|
if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) {
|
|
return -1;
|
|
}
|
|
|
|
offset_blocks = 0;
|
|
_iov_iter_init(&iter, iovs, iovcnt);
|
|
|
|
while (offset_blocks < num_blocks && _iov_iter_cont(&iter)) {
|
|
offset_in_block = 0;
|
|
while (offset_in_block < block_size && _iov_iter_cont(&iter)) {
|
|
_iov_iter_get_buf(&iter, &buf, &buf_len);
|
|
if (offset_in_block < block_size - md_size) {
|
|
buf_len = spdk_min(buf_len,
|
|
block_size - md_size - offset_in_block);
|
|
memset(buf, DATA_PATTERN, buf_len);
|
|
} else {
|
|
buf_len = spdk_min(buf_len, block_size - offset_in_block);
|
|
memset(buf, 0, buf_len);
|
|
}
|
|
_iov_iter_advance(&iter, buf_len);
|
|
offset_in_block += buf_len;
|
|
}
|
|
offset_blocks++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ut_data_pattern_verify(struct iovec *iovs, int iovcnt,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks)
|
|
{
|
|
struct _iov_iter iter;
|
|
uint32_t offset_blocks, offset_in_block, buf_len, i;
|
|
uint8_t *buf;
|
|
|
|
if (!_are_iovs_valid(iovs, iovcnt, block_size * num_blocks)) {
|
|
return -1;
|
|
}
|
|
|
|
offset_blocks = 0;
|
|
_iov_iter_init(&iter, iovs, iovcnt);
|
|
|
|
while (offset_blocks < num_blocks && _iov_iter_cont(&iter)) {
|
|
offset_in_block = 0;
|
|
while (offset_in_block < block_size && _iov_iter_cont(&iter)) {
|
|
_iov_iter_get_buf(&iter, (void *)&buf, &buf_len);
|
|
|
|
if (offset_in_block < block_size - md_size) {
|
|
buf_len = spdk_min(buf_len,
|
|
block_size - md_size - offset_in_block);
|
|
for (i = 0; i < buf_len; i++) {
|
|
if (buf[i] != DATA_PATTERN) {
|
|
return -1;
|
|
}
|
|
}
|
|
} else {
|
|
buf_len = spdk_min(buf_len, block_size - offset_in_block);
|
|
}
|
|
_iov_iter_advance(&iter, buf_len);
|
|
offset_in_block += buf_len;
|
|
}
|
|
offset_blocks++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
_iov_alloc_buf(struct iovec *iov, uint32_t len)
|
|
{
|
|
iov->iov_base = calloc(1, len);
|
|
iov->iov_len = len;
|
|
SPDK_CU_ASSERT_FATAL(iov->iov_base != NULL);
|
|
}
|
|
|
|
static void
|
|
_iov_free_buf(struct iovec *iov)
|
|
{
|
|
free(iov->iov_base);
|
|
}
|
|
|
|
static void
|
|
_dif_generate_and_verify(struct iovec *iov,
|
|
uint32_t block_size, uint32_t md_size, bool dif_loc,
|
|
enum spdk_dif_type dif_type, uint32_t dif_flags,
|
|
uint32_t ref_tag, uint32_t e_ref_tag,
|
|
uint16_t app_tag, uint16_t apptag_mask, uint16_t e_app_tag,
|
|
bool expect_pass)
|
|
{
|
|
struct spdk_dif_ctx ctx = {};
|
|
uint32_t guard_interval;
|
|
uint16_t guard = 0;
|
|
int rc;
|
|
|
|
rc = ut_data_pattern_generate(iov, 1, block_size, md_size, 1);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
guard_interval = _get_guard_interval(block_size, md_size, dif_loc, true);
|
|
|
|
ctx.dif_type = dif_type;
|
|
ctx.dif_flags = dif_flags;
|
|
ctx.init_ref_tag = ref_tag;
|
|
ctx.app_tag = app_tag;
|
|
|
|
if (dif_flags & SPDK_DIF_GUARD_CHECK) {
|
|
guard = spdk_crc16_t10dif(0, iov->iov_base, guard_interval);
|
|
}
|
|
|
|
_dif_generate(iov->iov_base + guard_interval, guard, 0, &ctx);
|
|
|
|
ctx.init_ref_tag = e_ref_tag;
|
|
ctx.apptag_mask = apptag_mask;
|
|
ctx.app_tag = e_app_tag;
|
|
|
|
rc = _dif_verify(iov->iov_base + guard_interval, guard, 0, &ctx, NULL);
|
|
CU_ASSERT((expect_pass && rc == 0) || (!expect_pass && rc != 0));
|
|
|
|
rc = ut_data_pattern_verify(iov, 1, block_size, md_size, 1);
|
|
CU_ASSERT(rc == 0);
|
|
}
|
|
|
|
static void
|
|
dif_generate_and_verify_test(void)
|
|
{
|
|
struct iovec iov;
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iov, 4096 + 128);
|
|
|
|
/* Positive cases */
|
|
|
|
/* The case that DIF is contained in the first 8 bytes of metadata. */
|
|
_dif_generate_and_verify(&iov,
|
|
4096 + 128, 128, false,
|
|
SPDK_DIF_TYPE1, dif_flags,
|
|
22, 22,
|
|
0x22, 0xFFFF, 0x22,
|
|
true);
|
|
|
|
/* The case that DIF is contained in the last 8 bytes of metadata. */
|
|
_dif_generate_and_verify(&iov,
|
|
4096 + 128, 128, true,
|
|
SPDK_DIF_TYPE1, dif_flags,
|
|
22, 22,
|
|
0x22, 0xFFFF, 0x22,
|
|
true);
|
|
|
|
/* Negative cases */
|
|
|
|
/* Reference tag doesn't match. */
|
|
_dif_generate_and_verify(&iov,
|
|
4096 + 128, 128, false,
|
|
SPDK_DIF_TYPE1, dif_flags,
|
|
22, 23,
|
|
0x22, 0xFFFF, 0x22,
|
|
false);
|
|
|
|
/* Application tag doesn't match. */
|
|
_dif_generate_and_verify(&iov,
|
|
4096 + 128, 128, false,
|
|
SPDK_DIF_TYPE1, dif_flags,
|
|
22, 22,
|
|
0x22, 0xFFFF, 0x23,
|
|
false);
|
|
|
|
_iov_free_buf(&iov);
|
|
}
|
|
|
|
static void
|
|
dif_disable_check_test(void)
|
|
{
|
|
struct iovec iov;
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iov, 4096 + 128);
|
|
|
|
/* The case that DIF check is disabled when the Application Tag is 0xFFFF for
|
|
* Type 1. DIF check is disabled and pass is expected.
|
|
*/
|
|
_dif_generate_and_verify(&iov,
|
|
4096 + 128, 128, false,
|
|
SPDK_DIF_TYPE1, dif_flags,
|
|
22, 22,
|
|
0xFFFF, 0xFFFF, 0x22,
|
|
true);
|
|
|
|
/* The case that DIF check is not disabled when the Application Tag is 0xFFFF but
|
|
* the Reference Tag is not 0xFFFFFFFF for Type 3. DIF check is not disabled and
|
|
* fail is expected.
|
|
*/
|
|
_dif_generate_and_verify(&iov,
|
|
4096 + 128, 128, false,
|
|
SPDK_DIF_TYPE3, dif_flags,
|
|
22, 22,
|
|
0xFFFF, 0xFFFF, 0x22,
|
|
false);
|
|
|
|
/* The case that DIF check is disabled when the Application Tag is 0xFFFF and
|
|
* the Reference Tag is 0xFFFFFFFF for Type 3. DIF check is disabled and
|
|
* pass is expected.
|
|
*/
|
|
_dif_generate_and_verify(&iov,
|
|
4096 + 128, 128, false,
|
|
SPDK_DIF_TYPE3, dif_flags,
|
|
0xFFFFFFFF, 22,
|
|
0xFFFF, 0xFFFF, 0x22,
|
|
true);
|
|
|
|
_iov_free_buf(&iov);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_0_error_test(void)
|
|
{
|
|
struct spdk_dif_ctx ctx = {};
|
|
int rc;
|
|
|
|
/* Metadata size is 0. */
|
|
rc = spdk_dif_ctx_init(&ctx, 512, 0, true, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
|
|
CU_ASSERT(rc != 0);
|
|
}
|
|
|
|
static void
|
|
dif_generate_and_verify(struct iovec *iovs, int iovcnt,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
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)
|
|
{
|
|
struct spdk_dif_ctx ctx = {};
|
|
int rc;
|
|
|
|
rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
|
|
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);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, NULL);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
|
|
CU_ASSERT(rc == 0);
|
|
}
|
|
|
|
static void
|
|
dif_disable_sec_512_md_8_single_iov_test(void)
|
|
{
|
|
struct iovec iov;
|
|
|
|
_iov_alloc_buf(&iov, (512 + 8) * 4);
|
|
|
|
dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_DISABLE, 0, 0, 0, 0);
|
|
|
|
_iov_free_buf(&iov);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_0_single_iov_test(void)
|
|
{
|
|
struct iovec iov;
|
|
|
|
_iov_alloc_buf(&iov, (512 + 8) * 4);
|
|
|
|
dif_generate_and_verify(&iov, 1, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
|
|
|
|
_iov_free_buf(&iov);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test(void)
|
|
{
|
|
struct iovec iovs[4];
|
|
int i, num_blocks;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], (512 + 8) * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
|
|
dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
0, 22, 0xFFFF, 0x22);
|
|
|
|
dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
SPDK_DIF_GUARD_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
SPDK_DIF_APPTAG_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
dif_generate_and_verify(iovs, 4, 512 + 8, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
SPDK_DIF_REFTAG_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_prchk_7_multi_iovs_test(void)
|
|
{
|
|
struct iovec iovs[4];
|
|
int i, num_blocks;
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
|
|
dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
dif_generate_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, true, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iovs[0], 512);
|
|
_iov_alloc_buf(&iovs[1], 8);
|
|
|
|
dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iovs[0], 256);
|
|
_iov_alloc_buf(&iovs[1], 264);
|
|
|
|
dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iovs[0], 513);
|
|
_iov_alloc_buf(&iovs[1], 7);
|
|
|
|
dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iovs[0], 515);
|
|
_iov_alloc_buf(&iovs[1], 5);
|
|
|
|
dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iovs[0], 518);
|
|
_iov_alloc_buf(&iovs[1], 2);
|
|
|
|
dif_generate_and_verify(iovs, 2, 512 + 8, 8, 1, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test(void)
|
|
{
|
|
struct iovec iovs[9];
|
|
uint32_t dif_flags;
|
|
int i;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
/* data[0][255:0] */
|
|
_iov_alloc_buf(&iovs[0], 256);
|
|
|
|
/* data[0][511:256], guard[0][0] */
|
|
_iov_alloc_buf(&iovs[1], 256 + 1);
|
|
|
|
/* guard[0][1], apptag[0][0] */
|
|
_iov_alloc_buf(&iovs[2], 1 + 1);
|
|
|
|
/* apptag[0][1], reftag[0][0] */
|
|
_iov_alloc_buf(&iovs[3], 1 + 1);
|
|
|
|
/* reftag[0][3:1], data[1][255:0] */
|
|
_iov_alloc_buf(&iovs[4], 3 + 256);
|
|
|
|
/* data[1][511:256], guard[1][0] */
|
|
_iov_alloc_buf(&iovs[5], 256 + 1);
|
|
|
|
/* guard[1][1], apptag[1][0] */
|
|
_iov_alloc_buf(&iovs[6], 1 + 1);
|
|
|
|
/* apptag[1][1], reftag[1][0] */
|
|
_iov_alloc_buf(&iovs[7], 1 + 1);
|
|
|
|
/* reftag[1][3:1] */
|
|
_iov_alloc_buf(&iovs[8], 3);
|
|
|
|
dif_generate_and_verify(iovs, 9, 512 + 8, 8, 2, false, SPDK_DIF_TYPE1, dif_flags,
|
|
22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test(void)
|
|
{
|
|
struct iovec iovs[11];
|
|
uint32_t dif_flags;
|
|
int i;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
/* data[0][1000:0] */
|
|
_iov_alloc_buf(&iovs[0], 1000);
|
|
|
|
/* data[0][3095:1000], guard[0][0] */
|
|
_iov_alloc_buf(&iovs[1], 3096 + 1);
|
|
|
|
/* guard[0][1], apptag[0][0] */
|
|
_iov_alloc_buf(&iovs[2], 1 + 1);
|
|
|
|
/* apptag[0][1], reftag[0][0] */
|
|
_iov_alloc_buf(&iovs[3], 1 + 1);
|
|
|
|
/* reftag[0][3:1], ignore[0][59:0] */
|
|
_iov_alloc_buf(&iovs[4], 3 + 60);
|
|
|
|
/* ignore[119:60], data[1][3050:0] */
|
|
_iov_alloc_buf(&iovs[5], 60 + 3051);
|
|
|
|
/* data[1][4095:3050], guard[1][0] */
|
|
_iov_alloc_buf(&iovs[6], 1045 + 1);
|
|
|
|
/* guard[1][1], apptag[1][0] */
|
|
_iov_alloc_buf(&iovs[7], 1 + 1);
|
|
|
|
/* apptag[1][1], reftag[1][0] */
|
|
_iov_alloc_buf(&iovs[8], 1 + 1);
|
|
|
|
/* reftag[1][3:1], ignore[1][9:0] */
|
|
_iov_alloc_buf(&iovs[9], 3 + 10);
|
|
|
|
/* ignore[1][127:9] */
|
|
_iov_alloc_buf(&iovs[10], 118);
|
|
|
|
dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, false, SPDK_DIF_TYPE1, dif_flags,
|
|
22, 0xFFFF, 0x22);
|
|
dif_generate_and_verify(iovs, 11, 4096 + 128, 128, 2, true, SPDK_DIF_TYPE1, dif_flags,
|
|
22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 11; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
uint32_t inject_flags, bool dif_loc)
|
|
{
|
|
struct spdk_dif_ctx ctx = {};
|
|
struct spdk_dif_error err_blk = {};
|
|
uint32_t inject_offset = 0, dif_flags;
|
|
int rc;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
rc = ut_data_pattern_generate(iovs, iovcnt, block_size, md_size, num_blocks);
|
|
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);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_generate(iovs, iovcnt, num_blocks, &ctx);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_inject_error(iovs, iovcnt, num_blocks, &ctx, inject_flags, &inject_offset);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_verify(iovs, iovcnt, num_blocks, &ctx, &err_blk);
|
|
CU_ASSERT(rc != 0);
|
|
if (inject_flags == SPDK_DIF_DATA_ERROR) {
|
|
CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
|
|
} else {
|
|
CU_ASSERT(inject_flags == err_blk.err_type);
|
|
}
|
|
CU_ASSERT(inject_offset == err_blk.err_offset);
|
|
|
|
rc = ut_data_pattern_verify(iovs, iovcnt, block_size, md_size, num_blocks);
|
|
CU_ASSERT((rc == 0 && (inject_flags != SPDK_DIF_DATA_ERROR)) ||
|
|
(rc != 0 && (inject_flags == SPDK_DIF_DATA_ERROR)));
|
|
}
|
|
|
|
static void
|
|
dif_inject_error_and_verify(struct iovec *iovs, int iovcnt,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
uint32_t inject_flags)
|
|
{
|
|
/* The case that DIF is contained in the first 8 bytes of metadata. */
|
|
_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
|
|
inject_flags, false);
|
|
|
|
/* The case that DIF is contained in the last 8 bytes of metadata. */
|
|
_dif_inject_error_and_verify(iovs, iovcnt, block_size, md_size, num_blocks,
|
|
inject_flags, true);
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
|
|
{
|
|
struct iovec iovs[4];
|
|
int i, num_blocks;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], (4096 + 128) * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
|
|
dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_GUARD_ERROR);
|
|
dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_APPTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_REFTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 4, 4096 + 128, 128, num_blocks, SPDK_DIF_DATA_ERROR);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
|
|
_iov_alloc_buf(&iovs[0], 4096);
|
|
_iov_alloc_buf(&iovs[1], 128);
|
|
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
|
|
_iov_alloc_buf(&iovs[0], 2048);
|
|
_iov_alloc_buf(&iovs[1], 2048 + 128);
|
|
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
|
|
_iov_alloc_buf(&iovs[0], 4096 + 1);
|
|
_iov_alloc_buf(&iovs[1], 127);
|
|
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
|
|
_iov_alloc_buf(&iovs[0], 4096 + 3);
|
|
_iov_alloc_buf(&iovs[1], 125);
|
|
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test(void)
|
|
{
|
|
struct iovec iovs[2];
|
|
|
|
_iov_alloc_buf(&iovs[0], 4096 + 6);
|
|
_iov_alloc_buf(&iovs[1], 122);
|
|
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_GUARD_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_APPTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_REFTAG_ERROR);
|
|
dif_inject_error_and_verify(iovs, 2, 4096 + 128, 128, 1, SPDK_DIF_DATA_ERROR);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
}
|
|
|
|
static void
|
|
dif_copy_gen_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
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)
|
|
{
|
|
struct spdk_dif_ctx ctx = {};
|
|
int rc;
|
|
|
|
rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
|
|
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);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, NULL);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = ut_data_pattern_verify(iovs, iovcnt, block_size - md_size, 0, num_blocks);
|
|
CU_ASSERT(rc == 0);
|
|
}
|
|
|
|
static void
|
|
dif_copy_sec_512_md_8_prchk_0_single_iov(void)
|
|
{
|
|
struct iovec iov, bounce_iov;
|
|
|
|
_iov_alloc_buf(&iov, 512 * 4);
|
|
_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
|
|
|
|
dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4,
|
|
false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
|
|
dif_copy_gen_and_verify(&iov, 1, &bounce_iov, 512 + 8, 8, 4,
|
|
true, SPDK_DIF_TYPE1, 0, 0, 0, 0);
|
|
|
|
_iov_free_buf(&iov);
|
|
_iov_free_buf(&bounce_iov);
|
|
}
|
|
|
|
static void
|
|
dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
|
|
{
|
|
struct iovec iovs[4], bounce_iov;
|
|
int i, num_blocks;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], 512 * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
|
|
_iov_alloc_buf(&bounce_iov, (512 + 8) * num_blocks);
|
|
|
|
dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
|
|
false, SPDK_DIF_TYPE1, 0, 22, 0xFFFF, 0x22);
|
|
|
|
dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
|
|
false, SPDK_DIF_TYPE1, SPDK_DIF_GUARD_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
|
|
false, SPDK_DIF_TYPE1, SPDK_DIF_APPTAG_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 512 + 8, 8, num_blocks,
|
|
false, SPDK_DIF_TYPE1, SPDK_DIF_REFTAG_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&bounce_iov);
|
|
}
|
|
|
|
static void
|
|
dif_copy_sec_4096_md_128_prchk_7_multi_iovs(void)
|
|
{
|
|
struct iovec iovs[4], bounce_iov;
|
|
uint32_t dif_flags;
|
|
int i, num_blocks;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
|
|
_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
|
|
|
|
dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks,
|
|
false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
|
|
dif_copy_gen_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128, num_blocks,
|
|
true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&bounce_iov);
|
|
}
|
|
|
|
static void
|
|
dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
|
|
{
|
|
struct iovec iovs[2], bounce_iov;
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iovs[0], 256);
|
|
_iov_alloc_buf(&iovs[1], 256);
|
|
|
|
_iov_alloc_buf(&bounce_iov, 512 + 8);
|
|
|
|
dif_copy_gen_and_verify(iovs, 2, &bounce_iov, 512 + 8, 8, 1,
|
|
false, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
_iov_free_buf(&bounce_iov);
|
|
}
|
|
|
|
static void
|
|
dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
|
|
{
|
|
struct iovec iovs[6], bounce_iov;
|
|
uint32_t dif_flags;
|
|
int i;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
/* data[0][255:0] */
|
|
_iov_alloc_buf(&iovs[0], 256);
|
|
|
|
/* data[0][511:256], data[1][255:0] */
|
|
_iov_alloc_buf(&iovs[1], 256 + 256);
|
|
|
|
/* data[1][382:256] */
|
|
_iov_alloc_buf(&iovs[2], 128);
|
|
|
|
/* data[1][383] */
|
|
_iov_alloc_buf(&iovs[3], 1);
|
|
|
|
/* data[1][510:384] */
|
|
_iov_alloc_buf(&iovs[4], 126);
|
|
|
|
/* data[1][511], data[2][511:0], data[3][511:0] */
|
|
_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
|
|
|
|
_iov_alloc_buf(&bounce_iov, (512 + 8) * 4);
|
|
|
|
dif_copy_gen_and_verify(iovs, 6, &bounce_iov, 512 + 8, 8, 4,
|
|
true, SPDK_DIF_TYPE1, dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&bounce_iov);
|
|
}
|
|
|
|
static void
|
|
_dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
uint32_t inject_flags, bool dif_loc)
|
|
{
|
|
struct spdk_dif_ctx ctx = {};
|
|
struct spdk_dif_error err_blk = {};
|
|
uint32_t inject_offset = 0, dif_flags;
|
|
int rc;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
rc = ut_data_pattern_generate(iovs, iovcnt, block_size - md_size, 0, num_blocks);
|
|
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_CU_ASSERT_FATAL(rc == 0);
|
|
|
|
rc = spdk_dif_generate_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_inject_error(bounce_iov, 1, num_blocks, &ctx, inject_flags, &inject_offset);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dif_verify_copy(iovs, iovcnt, bounce_iov, num_blocks, &ctx, &err_blk);
|
|
CU_ASSERT(rc != 0);
|
|
if (inject_flags == SPDK_DIF_DATA_ERROR) {
|
|
CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
|
|
} else {
|
|
CU_ASSERT(inject_flags == err_blk.err_type);
|
|
}
|
|
CU_ASSERT(inject_offset == err_blk.err_offset);
|
|
}
|
|
|
|
static void
|
|
dif_copy_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *bounce_iov,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
uint32_t inject_flags)
|
|
{
|
|
/* The case that DIF is contained in the first 8 bytes of metadata. */
|
|
_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
|
|
block_size, md_size, num_blocks,
|
|
inject_flags, false);
|
|
|
|
/* The case that DIF is contained in the last 8 bytes of metadata. */
|
|
_dif_copy_inject_error_and_verify(iovs, iovcnt, bounce_iov,
|
|
block_size, md_size, num_blocks,
|
|
inject_flags, true);
|
|
}
|
|
|
|
static void
|
|
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
|
|
{
|
|
struct iovec iovs[4], bounce_iov;
|
|
int i, num_blocks;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
|
|
_iov_alloc_buf(&bounce_iov, (4096 + 128) * num_blocks);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
num_blocks, SPDK_DIF_GUARD_ERROR);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
num_blocks, SPDK_DIF_APPTAG_ERROR);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
num_blocks, SPDK_DIF_REFTAG_ERROR);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
num_blocks, SPDK_DIF_DATA_ERROR);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&bounce_iov);
|
|
}
|
|
|
|
static void
|
|
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
|
|
{
|
|
struct iovec iovs[4], bounce_iov;
|
|
int i;
|
|
|
|
_iov_alloc_buf(&iovs[0], 2048);
|
|
_iov_alloc_buf(&iovs[1], 2048);
|
|
_iov_alloc_buf(&iovs[2], 1);
|
|
_iov_alloc_buf(&iovs[3], 4095);
|
|
|
|
_iov_alloc_buf(&bounce_iov, (4096 + 128) * 2);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
2, SPDK_DIF_GUARD_ERROR);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
2, SPDK_DIF_APPTAG_ERROR);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
2, SPDK_DIF_REFTAG_ERROR);
|
|
|
|
dif_copy_inject_error_and_verify(iovs, 4, &bounce_iov, 4096 + 128, 128,
|
|
2, SPDK_DIF_DATA_ERROR);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&bounce_iov);
|
|
}
|
|
|
|
static void
|
|
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);
|
|
CU_ASSERT(rc != 0);
|
|
}
|
|
|
|
static void
|
|
dix_generate_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
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)
|
|
{
|
|
struct spdk_dif_ctx ctx;
|
|
int rc;
|
|
|
|
rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
|
|
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);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, NULL);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = ut_data_pattern_verify(iovs, iovcnt, block_size, 0, num_blocks);
|
|
CU_ASSERT(rc == 0);
|
|
}
|
|
|
|
static void
|
|
dix_sec_512_md_8_prchk_0_single_iov(void)
|
|
{
|
|
struct iovec iov, md_iov;
|
|
|
|
_iov_alloc_buf(&iov, 512 * 4);
|
|
_iov_alloc_buf(&md_iov, 8 * 4);
|
|
|
|
dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1, 0, 0, 0, 0);
|
|
dix_generate_and_verify(&iov, 1, &md_iov, 512, 8, 4, true, SPDK_DIF_TYPE1, 0, 0, 0, 0);
|
|
|
|
_iov_free_buf(&iov);
|
|
_iov_free_buf(&md_iov);
|
|
}
|
|
|
|
static void
|
|
dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs(void)
|
|
{
|
|
struct iovec iovs[4], md_iov;
|
|
int i, num_blocks;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], 512 * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
_iov_alloc_buf(&md_iov, 8 * num_blocks);
|
|
|
|
dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
0, 22, 0xFFFF, 0x22);
|
|
|
|
dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
SPDK_DIF_GUARD_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
SPDK_DIF_APPTAG_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
dix_generate_and_verify(iovs, 4, &md_iov, 512, 8, num_blocks, false, SPDK_DIF_TYPE1,
|
|
SPDK_DIF_REFTAG_CHECK, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&md_iov);
|
|
}
|
|
|
|
static void
|
|
dix_sec_4096_md_128_prchk_7_multi_iovs(void)
|
|
{
|
|
struct iovec iovs[4], md_iov;
|
|
uint32_t dif_flags;
|
|
int i, num_blocks;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
_iov_alloc_buf(&md_iov, 128 * num_blocks);
|
|
|
|
dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
dix_generate_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, true, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&md_iov);
|
|
}
|
|
|
|
static void
|
|
dix_sec_512_md_8_prchk_7_multi_iovs_split_data(void)
|
|
{
|
|
struct iovec iovs[2], md_iov;
|
|
uint32_t dif_flags;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
_iov_alloc_buf(&iovs[0], 256);
|
|
_iov_alloc_buf(&iovs[1], 256);
|
|
_iov_alloc_buf(&md_iov, 8);
|
|
|
|
dix_generate_and_verify(iovs, 2, &md_iov, 512, 8, 1, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
_iov_free_buf(&iovs[0]);
|
|
_iov_free_buf(&iovs[1]);
|
|
_iov_free_buf(&md_iov);
|
|
}
|
|
|
|
static void
|
|
dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits(void)
|
|
{
|
|
struct iovec iovs[6], md_iov;
|
|
uint32_t dif_flags;
|
|
int i;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
/* data[0][255:0] */
|
|
_iov_alloc_buf(&iovs[0], 256);
|
|
|
|
/* data[0][511:256], data[1][255:0] */
|
|
_iov_alloc_buf(&iovs[1], 256 + 256);
|
|
|
|
/* data[1][382:256] */
|
|
_iov_alloc_buf(&iovs[2], 128);
|
|
|
|
/* data[1][383] */
|
|
_iov_alloc_buf(&iovs[3], 1);
|
|
|
|
/* data[1][510:384] */
|
|
_iov_alloc_buf(&iovs[4], 126);
|
|
|
|
/* data[1][511], data[2][511:0], data[3][511:0] */
|
|
_iov_alloc_buf(&iovs[5], 1 + 512 * 2);
|
|
|
|
_iov_alloc_buf(&md_iov, 8 * 4);
|
|
|
|
dix_generate_and_verify(iovs, 6, &md_iov, 512, 8, 4, false, SPDK_DIF_TYPE1,
|
|
dif_flags, 22, 0xFFFF, 0x22);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&md_iov);
|
|
}
|
|
|
|
static void
|
|
_dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
uint32_t inject_flags, bool dif_loc)
|
|
{
|
|
struct spdk_dif_ctx ctx = {};
|
|
struct spdk_dif_error err_blk = {};
|
|
uint32_t inject_offset = 0, dif_flags;
|
|
int rc;
|
|
|
|
dif_flags = SPDK_DIF_GUARD_CHECK | SPDK_DIF_APPTAG_CHECK | SPDK_DIF_REFTAG_CHECK;
|
|
|
|
rc = ut_data_pattern_generate(iovs, iovcnt, block_size, 0, num_blocks);
|
|
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);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dix_generate(iovs, iovcnt, md_iov, num_blocks, &ctx);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dix_inject_error(iovs, iovcnt, md_iov, num_blocks, &ctx, inject_flags, &inject_offset);
|
|
CU_ASSERT(rc == 0);
|
|
|
|
rc = spdk_dix_verify(iovs, iovcnt, md_iov, num_blocks, &ctx, &err_blk);
|
|
CU_ASSERT(rc != 0);
|
|
|
|
if (inject_flags == SPDK_DIF_DATA_ERROR) {
|
|
CU_ASSERT(SPDK_DIF_GUARD_ERROR == err_blk.err_type);
|
|
} else {
|
|
CU_ASSERT(inject_flags == err_blk.err_type);
|
|
}
|
|
CU_ASSERT(inject_offset == err_blk.err_offset);
|
|
}
|
|
|
|
static void
|
|
dix_inject_error_and_verify(struct iovec *iovs, int iovcnt, struct iovec *md_iov,
|
|
uint32_t block_size, uint32_t md_size, uint32_t num_blocks,
|
|
uint32_t inject_flags)
|
|
{
|
|
/* The case that DIF is contained in the first 8 bytes of metadata. */
|
|
_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
|
|
inject_flags, false);
|
|
|
|
/* The case that DIF is contained in the last 8 bytes of metadata. */
|
|
_dix_inject_error_and_verify(iovs, iovcnt, md_iov, block_size, md_size, num_blocks,
|
|
inject_flags, true);
|
|
}
|
|
|
|
static void
|
|
dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test(void)
|
|
{
|
|
struct iovec iovs[4], md_iov;
|
|
int i, num_blocks;
|
|
|
|
num_blocks = 0;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_alloc_buf(&iovs[i], 4096 * (i + 1));
|
|
num_blocks += i + 1;
|
|
}
|
|
|
|
_iov_alloc_buf(&md_iov, 128 * num_blocks);
|
|
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_GUARD_ERROR);
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_APPTAG_ERROR);
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_REFTAG_ERROR);
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, num_blocks, SPDK_DIF_DATA_ERROR);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&md_iov);
|
|
}
|
|
|
|
static void
|
|
dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test(void)
|
|
{
|
|
struct iovec iovs[4], md_iov;
|
|
int i;
|
|
|
|
_iov_alloc_buf(&iovs[0], 2048);
|
|
_iov_alloc_buf(&iovs[1], 2048);
|
|
_iov_alloc_buf(&iovs[2], 1);
|
|
_iov_alloc_buf(&iovs[3], 4095);
|
|
|
|
_iov_alloc_buf(&md_iov, 128 * 2);
|
|
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_GUARD_ERROR);
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_APPTAG_ERROR);
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_REFTAG_ERROR);
|
|
dix_inject_error_and_verify(iovs, 4, &md_iov, 4096, 128, 2, SPDK_DIF_DATA_ERROR);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
_iov_free_buf(&iovs[i]);
|
|
}
|
|
_iov_free_buf(&md_iov);
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
CU_pSuite suite = NULL;
|
|
unsigned int num_failures;
|
|
|
|
if (CU_initialize_registry() != CUE_SUCCESS) {
|
|
return CU_get_error();
|
|
}
|
|
|
|
suite = CU_add_suite("dif", NULL, NULL);
|
|
if (suite == NULL) {
|
|
CU_cleanup_registry();
|
|
return CU_get_error();
|
|
}
|
|
|
|
if (
|
|
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_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",
|
|
dif_sec_512_md_8_prchk_0_single_iov_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test",
|
|
dif_sec_512_md_8_prchk_0_1_2_4_multi_iovs_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_test",
|
|
dif_sec_4096_md_128_prchk_7_multi_iovs_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test",
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_data_and_md_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test",
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_data_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test",
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_guard_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test",
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_apptag_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test",
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_split_reftag_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test",
|
|
dif_sec_512_md_8_prchk_7_multi_iovs_complex_splits_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test",
|
|
dif_sec_4096_md_128_prchk_7_multi_iovs_complex_splits_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test",
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_and_md_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test",
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_data_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test",
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_guard_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8__multi_iovs_split_apptag_test",
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_apptag_test) == NULL ||
|
|
CU_add_test(suite, "dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test",
|
|
dif_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_reftag_test) == NULL ||
|
|
CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_single_iov",
|
|
dif_copy_sec_512_md_8_prchk_0_single_iov) == NULL ||
|
|
CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs",
|
|
dif_copy_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL ||
|
|
CU_add_test(suite, "dif_copy_sec_4096_md_128_prchk_7_multi_iovs",
|
|
dif_copy_sec_4096_md_128_prchk_7_multi_iovs) == NULL ||
|
|
CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data",
|
|
dif_copy_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL ||
|
|
CU_add_test(suite, "dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits",
|
|
dif_copy_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL ||
|
|
CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
|
|
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
|
|
CU_add_test(suite, "dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test",
|
|
dif_copy_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL ||
|
|
CU_add_test(suite, "dix_sec_512_md_0_error", dix_sec_512_md_0_error) == NULL ||
|
|
CU_add_test(suite, "dix_sec_512_md_8_prchk_0_single_iov",
|
|
dix_sec_512_md_8_prchk_0_single_iov) == NULL ||
|
|
CU_add_test(suite, "dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs",
|
|
dix_sec_512_md_8_prchk_0_1_2_4_multi_iovs) == NULL ||
|
|
CU_add_test(suite, "dix_sec_4096_md_128_prchk_7_multi_iovs",
|
|
dix_sec_4096_md_128_prchk_7_multi_iovs) == NULL ||
|
|
CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_split_data",
|
|
dix_sec_512_md_8_prchk_7_multi_iovs_split_data) == NULL ||
|
|
CU_add_test(suite, "dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits",
|
|
dix_sec_512_md_8_prchk_7_multi_iovs_complex_splits) == NULL ||
|
|
CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test",
|
|
dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_test) == NULL ||
|
|
CU_add_test(suite, "dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test",
|
|
dix_sec_4096_md_128_inject_1_2_4_8_multi_iovs_split_test) == NULL
|
|
) {
|
|
CU_cleanup_registry();
|
|
return CU_get_error();
|
|
}
|
|
|
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
|
|
|
CU_basic_run_tests();
|
|
|
|
num_failures = CU_get_number_of_failures();
|
|
CU_cleanup_registry();
|
|
|
|
return num_failures;
|
|
}
|