blob: 2799de827fb2798f4af0492cb75a31c424ccb0cf [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"
Matteo Scandolof65e6872020-04-15 15:18:43 -070036 "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
Matteo Scandolo4747d292019-08-05 11:50:18 -0700151
Matteo Scandolof65e6872020-04-15 15:18:43 -0700152 if options.BBSim.STagAllocation == common.TagAllocationShared && options.BBSim.CTagAllocation == common.TagAllocationShared {
153 oltLogger.Fatalf("This configuration will result in duplicate C/S tags combination")
154 } else if options.BBSim.STagAllocation == common.TagAllocationUnique && options.BBSim.CTagAllocation == common.TagAllocationUnique {
155 oltLogger.Fatalf("This configuration is not supported yet")
156 } else if options.BBSim.STagAllocation == common.TagAllocationShared && options.BBSim.CTagAllocation == common.TagAllocationUnique {
157 // ATT case
158 availableCTag := options.BBSim.CTag
159 for i := 0; i < olt.NumPon; i++ {
160 p := CreatePonPort(&olt, uint32(i))
161
162 // create ONU devices
163 for j := 0; j < olt.NumOnuPerPon; j++ {
164 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700165 o := CreateONU(&olt, p, uint32(j+1), options.BBSim.STag, availableCTag, options.BBSim.EnableAuth, options.BBSim.EnableDhcp, delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700166 p.Onus = append(p.Onus, o)
167 availableCTag = availableCTag + 1
168 }
169
170 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700171 }
Matteo Scandolof65e6872020-04-15 15:18:43 -0700172 } else if options.BBSim.STagAllocation == common.TagAllocationUnique && options.BBSim.CTagAllocation == common.TagAllocationShared {
173 // DT case
174 availableSTag := options.BBSim.STag
175 for i := 0; i < olt.NumPon; i++ {
176 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700177
Matteo Scandolof65e6872020-04-15 15:18:43 -0700178 // create ONU devices
179 for j := 0; j < olt.NumOnuPerPon; j++ {
180 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700181 o := CreateONU(&olt, p, uint32(j+1), availableSTag, options.BBSim.CTag, options.BBSim.EnableAuth, options.BBSim.EnableDhcp, delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700182 p.Onus = append(p.Onus, o)
183 availableSTag = availableSTag + 1
184 }
185
186 olt.Pons = append(olt.Pons, p)
187 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700188 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100189
Matteo Scandolod32c3822019-11-26 15:57:46 -0700190 if isMock != true {
191 if err := olt.InternalState.Event("initialize"); err != nil {
192 log.Errorf("Error initializing OLT: %v", err)
193 return nil
194 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100195 }
196
Pragya Arya324337e2020-02-20 14:35:08 +0530197 if olt.PublishEvents {
198 log.Debugf("BBSim event publishing is enabled")
199 // Create a channel to write event messages
200 olt.EventChannel = make(chan common.Event, 100)
201 }
202
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700203 return &olt
204}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700205
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100206func (o *OltDevice) InitOlt() error {
207
208 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800209 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100210 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800211 // FIXME there should never be a server running if we are initializing the OLT
212 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100213 }
214
215 // create new channel for processOltMessages Go routine
216 o.channel = make(chan Message)
217
218 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
219 // FIXME we are assuming we have only one NNI
220 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800221 // NOTE we want to make sure the state is down when we initialize the OLT,
222 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
223 // in-band management
224 o.Nnis[0].OperState.SetState("down")
225 ch, handle, err := o.Nnis[0].NewVethChan()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100226 if err == nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800227 oltLogger.WithFields(log.Fields{
228 "Type": o.Nnis[0].Type,
229 "IntfId": o.Nnis[0].ID,
230 "OperState": o.Nnis[0].OperState.Current(),
231 }).Info("NNI Channel created")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100232 o.nniPktInChannel = ch
Matteo Scandolo401503a2019-12-11 14:48:14 -0800233 o.nniHandle = handle
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100234 } else {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800235 oltLogger.Errorf("Error getting NNI channel: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100236 }
237 }
238
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100239 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700240}
241
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800242func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800244 rebootDelay := common.Options.Olt.OltRebootDelay
245
246 oltLogger.WithFields(log.Fields{
247 "oltId": o.ID,
248 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
249
250 // transition internal state to deleted
251 if err := o.InternalState.Event("delete"); err != nil {
252 oltLogger.WithFields(log.Fields{
253 "oltId": o.ID,
254 }).Errorf("Error deleting OLT: %v", err)
255 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100256 }
257
258 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800259 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
260 if err := o.StopOltServer(); err != nil {
Pragya Arya2225f202020-01-29 18:05:01 +0530261 oltLogger.Errorf("Error in stopping OLT server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100262 return err
263 }
264
Pragya Arya2225f202020-01-29 18:05:01 +0530265 for _, pon := range olt.Pons {
266 msg := Message{
267 Type: PonIndication,
268 Data: PonIndicationMessage{
269 OperState: DOWN,
270 PonPortID: pon.ID,
271 },
272 }
273 o.channel <- msg
274
275 for _, onu := range pon.Onus {
276 if onu.InternalState.Current() != "initialized" {
277 onu.InternalState.Event("disable")
278 }
279 }
280 }
281
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100282 // terminate the OLT's processOltMessages go routine
283 close(o.channel)
284 // terminate the OLT's processNniPacketIns go routine
Andy Bavier421f4d52020-01-21 15:39:22 -0700285 go o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100286 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100287
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100288 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100289
290 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800291 oltLogger.WithFields(log.Fields{
292 "oltId": o.ID,
293 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100294 return err
295 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800296 oltLogger.WithFields(log.Fields{
297 "oltId": o.ID,
298 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100299 return nil
300}
301
302// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800303func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100304 address := common.Options.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700305 lis, err := net.Listen("tcp", address)
306 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700307 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700308 }
309 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100310
Matteo Scandolo4747d292019-08-05 11:50:18 -0700311 openolt.RegisterOpenoltServer(grpcServer, o)
312
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100313 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700314
Matteo Scandolo4747d292019-08-05 11:50:18 -0700315 go grpcServer.Serve(lis)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100316 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700317
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100318 return grpcServer, nil
319}
320
321// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800322func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100323 // TODO handle poweroff vs graceful shutdown
324 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800325 oltLogger.WithFields(log.Fields{
326 "oltId": o.SerialNumber,
327 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100328 oltServer.Stop()
329 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700330 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800331
Matteo Scandolo4747d292019-08-05 11:50:18 -0700332 return nil
333}
334
335// Device Methods
336
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100337// Enable implements the OpenOLT EnableIndicationServer functionality
338func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700339 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530340 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700341
David Bainbridge103cf022019-12-16 20:11:35 +0000342 // If enabled has already been called then an enabled context has
343 // been created. If this is the case then we want to cancel all the
344 // proessing loops associated with that enable before we recreate
345 // new ones
346 o.Lock()
347 if o.enableContext != nil && o.enableContextCancel != nil {
348 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530349 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000350 }
351 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
352 o.Unlock()
353
Matteo Scandolo4747d292019-08-05 11:50:18 -0700354 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800355 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700356
Pragya Arya1cbefa42020-01-13 12:15:29 +0530357 o.OpenoltStream = &stream
358
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100359 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000360 go o.processOltMessages(o.enableContext, stream, &wg)
361 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700362
363 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100364 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700365 Type: OltIndication,
366 Data: OltIndicationMessage{
367 OperState: UP,
368 },
369 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100370 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700371
372 // send NNI Port Indications
373 for _, nni := range o.Nnis {
374 msg := Message{
375 Type: NniIndication,
376 Data: NniIndicationMessage{
377 OperState: UP,
378 NniPortID: nni.ID,
379 },
380 }
381 o.channel <- msg
382 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100383
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800384 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100385
Pragya Arya2225f202020-01-29 18:05:01 +0530386 if rebootFlag == true {
387 for _, pon := range o.Pons {
388 if pon.InternalState.Current() == "disabled" {
389 msg := Message{
390 Type: PonIndication,
391 Data: PonIndicationMessage{
392 OperState: UP,
393 PonPortID: pon.ID,
394 },
395 }
396 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000397 }
Pragya Arya2225f202020-01-29 18:05:01 +0530398 }
399 } else {
400
401 // 1. controlledActivation == Default: Send both PON and ONUs indications
402 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
403
404 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
405 // send PON Port indications
406 for _, pon := range o.Pons {
407 msg := Message{
408 Type: PonIndication,
409 Data: PonIndicationMessage{
410 OperState: UP,
411 PonPortID: pon.ID,
412 },
413 }
414 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700415 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700416 }
417 }
418
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800419 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530420
421 if !o.enablePerf {
422 // Start a go routine to send periodic port stats to openolt adapter
423 go o.periodicPortStats(o.enableContext)
424 }
425
Matteo Scandolo4747d292019-08-05 11:50:18 -0700426 wg.Wait()
427 return nil
428}
429
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800430func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400431 ch := omcisim.GetChannel()
432
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100433 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400434
David Bainbridge103cf022019-12-16 20:11:35 +0000435loop:
436 for {
437 select {
438 case <-ctx.Done():
439 oltLogger.Debug("OMCI processing canceled via context")
440 break loop
441 case message, ok := <-ch:
442 if !ok || ctx.Err() != nil {
443 oltLogger.Debug("OMCI processing canceled via channel close")
444 break loop
445 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800446
447 oltLogger.WithFields(log.Fields{
448 "messageType": message.Type,
449 "OnuId": message.Data.OnuId,
450 "IntfId": message.Data.IntfId,
451 }).Info("Received message on OMCI Sim channel")
452
David Bainbridge103cf022019-12-16 20:11:35 +0000453 onuId := message.Data.OnuId
454 intfId := message.Data.IntfId
455 onu, err := o.FindOnuById(intfId, onuId)
456 if err != nil {
457 oltLogger.Errorf("Failed to find onu: %v", err)
458 continue
459 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800460 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400461 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400462 }
David Bainbridge103cf022019-12-16 20:11:35 +0000463
464 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400465}
466
Pragya Arya996a0892020-03-09 21:47:52 +0530467func (o *OltDevice) periodicPortStats(ctx context.Context) {
468 var portStats *openolt.PortStatistics
469 for {
470 select {
471 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
472 // send NNI port stats
473 for _, port := range o.Nnis {
474 incrementStat := true
475 if port.OperState.Current() == "down" {
476 incrementStat = false
477 }
478 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
479 o.sendPortStatsIndication(portStats, port.ID, port.Type)
480 }
481
482 // send PON port stats
483 for _, port := range o.Pons {
484 incrementStat := true
485 // do not increment port stats if PON port is down or no ONU is activated on PON port
486 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
487 incrementStat = false
488 }
489 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
490 o.sendPortStatsIndication(portStats, port.ID, port.Type)
491 }
492 case <-ctx.Done():
493 log.Debug("Stop sending port stats")
494 return
495 }
496
497 }
498}
499
Matteo Scandolo4747d292019-08-05 11:50:18 -0700500// Helpers method
501
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700502func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700503 for _, pon := range o.Pons {
504 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700505 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700506 }
507 }
508 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
509}
510
511func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
512 for _, nni := range o.Nnis {
513 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700514 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700515 }
516 }
517 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
518}
519
Scott Baker41724b82020-01-21 19:54:53 -0800520func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
521 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
522 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
523 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
524 return
525 }
526
527 oltLogger.WithFields(log.Fields{
528 "AlarmIndication": alarmInd,
529 }).Debug("Sent Indication_AlarmInd")
530}
531
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100532func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700533 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
534 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700535 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800536 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700537 }
538
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700539 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700540 "OperState": msg.OperState,
541 }).Debug("Sent Indication_OltInd")
542}
543
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100544func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700545 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800546 if msg.OperState == UP {
547 if err := nni.OperState.Event("enable"); err != nil {
548 log.WithFields(log.Fields{
549 "Type": nni.Type,
550 "IntfId": nni.ID,
551 "OperState": nni.OperState.Current(),
552 }).Errorf("Can't move NNI Port to enabled state: %v", err)
553 }
554 } else if msg.OperState == DOWN {
555 if err := nni.OperState.Event("disable"); err != nil {
556 log.WithFields(log.Fields{
557 "Type": nni.Type,
558 "IntfId": nni.ID,
559 "OperState": nni.OperState.Current(),
560 }).Errorf("Can't move NNI Port to disable state: %v", err)
561 }
562 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700563 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700564 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700565 Type: nni.Type,
566 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700567 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700568 }}
569
570 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700571 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800572 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700573 }
574
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700575 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700576 "Type": nni.Type,
577 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700578 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700579 }).Debug("Sent Indication_IntfOperInd for NNI")
580}
581
Pragya Arya2225f202020-01-29 18:05:01 +0530582func (o *OltDevice) sendPonIndication(ponPortID uint32) {
583
584 stream := *o.OpenoltStream
585 pon, _ := o.GetPonById(ponPortID)
586 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700587 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700588 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700589 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700590 }}
591
592 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700593 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800594 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700595 }
596
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700597 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700598 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700599 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700600 }).Debug("Sent Indication_IntfInd")
601
Pragya Arya2225f202020-01-29 18:05:01 +0530602 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700603 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700604 Type: pon.Type,
605 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700606 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700607 }}
608
609 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700610 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800611 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612 }
613
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700614 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700615 "Type": pon.Type,
616 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700617 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700618 }).Debug("Sent Indication_IntfOperInd for PON")
619}
620
Pragya Arya996a0892020-03-09 21:47:52 +0530621func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530622 if o.InternalState.Current() == "enabled" {
623 oltLogger.WithFields(log.Fields{
624 "Type": portType,
625 "IntfId": portID,
626 }).Trace("Sending port stats")
627 stats.IntfId = InterfaceIDToPortNo(portID, portType)
628 data := &openolt.Indication_PortStats{
629 PortStats: stats,
630 }
631 stream := *o.OpenoltStream
632 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
633 oltLogger.Errorf("Failed to send PortStats: %v", err)
634 return
635 }
Pragya Arya996a0892020-03-09 21:47:52 +0530636 }
637}
638
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100639// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000640func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100641 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000642 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700643
David Bainbridge103cf022019-12-16 20:11:35 +0000644loop:
645 for {
646 select {
647 case <-ctx.Done():
648 oltLogger.Debug("OLT Indication processing canceled via context")
649 break loop
650 case message, ok := <-ch:
651 if !ok || ctx.Err() != nil {
652 oltLogger.Debug("OLT Indication processing canceled via closed channel")
653 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700654 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655
David Bainbridge103cf022019-12-16 20:11:35 +0000656 oltLogger.WithFields(log.Fields{
657 "oltId": o.ID,
658 "messageType": message.Type,
659 }).Trace("Received message")
660
661 switch message.Type {
662 case OltIndication:
663 msg, _ := message.Data.(OltIndicationMessage)
664 if msg.OperState == UP {
665 o.InternalState.Event("enable")
666 o.OperState.Event("enable")
667 } else if msg.OperState == DOWN {
668 o.InternalState.Event("disable")
669 o.OperState.Event("disable")
670 }
671 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800672 case AlarmIndication:
673 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
674 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000675 case NniIndication:
676 msg, _ := message.Data.(NniIndicationMessage)
677 o.sendNniIndication(msg, stream)
678 case PonIndication:
679 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530680 pon, _ := o.GetPonById(msg.PonPortID)
681 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530682 if err := pon.OperState.Event("enable"); err != nil {
683 oltLogger.WithFields(log.Fields{
684 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800685 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530686 }).Error("Can't Enable Oper state for PON Port")
687 }
688 if err := pon.InternalState.Event("enable"); err != nil {
689 oltLogger.WithFields(log.Fields{
690 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800691 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530692 }).Error("Can't Enable Internal state for PON Port")
693 }
Pragya Arya2225f202020-01-29 18:05:01 +0530694 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530695 if err := pon.OperState.Event("disable"); err != nil {
696 oltLogger.WithFields(log.Fields{
697 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800698 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530699 }).Error("Can't Disable Oper state for PON Port")
700 }
701 if err := pon.InternalState.Event("disable"); err != nil {
702 oltLogger.WithFields(log.Fields{
703 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800704 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530705 }).Error("Can't Disable Internal state for PON Port")
706 }
Pragya Arya2225f202020-01-29 18:05:01 +0530707 }
David Bainbridge103cf022019-12-16 20:11:35 +0000708 default:
709 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
710 }
711 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700712 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100713 wg.Done()
714 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700715}
716
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100717// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000718func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700719 oltLogger.WithFields(log.Fields{
720 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800721 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700722 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700723
David Bainbridge103cf022019-12-16 20:11:35 +0000724 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700725
David Bainbridge103cf022019-12-16 20:11:35 +0000726loop:
727 for {
728 select {
729 case <-ctx.Done():
730 oltLogger.Debug("NNI Indication processing canceled via context")
731 break loop
732 case message, ok := <-ch:
733 if !ok || ctx.Err() != nil {
734 oltLogger.Debug("NNI Indication processing canceled via channel closed")
735 break loop
736 }
737 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700738
David Bainbridge103cf022019-12-16 20:11:35 +0000739 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700740
David Bainbridge103cf022019-12-16 20:11:35 +0000741 if err != nil {
742 log.WithFields(log.Fields{
743 "IntfType": "nni",
744 "IntfId": nniId,
745 "Pkt": message.Pkt.Data(),
746 }).Error("Can't find Dst MacAddress in packet")
747 return
748 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700749
David Bainbridge103cf022019-12-16 20:11:35 +0000750 onu, err := o.FindOnuByMacAddress(onuMac)
751 if err != nil {
752 log.WithFields(log.Fields{
753 "IntfType": "nni",
754 "IntfId": nniId,
755 "Pkt": message.Pkt.Data(),
756 "MacAddress": onuMac.String(),
757 }).Error("Can't find ONU with MacAddress")
758 return
759 }
760
761 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
762 if err != nil {
763 log.Error("Fail to add double tag to packet")
764 }
765
766 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
767 IntfType: "nni",
768 IntfId: nniId,
769 Pkt: doubleTaggedPkt.Data()}}
770 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
771 oltLogger.WithFields(log.Fields{
772 "IntfType": data.PktInd.IntfType,
773 "IntfId": nniId,
774 "Pkt": doubleTaggedPkt.Data(),
775 }).Errorf("Fail to send PktInd indication: %v", err)
776 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700777 oltLogger.WithFields(log.Fields{
778 "IntfType": data.PktInd.IntfType,
779 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700780 "Pkt": doubleTaggedPkt.Data(),
David Bainbridge103cf022019-12-16 20:11:35 +0000781 "OnuSn": onu.Sn(),
782 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700783 }
784 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100785 wg.Done()
786 oltLogger.WithFields(log.Fields{
787 "nniChannel": o.nniPktInChannel,
788 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700789}
790
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700791// returns an ONU with a given Serial Number
792func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200793 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700794 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700795 for _, pon := range o.Pons {
796 for _, onu := range pon.Onus {
797 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700798 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700799 }
800 }
801 }
802
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700803 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
804}
805
William Kurkian9dadc5b2019-10-22 13:51:57 -0400806// returns an ONU with a given interface/Onu Id
807func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200808 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400809 // memoizing it will remove the bottleneck
810 for _, pon := range o.Pons {
811 if pon.ID == intfId {
812 for _, onu := range pon.Onus {
813 if onu.ID == onuId {
814 return onu, nil
815 }
816 }
817 }
818 }
819 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
820}
821
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700822// returns an ONU with a given Mac Address
823func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200824 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700825 // memoizing it will remove the bottleneck
826 for _, pon := range o.Pons {
827 for _, onu := range pon.Onus {
828 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700829 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700830 }
831 }
832 }
833
834 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700835}
836
Matteo Scandolo4747d292019-08-05 11:50:18 -0700837// GRPC Endpoints
838
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700839func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700840 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700841 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700842 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530843 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700844
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700845 pon, _ := o.GetPonById(onu.IntfId)
846 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500847 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700848
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700849 if err := _onu.OperState.Event("enable"); err != nil {
850 oltLogger.WithFields(log.Fields{
851 "IntfId": _onu.PonPortID,
852 "OnuSn": _onu.Sn(),
853 "OnuId": _onu.ID,
854 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700855 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700856 if err := _onu.InternalState.Event("enable"); err != nil {
857 oltLogger.WithFields(log.Fields{
858 "IntfId": _onu.PonPortID,
859 "OnuSn": _onu.Sn(),
860 "OnuId": _onu.ID,
861 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
862 }
863
864 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
865
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700866 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700867}
868
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700869func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700870 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700871 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700872}
873
Pragya Arya1cbefa42020-01-13 12:15:29 +0530874func (o OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
875 oltLogger.WithFields(log.Fields{
876 "IntfId": onu.IntfId,
877 "OnuId": onu.OnuId,
878 }).Info("Received DeleteOnu call from VOLTHA")
879
880 pon, err := o.GetPonById(onu.IntfId)
881 if err != nil {
882 oltLogger.WithFields(log.Fields{
883 "OnuId": onu.OnuId,
884 "IntfId": onu.IntfId,
885 "err": err,
886 }).Error("Can't find PonPort")
887 }
888 _onu, err := pon.GetOnuById(onu.OnuId)
889 if err != nil {
890 oltLogger.WithFields(log.Fields{
891 "OnuId": onu.OnuId,
892 "IntfId": onu.IntfId,
893 "err": err,
894 }).Error("Can't find Onu")
895 }
896
Hardik Windlassad790cb2020-06-17 21:26:22 +0530897 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530898 oltLogger.WithFields(log.Fields{
899 "IntfId": _onu.PonPortID,
900 "OnuSn": _onu.Sn(),
901 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530902 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
903 }
904
905 time.Sleep(1 * time.Second)
906
907 // ONU Re-Discovery
908 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
909 if err := _onu.InternalState.Event("initialize"); err != nil {
910 oltLogger.WithFields(log.Fields{
911 "IntfId": _onu.PonPortID,
912 "OnuSn": _onu.Sn(),
913 "OnuId": _onu.ID,
914 }).Infof("Failed to transition ONU to initialized state: %s", err.Error())
915 }
916
917 if err := _onu.InternalState.Event("discover"); err != nil {
918 oltLogger.WithFields(log.Fields{
919 "IntfId": _onu.PonPortID,
920 "OnuSn": _onu.Sn(),
921 "OnuId": _onu.ID,
922 }).Infof("Failed to transition ONU to discovered state: %s", err.Error())
923 }
Pragya Arya1cbefa42020-01-13 12:15:29 +0530924 }
925
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700926 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700927}
928
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700929func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700930 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800931 oltLogger.WithFields(log.Fields{
932 "oltId": o.ID,
933 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530934 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800935
Matteo Scandolo401503a2019-12-11 14:48:14 -0800936 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530937 if pon.InternalState.Current() == "enabled" {
938 // disable PONs
939 msg := Message{
940 Type: PonIndication,
941 Data: PonIndicationMessage{
942 OperState: DOWN,
943 PonPortID: pon.ID,
944 },
945 }
946 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800947 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800948 }
949
Matteo Scandolo401503a2019-12-11 14:48:14 -0800950 // Note that we are not disabling the NNI as the real OLT does not.
951 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800952
953 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100954 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700955 Type: OltIndication,
956 Data: OltIndicationMessage{
957 OperState: DOWN,
958 },
959 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100960 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700961 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700962}
963
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200964func (o OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530965 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200966 ponID := intf.GetIntfId()
967 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200968
969 msg := Message{
970 Type: PonIndication,
971 Data: PonIndicationMessage{
972 OperState: DOWN,
973 PonPortID: ponID,
974 },
975 }
976 o.channel <- msg
977
978 for _, onu := range pon.Onus {
979
980 onuIndication := OnuIndicationMessage{
981 OperState: DOWN,
982 PonPortID: ponID,
983 OnuID: onu.ID,
984 OnuSN: onu.SerialNumber,
985 }
986 onu.sendOnuIndication(onuIndication, *o.OpenoltStream)
987
988 }
989
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700990 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700991}
992
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100993func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700994 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530995 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700996 o.Enable(stream)
997 return nil
998}
999
Pragya Arya2225f202020-01-29 18:05:01 +05301000func (o OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301001 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301002 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001003 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001004
Pragya Arya2225f202020-01-29 18:05:01 +05301005 msg := Message{
1006 Type: PonIndication,
1007 Data: PonIndicationMessage{
1008 OperState: UP,
1009 PonPortID: ponID,
1010 },
1011 }
1012 o.channel <- msg
1013
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001014 for _, onu := range pon.Onus {
1015
1016 onuIndication := OnuIndicationMessage{
1017 OperState: UP,
1018 PonPortID: ponID,
1019 OnuID: onu.ID,
1020 OnuSN: onu.SerialNumber,
1021 }
1022 onu.sendOnuIndication(onuIndication, *o.OpenoltStream)
1023
1024 }
1025
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001026 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001027}
1028
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001029func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001030 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001031 "IntfId": flow.AccessIntfId,
1032 "OnuId": flow.OnuId,
1033 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001034 "InnerVlan": flow.Classifier.IVid,
1035 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001036 "FlowType": flow.FlowType,
1037 "FlowId": flow.FlowId,
1038 "UniID": flow.UniId,
1039 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301040 }).Tracef("OLT receives FlowAdd")
1041
1042 flowKey := FlowKey{}
1043 if !o.enablePerf {
1044 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
1045 olt.Flows[flowKey] = *flow
1046 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001047
1048 if flow.AccessIntfId == -1 {
1049 oltLogger.WithFields(log.Fields{
1050 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001051 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001052 } else if flow.FlowType == "multicast" {
1053 oltLogger.WithFields(log.Fields{
1054 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001055 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001056 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001057 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001058 if err != nil {
1059 oltLogger.WithFields(log.Fields{
1060 "OnuId": flow.OnuId,
1061 "IntfId": flow.AccessIntfId,
1062 "err": err,
1063 }).Error("Can't find PonPort")
1064 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001065 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001066 if err != nil {
1067 oltLogger.WithFields(log.Fields{
1068 "OnuId": flow.OnuId,
1069 "IntfId": flow.AccessIntfId,
1070 "err": err,
1071 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001072 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001073 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301074 if !o.enablePerf {
1075 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301076 // Generate event on first flow for ONU
1077 if len(onu.Flows) == 1 {
1078 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1079 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301080 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001081
1082 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001083 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001084 Data: OnuFlowUpdateMessage{
1085 PonPortID: pon.ID,
1086 OnuID: onu.ID,
1087 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001088 },
1089 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001090 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001091 }
1092
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001093 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001094}
1095
Pragya Arya8bdb4532020-03-02 17:08:09 +05301096// FlowRemove request from VOLTHA
1097func (o OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001098
Pragya Arya8bdb4532020-03-02 17:08:09 +05301099 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301100 "FlowId": flow.FlowId,
1101 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001102 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301103
1104 if !o.enablePerf { // remove only if flow were stored
1105 flowKey := FlowKey{
1106 ID: flow.FlowId,
1107 Direction: flow.FlowType,
1108 }
1109
1110 // Check if flow exists
1111 storedFlow, ok := o.Flows[flowKey]
1112 if !ok {
1113 oltLogger.Errorf("Flow %v not found", flow)
1114 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1115 }
1116
1117 // if its ONU flow remove it from ONU also
1118 if storedFlow.AccessIntfId != -1 {
1119 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1120 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1121 if err != nil {
1122 oltLogger.WithFields(log.Fields{
1123 "OnuId": storedFlow.OnuId,
1124 "IntfId": storedFlow.AccessIntfId,
1125 "err": err,
1126 }).Error("ONU not found")
1127 return new(openolt.Empty), nil
1128 }
1129 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301130 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301131 }
1132
1133 // delete from olt flows
1134 delete(o.Flows, flowKey)
1135 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001136
1137 if flow.AccessIntfId == -1 {
1138 oltLogger.WithFields(log.Fields{
1139 "FlowId": flow.FlowId,
1140 }).Debug("Removing OLT flow")
1141 } else if flow.FlowType == "multicast" {
1142 oltLogger.WithFields(log.Fields{
1143 "FlowId": flow.FlowId,
1144 }).Debug("Removing OLT multicast flow")
1145 } else {
1146
1147 onu, err := o.GetOnuByFlowId(flow.FlowId)
1148 if err != nil {
1149 oltLogger.WithFields(log.Fields{
1150 "OnuId": flow.OnuId,
1151 "IntfId": flow.AccessIntfId,
1152 "err": err,
1153 }).Error("Can't find Onu")
1154 return nil, err
1155 }
1156
1157 msg := Message{
1158 Type: FlowRemoved,
1159 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301160 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001161 },
1162 }
1163 onu.Channel <- msg
1164 }
1165
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001166 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001167}
1168
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001169func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001170 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1171 oltLogger.WithFields(log.Fields{
1172 "signature": res.HeartbeatSignature,
1173 }).Trace("HeartbeatCheck")
1174 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001175}
1176
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001177func (o *OltDevice) GetOnuByFlowId(flowId uint32) (*Onu, error) {
1178 for _, pon := range o.Pons {
1179 for _, onu := range pon.Onus {
1180 for _, fId := range onu.FlowIds {
1181 if fId == flowId {
1182 return onu, nil
1183 }
1184 }
1185 }
1186 }
1187 return nil, errors.New(fmt.Sprintf("Cannot find Onu by flowId %d", flowId))
1188}
1189
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001190func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001191
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001192 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001193 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001194 "PonPorts": o.NumPon,
1195 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001196 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +01001197 devinfo.Vendor = common.Options.Olt.Vendor
1198 devinfo.Model = common.Options.Olt.Model
1199 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
1200 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
1201 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001202 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001203 devinfo.OnuIdStart = 1
1204 devinfo.OnuIdEnd = 255
1205 devinfo.AllocIdStart = 1024
1206 devinfo.AllocIdEnd = 16383
1207 devinfo.GemportIdStart = 1024
1208 devinfo.GemportIdEnd = 65535
1209 devinfo.FlowIdStart = 1
1210 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001211 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +01001212 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001213
1214 return devinfo, nil
1215}
1216
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001217func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001218 pon, err := o.GetPonById(omci_msg.IntfId)
1219 if err != nil {
1220 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001221 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001222 "onu_id": omci_msg.OnuId,
1223 "pon_id": omci_msg.IntfId,
1224 }).Error("pon ID not found")
1225 return nil, err
1226 }
1227
1228 onu, err := pon.GetOnuById(omci_msg.OnuId)
1229 if err != nil {
1230 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001231 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001232 "onu_id": omci_msg.OnuId,
1233 "pon_id": omci_msg.IntfId,
1234 }).Error("onu ID not found")
1235 return nil, err
1236 }
1237
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001238 oltLogger.WithFields(log.Fields{
1239 "IntfId": onu.PonPortID,
1240 "OnuId": onu.ID,
1241 "OnuSn": onu.Sn(),
1242 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001243 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001244 Type: OMCI,
1245 Data: OmciMessage{
1246 OnuSN: onu.SerialNumber,
1247 OnuID: onu.ID,
1248 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001249 },
1250 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001251 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001252 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001253}
1254
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001255func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001256 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001257 if err != nil {
1258 oltLogger.WithFields(log.Fields{
1259 "OnuId": onuPkt.OnuId,
1260 "IntfId": onuPkt.IntfId,
1261 "err": err,
1262 }).Error("Can't find PonPort")
1263 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001264 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001265 if err != nil {
1266 oltLogger.WithFields(log.Fields{
1267 "OnuId": onuPkt.OnuId,
1268 "IntfId": onuPkt.IntfId,
1269 "err": err,
1270 }).Error("Can't find Onu")
1271 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001272
Matteo Scandolo075b1892019-10-07 12:11:07 -07001273 oltLogger.WithFields(log.Fields{
1274 "IntfId": onu.PonPortID,
1275 "OnuId": onu.ID,
1276 "OnuSn": onu.Sn(),
1277 }).Tracef("Received OnuPacketOut")
1278
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001279 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001280 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001281
Matteo Scandolo075b1892019-10-07 12:11:07 -07001282 msg := Message{
1283 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001284 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -07001285 IntfId: onuPkt.IntfId,
1286 OnuId: onuPkt.OnuId,
1287 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001288 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001289 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001290 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001291 onu.Channel <- msg
1292
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001293 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001294}
1295
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001296func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001297 oltLogger.WithFields(log.Fields{
1298 "oltId": o.ID,
1299 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301300 publishEvent("OLT-reboot-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001301 go o.RestartOLT()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001302 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001303}
1304
1305func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301306 oltLogger.WithFields(log.Fields{
1307 "oltId": o.ID,
1308 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301309 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301310
Pragya Arya2225f202020-01-29 18:05:01 +05301311 // enable OLT
1312 oltMsg := Message{
1313 Type: OltIndication,
1314 Data: OltIndicationMessage{
1315 OperState: UP,
1316 },
Pragya Arya1881df02020-01-29 18:05:01 +05301317 }
Pragya Arya2225f202020-01-29 18:05:01 +05301318 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301319
Pragya Arya2225f202020-01-29 18:05:01 +05301320 for _, pon := range o.Pons {
1321 if pon.InternalState.Current() == "disabled" {
1322 msg := Message{
1323 Type: PonIndication,
1324 Data: PonIndicationMessage{
1325 OperState: UP,
1326 PonPortID: pon.ID,
1327 },
1328 }
1329 o.channel <- msg
1330 }
1331 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001332
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001333 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001334}
1335
1336func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001337 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1338
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001339 o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001340 // NOTE should we return an error if sendNniPakcet fails?
1341 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001342}
1343
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001344func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001345 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001346 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001347}
1348
Matteo Scandolo4747d292019-08-05 11:50:18 -07001349func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001350 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001351 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001352}
1353
1354func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001355 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001356 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001357}
1358
1359func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001360 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001361 return new(openolt.Empty), nil
1362}
1363
1364func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001365 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001366 return new(openolt.Empty), nil
1367}
1368
Anand S Katti09541352020-01-29 15:54:01 +05301369func (s OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
1370 oltLogger.WithFields(log.Fields{
1371 "OnuId": trafficSchedulers.OnuId,
1372 "IntfId": trafficSchedulers.IntfId,
1373 "OnuPortNo": trafficSchedulers.PortNo,
1374 }).Info("received CreateTrafficSchedulers")
1375
1376 if !s.enablePerf {
1377 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1378 if err != nil {
1379 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1380 return new(openolt.Empty), err
1381 }
1382 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1383 if err != nil {
1384 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1385 return new(openolt.Empty), err
1386 }
1387 onu.TrafficSchedulers = trafficSchedulers
1388 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001389 return new(openolt.Empty), nil
1390}
1391
Anand S Katti09541352020-01-29 15:54:01 +05301392func (s OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
1393 oltLogger.WithFields(log.Fields{
1394 "OnuId": trafficSchedulers.OnuId,
1395 "IntfId": trafficSchedulers.IntfId,
1396 "OnuPortNo": trafficSchedulers.PortNo,
1397 }).Info("received RemoveTrafficSchedulers")
1398 if !s.enablePerf {
1399 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1400 if err != nil {
1401 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1402 return new(openolt.Empty), err
1403 }
1404 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1405 if err != nil {
1406 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1407 return new(openolt.Empty), err
1408 }
1409
1410 onu.TrafficSchedulers = nil
1411 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001412 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001413}
Scott Baker41724b82020-01-21 19:54:53 -08001414
1415// assumes caller has properly formulated an openolt.AlarmIndication
1416func (o OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
1417 msg := Message{
1418 Type: AlarmIndication,
1419 Data: ind,
1420 }
1421
1422 o.channel <- msg
1423 return nil
1424}
rajeshf921f882020-03-06 18:24:28 +05301425
1426func getOltIP() net.IP {
1427 conn, err := net.Dial("udp", "8.8.8.8:80")
1428 if err != nil {
1429 oltLogger.Error(err.Error())
1430 return net.IP{}
1431 }
1432 defer func() {
1433 err := conn.Close()
1434 if err != nil {
1435 oltLogger.Error(err.Error())
1436 }
1437 }()
1438
1439 localAddr := conn.LocalAddr().(*net.UDPAddr)
1440
1441 return localAddr.IP
1442}