blob: f9ef936a59f07c7155f30f19b7301561ea97e220 [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 Scandolocedde462021-03-09 17:37:16 -080050const (
51 onuIdStart = 1
52 onuIdEnd = 127
53 allocIdStart = 1024
54 allocIdEnd = 16383
55 gemportIdStart = 1024
56 gemportIdEnd = 65535
57 flowIdStart = 1
58 flowIdEnd = 65535
59)
60
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070061type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000062 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000063 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000064
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070065 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053066 ID int
67 SerialNumber string
68 NumNni int
69 NumPon int
70 NumOnuPerPon int
71 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080072 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070073 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010074 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053075 Delay int
76 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053077 EventChannel chan common.Event
78 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053079 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080080 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070081
Matteo Scandolo27428702019-10-11 16:21:16 -070082 Pons []*PonPort
83 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070084
85 // OLT Attributes
86 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000087
88 enableContext context.Context
89 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053090
Matteo Scandolo4a036262020-08-17 15:56:13 -070091 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053092 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070093}
94
Matteo Scandolo27428702019-10-11 16:21:16 -070095var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -070096
Matteo Scandolo27428702019-10-11 16:21:16 -070097func GetOLT() *OltDevice {
98 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070099}
100
Matteo Scandolo4a036262020-08-17 15:56:13 -0700101func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700102 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530103 "ID": options.Olt.ID,
104 "NumNni": options.Olt.NniPorts,
105 "NumPon": options.Olt.PonPorts,
106 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700107 }).Debug("CreateOLT")
108
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700109 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530110 ID: options.Olt.ID,
111 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700112 OperState: getOperStateFSM(func(e *fsm.Event) {
113 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
114 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800115 NumNni: int(options.Olt.NniPorts),
116 NumPon: int(options.Olt.PonPorts),
117 NumOnuPerPon: int(options.Olt.OnusPonPort),
118 Pons: []*PonPort{},
119 Nnis: []*NniPort{},
120 Delay: options.BBSim.Delay,
121 enablePerf: options.BBSim.EnablePerf,
122 PublishEvents: options.BBSim.Events,
123 PortStatsInterval: options.Olt.PortStatsInterval,
124 dhcpServer: dhcp.NewDHCPServer(),
125 PreviouslyConnected: false,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700126 }
127
Pragya Arya996a0892020-03-09 21:47:52 +0530128 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530129 olt.ControlledActivation = val
130 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700131 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530132 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
133 olt.ControlledActivation = Default
134 }
135
Matteo Scandolo4747d292019-08-05 11:50:18 -0700136 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700137 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700138 olt.InternalState = fsm.NewFSM(
139 "created",
140 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800141 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100142 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700143 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700144 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800145 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700146 },
147 fsm.Callbacks{
148 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700149 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100151 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700152 },
153 )
154
Shrey Baid688b4242020-07-10 20:40:10 +0530155 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700156 // create NNI Port
157 nniPort, err := CreateNNI(&olt)
158 if err != nil {
159 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
160 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700161
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700162 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700163 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700164
Matteo Scandolo4a036262020-08-17 15:56:13 -0700165 // Create device and Services
166
167 nextCtag := map[string]int{}
168 nextStag := map[string]int{}
169
Matteo Scandolo4747d292019-08-05 11:50:18 -0700170 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700171 for i := 0; i < olt.NumPon; i++ {
172 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700173
Matteo Scandolo4a036262020-08-17 15:56:13 -0700174 // create ONU devices
175 for j := 0; j < olt.NumOnuPerPon; j++ {
176 delay := time.Duration(olt.Delay*j) * time.Millisecond
177 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700178
Matteo Scandolo4a036262020-08-17 15:56:13 -0700179 for k, s := range common.Services {
180
181 // find the correct cTag for this service
182 if _, ok := nextCtag[s.Name]; !ok {
183 // it's the first time we iterate over this service,
184 // so we start from the config value
185 nextCtag[s.Name] = s.CTag
186 } else {
187 // we have a previous value, so we check it
188 // if Allocation is unique, we increment,
189 // otherwise (shared) we do nothing
190 if s.CTagAllocation == common.TagAllocationUnique.String() {
191 nextCtag[s.Name] = nextCtag[s.Name] + 1
192 }
193 }
194
195 // find the correct sTag for this service
196 if _, ok := nextStag[s.Name]; !ok {
197 nextStag[s.Name] = s.STag
198 } else {
199 if s.STagAllocation == common.TagAllocationUnique.String() {
200 nextStag[s.Name] = nextStag[s.Name] + 1
201 }
202 }
203
204 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
205 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
206 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
207 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
208
209 if err != nil {
210 oltLogger.WithFields(log.Fields{
211 "Err": err.Error(),
212 }).Fatal("Can't create Service")
213 }
214
215 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700216 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700217 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700218 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700219 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700220 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100221
Shrey Baid688b4242020-07-10 20:40:10 +0530222 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700223 if err := olt.InternalState.Event("initialize"); err != nil {
224 log.Errorf("Error initializing OLT: %v", err)
225 return nil
226 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100227 }
228
Pragya Arya324337e2020-02-20 14:35:08 +0530229 if olt.PublishEvents {
230 log.Debugf("BBSim event publishing is enabled")
231 // Create a channel to write event messages
232 olt.EventChannel = make(chan common.Event, 100)
233 }
234
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700235 return &olt
236}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700237
Shrey Baid688b4242020-07-10 20:40:10 +0530238func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100239
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000240 if o.OltServer == nil {
241 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100242 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800243 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100244 }
245
246 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800247 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100248
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100249 // FIXME we are assuming we have only one NNI
250 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800251 // NOTE we want to make sure the state is down when we initialize the OLT,
252 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
253 // in-band management
254 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100255 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700256}
257
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800258func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100259
Matteo Scandolo96f89192021-03-12 13:17:26 -0800260 o.PreviouslyConnected = false
261
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700262 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700263 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800264
265 oltLogger.WithFields(log.Fields{
266 "oltId": o.ID,
267 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
268
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700269 if o.InternalState.Is("enabled") {
270 oltLogger.WithFields(log.Fields{
271 "oltId": o.ID,
272 }).Info("This is an OLT soft reboot")
273 softReboot = true
274 }
275
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800276 // transition internal state to deleted
277 if err := o.InternalState.Event("delete"); err != nil {
278 oltLogger.WithFields(log.Fields{
279 "oltId": o.ID,
280 }).Errorf("Error deleting OLT: %v", err)
281 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100282 }
283
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800284 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 -0800285 o.StopOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100286
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700287 if softReboot {
288 for _, pon := range o.Pons {
289 if pon.InternalState.Current() == "enabled" {
290 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800291 msg := types.Message{
292 Type: types.PonIndication,
293 Data: types.PonIndicationMessage{
294 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700295 PonPortID: pon.ID,
296 },
297 }
298 o.channel <- msg
299 }
300
301 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800302 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700303 }
304 }
305 } else {
306 // PONs are already handled in the Disable call
307 for _, pon := range olt.Pons {
308 // ONUs are not automatically disabled when a PON goes down
309 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
310 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800311 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700312 }
Pragya Arya2225f202020-01-29 18:05:01 +0530313 }
314 }
315
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100316 // terminate the OLT's processOltMessages go routine
317 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700318
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700319 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100320
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100321 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100322
323 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800324 oltLogger.WithFields(log.Fields{
325 "oltId": o.ID,
326 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100327 return err
328 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800329 oltLogger.WithFields(log.Fields{
330 "oltId": o.ID,
331 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100332 return nil
333}
334
335// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800336func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700337 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700338 lis, err := net.Listen("tcp", address)
339 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700340 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700341 }
342 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100343
Matteo Scandolo4747d292019-08-05 11:50:18 -0700344 openolt.RegisterOpenoltServer(grpcServer, o)
345
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100346 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700347
Shrey Baid688b4242020-07-10 20:40:10 +0530348 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100349 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700350
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100351 return grpcServer, nil
352}
353
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800354// StartOltServer will create the grpc server that VOLTHA uses
355// to communicate with the device
356func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
357 oltServer, err := o.newOltServer()
358 if err != nil {
359 oltLogger.WithFields(log.Fields{
360 "err": err,
361 }).Error("Cannot OLT gRPC server")
362 return nil, err
363 }
364 return oltServer, nil
365}
366
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100367// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800368func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000369 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800370 oltLogger.WithFields(log.Fields{
371 "oltId": o.SerialNumber,
372 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000373 o.OltServer.Stop()
374 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700375 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700376}
377
378// Device Methods
379
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100380// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530381func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700382 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530383 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700384
David Bainbridge103cf022019-12-16 20:11:35 +0000385 // If enabled has already been called then an enabled context has
386 // been created. If this is the case then we want to cancel all the
387 // proessing loops associated with that enable before we recreate
388 // new ones
389 o.Lock()
390 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700391 oltLogger.Info("This is an OLT reboot")
David Bainbridge103cf022019-12-16 20:11:35 +0000392 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530393 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000394 }
395 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
396 o.Unlock()
397
Matteo Scandolo4747d292019-08-05 11:50:18 -0700398 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800399 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700400
Matteo Scandolo4a036262020-08-17 15:56:13 -0700401 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530402
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100403 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000404 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700405
406 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800407 oltMsg := types.Message{
408 Type: types.OltIndication,
409 Data: types.OltIndicationMessage{
410 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700411 },
412 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100413 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700414
415 // send NNI Port Indications
416 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800417 msg := types.Message{
418 Type: types.NniIndication,
419 Data: types.NniIndicationMessage{
420 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700421 NniPortID: nni.ID,
422 },
423 }
424 o.channel <- msg
425 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100426
Shrey Baid688b4242020-07-10 20:40:10 +0530427 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530428 for _, pon := range o.Pons {
429 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800430 msg := types.Message{
431 Type: types.PonIndication,
432 Data: types.PonIndicationMessage{
433 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530434 PonPortID: pon.ID,
435 },
436 }
437 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000438 }
Pragya Arya2225f202020-01-29 18:05:01 +0530439 }
440 } else {
441
442 // 1. controlledActivation == Default: Send both PON and ONUs indications
443 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
444
445 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
446 // send PON Port indications
447 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800448 msg := types.Message{
449 Type: types.PonIndication,
450 Data: types.PonIndicationMessage{
451 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530452 PonPortID: pon.ID,
453 },
454 }
455 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700456 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700457 }
458 }
459
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800460 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530461
462 if !o.enablePerf {
463 // Start a go routine to send periodic port stats to openolt adapter
464 go o.periodicPortStats(o.enableContext)
465 }
466
Matteo Scandolo4747d292019-08-05 11:50:18 -0700467 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700468}
469
Pragya Arya996a0892020-03-09 21:47:52 +0530470func (o *OltDevice) periodicPortStats(ctx context.Context) {
471 var portStats *openolt.PortStatistics
472 for {
473 select {
474 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
475 // send NNI port stats
476 for _, port := range o.Nnis {
477 incrementStat := true
478 if port.OperState.Current() == "down" {
479 incrementStat = false
480 }
481 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
482 o.sendPortStatsIndication(portStats, port.ID, port.Type)
483 }
484
485 // send PON port stats
486 for _, port := range o.Pons {
487 incrementStat := true
488 // do not increment port stats if PON port is down or no ONU is activated on PON port
489 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
490 incrementStat = false
491 }
492 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
493 o.sendPortStatsIndication(portStats, port.ID, port.Type)
494 }
495 case <-ctx.Done():
496 log.Debug("Stop sending port stats")
497 return
498 }
499
500 }
501}
502
Matteo Scandolo4747d292019-08-05 11:50:18 -0700503// Helpers method
504
Matteo Scandolof9d43412021-01-12 11:11:34 -0800505func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
506
507 switch interfaceType {
508 case "nni":
509 if !o.HasNni(interfaceId) {
510 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
511 }
512
513 case "pon":
514 if !o.HasPon(interfaceId) {
515 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
516 }
517 }
518
519 alarmIndication := &openolt.AlarmIndication{
520 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
521 Status: alarmStatus,
522 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
523 }},
524 }
525
526 msg := types.Message{
527 Type: types.AlarmIndication,
528 Data: alarmIndication,
529 }
530
531 o.channel <- msg
532
533 return nil
534}
535
536func (o *OltDevice) HasNni(id uint32) bool {
537 for _, intf := range o.Nnis {
538 if intf.ID == id {
539 return true
540 }
541 }
542 return false
543}
544
545func (o *OltDevice) HasPon(id uint32) bool {
546 for _, intf := range o.Pons {
547 if intf.ID == id {
548 return true
549 }
550 }
551 return false
552}
553
Shrey Baid688b4242020-07-10 20:40:10 +0530554func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700555 for _, pon := range o.Pons {
556 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700557 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700558 }
559 }
Shrey Baid688b4242020-07-10 20:40:10 +0530560 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700561}
562
Shrey Baid688b4242020-07-10 20:40:10 +0530563func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700564 for _, nni := range o.Nnis {
565 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700566 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700567 }
568 }
Shrey Baid688b4242020-07-10 20:40:10 +0530569 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700570}
571
Scott Baker41724b82020-01-21 19:54:53 -0800572func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
573 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
574 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
575 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
576 return
577 }
578
579 oltLogger.WithFields(log.Fields{
580 "AlarmIndication": alarmInd,
581 }).Debug("Sent Indication_AlarmInd")
582}
583
Matteo Scandolof9d43412021-01-12 11:11:34 -0800584func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700585 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
586 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700587 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800588 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700589 }
590
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700591 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700592 "OperState": msg.OperState,
593 }).Debug("Sent Indication_OltInd")
594}
595
Matteo Scandolof9d43412021-01-12 11:11:34 -0800596func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700597 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800598 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800599 if err := nni.OperState.Event("enable"); err != nil {
600 log.WithFields(log.Fields{
601 "Type": nni.Type,
602 "IntfId": nni.ID,
603 "OperState": nni.OperState.Current(),
604 }).Errorf("Can't move NNI Port to enabled state: %v", err)
605 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800606 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800607 if err := nni.OperState.Event("disable"); err != nil {
608 log.WithFields(log.Fields{
609 "Type": nni.Type,
610 "IntfId": nni.ID,
611 "OperState": nni.OperState.Current(),
612 }).Errorf("Can't move NNI Port to disable state: %v", err)
613 }
614 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700615 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700616 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
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 }}
621
622 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700623 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800624 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700625 }
626
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700627 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700628 "Type": nni.Type,
629 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700630 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700631 }).Debug("Sent Indication_IntfOperInd for NNI")
632}
633
Pragya Arya2225f202020-01-29 18:05:01 +0530634func (o *OltDevice) sendPonIndication(ponPortID uint32) {
635
Matteo Scandolo4a036262020-08-17 15:56:13 -0700636 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530637 pon, _ := o.GetPonById(ponPortID)
638 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700639 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700640 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: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700645 oltLogger.Errorf("Failed to send Indication_IntfInd: %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 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700651 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700652 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700653
Pragya Arya2225f202020-01-29 18:05:01 +0530654 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
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 }}
660
661 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700662 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800663 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664 }
665
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700666 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700667 "Type": pon.Type,
668 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700669 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700670 }).Debug("Sent Indication_IntfOperInd for PON")
671}
672
Pragya Arya996a0892020-03-09 21:47:52 +0530673func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530674 if o.InternalState.Current() == "enabled" {
675 oltLogger.WithFields(log.Fields{
676 "Type": portType,
677 "IntfId": portID,
678 }).Trace("Sending port stats")
679 stats.IntfId = InterfaceIDToPortNo(portID, portType)
680 data := &openolt.Indication_PortStats{
681 PortStats: stats,
682 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700683 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530684 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
685 oltLogger.Errorf("Failed to send PortStats: %v", err)
686 return
687 }
Pragya Arya996a0892020-03-09 21:47:52 +0530688 }
689}
690
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100691// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000692func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100693 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000694 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700695
David Bainbridge103cf022019-12-16 20:11:35 +0000696loop:
697 for {
698 select {
699 case <-ctx.Done():
700 oltLogger.Debug("OLT Indication processing canceled via context")
701 break loop
702 case message, ok := <-ch:
703 if !ok || ctx.Err() != nil {
704 oltLogger.Debug("OLT Indication processing canceled via closed channel")
705 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700706 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700707
David Bainbridge103cf022019-12-16 20:11:35 +0000708 oltLogger.WithFields(log.Fields{
709 "oltId": o.ID,
710 "messageType": message.Type,
711 }).Trace("Received message")
712
713 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800714 case types.OltIndication:
715 msg, _ := message.Data.(types.OltIndicationMessage)
716 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530717 _ = o.InternalState.Event("enable")
718 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800719 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530720 _ = o.InternalState.Event("disable")
721 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000722 }
723 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800724 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800725 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
726 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800727 case types.NniIndication:
728 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000729 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800730 case types.PonIndication:
731 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530732 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800733 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530734 if err := pon.OperState.Event("enable"); err != nil {
735 oltLogger.WithFields(log.Fields{
736 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800737 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530738 }).Error("Can't Enable Oper state for PON Port")
739 }
740 if err := pon.InternalState.Event("enable"); err != nil {
741 oltLogger.WithFields(log.Fields{
742 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800743 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530744 }).Error("Can't Enable Internal state for PON Port")
745 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800746 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530747 if err := pon.OperState.Event("disable"); err != nil {
748 oltLogger.WithFields(log.Fields{
749 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800750 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530751 }).Error("Can't Disable Oper state for PON Port")
752 }
753 if err := pon.InternalState.Event("disable"); err != nil {
754 oltLogger.WithFields(log.Fields{
755 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800756 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530757 }).Error("Can't Disable Internal state for PON Port")
758 }
Pragya Arya2225f202020-01-29 18:05:01 +0530759 }
David Bainbridge103cf022019-12-16 20:11:35 +0000760 default:
761 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
762 }
763 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700764 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100765 wg.Done()
766 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700767}
768
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700769// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530770func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200771 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700772 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700773 for _, pon := range o.Pons {
774 for _, onu := range pon.Onus {
775 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700776 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700777 }
778 }
779 }
780
Shrey Baid688b4242020-07-10 20:40:10 +0530781 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700782}
783
William Kurkian9dadc5b2019-10-22 13:51:57 -0400784// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530785func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200786 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400787 // memoizing it will remove the bottleneck
788 for _, pon := range o.Pons {
789 if pon.ID == intfId {
790 for _, onu := range pon.Onus {
791 if onu.ID == onuId {
792 return onu, nil
793 }
794 }
795 }
796 }
Shrey Baid688b4242020-07-10 20:40:10 +0530797 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400798}
799
Matteo Scandolo4a036262020-08-17 15:56:13 -0700800// returns a Service with a given Mac Address
801func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200802 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700803 // memoizing it will remove the bottleneck
804 for _, pon := range o.Pons {
805 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700806 s, err := onu.findServiceByMacAddress(mac)
807 if err == nil {
808 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700809 }
810 }
811 }
812
Matteo Scandolo4a036262020-08-17 15:56:13 -0700813 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700814}
815
Matteo Scandolo4747d292019-08-05 11:50:18 -0700816// GRPC Endpoints
817
Shrey Baid688b4242020-07-10 20:40:10 +0530818func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700819 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700820 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700821 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530822 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700823
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700824 pon, _ := o.GetPonById(onu.IntfId)
825 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500826 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700827
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700828 if err := _onu.OperState.Event("enable"); err != nil {
829 oltLogger.WithFields(log.Fields{
830 "IntfId": _onu.PonPortID,
831 "OnuSn": _onu.Sn(),
832 "OnuId": _onu.ID,
833 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700834 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800835 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700836 oltLogger.WithFields(log.Fields{
837 "IntfId": _onu.PonPortID,
838 "OnuSn": _onu.Sn(),
839 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800840 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700841 }
842
843 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
844
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700845 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700846}
847
Shrey Baid688b4242020-07-10 20:40:10 +0530848func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700849 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700850 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700851}
852
Shrey Baid688b4242020-07-10 20:40:10 +0530853func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530854 oltLogger.WithFields(log.Fields{
855 "IntfId": onu.IntfId,
856 "OnuId": onu.OnuId,
857 }).Info("Received DeleteOnu call from VOLTHA")
858
859 pon, err := o.GetPonById(onu.IntfId)
860 if err != nil {
861 oltLogger.WithFields(log.Fields{
862 "OnuId": onu.OnuId,
863 "IntfId": onu.IntfId,
864 "err": err,
865 }).Error("Can't find PonPort")
866 }
867 _onu, err := pon.GetOnuById(onu.OnuId)
868 if err != nil {
869 oltLogger.WithFields(log.Fields{
870 "OnuId": onu.OnuId,
871 "IntfId": onu.IntfId,
872 "err": err,
873 }).Error("Can't find Onu")
874 }
875
Matteo Scandolocedde462021-03-09 17:37:16 -0800876 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530877 oltLogger.WithFields(log.Fields{
878 "IntfId": _onu.PonPortID,
879 "OnuSn": _onu.Sn(),
880 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800881 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530882 }
883
Hardik Windlassad790cb2020-06-17 21:26:22 +0530884 // ONU Re-Discovery
885 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530886 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530887 }
888
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700889 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700890}
891
Shrey Baid688b4242020-07-10 20:40:10 +0530892func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700893 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800894 oltLogger.WithFields(log.Fields{
895 "oltId": o.ID,
896 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530897 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800898
Matteo Scandolo401503a2019-12-11 14:48:14 -0800899 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530900 if pon.InternalState.Current() == "enabled" {
901 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800902 msg := types.Message{
903 Type: types.PonIndication,
904 Data: types.PonIndicationMessage{
905 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530906 PonPortID: pon.ID,
907 },
908 }
909 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800910 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800911 }
912
Matteo Scandolo401503a2019-12-11 14:48:14 -0800913 // Note that we are not disabling the NNI as the real OLT does not.
914 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800915
916 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800917 oltMsg := types.Message{
918 Type: types.OltIndication,
919 Data: types.OltIndicationMessage{
920 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700921 },
922 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100923 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700924 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700925}
926
Shrey Baid688b4242020-07-10 20:40:10 +0530927func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530928 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200929 ponID := intf.GetIntfId()
930 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200931
Matteo Scandolof9d43412021-01-12 11:11:34 -0800932 msg := types.Message{
933 Type: types.PonIndication,
934 Data: types.PonIndicationMessage{
935 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200936 PonPortID: ponID,
937 },
938 }
939 o.channel <- msg
940
941 for _, onu := range pon.Onus {
942
Matteo Scandolof9d43412021-01-12 11:11:34 -0800943 onuIndication := types.OnuIndicationMessage{
944 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200945 PonPortID: ponID,
946 OnuID: onu.ID,
947 OnuSN: onu.SerialNumber,
948 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700949 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200950
951 }
952
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700953 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700954}
955
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100956func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700957 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530958 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700959 o.Enable(stream)
960 return nil
961}
962
Shrey Baid688b4242020-07-10 20:40:10 +0530963func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530964 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530965 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200966 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200967
Matteo Scandolof9d43412021-01-12 11:11:34 -0800968 msg := types.Message{
969 Type: types.PonIndication,
970 Data: types.PonIndicationMessage{
971 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530972 PonPortID: ponID,
973 },
974 }
975 o.channel <- msg
976
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200977 for _, onu := range pon.Onus {
978
Matteo Scandolof9d43412021-01-12 11:11:34 -0800979 onuIndication := types.OnuIndicationMessage{
980 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200981 PonPortID: ponID,
982 OnuID: onu.ID,
983 OnuSN: onu.SerialNumber,
984 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700985 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200986
987 }
988
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700989 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700990}
991
Shrey Baid688b4242020-07-10 20:40:10 +0530992func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700993 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700994 "IntfId": flow.AccessIntfId,
995 "OnuId": flow.OnuId,
996 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700997 "InnerVlan": flow.Classifier.IVid,
998 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700999 "FlowType": flow.FlowType,
1000 "FlowId": flow.FlowId,
1001 "UniID": flow.UniId,
1002 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301003 }).Tracef("OLT receives FlowAdd")
1004
1005 flowKey := FlowKey{}
1006 if !o.enablePerf {
1007 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001008 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301009 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001010
1011 if flow.AccessIntfId == -1 {
1012 oltLogger.WithFields(log.Fields{
1013 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001014 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001015 } else if flow.FlowType == "multicast" {
1016 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001017 "Cookie": flow.Cookie,
1018 "DstPort": flow.Classifier.DstPort,
1019 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1020 "FlowId": flow.FlowId,
1021 "FlowType": flow.FlowType,
1022 "GemportId": flow.GemportId,
1023 "InnerVlan": flow.Classifier.IVid,
1024 "IntfId": flow.AccessIntfId,
1025 "IpProto": flow.Classifier.IpProto,
1026 "OnuId": flow.OnuId,
1027 "OuterVlan": flow.Classifier.OVid,
1028 "PortNo": flow.PortNo,
1029 "SrcPort": flow.Classifier.SrcPort,
1030 "UniID": flow.UniId,
1031 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001032 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001033 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001034 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001035 if err != nil {
1036 oltLogger.WithFields(log.Fields{
1037 "OnuId": flow.OnuId,
1038 "IntfId": flow.AccessIntfId,
1039 "err": err,
1040 }).Error("Can't find PonPort")
1041 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001042 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001043 if err != nil {
1044 oltLogger.WithFields(log.Fields{
1045 "OnuId": flow.OnuId,
1046 "IntfId": flow.AccessIntfId,
1047 "err": err,
1048 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001049 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001050 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301051 if !o.enablePerf {
1052 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301053 // Generate event on first flow for ONU
1054 if len(onu.Flows) == 1 {
1055 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1056 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301057 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001058
Matteo Scandolof9d43412021-01-12 11:11:34 -08001059 msg := types.Message{
1060 Type: types.FlowAdd,
1061 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001062 PonPortID: pon.ID,
1063 OnuID: onu.ID,
1064 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001065 },
1066 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001067 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001068 }
1069
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001070 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001071}
1072
Pragya Arya8bdb4532020-03-02 17:08:09 +05301073// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301074func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001075
Pragya Arya8bdb4532020-03-02 17:08:09 +05301076 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301077 "FlowId": flow.FlowId,
1078 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001079 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301080
1081 if !o.enablePerf { // remove only if flow were stored
1082 flowKey := FlowKey{
1083 ID: flow.FlowId,
1084 Direction: flow.FlowType,
1085 }
1086
1087 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001088 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301089 if !ok {
1090 oltLogger.Errorf("Flow %v not found", flow)
1091 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1092 }
1093
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001094 storedFlow := storedFlowIntf.(openolt.Flow)
1095
Pragya Arya8bdb4532020-03-02 17:08:09 +05301096 // if its ONU flow remove it from ONU also
1097 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001098 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1099 if err != nil {
1100 oltLogger.WithFields(log.Fields{
1101 "OnuId": storedFlow.OnuId,
1102 "IntfId": storedFlow.AccessIntfId,
1103 "PONs": olt.Pons,
1104 "err": err,
1105 }).Error("PON-port-not-found")
1106 return new(openolt.Empty), nil
1107 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301108 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1109 if err != nil {
1110 oltLogger.WithFields(log.Fields{
1111 "OnuId": storedFlow.OnuId,
1112 "IntfId": storedFlow.AccessIntfId,
1113 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001114 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301115 return new(openolt.Empty), nil
1116 }
1117 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301118 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301119 }
1120
1121 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001122 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301123 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001124
1125 if flow.AccessIntfId == -1 {
1126 oltLogger.WithFields(log.Fields{
1127 "FlowId": flow.FlowId,
1128 }).Debug("Removing OLT flow")
1129 } else if flow.FlowType == "multicast" {
1130 oltLogger.WithFields(log.Fields{
1131 "FlowId": flow.FlowId,
1132 }).Debug("Removing OLT multicast flow")
1133 } else {
1134
1135 onu, err := o.GetOnuByFlowId(flow.FlowId)
1136 if err != nil {
1137 oltLogger.WithFields(log.Fields{
1138 "OnuId": flow.OnuId,
1139 "IntfId": flow.AccessIntfId,
1140 "err": err,
1141 }).Error("Can't find Onu")
1142 return nil, err
1143 }
1144
Matteo Scandolof9d43412021-01-12 11:11:34 -08001145 msg := types.Message{
1146 Type: types.FlowRemoved,
1147 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301148 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001149 },
1150 }
1151 onu.Channel <- msg
1152 }
1153
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001154 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001155}
1156
Shrey Baid688b4242020-07-10 20:40:10 +05301157func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001158 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1159 oltLogger.WithFields(log.Fields{
1160 "signature": res.HeartbeatSignature,
1161 }).Trace("HeartbeatCheck")
1162 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001163}
1164
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001165func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001166 for _, pon := range o.Pons {
1167 for _, onu := range pon.Onus {
1168 for _, fId := range onu.FlowIds {
1169 if fId == flowId {
1170 return onu, nil
1171 }
1172 }
1173 }
1174 }
Shrey Baid688b4242020-07-10 20:40:10 +05301175 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001176}
1177
Shrey Baid688b4242020-07-10 20:40:10 +05301178func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001179
Matteo Scandolocedde462021-03-09 17:37:16 -08001180 oltLogger.WithFields(log.Fields{
1181 "oltId": o.ID,
1182 "PonPorts": o.NumPon,
1183 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1184
1185 intfIDs := []uint32{}
1186 for i := 0; i < o.NumPon; i++ {
1187 intfIDs = append(intfIDs, uint32(i))
1188 }
1189
1190 devinfo := &openolt.DeviceInfo{
1191 Vendor: common.Config.Olt.Vendor,
1192 Model: common.Config.Olt.Model,
1193 HardwareVersion: common.Config.Olt.HardwareVersion,
1194 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1195 Technology: common.Config.Olt.Technology,
1196 PonPorts: uint32(o.NumPon),
1197 OnuIdStart: onuIdStart,
1198 OnuIdEnd: onuIdEnd,
1199 AllocIdStart: allocIdStart,
1200 AllocIdEnd: allocIdEnd,
1201 GemportIdStart: gemportIdStart,
1202 GemportIdEnd: gemportIdEnd,
1203 FlowIdStart: flowIdStart,
1204 FlowIdEnd: flowIdEnd,
1205 DeviceSerialNumber: o.SerialNumber,
1206 DeviceId: common.Config.Olt.DeviceId,
1207 PreviouslyConnected: o.PreviouslyConnected,
1208 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1209 {
1210 IntfIds: intfIDs,
1211 Technology: common.Config.Olt.Technology,
1212 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1213 {
1214 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1215 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1216 Start: onuIdStart,
1217 End: onuIdEnd,
1218 },
1219 {
1220 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1221 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1222 Start: allocIdStart,
1223 End: allocIdEnd,
1224 },
1225 {
1226 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1227 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1228 Start: gemportIdStart,
1229 End: gemportIdEnd,
1230 },
1231 {
1232 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1233 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1234 Start: flowIdStart,
1235 End: flowIdEnd,
1236 },
1237 },
1238 },
1239 },
1240 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001241
1242 oltLogger.WithFields(log.Fields{
1243 "Vendor": devinfo.Vendor,
1244 "Model": devinfo.Model,
1245 "HardwareVersion": devinfo.HardwareVersion,
1246 "FirmwareVersion": devinfo.FirmwareVersion,
1247 "Technology": devinfo.Technology,
1248 "PonPorts": devinfo.PonPorts,
1249 "OnuIdStart": devinfo.OnuIdStart,
1250 "OnuIdEnd": devinfo.OnuIdEnd,
1251 "AllocIdStart": devinfo.AllocIdStart,
1252 "AllocIdEnd": devinfo.AllocIdEnd,
1253 "GemportIdStart": devinfo.GemportIdStart,
1254 "GemportIdEnd": devinfo.GemportIdEnd,
1255 "FlowIdStart": devinfo.FlowIdStart,
1256 "FlowIdEnd": devinfo.FlowIdEnd,
1257 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1258 "DeviceId": devinfo.DeviceId,
1259 "PreviouslyConnected": devinfo.PreviouslyConnected,
1260 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1261
1262 // once we connect, set the flag
1263 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001264
1265 return devinfo, nil
1266}
1267
Shrey Baid688b4242020-07-10 20:40:10 +05301268func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001269 pon, err := o.GetPonById(omci_msg.IntfId)
1270 if err != nil {
1271 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001272 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001273 "onu_id": omci_msg.OnuId,
1274 "pon_id": omci_msg.IntfId,
1275 }).Error("pon ID not found")
1276 return nil, err
1277 }
1278
1279 onu, err := pon.GetOnuById(omci_msg.OnuId)
1280 if err != nil {
1281 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001282 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001283 "onu_id": omci_msg.OnuId,
1284 "pon_id": omci_msg.IntfId,
1285 }).Error("onu ID not found")
1286 return nil, err
1287 }
1288
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001289 oltLogger.WithFields(log.Fields{
1290 "IntfId": onu.PonPortID,
1291 "OnuId": onu.ID,
1292 "OnuSn": onu.Sn(),
1293 }).Tracef("Received OmciMsgOut")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001294 msg := types.Message{
1295 Type: types.OMCI,
1296 Data: types.OmciMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001297 OnuSN: onu.SerialNumber,
1298 OnuID: onu.ID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001299 OmciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001300 },
1301 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001302 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001303 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001304}
1305
Shrey Baid688b4242020-07-10 20:40:10 +05301306func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001307 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001308 if err != nil {
1309 oltLogger.WithFields(log.Fields{
1310 "OnuId": onuPkt.OnuId,
1311 "IntfId": onuPkt.IntfId,
1312 "err": err,
1313 }).Error("Can't find PonPort")
1314 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001315 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001316 if err != nil {
1317 oltLogger.WithFields(log.Fields{
1318 "OnuId": onuPkt.OnuId,
1319 "IntfId": onuPkt.IntfId,
1320 "err": err,
1321 }).Error("Can't find Onu")
1322 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001323
Matteo Scandolo075b1892019-10-07 12:11:07 -07001324 oltLogger.WithFields(log.Fields{
1325 "IntfId": onu.PonPortID,
1326 "OnuId": onu.ID,
1327 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001328 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001329 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001330
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001331 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001332
1333 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001334 if err != nil {
1335 onuLogger.WithFields(log.Fields{
1336 "IntfId": onu.PonPortID,
1337 "OnuId": onu.ID,
1338 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001339 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001340 }).Error("Can't find pktType in packet, droppint it")
1341 return new(openolt.Empty), nil
1342 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001343
Matteo Scandolo4a036262020-08-17 15:56:13 -07001344 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001345 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001346 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001347 "IntfId": onu.PonPortID,
1348 "OnuId": onu.ID,
1349 "OnuSn": onu.Sn(),
1350 "Pkt": rawpkt.Data(),
1351 }).Error("Can't find Dst MacAddress in packet, droppint it")
1352 return new(openolt.Empty), nil
1353 }
1354
Matteo Scandolof9d43412021-01-12 11:11:34 -08001355 msg := types.Message{
1356 Type: types.OnuPacketOut,
1357 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001358 IntfId: onuPkt.IntfId,
1359 OnuId: onuPkt.OnuId,
1360 Packet: rawpkt,
1361 Type: pktType,
1362 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001363 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001364 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001365
Matteo Scandolo075b1892019-10-07 12:11:07 -07001366 onu.Channel <- msg
1367
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001368 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001369}
1370
Shrey Baid688b4242020-07-10 20:40:10 +05301371func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001372
1373 // OLT Reboot is called in two cases:
1374 // - 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)
1375 // - when an OLT needs to be rebooted (voltcl device reboot)
1376
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001377 oltLogger.WithFields(log.Fields{
1378 "oltId": o.ID,
1379 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301380 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301381 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001382 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001383}
1384
Shrey Baid688b4242020-07-10 20:40:10 +05301385func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301386 oltLogger.WithFields(log.Fields{
1387 "oltId": o.ID,
1388 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301389 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301390
Pragya Arya2225f202020-01-29 18:05:01 +05301391 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001392 oltMsg := types.Message{
1393 Type: types.OltIndication,
1394 Data: types.OltIndicationMessage{
1395 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301396 },
Pragya Arya1881df02020-01-29 18:05:01 +05301397 }
Pragya Arya2225f202020-01-29 18:05:01 +05301398 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301399
Pragya Arya2225f202020-01-29 18:05:01 +05301400 for _, pon := range o.Pons {
1401 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001402 msg := types.Message{
1403 Type: types.PonIndication,
1404 Data: types.PonIndicationMessage{
1405 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301406 PonPortID: pon.ID,
1407 },
1408 }
1409 o.channel <- msg
1410 }
1411 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001412
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001413 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001414}
1415
Shrey Baid688b4242020-07-10 20:40:10 +05301416func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001417 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1418
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001419 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1420
1421 if err != nil {
1422 return nil, err
1423 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001424 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001425}
1426
Shrey Baid688b4242020-07-10 20:40:10 +05301427func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001428 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001429 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001430}
1431
Shrey Baid688b4242020-07-10 20:40:10 +05301432func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001433 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001434 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001435}
1436
Shrey Baid688b4242020-07-10 20:40:10 +05301437func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001438 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001439 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001440}
1441
Shrey Baid688b4242020-07-10 20:40:10 +05301442func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001443 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001444 return new(openolt.Empty), nil
1445}
1446
Shrey Baid688b4242020-07-10 20:40:10 +05301447func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001448 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001449 return new(openolt.Empty), nil
1450}
1451
Shrey Baid688b4242020-07-10 20:40:10 +05301452func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301453 oltLogger.WithFields(log.Fields{
1454 "OnuId": trafficSchedulers.OnuId,
1455 "IntfId": trafficSchedulers.IntfId,
1456 "OnuPortNo": trafficSchedulers.PortNo,
1457 }).Info("received CreateTrafficSchedulers")
1458
1459 if !s.enablePerf {
1460 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1461 if err != nil {
1462 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1463 return new(openolt.Empty), err
1464 }
1465 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1466 if err != nil {
1467 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1468 return new(openolt.Empty), err
1469 }
1470 onu.TrafficSchedulers = trafficSchedulers
1471 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001472 return new(openolt.Empty), nil
1473}
1474
Shrey Baid688b4242020-07-10 20:40:10 +05301475func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301476 oltLogger.WithFields(log.Fields{
1477 "OnuId": trafficSchedulers.OnuId,
1478 "IntfId": trafficSchedulers.IntfId,
1479 "OnuPortNo": trafficSchedulers.PortNo,
1480 }).Info("received RemoveTrafficSchedulers")
1481 if !s.enablePerf {
1482 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1483 if err != nil {
1484 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1485 return new(openolt.Empty), err
1486 }
1487 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1488 if err != nil {
1489 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1490 return new(openolt.Empty), err
1491 }
1492
1493 onu.TrafficSchedulers = nil
1494 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001495 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001496}
Scott Baker41724b82020-01-21 19:54:53 -08001497
Matteo Scandolo618a6582020-09-09 12:21:29 -07001498func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1499 oltLogger.WithFields(log.Fields{
1500 "GroupId": group.GroupId,
1501 "Command": group.Command,
1502 "Members": group.Members,
1503 "Action": group.Action,
1504 }).Debug("received PerformGroupOperation")
1505 return &openolt.Empty{}, nil
1506}
1507
1508func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1509 oltLogger.WithFields(log.Fields{
1510 "GroupId": group.GroupId,
1511 "Command": group.Command,
1512 "Members": group.Members,
1513 "Action": group.Action,
1514 }).Debug("received PerformGroupOperation")
1515 return &openolt.Empty{}, nil
1516}
1517
1518func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1519 return &common_protos.ReturnValues{}, nil
1520}
1521
1522func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1523 return &openolt.Empty{}, nil
1524}
1525
1526func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1527 return &openolt.OnuLogicalDistance{}, nil
1528}
1529
1530func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1531 return &openolt.OnuLogicalDistance{}, nil
1532}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001533
1534func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1535 return &openolt.GemPortStatistics{}, nil
1536}
1537
1538func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1539 return &openolt.OnuStatistics{}, nil
1540}