blob: c0e7d3bd1a543f70ef41bc3a5c7d4c2a009ae605 [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"
Matteo Scandolo4a036262020-08-17 15:56:13 -070021 "encoding/hex"
Matteo Scandolo4747d292019-08-05 11:50:18 -070022 "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
Matteo Scandolo4a036262020-08-17 15:56:13 -070077 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
Matteo Scandolo4a036262020-08-17 15:56:13 -070088func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, 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"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700129 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800130 {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
Shrey Baid688b4242020-07-10 20:40:10 +0530140 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700141 // 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 Scandolo4a036262020-08-17 15:56:13 -0700150 // Create device and Services
151
152 nextCtag := map[string]int{}
153 nextStag := map[string]int{}
154
Matteo Scandolo4747d292019-08-05 11:50:18 -0700155 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700156 for i := 0; i < olt.NumPon; i++ {
157 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700158
Matteo Scandolo4a036262020-08-17 15:56:13 -0700159 // create ONU devices
160 for j := 0; j < olt.NumOnuPerPon; j++ {
161 delay := time.Duration(olt.Delay*j) * time.Millisecond
162 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700163
Matteo Scandolo4a036262020-08-17 15:56:13 -0700164 for k, s := range common.Services {
165
166 // find the correct cTag for this service
167 if _, ok := nextCtag[s.Name]; !ok {
168 // it's the first time we iterate over this service,
169 // so we start from the config value
170 nextCtag[s.Name] = s.CTag
171 } else {
172 // we have a previous value, so we check it
173 // if Allocation is unique, we increment,
174 // otherwise (shared) we do nothing
175 if s.CTagAllocation == common.TagAllocationUnique.String() {
176 nextCtag[s.Name] = nextCtag[s.Name] + 1
177 }
178 }
179
180 // find the correct sTag for this service
181 if _, ok := nextStag[s.Name]; !ok {
182 nextStag[s.Name] = s.STag
183 } else {
184 if s.STagAllocation == common.TagAllocationUnique.String() {
185 nextStag[s.Name] = nextStag[s.Name] + 1
186 }
187 }
188
189 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
190 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
191 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
192 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
193
194 if err != nil {
195 oltLogger.WithFields(log.Fields{
196 "Err": err.Error(),
197 }).Fatal("Can't create Service")
198 }
199
200 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700201 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700202 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700203 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700204 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700205 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100206
Shrey Baid688b4242020-07-10 20:40:10 +0530207 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700208 if err := olt.InternalState.Event("initialize"); err != nil {
209 log.Errorf("Error initializing OLT: %v", err)
210 return nil
211 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100212 }
213
Pragya Arya324337e2020-02-20 14:35:08 +0530214 if olt.PublishEvents {
215 log.Debugf("BBSim event publishing is enabled")
216 // Create a channel to write event messages
217 olt.EventChannel = make(chan common.Event, 100)
218 }
219
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700220 return &olt
221}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700222
Shrey Baid688b4242020-07-10 20:40:10 +0530223func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100224
225 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800226 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100227 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800228 // FIXME there should never be a server running if we are initializing the OLT
229 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100230 }
231
232 // create new channel for processOltMessages Go routine
233 o.channel = make(chan Message)
234
235 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
236 // FIXME we are assuming we have only one NNI
237 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800238 // NOTE we want to make sure the state is down when we initialize the OLT,
239 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
240 // in-band management
241 o.Nnis[0].OperState.SetState("down")
242 ch, handle, err := o.Nnis[0].NewVethChan()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243 if err == nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800244 oltLogger.WithFields(log.Fields{
245 "Type": o.Nnis[0].Type,
246 "IntfId": o.Nnis[0].ID,
247 "OperState": o.Nnis[0].OperState.Current(),
248 }).Info("NNI Channel created")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100249 o.nniPktInChannel = ch
Matteo Scandolo401503a2019-12-11 14:48:14 -0800250 o.nniHandle = handle
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100251 } else {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800252 oltLogger.Errorf("Error getting NNI channel: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100253 }
254 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700255}
256
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800257func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100258
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700259 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700260 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800261
262 oltLogger.WithFields(log.Fields{
263 "oltId": o.ID,
264 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
265
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700266 if o.InternalState.Is("enabled") {
267 oltLogger.WithFields(log.Fields{
268 "oltId": o.ID,
269 }).Info("This is an OLT soft reboot")
270 softReboot = true
271 }
272
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800273 // transition internal state to deleted
274 if err := o.InternalState.Event("delete"); err != nil {
275 oltLogger.WithFields(log.Fields{
276 "oltId": o.ID,
277 }).Errorf("Error deleting OLT: %v", err)
278 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100279 }
280
281 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800282 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
283 if err := o.StopOltServer(); err != nil {
Pragya Arya2225f202020-01-29 18:05:01 +0530284 oltLogger.Errorf("Error in stopping OLT server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100285 return err
286 }
287
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700288 if softReboot {
289 for _, pon := range o.Pons {
290 if pon.InternalState.Current() == "enabled" {
291 // disable PONs
292 msg := Message{
293 Type: PonIndication,
294 Data: PonIndicationMessage{
295 OperState: DOWN,
296 PonPortID: pon.ID,
297 },
298 }
299 o.channel <- msg
300 }
301
302 for _, onu := range pon.Onus {
303 _ = onu.InternalState.Event("disable")
304 }
305 }
306 } else {
307 // PONs are already handled in the Disable call
308 for _, pon := range olt.Pons {
309 // ONUs are not automatically disabled when a PON goes down
310 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
311 for _, onu := range pon.Onus {
312 _ = onu.InternalState.Event("disable")
313 }
Pragya Arya2225f202020-01-29 18:05:01 +0530314 }
315 }
316
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100317 // terminate the OLT's processOltMessages go routine
318 close(o.channel)
319 // terminate the OLT's processNniPacketIns go routine
Andy Bavier421f4d52020-01-21 15:39:22 -0700320 go o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100321 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100322
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100323 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100324
325 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800326 oltLogger.WithFields(log.Fields{
327 "oltId": o.ID,
328 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100329 return err
330 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800331 oltLogger.WithFields(log.Fields{
332 "oltId": o.ID,
333 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100334 return nil
335}
336
337// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800338func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700339 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700340 lis, err := net.Listen("tcp", address)
341 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700342 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700343 }
344 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100345
Matteo Scandolo4747d292019-08-05 11:50:18 -0700346 openolt.RegisterOpenoltServer(grpcServer, o)
347
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100348 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700349
Shrey Baid688b4242020-07-10 20:40:10 +0530350 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100351 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700352
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100353 return grpcServer, nil
354}
355
356// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800357func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100358 // TODO handle poweroff vs graceful shutdown
359 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800360 oltLogger.WithFields(log.Fields{
361 "oltId": o.SerialNumber,
362 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100363 oltServer.Stop()
364 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700365 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800366
Matteo Scandolo4747d292019-08-05 11:50:18 -0700367 return nil
368}
369
370// Device Methods
371
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100372// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530373func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700374 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530375 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700376
David Bainbridge103cf022019-12-16 20:11:35 +0000377 // If enabled has already been called then an enabled context has
378 // been created. If this is the case then we want to cancel all the
379 // proessing loops associated with that enable before we recreate
380 // new ones
381 o.Lock()
382 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700383 oltLogger.Info("This is an OLT reboot")
David Bainbridge103cf022019-12-16 20:11:35 +0000384 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530385 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000386 }
387 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
388 o.Unlock()
389
Matteo Scandolo4747d292019-08-05 11:50:18 -0700390 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800391 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700392
Matteo Scandolo4a036262020-08-17 15:56:13 -0700393 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530394
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100395 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000396 go o.processOltMessages(o.enableContext, stream, &wg)
397 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700398
399 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100400 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700401 Type: OltIndication,
402 Data: OltIndicationMessage{
403 OperState: UP,
404 },
405 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100406 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700407
408 // send NNI Port Indications
409 for _, nni := range o.Nnis {
410 msg := Message{
411 Type: NniIndication,
412 Data: NniIndicationMessage{
413 OperState: UP,
414 NniPortID: nni.ID,
415 },
416 }
417 o.channel <- msg
418 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100419
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800420 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100421
Shrey Baid688b4242020-07-10 20:40:10 +0530422 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530423 for _, pon := range o.Pons {
424 if pon.InternalState.Current() == "disabled" {
425 msg := Message{
426 Type: PonIndication,
427 Data: PonIndicationMessage{
428 OperState: UP,
429 PonPortID: pon.ID,
430 },
431 }
432 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000433 }
Pragya Arya2225f202020-01-29 18:05:01 +0530434 }
435 } else {
436
437 // 1. controlledActivation == Default: Send both PON and ONUs indications
438 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
439
440 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
441 // send PON Port indications
442 for _, pon := range o.Pons {
443 msg := Message{
444 Type: PonIndication,
445 Data: PonIndicationMessage{
446 OperState: UP,
447 PonPortID: pon.ID,
448 },
449 }
450 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700451 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700452 }
453 }
454
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800455 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530456
457 if !o.enablePerf {
458 // Start a go routine to send periodic port stats to openolt adapter
459 go o.periodicPortStats(o.enableContext)
460 }
461
Matteo Scandolo4747d292019-08-05 11:50:18 -0700462 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700463}
464
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800465func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400466 ch := omcisim.GetChannel()
467
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100468 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400469
David Bainbridge103cf022019-12-16 20:11:35 +0000470loop:
471 for {
472 select {
473 case <-ctx.Done():
474 oltLogger.Debug("OMCI processing canceled via context")
475 break loop
476 case message, ok := <-ch:
477 if !ok || ctx.Err() != nil {
478 oltLogger.Debug("OMCI processing canceled via channel close")
479 break loop
480 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800481
482 oltLogger.WithFields(log.Fields{
483 "messageType": message.Type,
484 "OnuId": message.Data.OnuId,
485 "IntfId": message.Data.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700486 }).Debug("Received message on OMCI Sim channel")
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800487
David Bainbridge103cf022019-12-16 20:11:35 +0000488 onuId := message.Data.OnuId
489 intfId := message.Data.IntfId
490 onu, err := o.FindOnuById(intfId, onuId)
491 if err != nil {
492 oltLogger.Errorf("Failed to find onu: %v", err)
493 continue
494 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800495 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400496 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400497 }
David Bainbridge103cf022019-12-16 20:11:35 +0000498
499 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400500}
501
Pragya Arya996a0892020-03-09 21:47:52 +0530502func (o *OltDevice) periodicPortStats(ctx context.Context) {
503 var portStats *openolt.PortStatistics
504 for {
505 select {
506 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
507 // send NNI port stats
508 for _, port := range o.Nnis {
509 incrementStat := true
510 if port.OperState.Current() == "down" {
511 incrementStat = false
512 }
513 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
514 o.sendPortStatsIndication(portStats, port.ID, port.Type)
515 }
516
517 // send PON port stats
518 for _, port := range o.Pons {
519 incrementStat := true
520 // do not increment port stats if PON port is down or no ONU is activated on PON port
521 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
522 incrementStat = false
523 }
524 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
525 o.sendPortStatsIndication(portStats, port.ID, port.Type)
526 }
527 case <-ctx.Done():
528 log.Debug("Stop sending port stats")
529 return
530 }
531
532 }
533}
534
Matteo Scandolo4747d292019-08-05 11:50:18 -0700535// Helpers method
536
Shrey Baid688b4242020-07-10 20:40:10 +0530537func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700538 for _, pon := range o.Pons {
539 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700540 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700541 }
542 }
Shrey Baid688b4242020-07-10 20:40:10 +0530543 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700544}
545
Shrey Baid688b4242020-07-10 20:40:10 +0530546func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700547 for _, nni := range o.Nnis {
548 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700549 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700550 }
551 }
Shrey Baid688b4242020-07-10 20:40:10 +0530552 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700553}
554
Scott Baker41724b82020-01-21 19:54:53 -0800555func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
556 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
557 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
558 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
559 return
560 }
561
562 oltLogger.WithFields(log.Fields{
563 "AlarmIndication": alarmInd,
564 }).Debug("Sent Indication_AlarmInd")
565}
566
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100567func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700568 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
569 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700570 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800571 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700572 }
573
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700574 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700575 "OperState": msg.OperState,
576 }).Debug("Sent Indication_OltInd")
577}
578
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100579func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700580 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800581 if msg.OperState == UP {
582 if err := nni.OperState.Event("enable"); err != nil {
583 log.WithFields(log.Fields{
584 "Type": nni.Type,
585 "IntfId": nni.ID,
586 "OperState": nni.OperState.Current(),
587 }).Errorf("Can't move NNI Port to enabled state: %v", err)
588 }
589 } else if msg.OperState == DOWN {
590 if err := nni.OperState.Event("disable"); err != nil {
591 log.WithFields(log.Fields{
592 "Type": nni.Type,
593 "IntfId": nni.ID,
594 "OperState": nni.OperState.Current(),
595 }).Errorf("Can't move NNI Port to disable state: %v", err)
596 }
597 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700598 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700599 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700600 Type: nni.Type,
601 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700602 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700603 }}
604
605 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700606 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800607 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700608 }
609
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700610 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700611 "Type": nni.Type,
612 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700613 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700614 }).Debug("Sent Indication_IntfOperInd for NNI")
615}
616
Pragya Arya2225f202020-01-29 18:05:01 +0530617func (o *OltDevice) sendPonIndication(ponPortID uint32) {
618
Matteo Scandolo4a036262020-08-17 15:56:13 -0700619 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530620 pon, _ := o.GetPonById(ponPortID)
621 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700622 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700623 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700624 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700625 }}
626
627 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700628 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800629 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700630 }
631
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700632 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700633 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700634 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700635 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700636
Pragya Arya2225f202020-01-29 18:05:01 +0530637 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700638 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700639 Type: pon.Type,
640 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700641 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700642 }}
643
644 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700645 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800646 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700647 }
648
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700649 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700650 "Type": pon.Type,
651 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700652 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700653 }).Debug("Sent Indication_IntfOperInd for PON")
654}
655
Pragya Arya996a0892020-03-09 21:47:52 +0530656func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530657 if o.InternalState.Current() == "enabled" {
658 oltLogger.WithFields(log.Fields{
659 "Type": portType,
660 "IntfId": portID,
661 }).Trace("Sending port stats")
662 stats.IntfId = InterfaceIDToPortNo(portID, portType)
663 data := &openolt.Indication_PortStats{
664 PortStats: stats,
665 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700666 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530667 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
668 oltLogger.Errorf("Failed to send PortStats: %v", err)
669 return
670 }
Pragya Arya996a0892020-03-09 21:47:52 +0530671 }
672}
673
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100674// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000675func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100676 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000677 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700678
David Bainbridge103cf022019-12-16 20:11:35 +0000679loop:
680 for {
681 select {
682 case <-ctx.Done():
683 oltLogger.Debug("OLT Indication processing canceled via context")
684 break loop
685 case message, ok := <-ch:
686 if !ok || ctx.Err() != nil {
687 oltLogger.Debug("OLT Indication processing canceled via closed channel")
688 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700689 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700690
David Bainbridge103cf022019-12-16 20:11:35 +0000691 oltLogger.WithFields(log.Fields{
692 "oltId": o.ID,
693 "messageType": message.Type,
694 }).Trace("Received message")
695
696 switch message.Type {
697 case OltIndication:
698 msg, _ := message.Data.(OltIndicationMessage)
699 if msg.OperState == UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530700 _ = o.InternalState.Event("enable")
701 _ = o.OperState.Event("enable")
David Bainbridge103cf022019-12-16 20:11:35 +0000702 } else if msg.OperState == DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530703 _ = o.InternalState.Event("disable")
704 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000705 }
706 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800707 case AlarmIndication:
708 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
709 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000710 case NniIndication:
711 msg, _ := message.Data.(NniIndicationMessage)
712 o.sendNniIndication(msg, stream)
713 case PonIndication:
714 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530715 pon, _ := o.GetPonById(msg.PonPortID)
716 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530717 if err := pon.OperState.Event("enable"); err != nil {
718 oltLogger.WithFields(log.Fields{
719 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800720 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530721 }).Error("Can't Enable Oper state for PON Port")
722 }
723 if err := pon.InternalState.Event("enable"); err != nil {
724 oltLogger.WithFields(log.Fields{
725 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800726 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530727 }).Error("Can't Enable Internal state for PON Port")
728 }
Pragya Arya2225f202020-01-29 18:05:01 +0530729 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530730 if err := pon.OperState.Event("disable"); err != nil {
731 oltLogger.WithFields(log.Fields{
732 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800733 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530734 }).Error("Can't Disable Oper state for PON Port")
735 }
736 if err := pon.InternalState.Event("disable"); err != nil {
737 oltLogger.WithFields(log.Fields{
738 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800739 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530740 }).Error("Can't Disable Internal state for PON Port")
741 }
Pragya Arya2225f202020-01-29 18:05:01 +0530742 }
David Bainbridge103cf022019-12-16 20:11:35 +0000743 default:
744 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
745 }
746 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700747 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100748 wg.Done()
749 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700750}
751
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100752// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000753func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700754 oltLogger.WithFields(log.Fields{
755 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800756 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700757 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700758
David Bainbridge103cf022019-12-16 20:11:35 +0000759 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700760
David Bainbridge103cf022019-12-16 20:11:35 +0000761loop:
762 for {
763 select {
764 case <-ctx.Done():
765 oltLogger.Debug("NNI Indication processing canceled via context")
766 break loop
767 case message, ok := <-ch:
768 if !ok || ctx.Err() != nil {
769 oltLogger.Debug("NNI Indication processing canceled via channel closed")
770 break loop
771 }
772 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700773
David Bainbridge103cf022019-12-16 20:11:35 +0000774 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700775
David Bainbridge103cf022019-12-16 20:11:35 +0000776 if err != nil {
777 log.WithFields(log.Fields{
778 "IntfType": "nni",
779 "IntfId": nniId,
780 "Pkt": message.Pkt.Data(),
781 }).Error("Can't find Dst MacAddress in packet")
782 return
783 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700784
Matteo Scandolo4a036262020-08-17 15:56:13 -0700785 s, err := o.FindServiceByMacAddress(onuMac)
David Bainbridge103cf022019-12-16 20:11:35 +0000786 if err != nil {
787 log.WithFields(log.Fields{
788 "IntfType": "nni",
789 "IntfId": nniId,
790 "Pkt": message.Pkt.Data(),
791 "MacAddress": onuMac.String(),
792 }).Error("Can't find ONU with MacAddress")
793 return
794 }
795
Matteo Scandolo4a036262020-08-17 15:56:13 -0700796 service := s.(*Service)
797
Matteo Scandolo8d281372020-09-03 16:23:37 -0700798 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(service.STag, service.CTag, message.Pkt, service.UsPonCTagPriority)
David Bainbridge103cf022019-12-16 20:11:35 +0000799 if err != nil {
800 log.Error("Fail to add double tag to packet")
801 }
802
803 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
804 IntfType: "nni",
805 IntfId: nniId,
806 Pkt: doubleTaggedPkt.Data()}}
807 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
808 oltLogger.WithFields(log.Fields{
809 "IntfType": data.PktInd.IntfType,
810 "IntfId": nniId,
811 "Pkt": doubleTaggedPkt.Data(),
812 }).Errorf("Fail to send PktInd indication: %v", err)
813 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700814 oltLogger.WithFields(log.Fields{
815 "IntfType": data.PktInd.IntfType,
816 "IntfId": nniId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700817 "Pkt": hex.EncodeToString(doubleTaggedPkt.Data()),
818 "OnuSn": service.Onu.Sn(),
819 }).Trace("Sent PktInd indication (from NNI to VOLTHA)")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700820 }
821 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100822 wg.Done()
823 oltLogger.WithFields(log.Fields{
824 "nniChannel": o.nniPktInChannel,
825 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700826}
827
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700828// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530829func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200830 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700831 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700832 for _, pon := range o.Pons {
833 for _, onu := range pon.Onus {
834 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700835 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700836 }
837 }
838 }
839
Shrey Baid688b4242020-07-10 20:40:10 +0530840 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700841}
842
William Kurkian9dadc5b2019-10-22 13:51:57 -0400843// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530844func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200845 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400846 // memoizing it will remove the bottleneck
847 for _, pon := range o.Pons {
848 if pon.ID == intfId {
849 for _, onu := range pon.Onus {
850 if onu.ID == onuId {
851 return onu, nil
852 }
853 }
854 }
855 }
Shrey Baid688b4242020-07-10 20:40:10 +0530856 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400857}
858
Matteo Scandolo4a036262020-08-17 15:56:13 -0700859// returns a Service with a given Mac Address
860func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200861 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700862 // memoizing it will remove the bottleneck
863 for _, pon := range o.Pons {
864 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700865 s, err := onu.findServiceByMacAddress(mac)
866 if err == nil {
867 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700868 }
869 }
870 }
871
Matteo Scandolo4a036262020-08-17 15:56:13 -0700872 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700873}
874
Matteo Scandolo4747d292019-08-05 11:50:18 -0700875// GRPC Endpoints
876
Shrey Baid688b4242020-07-10 20:40:10 +0530877func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700878 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700879 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700880 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530881 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700882
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700883 pon, _ := o.GetPonById(onu.IntfId)
884 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500885 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700886
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700887 if err := _onu.OperState.Event("enable"); err != nil {
888 oltLogger.WithFields(log.Fields{
889 "IntfId": _onu.PonPortID,
890 "OnuSn": _onu.Sn(),
891 "OnuId": _onu.ID,
892 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700893 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700894 if err := _onu.InternalState.Event("enable"); err != nil {
895 oltLogger.WithFields(log.Fields{
896 "IntfId": _onu.PonPortID,
897 "OnuSn": _onu.Sn(),
898 "OnuId": _onu.ID,
899 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
900 }
901
902 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
903
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700904 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700905}
906
Shrey Baid688b4242020-07-10 20:40:10 +0530907func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700908 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700909 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700910}
911
Shrey Baid688b4242020-07-10 20:40:10 +0530912func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530913 oltLogger.WithFields(log.Fields{
914 "IntfId": onu.IntfId,
915 "OnuId": onu.OnuId,
916 }).Info("Received DeleteOnu call from VOLTHA")
917
918 pon, err := o.GetPonById(onu.IntfId)
919 if err != nil {
920 oltLogger.WithFields(log.Fields{
921 "OnuId": onu.OnuId,
922 "IntfId": onu.IntfId,
923 "err": err,
924 }).Error("Can't find PonPort")
925 }
926 _onu, err := pon.GetOnuById(onu.OnuId)
927 if err != nil {
928 oltLogger.WithFields(log.Fields{
929 "OnuId": onu.OnuId,
930 "IntfId": onu.IntfId,
931 "err": err,
932 }).Error("Can't find Onu")
933 }
934
Hardik Windlassad790cb2020-06-17 21:26:22 +0530935 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530936 oltLogger.WithFields(log.Fields{
937 "IntfId": _onu.PonPortID,
938 "OnuSn": _onu.Sn(),
939 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530940 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
941 }
942
Hardik Windlassad790cb2020-06-17 21:26:22 +0530943 // ONU Re-Discovery
944 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530945 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530946 }
947
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700948 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700949}
950
Shrey Baid688b4242020-07-10 20:40:10 +0530951func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700952 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800953 oltLogger.WithFields(log.Fields{
954 "oltId": o.ID,
955 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530956 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800957
Matteo Scandolo401503a2019-12-11 14:48:14 -0800958 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530959 if pon.InternalState.Current() == "enabled" {
960 // disable PONs
961 msg := Message{
962 Type: PonIndication,
963 Data: PonIndicationMessage{
964 OperState: DOWN,
965 PonPortID: pon.ID,
966 },
967 }
968 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800969 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800970 }
971
Matteo Scandolo401503a2019-12-11 14:48:14 -0800972 // Note that we are not disabling the NNI as the real OLT does not.
973 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800974
975 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100976 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700977 Type: OltIndication,
978 Data: OltIndicationMessage{
979 OperState: DOWN,
980 },
981 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100982 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700983 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700984}
985
Shrey Baid688b4242020-07-10 20:40:10 +0530986func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530987 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200988 ponID := intf.GetIntfId()
989 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200990
991 msg := Message{
992 Type: PonIndication,
993 Data: PonIndicationMessage{
994 OperState: DOWN,
995 PonPortID: ponID,
996 },
997 }
998 o.channel <- msg
999
1000 for _, onu := range pon.Onus {
1001
1002 onuIndication := OnuIndicationMessage{
1003 OperState: DOWN,
1004 PonPortID: ponID,
1005 OnuID: onu.ID,
1006 OnuSN: onu.SerialNumber,
1007 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001008 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001009
1010 }
1011
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001012 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001013}
1014
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001015func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001016 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301017 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001018 o.Enable(stream)
1019 return nil
1020}
1021
Shrey Baid688b4242020-07-10 20:40:10 +05301022func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301023 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301024 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001025 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001026
Pragya Arya2225f202020-01-29 18:05:01 +05301027 msg := Message{
1028 Type: PonIndication,
1029 Data: PonIndicationMessage{
1030 OperState: UP,
1031 PonPortID: ponID,
1032 },
1033 }
1034 o.channel <- msg
1035
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001036 for _, onu := range pon.Onus {
1037
1038 onuIndication := OnuIndicationMessage{
1039 OperState: UP,
1040 PonPortID: ponID,
1041 OnuID: onu.ID,
1042 OnuSN: onu.SerialNumber,
1043 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001044 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001045
1046 }
1047
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001048 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001049}
1050
Shrey Baid688b4242020-07-10 20:40:10 +05301051func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001052 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001053 "IntfId": flow.AccessIntfId,
1054 "OnuId": flow.OnuId,
1055 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001056 "InnerVlan": flow.Classifier.IVid,
1057 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001058 "FlowType": flow.FlowType,
1059 "FlowId": flow.FlowId,
1060 "UniID": flow.UniId,
1061 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301062 }).Tracef("OLT receives FlowAdd")
1063
1064 flowKey := FlowKey{}
1065 if !o.enablePerf {
1066 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
1067 olt.Flows[flowKey] = *flow
1068 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001069
1070 if flow.AccessIntfId == -1 {
1071 oltLogger.WithFields(log.Fields{
1072 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001073 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001074 } else if flow.FlowType == "multicast" {
1075 oltLogger.WithFields(log.Fields{
1076 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001077 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001078 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001079 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001080 if err != nil {
1081 oltLogger.WithFields(log.Fields{
1082 "OnuId": flow.OnuId,
1083 "IntfId": flow.AccessIntfId,
1084 "err": err,
1085 }).Error("Can't find PonPort")
1086 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001087 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001088 if err != nil {
1089 oltLogger.WithFields(log.Fields{
1090 "OnuId": flow.OnuId,
1091 "IntfId": flow.AccessIntfId,
1092 "err": err,
1093 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001094 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001095 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301096 if !o.enablePerf {
1097 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301098 // Generate event on first flow for ONU
1099 if len(onu.Flows) == 1 {
1100 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1101 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301102 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001103
1104 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001105 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001106 Data: OnuFlowUpdateMessage{
1107 PonPortID: pon.ID,
1108 OnuID: onu.ID,
1109 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001110 },
1111 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001112 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001113 }
1114
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001115 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001116}
1117
Pragya Arya8bdb4532020-03-02 17:08:09 +05301118// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301119func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001120
Pragya Arya8bdb4532020-03-02 17:08:09 +05301121 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301122 "FlowId": flow.FlowId,
1123 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001124 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301125
1126 if !o.enablePerf { // remove only if flow were stored
1127 flowKey := FlowKey{
1128 ID: flow.FlowId,
1129 Direction: flow.FlowType,
1130 }
1131
1132 // Check if flow exists
1133 storedFlow, ok := o.Flows[flowKey]
1134 if !ok {
1135 oltLogger.Errorf("Flow %v not found", flow)
1136 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1137 }
1138
1139 // if its ONU flow remove it from ONU also
1140 if storedFlow.AccessIntfId != -1 {
1141 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1142 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1143 if err != nil {
1144 oltLogger.WithFields(log.Fields{
1145 "OnuId": storedFlow.OnuId,
1146 "IntfId": storedFlow.AccessIntfId,
1147 "err": err,
1148 }).Error("ONU not found")
1149 return new(openolt.Empty), nil
1150 }
1151 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301152 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301153 }
1154
1155 // delete from olt flows
1156 delete(o.Flows, flowKey)
1157 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001158
1159 if flow.AccessIntfId == -1 {
1160 oltLogger.WithFields(log.Fields{
1161 "FlowId": flow.FlowId,
1162 }).Debug("Removing OLT flow")
1163 } else if flow.FlowType == "multicast" {
1164 oltLogger.WithFields(log.Fields{
1165 "FlowId": flow.FlowId,
1166 }).Debug("Removing OLT multicast flow")
1167 } else {
1168
1169 onu, err := o.GetOnuByFlowId(flow.FlowId)
1170 if err != nil {
1171 oltLogger.WithFields(log.Fields{
1172 "OnuId": flow.OnuId,
1173 "IntfId": flow.AccessIntfId,
1174 "err": err,
1175 }).Error("Can't find Onu")
1176 return nil, err
1177 }
1178
1179 msg := Message{
1180 Type: FlowRemoved,
1181 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301182 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001183 },
1184 }
1185 onu.Channel <- msg
1186 }
1187
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001188 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001189}
1190
Shrey Baid688b4242020-07-10 20:40:10 +05301191func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001192 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1193 oltLogger.WithFields(log.Fields{
1194 "signature": res.HeartbeatSignature,
1195 }).Trace("HeartbeatCheck")
1196 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001197}
1198
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001199func (o *OltDevice) GetOnuByFlowId(flowId uint32) (*Onu, error) {
1200 for _, pon := range o.Pons {
1201 for _, onu := range pon.Onus {
1202 for _, fId := range onu.FlowIds {
1203 if fId == flowId {
1204 return onu, nil
1205 }
1206 }
1207 }
1208 }
Shrey Baid688b4242020-07-10 20:40:10 +05301209 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001210}
1211
Shrey Baid688b4242020-07-10 20:40:10 +05301212func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001213
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001214 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001215 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001216 "PonPorts": o.NumPon,
1217 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001218 devinfo := new(openolt.DeviceInfo)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001219 devinfo.Vendor = common.Config.Olt.Vendor
1220 devinfo.Model = common.Config.Olt.Model
1221 devinfo.HardwareVersion = common.Config.Olt.HardwareVersion
1222 devinfo.FirmwareVersion = common.Config.Olt.FirmwareVersion
1223 devinfo.Technology = common.Config.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001224 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001225 devinfo.OnuIdStart = 1
1226 devinfo.OnuIdEnd = 255
1227 devinfo.AllocIdStart = 1024
1228 devinfo.AllocIdEnd = 16383
1229 devinfo.GemportIdStart = 1024
1230 devinfo.GemportIdEnd = 65535
1231 devinfo.FlowIdStart = 1
1232 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001233 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4a036262020-08-17 15:56:13 -07001234 devinfo.DeviceId = common.Config.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001235
1236 return devinfo, nil
1237}
1238
Shrey Baid688b4242020-07-10 20:40:10 +05301239func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001240 pon, err := o.GetPonById(omci_msg.IntfId)
1241 if err != nil {
1242 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001243 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001244 "onu_id": omci_msg.OnuId,
1245 "pon_id": omci_msg.IntfId,
1246 }).Error("pon ID not found")
1247 return nil, err
1248 }
1249
1250 onu, err := pon.GetOnuById(omci_msg.OnuId)
1251 if err != nil {
1252 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001253 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001254 "onu_id": omci_msg.OnuId,
1255 "pon_id": omci_msg.IntfId,
1256 }).Error("onu ID not found")
1257 return nil, err
1258 }
1259
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001260 oltLogger.WithFields(log.Fields{
1261 "IntfId": onu.PonPortID,
1262 "OnuId": onu.ID,
1263 "OnuSn": onu.Sn(),
1264 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001265 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001266 Type: OMCI,
1267 Data: OmciMessage{
1268 OnuSN: onu.SerialNumber,
1269 OnuID: onu.ID,
1270 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001271 },
1272 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001273 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001274 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001275}
1276
Shrey Baid688b4242020-07-10 20:40:10 +05301277func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001278 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001279 if err != nil {
1280 oltLogger.WithFields(log.Fields{
1281 "OnuId": onuPkt.OnuId,
1282 "IntfId": onuPkt.IntfId,
1283 "err": err,
1284 }).Error("Can't find PonPort")
1285 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001286 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001287 if err != nil {
1288 oltLogger.WithFields(log.Fields{
1289 "OnuId": onuPkt.OnuId,
1290 "IntfId": onuPkt.IntfId,
1291 "err": err,
1292 }).Error("Can't find Onu")
1293 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001294
Matteo Scandolo075b1892019-10-07 12:11:07 -07001295 oltLogger.WithFields(log.Fields{
1296 "IntfId": onu.PonPortID,
1297 "OnuId": onu.ID,
1298 "OnuSn": onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001299 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001300
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001301 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Shrey Baid688b4242020-07-10 20:40:10 +05301302 pktType, _ := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001303
Matteo Scandolo4a036262020-08-17 15:56:13 -07001304 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
1305
1306 if err != nil {
1307 log.WithFields(log.Fields{
1308 "IntfId": onu.PonPortID,
1309 "OnuId": onu.ID,
1310 "OnuSn": onu.Sn(),
1311 "Pkt": rawpkt.Data(),
1312 }).Error("Can't find Dst MacAddress in packet, droppint it")
1313 return new(openolt.Empty), nil
1314 }
1315
Matteo Scandolo075b1892019-10-07 12:11:07 -07001316 msg := Message{
1317 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001318 Data: OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001319 IntfId: onuPkt.IntfId,
1320 OnuId: onuPkt.OnuId,
1321 Packet: rawpkt,
1322 Type: pktType,
1323 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001324 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001325 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001326
Matteo Scandolo075b1892019-10-07 12:11:07 -07001327 onu.Channel <- msg
1328
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001329 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001330}
1331
Shrey Baid688b4242020-07-10 20:40:10 +05301332func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001333
1334 // OLT Reboot is called in two cases:
1335 // - when an OLT is being removed (voltctl device disable -> voltctl device delete are called, then a new voltctl device create -> voltctl device enable will be issued)
1336 // - when an OLT needs to be rebooted (voltcl device reboot)
1337
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001338 oltLogger.WithFields(log.Fields{
1339 "oltId": o.ID,
1340 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301341 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301342 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001343 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001344}
1345
Shrey Baid688b4242020-07-10 20:40:10 +05301346func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301347 oltLogger.WithFields(log.Fields{
1348 "oltId": o.ID,
1349 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301350 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301351
Pragya Arya2225f202020-01-29 18:05:01 +05301352 // enable OLT
1353 oltMsg := Message{
1354 Type: OltIndication,
1355 Data: OltIndicationMessage{
1356 OperState: UP,
1357 },
Pragya Arya1881df02020-01-29 18:05:01 +05301358 }
Pragya Arya2225f202020-01-29 18:05:01 +05301359 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301360
Pragya Arya2225f202020-01-29 18:05:01 +05301361 for _, pon := range o.Pons {
1362 if pon.InternalState.Current() == "disabled" {
1363 msg := Message{
1364 Type: PonIndication,
1365 Data: PonIndicationMessage{
1366 OperState: UP,
1367 PonPortID: pon.ID,
1368 },
1369 }
1370 o.channel <- msg
1371 }
1372 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001373
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001374 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001375}
1376
Shrey Baid688b4242020-07-10 20:40:10 +05301377func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001378 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1379
Shrey Baid688b4242020-07-10 20:40:10 +05301380 _ = o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001381 // NOTE should we return an error if sendNniPakcet fails?
1382 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001383}
1384
Shrey Baid688b4242020-07-10 20:40:10 +05301385func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001386 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001387 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001388}
1389
Shrey Baid688b4242020-07-10 20:40:10 +05301390func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001391 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001392 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001393}
1394
Shrey Baid688b4242020-07-10 20:40:10 +05301395func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001396 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001397 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001398}
1399
Shrey Baid688b4242020-07-10 20:40:10 +05301400func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001401 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001402 return new(openolt.Empty), nil
1403}
1404
Shrey Baid688b4242020-07-10 20:40:10 +05301405func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001406 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001407 return new(openolt.Empty), nil
1408}
1409
Shrey Baid688b4242020-07-10 20:40:10 +05301410func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301411 oltLogger.WithFields(log.Fields{
1412 "OnuId": trafficSchedulers.OnuId,
1413 "IntfId": trafficSchedulers.IntfId,
1414 "OnuPortNo": trafficSchedulers.PortNo,
1415 }).Info("received CreateTrafficSchedulers")
1416
1417 if !s.enablePerf {
1418 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1419 if err != nil {
1420 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1421 return new(openolt.Empty), err
1422 }
1423 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1424 if err != nil {
1425 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1426 return new(openolt.Empty), err
1427 }
1428 onu.TrafficSchedulers = trafficSchedulers
1429 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001430 return new(openolt.Empty), nil
1431}
1432
Shrey Baid688b4242020-07-10 20:40:10 +05301433func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301434 oltLogger.WithFields(log.Fields{
1435 "OnuId": trafficSchedulers.OnuId,
1436 "IntfId": trafficSchedulers.IntfId,
1437 "OnuPortNo": trafficSchedulers.PortNo,
1438 }).Info("received RemoveTrafficSchedulers")
1439 if !s.enablePerf {
1440 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1441 if err != nil {
1442 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1443 return new(openolt.Empty), err
1444 }
1445 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1446 if err != nil {
1447 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1448 return new(openolt.Empty), err
1449 }
1450
1451 onu.TrafficSchedulers = nil
1452 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001453 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001454}
Scott Baker41724b82020-01-21 19:54:53 -08001455
1456// assumes caller has properly formulated an openolt.AlarmIndication
Shrey Baid688b4242020-07-10 20:40:10 +05301457func (o *OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
Scott Baker41724b82020-01-21 19:54:53 -08001458 msg := Message{
1459 Type: AlarmIndication,
1460 Data: ind,
1461 }
1462
1463 o.channel <- msg
1464 return nil
1465}