Merge pull request #32 from carmark/update_sn
small refactor: combine all package response generation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -44,5 +44,4 @@ _testmain.go
|
|||||||
.idea
|
.idea
|
||||||
/gotgt
|
/gotgt
|
||||||
*.out
|
*.out
|
||||||
examples/*
|
|
||||||
*.bak
|
*.bak
|
||||||
|
|||||||
76
README.md
76
README.md
@@ -1,8 +1,22 @@
|
|||||||
## gotgt [](https://travis-ci.org/gostor/gotgt)
|
## gotgt [](https://travis-ci.org/gostor/gotgt)
|
||||||
|
|
||||||
Simple Golang SCSI Target framework, this includes only one binary, you can start a daemon via `gotgt daemon` and control it via `gotgt list/create/rm`.
|
gotgt is a simple SCSI Target framework implemented by golang, built for performance and density..
|
||||||
|
|
||||||
## Build
|
### What is SCSI?
|
||||||
|
Small Computer System Interface (SCSI) is a set of standards for physically connecting and transferring data between computers and peripheral devices. The SCSI standards define commands, protocols, electrical and optical interfaces. SCSI is most commonly used for hard disk drives and tape drives, but it can connect a wide range of other devices, including scanners and CD drives, although not all controllers can handle all devices.
|
||||||
|
|
||||||
|
### What is iSCSI?
|
||||||
|
The iSCSI is an acronym for Internet Small Computer Systems Interface, an Internet Protocol (IP)-based storage networking standard for linking data storage facilities. In a nutshell, it provides block-level access to storage devices over a TCP/IP network.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
Currently, the gotgt is under heavy development, so there is no any release binaries so far, you have to build it from source.
|
||||||
|
|
||||||
|
There is a only on binary name `gotgt`, you can start a daemon via `gotgt daemon` and control it via `gotgt list/create/rm`.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
You will need to make sure that you have Go installed on your system and the `gotgt` repository is cloned in your $GOPATH.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ mkdir -p $GOPATH/src/github.com/gostor/
|
$ mkdir -p $GOPATH/src/github.com/gostor/
|
||||||
@@ -14,60 +28,22 @@ $ ./configure
|
|||||||
$ make
|
$ make
|
||||||
```
|
```
|
||||||
|
|
||||||
## How to use
|
### How to use
|
||||||
|
|
||||||
Currenty, there is lack of commands to operate the target and LU, however you can init the target/LU with config file in `~/.gotgt/config.json`, such as:
|
Now, there is lack of commands to operate the target and LU, however you can init the target/LU with config file in `~/.gotgt/config.json`, you may find a example at [here](./examples/config.json).
|
||||||
|
Please note, if you want use that exmaple, you have to make sure file `/var/tmp/disk.img` is existed.
|
||||||
|
|
||||||
```
|
### Test
|
||||||
{
|
|
||||||
"storages":[
|
|
||||||
{
|
|
||||||
"deviceID":1000,
|
|
||||||
"path":"file:/var/tmp/disk.img",
|
|
||||||
"online":true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"iscsiportals":[
|
|
||||||
{
|
|
||||||
"id":0,
|
|
||||||
"portal":"127.0.0.1:3260"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"iscsitargets":{
|
|
||||||
"iqn.2016-09.com.gotgt.gostor:02:example-tgt-0":{
|
|
||||||
"tpgts":{
|
|
||||||
"1":[0]
|
|
||||||
},
|
|
||||||
"luns":{
|
|
||||||
"0":1000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
> Note: make sure file `/var/tmp/disk.img` is existed, you can use `dd` to create it.
|
|
||||||
|
|
||||||
## Test
|
|
||||||
|
|
||||||
You can test this with [open-iscsi](http://www.open-iscsi.com/) or [libiscsi](https://github.com/gostor/libiscsi).
|
You can test this with [open-iscsi](http://www.open-iscsi.com/) or [libiscsi](https://github.com/gostor/libiscsi).
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
* Auth (p3)
|
|
||||||
* Login Process (orzhang, p2)
|
The current roadmap and milestones for alpha and beta completion are in the github issues on this repository. Please refer to these issues for what is being worked on and completed for the various stages of development.
|
||||||
* ACL (Access control) (p3)
|
|
||||||
* SCSI Task Management (p3)
|
|
||||||
* iSCSI Task Management (p3)
|
|
||||||
* SCSI Command Queue (p2)
|
|
||||||
* More SCSI commands (p2)
|
|
||||||
* Refactor (carmark, p1)
|
|
||||||
* Command Line (carmark, p1)
|
|
||||||
* More Backstore Plugins(such as `ceph` and `raw device`) (orzhang, p1)
|
|
||||||
* Redirect iSCSI Target (orzhang, p2)
|
|
||||||
* Homepage (p3)
|
|
||||||
* More test cases (p2)
|
|
||||||
* IDM implementation (p3) https://tools.ietf.org/html/rfc5047
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@@ -89,7 +88,8 @@ func createDaemon(host, driver, level string) error {
|
|||||||
targetDriver.NewTarget(tgtname, config)
|
targetDriver.NewTarget(tgtname, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
// comment this to avoid concurrent issue
|
||||||
|
// runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
// run a service
|
// run a service
|
||||||
go targetDriver.Run()
|
go targetDriver.Run()
|
||||||
|
|
||||||
|
|||||||
25
examples/config.json
Normal file
25
examples/config.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"storages":[
|
||||||
|
{
|
||||||
|
"deviceID":1000,
|
||||||
|
"path":"file:/var/tmp/disk.img",
|
||||||
|
"online":true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"iscsiportals":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"portal":"127.0.0.1:3260"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"iscsitargets":{
|
||||||
|
"iqn.2016-09.com.gotgt.gostor:02:example-tgt-0":{
|
||||||
|
"tpgts":{
|
||||||
|
"1":[0]
|
||||||
|
},
|
||||||
|
"luns":{
|
||||||
|
"0":1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/gostor/gotgt/pkg/api"
|
"github.com/gostor/gotgt/pkg/api"
|
||||||
|
"github.com/gostor/gotgt/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -140,3 +141,70 @@ func (conn *iscsiConnection) ReInstatement(newConn *iscsiConnection) {
|
|||||||
conn.close()
|
conn.close()
|
||||||
conn.conn = newConn.conn
|
conn.conn = newConn.conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (conn *iscsiConnection) buildRespPackage(oc OpCode) error {
|
||||||
|
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: &api.SCSICommand{}}
|
||||||
|
conn.txIOState = IOSTATE_TX_BHS
|
||||||
|
conn.statSN += 1
|
||||||
|
task := conn.rxTask
|
||||||
|
resp := &ISCSICommand{
|
||||||
|
StatSN: conn.req.ExpStatSN,
|
||||||
|
TaskTag: conn.req.TaskTag,
|
||||||
|
ExpCmdSN: conn.session.ExpCmdSN,
|
||||||
|
MaxCmdSN: conn.session.ExpCmdSN + conn.session.MaxQueueCommand,
|
||||||
|
}
|
||||||
|
switch oc {
|
||||||
|
case OpReady:
|
||||||
|
resp.OpCode = OpReady
|
||||||
|
resp.R2TSN = task.r2tSN
|
||||||
|
resp.BufferOffset = uint32(task.offset)
|
||||||
|
resp.DesiredLength = uint32(task.r2tCount)
|
||||||
|
if val := conn.loginParam.sessionParam[ISCSI_PARAM_MAX_BURST].Value; task.r2tCount > int(val) {
|
||||||
|
resp.DesiredLength = uint32(val)
|
||||||
|
}
|
||||||
|
case OpSCSIIn, OpSCSIResp:
|
||||||
|
resp.OpCode = oc
|
||||||
|
resp.Immediate = true
|
||||||
|
resp.Final = true
|
||||||
|
resp.SCSIResponse = 0x00
|
||||||
|
resp.HasStatus = true
|
||||||
|
scmd := task.scmd
|
||||||
|
resp.Status = scmd.Result
|
||||||
|
if scmd.Direction == api.SCSIDataRead || scmd.Direction == api.SCSIDataWrite {
|
||||||
|
if scmd.InSDBBuffer.Buffer != nil {
|
||||||
|
buf := scmd.InSDBBuffer.Buffer.Bytes()
|
||||||
|
resp.RawData = buf
|
||||||
|
} else {
|
||||||
|
resp.RawData = []byte{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if scmd.Result != 0 && scmd.SenseBuffer != nil {
|
||||||
|
resp.RawData = scmd.SenseBuffer.Bytes()
|
||||||
|
}
|
||||||
|
case OpNoopIn, OpSCSITaskResp, OpReject:
|
||||||
|
resp.OpCode = oc
|
||||||
|
resp.Final = true
|
||||||
|
resp.NSG = FullFeaturePhase
|
||||||
|
resp.ExpCmdSN = conn.req.CmdSN + 1
|
||||||
|
case OpLoginResp:
|
||||||
|
resp.OpCode = OpLoginResp
|
||||||
|
resp.Transit = conn.loginParam.tgtTrans
|
||||||
|
resp.CSG = conn.req.CSG
|
||||||
|
resp.NSG = conn.loginParam.tgtNSG
|
||||||
|
resp.ExpCmdSN = conn.req.CmdSN
|
||||||
|
resp.MaxCmdSN = conn.req.CmdSN
|
||||||
|
negoKeys, err := conn.processLoginData()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !conn.loginParam.keyDeclared {
|
||||||
|
negoKeys = loginKVDeclare(conn, negoKeys)
|
||||||
|
conn.loginParam.keyDeclared = true
|
||||||
|
}
|
||||||
|
resp.RawData = util.MarshalKVText(negoKeys)
|
||||||
|
conn.txTask = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.resp = resp
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -320,11 +320,7 @@ func (s *ISCSITargetDriver) rxHandler(conn *iscsiConnection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error {
|
func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error {
|
||||||
var (
|
var cmd = conn.req
|
||||||
cmd = conn.req
|
|
||||||
err error
|
|
||||||
negoKeys []util.KeyValue
|
|
||||||
)
|
|
||||||
|
|
||||||
conn.cid = cmd.ConnID
|
conn.cid = cmd.ConnID
|
||||||
conn.loginParam.iniCSG = cmd.CSG
|
conn.loginParam.iniCSG = cmd.CSG
|
||||||
@@ -334,23 +330,16 @@ 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.statSN += 1
|
|
||||||
|
|
||||||
if conn.loginParam.iniCSG == SecurityNegotiation {
|
if conn.loginParam.iniCSG == SecurityNegotiation {
|
||||||
conn.state = CONN_STATE_EXIT
|
conn.state = CONN_STATE_EXIT
|
||||||
return fmt.Errorf("Doesn't support Auth")
|
return fmt.Errorf("Doesn't support Auth")
|
||||||
}
|
}
|
||||||
|
|
||||||
pairs := util.ParseKVText(cmd.RawData)
|
_, err := conn.processLoginData()
|
||||||
|
|
||||||
negoKeys, err = loginKVProcess(conn, pairs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !conn.loginParam.keyDeclared {
|
|
||||||
negoKeys = loginKVDeclare(conn, negoKeys)
|
|
||||||
conn.loginParam.keyDeclared = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !conn.loginParam.paramInit {
|
if !conn.loginParam.paramInit {
|
||||||
err = s.BindISCSISession(conn)
|
err = s.BindISCSISession(conn)
|
||||||
@@ -367,19 +356,7 @@ func (s *ISCSITargetDriver) iscsiExecLogin(conn *iscsiConnection) error {
|
|||||||
conn.state = CONN_STATE_LOGIN
|
conn.state = CONN_STATE_LOGIN
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.resp = &ISCSICommand{
|
return conn.buildRespPackage(OpLoginResp)
|
||||||
OpCode: OpLoginResp,
|
|
||||||
Transit: conn.loginParam.tgtTrans,
|
|
||||||
CSG: cmd.CSG,
|
|
||||||
NSG: conn.loginParam.tgtNSG,
|
|
||||||
StatSN: cmd.ExpStatSN,
|
|
||||||
TaskTag: cmd.TaskTag,
|
|
||||||
ExpCmdSN: cmd.CmdSN,
|
|
||||||
MaxCmdSN: cmd.CmdSN,
|
|
||||||
RawData: util.MarshalKVText(negoKeys),
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func iscsiExecLogout(conn *iscsiConnection) error {
|
func iscsiExecLogout(conn *iscsiConnection) error {
|
||||||
@@ -394,7 +371,7 @@ func iscsiExecLogout(conn *iscsiConnection) error {
|
|||||||
conn.resp.MaxCmdSN = cmd.CmdSN
|
conn.resp.MaxCmdSN = cmd.CmdSN
|
||||||
} else {
|
} else {
|
||||||
conn.resp.ExpCmdSN = conn.session.ExpCmdSN
|
conn.resp.ExpCmdSN = conn.session.ExpCmdSN
|
||||||
conn.resp.MaxCmdSN = conn.session.ExpCmdSN + 10
|
conn.resp.MaxCmdSN = conn.session.ExpCmdSN + conn.session.MaxQueueCommand
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -434,62 +411,19 @@ func (s *ISCSITargetDriver) iscsiExecText(conn *iscsiConnection) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func iscsiExecNoopOut(conn *iscsiConnection) error {
|
func iscsiExecNoopOut(conn *iscsiConnection) error {
|
||||||
cmd := conn.req
|
return conn.buildRespPackage(OpNoopIn)
|
||||||
conn.resp = &ISCSICommand{
|
|
||||||
OpCode: OpNoopIn,
|
|
||||||
Final: true,
|
|
||||||
NSG: FullFeaturePhase,
|
|
||||||
StatSN: cmd.ExpStatSN,
|
|
||||||
TaskTag: cmd.TaskTag,
|
|
||||||
ExpCmdSN: cmd.CmdSN + 1,
|
|
||||||
MaxCmdSN: cmd.CmdSN + 10,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func iscsiExecTMFunction(conn *iscsiConnection) error {
|
func iscsiExecTMFunction(conn *iscsiConnection) error {
|
||||||
cmd := conn.req
|
return conn.buildRespPackage(OpSCSITaskResp)
|
||||||
conn.resp = &ISCSICommand{
|
|
||||||
OpCode: OpSCSITaskResp,
|
|
||||||
Final: true,
|
|
||||||
NSG: FullFeaturePhase,
|
|
||||||
StatSN: cmd.ExpStatSN,
|
|
||||||
TaskTag: cmd.TaskTag,
|
|
||||||
ExpCmdSN: cmd.CmdSN + 1,
|
|
||||||
MaxCmdSN: cmd.CmdSN + 10,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func iscsiExecReject(conn *iscsiConnection) error {
|
func iscsiExecReject(conn *iscsiConnection) error {
|
||||||
conn.resp = &ISCSICommand{
|
return conn.buildRespPackage(OpReject)
|
||||||
OpCode: OpReject,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func iscsiExecR2T(conn *iscsiConnection) error {
|
func iscsiExecR2T(conn *iscsiConnection) error {
|
||||||
var val uint
|
return conn.buildRespPackage(OpReady)
|
||||||
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: &api.SCSICommand{}}
|
|
||||||
conn.txIOState = IOSTATE_TX_BHS
|
|
||||||
conn.statSN += 1
|
|
||||||
task := conn.rxTask
|
|
||||||
resp := &ISCSICommand{
|
|
||||||
OpCode: OpReady,
|
|
||||||
StatSN: conn.req.ExpStatSN,
|
|
||||||
TaskTag: conn.req.TaskTag,
|
|
||||||
ExpCmdSN: conn.session.ExpCmdSN,
|
|
||||||
MaxCmdSN: conn.session.ExpCmdSN + 10,
|
|
||||||
R2TSN: task.r2tSN,
|
|
||||||
BufferOffset: uint32(task.offset),
|
|
||||||
DesiredLength: uint32(task.r2tCount),
|
|
||||||
}
|
|
||||||
|
|
||||||
if val = conn.loginParam.sessionParam[ISCSI_PARAM_MAX_BURST].Value; task.r2tCount > int(val) {
|
|
||||||
resp.DesiredLength = uint32(val)
|
|
||||||
}
|
|
||||||
conn.resp = resp
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) {
|
func (s *ISCSITargetDriver) txHandler(conn *iscsiConnection) {
|
||||||
@@ -625,46 +559,12 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
|
|||||||
if err = s.iscsiTaskQueueHandler(task); err != nil {
|
if err = s.iscsiTaskQueueHandler(task); err != nil {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
if scmd.Direction == api.SCSIDataRead {
|
||||||
|
conn.buildRespPackage(OpSCSIIn)
|
||||||
|
} else {
|
||||||
|
conn.buildRespPackage(OpSCSIResp)
|
||||||
|
}
|
||||||
conn.rxTask = nil
|
conn.rxTask = nil
|
||||||
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: &api.SCSICommand{}}
|
|
||||||
conn.txIOState = IOSTATE_TX_BHS
|
|
||||||
conn.statSN += 1
|
|
||||||
resp := &ISCSICommand{
|
|
||||||
Immediate: true,
|
|
||||||
Final: true,
|
|
||||||
StatSN: req.ExpStatSN,
|
|
||||||
TaskTag: req.TaskTag,
|
|
||||||
ExpCmdSN: conn.session.ExpCmdSN,
|
|
||||||
MaxCmdSN: conn.session.ExpCmdSN + 10,
|
|
||||||
Status: scmd.Result,
|
|
||||||
SCSIResponse: 0x00,
|
|
||||||
HasStatus: true,
|
|
||||||
}
|
|
||||||
switch scmd.Direction {
|
|
||||||
case api.SCSIDataRead:
|
|
||||||
resp.OpCode = OpSCSIIn
|
|
||||||
if scmd.InSDBBuffer.Buffer != nil {
|
|
||||||
buf := scmd.InSDBBuffer.Buffer.Bytes()
|
|
||||||
resp.RawData = buf
|
|
||||||
} else {
|
|
||||||
resp.RawData = []byte{}
|
|
||||||
}
|
|
||||||
case api.SCSIDataWrite:
|
|
||||||
resp.OpCode = OpSCSIResp
|
|
||||||
if scmd.InSDBBuffer.Buffer != nil {
|
|
||||||
buf := scmd.InSDBBuffer.Buffer.Bytes()
|
|
||||||
resp.RawData = buf
|
|
||||||
} else {
|
|
||||||
resp.RawData = []byte{}
|
|
||||||
}
|
|
||||||
case api.SCSIDataBidirection:
|
|
||||||
case api.SCSIDataNone:
|
|
||||||
resp.OpCode = OpSCSIResp
|
|
||||||
}
|
|
||||||
if scmd.Result != 0 && scmd.SenseBuffer != nil {
|
|
||||||
resp.RawData = scmd.SenseBuffer.Bytes()
|
|
||||||
}
|
|
||||||
conn.resp = resp
|
|
||||||
}
|
}
|
||||||
case OpSCSITaskReq:
|
case OpSCSITaskReq:
|
||||||
// task management function
|
// task management function
|
||||||
@@ -712,27 +612,10 @@ func (s *ISCSITargetDriver) scsiCommandHandler(conn *iscsiConnection) (err error
|
|||||||
if err = s.iscsiExecTask(task); err != nil {
|
if err = s.iscsiExecTask(task); err != nil {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
conn.buildRespPackage(OpSCSIResp)
|
||||||
conn.rxTask = nil
|
conn.rxTask = nil
|
||||||
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: &api.SCSICommand{}, state: taskSCSI}
|
|
||||||
conn.txIOState = IOSTATE_TX_BHS
|
|
||||||
conn.statSN += 1
|
|
||||||
resp := &ISCSICommand{
|
|
||||||
OpCode: OpSCSIResp,
|
|
||||||
Immediate: true,
|
|
||||||
Final: true,
|
|
||||||
StatSN: req.ExpStatSN,
|
|
||||||
TaskTag: req.TaskTag,
|
|
||||||
ExpCmdSN: conn.session.ExpCmdSN,
|
|
||||||
MaxCmdSN: conn.session.ExpCmdSN + 10,
|
|
||||||
Status: task.scmd.Result,
|
|
||||||
SCSIResponse: 0x00,
|
|
||||||
HasStatus: true,
|
|
||||||
}
|
|
||||||
conn.resp = resp
|
|
||||||
}
|
}
|
||||||
case OpNoopOut:
|
case OpNoopOut:
|
||||||
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag}
|
|
||||||
conn.txIOState = IOSTATE_TX_BHS
|
|
||||||
iscsiExecNoopOut(conn)
|
iscsiExecNoopOut(conn)
|
||||||
case OpLogoutReq:
|
case OpLogoutReq:
|
||||||
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag}
|
conn.txTask = &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func loginKVDeclare(conn *iscsiConnection, negoKV []util.KeyValue) []util.KeyVal
|
|||||||
return negoKV
|
return negoKV
|
||||||
|
|
||||||
}
|
}
|
||||||
func loginKVProcess(conn *iscsiConnection, loginKV map[string]string) ([]util.KeyValue, error) {
|
func (conn *iscsiConnection) processLoginData() ([]util.KeyValue, error) {
|
||||||
var (
|
var (
|
||||||
uintVal uint
|
uintVal uint
|
||||||
ok bool
|
ok bool
|
||||||
@@ -62,6 +62,7 @@ func loginKVProcess(conn *iscsiConnection, loginKV map[string]string) ([]util.Ke
|
|||||||
negoKV []util.KeyValue
|
negoKV []util.KeyValue
|
||||||
kvChanges int
|
kvChanges int
|
||||||
)
|
)
|
||||||
|
loginKV := util.ParseKVText(conn.req.RawData)
|
||||||
|
|
||||||
for key, val := range loginKV {
|
for key, val := range loginKV {
|
||||||
// The MaxRecvDataSegmentLength of initiator
|
// The MaxRecvDataSegmentLength of initiator
|
||||||
|
|||||||
Reference in New Issue
Block a user