-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
140 lines (119 loc) · 3.05 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"log"
"sync"
fc "github.com/bluecmd/fibrechannel"
els "github.com/bluecmd/fibrechannel/els"
"github.com/bluecmd/fikonfarm/fcoe"
)
const (
PortTypeF PortType = 1
PortTypeE PortType = 2
)
type PortType int
type Port interface {
Send(*fc.Frame) error
Receive() (*fc.Frame, error)
String() string
}
type sanSwitch struct {
lock *sync.Mutex
p []Port
pt []PortType
}
func main() {
sw := NewSwitch()
// Add one FCoE F_port
f, err := fcoe.NewPort("ens1")
if err != nil {
log.Fatalf("FCoE port creation failed: %v", err)
}
sw.AddPort(f, PortTypeF)
// Block forever.
select {}
}
func NewSwitch() *sanSwitch {
sw := &sanSwitch{
lock: &sync.Mutex{},
}
return sw
}
func (sw *sanSwitch) AddPort(p Port, pt PortType) {
sw.lock.Lock()
defer sw.lock.Unlock()
sw.p = append(sw.p, p)
sw.pt = append(sw.pt, pt)
go sw.portRecv(p, pt)
log.Printf("Added port %s to switch", p)
}
func (sw *sanSwitch) portRecv(p Port, pt PortType) {
for {
f, err := p.Receive()
if err != nil {
log.Printf("Port %s failed: %v", p.String(), err)
return
}
if f.Type == fc.TypeELS {
fe := els.Frame{}
if err := (&fe).UnmarshalBinary(f.Payload); err != nil {
log.Printf("failed to unmarshal ELS frame: %v", err)
return
}
if fe.Command == els.CmdFLOGI {
if err := sw.handleFLOGI(p, f, fe.Payload); err != nil {
log.Printf("failed to handle FLOGI: %v", err)
return
}
} else {
log.Printf("Unknown ELS command: 0x%02x", fe.Command)
}
} else {
log.Printf("Unknown FC frame type: 0x%02x", f.Type)
}
}
}
func (sw *sanSwitch) newReply(f *fc.Frame) *fc.Frame {
var fr fc.Frame
// TODO(bluecmd): Check that the SOF/EOF
fr.SOF = f.SOF
fr.EOF = f.EOF
fr.CSCtl = new(fc.ClassControl)
fr.Source = f.Destination
fr.Destination = f.Source
fr.OXID = f.OXID
fr.RXID = 0xf000
fr.FCtl = 0x980000
fr.SeqID = f.SeqID
// TODO more
return &fr
}
func (sw *sanSwitch) handleFLOGI(p Port, f *fc.Frame, b []byte) error {
var fr els.FLOGI
if err := (&fr).UnmarshalBinary(b); err != nil {
return err
}
log.Printf("FLOGI [%s -> %s]: %+v", fr.WWPN.String(), fr.WWNN.String(), fr)
//f.p.Send(...)
// 1. Assign FCID
// 2. Buffer credits?
// 3. Send ACC
r := sw.newReply(f)
r.RCtl = 0x23
r.Type = fc.TypeELS
r.Destination = fc.Address([3]byte{0xef, 0x01, 0x00})
r.Payload = []byte{
0x02, 0x00, 0x00, 0x00, 0x20, 0x06, 0x00, 0x10, 0x13, 0x00,
0x08, 0x0c, 0x00, 0x00, 0x27, 0x10, 0x00, 0x00, 0x07, 0xd0,
0x20, 0x0c, 0x00, 0x0d, 0xec, 0x30, 0x98, 0x80, 0x20, 0x01,
0x00, 0x0d, 0xec, 0x30, 0x98, 0x81, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
return p.Send(r)
}