Commit 740e5dc5 authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

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: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/369312


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 30c42b9b
Loading
Loading
Loading
Loading
+0 −35
Original line number Diff line number Diff line
@@ -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;
}
+0 −2
Original line number Diff line number Diff line
@@ -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 */
+46 −34
Original line number Diff line number Diff line
@@ -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;