Fix incorrect implementation of HPDA/CPDA in NVMe/TCP target code.

The current implementation treats HPDA/CPDA as the absolute offset
to the beginning of the PDU where the payload data starts. This is
incorrect. The HPDA/CPDA actually specify where the payload data
should start such that the starting location is a multiple of HPDA
(for C2H PDU) or CPDA (for H2C PDU or CapsuleCmd PDU).

The other issue fixed is that the current implementation calculates
padding only when header digest is enabled. This is also incorrect.

Signed-off-by: Wenhua Liu <liuw@vmware.com>
Change-Id: If7a3896a4c1d73f6d062bd3dbe6a912d31771180
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6256
Community-CI: Broadcom CI
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
Wenhua Liu 2021-02-04 08:28:22 +00:00 committed by Tomasz Zawadzki
parent 77573e830e
commit e7f6ff2db6
2 changed files with 12 additions and 11 deletions

View File

@ -618,12 +618,12 @@ nvme_tcp_pdu_calc_psh_len(struct nvme_tcp_pdu *pdu, bool hdgst_enable)
if (g_nvme_tcp_hdgst[pdu->hdr.common.pdu_type] && hdgst_enable) {
pdu->has_hdgst = true;
psh_len += SPDK_NVME_TCP_DIGEST_LEN;
if (pdu->hdr.common.plen > psh_len) {
pdo = pdu->hdr.common.pdo;
padding_len = pdo - psh_len;
if (padding_len > 0) {
psh_len = pdo;
}
}
if (pdu->hdr.common.plen > psh_len) {
pdo = pdu->hdr.common.pdo;
padding_len = pdo - psh_len;
if (padding_len > 0) {
psh_len = pdo;
}
}

View File

@ -1824,7 +1824,7 @@ nvmf_tcp_pdu_ch_handle(struct spdk_nvmf_tcp_qpair *tqpair)
case SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD:
expected_hlen = sizeof(struct spdk_nvme_tcp_cmd);
pdo = pdu->hdr.common.pdo;
if ((tqpair->cpda != 0) && (pdo != ((tqpair->cpda + 1) << 2))) {
if ((tqpair->cpda != 0) && (pdo % ((tqpair->cpda + 1) << 2) != 0)) {
pdo_error = true;
break;
}
@ -1836,7 +1836,7 @@ nvmf_tcp_pdu_ch_handle(struct spdk_nvmf_tcp_qpair *tqpair)
case SPDK_NVME_TCP_PDU_TYPE_H2C_DATA:
expected_hlen = sizeof(struct spdk_nvme_tcp_h2c_data_hdr);
pdo = pdu->hdr.common.pdo;
if ((tqpair->cpda != 0) && (pdo != ((tqpair->cpda + 1) << 2))) {
if ((tqpair->cpda != 0) && (pdo % ((tqpair->cpda + 1) << 2) != 0)) {
pdo_error = true;
break;
}
@ -2216,9 +2216,10 @@ _nvmf_tcp_send_c2h_data(struct spdk_nvmf_tcp_qpair *tqpair,
pdo = plen;
if (tqpair->cpda) {
alignment = (tqpair->cpda + 1) << 2;
if (alignment > plen) {
rsp_pdu->padding_len = alignment - plen;
pdo = plen = alignment;
if (plen % alignment != 0) {
pdo = (plen + alignment) / alignment * alignment;
rsp_pdu->padding_len = pdo - plen;
plen = pdo;
}
}