From 0b629a16fed4bf6cc7547c96a14bd59c2bf92a98 Mon Sep 17 00:00:00 2001 From: Payes Anand Date: Sun, 12 Mar 2017 01:35:58 +0530 Subject: [PATCH 1/2] Sending data in dataIn PDUs splitted by maxRecvDataSegment Length --- pkg/port/iscsit/cmd.go | 20 ++++++++------ pkg/port/iscsit/conn.go | 5 +++- pkg/port/iscsit/iscsid.go | 55 +++++++++++++++++++++++++++++++++------ pkg/port/iscsit/login.go | 1 + 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index 10ce684..91fa46b 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -62,6 +62,7 @@ type ISCSICommand struct { DataLen int RawData []byte Final bool + FinalInSeq bool Immediate bool TaskTag uint32 ExpCmdSN, MaxCmdSN uint32 @@ -276,23 +277,26 @@ func (m *ISCSICommand) dataInBytes() []byte { buf := &bytes.Buffer{} buf.WriteByte(byte(OpSCSIIn)) var b byte - b = 0x80 - if m.HasStatus { + b = 0x0 + if m.FinalInSeq || m.Final == true { + b |= 0x80 + } + if m.HasStatus && m.Final == true { b |= 0x01 } buf.WriteByte(b) buf.WriteByte(0x00) - if m.HasStatus { + if m.HasStatus && m.Final == true { b = byte(m.Status) } buf.WriteByte(b) buf.WriteByte(0x00) // 4 - buf.Write(util.MarshalUint64(uint64(len(m.RawData)))[5:]) // 5-8 - // Skip through to byte 16 + buf.Write(util.MarshalUint64(uint64(m.DataLen))[5:]) // 5-8 + // Skip through to byte 16 Since A bit is not set 11.7.4 for i := 0; i < 8; i++ { - buf.WriteByte(byte(m.LUN[i])) + buf.WriteByte(0x00) } buf.Write(util.MarshalUint64(uint64(m.TaskTag))[4:]) for i := 0; i < 4; i++ { @@ -307,8 +311,8 @@ func (m *ISCSICommand) dataInBytes() []byte { for i := 0; i < 4; i++ { buf.WriteByte(0x00) } - buf.Write(m.RawData) - dl := len(m.RawData) + buf.Write(m.RawData[m.BufferOffset : m.BufferOffset+uint32(m.DataLen)]) + dl := m.DataLen for dl%4 > 0 { dl++ buf.WriteByte(0x00) diff --git a/pkg/port/iscsit/conn.go b/pkg/port/iscsit/conn.go index f9b0775..f45260d 100644 --- a/pkg/port/iscsit/conn.go +++ b/pkg/port/iscsit/conn.go @@ -77,7 +77,10 @@ type iscsiConnection struct { // ExpCmdSN - the next expected command sequence number at the target expCmdSN uint32 // MaxCmdSN - the maximum CmdSN acceptable at the target from this initiator - maxCmdSN uint32 + maxCmdSN uint32 + maxRecvDataSegmentLength uint32 + maxBurstLength uint32 + maxSeqCount uint32 rxTask *iscsiTask txTask *iscsiTask diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index 6feda45..76bcc98 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -330,6 +330,9 @@ func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error { conn.loginParam.isid = cmd.ISID conn.loginParam.tsih = cmd.TSIH conn.expCmdSN = cmd.CmdSN + conn.maxBurstLength = 262144 + conn.maxRecvDataSegmentLength = 65536 + conn.maxSeqCount = conn.maxBurstLength / conn.maxRecvDataSegmentLength if conn.loginParam.iniCSG == SecurityNegotiation { conn.state = CONN_STATE_EXIT @@ -428,9 +431,11 @@ func iscsiExecR2T(conn *iscsiConnection) error { func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) { var ( - hdigest uint = 0 - ddigest uint = 0 - final bool = false + hdigest uint = 0 + ddigest uint = 0 + offset uint32 = 0 + final bool = false + count uint32 = 0 ) if conn.state == CONN_STATE_SCSI { hdigest = conn.loginParam.sessionParam[ISCSI_PARAM_HDRDGST_EN].Value & DIGEST_CRC32C @@ -443,14 +448,42 @@ func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) { return } } + resp := conn.resp + segmentLen := conn.maxRecvDataSegmentLength + transferLen := len(resp.RawData) + resp.DataSN = 0 + maxCount := conn.maxSeqCount + + /* send data splitted by segmentLen */ +SendRemainingData: + if resp.OpCode == OpSCSIIn { + resp.BufferOffset = offset + if int(offset+segmentLen) < transferLen { + count += 1 + if count < maxCount { + resp.FinalInSeq = false + resp.Final = false + } else { + count = 0 + resp.FinalInSeq = true + resp.Final = false + } + offset = offset + segmentLen + resp.DataLen = int(segmentLen) + } else { + resp.FinalInSeq = true + resp.Final = true + resp.DataLen = transferLen - int(offset) + } + } for { switch conn.txIOState { case IOSTATE_TX_BHS: log.Debug("ready to write response") - log.Debugf("%s", conn.resp.String()) - log.Debugf("length of RawData is %d", len(conn.resp.RawData)) - log.Debugf("length of resp is %d", len(conn.resp.Bytes())) - if l, err := conn.write(conn.resp.Bytes()); err != nil { + log.Debugf("%s", resp.String()) + log.Debugf("length of RawData is %d", len(resp.RawData)) + log.Debugf("length of resp is %d", len(resp.Bytes())) + if l, err := conn.write(resp.Bytes()); err != nil { log.Error(err) return } else { @@ -479,7 +512,13 @@ func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) { } if final { - break + if resp.OpCode == OpSCSIIn && resp.Final != true { + resp.DataSN++ + conn.txIOState = IOSTATE_TX_BHS + goto SendRemainingData + } else { + break + } } } diff --git a/pkg/port/iscsit/login.go b/pkg/port/iscsit/login.go index 55564cb..547962a 100644 --- a/pkg/port/iscsit/login.go +++ b/pkg/port/iscsit/login.go @@ -16,6 +16,7 @@ var ( {"InitialR2T", "Yes"}, {"MaxBurstLength", "262144"}, {"FirstBurstLength", "65536"}, + {"MaxRecvDataSegmentLength", "65536"}, {"DefaultTime2Wait", "2"}, {"DefaultTime2Retain", "0"}, {"MaxOutstandingR2T", "1"}, From 6deca564873da3242a284ce653e37d6fd8425eca Mon Sep 17 00:00:00 2001 From: Payes Date: Fri, 21 Apr 2017 13:41:52 +0530 Subject: [PATCH 2/2] Create constants for MaxRecvDataSegmentLength and MaxBurstLength --- pkg/port/iscsit/cmd.go | 5 +++++ pkg/port/iscsit/iscsid.go | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/port/iscsit/cmd.go b/pkg/port/iscsit/cmd.go index 91fa46b..55816a7 100644 --- a/pkg/port/iscsit/cmd.go +++ b/pkg/port/iscsit/cmd.go @@ -33,6 +33,11 @@ const ( OpReject = 0x3f ) +const ( + MaxBurstLength uint32 = 262144 + MaxRecvDataSegmentLength uint32 = 65536 +) + var opCodeMap = map[OpCode]string{ OpNoopOut: "NOP-Out", OpSCSICmd: "SCSI Command", diff --git a/pkg/port/iscsit/iscsid.go b/pkg/port/iscsit/iscsid.go index 76bcc98..dca7c21 100644 --- a/pkg/port/iscsit/iscsid.go +++ b/pkg/port/iscsit/iscsid.go @@ -330,8 +330,8 @@ func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error { conn.loginParam.isid = cmd.ISID conn.loginParam.tsih = cmd.TSIH conn.expCmdSN = cmd.CmdSN - conn.maxBurstLength = 262144 - conn.maxRecvDataSegmentLength = 65536 + conn.maxBurstLength = MaxBurstLength + conn.maxRecvDataSegmentLength = MaxRecvDataSegmentLength conn.maxSeqCount = conn.maxBurstLength / conn.maxRecvDataSegmentLength if conn.loginParam.iniCSG == SecurityNegotiation {