blob: cc4965cab6a6e51f5bb2977632771e67e3029e50 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package devices
18
19import (
20 "context"
21 "errors"
22 "fmt"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020023 "net"
24 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010025 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020026
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070027 "github.com/google/gopacket"
28 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070029 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070030 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070031 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010032 "github.com/opencord/bbsim/internal/common"
William Kurkian9dadc5b2019-10-22 13:51:57 -040033 omcisim "github.com/opencord/omci-sim"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080034 "github.com/opencord/voltha-protos/v2/go/openolt"
35 "github.com/opencord/voltha-protos/v2/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070036 log "github.com/sirupsen/logrus"
37 "google.golang.org/grpc"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010038 "google.golang.org/grpc/reflection"
Matteo Scandolo4747d292019-08-05 11:50:18 -070039)
40
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070041var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070042 "module": "OLT",
43})
44
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070045type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000046 sync.Mutex
47
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070048 // BBSIM Internals
49 ID int
50 SerialNumber string
51 NumNni int
52 NumPon int
53 NumOnuPerPon int
54 InternalState *fsm.FSM
55 channel chan Message
Zdravko Bozakov681364d2019-11-10 14:28:46 +010056 nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070057
Matteo Scandoloe33447a2019-10-31 12:38:23 -070058 Delay int
59
Matteo Scandolo27428702019-10-11 16:21:16 -070060 Pons []*PonPort
61 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070062
63 // OLT Attributes
64 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000065
66 enableContext context.Context
67 enableContextCancel context.CancelFunc
Matteo Scandolo4747d292019-08-05 11:50:18 -070068}
69
Matteo Scandolo27428702019-10-11 16:21:16 -070070var olt OltDevice
Zdravko Bozakov681364d2019-11-10 14:28:46 +010071var oltServer *grpc.Server
Matteo Scandolo84f7d482019-08-08 19:00:47 -070072
Matteo Scandolo27428702019-10-11 16:21:16 -070073func GetOLT() *OltDevice {
74 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070075}
76
Zdravko Bozakov681364d2019-11-10 14:28:46 +010077func CreateOLT(oltId int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, auth bool, dhcp bool, delay int, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070078 oltLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070079 "ID": oltId,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070080 "NumNni": nni,
81 "NumPon": pon,
82 "NumOnuPerPon": onuPerPon,
Matteo Scandolo4747d292019-08-05 11:50:18 -070083 }).Debug("CreateOLT")
84
Matteo Scandolo84f7d482019-08-08 19:00:47 -070085 olt = OltDevice{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070086 ID: oltId,
87 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", oltId),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070088 OperState: getOperStateFSM(func(e *fsm.Event) {
89 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
90 }),
Zdravko Bozakov681364d2019-11-10 14:28:46 +010091 NumNni: nni,
92 NumPon: pon,
93 NumOnuPerPon: onuPerPon,
94 Pons: []*PonPort{},
95 Nnis: []*NniPort{},
96 Delay: delay,
Matteo Scandolo4747d292019-08-05 11:50:18 -070097 }
98
99 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700100 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700101 olt.InternalState = fsm.NewFSM(
102 "created",
103 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800104 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100105 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700106 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800107 {Name: "delete", Src: []string{"disabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700108 },
109 fsm.Callbacks{
110 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700111 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700112 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100113 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700114 },
115 )
116
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700117 if isMock != true {
118 // create NNI Port
119 nniPort, err := CreateNNI(&olt)
120 if err != nil {
121 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
122 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700123
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700124 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700125 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700126
Matteo Scandolo4747d292019-08-05 11:50:18 -0700127 // create PON ports
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700128 availableCTag := cTagInit
Matteo Scandolo4747d292019-08-05 11:50:18 -0700129 for i := 0; i < pon; i++ {
130 p := PonPort{
131 NumOnu: olt.NumOnuPerPon,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700132 ID: uint32(i),
133 Type: "pon",
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700134 Olt: olt,
Matteo Scandolo27428702019-10-11 16:21:16 -0700135 Onus: []*Onu{},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700136 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700137 p.OperState = getOperStateFSM(func(e *fsm.Event) {
138 oltLogger.WithFields(log.Fields{
139 "ID": p.ID,
140 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
141 })
Matteo Scandolo4747d292019-08-05 11:50:18 -0700142
143 // create ONU devices
144 for j := 0; j < onuPerPon; j++ {
Matteo Scandoloc1147092019-10-29 09:38:33 -0700145 o := CreateONU(olt, p, uint32(j+1), sTag, availableCTag, auth, dhcp)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700146 p.Onus = append(p.Onus, o)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700147 availableCTag = availableCTag + 1
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 }
149
Matteo Scandolo27428702019-10-11 16:21:16 -0700150 olt.Pons = append(olt.Pons, &p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700151 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100152
Matteo Scandolod32c3822019-11-26 15:57:46 -0700153 if isMock != true {
154 if err := olt.InternalState.Event("initialize"); err != nil {
155 log.Errorf("Error initializing OLT: %v", err)
156 return nil
157 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100158 }
159
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700160 return &olt
161}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700162
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100163func (o *OltDevice) InitOlt() error {
164
165 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800166 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100167 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800168 // FIXME there should never be a server running if we are initializing the OLT
169 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100170 }
171
172 // create new channel for processOltMessages Go routine
173 o.channel = make(chan Message)
174
175 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
176 // FIXME we are assuming we have only one NNI
177 if o.Nnis[0] != nil {
178 ch, err := o.Nnis[0].NewVethChan()
179 if err == nil {
180 o.nniPktInChannel = ch
181 } else {
182 log.Errorf("Error getting NNI channel: %v", err)
183 }
184 }
185
186 for i := range olt.Pons {
187 for _, onu := range olt.Pons[i].Onus {
188 if err := onu.InternalState.Event("initialize"); err != nil {
189 log.Errorf("Error initializing ONU: %v", err)
190 return err
191 }
192 }
193 }
194
195 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700196}
197
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800198func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100199
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800200 rebootDelay := common.Options.Olt.OltRebootDelay
201
202 oltLogger.WithFields(log.Fields{
203 "oltId": o.ID,
204 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
205
206 // transition internal state to deleted
207 if err := o.InternalState.Event("delete"); err != nil {
208 oltLogger.WithFields(log.Fields{
209 "oltId": o.ID,
210 }).Errorf("Error deleting OLT: %v", err)
211 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100212 }
213
214 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800215 time.Sleep(1 * time.Second) // we need to give the OLT the time to respond to all the pending gRPC request before stopping the server
216 if err := o.StopOltServer(); err != nil {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100217 return err
218 }
219
220 // terminate the OLT's processOltMessages go routine
221 close(o.channel)
222 // terminate the OLT's processNniPacketIns go routine
223 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100224
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100225 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100226
227 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800228 oltLogger.WithFields(log.Fields{
229 "oltId": o.ID,
230 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231 return err
232 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800233 oltLogger.WithFields(log.Fields{
234 "oltId": o.ID,
235 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100236 return nil
237}
238
239// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800240func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100241 address := common.Options.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700242 lis, err := net.Listen("tcp", address)
243 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700244 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700245 }
246 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100247
Matteo Scandolo4747d292019-08-05 11:50:18 -0700248 openolt.RegisterOpenoltServer(grpcServer, o)
249
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100250 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700251
Matteo Scandolo4747d292019-08-05 11:50:18 -0700252 go grpcServer.Serve(lis)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100253 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700254
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100255 return grpcServer, nil
256}
257
258// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800259func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100260 // TODO handle poweroff vs graceful shutdown
261 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800262 oltLogger.WithFields(log.Fields{
263 "oltId": o.SerialNumber,
264 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100265 oltServer.Stop()
266 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700267 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800268
Matteo Scandolo4747d292019-08-05 11:50:18 -0700269 return nil
270}
271
272// Device Methods
273
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100274// Enable implements the OpenOLT EnableIndicationServer functionality
275func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700276 oltLogger.Debug("Enable OLT called")
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700277
David Bainbridge103cf022019-12-16 20:11:35 +0000278 // If enabled has already been called then an enabled context has
279 // been created. If this is the case then we want to cancel all the
280 // proessing loops associated with that enable before we recreate
281 // new ones
282 o.Lock()
283 if o.enableContext != nil && o.enableContextCancel != nil {
284 o.enableContextCancel()
285 }
286 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
287 o.Unlock()
288
Matteo Scandolo4747d292019-08-05 11:50:18 -0700289 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800290 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700291
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100292 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000293 go o.processOltMessages(o.enableContext, stream, &wg)
294 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700295
296 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100297 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700298 Type: OltIndication,
299 Data: OltIndicationMessage{
300 OperState: UP,
301 },
302 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100303 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700304
305 // send NNI Port Indications
306 for _, nni := range o.Nnis {
307 msg := Message{
308 Type: NniIndication,
309 Data: NniIndicationMessage{
310 OperState: UP,
311 NniPortID: nni.ID,
312 },
313 }
314 o.channel <- msg
315 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100316
David Bainbridge103cf022019-12-16 20:11:35 +0000317 go o.processOmciMessages(o.enableContext, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100318
Matteo Scandolo4747d292019-08-05 11:50:18 -0700319 // send PON Port indications
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100320 for i, pon := range o.Pons {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700321 msg := Message{
322 Type: PonIndication,
323 Data: PonIndicationMessage{
324 OperState: UP,
325 PonPortID: pon.ID,
326 },
327 }
328 o.channel <- msg
329
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100330 for _, onu := range o.Pons[i].Onus {
David Bainbridge103cf022019-12-16 20:11:35 +0000331 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
332 if onu.InternalState.Current() != "initialized" {
333 continue
334 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100335 if err := onu.InternalState.Event("discover"); err != nil {
336 log.Errorf("Error discover ONU: %v", err)
337 return err
Matteo Scandolo4747d292019-08-05 11:50:18 -0700338 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700339 }
340 }
341
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800342 oltLogger.Debug("Enable OLT Done")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700343 wg.Wait()
344 return nil
345}
346
David Bainbridge103cf022019-12-16 20:11:35 +0000347func (o *OltDevice) processOmciMessages(ctx context.Context, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400348 ch := omcisim.GetChannel()
349
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100350 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400351
David Bainbridge103cf022019-12-16 20:11:35 +0000352loop:
353 for {
354 select {
355 case <-ctx.Done():
356 oltLogger.Debug("OMCI processing canceled via context")
357 break loop
358 case message, ok := <-ch:
359 if !ok || ctx.Err() != nil {
360 oltLogger.Debug("OMCI processing canceled via channel close")
361 break loop
362 }
363 onuId := message.Data.OnuId
364 intfId := message.Data.IntfId
365 onu, err := o.FindOnuById(intfId, onuId)
366 if err != nil {
367 oltLogger.Errorf("Failed to find onu: %v", err)
368 continue
369 }
370 go onu.processOmciMessage(message)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400371 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400372 }
David Bainbridge103cf022019-12-16 20:11:35 +0000373
374 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400375}
376
Matteo Scandolo4747d292019-08-05 11:50:18 -0700377// Helpers method
378
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700379func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700380 for _, pon := range o.Pons {
381 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700382 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700383 }
384 }
385 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
386}
387
388func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
389 for _, nni := range o.Nnis {
390 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700391 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700392 }
393 }
394 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
395}
396
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100397func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700398 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
399 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700400 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800401 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700402 }
403
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700404 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700405 "OperState": msg.OperState,
406 }).Debug("Sent Indication_OltInd")
407}
408
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100409func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700410 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700411 nni.OperState.Event("enable")
412 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700413 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700414 Type: nni.Type,
415 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700416 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700417 }}
418
419 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700420 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800421 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700422 }
423
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700424 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700425 "Type": nni.Type,
426 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700427 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700428 }).Debug("Sent Indication_IntfOperInd for NNI")
429}
430
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100431func (o *OltDevice) sendPonIndication(msg PonIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700432 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700433 pon.OperState.Event("enable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700434 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700435 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700436 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700437 }}
438
439 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700440 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800441 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700442 }
443
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700444 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700445 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700446 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700447 }).Debug("Sent Indication_IntfInd")
448
449 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700450 Type: pon.Type,
451 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700452 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700453 }}
454
455 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700456 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800457 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700458 }
459
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700460 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700461 "Type": pon.Type,
462 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700463 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700464 }).Debug("Sent Indication_IntfOperInd for PON")
465}
466
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100467// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000468func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100469 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000470 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700471
David Bainbridge103cf022019-12-16 20:11:35 +0000472loop:
473 for {
474 select {
475 case <-ctx.Done():
476 oltLogger.Debug("OLT Indication processing canceled via context")
477 break loop
478 case message, ok := <-ch:
479 if !ok || ctx.Err() != nil {
480 oltLogger.Debug("OLT Indication processing canceled via closed channel")
481 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700482 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700483
David Bainbridge103cf022019-12-16 20:11:35 +0000484 oltLogger.WithFields(log.Fields{
485 "oltId": o.ID,
486 "messageType": message.Type,
487 }).Trace("Received message")
488
489 switch message.Type {
490 case OltIndication:
491 msg, _ := message.Data.(OltIndicationMessage)
492 if msg.OperState == UP {
493 o.InternalState.Event("enable")
494 o.OperState.Event("enable")
495 } else if msg.OperState == DOWN {
496 o.InternalState.Event("disable")
497 o.OperState.Event("disable")
498 }
499 o.sendOltIndication(msg, stream)
500 case NniIndication:
501 msg, _ := message.Data.(NniIndicationMessage)
502 o.sendNniIndication(msg, stream)
503 case PonIndication:
504 msg, _ := message.Data.(PonIndicationMessage)
505 o.sendPonIndication(msg, stream)
506 default:
507 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
508 }
509 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700510 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100511 wg.Done()
512 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700513}
514
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100515// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000516func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700517 oltLogger.WithFields(log.Fields{
518 "nniChannel": o.nniPktInChannel,
519 }).Debug("Started NNI Channel")
520 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700521
David Bainbridge103cf022019-12-16 20:11:35 +0000522 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700523
David Bainbridge103cf022019-12-16 20:11:35 +0000524loop:
525 for {
526 select {
527 case <-ctx.Done():
528 oltLogger.Debug("NNI Indication processing canceled via context")
529 break loop
530 case message, ok := <-ch:
531 if !ok || ctx.Err() != nil {
532 oltLogger.Debug("NNI Indication processing canceled via channel closed")
533 break loop
534 }
535 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700536
David Bainbridge103cf022019-12-16 20:11:35 +0000537 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700538
David Bainbridge103cf022019-12-16 20:11:35 +0000539 if err != nil {
540 log.WithFields(log.Fields{
541 "IntfType": "nni",
542 "IntfId": nniId,
543 "Pkt": message.Pkt.Data(),
544 }).Error("Can't find Dst MacAddress in packet")
545 return
546 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700547
David Bainbridge103cf022019-12-16 20:11:35 +0000548 onu, err := o.FindOnuByMacAddress(onuMac)
549 if err != nil {
550 log.WithFields(log.Fields{
551 "IntfType": "nni",
552 "IntfId": nniId,
553 "Pkt": message.Pkt.Data(),
554 "MacAddress": onuMac.String(),
555 }).Error("Can't find ONU with MacAddress")
556 return
557 }
558
559 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
560 if err != nil {
561 log.Error("Fail to add double tag to packet")
562 }
563
564 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
565 IntfType: "nni",
566 IntfId: nniId,
567 Pkt: doubleTaggedPkt.Data()}}
568 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
569 oltLogger.WithFields(log.Fields{
570 "IntfType": data.PktInd.IntfType,
571 "IntfId": nniId,
572 "Pkt": doubleTaggedPkt.Data(),
573 }).Errorf("Fail to send PktInd indication: %v", err)
574 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700575 oltLogger.WithFields(log.Fields{
576 "IntfType": data.PktInd.IntfType,
577 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700578 "Pkt": doubleTaggedPkt.Data(),
David Bainbridge103cf022019-12-16 20:11:35 +0000579 "OnuSn": onu.Sn(),
580 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700581 }
582 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100583 wg.Done()
584 oltLogger.WithFields(log.Fields{
585 "nniChannel": o.nniPktInChannel,
586 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700587}
588
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700589// returns an ONU with a given Serial Number
590func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200591 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700592 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700593 for _, pon := range o.Pons {
594 for _, onu := range pon.Onus {
595 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700596 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700597 }
598 }
599 }
600
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700601 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
602}
603
William Kurkian9dadc5b2019-10-22 13:51:57 -0400604// returns an ONU with a given interface/Onu Id
605func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200606 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400607 // memoizing it will remove the bottleneck
608 for _, pon := range o.Pons {
609 if pon.ID == intfId {
610 for _, onu := range pon.Onus {
611 if onu.ID == onuId {
612 return onu, nil
613 }
614 }
615 }
616 }
617 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
618}
619
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700620// returns an ONU with a given Mac Address
621func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200622 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700623 // memoizing it will remove the bottleneck
624 for _, pon := range o.Pons {
625 for _, onu := range pon.Onus {
626 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700627 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700628 }
629 }
630 }
631
632 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700633}
634
Matteo Scandolo4747d292019-08-05 11:50:18 -0700635// GRPC Endpoints
636
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700637func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700638 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700639 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700640 }).Info("Received ActivateOnu call from VOLTHA")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700641
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700642 pon, _ := o.GetPonById(onu.IntfId)
643 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500644 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700645
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700646 if err := _onu.OperState.Event("enable"); err != nil {
647 oltLogger.WithFields(log.Fields{
648 "IntfId": _onu.PonPortID,
649 "OnuSn": _onu.Sn(),
650 "OnuId": _onu.ID,
651 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700652 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700653 if err := _onu.InternalState.Event("enable"); err != nil {
654 oltLogger.WithFields(log.Fields{
655 "IntfId": _onu.PonPortID,
656 "OnuSn": _onu.Sn(),
657 "OnuId": _onu.ID,
658 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
659 }
660
661 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
662
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700663 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664}
665
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700666func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700667 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700668 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700669}
670
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700671func (o OltDevice) DeleteOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700672 oltLogger.Error("DeleteOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700673 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700674}
675
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700676func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700677 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800678 oltLogger.WithFields(log.Fields{
679 "oltId": o.ID,
680 }).Info("Disabling OLT")
681
682 for i, pon := range o.Pons {
683 // disable all onus
684 for _, onu := range o.Pons[i].Onus {
685 // NOTE order of these is important.
686 if err := onu.OperState.Event("disable"); err != nil {
687 log.Errorf("Error disabling ONU oper state: %v", err)
688 }
689 if err := onu.InternalState.Event("disable"); err != nil {
690 log.Errorf("Error disabling ONU: %v", err)
691 }
692 }
693
694 // disable PONs
695 msg := Message{
696 Type: PonIndication,
697 Data: PonIndicationMessage{
698 OperState: DOWN,
699 PonPortID: pon.ID,
700 },
701 }
702
703 o.channel <- msg
704 }
705
706 // disable NNI
707 for _, nni := range o.Nnis {
708 msg := Message{
709 Type: NniIndication,
710 Data: NniIndicationMessage{
711 OperState: DOWN,
712 NniPortID: nni.ID,
713 },
714 }
715 o.channel <- msg
716 }
717
718 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100719 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700720 Type: OltIndication,
721 Data: OltIndicationMessage{
722 OperState: DOWN,
723 },
724 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100725 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700726 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700727}
728
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700729func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700730 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700731 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700732}
733
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100734func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700735 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700736 o.Enable(stream)
737 return nil
738}
739
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700740func (o OltDevice) EnablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700741 oltLogger.Error("EnablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700742 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700743}
744
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700745func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700746 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700747 "IntfId": flow.AccessIntfId,
748 "OnuId": flow.OnuId,
749 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700750 "InnerVlan": flow.Classifier.IVid,
751 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700752 "FlowType": flow.FlowType,
753 "FlowId": flow.FlowId,
754 "UniID": flow.UniId,
755 "PortNo": flow.PortNo,
756 }).Tracef("OLT receives Flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700757 // TODO optionally store flows somewhere
758
759 if flow.AccessIntfId == -1 {
760 oltLogger.WithFields(log.Fields{
761 "FlowId": flow.FlowId,
762 }).Debugf("This is an OLT flow")
763 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700764 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700765 if err != nil {
766 oltLogger.WithFields(log.Fields{
767 "OnuId": flow.OnuId,
768 "IntfId": flow.AccessIntfId,
769 "err": err,
770 }).Error("Can't find PonPort")
771 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700772 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700773 if err != nil {
774 oltLogger.WithFields(log.Fields{
775 "OnuId": flow.OnuId,
776 "IntfId": flow.AccessIntfId,
777 "err": err,
778 }).Error("Can't find Onu")
779 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700780
781 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700782 Type: FlowUpdate,
783 Data: OnuFlowUpdateMessage{
784 PonPortID: pon.ID,
785 OnuID: onu.ID,
786 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700787 },
788 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700789 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700790 }
791
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700792 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700793}
794
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700795func (o OltDevice) FlowRemove(context.Context, *openolt.Flow) (*openolt.Empty, error) {
796 oltLogger.Tracef("received FlowRemove")
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700797 // TODO store flows somewhere
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700798 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700799}
800
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700801func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700802 oltLogger.Error("HeartbeatCheck not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700803 return new(openolt.Heartbeat), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700804}
805
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700806func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700807
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700808 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700809 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700810 "PonPorts": o.NumPon,
811 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700812 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100813 devinfo.Vendor = common.Options.Olt.Vendor
814 devinfo.Model = common.Options.Olt.Model
815 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
816 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
817 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700818 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700819 devinfo.OnuIdStart = 1
820 devinfo.OnuIdEnd = 255
821 devinfo.AllocIdStart = 1024
822 devinfo.AllocIdEnd = 16383
823 devinfo.GemportIdStart = 1024
824 devinfo.GemportIdEnd = 65535
825 devinfo.FlowIdStart = 1
826 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700827 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100828 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -0700829
830 return devinfo, nil
831}
832
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700833func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700834 pon, _ := o.GetPonById(omci_msg.IntfId)
835 onu, _ := pon.GetOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700836 oltLogger.WithFields(log.Fields{
837 "IntfId": onu.PonPortID,
838 "OnuId": onu.ID,
839 "OnuSn": onu.Sn(),
840 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700841 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700842 Type: OMCI,
843 Data: OmciMessage{
844 OnuSN: onu.SerialNumber,
845 OnuID: onu.ID,
846 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700847 },
848 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700849 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700850 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700851}
852
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700853func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700854 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700855 if err != nil {
856 oltLogger.WithFields(log.Fields{
857 "OnuId": onuPkt.OnuId,
858 "IntfId": onuPkt.IntfId,
859 "err": err,
860 }).Error("Can't find PonPort")
861 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700862 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700863 if err != nil {
864 oltLogger.WithFields(log.Fields{
865 "OnuId": onuPkt.OnuId,
866 "IntfId": onuPkt.IntfId,
867 "err": err,
868 }).Error("Can't find Onu")
869 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700870
Matteo Scandolo075b1892019-10-07 12:11:07 -0700871 oltLogger.WithFields(log.Fields{
872 "IntfId": onu.PonPortID,
873 "OnuId": onu.ID,
874 "OnuSn": onu.Sn(),
875 }).Tracef("Received OnuPacketOut")
876
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700877 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700878 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700879
Matteo Scandolo075b1892019-10-07 12:11:07 -0700880 msg := Message{
881 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700882 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -0700883 IntfId: onuPkt.IntfId,
884 OnuId: onuPkt.OnuId,
885 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700886 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700887 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700888 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700889 onu.Channel <- msg
890
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700891 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700892}
893
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700894func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800895 oltLogger.WithFields(log.Fields{
896 "oltId": o.ID,
897 }).Info("Shutting down")
898 go o.RestartOLT()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700899 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700900}
901
902func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700903 oltLogger.Error("ReenableOlt not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700904 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700905}
906
907func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700908 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
909
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100910 o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700911 // NOTE should we return an error if sendNniPakcet fails?
912 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700913}
914
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700915func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700916 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700917 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700918}
919
Matteo Scandolo4747d292019-08-05 11:50:18 -0700920func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700921 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700922 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700923}
924
925func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700926 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700927 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -0700928}
929
930func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700931 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700932 return new(openolt.Empty), nil
933}
934
935func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700936 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700937 return new(openolt.Empty), nil
938}
939
940func (s OltDevice) CreateTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700941 oltLogger.Info("received CreateTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700942 return new(openolt.Empty), nil
943}
944
945func (s OltDevice) RemoveTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700946 oltLogger.Info("received RemoveTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700947 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700948}