Sending data in dataIn PDUs splitted by maxRecvDataSegment Length
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ var (
|
||||
{"InitialR2T", "Yes"},
|
||||
{"MaxBurstLength", "262144"},
|
||||
{"FirstBurstLength", "65536"},
|
||||
{"MaxRecvDataSegmentLength", "65536"},
|
||||
{"DefaultTime2Wait", "2"},
|
||||
{"DefaultTime2Retain", "0"},
|
||||
{"MaxOutstandingR2T", "1"},
|
||||
|
||||
Reference in New Issue
Block a user