forked from platinasystems/vnet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vnet.go
282 lines (240 loc) · 6.94 KB
/
vnet.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// Copyright 2016 Platina Systems, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package vnet
import (
"net"
"github.com/platinasystems/elib"
"github.com/platinasystems/elib/cpu"
"github.com/platinasystems/elib/dep"
"github.com/platinasystems/elib/loop"
"github.com/platinasystems/elib/parse"
"github.com/platinasystems/vnet/internal/dbgvnet"
"github.com/platinasystems/xeth"
)
//Debug Flags
var AdjDebug bool
// drivers/net/ethernet/xeth/platina_mk1.c: xeth.MsgIfinfo
//
// vnetd.go moved to go/platform/mk1/vnetd.go
// PortEntry go/main/goes-platina-mk1/vnetd.go:vnetdInit() xeth.XETH_MSG_KIND_IFINFO
// PortProvision go/main/goes-platina-mk1/vnetd.go:parsePortConfig() from entry Ports
//
// PortConfig fe1/platform.go:parsePortConfig() PortProvision
// Port fe1/internal/fe1a/port_init.go:PortInit()
//
// 1. go/main/goes-platina-mk1/vnetd
// 2. vnet/unix/fdb PortEntry from msg(1)
// vnetd makes PortProvision(3) from PortEntry
// platform.go parses portprovision to create PortConfig(4)
// which PortInit uses to set config structure(5).
//
// NOTE: PortEntry is used by port, vlan, and bridge devtypes
type PortEntry struct {
Net uint64
Ifindex int32
Iflinkindex int32 // system side eth# ifindex
Ifname string
Flags xeth.EthtoolPrivFlags
Iff net.Flags
Speed xeth.Mbps
Autoneg uint8
PortVid uint16
Stag uint16 // internal vlan tag for bridge
Ctag uint16 // vlan tag to identify vlan member and set l3_iif/vrf via vlan_xlate
Portindex int16
Subportindex int8
PuntIndex uint8 // 0-based meth#, derived from Iflinkindex
Devtype uint8
StationAddr net.HardwareAddr
IPNets []*net.IPNet
}
var Ports map[string]*PortEntry // FIXME ifname of bridge need not be unique across netns
var PortsByIndex map[int32]*PortEntry // FIXME - driver only sends platina-mk1 type
var SiByIfindex map[int32]Si // FIXME ifindex is not unique across netns, also impacts PortsByIndex[]
type BridgeNotifierFn func()
func (v *Vnet) SetSiByIfindex(ifindex uint32, si Si) {
if SiByIfindex == nil {
SiByIfindex = make(map[int32]Si)
}
SiByIfindex[int32(ifindex)] = si
}
// port or bridge member
func SetPort(ifname string) *PortEntry {
if Ports == nil {
Ports = make(map[string]*PortEntry)
}
entry, found := Ports[ifname]
if !found {
entry = new(PortEntry)
entry.StationAddr = make(net.HardwareAddr, 6)
Ports[ifname] = entry
}
entry.Ifname = ifname
return entry
}
func SetPortByIndex(ifindex int32, ifname string) *PortEntry {
if PortsByIndex == nil {
PortsByIndex = make(map[int32]*PortEntry)
}
PortsByIndex[ifindex] = Ports[ifname]
return PortsByIndex[ifindex]
}
func GetPortByIndex(ifindex int32) (entry *PortEntry) {
if PortsByIndex == nil {
return nil
}
entry, _ = PortsByIndex[ifindex]
return entry
}
func UnsetPort(ifname string) {
dbgvnet.Bridge.Log(ifname)
entry, found := Ports[ifname]
if found {
dbgvnet.Bridge.Logf("delete port %v ctag:%v stag:%v, ifindex %v",
ifname, entry.Ctag, entry.Stag, entry.Ifindex)
delete(SiByIfindex, entry.Ifindex)
delete(PortsByIndex, entry.Ifindex)
delete(Ports, ifname)
dbgvnet.Bridge.Logf("%+v", entry)
} else {
dbgvnet.Bridge.Logf("delete port %v, not found", ifname)
}
}
func GetNumSubports(ifname string) (numSubports uint) {
numSubports = 0
entry, found := Ports[ifname]
if !found {
return
}
portindex := entry.Portindex
for _, pe := range Ports {
if pe.Devtype == xeth.XETH_DEVTYPE_XETH_PORT &&
pe.Portindex == int16(portindex) {
numSubports++
}
}
return
}
func IfName(portindex, subportindex int) (name string) {
name = ""
for _, pe := range Ports {
if int(pe.Portindex) == portindex && int(pe.Subportindex) == subportindex {
name = pe.Ifname
}
}
return
}
var (
PortIsCopper = func(ifname string) bool { return false }
PortIsFec74 = func(ifname string) bool { return false }
PortIsFec91 = func(ifname string) bool { return false }
)
type RxTx int
const (
Rx RxTx = iota
Tx
NRxTx
)
var rxTxStrings = [...]string{
Rx: "rx",
Tx: "tx",
}
func (x RxTx) String() (s string) {
return elib.Stringer(rxTxStrings[:], int(x))
}
type IsDel bool
func (x IsDel) String() string {
if x {
return "delete"
}
return "add"
}
//go:generate gentemplate -id initHook -d Package=vnet -d DepsType=initHookVec -d Type=initHook -d Data=hooks github.com/platinasystems/elib/dep/dep.tmpl
type initHook func(v *Vnet)
var initHooks initHookVec
func AddInit(f initHook, deps ...*dep.Dep) { initHooks.Add(f, deps...) }
func (v *Vnet) configure(in *parse.Input) (err error) {
if err = v.ConfigurePackages(in); err != nil {
return
}
if err = v.InitPackages(); err != nil {
return
}
return
}
func (v *Vnet) TimeDiff(t0, t1 cpu.Time) float64 { return v.loop.TimeDiff(t1, t0) }
func (v *Vnet) Run(in *parse.Input) (err error) {
loop.AddInit(func(l *loop.Loop) {
v.interfaceMain.init()
v.CliInit()
v.eventInit()
for i := range initHooks.hooks {
initHooks.Get(i)(v)
}
if err := v.configure(in); err != nil {
panic(err)
}
})
v.loop.Run()
err = v.ExitPackages()
return
}
func (v *Vnet) Quit() { v.loop.Quit() }
func (pe *PortEntry) AddIPNet(ipnet *net.IPNet) {
pe.IPNets = append(pe.IPNets, ipnet)
}
func (pe *PortEntry) DelIPNet(ipnet *net.IPNet) {
for i, peipnet := range pe.IPNets {
if peipnet.IP.Equal(ipnet.IP) {
n := len(pe.IPNets) - 1
copy(pe.IPNets[i:], pe.IPNets[i+1:])
pe.IPNets = pe.IPNets[:n]
break
}
}
}
type ActionType int
const (
PreVnetd ActionType = iota // before vnetd is started
ReadyVnetd // vnetd has declared it's ready
PostReadyVnetd // vnetd processing something initated from previous state
Dynamic // free-run case
)
// Could collapse all vnet Hooks calls into this message
// to avoid direct function calls from vnet to fe
type SviVnetFeMsg struct {
data []byte
}
const (
MSG_FROM_VNET = iota
MSG_SVI_BRIDGE_ADD
MSG_SVI_BRIDGE_DELETE
MSG_SVI_BRIDGE_MEMBER_ADD
MSG_SVI_BRIDGE_MEMBER_DELETE
)
const (
MSG_FROM_FE = iota + 128
MSG_SVI_FDB_ADD
MSG_SVI_FDB_DELETE
)
type FromFeMsg struct {
MsgId uint8
Addr [6]uint8
Stag uint16
PipePort uint16
}
var SviFromFeCh chan FromFeMsg // for l2-mod learning event reporting
// simplified hooks for direct calls to fe1 from vnet
type BridgeAddDelHook_t func(brsi Si, stag uint16, puntIndex uint8, addr net.HardwareAddr, isAdd bool) (err error)
type BridgeMemberAddDelHook_t func(stag uint16, brmSi Si, pipe_port uint16, ctag uint16, isAdd bool, nBrm uint8) (err error)
type BridgeMemberLookup_t func(stag uint16, addr net.HardwareAddr) (pipe_port uint16, err error)
func (v *Vnet) RegisterBridgeAddDelHook(h BridgeAddDelHook_t) {
v.BridgeAddDelHook = h
}
func (v *Vnet) RegisterBridgeMemberAddDelHook(h BridgeMemberAddDelHook_t) {
v.BridgeMemberAddDelHook = h
}
func (v *Vnet) RegisterBridgeMemberLookup(h BridgeMemberLookup_t) {
v.BridgeMemberLookup = h
}