diff --git a/CHANGELOG.md b/CHANGELOG.md index 8106a121fb..0f684342af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ A new uuid API `spdk_uuid_copy` was added to make a copy of the source uuid. admin_timeout_ms was added to NVMe controller initialization options, users can change the default value when probing a controller. +Add two new fields "header_digest" and "data_digest" in struct spdk_nvme_ctrlr_opts, +it will be used to enable the digest support for the NVMe/TCP transport. + +Add a new TCP/IP transport(located in lib/nvme/nvme_tcp.c) in nvme driver. With +this new transport, it can be used to connect the NVMe-oF target with the +same TCP/IP support. + ### NVMe-oF Target The `spdk_nvmf_tgt_opts` struct has been deprecated in favor of `spdk_nvmf_transport_opts`. @@ -22,12 +29,6 @@ prior to calling `spdk_nvmf_tgt_listen`. Related to the previous change, the rpc `set_nvmf_target_options` has been renamed to `set_nvmf_target_max_subsystems` to indicate that this is the only target option available for the user to edit. -### nvme - -Add a new TCP/IP transport(located in lib/nvme/nvme_tcp.c) in nvme driver. With -this new transport, it can be used to connect the NVMe-oF target with the -same TCP/IP support. - ### nvmf Add a new TCP/IP transport (located in lib/nvmf/tcp.c). With this tranport, diff --git a/examples/nvme/fio_plugin/fio_plugin.c b/examples/nvme/fio_plugin/fio_plugin.c index bb6a776d47..e0e1cad8fe 100644 --- a/examples/nvme/fio_plugin/fio_plugin.c +++ b/examples/nvme/fio_plugin/fio_plugin.c @@ -60,6 +60,7 @@ struct spdk_fio_options { char *hostnqn; int pi_act; char *pi_chk; + char *digest_enable; }; struct spdk_fio_request { @@ -159,6 +160,17 @@ probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, snprintf(opts->hostnqn, sizeof(opts->hostnqn), "%s", fio_options->hostnqn); } + if (fio_options->digest_enable) { + if (strcasecmp(fio_options->digest_enable, "HEADER") == 0) { + opts->header_digest = true; + } else if (strcasecmp(fio_options->digest_enable, "DATA") == 0) { + opts->data_digest = true; + } else if (strcasecmp(fio_options->digest_enable, "BOTH") == 0) { + opts->header_digest = true; + opts->data_digest = true; + } + } + return true; } @@ -915,6 +927,16 @@ static struct fio_option options[] = { .category = FIO_OPT_C_ENGINE, .group = FIO_OPT_G_INVALID, }, + { + .name = "digest_enable", + .lname = "PDU digest choice for NVMe/TCP Transport(NONE|HEADER|DATA|BOTH)", + .type = FIO_OPT_STR_STORE, + .off1 = offsetof(struct spdk_fio_options, digest_enable), + .def = NULL, + .help = "Control the NVMe/TCP control(digest_enable=NONE|HEADER|DATA|BOTH)", + .category = FIO_OPT_C_ENGINE, + .group = FIO_OPT_G_INVALID, + }, { .name = NULL, }, diff --git a/examples/nvme/perf/perf.c b/examples/nvme/perf/perf.c index f8f4d75e26..8099a8062e 100644 --- a/examples/nvme/perf/perf.c +++ b/examples/nvme/perf/perf.c @@ -182,6 +182,8 @@ static int g_shm_id = -1; static uint32_t g_disable_sq_cmb; static bool g_no_pci; static bool g_warn; +static bool g_header_digest; +static bool g_data_digest; static const char *g_core_mask; @@ -921,6 +923,8 @@ static void usage(char *program_name) printf("\t[-c core mask for I/O submission/completion.]\n"); printf("\t\t(default: 1)]\n"); printf("\t[-D disable submission queue in controller memory buffer, default: enabled]\n"); + printf("\t[-H enable header digest for TCP transport, default: disabled]\n"); + printf("\t[-I enable data digest for TCP transport, default: disabled]\n"); printf("\t[-r Transport ID for local PCIe NVMe or NVMeoF]\n"); printf("\t Format: 'key:value [key:value] ...'\n"); printf("\t Keys:\n"); @@ -1279,7 +1283,7 @@ parse_args(int argc, char **argv) g_core_mask = NULL; g_max_completions = 0; - while ((op = getopt(argc, argv, "c:e:i:lm:o:q:r:s:t:w:DLM:")) != -1) { + while ((op = getopt(argc, argv, "c:e:i:lm:o:q:r:s:t:w:DHILM:")) != -1) { switch (op) { case 'c': g_core_mask = optarg; @@ -1323,6 +1327,12 @@ parse_args(int argc, char **argv) case 'D': g_disable_sq_cmb = 1; break; + case 'H': + g_header_digest = 1; + break; + case 'I': + g_data_digest = 1; + break; case 'L': g_latency_sw_tracking_level++; break; @@ -1494,6 +1504,10 @@ probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid, */ opts->io_queue_size = UINT16_MAX; + /* Set the header and data_digest */ + opts->header_digest = g_header_digest; + opts->data_digest = g_data_digest; + return true; } diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index 3d96f4c536..e034a6aee3 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -167,6 +167,20 @@ struct spdk_nvme_ctrlr_opts { * callback. */ uint32_t admin_timeout_ms; + + /** + * It is used for TCP transport. + * + * Set to true, means having header digest for the header in the NVMe/TCP PDU + */ + bool header_digest; + + /** + * It is used for TCP transport. + * + * Set to true, means having data digest for the data in the NVMe/TCP PDU + */ + bool data_digest; }; /** diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index ec60ce4382..a291d7d923 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -146,6 +146,14 @@ spdk_nvme_ctrlr_get_default_ctrlr_opts(struct spdk_nvme_ctrlr_opts *opts, size_t if (FIELD_OK(admin_timeout_ms)) { opts->admin_timeout_ms = NVME_MAX_TIMEOUT_PERIOD * 1000; } + + if (FIELD_OK(header_digest)) { + opts->header_digest = false; + } + + if (FIELD_OK(data_digest)) { + opts->data_digest = false; + } #undef FIELD_OK } diff --git a/lib/nvme/nvme_tcp.c b/lib/nvme/nvme_tcp.c index bf52b6501a..705cc04fc8 100644 --- a/lib/nvme/nvme_tcp.c +++ b/lib/nvme/nvme_tcp.c @@ -1613,8 +1613,8 @@ nvme_tcp_qpair_icreq_send(struct nvme_tcp_qpair *tqpair) ic_req->maxr2t = NVME_TCP_MAX_R2T_DEFAULT - 1; ic_req->hpda = NVME_TCP_HPDA_DEFAULT; - ic_req->dgst.bits.hdgst_enable = 0; - ic_req->dgst.bits.ddgst_enable = 0; + ic_req->dgst.bits.hdgst_enable = tqpair->qpair.ctrlr->opts.header_digest; + ic_req->dgst.bits.ddgst_enable = tqpair->qpair.ctrlr->opts.data_digest; nvme_tcp_qpair_write_pdu(tqpair, pdu, nvme_tcp_send_icreq_complete, tqpair);