From 902b467aada58dbf8090e1dff31355e8441b2ab4 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Wed, 16 Oct 2019 16:36:55 +0900 Subject: [PATCH] lib/iscsi: Separate PDU header and payload handling for NOP-Out As same as SCSI Command Request and SCSI Data-Out, separate PDU header handling and payload handling into different functions. In iscsi_op_nopout(), if it sees pdu->is_rejected is true, do nothing. Signed-off-by: Shuhei Matsumoto Change-Id: If50cd64bacf18c014e2aa232fd84357b877d9821 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/471011 Tested-by: SPDK CI Jenkins Reviewed-by: Changpeng Liu Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- lib/iscsi/iscsi.c | 70 ++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/lib/iscsi/iscsi.c b/lib/iscsi/iscsi.c index 193092775..7ec833445 100644 --- a/lib/iscsi/iscsi.c +++ b/lib/iscsi/iscsi.c @@ -3927,36 +3927,25 @@ void spdk_iscsi_send_nopin(struct spdk_iscsi_conn *conn) } static int -iscsi_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) +iscsi_pdu_hdr_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) { - struct spdk_iscsi_pdu *rsp_pdu; struct iscsi_bhs_nop_out *reqh; - struct iscsi_bhs_nop_in *rsph; - uint8_t *data; - uint64_t lun; uint32_t task_tag; uint32_t transfer_tag; int I_bit; - int data_len; if (conn->sess->session_type == SESSION_TYPE_DISCOVERY) { SPDK_ERRLOG("ISCSI_OP_NOPOUT not allowed in discovery session\n"); return SPDK_ISCSI_CONNECTION_FATAL; } + reqh = (struct iscsi_bhs_nop_out *)&pdu->bhs; + I_bit = reqh->immediate; + if (pdu->data_segment_len > SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) { return iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR); } - reqh = (struct iscsi_bhs_nop_out *)&pdu->bhs; - I_bit = reqh->immediate; - - data_len = pdu->data_segment_len; - if (data_len > conn->MaxRecvDataSegmentLength) { - data_len = conn->MaxRecvDataSegmentLength; - } - - lun = from_be64(&reqh->lun); task_tag = from_be32(&reqh->itt); transfer_tag = from_be32(&reqh->ttt); @@ -3975,6 +3964,43 @@ iscsi_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) */ } + if (task_tag == 0xffffffffU && I_bit == 0) { + SPDK_ERRLOG("got NOPOUT ITT=0xffffffff, I=0\n"); + return SPDK_ISCSI_CONNECTION_FATAL; + } + + return 0; +} + +static int +iscsi_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) +{ + struct spdk_iscsi_pdu *rsp_pdu; + struct iscsi_bhs_nop_out *reqh; + struct iscsi_bhs_nop_in *rsph; + uint8_t *data; + uint64_t lun; + uint32_t task_tag; + int I_bit; + int data_len; + int rc; + + rc = iscsi_pdu_hdr_op_nopout(conn, pdu); + if (rc != 0 || pdu->is_rejected) { + return rc; + } + + reqh = (struct iscsi_bhs_nop_out *)&pdu->bhs; + I_bit = reqh->immediate; + + data_len = pdu->data_segment_len; + if (data_len > conn->MaxRecvDataSegmentLength) { + data_len = conn->MaxRecvDataSegmentLength; + } + + lun = from_be64(&reqh->lun); + task_tag = from_be32(&reqh->itt); + /* * We don't actually check to see if this is a response to the NOP-In * that we sent. Our goal is to just verify that the initiator is @@ -3984,13 +4010,9 @@ iscsi_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) conn->nop_outstanding = false; if (task_tag == 0xffffffffU) { - if (I_bit == 1) { - SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "got NOPOUT ITT=0xffffffff\n"); - return 0; - } else { - SPDK_ERRLOG("got NOPOUT ITT=0xffffffff, I=0\n"); - return SPDK_ISCSI_CONNECTION_FATAL; - } + assert(I_bit == 1); + SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "got NOPOUT ITT=0xffffffff\n"); + return 0; } data = calloc(1, data_len); @@ -4005,8 +4027,6 @@ iscsi_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) memcpy(data, pdu->data, data_len); } - transfer_tag = 0xffffffffU; - /* response PDU */ rsp_pdu = spdk_get_pdu(); if (rsp_pdu == NULL) { @@ -4020,7 +4040,7 @@ iscsi_op_nopout(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu) DSET24(rsph->data_segment_len, data_len); to_be64(&rsph->lun, lun); to_be32(&rsph->itt, task_tag); - to_be32(&rsph->ttt, transfer_tag); + to_be32(&rsph->ttt, 0xffffffffU); to_be32(&rsph->stat_sn, conn->StatSN); conn->StatSN++;