Skip to content
This repository has been archived by the owner on Dec 18, 2020. It is now read-only.

stats #9

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ type SCSIDataBuffer struct {
}

type SCSICommand struct {
OpCode byte
Target *SCSITarget
DeviceID uint64
Device *SCSILu
Expand Down
8 changes: 7 additions & 1 deletion pkg/port/iscsit/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"strings"
"time"

"github.com/openebs/gotgt/pkg/util"
)
Expand Down Expand Up @@ -61,7 +62,7 @@ type ISCSICommand struct {
RawHeader []byte
DataLen int
RawData []byte
SenseLen uint32
SenseLen uint32
Final bool
FinalInSeq bool
Immediate bool
Expand All @@ -87,6 +88,7 @@ type ISCSICommand struct {
StatusDetail uint8

// SCSI commands
SCSIOpCode byte
ExpectedDataLen uint32
CDB []byte
Status byte
Expand All @@ -100,6 +102,8 @@ type ISCSICommand struct {
HasStatus bool
DataSN uint32
BufferOffset uint32

StartTime time.Time
}

func (cmd *ISCSICommand) Bytes() []byte {
Expand Down Expand Up @@ -185,6 +189,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) {
m.AHSLen = int(data[4]) * 4
m.DataLen = int(ParseUint(data[5:8]))
m.TaskTag = uint32(ParseUint(data[16:20]))
m.StartTime = time.Now()
switch m.OpCode {
case OpSCSICmd, OpSCSITaskReq:
m.LUN = [8]byte{data[9]}
Expand All @@ -193,6 +198,7 @@ func parseHeader(data []byte) (*ISCSICommand, error) {
m.Read = data[1]&0x40 == 0x40
m.Write = data[1]&0x20 == 0x20
m.CDB = data[32:48]
m.SCSIOpCode = m.CDB[0]
m.ExpStatSN = uint32(ParseUint(data[28:32]))
case OpSCSIResp:
case OpSCSIOut:
Expand Down
21 changes: 11 additions & 10 deletions pkg/port/iscsit/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var (
)

type iscsiConnection struct {
ConnNum int
state int
authState int
session *ISCSISession
Expand Down Expand Up @@ -99,16 +100,16 @@ const (
)

type iscsiTask struct {
tag uint32
conn *iscsiConnection
cmd *ISCSICommand
scmd *api.SCSICommand
state taskState

offset int
r2tCount int
unsolCount int
expR2TSN int
tag uint32
conn *iscsiConnection
cmd *ISCSICommand
scmd *api.SCSICommand
state taskState
expectedDataLength int64
offset int
r2tCount int
unsolCount int
expR2TSN int

r2tSN uint32
}
Expand Down
193 changes: 168 additions & 25 deletions pkg/port/iscsit/iscsid.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"os"
"strconv"
"sync"
"time"

glog "github.com/Sirupsen/logrus"
"github.com/openebs/gotgt/pkg/api"
Expand All @@ -38,6 +39,11 @@ type ISCSITargetService struct {
Name string
iSCSITargets map[string]*ISCSITarget
done chan bool
stopFeed chan bool
txIO chan Msg
statsEnq chan bool
statsRes chan port.Stats
SCSIIOCount map[int]int64
listen net.Listener
state uint8
lock *sync.RWMutex
Expand All @@ -60,6 +66,11 @@ func NewISCSITargetService(base *scsi.SCSITargetService) (port.SCSITargetService
iSCSITargets: map[string]*ISCSITarget{},
SCSI: base,
done: make(chan bool, 1),
stopFeed: make(chan bool, 1),
txIO: make(chan Msg, 100),
statsEnq: make(chan bool, 1),
statsRes: make(chan port.Stats, 1),
SCSIIOCount: map[int]int64{},
state: STATE_INIT,
lock: &sync.RWMutex{},
}, nil
Expand All @@ -79,6 +90,16 @@ func (s *ISCSITargetService) setState(st uint8) {
s.state = st
}

func (s *ISCSITargetService) Stats() port.Stats {
s.lock.Lock()
defer s.lock.Unlock()

s.statsEnq <- true
stats := <-s.statsRes
stats.SCSIIOCount = s.SCSIIOCount
return stats
}

func (s *ISCSITargetService) NewTarget(tgtName string, configInfo *config.Config) (port.SCSITargetDriver, error) {
if _, ok := s.iSCSITargets[tgtName]; ok {
return nil, fmt.Errorf("target name has been existed")
Expand Down Expand Up @@ -173,7 +194,10 @@ func (s *ISCSITargetService) Stop() error {
}

func (s *ISCSITargetService) Run() error {
var err error
var (
err error
connNum int
)
for _, iSCSITarget := range s.iSCSITargets {
for _, iSCSITPGT := range iSCSITarget.TPGTs {
for portal, _ := range iSCSITPGT.Portals {
Expand All @@ -194,6 +218,7 @@ func (s *ISCSITargetService) Run() error {
s.setState(STATE_TERMINATE)
}()
s.setState(STATE_RUNNING)
go s.StatsFeed()
for {
glog.Info("Listening ...")
conn, err := s.listen.Accept()
Expand All @@ -210,6 +235,8 @@ func (s *ISCSITargetService) Run() error {
glog.Info("Accepting ...")
iscsiConn := &iscsiConnection{conn: conn}
iscsiConn.init()
iscsiConn.ConnNum = connNum
connNum += 1
iscsiConn.rxIOState = IOSTATE_RX_BHS

glog.Infof("connection is connected from %s...\n", conn.RemoteAddr().String())
Expand Down Expand Up @@ -569,13 +596,110 @@ func iscsiExecR2T(conn *iscsiConnection) error {
return nil
}

type Msg struct {
ConnNum int
OpCode int
BlockCount int64
ElapsedTime time.Duration
}

func (s *ISCSITargetService) StatsFeed() {
var (
//msg Msg
//iocounter int64
TotalIOPSPS int64
ReadIOPS int64
WriteIOPS int64
//TotalBlockCount int64

TotalReadTimePS time.Duration
ReadsPS int64
ReadLatency int64
ReadThroughput int64
TotalReadBlockCount int64
AvgReadBlockSize int64

TotalWriteTimePS time.Duration
WritesPS int64
WriteLatency int64
WriteThroughput int64
TotalWriteBlockCount int64
AvgWriteBlockSize int64
)

ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
TotalIOPSPS = ReadsPS + WritesPS
if ReadsPS != 0 {
ReadIOPS = ReadsPS
ReadLatency = int64(TotalReadTimePS) / ReadsPS
AvgReadBlockSize = TotalReadBlockCount / ReadsPS
ReadThroughput = AvgReadBlockSize * ReadsPS
} else {
ReadIOPS = 0
ReadLatency = 0
AvgReadBlockSize = 0
ReadThroughput = 0
}
if WritesPS != 0 {
WriteIOPS = WritesPS
WriteLatency = int64(TotalWriteTimePS) / WritesPS
AvgWriteBlockSize = TotalWriteBlockCount / WritesPS
WriteThroughput = AvgWriteBlockSize * WritesPS
} else {
WriteIOPS = 0
WriteLatency = 0
AvgWriteBlockSize = 0
WriteThroughput = 0
}
ReadsPS = 0
TotalReadTimePS = 0
WritesPS = 0
TotalWriteTimePS = 0
fmt.Println("IOPS =", TotalIOPSPS, ",RL =", ReadLatency, ",WL =", WriteLatency, ",AvgRD =", AvgReadBlockSize, ",AvgWR =", AvgWriteBlockSize, ",RDT =", ReadThroughput, ",WRT =", WriteThroughput)
case <-s.stopFeed:
return
case msg := <-s.txIO:
switch api.SCSICommandType(msg.OpCode) {
case api.READ_6, api.READ_10, api.READ_12, api.READ_16:
ReadsPS += 1
TotalReadTimePS += msg.ElapsedTime
TotalReadBlockCount += msg.BlockCount
break
case api.WRITE_6, api.WRITE_10, api.WRITE_12, api.WRITE_16:
WritesPS += 1
TotalWriteTimePS += msg.ElapsedTime
TotalWriteBlockCount += msg.BlockCount
break
}
case <-s.statsEnq:
s.statsRes <- port.Stats{
ReadIOPS: ReadIOPS,
ReadLatency: ReadLatency,
AvgReadBlockSize: AvgReadBlockSize,
ReadThroughput: ReadThroughput,

WriteIOPS: WriteIOPS,
WriteLatency: WriteLatency,
AvgWriteBlockSize: AvgWriteBlockSize,
WriteThroughput: WriteThroughput,
}

}
}
}

func (s *ISCSITargetService) txHandler(conn *iscsiConnection) {
var (
hdigest uint = 0
ddigest uint = 0
offset uint32 = 0
final bool = false
count uint32 = 0
msg Msg
)
if conn.state == CONN_STATE_SCSI {
hdigest = conn.sessionParam[ISCSI_PARAM_HDRDGST_EN].Value & DIGEST_CRC32C
Expand All @@ -593,7 +717,13 @@ func (s *ISCSITargetService) txHandler(conn *iscsiConnection) {
transferLen := len(resp.RawData)
resp.DataSN = 0
maxCount := conn.maxSeqCount

if resp.OpCode == OpSCSIResp || resp.OpCode == OpSCSIIn {
msg.ConnNum = conn.ConnNum
msg.OpCode = int(resp.SCSIOpCode)
msg.ElapsedTime = time.Since(resp.StartTime)
msg.BlockCount = int64(resp.ExpectedDataLen)
s.txIO <- msg
}
/* send data splitted by segmentLen */
SendRemainingData:
if resp.OpCode == OpSCSIIn {
Expand Down Expand Up @@ -697,10 +827,17 @@ func (s *ISCSITargetService) scsiCommandHandler(conn *iscsiConnection) (err erro
switch req.OpCode {
case OpSCSICmd:
glog.Debugf("SCSI Command processing...")
if _, ok := s.SCSIIOCount[(int)(req.CDB[0])]; ok != false {
s.SCSIIOCount[(int)(req.CDB[0])] += 1
} else {
s.SCSIIOCount[(int)(req.CDB[0])] = 1
}
scmd := &api.SCSICommand{}
task := &iscsiTask{conn: conn, cmd: conn.req, tag: conn.req.TaskTag, scmd: scmd}
task.scmd.OpCode = conn.req.SCSIOpCode
if req.Write {
task.offset = req.DataLen
task.expectedDataLength = int64(req.ExpectedDataLen)
task.r2tCount = int(req.ExpectedDataLen) - req.DataLen
if !req.Final {
task.unsolCount = 1
Expand Down Expand Up @@ -733,20 +870,23 @@ func (s *ISCSITargetService) scsiCommandHandler(conn *iscsiConnection) (err erro
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,
SenseLen: scmd.SenseLength,
StartTime: req.StartTime,
ExpectedDataLen: req.ExpectedDataLen,
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,
SenseLen: scmd.SenseLength,
}
switch scmd.Direction {
case api.SCSIDataRead:
resp.OpCode = OpSCSIIn
resp.SCSIOpCode = conn.req.SCSIOpCode
if scmd.InSDBBuffer.Buffer != nil {
buf := scmd.InSDBBuffer.Buffer.Bytes()
resp.RawData = buf
Expand Down Expand Up @@ -817,21 +957,24 @@ func (s *ISCSITargetService) scsiCommandHandler(conn *iscsiConnection) (err erro
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,
SenseLen: task.scmd.SenseLength,
StartTime: req.StartTime,
OpCode: OpSCSIResp,
ExpectedDataLen: uint32(task.expectedDataLength),
Immediate: true,
Final: true,
StatSN: req.ExpStatSN,
TaskTag: req.TaskTag,
ExpCmdSN: conn.session.ExpCmdSN,
MaxCmdSN: conn.session.ExpCmdSN + 10,
Status: task.scmd.Result,
SCSIOpCode: task.scmd.OpCode,
SCSIResponse: 0x00,
HasStatus: true,
SenseLen: task.scmd.SenseLength,
}
if task.scmd.Result != 0 && task.scmd.SenseBuffer != nil {
resp.RawData = task.scmd.SenseBuffer.Bytes()
}
resp.RawData = task.scmd.SenseBuffer.Bytes()
}
conn.resp = resp
}
case OpNoopOut:
Expand Down
Loading