iscsi: refactor and simplify digest calculations

Factor out the common PDU header and data digest calculations into
helper functions in iscsi.c.  This eliminates the need for the crc32c.c
iSCSI-specific padding functions spdk_fixup_crc32c() and spdk_crc32c(),
so remove them.

Change-Id: I8cbf269c43177d7483f1df2e7ce9ce83776e7169
Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/369312
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Daniel Verkamp 2017-07-12 17:11:12 -07:00
parent 30c42b9b32
commit 740e5dc50b
3 changed files with 46 additions and 71 deletions

View File

@ -93,38 +93,3 @@ spdk_update_crc32c(const uint8_t *buf, size_t len, uint32_t crc)
return crc;
}
#endif /* USE_ISAL */
uint32_t
spdk_fixup_crc32c(size_t total, uint32_t crc)
{
uint8_t padding[ISCSI_ALIGNMENT];
size_t pad_length;
size_t rest;
if (total == 0)
return crc;
rest = total % ISCSI_ALIGNMENT;
if (rest != 0) {
pad_length = ISCSI_ALIGNMENT;
pad_length -= rest;
if (pad_length > 0 && pad_length < sizeof padding) {
memset(padding, 0, sizeof padding);
crc = spdk_update_crc32c(padding, pad_length, crc);
}
}
return crc;
}
uint32_t
spdk_crc32c(const uint8_t *buf, size_t len)
{
uint32_t crc32c;
crc32c = SPDK_CRC32C_INITIAL;
crc32c = spdk_update_crc32c(buf, len, crc32c);
if ((len % ISCSI_ALIGNMENT) != 0) {
crc32c = spdk_fixup_crc32c(len, crc32c);
}
crc32c = crc32c ^ SPDK_CRC32C_XOR;
return crc32c;
}

View File

@ -48,7 +48,5 @@ uint32_t crc32_iscsi(const uint8_t *buf, size_t len, uint32_t crc);
#else
uint32_t spdk_update_crc32c(const uint8_t *buf, size_t len, uint32_t crc);
#endif
uint32_t spdk_fixup_crc32c(size_t total, uint32_t crc);
uint32_t spdk_crc32c(const uint8_t *buf, size_t len);
#endif /* SPDK_CRC32C_H */

View File

@ -303,6 +303,48 @@ spdk_islun2lun(uint64_t islun)
return lun_i;
}
static uint32_t
spdk_iscsi_pdu_calc_header_digest(struct spdk_iscsi_pdu *pdu)
{
uint32_t crc32c;
uint32_t ahs_len_bytes = pdu->bhs.total_ahs_len * 4;
crc32c = SPDK_CRC32C_INITIAL;
crc32c = spdk_update_crc32c((uint8_t *)&pdu->bhs, ISCSI_BHS_LEN, crc32c);
if (ahs_len_bytes) {
crc32c = spdk_update_crc32c((uint8_t *)pdu->ahs, ahs_len_bytes, crc32c);
}
/* BHS and AHS are always 4-byte multiples in length, so no padding is necessary. */
crc32c = crc32c ^ SPDK_CRC32C_XOR;
return crc32c;
}
static uint32_t
spdk_iscsi_pdu_calc_data_digest(struct spdk_iscsi_pdu *pdu)
{
uint32_t data_len = DGET24(pdu->bhs.data_segment_len);
uint32_t crc32c;
uint32_t mod;
crc32c = SPDK_CRC32C_INITIAL;
crc32c = spdk_update_crc32c(pdu->data, data_len, crc32c);
mod = data_len % ISCSI_ALIGNMENT;
if (mod != 0) {
uint32_t pad_length = ISCSI_ALIGNMENT - mod;
uint8_t pad[3] = {0, 0, 0};
assert(pad_length > 0);
assert(pad_length <= sizeof(pad));
crc32c = spdk_update_crc32c(pad, pad_length, crc32c);
}
crc32c = crc32c ^ SPDK_CRC32C_XOR;
return crc32c;
}
int
spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu)
{
@ -496,21 +538,7 @@ spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu)
/* check digest */
if (conn->header_digest) {
if (ahs_len == 0) {
crc32c = spdk_crc32c((uint8_t *)&pdu->bhs,
ISCSI_BHS_LEN);
} else {
int upd_total = 0;
crc32c = SPDK_CRC32C_INITIAL;
crc32c = spdk_update_crc32c((uint8_t *)&pdu->bhs,
ISCSI_BHS_LEN, crc32c);
upd_total += ISCSI_BHS_LEN;
crc32c = spdk_update_crc32c((uint8_t *)pdu->ahs,
ahs_len, crc32c);
upd_total += ahs_len;
crc32c = spdk_fixup_crc32c(upd_total, crc32c);
crc32c = crc32c ^ SPDK_CRC32C_XOR;
}
crc32c = spdk_iscsi_pdu_calc_header_digest(pdu);
rc = MATCH_DIGEST_WORD(pdu->header_digest, crc32c);
if (rc == 0) {
SPDK_ERRLOG("header digest error (%s)\n", conn->initiator_name);
@ -519,7 +547,7 @@ spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu)
}
}
if (conn->data_digest && data_len != 0) {
crc32c = spdk_crc32c(pdu->data, ISCSI_ALIGN(data_len));
crc32c = spdk_iscsi_pdu_calc_data_digest(pdu);
rc = MATCH_DIGEST_WORD(pdu->data_digest, crc32c);
if (rc == 0) {
SPDK_ERRLOG("data digest error (%s)\n", conn->initiator_name);
@ -565,23 +593,7 @@ spdk_iscsi_build_iovecs(struct spdk_iscsi_conn *conn, struct iovec *iovec,
/* Header Digest */
if (enable_digest && conn->header_digest) {
if (total_ahs_len == 0) {
crc32c = spdk_crc32c((uint8_t *)&pdu->bhs,
ISCSI_BHS_LEN);
} else {
int upd_total = 0;
crc32c = SPDK_CRC32C_INITIAL;
crc32c = spdk_update_crc32c((uint8_t *)&pdu->bhs,
ISCSI_BHS_LEN, crc32c);
upd_total += ISCSI_BHS_LEN;
crc32c = spdk_update_crc32c((uint8_t *)pdu->ahs,
(4 * total_ahs_len),
crc32c);
upd_total += (4 * total_ahs_len);
crc32c = spdk_fixup_crc32c(upd_total, crc32c);
crc32c = crc32c ^ SPDK_CRC32C_XOR;
}
crc32c = spdk_iscsi_pdu_calc_header_digest(pdu);
MAKE_DIGEST_WORD(pdu->header_digest, crc32c);
iovec[iovec_cnt].iov_base = pdu->header_digest;
@ -598,7 +610,7 @@ spdk_iscsi_build_iovecs(struct spdk_iscsi_conn *conn, struct iovec *iovec,
/* Data Digest */
if (enable_digest && conn->data_digest && data_len != 0) {
crc32c = spdk_crc32c(pdu->data, ISCSI_ALIGN(data_len));
crc32c = spdk_iscsi_pdu_calc_data_digest(pdu);
MAKE_DIGEST_WORD(pdu->data_digest, crc32c);
iovec[iovec_cnt].iov_base = pdu->data_digest;