blob: b2c82d90dc61dd4a60e4635a2603a03439ca9fb9 [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"
Matteo Scandolo90d08f62020-10-29 12:06:55 -070023 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
Matteo Scandolof9d43412021-01-12 11:11:34 -080024 "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070025 "github.com/opencord/voltha-protos/v4/go/ext/config"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020026 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080027 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020028 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010029 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020030
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070031 "github.com/google/gopacket"
32 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070033 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070034 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010035 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070036 common_protos "github.com/opencord/voltha-protos/v4/go/common"
37 "github.com/opencord/voltha-protos/v4/go/openolt"
38 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070039 log "github.com/sirupsen/logrus"
40 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053041 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010042 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053043 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070044)
45
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070046var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070047 "module": "OLT",
48})
49
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070050type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000051 sync.Mutex
Matteo Scandolo88c204a2020-11-03 10:34:24 -080052 oltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000053
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070054 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053055 ID int
56 SerialNumber string
57 NumNni int
58 NumPon int
59 NumOnuPerPon int
60 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080061 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070062 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010063 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053064 Delay int
65 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053066 EventChannel chan common.Event
67 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053068 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080069 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070070
Matteo Scandolo27428702019-10-11 16:21:16 -070071 Pons []*PonPort
72 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070073
74 // OLT Attributes
75 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000076
77 enableContext context.Context
78 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053079
Matteo Scandolo4a036262020-08-17 15:56:13 -070080 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053081 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070082}
83
Matteo Scandolo27428702019-10-11 16:21:16 -070084var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -070085
Matteo Scandolo27428702019-10-11 16:21:16 -070086func GetOLT() *OltDevice {
87 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070088}
89
Matteo Scandolo4a036262020-08-17 15:56:13 -070090func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070091 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +053092 "ID": options.Olt.ID,
93 "NumNni": options.Olt.NniPorts,
94 "NumPon": options.Olt.PonPorts,
95 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -070096 }).Debug("CreateOLT")
97
Matteo Scandolo84f7d482019-08-08 19:00:47 -070098 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +053099 ID: options.Olt.ID,
100 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700101 OperState: getOperStateFSM(func(e *fsm.Event) {
102 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
103 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800104 NumNni: int(options.Olt.NniPorts),
105 NumPon: int(options.Olt.PonPorts),
106 NumOnuPerPon: int(options.Olt.OnusPonPort),
107 Pons: []*PonPort{},
108 Nnis: []*NniPort{},
109 Delay: options.BBSim.Delay,
110 enablePerf: options.BBSim.EnablePerf,
111 PublishEvents: options.BBSim.Events,
112 PortStatsInterval: options.Olt.PortStatsInterval,
113 dhcpServer: dhcp.NewDHCPServer(),
114 PreviouslyConnected: false,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700115 }
116
Pragya Arya996a0892020-03-09 21:47:52 +0530117 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530118 olt.ControlledActivation = val
119 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700120 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530121 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
122 olt.ControlledActivation = Default
123 }
124
Matteo Scandolo4747d292019-08-05 11:50:18 -0700125 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700126 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700127 olt.InternalState = fsm.NewFSM(
128 "created",
129 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800130 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100131 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700132 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700133 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800134 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135 },
136 fsm.Callbacks{
137 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700138 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700139 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100140 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700141 },
142 )
143
Shrey Baid688b4242020-07-10 20:40:10 +0530144 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700145 // create NNI Port
146 nniPort, err := CreateNNI(&olt)
147 if err != nil {
148 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
149 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700150
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700151 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700152 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700153
Matteo Scandolo4a036262020-08-17 15:56:13 -0700154 // Create device and Services
155
156 nextCtag := map[string]int{}
157 nextStag := map[string]int{}
158
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700160 for i := 0; i < olt.NumPon; i++ {
161 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700162
Matteo Scandolo4a036262020-08-17 15:56:13 -0700163 // create ONU devices
164 for j := 0; j < olt.NumOnuPerPon; j++ {
165 delay := time.Duration(olt.Delay*j) * time.Millisecond
166 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700167
Matteo Scandolo4a036262020-08-17 15:56:13 -0700168 for k, s := range common.Services {
169
170 // find the correct cTag for this service
171 if _, ok := nextCtag[s.Name]; !ok {
172 // it's the first time we iterate over this service,
173 // so we start from the config value
174 nextCtag[s.Name] = s.CTag
175 } else {
176 // we have a previous value, so we check it
177 // if Allocation is unique, we increment,
178 // otherwise (shared) we do nothing
179 if s.CTagAllocation == common.TagAllocationUnique.String() {
180 nextCtag[s.Name] = nextCtag[s.Name] + 1
181 }
182 }
183
184 // find the correct sTag for this service
185 if _, ok := nextStag[s.Name]; !ok {
186 nextStag[s.Name] = s.STag
187 } else {
188 if s.STagAllocation == common.TagAllocationUnique.String() {
189 nextStag[s.Name] = nextStag[s.Name] + 1
190 }
191 }
192
193 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
194 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
195 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
196 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
197
198 if err != nil {
199 oltLogger.WithFields(log.Fields{
200 "Err": err.Error(),
201 }).Fatal("Can't create Service")
202 }
203
204 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700205 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700206 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700207 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700208 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700209 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100210
Shrey Baid688b4242020-07-10 20:40:10 +0530211 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700212 if err := olt.InternalState.Event("initialize"); err != nil {
213 log.Errorf("Error initializing OLT: %v", err)
214 return nil
215 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100216 }
217
Pragya Arya324337e2020-02-20 14:35:08 +0530218 if olt.PublishEvents {
219 log.Debugf("BBSim event publishing is enabled")
220 // Create a channel to write event messages
221 olt.EventChannel = make(chan common.Event, 100)
222 }
223
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700224 return &olt
225}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700226
Shrey Baid688b4242020-07-10 20:40:10 +0530227func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100228
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800229 if o.oltServer == nil {
230 o.oltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800232 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100233 }
234
235 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800236 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100237
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100238 // FIXME we are assuming we have only one NNI
239 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800240 // NOTE we want to make sure the state is down when we initialize the OLT,
241 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
242 // in-band management
243 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100244 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700245}
246
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800247func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100248
Matteo Scandolo96f89192021-03-12 13:17:26 -0800249 o.PreviouslyConnected = false
250
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700251 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700252 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800253
254 oltLogger.WithFields(log.Fields{
255 "oltId": o.ID,
256 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
257
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700258 if o.InternalState.Is("enabled") {
259 oltLogger.WithFields(log.Fields{
260 "oltId": o.ID,
261 }).Info("This is an OLT soft reboot")
262 softReboot = true
263 }
264
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800265 // transition internal state to deleted
266 if err := o.InternalState.Event("delete"); err != nil {
267 oltLogger.WithFields(log.Fields{
268 "oltId": o.ID,
269 }).Errorf("Error deleting OLT: %v", err)
270 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100271 }
272
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800273 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
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800274 o.StopOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100275
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700276 if softReboot {
277 for _, pon := range o.Pons {
278 if pon.InternalState.Current() == "enabled" {
279 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800280 msg := types.Message{
281 Type: types.PonIndication,
282 Data: types.PonIndicationMessage{
283 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700284 PonPortID: pon.ID,
285 },
286 }
287 o.channel <- msg
288 }
289
290 for _, onu := range pon.Onus {
291 _ = onu.InternalState.Event("disable")
292 }
293 }
294 } else {
295 // PONs are already handled in the Disable call
296 for _, pon := range olt.Pons {
297 // ONUs are not automatically disabled when a PON goes down
298 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
299 for _, onu := range pon.Onus {
300 _ = onu.InternalState.Event("disable")
301 }
Pragya Arya2225f202020-01-29 18:05:01 +0530302 }
303 }
304
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100305 // terminate the OLT's processOltMessages go routine
306 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700307
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700308 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100309
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100310 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100311
312 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800313 oltLogger.WithFields(log.Fields{
314 "oltId": o.ID,
315 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100316 return err
317 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800318 oltLogger.WithFields(log.Fields{
319 "oltId": o.ID,
320 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100321 return nil
322}
323
324// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800325func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700326 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700327 lis, err := net.Listen("tcp", address)
328 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700329 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700330 }
331 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100332
Matteo Scandolo4747d292019-08-05 11:50:18 -0700333 openolt.RegisterOpenoltServer(grpcServer, o)
334
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100335 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700336
Shrey Baid688b4242020-07-10 20:40:10 +0530337 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100338 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700339
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100340 return grpcServer, nil
341}
342
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800343// StartOltServer will create the grpc server that VOLTHA uses
344// to communicate with the device
345func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
346 oltServer, err := o.newOltServer()
347 if err != nil {
348 oltLogger.WithFields(log.Fields{
349 "err": err,
350 }).Error("Cannot OLT gRPC server")
351 return nil, err
352 }
353 return oltServer, nil
354}
355
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100356// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800357func (o *OltDevice) StopOltServer() {
358 if o.oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800359 oltLogger.WithFields(log.Fields{
360 "oltId": o.SerialNumber,
361 }).Warnf("Stopping OLT gRPC server")
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800362 o.oltServer.Stop()
363 o.oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700364 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700365}
366
367// Device Methods
368
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100369// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530370func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700371 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530372 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700373
David Bainbridge103cf022019-12-16 20:11:35 +0000374 // If enabled has already been called then an enabled context has
375 // been created. If this is the case then we want to cancel all the
376 // proessing loops associated with that enable before we recreate
377 // new ones
378 o.Lock()
379 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700380 oltLogger.Info("This is an OLT reboot")
David Bainbridge103cf022019-12-16 20:11:35 +0000381 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530382 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000383 }
384 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
385 o.Unlock()
386
Matteo Scandolo4747d292019-08-05 11:50:18 -0700387 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800388 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700389
Matteo Scandolo4a036262020-08-17 15:56:13 -0700390 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530391
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100392 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000393 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700394
395 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800396 oltMsg := types.Message{
397 Type: types.OltIndication,
398 Data: types.OltIndicationMessage{
399 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700400 },
401 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100402 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700403
404 // send NNI Port Indications
405 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800406 msg := types.Message{
407 Type: types.NniIndication,
408 Data: types.NniIndicationMessage{
409 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700410 NniPortID: nni.ID,
411 },
412 }
413 o.channel <- msg
414 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100415
Shrey Baid688b4242020-07-10 20:40:10 +0530416 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530417 for _, pon := range o.Pons {
418 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800419 msg := types.Message{
420 Type: types.PonIndication,
421 Data: types.PonIndicationMessage{
422 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530423 PonPortID: pon.ID,
424 },
425 }
426 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000427 }
Pragya Arya2225f202020-01-29 18:05:01 +0530428 }
429 } else {
430
431 // 1. controlledActivation == Default: Send both PON and ONUs indications
432 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
433
434 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
435 // send PON Port indications
436 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800437 msg := types.Message{
438 Type: types.PonIndication,
439 Data: types.PonIndicationMessage{
440 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530441 PonPortID: pon.ID,
442 },
443 }
444 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700445 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700446 }
447 }
448
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800449 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530450
451 if !o.enablePerf {
452 // Start a go routine to send periodic port stats to openolt adapter
453 go o.periodicPortStats(o.enableContext)
454 }
455
Matteo Scandolo4747d292019-08-05 11:50:18 -0700456 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700457}
458
Pragya Arya996a0892020-03-09 21:47:52 +0530459func (o *OltDevice) periodicPortStats(ctx context.Context) {
460 var portStats *openolt.PortStatistics
461 for {
462 select {
463 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
464 // send NNI port stats
465 for _, port := range o.Nnis {
466 incrementStat := true
467 if port.OperState.Current() == "down" {
468 incrementStat = false
469 }
470 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
471 o.sendPortStatsIndication(portStats, port.ID, port.Type)
472 }
473
474 // send PON port stats
475 for _, port := range o.Pons {
476 incrementStat := true
477 // do not increment port stats if PON port is down or no ONU is activated on PON port
478 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
479 incrementStat = false
480 }
481 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
482 o.sendPortStatsIndication(portStats, port.ID, port.Type)
483 }
484 case <-ctx.Done():
485 log.Debug("Stop sending port stats")
486 return
487 }
488
489 }
490}
491
Matteo Scandolo4747d292019-08-05 11:50:18 -0700492// Helpers method
493
Matteo Scandolof9d43412021-01-12 11:11:34 -0800494func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
495
496 switch interfaceType {
497 case "nni":
498 if !o.HasNni(interfaceId) {
499 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
500 }
501
502 case "pon":
503 if !o.HasPon(interfaceId) {
504 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
505 }
506 }
507
508 alarmIndication := &openolt.AlarmIndication{
509 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
510 Status: alarmStatus,
511 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
512 }},
513 }
514
515 msg := types.Message{
516 Type: types.AlarmIndication,
517 Data: alarmIndication,
518 }
519
520 o.channel <- msg
521
522 return nil
523}
524
525func (o *OltDevice) HasNni(id uint32) bool {
526 for _, intf := range o.Nnis {
527 if intf.ID == id {
528 return true
529 }
530 }
531 return false
532}
533
534func (o *OltDevice) HasPon(id uint32) bool {
535 for _, intf := range o.Pons {
536 if intf.ID == id {
537 return true
538 }
539 }
540 return false
541}
542
Shrey Baid688b4242020-07-10 20:40:10 +0530543func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700544 for _, pon := range o.Pons {
545 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700546 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700547 }
548 }
Shrey Baid688b4242020-07-10 20:40:10 +0530549 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700550}
551
Shrey Baid688b4242020-07-10 20:40:10 +0530552func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700553 for _, nni := range o.Nnis {
554 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700555 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700556 }
557 }
Shrey Baid688b4242020-07-10 20:40:10 +0530558 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700559}
560
Scott Baker41724b82020-01-21 19:54:53 -0800561func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
562 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
563 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
564 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
565 return
566 }
567
568 oltLogger.WithFields(log.Fields{
569 "AlarmIndication": alarmInd,
570 }).Debug("Sent Indication_AlarmInd")
571}
572
Matteo Scandolof9d43412021-01-12 11:11:34 -0800573func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700574 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
575 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700576 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800577 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700578 }
579
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700580 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700581 "OperState": msg.OperState,
582 }).Debug("Sent Indication_OltInd")
583}
584
Matteo Scandolof9d43412021-01-12 11:11:34 -0800585func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700586 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800587 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800588 if err := nni.OperState.Event("enable"); err != nil {
589 log.WithFields(log.Fields{
590 "Type": nni.Type,
591 "IntfId": nni.ID,
592 "OperState": nni.OperState.Current(),
593 }).Errorf("Can't move NNI Port to enabled state: %v", err)
594 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800595 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800596 if err := nni.OperState.Event("disable"); err != nil {
597 log.WithFields(log.Fields{
598 "Type": nni.Type,
599 "IntfId": nni.ID,
600 "OperState": nni.OperState.Current(),
601 }).Errorf("Can't move NNI Port to disable state: %v", err)
602 }
603 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700604 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700605 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700606 Type: nni.Type,
607 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700608 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 }}
610
611 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700612 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800613 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700614 }
615
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700616 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700617 "Type": nni.Type,
618 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700619 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700620 }).Debug("Sent Indication_IntfOperInd for NNI")
621}
622
Pragya Arya2225f202020-01-29 18:05:01 +0530623func (o *OltDevice) sendPonIndication(ponPortID uint32) {
624
Matteo Scandolo4a036262020-08-17 15:56:13 -0700625 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530626 pon, _ := o.GetPonById(ponPortID)
627 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700628 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700629 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700630 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700631 }}
632
633 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700634 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800635 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700636 }
637
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700638 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700639 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700640 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700641 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700642
Pragya Arya2225f202020-01-29 18:05:01 +0530643 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700645 Type: pon.Type,
646 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700647 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700648 }}
649
650 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700651 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800652 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700653 }
654
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700655 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700656 "Type": pon.Type,
657 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700658 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700659 }).Debug("Sent Indication_IntfOperInd for PON")
660}
661
Pragya Arya996a0892020-03-09 21:47:52 +0530662func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530663 if o.InternalState.Current() == "enabled" {
664 oltLogger.WithFields(log.Fields{
665 "Type": portType,
666 "IntfId": portID,
667 }).Trace("Sending port stats")
668 stats.IntfId = InterfaceIDToPortNo(portID, portType)
669 data := &openolt.Indication_PortStats{
670 PortStats: stats,
671 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700672 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530673 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
674 oltLogger.Errorf("Failed to send PortStats: %v", err)
675 return
676 }
Pragya Arya996a0892020-03-09 21:47:52 +0530677 }
678}
679
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100680// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000681func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100682 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000683 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700684
David Bainbridge103cf022019-12-16 20:11:35 +0000685loop:
686 for {
687 select {
688 case <-ctx.Done():
689 oltLogger.Debug("OLT Indication processing canceled via context")
690 break loop
691 case message, ok := <-ch:
692 if !ok || ctx.Err() != nil {
693 oltLogger.Debug("OLT Indication processing canceled via closed channel")
694 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700695 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700696
David Bainbridge103cf022019-12-16 20:11:35 +0000697 oltLogger.WithFields(log.Fields{
698 "oltId": o.ID,
699 "messageType": message.Type,
700 }).Trace("Received message")
701
702 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800703 case types.OltIndication:
704 msg, _ := message.Data.(types.OltIndicationMessage)
705 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530706 _ = o.InternalState.Event("enable")
707 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800708 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530709 _ = o.InternalState.Event("disable")
710 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000711 }
712 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800713 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800714 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
715 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800716 case types.NniIndication:
717 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000718 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800719 case types.PonIndication:
720 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530721 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800722 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530723 if err := pon.OperState.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 Oper state for PON Port")
728 }
729 if err := pon.InternalState.Event("enable"); err != nil {
730 oltLogger.WithFields(log.Fields{
731 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800732 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530733 }).Error("Can't Enable Internal state for PON Port")
734 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800735 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530736 if err := pon.OperState.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 Oper state for PON Port")
741 }
742 if err := pon.InternalState.Event("disable"); err != nil {
743 oltLogger.WithFields(log.Fields{
744 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800745 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530746 }).Error("Can't Disable Internal state for PON Port")
747 }
Pragya Arya2225f202020-01-29 18:05:01 +0530748 }
David Bainbridge103cf022019-12-16 20:11:35 +0000749 default:
750 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
751 }
752 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700753 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100754 wg.Done()
755 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700756}
757
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700758// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530759func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200760 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700761 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700762 for _, pon := range o.Pons {
763 for _, onu := range pon.Onus {
764 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700765 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700766 }
767 }
768 }
769
Shrey Baid688b4242020-07-10 20:40:10 +0530770 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700771}
772
William Kurkian9dadc5b2019-10-22 13:51:57 -0400773// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530774func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200775 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400776 // memoizing it will remove the bottleneck
777 for _, pon := range o.Pons {
778 if pon.ID == intfId {
779 for _, onu := range pon.Onus {
780 if onu.ID == onuId {
781 return onu, nil
782 }
783 }
784 }
785 }
Shrey Baid688b4242020-07-10 20:40:10 +0530786 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400787}
788
Matteo Scandolo4a036262020-08-17 15:56:13 -0700789// returns a Service with a given Mac Address
790func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200791 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700792 // memoizing it will remove the bottleneck
793 for _, pon := range o.Pons {
794 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700795 s, err := onu.findServiceByMacAddress(mac)
796 if err == nil {
797 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700798 }
799 }
800 }
801
Matteo Scandolo4a036262020-08-17 15:56:13 -0700802 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700803}
804
Matteo Scandolo4747d292019-08-05 11:50:18 -0700805// GRPC Endpoints
806
Shrey Baid688b4242020-07-10 20:40:10 +0530807func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700808 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700809 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700810 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530811 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700812
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700813 pon, _ := o.GetPonById(onu.IntfId)
814 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500815 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700816
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700817 if err := _onu.OperState.Event("enable"); err != nil {
818 oltLogger.WithFields(log.Fields{
819 "IntfId": _onu.PonPortID,
820 "OnuSn": _onu.Sn(),
821 "OnuId": _onu.ID,
822 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700823 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700824 if err := _onu.InternalState.Event("enable"); err != nil {
825 oltLogger.WithFields(log.Fields{
826 "IntfId": _onu.PonPortID,
827 "OnuSn": _onu.Sn(),
828 "OnuId": _onu.ID,
829 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
830 }
831
832 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
833
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700834 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700835}
836
Shrey Baid688b4242020-07-10 20:40:10 +0530837func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700838 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700839 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700840}
841
Shrey Baid688b4242020-07-10 20:40:10 +0530842func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530843 oltLogger.WithFields(log.Fields{
844 "IntfId": onu.IntfId,
845 "OnuId": onu.OnuId,
846 }).Info("Received DeleteOnu call from VOLTHA")
847
848 pon, err := o.GetPonById(onu.IntfId)
849 if err != nil {
850 oltLogger.WithFields(log.Fields{
851 "OnuId": onu.OnuId,
852 "IntfId": onu.IntfId,
853 "err": err,
854 }).Error("Can't find PonPort")
855 }
856 _onu, err := pon.GetOnuById(onu.OnuId)
857 if err != nil {
858 oltLogger.WithFields(log.Fields{
859 "OnuId": onu.OnuId,
860 "IntfId": onu.IntfId,
861 "err": err,
862 }).Error("Can't find Onu")
863 }
864
Hardik Windlassad790cb2020-06-17 21:26:22 +0530865 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530866 oltLogger.WithFields(log.Fields{
867 "IntfId": _onu.PonPortID,
868 "OnuSn": _onu.Sn(),
869 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530870 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
871 }
872
Hardik Windlassad790cb2020-06-17 21:26:22 +0530873 // ONU Re-Discovery
874 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530875 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530876 }
877
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700878 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700879}
880
Shrey Baid688b4242020-07-10 20:40:10 +0530881func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700882 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800883 oltLogger.WithFields(log.Fields{
884 "oltId": o.ID,
885 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530886 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800887
Matteo Scandolo401503a2019-12-11 14:48:14 -0800888 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530889 if pon.InternalState.Current() == "enabled" {
890 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800891 msg := types.Message{
892 Type: types.PonIndication,
893 Data: types.PonIndicationMessage{
894 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530895 PonPortID: pon.ID,
896 },
897 }
898 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800899 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800900 }
901
Matteo Scandolo401503a2019-12-11 14:48:14 -0800902 // Note that we are not disabling the NNI as the real OLT does not.
903 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800904
905 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800906 oltMsg := types.Message{
907 Type: types.OltIndication,
908 Data: types.OltIndicationMessage{
909 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700910 },
911 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100912 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700913 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700914}
915
Shrey Baid688b4242020-07-10 20:40:10 +0530916func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530917 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200918 ponID := intf.GetIntfId()
919 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200920
Matteo Scandolof9d43412021-01-12 11:11:34 -0800921 msg := types.Message{
922 Type: types.PonIndication,
923 Data: types.PonIndicationMessage{
924 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200925 PonPortID: ponID,
926 },
927 }
928 o.channel <- msg
929
930 for _, onu := range pon.Onus {
931
Matteo Scandolof9d43412021-01-12 11:11:34 -0800932 onuIndication := types.OnuIndicationMessage{
933 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200934 PonPortID: ponID,
935 OnuID: onu.ID,
936 OnuSN: onu.SerialNumber,
937 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700938 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200939
940 }
941
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700942 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700943}
944
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100945func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700946 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530947 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700948 o.Enable(stream)
949 return nil
950}
951
Shrey Baid688b4242020-07-10 20:40:10 +0530952func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530953 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530954 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200955 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200956
Matteo Scandolof9d43412021-01-12 11:11:34 -0800957 msg := types.Message{
958 Type: types.PonIndication,
959 Data: types.PonIndicationMessage{
960 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530961 PonPortID: ponID,
962 },
963 }
964 o.channel <- msg
965
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200966 for _, onu := range pon.Onus {
967
Matteo Scandolof9d43412021-01-12 11:11:34 -0800968 onuIndication := types.OnuIndicationMessage{
969 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200970 PonPortID: ponID,
971 OnuID: onu.ID,
972 OnuSN: onu.SerialNumber,
973 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700974 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200975
976 }
977
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700978 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700979}
980
Shrey Baid688b4242020-07-10 20:40:10 +0530981func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700982 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700983 "IntfId": flow.AccessIntfId,
984 "OnuId": flow.OnuId,
985 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700986 "InnerVlan": flow.Classifier.IVid,
987 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700988 "FlowType": flow.FlowType,
989 "FlowId": flow.FlowId,
990 "UniID": flow.UniId,
991 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +0530992 }).Tracef("OLT receives FlowAdd")
993
994 flowKey := FlowKey{}
995 if !o.enablePerf {
996 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +0100997 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +0530998 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700999
1000 if flow.AccessIntfId == -1 {
1001 oltLogger.WithFields(log.Fields{
1002 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001003 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001004 } else if flow.FlowType == "multicast" {
1005 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001006 "Cookie": flow.Cookie,
1007 "DstPort": flow.Classifier.DstPort,
1008 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1009 "FlowId": flow.FlowId,
1010 "FlowType": flow.FlowType,
1011 "GemportId": flow.GemportId,
1012 "InnerVlan": flow.Classifier.IVid,
1013 "IntfId": flow.AccessIntfId,
1014 "IpProto": flow.Classifier.IpProto,
1015 "OnuId": flow.OnuId,
1016 "OuterVlan": flow.Classifier.OVid,
1017 "PortNo": flow.PortNo,
1018 "SrcPort": flow.Classifier.SrcPort,
1019 "UniID": flow.UniId,
1020 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001021 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001022 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001023 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001024 if err != nil {
1025 oltLogger.WithFields(log.Fields{
1026 "OnuId": flow.OnuId,
1027 "IntfId": flow.AccessIntfId,
1028 "err": err,
1029 }).Error("Can't find PonPort")
1030 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001031 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001032 if err != nil {
1033 oltLogger.WithFields(log.Fields{
1034 "OnuId": flow.OnuId,
1035 "IntfId": flow.AccessIntfId,
1036 "err": err,
1037 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001038 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001039 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301040 if !o.enablePerf {
1041 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301042 // Generate event on first flow for ONU
1043 if len(onu.Flows) == 1 {
1044 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1045 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301046 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001047
Matteo Scandolof9d43412021-01-12 11:11:34 -08001048 msg := types.Message{
1049 Type: types.FlowAdd,
1050 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001051 PonPortID: pon.ID,
1052 OnuID: onu.ID,
1053 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001054 },
1055 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001056 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001057 }
1058
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001059 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001060}
1061
Pragya Arya8bdb4532020-03-02 17:08:09 +05301062// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301063func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001064
Pragya Arya8bdb4532020-03-02 17:08:09 +05301065 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301066 "FlowId": flow.FlowId,
1067 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001068 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301069
1070 if !o.enablePerf { // remove only if flow were stored
1071 flowKey := FlowKey{
1072 ID: flow.FlowId,
1073 Direction: flow.FlowType,
1074 }
1075
1076 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001077 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301078 if !ok {
1079 oltLogger.Errorf("Flow %v not found", flow)
1080 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1081 }
1082
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001083 storedFlow := storedFlowIntf.(openolt.Flow)
1084
Pragya Arya8bdb4532020-03-02 17:08:09 +05301085 // if its ONU flow remove it from ONU also
1086 if storedFlow.AccessIntfId != -1 {
1087 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1088 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1089 if err != nil {
1090 oltLogger.WithFields(log.Fields{
1091 "OnuId": storedFlow.OnuId,
1092 "IntfId": storedFlow.AccessIntfId,
1093 "err": err,
1094 }).Error("ONU not found")
1095 return new(openolt.Empty), nil
1096 }
1097 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301098 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301099 }
1100
1101 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001102 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301103 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001104
1105 if flow.AccessIntfId == -1 {
1106 oltLogger.WithFields(log.Fields{
1107 "FlowId": flow.FlowId,
1108 }).Debug("Removing OLT flow")
1109 } else if flow.FlowType == "multicast" {
1110 oltLogger.WithFields(log.Fields{
1111 "FlowId": flow.FlowId,
1112 }).Debug("Removing OLT multicast flow")
1113 } else {
1114
1115 onu, err := o.GetOnuByFlowId(flow.FlowId)
1116 if err != nil {
1117 oltLogger.WithFields(log.Fields{
1118 "OnuId": flow.OnuId,
1119 "IntfId": flow.AccessIntfId,
1120 "err": err,
1121 }).Error("Can't find Onu")
1122 return nil, err
1123 }
1124
Matteo Scandolof9d43412021-01-12 11:11:34 -08001125 msg := types.Message{
1126 Type: types.FlowRemoved,
1127 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301128 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001129 },
1130 }
1131 onu.Channel <- msg
1132 }
1133
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001134 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001135}
1136
Shrey Baid688b4242020-07-10 20:40:10 +05301137func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001138 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1139 oltLogger.WithFields(log.Fields{
1140 "signature": res.HeartbeatSignature,
1141 }).Trace("HeartbeatCheck")
1142 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001143}
1144
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001145func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001146 for _, pon := range o.Pons {
1147 for _, onu := range pon.Onus {
1148 for _, fId := range onu.FlowIds {
1149 if fId == flowId {
1150 return onu, nil
1151 }
1152 }
1153 }
1154 }
Shrey Baid688b4242020-07-10 20:40:10 +05301155 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001156}
1157
Shrey Baid688b4242020-07-10 20:40:10 +05301158func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001159
Matteo Scandolo4747d292019-08-05 11:50:18 -07001160 devinfo := new(openolt.DeviceInfo)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001161 devinfo.Vendor = common.Config.Olt.Vendor
1162 devinfo.Model = common.Config.Olt.Model
1163 devinfo.HardwareVersion = common.Config.Olt.HardwareVersion
1164 devinfo.FirmwareVersion = common.Config.Olt.FirmwareVersion
1165 devinfo.Technology = common.Config.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001166 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001167 devinfo.OnuIdStart = 1
1168 devinfo.OnuIdEnd = 255
1169 devinfo.AllocIdStart = 1024
1170 devinfo.AllocIdEnd = 16383
1171 devinfo.GemportIdStart = 1024
1172 devinfo.GemportIdEnd = 65535
1173 devinfo.FlowIdStart = 1
1174 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001175 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4a036262020-08-17 15:56:13 -07001176 devinfo.DeviceId = common.Config.Olt.DeviceId
Matteo Scandolo96f89192021-03-12 13:17:26 -08001177 devinfo.PreviouslyConnected = o.PreviouslyConnected
1178
1179 oltLogger.WithFields(log.Fields{
1180 "Vendor": devinfo.Vendor,
1181 "Model": devinfo.Model,
1182 "HardwareVersion": devinfo.HardwareVersion,
1183 "FirmwareVersion": devinfo.FirmwareVersion,
1184 "Technology": devinfo.Technology,
1185 "PonPorts": devinfo.PonPorts,
1186 "OnuIdStart": devinfo.OnuIdStart,
1187 "OnuIdEnd": devinfo.OnuIdEnd,
1188 "AllocIdStart": devinfo.AllocIdStart,
1189 "AllocIdEnd": devinfo.AllocIdEnd,
1190 "GemportIdStart": devinfo.GemportIdStart,
1191 "GemportIdEnd": devinfo.GemportIdEnd,
1192 "FlowIdStart": devinfo.FlowIdStart,
1193 "FlowIdEnd": devinfo.FlowIdEnd,
1194 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1195 "DeviceId": devinfo.DeviceId,
1196 "PreviouslyConnected": devinfo.PreviouslyConnected,
1197 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1198
1199 // once we connect, set the flag
1200 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001201
1202 return devinfo, nil
1203}
1204
Shrey Baid688b4242020-07-10 20:40:10 +05301205func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001206 pon, err := o.GetPonById(omci_msg.IntfId)
1207 if err != nil {
1208 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001209 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001210 "onu_id": omci_msg.OnuId,
1211 "pon_id": omci_msg.IntfId,
1212 }).Error("pon ID not found")
1213 return nil, err
1214 }
1215
1216 onu, err := pon.GetOnuById(omci_msg.OnuId)
1217 if err != nil {
1218 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001219 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001220 "onu_id": omci_msg.OnuId,
1221 "pon_id": omci_msg.IntfId,
1222 }).Error("onu ID not found")
1223 return nil, err
1224 }
1225
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001226 oltLogger.WithFields(log.Fields{
1227 "IntfId": onu.PonPortID,
1228 "OnuId": onu.ID,
1229 "OnuSn": onu.Sn(),
1230 }).Tracef("Received OmciMsgOut")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001231 msg := types.Message{
1232 Type: types.OMCI,
1233 Data: types.OmciMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001234 OnuSN: onu.SerialNumber,
1235 OnuID: onu.ID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001236 OmciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001237 },
1238 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001239 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001240 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001241}
1242
Shrey Baid688b4242020-07-10 20:40:10 +05301243func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001244 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001245 if err != nil {
1246 oltLogger.WithFields(log.Fields{
1247 "OnuId": onuPkt.OnuId,
1248 "IntfId": onuPkt.IntfId,
1249 "err": err,
1250 }).Error("Can't find PonPort")
1251 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001252 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001253 if err != nil {
1254 oltLogger.WithFields(log.Fields{
1255 "OnuId": onuPkt.OnuId,
1256 "IntfId": onuPkt.IntfId,
1257 "err": err,
1258 }).Error("Can't find Onu")
1259 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001260
Matteo Scandolo075b1892019-10-07 12:11:07 -07001261 oltLogger.WithFields(log.Fields{
1262 "IntfId": onu.PonPortID,
1263 "OnuId": onu.ID,
1264 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001265 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001266 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001267
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001268 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001269
1270 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001271 if err != nil {
1272 onuLogger.WithFields(log.Fields{
1273 "IntfId": onu.PonPortID,
1274 "OnuId": onu.ID,
1275 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001276 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001277 }).Error("Can't find pktType in packet, droppint it")
1278 return new(openolt.Empty), nil
1279 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001280
Matteo Scandolo4a036262020-08-17 15:56:13 -07001281 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001282 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001283 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001284 "IntfId": onu.PonPortID,
1285 "OnuId": onu.ID,
1286 "OnuSn": onu.Sn(),
1287 "Pkt": rawpkt.Data(),
1288 }).Error("Can't find Dst MacAddress in packet, droppint it")
1289 return new(openolt.Empty), nil
1290 }
1291
Matteo Scandolof9d43412021-01-12 11:11:34 -08001292 msg := types.Message{
1293 Type: types.OnuPacketOut,
1294 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001295 IntfId: onuPkt.IntfId,
1296 OnuId: onuPkt.OnuId,
1297 Packet: rawpkt,
1298 Type: pktType,
1299 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001300 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001301 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001302
Matteo Scandolo075b1892019-10-07 12:11:07 -07001303 onu.Channel <- msg
1304
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001305 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001306}
1307
Shrey Baid688b4242020-07-10 20:40:10 +05301308func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001309
1310 // OLT Reboot is called in two cases:
1311 // - 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)
1312 // - when an OLT needs to be rebooted (voltcl device reboot)
1313
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001314 oltLogger.WithFields(log.Fields{
1315 "oltId": o.ID,
1316 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301317 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301318 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001319 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001320}
1321
Shrey Baid688b4242020-07-10 20:40:10 +05301322func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301323 oltLogger.WithFields(log.Fields{
1324 "oltId": o.ID,
1325 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301326 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301327
Pragya Arya2225f202020-01-29 18:05:01 +05301328 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001329 oltMsg := types.Message{
1330 Type: types.OltIndication,
1331 Data: types.OltIndicationMessage{
1332 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301333 },
Pragya Arya1881df02020-01-29 18:05:01 +05301334 }
Pragya Arya2225f202020-01-29 18:05:01 +05301335 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301336
Pragya Arya2225f202020-01-29 18:05:01 +05301337 for _, pon := range o.Pons {
1338 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001339 msg := types.Message{
1340 Type: types.PonIndication,
1341 Data: types.PonIndicationMessage{
1342 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301343 PonPortID: pon.ID,
1344 },
1345 }
1346 o.channel <- msg
1347 }
1348 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001349
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001350 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001351}
1352
Shrey Baid688b4242020-07-10 20:40:10 +05301353func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001354 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1355
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001356 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1357
1358 if err != nil {
1359 return nil, err
1360 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001361 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001362}
1363
Shrey Baid688b4242020-07-10 20:40:10 +05301364func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001365 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001366 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001367}
1368
Shrey Baid688b4242020-07-10 20:40:10 +05301369func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001370 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001371 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001372}
1373
Shrey Baid688b4242020-07-10 20:40:10 +05301374func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001375 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001376 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001377}
1378
Shrey Baid688b4242020-07-10 20:40:10 +05301379func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001380 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001381 return new(openolt.Empty), nil
1382}
1383
Shrey Baid688b4242020-07-10 20:40:10 +05301384func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001385 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001386 return new(openolt.Empty), nil
1387}
1388
Shrey Baid688b4242020-07-10 20:40:10 +05301389func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301390 oltLogger.WithFields(log.Fields{
1391 "OnuId": trafficSchedulers.OnuId,
1392 "IntfId": trafficSchedulers.IntfId,
1393 "OnuPortNo": trafficSchedulers.PortNo,
1394 }).Info("received CreateTrafficSchedulers")
1395
1396 if !s.enablePerf {
1397 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1398 if err != nil {
1399 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1400 return new(openolt.Empty), err
1401 }
1402 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1403 if err != nil {
1404 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1405 return new(openolt.Empty), err
1406 }
1407 onu.TrafficSchedulers = trafficSchedulers
1408 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001409 return new(openolt.Empty), nil
1410}
1411
Shrey Baid688b4242020-07-10 20:40:10 +05301412func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301413 oltLogger.WithFields(log.Fields{
1414 "OnuId": trafficSchedulers.OnuId,
1415 "IntfId": trafficSchedulers.IntfId,
1416 "OnuPortNo": trafficSchedulers.PortNo,
1417 }).Info("received RemoveTrafficSchedulers")
1418 if !s.enablePerf {
1419 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1420 if err != nil {
1421 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1422 return new(openolt.Empty), err
1423 }
1424 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1425 if err != nil {
1426 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1427 return new(openolt.Empty), err
1428 }
1429
1430 onu.TrafficSchedulers = nil
1431 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001432 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001433}
Scott Baker41724b82020-01-21 19:54:53 -08001434
Matteo Scandolo618a6582020-09-09 12:21:29 -07001435func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1436 oltLogger.WithFields(log.Fields{
1437 "GroupId": group.GroupId,
1438 "Command": group.Command,
1439 "Members": group.Members,
1440 "Action": group.Action,
1441 }).Debug("received PerformGroupOperation")
1442 return &openolt.Empty{}, nil
1443}
1444
1445func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1446 oltLogger.WithFields(log.Fields{
1447 "GroupId": group.GroupId,
1448 "Command": group.Command,
1449 "Members": group.Members,
1450 "Action": group.Action,
1451 }).Debug("received PerformGroupOperation")
1452 return &openolt.Empty{}, nil
1453}
1454
1455func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1456 return &common_protos.ReturnValues{}, nil
1457}
1458
1459func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1460 return &openolt.Empty{}, nil
1461}
1462
1463func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1464 return &openolt.OnuLogicalDistance{}, nil
1465}
1466
1467func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1468 return &openolt.OnuLogicalDistance{}, nil
1469}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001470
1471func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1472 return &openolt.GemPortStatistics{}, nil
1473}
1474
1475func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1476 return &openolt.OnuStatistics{}, nil
1477}