nvmf_tcp: Don't require a data digest for PDUs without data

If a PDU (such as a Command Capsule PDU) on a connection that has
enabled data digests does not have a data section, it will not have
the the PDU data digest flag set.  The previous check was requiring
this flag to be present on all PDU types that support data sections
even if no data was included in the PDU.

Sponsored by:	Chelsio Communications
This commit is contained in:
John Baldwin 2024-07-22 15:38:12 -04:00
parent 7f2411b181
commit 43d45f2641

View File

@ -41,6 +41,13 @@ nvmf_tcp_validate_pdu_header(const struct nvme_tcp_common_pdu_hdr *ch,
uint8_t digest_flags, valid_flags;
plen = le32toh(ch->plen);
full_hlen = ch->hlen;
if ((ch->flags & NVME_TCP_CH_FLAGS_HDGSTF) != 0)
full_hlen += sizeof(uint32_t);
if (plen == full_hlen)
data_len = 0;
else
data_len = plen - ch->pdo;
/*
* Errors must be reported for the lowest incorrect field
@ -125,11 +132,15 @@ nvmf_tcp_validate_pdu_header(const struct nvme_tcp_common_pdu_hdr *ch,
return (EBADMSG);
}
/* Verify that digests are present iff enabled. */
/*
* Verify that digests are present iff enabled. Note that the
* data digest will not be present if there is no data
* payload.
*/
digest_flags = 0;
if (header_digests)
digest_flags |= NVME_TCP_CH_FLAGS_HDGSTF;
if (data_digests)
if (data_digests && data_len != 0)
digest_flags |= NVME_TCP_CH_FLAGS_DDGSTF;
if ((digest_flags & valid_flags) !=
(ch->flags & (NVME_TCP_CH_FLAGS_HDGSTF |
@ -184,9 +195,6 @@ nvmf_tcp_validate_pdu_header(const struct nvme_tcp_common_pdu_hdr *ch,
}
/* Validate pdo. */
full_hlen = ch->hlen;
if ((ch->flags & NVME_TCP_CH_FLAGS_HDGSTF) != 0)
full_hlen += sizeof(uint32_t);
switch (ch->pdu_type) {
default:
__assert_unreachable();
@ -207,7 +215,7 @@ nvmf_tcp_validate_pdu_header(const struct nvme_tcp_common_pdu_hdr *ch,
case NVME_TCP_PDU_TYPE_H2C_DATA:
case NVME_TCP_PDU_TYPE_C2H_DATA:
/* Permit PDO of 0 if there is no data. */
if (full_hlen == plen && ch->pdo == 0)
if (data_len == 0 && ch->pdo == 0)
break;
if (ch->pdo < full_hlen || ch->pdo > plen ||
@ -229,10 +237,6 @@ nvmf_tcp_validate_pdu_header(const struct nvme_tcp_common_pdu_hdr *ch,
return (EBADMSG);
}
if (plen == full_hlen)
data_len = 0;
else
data_len = plen - ch->pdo;
switch (ch->pdu_type) {
default:
__assert_unreachable();