blob: 0209b88649cfb206a1a7c93c399538e7e5277363 [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
Pragya Arya996a0892020-03-09 21:47:52 +053066 PortStatsInterval int
Matteo Scandoloe33447a2019-10-31 12:38:23 -070067
Matteo Scandolo27428702019-10-11 16:21:16 -070068 Pons []*PonPort
69 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070070
71 // OLT Attributes
72 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000073
74 enableContext context.Context
75 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053076
77 OpenoltStream *openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053078 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070079}
80
Matteo Scandolo27428702019-10-11 16:21:16 -070081var olt OltDevice
Zdravko Bozakov681364d2019-11-10 14:28:46 +010082var oltServer *grpc.Server
Matteo Scandolo84f7d482019-08-08 19:00:47 -070083
Matteo Scandolo27428702019-10-11 16:21:16 -070084func GetOLT() *OltDevice {
85 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070086}
87
Pragya Arya996a0892020-03-09 21:47:52 +053088func CreateOLT(options common.BBSimYamlConfig, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070089 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +053090 "ID": options.Olt.ID,
91 "NumNni": options.Olt.NniPorts,
92 "NumPon": options.Olt.PonPorts,
93 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -070094 }).Debug("CreateOLT")
95
Matteo Scandolo84f7d482019-08-08 19:00:47 -070096 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +053097 ID: options.Olt.ID,
98 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070099 OperState: getOperStateFSM(func(e *fsm.Event) {
100 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
101 }),
Pragya Arya996a0892020-03-09 21:47:52 +0530102 NumNni: int(options.Olt.NniPorts),
103 NumPon: int(options.Olt.PonPorts),
104 NumOnuPerPon: int(options.Olt.OnusPonPort),
105 Pons: []*PonPort{},
106 Nnis: []*NniPort{},
107 Delay: options.BBSim.Delay,
108 Flows: make(map[FlowKey]openolt.Flow),
109 enablePerf: options.BBSim.EnablePerf,
110 PublishEvents: options.BBSim.Events,
111 PortStatsInterval: options.Olt.PortStatsInterval,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700112 }
113
Pragya Arya996a0892020-03-09 21:47:52 +0530114 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530115 olt.ControlledActivation = val
116 } else {
117 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
118 olt.ControlledActivation = Default
119 }
120
Matteo Scandolo4747d292019-08-05 11:50:18 -0700121 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700122 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700123 olt.InternalState = fsm.NewFSM(
124 "created",
125 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800126 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100127 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700128 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800129 //delete event in enabled state below is for reboot OLT case.
130 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700131 },
132 fsm.Callbacks{
133 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700134 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100136 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700137 },
138 )
139
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700140 if isMock != true {
141 // create NNI Port
142 nniPort, err := CreateNNI(&olt)
143 if err != nil {
144 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
145 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700146
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700147 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700149
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150 // create PON ports
Pragya Arya996a0892020-03-09 21:47:52 +0530151 availableCTag := options.BBSim.CTagInit
152 for i := 0; i < olt.NumPon; i++ {
Pragya Arya2225f202020-01-29 18:05:01 +0530153 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700154
155 // create ONU devices
Pragya Arya996a0892020-03-09 21:47:52 +0530156 for j := 0; j < olt.NumOnuPerPon; j++ {
Matteo Scandolo583f17d2020-02-13 10:35:17 -0800157 delay := time.Duration(olt.Delay*j) * time.Millisecond
Pragya Arya996a0892020-03-09 21:47:52 +0530158 o := CreateONU(&olt, *p, uint32(j+1), options.BBSim.STag, availableCTag, options.BBSim.EnableAuth, options.BBSim.EnableDhcp, delay, isMock)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159 p.Onus = append(p.Onus, o)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700160 availableCTag = availableCTag + 1
Matteo Scandolo4747d292019-08-05 11:50:18 -0700161 }
162
Pragya Arya6a708d62020-01-01 17:17:20 +0530163 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700164 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100165
Matteo Scandolod32c3822019-11-26 15:57:46 -0700166 if isMock != true {
167 if err := olt.InternalState.Event("initialize"); err != nil {
168 log.Errorf("Error initializing OLT: %v", err)
169 return nil
170 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100171 }
172
Pragya Arya324337e2020-02-20 14:35:08 +0530173 if olt.PublishEvents {
174 log.Debugf("BBSim event publishing is enabled")
175 // Create a channel to write event messages
176 olt.EventChannel = make(chan common.Event, 100)
177 }
178
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700179 return &olt
180}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700181
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100182func (o *OltDevice) InitOlt() error {
183
184 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800185 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100186 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800187 // FIXME there should never be a server running if we are initializing the OLT
188 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100189 }
190
191 // create new channel for processOltMessages Go routine
192 o.channel = make(chan Message)
193
194 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
195 // FIXME we are assuming we have only one NNI
196 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800197 // NOTE we want to make sure the state is down when we initialize the OLT,
198 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
199 // in-band management
200 o.Nnis[0].OperState.SetState("down")
201 ch, handle, err := o.Nnis[0].NewVethChan()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100202 if err == nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800203 oltLogger.WithFields(log.Fields{
204 "Type": o.Nnis[0].Type,
205 "IntfId": o.Nnis[0].ID,
206 "OperState": o.Nnis[0].OperState.Current(),
207 }).Info("NNI Channel created")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100208 o.nniPktInChannel = ch
Matteo Scandolo401503a2019-12-11 14:48:14 -0800209 o.nniHandle = handle
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100210 } else {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800211 oltLogger.Errorf("Error getting NNI channel: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100212 }
213 }
214
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100215 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700216}
217
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800218func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100219
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800220 rebootDelay := common.Options.Olt.OltRebootDelay
221
222 oltLogger.WithFields(log.Fields{
223 "oltId": o.ID,
224 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
225
226 // transition internal state to deleted
227 if err := o.InternalState.Event("delete"); err != nil {
228 oltLogger.WithFields(log.Fields{
229 "oltId": o.ID,
230 }).Errorf("Error deleting OLT: %v", err)
231 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100232 }
233
234 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800235 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
236 if err := o.StopOltServer(); err != nil {
Pragya Arya2225f202020-01-29 18:05:01 +0530237 oltLogger.Errorf("Error in stopping OLT server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100238 return err
239 }
240
Pragya Arya2225f202020-01-29 18:05:01 +0530241 for _, pon := range olt.Pons {
242 msg := Message{
243 Type: PonIndication,
244 Data: PonIndicationMessage{
245 OperState: DOWN,
246 PonPortID: pon.ID,
247 },
248 }
249 o.channel <- msg
250
251 for _, onu := range pon.Onus {
252 if onu.InternalState.Current() != "initialized" {
253 onu.InternalState.Event("disable")
254 }
255 }
256 }
257
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100258 // terminate the OLT's processOltMessages go routine
259 close(o.channel)
260 // terminate the OLT's processNniPacketIns go routine
Andy Bavier421f4d52020-01-21 15:39:22 -0700261 go o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100262 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100263
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100264 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100265
266 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800267 oltLogger.WithFields(log.Fields{
268 "oltId": o.ID,
269 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100270 return err
271 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800272 oltLogger.WithFields(log.Fields{
273 "oltId": o.ID,
274 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100275 return nil
276}
277
278// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800279func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100280 address := common.Options.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700281 lis, err := net.Listen("tcp", address)
282 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700283 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700284 }
285 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100286
Matteo Scandolo4747d292019-08-05 11:50:18 -0700287 openolt.RegisterOpenoltServer(grpcServer, o)
288
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100289 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700290
Matteo Scandolo4747d292019-08-05 11:50:18 -0700291 go grpcServer.Serve(lis)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100292 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700293
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100294 return grpcServer, nil
295}
296
297// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800298func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100299 // TODO handle poweroff vs graceful shutdown
300 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800301 oltLogger.WithFields(log.Fields{
302 "oltId": o.SerialNumber,
303 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100304 oltServer.Stop()
305 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700306 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800307
Matteo Scandolo4747d292019-08-05 11:50:18 -0700308 return nil
309}
310
311// Device Methods
312
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100313// Enable implements the OpenOLT EnableIndicationServer functionality
314func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700315 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530316 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700317
David Bainbridge103cf022019-12-16 20:11:35 +0000318 // If enabled has already been called then an enabled context has
319 // been created. If this is the case then we want to cancel all the
320 // proessing loops associated with that enable before we recreate
321 // new ones
322 o.Lock()
323 if o.enableContext != nil && o.enableContextCancel != nil {
324 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530325 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000326 }
327 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
328 o.Unlock()
329
Matteo Scandolo4747d292019-08-05 11:50:18 -0700330 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800331 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700332
Pragya Arya1cbefa42020-01-13 12:15:29 +0530333 o.OpenoltStream = &stream
334
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100335 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000336 go o.processOltMessages(o.enableContext, stream, &wg)
337 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700338
339 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100340 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700341 Type: OltIndication,
342 Data: OltIndicationMessage{
343 OperState: UP,
344 },
345 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100346 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700347
348 // send NNI Port Indications
349 for _, nni := range o.Nnis {
350 msg := Message{
351 Type: NniIndication,
352 Data: NniIndicationMessage{
353 OperState: UP,
354 NniPortID: nni.ID,
355 },
356 }
357 o.channel <- msg
358 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100359
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800360 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100361
Pragya Arya2225f202020-01-29 18:05:01 +0530362 if rebootFlag == true {
363 for _, pon := range o.Pons {
364 if pon.InternalState.Current() == "disabled" {
365 msg := Message{
366 Type: PonIndication,
367 Data: PonIndicationMessage{
368 OperState: UP,
369 PonPortID: pon.ID,
370 },
371 }
372 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000373 }
Pragya Arya2225f202020-01-29 18:05:01 +0530374 }
375 } else {
376
377 // 1. controlledActivation == Default: Send both PON and ONUs indications
378 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
379
380 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
381 // send PON Port indications
382 for _, pon := range o.Pons {
383 msg := Message{
384 Type: PonIndication,
385 Data: PonIndicationMessage{
386 OperState: UP,
387 PonPortID: pon.ID,
388 },
389 }
390 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700391 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700392 }
393 }
394
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800395 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530396
397 if !o.enablePerf {
398 // Start a go routine to send periodic port stats to openolt adapter
399 go o.periodicPortStats(o.enableContext)
400 }
401
Matteo Scandolo4747d292019-08-05 11:50:18 -0700402 wg.Wait()
403 return nil
404}
405
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800406func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400407 ch := omcisim.GetChannel()
408
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100409 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400410
David Bainbridge103cf022019-12-16 20:11:35 +0000411loop:
412 for {
413 select {
414 case <-ctx.Done():
415 oltLogger.Debug("OMCI processing canceled via context")
416 break loop
417 case message, ok := <-ch:
418 if !ok || ctx.Err() != nil {
419 oltLogger.Debug("OMCI processing canceled via channel close")
420 break loop
421 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800422
423 oltLogger.WithFields(log.Fields{
424 "messageType": message.Type,
425 "OnuId": message.Data.OnuId,
426 "IntfId": message.Data.IntfId,
427 }).Info("Received message on OMCI Sim channel")
428
David Bainbridge103cf022019-12-16 20:11:35 +0000429 onuId := message.Data.OnuId
430 intfId := message.Data.IntfId
431 onu, err := o.FindOnuById(intfId, onuId)
432 if err != nil {
433 oltLogger.Errorf("Failed to find onu: %v", err)
434 continue
435 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800436 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400437 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400438 }
David Bainbridge103cf022019-12-16 20:11:35 +0000439
440 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400441}
442
Pragya Arya996a0892020-03-09 21:47:52 +0530443func (o *OltDevice) periodicPortStats(ctx context.Context) {
444 var portStats *openolt.PortStatistics
445 for {
446 select {
447 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
448 // send NNI port stats
449 for _, port := range o.Nnis {
450 incrementStat := true
451 if port.OperState.Current() == "down" {
452 incrementStat = false
453 }
454 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
455 o.sendPortStatsIndication(portStats, port.ID, port.Type)
456 }
457
458 // send PON port stats
459 for _, port := range o.Pons {
460 incrementStat := true
461 // do not increment port stats if PON port is down or no ONU is activated on PON port
462 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
463 incrementStat = false
464 }
465 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
466 o.sendPortStatsIndication(portStats, port.ID, port.Type)
467 }
468 case <-ctx.Done():
469 log.Debug("Stop sending port stats")
470 return
471 }
472
473 }
474}
475
Matteo Scandolo4747d292019-08-05 11:50:18 -0700476// Helpers method
477
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700478func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700479 for _, pon := range o.Pons {
480 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700481 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700482 }
483 }
484 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
485}
486
487func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
488 for _, nni := range o.Nnis {
489 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700490 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700491 }
492 }
493 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
494}
495
Scott Baker41724b82020-01-21 19:54:53 -0800496func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
497 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
498 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
499 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
500 return
501 }
502
503 oltLogger.WithFields(log.Fields{
504 "AlarmIndication": alarmInd,
505 }).Debug("Sent Indication_AlarmInd")
506}
507
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100508func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700509 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
510 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700511 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800512 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700513 }
514
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700515 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700516 "OperState": msg.OperState,
517 }).Debug("Sent Indication_OltInd")
518}
519
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100520func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700521 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800522 if msg.OperState == UP {
523 if err := nni.OperState.Event("enable"); err != nil {
524 log.WithFields(log.Fields{
525 "Type": nni.Type,
526 "IntfId": nni.ID,
527 "OperState": nni.OperState.Current(),
528 }).Errorf("Can't move NNI Port to enabled state: %v", err)
529 }
530 } else if msg.OperState == DOWN {
531 if err := nni.OperState.Event("disable"); err != nil {
532 log.WithFields(log.Fields{
533 "Type": nni.Type,
534 "IntfId": nni.ID,
535 "OperState": nni.OperState.Current(),
536 }).Errorf("Can't move NNI Port to disable state: %v", err)
537 }
538 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700539 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700540 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700541 Type: nni.Type,
542 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700543 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700544 }}
545
546 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700547 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800548 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700549 }
550
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700551 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700552 "Type": nni.Type,
553 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700554 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700555 }).Debug("Sent Indication_IntfOperInd for NNI")
556}
557
Pragya Arya2225f202020-01-29 18:05:01 +0530558func (o *OltDevice) sendPonIndication(ponPortID uint32) {
559
560 stream := *o.OpenoltStream
561 pon, _ := o.GetPonById(ponPortID)
562 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700563 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700564 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700565 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700566 }}
567
568 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700569 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800570 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700571 }
572
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700573 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700574 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700575 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700576 }).Debug("Sent Indication_IntfInd")
577
Pragya Arya2225f202020-01-29 18:05:01 +0530578 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700579 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700580 Type: pon.Type,
581 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700582 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700583 }}
584
585 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700586 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800587 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700588 }
589
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700590 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700591 "Type": pon.Type,
592 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700593 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700594 }).Debug("Sent Indication_IntfOperInd for PON")
595}
596
Pragya Arya996a0892020-03-09 21:47:52 +0530597func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
598 oltLogger.WithFields(log.Fields{
599 "Type": portType,
600 "IntfId": portID,
601 }).Trace("Sending port stats")
602 stats.IntfId = InterfaceIDToPortNo(portID, portType)
603 data := &openolt.Indication_PortStats{
604 PortStats: stats,
605 }
606 stream := *o.OpenoltStream
607 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
608 oltLogger.Errorf("Failed to send PortStats: %v", err)
609 return
610 }
611}
612
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100613// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000614func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100615 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000616 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700617
David Bainbridge103cf022019-12-16 20:11:35 +0000618loop:
619 for {
620 select {
621 case <-ctx.Done():
622 oltLogger.Debug("OLT Indication processing canceled via context")
623 break loop
624 case message, ok := <-ch:
625 if !ok || ctx.Err() != nil {
626 oltLogger.Debug("OLT Indication processing canceled via closed channel")
627 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700628 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700629
David Bainbridge103cf022019-12-16 20:11:35 +0000630 oltLogger.WithFields(log.Fields{
631 "oltId": o.ID,
632 "messageType": message.Type,
633 }).Trace("Received message")
634
635 switch message.Type {
636 case OltIndication:
637 msg, _ := message.Data.(OltIndicationMessage)
638 if msg.OperState == UP {
639 o.InternalState.Event("enable")
640 o.OperState.Event("enable")
641 } else if msg.OperState == DOWN {
642 o.InternalState.Event("disable")
643 o.OperState.Event("disable")
644 }
645 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800646 case AlarmIndication:
647 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
648 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000649 case NniIndication:
650 msg, _ := message.Data.(NniIndicationMessage)
651 o.sendNniIndication(msg, stream)
652 case PonIndication:
653 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530654 pon, _ := o.GetPonById(msg.PonPortID)
655 if msg.OperState == UP {
656 pon.OperState.Event("enable")
657 pon.InternalState.Event("enable")
658 } else if msg.OperState == DOWN {
659 pon.OperState.Event("disable")
660 pon.InternalState.Event("disable")
661 }
David Bainbridge103cf022019-12-16 20:11:35 +0000662 default:
663 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
664 }
665 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100667 wg.Done()
668 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700669}
670
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100671// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000672func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700673 oltLogger.WithFields(log.Fields{
674 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800675 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700676 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700677
David Bainbridge103cf022019-12-16 20:11:35 +0000678 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700679
David Bainbridge103cf022019-12-16 20:11:35 +0000680loop:
681 for {
682 select {
683 case <-ctx.Done():
684 oltLogger.Debug("NNI Indication processing canceled via context")
685 break loop
686 case message, ok := <-ch:
687 if !ok || ctx.Err() != nil {
688 oltLogger.Debug("NNI Indication processing canceled via channel closed")
689 break loop
690 }
691 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700692
David Bainbridge103cf022019-12-16 20:11:35 +0000693 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700694
David Bainbridge103cf022019-12-16 20:11:35 +0000695 if err != nil {
696 log.WithFields(log.Fields{
697 "IntfType": "nni",
698 "IntfId": nniId,
699 "Pkt": message.Pkt.Data(),
700 }).Error("Can't find Dst MacAddress in packet")
701 return
702 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700703
David Bainbridge103cf022019-12-16 20:11:35 +0000704 onu, err := o.FindOnuByMacAddress(onuMac)
705 if err != nil {
706 log.WithFields(log.Fields{
707 "IntfType": "nni",
708 "IntfId": nniId,
709 "Pkt": message.Pkt.Data(),
710 "MacAddress": onuMac.String(),
711 }).Error("Can't find ONU with MacAddress")
712 return
713 }
714
715 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
716 if err != nil {
717 log.Error("Fail to add double tag to packet")
718 }
719
720 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
721 IntfType: "nni",
722 IntfId: nniId,
723 Pkt: doubleTaggedPkt.Data()}}
724 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
725 oltLogger.WithFields(log.Fields{
726 "IntfType": data.PktInd.IntfType,
727 "IntfId": nniId,
728 "Pkt": doubleTaggedPkt.Data(),
729 }).Errorf("Fail to send PktInd indication: %v", err)
730 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700731 oltLogger.WithFields(log.Fields{
732 "IntfType": data.PktInd.IntfType,
733 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700734 "Pkt": doubleTaggedPkt.Data(),
David Bainbridge103cf022019-12-16 20:11:35 +0000735 "OnuSn": onu.Sn(),
736 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700737 }
738 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100739 wg.Done()
740 oltLogger.WithFields(log.Fields{
741 "nniChannel": o.nniPktInChannel,
742 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700743}
744
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700745// returns an ONU with a given Serial Number
746func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200747 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700748 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700749 for _, pon := range o.Pons {
750 for _, onu := range pon.Onus {
751 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700752 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700753 }
754 }
755 }
756
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700757 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
758}
759
William Kurkian9dadc5b2019-10-22 13:51:57 -0400760// returns an ONU with a given interface/Onu Id
761func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200762 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400763 // memoizing it will remove the bottleneck
764 for _, pon := range o.Pons {
765 if pon.ID == intfId {
766 for _, onu := range pon.Onus {
767 if onu.ID == onuId {
768 return onu, nil
769 }
770 }
771 }
772 }
773 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
774}
775
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700776// returns an ONU with a given Mac Address
777func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200778 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700779 // memoizing it will remove the bottleneck
780 for _, pon := range o.Pons {
781 for _, onu := range pon.Onus {
782 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700783 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700784 }
785 }
786 }
787
788 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700789}
790
Matteo Scandolo4747d292019-08-05 11:50:18 -0700791// GRPC Endpoints
792
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700793func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700794 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700795 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700796 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530797 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700798
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700799 pon, _ := o.GetPonById(onu.IntfId)
800 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500801 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700802
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700803 if err := _onu.OperState.Event("enable"); err != nil {
804 oltLogger.WithFields(log.Fields{
805 "IntfId": _onu.PonPortID,
806 "OnuSn": _onu.Sn(),
807 "OnuId": _onu.ID,
808 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700809 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700810 if err := _onu.InternalState.Event("enable"); err != nil {
811 oltLogger.WithFields(log.Fields{
812 "IntfId": _onu.PonPortID,
813 "OnuSn": _onu.Sn(),
814 "OnuId": _onu.ID,
815 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
816 }
817
818 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
819
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700820 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700821}
822
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700823func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700824 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700825 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700826}
827
Pragya Arya1cbefa42020-01-13 12:15:29 +0530828func (o OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
829 oltLogger.WithFields(log.Fields{
830 "IntfId": onu.IntfId,
831 "OnuId": onu.OnuId,
832 }).Info("Received DeleteOnu call from VOLTHA")
833
834 pon, err := o.GetPonById(onu.IntfId)
835 if err != nil {
836 oltLogger.WithFields(log.Fields{
837 "OnuId": onu.OnuId,
838 "IntfId": onu.IntfId,
839 "err": err,
840 }).Error("Can't find PonPort")
841 }
842 _onu, err := pon.GetOnuById(onu.OnuId)
843 if err != nil {
844 oltLogger.WithFields(log.Fields{
845 "OnuId": onu.OnuId,
846 "IntfId": onu.IntfId,
847 "err": err,
848 }).Error("Can't find Onu")
849 }
850
851 if err := _onu.InternalState.Event("initialize"); err != nil {
852 oltLogger.WithFields(log.Fields{
853 "IntfId": _onu.PonPortID,
854 "OnuSn": _onu.Sn(),
855 "OnuId": _onu.ID,
856 }).Infof("Failed to transition ONU to initialized state: %s", err.Error())
857 }
858
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700859 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700860}
861
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700862func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700863 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800864 oltLogger.WithFields(log.Fields{
865 "oltId": o.ID,
866 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530867 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800868
Matteo Scandolo401503a2019-12-11 14:48:14 -0800869 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530870 if pon.InternalState.Current() == "enabled" {
871 // disable PONs
872 msg := Message{
873 Type: PonIndication,
874 Data: PonIndicationMessage{
875 OperState: DOWN,
876 PonPortID: pon.ID,
877 },
878 }
879 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800880 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800881 }
882
Matteo Scandolo401503a2019-12-11 14:48:14 -0800883 // Note that we are not disabling the NNI as the real OLT does not.
884 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800885
886 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100887 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700888 Type: OltIndication,
889 Data: OltIndicationMessage{
890 OperState: DOWN,
891 },
892 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100893 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700894 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700895}
896
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700897func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700898 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700899 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700900}
901
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100902func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700903 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530904 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700905 o.Enable(stream)
906 return nil
907}
908
Pragya Arya2225f202020-01-29 18:05:01 +0530909func (o OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
910 oltLogger.Errorf("EnablePonIf request received for PON %d", intf.IntfId)
911 ponID := intf.GetIntfId()
912 msg := Message{
913 Type: PonIndication,
914 Data: PonIndicationMessage{
915 OperState: UP,
916 PonPortID: ponID,
917 },
918 }
919 o.channel <- msg
920
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700921 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700922}
923
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700924func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700925 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700926 "IntfId": flow.AccessIntfId,
927 "OnuId": flow.OnuId,
928 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700929 "InnerVlan": flow.Classifier.IVid,
930 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700931 "FlowType": flow.FlowType,
932 "FlowId": flow.FlowId,
933 "UniID": flow.UniId,
934 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +0530935 }).Tracef("OLT receives FlowAdd")
936
937 flowKey := FlowKey{}
938 if !o.enablePerf {
939 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
940 olt.Flows[flowKey] = *flow
941 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700942
943 if flow.AccessIntfId == -1 {
944 oltLogger.WithFields(log.Fields{
945 "FlowId": flow.FlowId,
946 }).Debugf("This is an OLT flow")
947 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700948 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700949 if err != nil {
950 oltLogger.WithFields(log.Fields{
951 "OnuId": flow.OnuId,
952 "IntfId": flow.AccessIntfId,
953 "err": err,
954 }).Error("Can't find PonPort")
955 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700956 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700957 if err != nil {
958 oltLogger.WithFields(log.Fields{
959 "OnuId": flow.OnuId,
960 "IntfId": flow.AccessIntfId,
961 "err": err,
962 }).Error("Can't find Onu")
963 }
Pragya Arya8bdb4532020-03-02 17:08:09 +0530964 if !o.enablePerf {
965 onu.Flows = append(onu.Flows, flowKey)
966 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700967
968 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700969 Type: FlowUpdate,
970 Data: OnuFlowUpdateMessage{
971 PonPortID: pon.ID,
972 OnuID: onu.ID,
973 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700974 },
975 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700976 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700977 }
978
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700979 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700980}
981
Pragya Arya8bdb4532020-03-02 17:08:09 +0530982// FlowRemove request from VOLTHA
983func (o OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
984 oltLogger.WithFields(log.Fields{
985 "FlowId": flow.FlowId,
986 "FlowType": flow.FlowType,
987 }).Tracef("OLT receives FlowRemove")
988
989 if !o.enablePerf { // remove only if flow were stored
990 flowKey := FlowKey{
991 ID: flow.FlowId,
992 Direction: flow.FlowType,
993 }
994
995 // Check if flow exists
996 storedFlow, ok := o.Flows[flowKey]
997 if !ok {
998 oltLogger.Errorf("Flow %v not found", flow)
999 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1000 }
1001
1002 // if its ONU flow remove it from ONU also
1003 if storedFlow.AccessIntfId != -1 {
1004 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1005 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1006 if err != nil {
1007 oltLogger.WithFields(log.Fields{
1008 "OnuId": storedFlow.OnuId,
1009 "IntfId": storedFlow.AccessIntfId,
1010 "err": err,
1011 }).Error("ONU not found")
1012 return new(openolt.Empty), nil
1013 }
1014 onu.DeleteFlow(flowKey)
1015 }
1016
1017 // delete from olt flows
1018 delete(o.Flows, flowKey)
1019 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001020 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001021}
1022
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001023func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001024 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1025 oltLogger.WithFields(log.Fields{
1026 "signature": res.HeartbeatSignature,
1027 }).Trace("HeartbeatCheck")
1028 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001029}
1030
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001031func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001032
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001033 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001034 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001035 "PonPorts": o.NumPon,
1036 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001037 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +01001038 devinfo.Vendor = common.Options.Olt.Vendor
1039 devinfo.Model = common.Options.Olt.Model
1040 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
1041 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
1042 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001043 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001044 devinfo.OnuIdStart = 1
1045 devinfo.OnuIdEnd = 255
1046 devinfo.AllocIdStart = 1024
1047 devinfo.AllocIdEnd = 16383
1048 devinfo.GemportIdStart = 1024
1049 devinfo.GemportIdEnd = 65535
1050 devinfo.FlowIdStart = 1
1051 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001052 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +01001053 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001054
1055 return devinfo, nil
1056}
1057
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001058func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001059 pon, _ := o.GetPonById(omci_msg.IntfId)
1060 onu, _ := pon.GetOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001061 oltLogger.WithFields(log.Fields{
1062 "IntfId": onu.PonPortID,
1063 "OnuId": onu.ID,
1064 "OnuSn": onu.Sn(),
1065 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001066 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001067 Type: OMCI,
1068 Data: OmciMessage{
1069 OnuSN: onu.SerialNumber,
1070 OnuID: onu.ID,
1071 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001072 },
1073 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001074 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001075 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001076}
1077
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001078func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001079 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001080 if err != nil {
1081 oltLogger.WithFields(log.Fields{
1082 "OnuId": onuPkt.OnuId,
1083 "IntfId": onuPkt.IntfId,
1084 "err": err,
1085 }).Error("Can't find PonPort")
1086 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001087 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001088 if err != nil {
1089 oltLogger.WithFields(log.Fields{
1090 "OnuId": onuPkt.OnuId,
1091 "IntfId": onuPkt.IntfId,
1092 "err": err,
1093 }).Error("Can't find Onu")
1094 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001095
Matteo Scandolo075b1892019-10-07 12:11:07 -07001096 oltLogger.WithFields(log.Fields{
1097 "IntfId": onu.PonPortID,
1098 "OnuId": onu.ID,
1099 "OnuSn": onu.Sn(),
1100 }).Tracef("Received OnuPacketOut")
1101
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001102 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001103 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001104
Matteo Scandolo075b1892019-10-07 12:11:07 -07001105 msg := Message{
1106 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001107 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -07001108 IntfId: onuPkt.IntfId,
1109 OnuId: onuPkt.OnuId,
1110 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001111 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001112 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001113 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001114 onu.Channel <- msg
1115
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001116 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001117}
1118
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001119func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001120 oltLogger.WithFields(log.Fields{
1121 "oltId": o.ID,
1122 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301123 publishEvent("OLT-reboot-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001124 go o.RestartOLT()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001125 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001126}
1127
1128func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301129 oltLogger.WithFields(log.Fields{
1130 "oltId": o.ID,
1131 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301132 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301133
Pragya Arya2225f202020-01-29 18:05:01 +05301134 // enable OLT
1135 oltMsg := Message{
1136 Type: OltIndication,
1137 Data: OltIndicationMessage{
1138 OperState: UP,
1139 },
Pragya Arya1881df02020-01-29 18:05:01 +05301140 }
Pragya Arya2225f202020-01-29 18:05:01 +05301141 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301142
Pragya Arya2225f202020-01-29 18:05:01 +05301143 for _, pon := range o.Pons {
1144 if pon.InternalState.Current() == "disabled" {
1145 msg := Message{
1146 Type: PonIndication,
1147 Data: PonIndicationMessage{
1148 OperState: UP,
1149 PonPortID: pon.ID,
1150 },
1151 }
1152 o.channel <- msg
1153 }
1154 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001155
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001156 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001157}
1158
1159func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001160 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1161
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001162 o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001163 // NOTE should we return an error if sendNniPakcet fails?
1164 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001165}
1166
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001167func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001168 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001169 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001170}
1171
Matteo Scandolo4747d292019-08-05 11:50:18 -07001172func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001173 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001174 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001175}
1176
1177func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001178 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001179 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001180}
1181
1182func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001183 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001184 return new(openolt.Empty), nil
1185}
1186
1187func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001188 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001189 return new(openolt.Empty), nil
1190}
1191
Anand S Katti09541352020-01-29 15:54:01 +05301192func (s OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
1193 oltLogger.WithFields(log.Fields{
1194 "OnuId": trafficSchedulers.OnuId,
1195 "IntfId": trafficSchedulers.IntfId,
1196 "OnuPortNo": trafficSchedulers.PortNo,
1197 }).Info("received CreateTrafficSchedulers")
1198
1199 if !s.enablePerf {
1200 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1201 if err != nil {
1202 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1203 return new(openolt.Empty), err
1204 }
1205 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1206 if err != nil {
1207 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1208 return new(openolt.Empty), err
1209 }
1210 onu.TrafficSchedulers = trafficSchedulers
1211 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001212 return new(openolt.Empty), nil
1213}
1214
Anand S Katti09541352020-01-29 15:54:01 +05301215func (s OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
1216 oltLogger.WithFields(log.Fields{
1217 "OnuId": trafficSchedulers.OnuId,
1218 "IntfId": trafficSchedulers.IntfId,
1219 "OnuPortNo": trafficSchedulers.PortNo,
1220 }).Info("received RemoveTrafficSchedulers")
1221 if !s.enablePerf {
1222 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1223 if err != nil {
1224 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1225 return new(openolt.Empty), err
1226 }
1227 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1228 if err != nil {
1229 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1230 return new(openolt.Empty), err
1231 }
1232
1233 onu.TrafficSchedulers = nil
1234 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001235 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001236}
Scott Baker41724b82020-01-21 19:54:53 -08001237
1238// assumes caller has properly formulated an openolt.AlarmIndication
1239func (o OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
1240 msg := Message{
1241 Type: AlarmIndication,
1242 Data: ind,
1243 }
1244
1245 o.channel <- msg
1246 return nil
1247}
rajeshf921f882020-03-06 18:24:28 +05301248
1249func getOltIP() net.IP {
1250 conn, err := net.Dial("udp", "8.8.8.8:80")
1251 if err != nil {
1252 oltLogger.Error(err.Error())
1253 return net.IP{}
1254 }
1255 defer func() {
1256 err := conn.Close()
1257 if err != nil {
1258 oltLogger.Error(err.Error())
1259 }
1260 }()
1261
1262 localAddr := conn.LocalAddr().(*net.UDPAddr)
1263
1264 return localAddr.IP
1265}