fix bugs and make it run basically

This commit is contained in:
Lei Xue
2016-08-27 20:07:51 +08:00
parent f97ab027de
commit aedc09021f
22 changed files with 1997 additions and 431 deletions

View File

@@ -1,5 +1,5 @@
/*
Copyright 2015 The GoStor Authors All rights reserved.
Copyright 2016 The GoStor Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,13 +16,133 @@ limitations under the License.
package iscsit
import "crypto/rand"
import (
"fmt"
"math/rand"
"time"
)
var (
SESSION_NORMAL int = 0
SESSION_DISCOVERY int = 1
)
var DIGEST_CRC32C uint = 1 << 1
var DIGEST_NONE uint = 1 << 0
var DIGEST_ALL uint = DIGEST_NONE | DIGEST_CRC32C
var BHS_SIZE = 48
const (
MAX_QUEUE_CMD_MIN = 1
MAX_QUEUE_CMD_DEF = 128
MAX_QUEUE_CMD_MAX = 512
)
const (
ISCSI_PARAM_MAX_RECV_DLENGTH = iota
ISCSI_PARAM_HDRDGST_EN
ISCSI_PARAM_DATADGST_EN
ISCSI_PARAM_INITIAL_R2T_EN
ISCSI_PARAM_MAX_R2T
ISCSI_PARAM_IMM_DATA_EN
ISCSI_PARAM_FIRST_BURST
ISCSI_PARAM_MAX_BURST
ISCSI_PARAM_PDU_INORDER_EN
ISCSI_PARAM_DATASEQ_INORDER_EN
ISCSI_PARAM_ERL
ISCSI_PARAM_IFMARKER_EN
ISCSI_PARAM_OFMARKER_EN
ISCSI_PARAM_DEFAULTTIME2WAIT
ISCSI_PARAM_DEFAULTTIME2RETAIN
ISCSI_PARAM_OFMARKINT
ISCSI_PARAM_IFMARKINT
ISCSI_PARAM_MAXCONNECTIONS
/* iSCSI Extensions for RDMA (RFC5046) */
ISCSI_PARAM_RDMA_EXTENSIONS
ISCSI_PARAM_TARGET_RDSL
ISCSI_PARAM_INITIATOR_RDSL
ISCSI_PARAM_MAX_OUTST_PDU
/* "local" parmas, never sent to the initiator */
ISCSI_PARAM_FIRST_LOCAL
ISCSI_PARAM_MAX_XMIT_DLENGTH = ISCSI_PARAM_FIRST_LOCAL
ISCSI_PARAM_MAX_QUEUE_CMD
/* must always be last */
ISCSI_PARAM_MAX
)
type ISCSISessionParam struct {
State int
Value uint
}
/*
* The defaults here are according to the spec and must not be changed,
* otherwise the initiator may make the wrong assumption. If you want
* to change a value, edit the value in iscsi_target_create.
*
* The param MaxXmitDataSegmentLength doesn't really exist. It's a way
* to remember the RDSL of the initiator, which defaults to 8k if he has
* not told us otherwise.
*/
type iscsiSessionKeys struct {
name string
def uint
min uint
max uint
}
var sessionKeys []iscsiSessionKeys = []iscsiSessionKeys{
// ISCSI_PARAM_MAX_RECV_DLENGTH
{"MaxRecvDataSegmentLength", 8192, 512, 16777215},
// ISCSI_PARAM_HDRDGST_EN
{"HeaderDigest", DIGEST_NONE, DIGEST_NONE, DIGEST_ALL},
// ISCSI_PARAM_DATADGST_EN
{"DataDigest", DIGEST_NONE, DIGEST_NONE, DIGEST_ALL},
// ISCSI_PARAM_INITIAL_R2T_EN
{"InitialR2T", 1, 0, 1},
// ISCSI_PARAM_MAX_R2T
{"MaxOutstandingR2T", 1, 1, 65535},
// ISCSI_PARAM_IMM_DATA_EN
{"ImmediateData", 1, 0, 1},
// ISCSI_PARAM_FIRST_BURST
{"FirstBurstLength", 65536, 512, 16777215},
// ISCSI_PARAM_MAX_BURST
{"MaxBurstLength", 262144, 512, 16777215},
// ISCSI_PARAM_PDU_INORDER_EN
{"DataPDUInOrder", 1, 0, 1},
// ISCSI_PARAM_DATASEQ_INORDER_EN
{"DataSequenceInOrder", 1, 0, 1},
// ISCSI_PARAM_ERL
{"ErrorRecoveryLevel", 0, 0, 2},
// ISCSI_PARAM_IFMARKER_EN
{"IFMarker", 0, 0, 1},
// ISCSI_PARAM_OFMARKER_EN
{"OFMarker", 0, 0, 1},
// ISCSI_PARAM_DEFAULTTIME2WAIT
{"DefaultTime2Wait", 2, 0, 3600},
// ISCSI_PARAM_DEFAULTTIME2RETAIN
{"DefaultTime2Retain", 20, 0, 3600},
// ISCSI_PARAM_OFMARKINT
{"OFMarkInt", 2048, 1, 65535},
// ISCSI_PARAM_IFMARKINT
{"IFMarkInt", 2048, 1, 65535},
// ISCSI_PARAM_MAXCONNECTIONS
{"MaxConnections", 1, 1, 65535},
// ISCSI_PARAM_RDMA_EXTENSIONS
{"RDMAExtensions", 0, 0, 1},
// ISCSI_PARAM_TARGET_RDSL
{"TargetRecvDataSegmentLength", 8192, 512, 16777215},
// ISCSI_PARAM_INITIATOR_RDSL
{"InitiatorRecvDataSegmentLength", 8192, 512, 16777215},
// ISCSI_PARAM_MAX_OUTST_PDU
{"MaxOutstandingUnexpectedPDUs", 0, 2, 4294967295},
// "local" parmas, never sent to the initiator
// ISCSI_PARAM_MAX_XMIT_DLENGTH
{"MaxXmitDataSegmentLength", 8192, 512, 16777215},
// ISCSI_PARAM_MAX_QUEUE_CMD
{"MaxQueueCmd", MAX_QUEUE_CMD_DEF, MAX_QUEUE_CMD_MIN, MAX_QUEUE_CMD_MAX},
}
// Session is an iSCSI session.
type ISCSISession struct {
Refcount int
@@ -30,58 +150,112 @@ type ISCSISession struct {
InitiatorAlias string
Target *ISCSITarget
Isid uint64
Tsih uint16
Tsih uint64
ExpCmdSN uint32
// only one connection per session
Connections []*ISCSIConnection
Commands []*ISCSICommand
PendingCommands []*ISCSICommand
ExpectionCommandSN uint32
MaxQueueCommand uint32
SessionParam []ISCSISessionParam
Info string
Rdma int
Connections []*iscsiConnection
Commands []*ISCSICommand
PendingTasks taskQueue
MaxQueueCommand uint32
SessionParam []ISCSISessionParam
Info string
Rdma int
}
type ISCSIHeader struct {
type taskQueue []*iscsiTask
func (tq taskQueue) Len() int { return len(tq) }
func (tq taskQueue) Less(i, j int) bool {
// We want Pop to give us the highest, not lowest, priority so we use greater than here.
return tq[i].cmd.CmdSN > tq[j].cmd.CmdSN
}
type ISCSIPdu struct {
Bhs ISCSIHeader
AhsSize uint
DataSize uint
func (tq taskQueue) Swap(i, j int) {
tq[i], tq[j] = tq[j], tq[i]
}
type ISCSIConnection struct {
State int
RxIostate int
TxIostate int
Refcount int
func (tq *taskQueue) Push(x interface{}) {
item := x.(*iscsiTask)
*tq = append(*tq, item)
}
Session *ISCSISession
func (tq *taskQueue) Pop() interface{} {
old := *tq
n := len(old)
item := old[n-1]
*tq = old[0 : n-1]
return item
}
TID int
CID int
Auth AuthMethod
StatSN uint32
ExpectionStatSN uint32
CommandSN uint32
ExpectionCommandSN uint32
MaxCommandSN uint32
Request ISCSIPdu
Response ISCSIPdu
// The BHS is 48 bytes long. The Opcode and DataSegmentLength fields
// appear in all iSCSI PDUs. In addition, when used, the Initiator Task
// Tag and Logical Unit Number always appear in the same location in the
// header.
type iscsiHeader struct {
opcode uint8
flags uint8 // Final bit
rsvd2 [2]uint8
hlength uint8 // AHSs total length
dlength [3]uint8 // Data length
lun [8]uint8
itt uint8 // Initiator Task Tag
ttt uint8 // Target Task Tag
statsn uint8
expStatSN uint8
maxStatSN uint8
other [12]uint8
}
type iscsiPdu struct {
bhs iscsiHeader
ahsSize uint
dataSize uint
}
// New creates a new session.
func NewISCSISession() (*ISCSISession, error) {
var tsih uint16
b := make([]byte, 2)
if _, err := rand.Read(b); err != nil {
return nil, err
}
tsih += uint16(b[0]) << 8
tsih += uint16(b[1])
func (s *ISCSITargetService) NewISCSISession(conn *iscsiConnection) (*ISCSISession, error) {
var (
target *ISCSITarget
tsih uint64
)
return &ISCSISession{
Tsih: tsih,
}, nil
for _, t := range s.Targets {
if t.TID == conn.tid {
target = t
break
}
}
if target == nil {
return nil, fmt.Errorf("No target found with tid(%d)", conn.tid)
}
for {
rand.Seed(int64(time.Now().UTC().Nanosecond()))
tsih = uint64(rand.Uint32())
for _, s := range target.Sessions {
if s.Tsih == tsih {
tsih = 0
break
}
}
if tsih != 0 {
break
}
}
sess := &ISCSISession{
Tsih: tsih,
Initiator: conn.initiator,
InitiatorAlias: conn.initiatorAlias,
Target: target,
Connections: []*iscsiConnection{conn},
SessionParam: conn.sessionParam,
MaxQueueCommand: uint32(conn.sessionParam[ISCSI_PARAM_MAX_QUEUE_CMD].Value),
Rdma: 0,
ExpCmdSN: conn.expCmdSN,
}
conn.session = sess
return sess, nil
}