Merge pull request #51 from openebs/dev

Send data in dataIn PDUs splitted by maxRecvDataSegment Length
This commit is contained in:
Lei Xue
2017-04-23 19:35:38 +08:00
committed by GitHub
4 changed files with 69 additions and 17 deletions

View File

@@ -33,6 +33,11 @@ const (
OpReject = 0x3f OpReject = 0x3f
) )
const (
MaxBurstLength uint32 = 262144
MaxRecvDataSegmentLength uint32 = 65536
)
var opCodeMap = map[OpCode]string{ var opCodeMap = map[OpCode]string{
OpNoopOut: "NOP-Out", OpNoopOut: "NOP-Out",
OpSCSICmd: "SCSI Command", OpSCSICmd: "SCSI Command",
@@ -62,6 +67,7 @@ type ISCSICommand struct {
DataLen int DataLen int
RawData []byte RawData []byte
Final bool Final bool
FinalInSeq bool
Immediate bool Immediate bool
TaskTag uint32 TaskTag uint32
ExpCmdSN, MaxCmdSN uint32 ExpCmdSN, MaxCmdSN uint32
@@ -276,23 +282,26 @@ func (m *ISCSICommand) dataInBytes() []byte {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
buf.WriteByte(byte(OpSCSIIn)) buf.WriteByte(byte(OpSCSIIn))
var b byte var b byte
b = 0x80 b = 0x0
if m.HasStatus { if m.FinalInSeq || m.Final == true {
b |= 0x80
}
if m.HasStatus && m.Final == true {
b |= 0x01 b |= 0x01
} }
buf.WriteByte(b) buf.WriteByte(b)
buf.WriteByte(0x00) buf.WriteByte(0x00)
if m.HasStatus { if m.HasStatus && m.Final == true {
b = byte(m.Status) b = byte(m.Status)
} }
buf.WriteByte(b) buf.WriteByte(b)
buf.WriteByte(0x00) // 4 buf.WriteByte(0x00) // 4
buf.Write(util.MarshalUint64(uint64(len(m.RawData)))[5:]) // 5-8 buf.Write(util.MarshalUint64(uint64(m.DataLen))[5:]) // 5-8
// Skip through to byte 16 // Skip through to byte 16 Since A bit is not set 11.7.4
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
buf.WriteByte(byte(m.LUN[i])) buf.WriteByte(0x00)
} }
buf.Write(util.MarshalUint64(uint64(m.TaskTag))[4:]) buf.Write(util.MarshalUint64(uint64(m.TaskTag))[4:])
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
@@ -307,8 +316,8 @@ func (m *ISCSICommand) dataInBytes() []byte {
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
buf.WriteByte(0x00) buf.WriteByte(0x00)
} }
buf.Write(m.RawData) buf.Write(m.RawData[m.BufferOffset : m.BufferOffset+uint32(m.DataLen)])
dl := len(m.RawData) dl := m.DataLen
for dl%4 > 0 { for dl%4 > 0 {
dl++ dl++
buf.WriteByte(0x00) buf.WriteByte(0x00)

View File

@@ -77,7 +77,10 @@ type iscsiConnection struct {
// ExpCmdSN - the next expected command sequence number at the target // ExpCmdSN - the next expected command sequence number at the target
expCmdSN uint32 expCmdSN uint32
// MaxCmdSN - the maximum CmdSN acceptable at the target from this initiator // MaxCmdSN - the maximum CmdSN acceptable at the target from this initiator
maxCmdSN uint32 maxCmdSN uint32
maxRecvDataSegmentLength uint32
maxBurstLength uint32
maxSeqCount uint32
rxTask *iscsiTask rxTask *iscsiTask
txTask *iscsiTask txTask *iscsiTask

View File

@@ -330,6 +330,9 @@ func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error {
conn.loginParam.isid = cmd.ISID conn.loginParam.isid = cmd.ISID
conn.loginParam.tsih = cmd.TSIH conn.loginParam.tsih = cmd.TSIH
conn.expCmdSN = cmd.CmdSN conn.expCmdSN = cmd.CmdSN
conn.maxBurstLength = MaxBurstLength
conn.maxRecvDataSegmentLength = MaxRecvDataSegmentLength
conn.maxSeqCount = conn.maxBurstLength / conn.maxRecvDataSegmentLength
if conn.loginParam.iniCSG == SecurityNegotiation { if conn.loginParam.iniCSG == SecurityNegotiation {
conn.state = CONN_STATE_EXIT conn.state = CONN_STATE_EXIT
@@ -428,9 +431,11 @@ func iscsiExecR2T(conn *iscsiConnection) error {
func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) { func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) {
var ( var (
hdigest uint = 0 hdigest uint = 0
ddigest uint = 0 ddigest uint = 0
final bool = false offset uint32 = 0
final bool = false
count uint32 = 0
) )
if conn.state == CONN_STATE_SCSI { if conn.state == CONN_STATE_SCSI {
hdigest = conn.loginParam.sessionParam[ISCSI_PARAM_HDRDGST_EN].Value & DIGEST_CRC32C hdigest = conn.loginParam.sessionParam[ISCSI_PARAM_HDRDGST_EN].Value & DIGEST_CRC32C
@@ -443,14 +448,42 @@ func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) {
return 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 { for {
switch conn.txIOState { switch conn.txIOState {
case IOSTATE_TX_BHS: case IOSTATE_TX_BHS:
log.Debug("ready to write response") log.Debug("ready to write response")
log.Debugf("%s", conn.resp.String()) log.Debugf("%s", resp.String())
log.Debugf("length of RawData is %d", len(conn.resp.RawData)) log.Debugf("length of RawData is %d", len(resp.RawData))
log.Debugf("length of resp is %d", len(conn.resp.Bytes())) log.Debugf("length of resp is %d", len(resp.Bytes()))
if l, err := conn.write(conn.resp.Bytes()); err != nil { if l, err := conn.write(resp.Bytes()); err != nil {
log.Error(err) log.Error(err)
return return
} else { } else {
@@ -479,7 +512,13 @@ func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) {
} }
if final { if final {
break if resp.OpCode == OpSCSIIn && resp.Final != true {
resp.DataSN++
conn.txIOState = IOSTATE_TX_BHS
goto SendRemainingData
} else {
break
}
} }
} }

View File

@@ -16,6 +16,7 @@ var (
{"InitialR2T", "Yes"}, {"InitialR2T", "Yes"},
{"MaxBurstLength", "262144"}, {"MaxBurstLength", "262144"},
{"FirstBurstLength", "65536"}, {"FirstBurstLength", "65536"},
{"MaxRecvDataSegmentLength", "65536"},
{"DefaultTime2Wait", "2"}, {"DefaultTime2Wait", "2"},
{"DefaultTime2Retain", "0"}, {"DefaultTime2Retain", "0"},
{"MaxOutstandingR2T", "1"}, {"MaxOutstandingR2T", "1"},