blob: 8a0d01e31be3310bf0a6fd338f375e46c2da2763 [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 Scandolodf3f85d2020-01-15 12:50:48 -080029 "github.com/google/gopacket/pcap"
Matteo Scandolo4747d292019-08-05 11:50:18 -070030 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070031 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070032 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010033 "github.com/opencord/bbsim/internal/common"
William Kurkian9dadc5b2019-10-22 13:51:57 -040034 omcisim "github.com/opencord/omci-sim"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080035 "github.com/opencord/voltha-protos/v2/go/openolt"
Anand S Katti09541352020-01-29 15:54:01 +053036 tech_profile "github.com/opencord/voltha-protos/v2/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070037 log "github.com/sirupsen/logrus"
38 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053039 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010040 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053041 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070042)
43
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070044var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070045 "module": "OLT",
46})
47
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070048type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000049 sync.Mutex
50
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070051 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053052 ID int
53 SerialNumber string
54 NumNni int
55 NumPon int
56 NumOnuPerPon int
57 InternalState *fsm.FSM
58 channel chan Message
59 nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
60 nniHandle *pcap.Handle // handle on the NNI interface, close it when shutting down the NNI channel
Pragya Arya8bdb4532020-03-02 17:08:09 +053061 Flows map[FlowKey]openolt.Flow
Pragya Arya2225f202020-01-29 18:05:01 +053062 Delay int
63 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053064 EventChannel chan common.Event
65 PublishEvents bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070066
Matteo Scandolo27428702019-10-11 16:21:16 -070067 Pons []*PonPort
68 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070069
70 // OLT Attributes
71 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000072
73 enableContext context.Context
74 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053075
76 OpenoltStream *openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053077 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070078}
79
Matteo Scandolo27428702019-10-11 16:21:16 -070080var olt OltDevice
Zdravko Bozakov681364d2019-11-10 14:28:46 +010081var oltServer *grpc.Server
Matteo Scandolo84f7d482019-08-08 19:00:47 -070082
Matteo Scandolo27428702019-10-11 16:21:16 -070083func GetOLT() *OltDevice {
84 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070085}
86
Pragya Arya324337e2020-02-20 14:35:08 +053087func CreateOLT(oltId int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, auth bool, dhcp bool, delay int, ca string, enablePerf bool, event bool, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070088 oltLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070089 "ID": oltId,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070090 "NumNni": nni,
91 "NumPon": pon,
92 "NumOnuPerPon": onuPerPon,
Matteo Scandolo4747d292019-08-05 11:50:18 -070093 }).Debug("CreateOLT")
94
Matteo Scandolo84f7d482019-08-08 19:00:47 -070095 olt = OltDevice{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070096 ID: oltId,
97 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", oltId),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070098 OperState: getOperStateFSM(func(e *fsm.Event) {
99 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
100 }),
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800101 NumNni: nni,
102 NumPon: pon,
103 NumOnuPerPon: onuPerPon,
104 Pons: []*PonPort{},
105 Nnis: []*NniPort{},
106 Delay: delay,
107 Flows: make(map[FlowKey]openolt.Flow),
108 enablePerf: enablePerf,
Pragya Arya324337e2020-02-20 14:35:08 +0530109 PublishEvents: event,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700110 }
111
Pragya Arya2225f202020-01-29 18:05:01 +0530112 if val, ok := ControlledActivationModes[ca]; ok {
113 olt.ControlledActivation = val
114 } else {
115 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
116 olt.ControlledActivation = Default
117 }
118
Matteo Scandolo4747d292019-08-05 11:50:18 -0700119 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700120 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700121 olt.InternalState = fsm.NewFSM(
122 "created",
123 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800124 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100125 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700126 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800127 //delete event in enabled state below is for reboot OLT case.
128 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700129 },
130 fsm.Callbacks{
131 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700132 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700133 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100134 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135 },
136 )
137
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700138 if isMock != true {
139 // create NNI Port
140 nniPort, err := CreateNNI(&olt)
141 if err != nil {
142 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
143 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700144
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700145 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700146 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700147
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 // create PON ports
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700149 availableCTag := cTagInit
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150 for i := 0; i < pon; i++ {
Pragya Arya2225f202020-01-29 18:05:01 +0530151 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700152
153 // create ONU devices
154 for j := 0; j < onuPerPon; j++ {
Matteo Scandolo583f17d2020-02-13 10:35:17 -0800155 delay := time.Duration(olt.Delay*j) * time.Millisecond
Pragya Arya2225f202020-01-29 18:05:01 +0530156 o := CreateONU(&olt, *p, uint32(j+1), sTag, availableCTag, auth, dhcp, delay, isMock)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700157 p.Onus = append(p.Onus, o)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700158 availableCTag = availableCTag + 1
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159 }
160
Pragya Arya6a708d62020-01-01 17:17:20 +0530161 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700162 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100163
Matteo Scandolod32c3822019-11-26 15:57:46 -0700164 if isMock != true {
165 if err := olt.InternalState.Event("initialize"); err != nil {
166 log.Errorf("Error initializing OLT: %v", err)
167 return nil
168 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100169 }
170
Pragya Arya324337e2020-02-20 14:35:08 +0530171 if olt.PublishEvents {
172 log.Debugf("BBSim event publishing is enabled")
173 // Create a channel to write event messages
174 olt.EventChannel = make(chan common.Event, 100)
175 }
176
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700177 return &olt
178}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700179
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100180func (o *OltDevice) InitOlt() error {
181
182 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800183 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100184 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800185 // FIXME there should never be a server running if we are initializing the OLT
186 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100187 }
188
189 // create new channel for processOltMessages Go routine
190 o.channel = make(chan Message)
191
192 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
193 // FIXME we are assuming we have only one NNI
194 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800195 // NOTE we want to make sure the state is down when we initialize the OLT,
196 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
197 // in-band management
198 o.Nnis[0].OperState.SetState("down")
199 ch, handle, err := o.Nnis[0].NewVethChan()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100200 if err == nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800201 oltLogger.WithFields(log.Fields{
202 "Type": o.Nnis[0].Type,
203 "IntfId": o.Nnis[0].ID,
204 "OperState": o.Nnis[0].OperState.Current(),
205 }).Info("NNI Channel created")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100206 o.nniPktInChannel = ch
Matteo Scandolo401503a2019-12-11 14:48:14 -0800207 o.nniHandle = handle
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100208 } else {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800209 oltLogger.Errorf("Error getting NNI channel: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100210 }
211 }
212
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100213 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700214}
215
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800216func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100217
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800218 rebootDelay := common.Options.Olt.OltRebootDelay
219
220 oltLogger.WithFields(log.Fields{
221 "oltId": o.ID,
222 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
223
224 // transition internal state to deleted
225 if err := o.InternalState.Event("delete"); err != nil {
226 oltLogger.WithFields(log.Fields{
227 "oltId": o.ID,
228 }).Errorf("Error deleting OLT: %v", err)
229 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100230 }
231
232 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800233 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
234 if err := o.StopOltServer(); err != nil {
Pragya Arya2225f202020-01-29 18:05:01 +0530235 oltLogger.Errorf("Error in stopping OLT server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100236 return err
237 }
238
Pragya Arya2225f202020-01-29 18:05:01 +0530239 for _, pon := range olt.Pons {
240 msg := Message{
241 Type: PonIndication,
242 Data: PonIndicationMessage{
243 OperState: DOWN,
244 PonPortID: pon.ID,
245 },
246 }
247 o.channel <- msg
248
249 for _, onu := range pon.Onus {
250 if onu.InternalState.Current() != "initialized" {
251 onu.InternalState.Event("disable")
252 }
253 }
254 }
255
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100256 // terminate the OLT's processOltMessages go routine
257 close(o.channel)
258 // terminate the OLT's processNniPacketIns go routine
Andy Bavier421f4d52020-01-21 15:39:22 -0700259 go o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100260 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100261
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100262 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100263
264 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800265 oltLogger.WithFields(log.Fields{
266 "oltId": o.ID,
267 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100268 return err
269 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800270 oltLogger.WithFields(log.Fields{
271 "oltId": o.ID,
272 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100273 return nil
274}
275
276// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800277func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100278 address := common.Options.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700279 lis, err := net.Listen("tcp", address)
280 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700281 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700282 }
283 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100284
Matteo Scandolo4747d292019-08-05 11:50:18 -0700285 openolt.RegisterOpenoltServer(grpcServer, o)
286
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100287 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700288
Matteo Scandolo4747d292019-08-05 11:50:18 -0700289 go grpcServer.Serve(lis)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100290 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700291
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100292 return grpcServer, nil
293}
294
295// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800296func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100297 // TODO handle poweroff vs graceful shutdown
298 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800299 oltLogger.WithFields(log.Fields{
300 "oltId": o.SerialNumber,
301 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100302 oltServer.Stop()
303 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700304 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800305
Matteo Scandolo4747d292019-08-05 11:50:18 -0700306 return nil
307}
308
309// Device Methods
310
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100311// Enable implements the OpenOLT EnableIndicationServer functionality
312func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700313 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530314 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700315
David Bainbridge103cf022019-12-16 20:11:35 +0000316 // If enabled has already been called then an enabled context has
317 // been created. If this is the case then we want to cancel all the
318 // proessing loops associated with that enable before we recreate
319 // new ones
320 o.Lock()
321 if o.enableContext != nil && o.enableContextCancel != nil {
322 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530323 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000324 }
325 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
326 o.Unlock()
327
Matteo Scandolo4747d292019-08-05 11:50:18 -0700328 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800329 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700330
Pragya Arya1cbefa42020-01-13 12:15:29 +0530331 o.OpenoltStream = &stream
332
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100333 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000334 go o.processOltMessages(o.enableContext, stream, &wg)
335 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700336
337 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100338 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700339 Type: OltIndication,
340 Data: OltIndicationMessage{
341 OperState: UP,
342 },
343 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100344 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700345
346 // send NNI Port Indications
347 for _, nni := range o.Nnis {
348 msg := Message{
349 Type: NniIndication,
350 Data: NniIndicationMessage{
351 OperState: UP,
352 NniPortID: nni.ID,
353 },
354 }
355 o.channel <- msg
356 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100357
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800358 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100359
Pragya Arya2225f202020-01-29 18:05:01 +0530360 if rebootFlag == true {
361 for _, pon := range o.Pons {
362 if pon.InternalState.Current() == "disabled" {
363 msg := Message{
364 Type: PonIndication,
365 Data: PonIndicationMessage{
366 OperState: UP,
367 PonPortID: pon.ID,
368 },
369 }
370 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000371 }
Pragya Arya2225f202020-01-29 18:05:01 +0530372 }
373 } else {
374
375 // 1. controlledActivation == Default: Send both PON and ONUs indications
376 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
377
378 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
379 // send PON Port indications
380 for _, pon := range o.Pons {
381 msg := Message{
382 Type: PonIndication,
383 Data: PonIndicationMessage{
384 OperState: UP,
385 PonPortID: pon.ID,
386 },
387 }
388 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700389 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700390 }
391 }
392
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800393 oltLogger.Debug("Enable OLT Done")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700394 wg.Wait()
395 return nil
396}
397
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800398func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400399 ch := omcisim.GetChannel()
400
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100401 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400402
David Bainbridge103cf022019-12-16 20:11:35 +0000403loop:
404 for {
405 select {
406 case <-ctx.Done():
407 oltLogger.Debug("OMCI processing canceled via context")
408 break loop
409 case message, ok := <-ch:
410 if !ok || ctx.Err() != nil {
411 oltLogger.Debug("OMCI processing canceled via channel close")
412 break loop
413 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800414
415 oltLogger.WithFields(log.Fields{
416 "messageType": message.Type,
417 "OnuId": message.Data.OnuId,
418 "IntfId": message.Data.IntfId,
419 }).Info("Received message on OMCI Sim channel")
420
David Bainbridge103cf022019-12-16 20:11:35 +0000421 onuId := message.Data.OnuId
422 intfId := message.Data.IntfId
423 onu, err := o.FindOnuById(intfId, onuId)
424 if err != nil {
425 oltLogger.Errorf("Failed to find onu: %v", err)
426 continue
427 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800428 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400429 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400430 }
David Bainbridge103cf022019-12-16 20:11:35 +0000431
432 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400433}
434
Matteo Scandolo4747d292019-08-05 11:50:18 -0700435// Helpers method
436
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700437func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700438 for _, pon := range o.Pons {
439 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700440 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700441 }
442 }
443 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
444}
445
446func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
447 for _, nni := range o.Nnis {
448 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700449 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700450 }
451 }
452 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
453}
454
Scott Baker41724b82020-01-21 19:54:53 -0800455func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
456 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
457 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
458 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
459 return
460 }
461
462 oltLogger.WithFields(log.Fields{
463 "AlarmIndication": alarmInd,
464 }).Debug("Sent Indication_AlarmInd")
465}
466
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100467func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700468 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
469 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700470 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800471 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700472 }
473
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700474 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700475 "OperState": msg.OperState,
476 }).Debug("Sent Indication_OltInd")
477}
478
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100479func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700480 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800481 if msg.OperState == UP {
482 if err := nni.OperState.Event("enable"); err != nil {
483 log.WithFields(log.Fields{
484 "Type": nni.Type,
485 "IntfId": nni.ID,
486 "OperState": nni.OperState.Current(),
487 }).Errorf("Can't move NNI Port to enabled state: %v", err)
488 }
489 } else if msg.OperState == DOWN {
490 if err := nni.OperState.Event("disable"); err != nil {
491 log.WithFields(log.Fields{
492 "Type": nni.Type,
493 "IntfId": nni.ID,
494 "OperState": nni.OperState.Current(),
495 }).Errorf("Can't move NNI Port to disable state: %v", err)
496 }
497 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700498 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700499 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700500 Type: nni.Type,
501 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700502 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700503 }}
504
505 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700506 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800507 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700508 }
509
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700510 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700511 "Type": nni.Type,
512 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700513 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700514 }).Debug("Sent Indication_IntfOperInd for NNI")
515}
516
Pragya Arya2225f202020-01-29 18:05:01 +0530517func (o *OltDevice) sendPonIndication(ponPortID uint32) {
518
519 stream := *o.OpenoltStream
520 pon, _ := o.GetPonById(ponPortID)
521 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700522 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700523 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700524 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700525 }}
526
527 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700528 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800529 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700530 }
531
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700532 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700533 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700534 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700535 }).Debug("Sent Indication_IntfInd")
536
Pragya Arya2225f202020-01-29 18:05:01 +0530537 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700538 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700539 Type: pon.Type,
540 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700541 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700542 }}
543
544 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700545 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800546 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700547 }
548
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700549 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700550 "Type": pon.Type,
551 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700552 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700553 }).Debug("Sent Indication_IntfOperInd for PON")
554}
555
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100556// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000557func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100558 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000559 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700560
David Bainbridge103cf022019-12-16 20:11:35 +0000561loop:
562 for {
563 select {
564 case <-ctx.Done():
565 oltLogger.Debug("OLT Indication processing canceled via context")
566 break loop
567 case message, ok := <-ch:
568 if !ok || ctx.Err() != nil {
569 oltLogger.Debug("OLT Indication processing canceled via closed channel")
570 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700571 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700572
David Bainbridge103cf022019-12-16 20:11:35 +0000573 oltLogger.WithFields(log.Fields{
574 "oltId": o.ID,
575 "messageType": message.Type,
576 }).Trace("Received message")
577
578 switch message.Type {
579 case OltIndication:
580 msg, _ := message.Data.(OltIndicationMessage)
581 if msg.OperState == UP {
582 o.InternalState.Event("enable")
583 o.OperState.Event("enable")
584 } else if msg.OperState == DOWN {
585 o.InternalState.Event("disable")
586 o.OperState.Event("disable")
587 }
588 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800589 case AlarmIndication:
590 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
591 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000592 case NniIndication:
593 msg, _ := message.Data.(NniIndicationMessage)
594 o.sendNniIndication(msg, stream)
595 case PonIndication:
596 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530597 pon, _ := o.GetPonById(msg.PonPortID)
598 if msg.OperState == UP {
599 pon.OperState.Event("enable")
600 pon.InternalState.Event("enable")
601 } else if msg.OperState == DOWN {
602 pon.OperState.Event("disable")
603 pon.InternalState.Event("disable")
604 }
David Bainbridge103cf022019-12-16 20:11:35 +0000605 default:
606 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
607 }
608 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100610 wg.Done()
611 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612}
613
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100614// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000615func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700616 oltLogger.WithFields(log.Fields{
617 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800618 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700619 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700620
David Bainbridge103cf022019-12-16 20:11:35 +0000621 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700622
David Bainbridge103cf022019-12-16 20:11:35 +0000623loop:
624 for {
625 select {
626 case <-ctx.Done():
627 oltLogger.Debug("NNI Indication processing canceled via context")
628 break loop
629 case message, ok := <-ch:
630 if !ok || ctx.Err() != nil {
631 oltLogger.Debug("NNI Indication processing canceled via channel closed")
632 break loop
633 }
634 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700635
David Bainbridge103cf022019-12-16 20:11:35 +0000636 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700637
David Bainbridge103cf022019-12-16 20:11:35 +0000638 if err != nil {
639 log.WithFields(log.Fields{
640 "IntfType": "nni",
641 "IntfId": nniId,
642 "Pkt": message.Pkt.Data(),
643 }).Error("Can't find Dst MacAddress in packet")
644 return
645 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700646
David Bainbridge103cf022019-12-16 20:11:35 +0000647 onu, err := o.FindOnuByMacAddress(onuMac)
648 if err != nil {
649 log.WithFields(log.Fields{
650 "IntfType": "nni",
651 "IntfId": nniId,
652 "Pkt": message.Pkt.Data(),
653 "MacAddress": onuMac.String(),
654 }).Error("Can't find ONU with MacAddress")
655 return
656 }
657
658 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
659 if err != nil {
660 log.Error("Fail to add double tag to packet")
661 }
662
663 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
664 IntfType: "nni",
665 IntfId: nniId,
666 Pkt: doubleTaggedPkt.Data()}}
667 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
668 oltLogger.WithFields(log.Fields{
669 "IntfType": data.PktInd.IntfType,
670 "IntfId": nniId,
671 "Pkt": doubleTaggedPkt.Data(),
672 }).Errorf("Fail to send PktInd indication: %v", err)
673 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700674 oltLogger.WithFields(log.Fields{
675 "IntfType": data.PktInd.IntfType,
676 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700677 "Pkt": doubleTaggedPkt.Data(),
David Bainbridge103cf022019-12-16 20:11:35 +0000678 "OnuSn": onu.Sn(),
679 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700680 }
681 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100682 wg.Done()
683 oltLogger.WithFields(log.Fields{
684 "nniChannel": o.nniPktInChannel,
685 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700686}
687
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700688// returns an ONU with a given Serial Number
689func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200690 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700691 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700692 for _, pon := range o.Pons {
693 for _, onu := range pon.Onus {
694 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700695 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700696 }
697 }
698 }
699
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700700 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
701}
702
William Kurkian9dadc5b2019-10-22 13:51:57 -0400703// returns an ONU with a given interface/Onu Id
704func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200705 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400706 // memoizing it will remove the bottleneck
707 for _, pon := range o.Pons {
708 if pon.ID == intfId {
709 for _, onu := range pon.Onus {
710 if onu.ID == onuId {
711 return onu, nil
712 }
713 }
714 }
715 }
716 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
717}
718
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700719// returns an ONU with a given Mac Address
720func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200721 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700722 // memoizing it will remove the bottleneck
723 for _, pon := range o.Pons {
724 for _, onu := range pon.Onus {
725 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700726 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700727 }
728 }
729 }
730
731 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700732}
733
Matteo Scandolo4747d292019-08-05 11:50:18 -0700734// GRPC Endpoints
735
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700736func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700737 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700738 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700739 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530740 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700741
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700742 pon, _ := o.GetPonById(onu.IntfId)
743 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500744 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700745
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700746 if err := _onu.OperState.Event("enable"); err != nil {
747 oltLogger.WithFields(log.Fields{
748 "IntfId": _onu.PonPortID,
749 "OnuSn": _onu.Sn(),
750 "OnuId": _onu.ID,
751 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700752 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700753 if err := _onu.InternalState.Event("enable"); err != nil {
754 oltLogger.WithFields(log.Fields{
755 "IntfId": _onu.PonPortID,
756 "OnuSn": _onu.Sn(),
757 "OnuId": _onu.ID,
758 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
759 }
760
761 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
762
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700763 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700764}
765
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700766func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700767 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700768 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700769}
770
Pragya Arya1cbefa42020-01-13 12:15:29 +0530771func (o OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
772 oltLogger.WithFields(log.Fields{
773 "IntfId": onu.IntfId,
774 "OnuId": onu.OnuId,
775 }).Info("Received DeleteOnu call from VOLTHA")
776
777 pon, err := o.GetPonById(onu.IntfId)
778 if err != nil {
779 oltLogger.WithFields(log.Fields{
780 "OnuId": onu.OnuId,
781 "IntfId": onu.IntfId,
782 "err": err,
783 }).Error("Can't find PonPort")
784 }
785 _onu, err := pon.GetOnuById(onu.OnuId)
786 if err != nil {
787 oltLogger.WithFields(log.Fields{
788 "OnuId": onu.OnuId,
789 "IntfId": onu.IntfId,
790 "err": err,
791 }).Error("Can't find Onu")
792 }
793
794 if err := _onu.InternalState.Event("initialize"); err != nil {
795 oltLogger.WithFields(log.Fields{
796 "IntfId": _onu.PonPortID,
797 "OnuSn": _onu.Sn(),
798 "OnuId": _onu.ID,
799 }).Infof("Failed to transition ONU to initialized state: %s", err.Error())
800 }
801
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700802 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700803}
804
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700805func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700806 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800807 oltLogger.WithFields(log.Fields{
808 "oltId": o.ID,
809 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530810 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800811
Matteo Scandolo401503a2019-12-11 14:48:14 -0800812 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530813 if pon.InternalState.Current() == "enabled" {
814 // disable PONs
815 msg := Message{
816 Type: PonIndication,
817 Data: PonIndicationMessage{
818 OperState: DOWN,
819 PonPortID: pon.ID,
820 },
821 }
822 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800823 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800824 }
825
Matteo Scandolo401503a2019-12-11 14:48:14 -0800826 // Note that we are not disabling the NNI as the real OLT does not.
827 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800828
829 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100830 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700831 Type: OltIndication,
832 Data: OltIndicationMessage{
833 OperState: DOWN,
834 },
835 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100836 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700837 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700838}
839
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700840func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700841 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700842 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700843}
844
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100845func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700846 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530847 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700848 o.Enable(stream)
849 return nil
850}
851
Pragya Arya2225f202020-01-29 18:05:01 +0530852func (o OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
853 oltLogger.Errorf("EnablePonIf request received for PON %d", intf.IntfId)
854 ponID := intf.GetIntfId()
855 msg := Message{
856 Type: PonIndication,
857 Data: PonIndicationMessage{
858 OperState: UP,
859 PonPortID: ponID,
860 },
861 }
862 o.channel <- msg
863
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700864 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700865}
866
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700867func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700868 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700869 "IntfId": flow.AccessIntfId,
870 "OnuId": flow.OnuId,
871 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700872 "InnerVlan": flow.Classifier.IVid,
873 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700874 "FlowType": flow.FlowType,
875 "FlowId": flow.FlowId,
876 "UniID": flow.UniId,
877 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +0530878 }).Tracef("OLT receives FlowAdd")
879
880 flowKey := FlowKey{}
881 if !o.enablePerf {
882 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
883 olt.Flows[flowKey] = *flow
884 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700885
886 if flow.AccessIntfId == -1 {
887 oltLogger.WithFields(log.Fields{
888 "FlowId": flow.FlowId,
889 }).Debugf("This is an OLT flow")
890 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700891 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700892 if err != nil {
893 oltLogger.WithFields(log.Fields{
894 "OnuId": flow.OnuId,
895 "IntfId": flow.AccessIntfId,
896 "err": err,
897 }).Error("Can't find PonPort")
898 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700899 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700900 if err != nil {
901 oltLogger.WithFields(log.Fields{
902 "OnuId": flow.OnuId,
903 "IntfId": flow.AccessIntfId,
904 "err": err,
905 }).Error("Can't find Onu")
906 }
Pragya Arya8bdb4532020-03-02 17:08:09 +0530907 if !o.enablePerf {
908 onu.Flows = append(onu.Flows, flowKey)
909 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700910
911 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700912 Type: FlowUpdate,
913 Data: OnuFlowUpdateMessage{
914 PonPortID: pon.ID,
915 OnuID: onu.ID,
916 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700917 },
918 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700919 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700920 }
921
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700922 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700923}
924
Pragya Arya8bdb4532020-03-02 17:08:09 +0530925// FlowRemove request from VOLTHA
926func (o OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
927 oltLogger.WithFields(log.Fields{
928 "FlowId": flow.FlowId,
929 "FlowType": flow.FlowType,
930 }).Tracef("OLT receives FlowRemove")
931
932 if !o.enablePerf { // remove only if flow were stored
933 flowKey := FlowKey{
934 ID: flow.FlowId,
935 Direction: flow.FlowType,
936 }
937
938 // Check if flow exists
939 storedFlow, ok := o.Flows[flowKey]
940 if !ok {
941 oltLogger.Errorf("Flow %v not found", flow)
942 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
943 }
944
945 // if its ONU flow remove it from ONU also
946 if storedFlow.AccessIntfId != -1 {
947 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
948 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
949 if err != nil {
950 oltLogger.WithFields(log.Fields{
951 "OnuId": storedFlow.OnuId,
952 "IntfId": storedFlow.AccessIntfId,
953 "err": err,
954 }).Error("ONU not found")
955 return new(openolt.Empty), nil
956 }
957 onu.DeleteFlow(flowKey)
958 }
959
960 // delete from olt flows
961 delete(o.Flows, flowKey)
962 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700963 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700964}
965
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700966func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -0800967 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
968 oltLogger.WithFields(log.Fields{
969 "signature": res.HeartbeatSignature,
970 }).Trace("HeartbeatCheck")
971 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700972}
973
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700974func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700975
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700976 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700977 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700978 "PonPorts": o.NumPon,
979 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700980 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100981 devinfo.Vendor = common.Options.Olt.Vendor
982 devinfo.Model = common.Options.Olt.Model
983 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
984 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
985 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700986 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700987 devinfo.OnuIdStart = 1
988 devinfo.OnuIdEnd = 255
989 devinfo.AllocIdStart = 1024
990 devinfo.AllocIdEnd = 16383
991 devinfo.GemportIdStart = 1024
992 devinfo.GemportIdEnd = 65535
993 devinfo.FlowIdStart = 1
994 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700995 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100996 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -0700997
998 return devinfo, nil
999}
1000
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001001func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001002 pon, _ := o.GetPonById(omci_msg.IntfId)
1003 onu, _ := pon.GetOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001004 oltLogger.WithFields(log.Fields{
1005 "IntfId": onu.PonPortID,
1006 "OnuId": onu.ID,
1007 "OnuSn": onu.Sn(),
1008 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001009 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001010 Type: OMCI,
1011 Data: OmciMessage{
1012 OnuSN: onu.SerialNumber,
1013 OnuID: onu.ID,
1014 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001015 },
1016 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001017 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001018 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001019}
1020
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001021func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001022 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001023 if err != nil {
1024 oltLogger.WithFields(log.Fields{
1025 "OnuId": onuPkt.OnuId,
1026 "IntfId": onuPkt.IntfId,
1027 "err": err,
1028 }).Error("Can't find PonPort")
1029 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001030 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001031 if err != nil {
1032 oltLogger.WithFields(log.Fields{
1033 "OnuId": onuPkt.OnuId,
1034 "IntfId": onuPkt.IntfId,
1035 "err": err,
1036 }).Error("Can't find Onu")
1037 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001038
Matteo Scandolo075b1892019-10-07 12:11:07 -07001039 oltLogger.WithFields(log.Fields{
1040 "IntfId": onu.PonPortID,
1041 "OnuId": onu.ID,
1042 "OnuSn": onu.Sn(),
1043 }).Tracef("Received OnuPacketOut")
1044
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001045 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001046 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001047
Matteo Scandolo075b1892019-10-07 12:11:07 -07001048 msg := Message{
1049 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001050 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -07001051 IntfId: onuPkt.IntfId,
1052 OnuId: onuPkt.OnuId,
1053 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001054 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001055 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001056 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001057 onu.Channel <- msg
1058
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001059 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001060}
1061
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001062func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001063 oltLogger.WithFields(log.Fields{
1064 "oltId": o.ID,
1065 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301066 publishEvent("OLT-reboot-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001067 go o.RestartOLT()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001068 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001069}
1070
1071func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301072 oltLogger.WithFields(log.Fields{
1073 "oltId": o.ID,
1074 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301075 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301076
Pragya Arya2225f202020-01-29 18:05:01 +05301077 // enable OLT
1078 oltMsg := Message{
1079 Type: OltIndication,
1080 Data: OltIndicationMessage{
1081 OperState: UP,
1082 },
Pragya Arya1881df02020-01-29 18:05:01 +05301083 }
Pragya Arya2225f202020-01-29 18:05:01 +05301084 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301085
Pragya Arya2225f202020-01-29 18:05:01 +05301086 for _, pon := range o.Pons {
1087 if pon.InternalState.Current() == "disabled" {
1088 msg := Message{
1089 Type: PonIndication,
1090 Data: PonIndicationMessage{
1091 OperState: UP,
1092 PonPortID: pon.ID,
1093 },
1094 }
1095 o.channel <- msg
1096 }
1097 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001098
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001099 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001100}
1101
1102func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001103 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1104
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001105 o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001106 // NOTE should we return an error if sendNniPakcet fails?
1107 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001108}
1109
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001110func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001111 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001112 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001113}
1114
Matteo Scandolo4747d292019-08-05 11:50:18 -07001115func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001116 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001117 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001118}
1119
1120func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001121 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001122 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001123}
1124
1125func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001126 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001127 return new(openolt.Empty), nil
1128}
1129
1130func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001131 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001132 return new(openolt.Empty), nil
1133}
1134
Anand S Katti09541352020-01-29 15:54:01 +05301135func (s OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
1136 oltLogger.WithFields(log.Fields{
1137 "OnuId": trafficSchedulers.OnuId,
1138 "IntfId": trafficSchedulers.IntfId,
1139 "OnuPortNo": trafficSchedulers.PortNo,
1140 }).Info("received CreateTrafficSchedulers")
1141
1142 if !s.enablePerf {
1143 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1144 if err != nil {
1145 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1146 return new(openolt.Empty), err
1147 }
1148 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1149 if err != nil {
1150 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1151 return new(openolt.Empty), err
1152 }
1153 onu.TrafficSchedulers = trafficSchedulers
1154 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001155 return new(openolt.Empty), nil
1156}
1157
Anand S Katti09541352020-01-29 15:54:01 +05301158func (s OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
1159 oltLogger.WithFields(log.Fields{
1160 "OnuId": trafficSchedulers.OnuId,
1161 "IntfId": trafficSchedulers.IntfId,
1162 "OnuPortNo": trafficSchedulers.PortNo,
1163 }).Info("received RemoveTrafficSchedulers")
1164 if !s.enablePerf {
1165 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1166 if err != nil {
1167 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1168 return new(openolt.Empty), err
1169 }
1170 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1171 if err != nil {
1172 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1173 return new(openolt.Empty), err
1174 }
1175
1176 onu.TrafficSchedulers = nil
1177 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001178 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001179}
Scott Baker41724b82020-01-21 19:54:53 -08001180
1181// assumes caller has properly formulated an openolt.AlarmIndication
1182func (o OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
1183 msg := Message{
1184 Type: AlarmIndication,
1185 Data: ind,
1186 }
1187
1188 o.channel <- msg
1189 return nil
1190}