From 3e66e72651c4d81ca5f7c4da5e21daf8619b7818 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Fri, 6 Jul 2018 17:05:58 +0900 Subject: [PATCH] ut/iscsi: Add unit test for residual count of SCSI Request Sense Current SPDK implements SCSI Request Sense command so that a SCSI Data-In PDU and a SCSI Response PDU are returned and underflow are set to both of them. On the other hand, some implementation return only a SCSI Data-In PDU and some implementation return only a SCSI Response PDU. Adding test code will be helpful for every implementation. Change-Id: Icccc2d6e334146f558f8d75215bab1362b2b68f0 Signed-off-by: Shuhei Matsumoto Reviewed-on: https://review.gerrithub.io/418175 Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Daniel Verkamp Reviewed-by: Ben Walker --- test/unit/lib/iscsi/iscsi.c/iscsi_ut.c | 92 ++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/test/unit/lib/iscsi/iscsi.c/iscsi_ut.c b/test/unit/lib/iscsi/iscsi.c/iscsi_ut.c index 5d4cc7e6c..3ad3df2f8 100644 --- a/test/unit/lib/iscsi/iscsi.c/iscsi_ut.c +++ b/test/unit/lib/iscsi/iscsi.c/iscsi_ut.c @@ -367,6 +367,96 @@ underflow_for_zero_read_transfer_test(void) CU_ASSERT(TAILQ_EMPTY(&g_write_pdu_list)); } +static void +underflow_for_request_sense_test(void) +{ + struct spdk_iscsi_sess sess; + struct spdk_iscsi_conn conn; + struct spdk_iscsi_task task; + struct spdk_iscsi_pdu *pdu; + struct iscsi_bhs_scsi_req *scsi_req; + struct iscsi_bhs_data_in *datah; + struct iscsi_bhs_scsi_resp *resph; + uint32_t residual_count = 0, data_segment_len; + + TAILQ_INIT(&g_write_pdu_list); + + memset(&sess, 0, sizeof(sess)); + memset(&conn, 0, sizeof(conn)); + memset(&task, 0, sizeof(task)); + + sess.MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH; + + conn.sess = &sess; + conn.MaxRecvDataSegmentLength = 8192; + + pdu = spdk_get_pdu(); + SPDK_CU_ASSERT_FATAL(pdu != NULL); + + scsi_req = (struct iscsi_bhs_scsi_req *)&pdu->bhs; + scsi_req->read_bit = 1; + + spdk_iscsi_task_set_pdu(&task, pdu); + task.parent = NULL; + + task.scsi.iovs = &task.scsi.iov; + task.scsi.iovcnt = 1; + task.scsi.length = 512; + task.scsi.transfer_len = 512; + task.bytes_completed = 512; + + task.scsi.sense_data_len = 18; + task.scsi.data_transferred = 18; + task.scsi.status = SPDK_SCSI_STATUS_GOOD; + + spdk_iscsi_task_response(&conn, &task); + spdk_put_pdu(pdu); + + /* + * In this case, a SCSI Data-In PDU and a SCSI Response PDU are returned. + * Sense data are set both in payload and sense area. + * The SCSI Data-In PDU sets FINAL and the SCSI Response PDU sets UNDERFLOW. + * + * Probably there will be different implementation but keeping current SPDK + * implementation by adding UT will be valuable for any implementation. + */ + to_be32(&residual_count, 494); + + pdu = TAILQ_FIRST(&g_write_pdu_list); + SPDK_CU_ASSERT_FATAL(pdu != NULL); + + CU_ASSERT(pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN); + + datah = (struct iscsi_bhs_data_in *)&pdu->bhs; + + CU_ASSERT(datah->flags == ISCSI_FLAG_FINAL); + + data_segment_len = DGET24(datah->data_segment_len); + CU_ASSERT(data_segment_len == 18); + CU_ASSERT(datah->res_cnt == 0); + + TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq); + spdk_put_pdu(pdu); + + pdu = TAILQ_FIRST(&g_write_pdu_list); + SPDK_CU_ASSERT_FATAL(pdu != NULL); + + CU_ASSERT(pdu->bhs.opcode == ISCSI_OP_SCSI_RSP); + + resph = (struct iscsi_bhs_scsi_resp *)&pdu->bhs; + + CU_ASSERT(resph->flags == (ISCSI_SCSI_UNDERFLOW | 0x80)); + + data_segment_len = DGET24(resph->data_segment_len); + CU_ASSERT(data_segment_len == task.scsi.sense_data_len + 2); + CU_ASSERT(resph->res_cnt == residual_count); + + TAILQ_REMOVE(&g_write_pdu_list, pdu, tailq); + spdk_put_pdu(pdu); + + CU_ASSERT(TAILQ_EMPTY(&g_write_pdu_list)); +} + int main(int argc, char **argv) { @@ -390,6 +480,8 @@ main(int argc, char **argv) underflow_for_read_transfer_test) == NULL || CU_add_test(suite, "underflow for zero read transfer test", underflow_for_zero_read_transfer_test) == NULL + || CU_add_test(suite, "underflow for request sense test", + underflow_for_request_sense_test) == NULL ) { CU_cleanup_registry(); return CU_get_error();