blob: 6540a56e69fe1081f1052066e13ba7b0e37cd566 [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 Scandoloe33447a2019-10-31 12:38:23 -070069
Matteo Scandolo27428702019-10-11 16:21:16 -070070 Pons []*PonPort
71 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070072
73 // OLT Attributes
74 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000075
76 enableContext context.Context
77 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053078
Matteo Scandolo4a036262020-08-17 15:56:13 -070079 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053080 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070081}
82
Matteo Scandolo27428702019-10-11 16:21:16 -070083var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -070084
Matteo Scandolo27428702019-10-11 16:21:16 -070085func GetOLT() *OltDevice {
86 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070087}
88
Matteo Scandolo4a036262020-08-17 15:56:13 -070089func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070090 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +053091 "ID": options.Olt.ID,
92 "NumNni": options.Olt.NniPorts,
93 "NumPon": options.Olt.PonPorts,
94 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -070095 }).Debug("CreateOLT")
96
Matteo Scandolo84f7d482019-08-08 19:00:47 -070097 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +053098 ID: options.Olt.ID,
99 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700100 OperState: getOperStateFSM(func(e *fsm.Event) {
101 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
102 }),
Pragya Arya996a0892020-03-09 21:47:52 +0530103 NumNni: int(options.Olt.NniPorts),
104 NumPon: int(options.Olt.PonPorts),
105 NumOnuPerPon: int(options.Olt.OnusPonPort),
106 Pons: []*PonPort{},
107 Nnis: []*NniPort{},
108 Delay: options.BBSim.Delay,
Pragya Arya996a0892020-03-09 21:47:52 +0530109 enablePerf: options.BBSim.EnablePerf,
110 PublishEvents: options.BBSim.Events,
111 PortStatsInterval: options.Olt.PortStatsInterval,
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700112 dhcpServer: dhcp.NewDHCPServer(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700113 }
114
Pragya Arya996a0892020-03-09 21:47:52 +0530115 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530116 olt.ControlledActivation = val
117 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700118 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530119 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
120 olt.ControlledActivation = Default
121 }
122
Matteo Scandolo4747d292019-08-05 11:50:18 -0700123 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700124 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700125 olt.InternalState = fsm.NewFSM(
126 "created",
127 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800128 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100129 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700130 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700131 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800132 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700133 },
134 fsm.Callbacks{
135 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700136 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700137 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100138 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700139 },
140 )
141
Shrey Baid688b4242020-07-10 20:40:10 +0530142 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700143 // create NNI Port
144 nniPort, err := CreateNNI(&olt)
145 if err != nil {
146 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
147 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700148
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700149 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700151
Matteo Scandolo4a036262020-08-17 15:56:13 -0700152 // Create device and Services
153
154 nextCtag := map[string]int{}
155 nextStag := map[string]int{}
156
Matteo Scandolo4747d292019-08-05 11:50:18 -0700157 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700158 for i := 0; i < olt.NumPon; i++ {
159 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700160
Matteo Scandolo4a036262020-08-17 15:56:13 -0700161 // create ONU devices
162 for j := 0; j < olt.NumOnuPerPon; j++ {
163 delay := time.Duration(olt.Delay*j) * time.Millisecond
164 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700165
Matteo Scandolo4a036262020-08-17 15:56:13 -0700166 for k, s := range common.Services {
167
168 // find the correct cTag for this service
169 if _, ok := nextCtag[s.Name]; !ok {
170 // it's the first time we iterate over this service,
171 // so we start from the config value
172 nextCtag[s.Name] = s.CTag
173 } else {
174 // we have a previous value, so we check it
175 // if Allocation is unique, we increment,
176 // otherwise (shared) we do nothing
177 if s.CTagAllocation == common.TagAllocationUnique.String() {
178 nextCtag[s.Name] = nextCtag[s.Name] + 1
179 }
180 }
181
182 // find the correct sTag for this service
183 if _, ok := nextStag[s.Name]; !ok {
184 nextStag[s.Name] = s.STag
185 } else {
186 if s.STagAllocation == common.TagAllocationUnique.String() {
187 nextStag[s.Name] = nextStag[s.Name] + 1
188 }
189 }
190
191 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
192 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
193 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
194 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
195
196 if err != nil {
197 oltLogger.WithFields(log.Fields{
198 "Err": err.Error(),
199 }).Fatal("Can't create Service")
200 }
201
202 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700203 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700204 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700205 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700206 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700207 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100208
Shrey Baid688b4242020-07-10 20:40:10 +0530209 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700210 if err := olt.InternalState.Event("initialize"); err != nil {
211 log.Errorf("Error initializing OLT: %v", err)
212 return nil
213 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100214 }
215
Pragya Arya324337e2020-02-20 14:35:08 +0530216 if olt.PublishEvents {
217 log.Debugf("BBSim event publishing is enabled")
218 // Create a channel to write event messages
219 olt.EventChannel = make(chan common.Event, 100)
220 }
221
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700222 return &olt
223}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700224
Shrey Baid688b4242020-07-10 20:40:10 +0530225func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100226
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800227 if o.oltServer == nil {
228 o.oltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100229 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800230 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231 }
232
233 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800234 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100235
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100236 // FIXME we are assuming we have only one NNI
237 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800238 // NOTE we want to make sure the state is down when we initialize the OLT,
239 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
240 // in-band management
241 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100242 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700243}
244
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800245func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100246
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700247 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700248 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800249
250 oltLogger.WithFields(log.Fields{
251 "oltId": o.ID,
252 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
253
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700254 if o.InternalState.Is("enabled") {
255 oltLogger.WithFields(log.Fields{
256 "oltId": o.ID,
257 }).Info("This is an OLT soft reboot")
258 softReboot = true
259 }
260
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800261 // transition internal state to deleted
262 if err := o.InternalState.Event("delete"); err != nil {
263 oltLogger.WithFields(log.Fields{
264 "oltId": o.ID,
265 }).Errorf("Error deleting OLT: %v", err)
266 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100267 }
268
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800269 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 -0800270 o.StopOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100271
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700272 if softReboot {
273 for _, pon := range o.Pons {
274 if pon.InternalState.Current() == "enabled" {
275 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800276 msg := types.Message{
277 Type: types.PonIndication,
278 Data: types.PonIndicationMessage{
279 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700280 PonPortID: pon.ID,
281 },
282 }
283 o.channel <- msg
284 }
285
286 for _, onu := range pon.Onus {
287 _ = onu.InternalState.Event("disable")
288 }
289 }
290 } else {
291 // PONs are already handled in the Disable call
292 for _, pon := range olt.Pons {
293 // ONUs are not automatically disabled when a PON goes down
294 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
295 for _, onu := range pon.Onus {
296 _ = onu.InternalState.Event("disable")
297 }
Pragya Arya2225f202020-01-29 18:05:01 +0530298 }
299 }
300
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100301 // terminate the OLT's processOltMessages go routine
302 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700303
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700304 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100305
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100306 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100307
308 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800309 oltLogger.WithFields(log.Fields{
310 "oltId": o.ID,
311 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100312 return err
313 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800314 oltLogger.WithFields(log.Fields{
315 "oltId": o.ID,
316 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100317 return nil
318}
319
320// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800321func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700322 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700323 lis, err := net.Listen("tcp", address)
324 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700325 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700326 }
327 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100328
Matteo Scandolo4747d292019-08-05 11:50:18 -0700329 openolt.RegisterOpenoltServer(grpcServer, o)
330
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100331 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700332
Shrey Baid688b4242020-07-10 20:40:10 +0530333 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100334 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700335
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100336 return grpcServer, nil
337}
338
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800339// StartOltServer will create the grpc server that VOLTHA uses
340// to communicate with the device
341func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
342 oltServer, err := o.newOltServer()
343 if err != nil {
344 oltLogger.WithFields(log.Fields{
345 "err": err,
346 }).Error("Cannot OLT gRPC server")
347 return nil, err
348 }
349 return oltServer, nil
350}
351
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100352// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800353func (o *OltDevice) StopOltServer() {
354 if o.oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800355 oltLogger.WithFields(log.Fields{
356 "oltId": o.SerialNumber,
357 }).Warnf("Stopping OLT gRPC server")
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800358 o.oltServer.Stop()
359 o.oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700360 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700361}
362
363// Device Methods
364
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100365// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530366func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700367 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530368 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700369
David Bainbridge103cf022019-12-16 20:11:35 +0000370 // If enabled has already been called then an enabled context has
371 // been created. If this is the case then we want to cancel all the
372 // proessing loops associated with that enable before we recreate
373 // new ones
374 o.Lock()
375 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700376 oltLogger.Info("This is an OLT reboot")
David Bainbridge103cf022019-12-16 20:11:35 +0000377 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530378 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000379 }
380 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
381 o.Unlock()
382
Matteo Scandolo4747d292019-08-05 11:50:18 -0700383 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800384 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700385
Matteo Scandolo4a036262020-08-17 15:56:13 -0700386 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530387
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100388 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000389 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700390
391 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800392 oltMsg := types.Message{
393 Type: types.OltIndication,
394 Data: types.OltIndicationMessage{
395 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700396 },
397 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100398 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700399
400 // send NNI Port Indications
401 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800402 msg := types.Message{
403 Type: types.NniIndication,
404 Data: types.NniIndicationMessage{
405 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700406 NniPortID: nni.ID,
407 },
408 }
409 o.channel <- msg
410 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100411
Shrey Baid688b4242020-07-10 20:40:10 +0530412 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530413 for _, pon := range o.Pons {
414 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800415 msg := types.Message{
416 Type: types.PonIndication,
417 Data: types.PonIndicationMessage{
418 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530419 PonPortID: pon.ID,
420 },
421 }
422 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000423 }
Pragya Arya2225f202020-01-29 18:05:01 +0530424 }
425 } else {
426
427 // 1. controlledActivation == Default: Send both PON and ONUs indications
428 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
429
430 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
431 // send PON Port indications
432 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800433 msg := types.Message{
434 Type: types.PonIndication,
435 Data: types.PonIndicationMessage{
436 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530437 PonPortID: pon.ID,
438 },
439 }
440 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700441 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700442 }
443 }
444
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800445 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530446
447 if !o.enablePerf {
448 // Start a go routine to send periodic port stats to openolt adapter
449 go o.periodicPortStats(o.enableContext)
450 }
451
Matteo Scandolo4747d292019-08-05 11:50:18 -0700452 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700453}
454
Pragya Arya996a0892020-03-09 21:47:52 +0530455func (o *OltDevice) periodicPortStats(ctx context.Context) {
456 var portStats *openolt.PortStatistics
457 for {
458 select {
459 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
460 // send NNI port stats
461 for _, port := range o.Nnis {
462 incrementStat := true
463 if port.OperState.Current() == "down" {
464 incrementStat = false
465 }
466 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
467 o.sendPortStatsIndication(portStats, port.ID, port.Type)
468 }
469
470 // send PON port stats
471 for _, port := range o.Pons {
472 incrementStat := true
473 // do not increment port stats if PON port is down or no ONU is activated on PON port
474 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
475 incrementStat = false
476 }
477 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
478 o.sendPortStatsIndication(portStats, port.ID, port.Type)
479 }
480 case <-ctx.Done():
481 log.Debug("Stop sending port stats")
482 return
483 }
484
485 }
486}
487
Matteo Scandolo4747d292019-08-05 11:50:18 -0700488// Helpers method
489
Matteo Scandolof9d43412021-01-12 11:11:34 -0800490func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
491
492 switch interfaceType {
493 case "nni":
494 if !o.HasNni(interfaceId) {
495 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
496 }
497
498 case "pon":
499 if !o.HasPon(interfaceId) {
500 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
501 }
502 }
503
504 alarmIndication := &openolt.AlarmIndication{
505 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
506 Status: alarmStatus,
507 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
508 }},
509 }
510
511 msg := types.Message{
512 Type: types.AlarmIndication,
513 Data: alarmIndication,
514 }
515
516 o.channel <- msg
517
518 return nil
519}
520
521func (o *OltDevice) HasNni(id uint32) bool {
522 for _, intf := range o.Nnis {
523 if intf.ID == id {
524 return true
525 }
526 }
527 return false
528}
529
530func (o *OltDevice) HasPon(id uint32) bool {
531 for _, intf := range o.Pons {
532 if intf.ID == id {
533 return true
534 }
535 }
536 return false
537}
538
Shrey Baid688b4242020-07-10 20:40:10 +0530539func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700540 for _, pon := range o.Pons {
541 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700542 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700543 }
544 }
Shrey Baid688b4242020-07-10 20:40:10 +0530545 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700546}
547
Shrey Baid688b4242020-07-10 20:40:10 +0530548func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700549 for _, nni := range o.Nnis {
550 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700551 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700552 }
553 }
Shrey Baid688b4242020-07-10 20:40:10 +0530554 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700555}
556
Scott Baker41724b82020-01-21 19:54:53 -0800557func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
558 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
559 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
560 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
561 return
562 }
563
564 oltLogger.WithFields(log.Fields{
565 "AlarmIndication": alarmInd,
566 }).Debug("Sent Indication_AlarmInd")
567}
568
Matteo Scandolof9d43412021-01-12 11:11:34 -0800569func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700570 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
571 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700572 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800573 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700574 }
575
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700576 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700577 "OperState": msg.OperState,
578 }).Debug("Sent Indication_OltInd")
579}
580
Matteo Scandolof9d43412021-01-12 11:11:34 -0800581func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700582 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800583 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800584 if err := nni.OperState.Event("enable"); err != nil {
585 log.WithFields(log.Fields{
586 "Type": nni.Type,
587 "IntfId": nni.ID,
588 "OperState": nni.OperState.Current(),
589 }).Errorf("Can't move NNI Port to enabled state: %v", err)
590 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800591 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800592 if err := nni.OperState.Event("disable"); err != nil {
593 log.WithFields(log.Fields{
594 "Type": nni.Type,
595 "IntfId": nni.ID,
596 "OperState": nni.OperState.Current(),
597 }).Errorf("Can't move NNI Port to disable state: %v", err)
598 }
599 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700600 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700601 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700602 Type: nni.Type,
603 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700604 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700605 }}
606
607 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700608 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800609 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700610 }
611
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700612 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700613 "Type": nni.Type,
614 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700615 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700616 }).Debug("Sent Indication_IntfOperInd for NNI")
617}
618
Pragya Arya2225f202020-01-29 18:05:01 +0530619func (o *OltDevice) sendPonIndication(ponPortID uint32) {
620
Matteo Scandolo4a036262020-08-17 15:56:13 -0700621 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530622 pon, _ := o.GetPonById(ponPortID)
623 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700624 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700625 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700626 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700627 }}
628
629 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700630 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800631 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700632 }
633
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700634 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700635 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700636 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700637 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700638
Pragya Arya2225f202020-01-29 18:05:01 +0530639 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700640 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700641 Type: pon.Type,
642 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700643 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 }}
645
646 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700647 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800648 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700649 }
650
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700651 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700652 "Type": pon.Type,
653 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700654 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655 }).Debug("Sent Indication_IntfOperInd for PON")
656}
657
Pragya Arya996a0892020-03-09 21:47:52 +0530658func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530659 if o.InternalState.Current() == "enabled" {
660 oltLogger.WithFields(log.Fields{
661 "Type": portType,
662 "IntfId": portID,
663 }).Trace("Sending port stats")
664 stats.IntfId = InterfaceIDToPortNo(portID, portType)
665 data := &openolt.Indication_PortStats{
666 PortStats: stats,
667 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700668 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530669 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
670 oltLogger.Errorf("Failed to send PortStats: %v", err)
671 return
672 }
Pragya Arya996a0892020-03-09 21:47:52 +0530673 }
674}
675
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100676// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000677func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100678 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000679 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700680
David Bainbridge103cf022019-12-16 20:11:35 +0000681loop:
682 for {
683 select {
684 case <-ctx.Done():
685 oltLogger.Debug("OLT Indication processing canceled via context")
686 break loop
687 case message, ok := <-ch:
688 if !ok || ctx.Err() != nil {
689 oltLogger.Debug("OLT Indication processing canceled via closed channel")
690 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700691 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700692
David Bainbridge103cf022019-12-16 20:11:35 +0000693 oltLogger.WithFields(log.Fields{
694 "oltId": o.ID,
695 "messageType": message.Type,
696 }).Trace("Received message")
697
698 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800699 case types.OltIndication:
700 msg, _ := message.Data.(types.OltIndicationMessage)
701 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530702 _ = o.InternalState.Event("enable")
703 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800704 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530705 _ = o.InternalState.Event("disable")
706 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000707 }
708 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800709 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800710 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
711 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800712 case types.NniIndication:
713 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000714 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800715 case types.PonIndication:
716 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530717 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800718 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530719 if err := pon.OperState.Event("enable"); err != nil {
720 oltLogger.WithFields(log.Fields{
721 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800722 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530723 }).Error("Can't Enable Oper state for PON Port")
724 }
725 if err := pon.InternalState.Event("enable"); err != nil {
726 oltLogger.WithFields(log.Fields{
727 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800728 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530729 }).Error("Can't Enable Internal state for PON Port")
730 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800731 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530732 if err := pon.OperState.Event("disable"); err != nil {
733 oltLogger.WithFields(log.Fields{
734 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800735 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530736 }).Error("Can't Disable Oper state for PON Port")
737 }
738 if err := pon.InternalState.Event("disable"); err != nil {
739 oltLogger.WithFields(log.Fields{
740 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800741 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530742 }).Error("Can't Disable Internal state for PON Port")
743 }
Pragya Arya2225f202020-01-29 18:05:01 +0530744 }
David Bainbridge103cf022019-12-16 20:11:35 +0000745 default:
746 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
747 }
748 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700749 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100750 wg.Done()
751 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700752}
753
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700754// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530755func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200756 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700757 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700758 for _, pon := range o.Pons {
759 for _, onu := range pon.Onus {
760 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700761 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700762 }
763 }
764 }
765
Shrey Baid688b4242020-07-10 20:40:10 +0530766 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700767}
768
William Kurkian9dadc5b2019-10-22 13:51:57 -0400769// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530770func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200771 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400772 // memoizing it will remove the bottleneck
773 for _, pon := range o.Pons {
774 if pon.ID == intfId {
775 for _, onu := range pon.Onus {
776 if onu.ID == onuId {
777 return onu, nil
778 }
779 }
780 }
781 }
Shrey Baid688b4242020-07-10 20:40:10 +0530782 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400783}
784
Matteo Scandolo4a036262020-08-17 15:56:13 -0700785// returns a Service with a given Mac Address
786func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200787 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700788 // memoizing it will remove the bottleneck
789 for _, pon := range o.Pons {
790 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700791 s, err := onu.findServiceByMacAddress(mac)
792 if err == nil {
793 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700794 }
795 }
796 }
797
Matteo Scandolo4a036262020-08-17 15:56:13 -0700798 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700799}
800
Matteo Scandolo4747d292019-08-05 11:50:18 -0700801// GRPC Endpoints
802
Shrey Baid688b4242020-07-10 20:40:10 +0530803func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700804 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700805 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700806 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530807 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700808
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700809 pon, _ := o.GetPonById(onu.IntfId)
810 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500811 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700812
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700813 if err := _onu.OperState.Event("enable"); err != nil {
814 oltLogger.WithFields(log.Fields{
815 "IntfId": _onu.PonPortID,
816 "OnuSn": _onu.Sn(),
817 "OnuId": _onu.ID,
818 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700819 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700820 if err := _onu.InternalState.Event("enable"); err != nil {
821 oltLogger.WithFields(log.Fields{
822 "IntfId": _onu.PonPortID,
823 "OnuSn": _onu.Sn(),
824 "OnuId": _onu.ID,
825 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
826 }
827
828 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
829
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700830 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700831}
832
Shrey Baid688b4242020-07-10 20:40:10 +0530833func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700834 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700835 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700836}
837
Shrey Baid688b4242020-07-10 20:40:10 +0530838func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530839 oltLogger.WithFields(log.Fields{
840 "IntfId": onu.IntfId,
841 "OnuId": onu.OnuId,
842 }).Info("Received DeleteOnu call from VOLTHA")
843
844 pon, err := o.GetPonById(onu.IntfId)
845 if err != nil {
846 oltLogger.WithFields(log.Fields{
847 "OnuId": onu.OnuId,
848 "IntfId": onu.IntfId,
849 "err": err,
850 }).Error("Can't find PonPort")
851 }
852 _onu, err := pon.GetOnuById(onu.OnuId)
853 if err != nil {
854 oltLogger.WithFields(log.Fields{
855 "OnuId": onu.OnuId,
856 "IntfId": onu.IntfId,
857 "err": err,
858 }).Error("Can't find Onu")
859 }
860
Hardik Windlassad790cb2020-06-17 21:26:22 +0530861 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530862 oltLogger.WithFields(log.Fields{
863 "IntfId": _onu.PonPortID,
864 "OnuSn": _onu.Sn(),
865 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530866 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
867 }
868
Hardik Windlassad790cb2020-06-17 21:26:22 +0530869 // ONU Re-Discovery
870 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530871 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530872 }
873
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700874 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700875}
876
Shrey Baid688b4242020-07-10 20:40:10 +0530877func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700878 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800879 oltLogger.WithFields(log.Fields{
880 "oltId": o.ID,
881 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530882 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800883
Matteo Scandolo401503a2019-12-11 14:48:14 -0800884 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530885 if pon.InternalState.Current() == "enabled" {
886 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800887 msg := types.Message{
888 Type: types.PonIndication,
889 Data: types.PonIndicationMessage{
890 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530891 PonPortID: pon.ID,
892 },
893 }
894 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800895 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800896 }
897
Matteo Scandolo401503a2019-12-11 14:48:14 -0800898 // Note that we are not disabling the NNI as the real OLT does not.
899 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800900
901 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800902 oltMsg := types.Message{
903 Type: types.OltIndication,
904 Data: types.OltIndicationMessage{
905 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700906 },
907 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100908 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700909 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700910}
911
Shrey Baid688b4242020-07-10 20:40:10 +0530912func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530913 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200914 ponID := intf.GetIntfId()
915 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200916
Matteo Scandolof9d43412021-01-12 11:11:34 -0800917 msg := types.Message{
918 Type: types.PonIndication,
919 Data: types.PonIndicationMessage{
920 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200921 PonPortID: ponID,
922 },
923 }
924 o.channel <- msg
925
926 for _, onu := range pon.Onus {
927
Matteo Scandolof9d43412021-01-12 11:11:34 -0800928 onuIndication := types.OnuIndicationMessage{
929 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200930 PonPortID: ponID,
931 OnuID: onu.ID,
932 OnuSN: onu.SerialNumber,
933 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700934 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200935
936 }
937
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700938 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700939}
940
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100941func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700942 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530943 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700944 o.Enable(stream)
945 return nil
946}
947
Shrey Baid688b4242020-07-10 20:40:10 +0530948func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530949 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530950 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200951 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200952
Matteo Scandolof9d43412021-01-12 11:11:34 -0800953 msg := types.Message{
954 Type: types.PonIndication,
955 Data: types.PonIndicationMessage{
956 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530957 PonPortID: ponID,
958 },
959 }
960 o.channel <- msg
961
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200962 for _, onu := range pon.Onus {
963
Matteo Scandolof9d43412021-01-12 11:11:34 -0800964 onuIndication := types.OnuIndicationMessage{
965 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200966 PonPortID: ponID,
967 OnuID: onu.ID,
968 OnuSN: onu.SerialNumber,
969 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700970 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200971
972 }
973
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700974 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700975}
976
Shrey Baid688b4242020-07-10 20:40:10 +0530977func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700978 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700979 "IntfId": flow.AccessIntfId,
980 "OnuId": flow.OnuId,
981 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700982 "InnerVlan": flow.Classifier.IVid,
983 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700984 "FlowType": flow.FlowType,
985 "FlowId": flow.FlowId,
986 "UniID": flow.UniId,
987 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +0530988 }).Tracef("OLT receives FlowAdd")
989
990 flowKey := FlowKey{}
991 if !o.enablePerf {
992 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +0100993 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +0530994 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700995
996 if flow.AccessIntfId == -1 {
997 oltLogger.WithFields(log.Fields{
998 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700999 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001000 } else if flow.FlowType == "multicast" {
1001 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001002 "Cookie": flow.Cookie,
1003 "DstPort": flow.Classifier.DstPort,
1004 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1005 "FlowId": flow.FlowId,
1006 "FlowType": flow.FlowType,
1007 "GemportId": flow.GemportId,
1008 "InnerVlan": flow.Classifier.IVid,
1009 "IntfId": flow.AccessIntfId,
1010 "IpProto": flow.Classifier.IpProto,
1011 "OnuId": flow.OnuId,
1012 "OuterVlan": flow.Classifier.OVid,
1013 "PortNo": flow.PortNo,
1014 "SrcPort": flow.Classifier.SrcPort,
1015 "UniID": flow.UniId,
1016 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001017 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001018 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001019 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001020 if err != nil {
1021 oltLogger.WithFields(log.Fields{
1022 "OnuId": flow.OnuId,
1023 "IntfId": flow.AccessIntfId,
1024 "err": err,
1025 }).Error("Can't find PonPort")
1026 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001027 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001028 if err != nil {
1029 oltLogger.WithFields(log.Fields{
1030 "OnuId": flow.OnuId,
1031 "IntfId": flow.AccessIntfId,
1032 "err": err,
1033 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001034 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001035 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301036 if !o.enablePerf {
1037 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301038 // Generate event on first flow for ONU
1039 if len(onu.Flows) == 1 {
1040 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1041 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301042 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001043
Matteo Scandolof9d43412021-01-12 11:11:34 -08001044 msg := types.Message{
1045 Type: types.FlowAdd,
1046 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001047 PonPortID: pon.ID,
1048 OnuID: onu.ID,
1049 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001050 },
1051 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001052 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001053 }
1054
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001055 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001056}
1057
Pragya Arya8bdb4532020-03-02 17:08:09 +05301058// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301059func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001060
Pragya Arya8bdb4532020-03-02 17:08:09 +05301061 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301062 "FlowId": flow.FlowId,
1063 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001064 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301065
1066 if !o.enablePerf { // remove only if flow were stored
1067 flowKey := FlowKey{
1068 ID: flow.FlowId,
1069 Direction: flow.FlowType,
1070 }
1071
1072 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001073 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301074 if !ok {
1075 oltLogger.Errorf("Flow %v not found", flow)
1076 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1077 }
1078
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001079 storedFlow := storedFlowIntf.(openolt.Flow)
1080
Pragya Arya8bdb4532020-03-02 17:08:09 +05301081 // if its ONU flow remove it from ONU also
1082 if storedFlow.AccessIntfId != -1 {
1083 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1084 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1085 if err != nil {
1086 oltLogger.WithFields(log.Fields{
1087 "OnuId": storedFlow.OnuId,
1088 "IntfId": storedFlow.AccessIntfId,
1089 "err": err,
1090 }).Error("ONU not found")
1091 return new(openolt.Empty), nil
1092 }
1093 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301094 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301095 }
1096
1097 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001098 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301099 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001100
1101 if flow.AccessIntfId == -1 {
1102 oltLogger.WithFields(log.Fields{
1103 "FlowId": flow.FlowId,
1104 }).Debug("Removing OLT flow")
1105 } else if flow.FlowType == "multicast" {
1106 oltLogger.WithFields(log.Fields{
1107 "FlowId": flow.FlowId,
1108 }).Debug("Removing OLT multicast flow")
1109 } else {
1110
1111 onu, err := o.GetOnuByFlowId(flow.FlowId)
1112 if err != nil {
1113 oltLogger.WithFields(log.Fields{
1114 "OnuId": flow.OnuId,
1115 "IntfId": flow.AccessIntfId,
1116 "err": err,
1117 }).Error("Can't find Onu")
1118 return nil, err
1119 }
1120
Matteo Scandolof9d43412021-01-12 11:11:34 -08001121 msg := types.Message{
1122 Type: types.FlowRemoved,
1123 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301124 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001125 },
1126 }
1127 onu.Channel <- msg
1128 }
1129
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001130 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001131}
1132
Shrey Baid688b4242020-07-10 20:40:10 +05301133func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001134 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1135 oltLogger.WithFields(log.Fields{
1136 "signature": res.HeartbeatSignature,
1137 }).Trace("HeartbeatCheck")
1138 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001139}
1140
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001141func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001142 for _, pon := range o.Pons {
1143 for _, onu := range pon.Onus {
1144 for _, fId := range onu.FlowIds {
1145 if fId == flowId {
1146 return onu, nil
1147 }
1148 }
1149 }
1150 }
Shrey Baid688b4242020-07-10 20:40:10 +05301151 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001152}
1153
Shrey Baid688b4242020-07-10 20:40:10 +05301154func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001155
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001156 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001157 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001158 "PonPorts": o.NumPon,
1159 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
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 Scandolo4747d292019-08-05 11:50:18 -07001177
1178 return devinfo, nil
1179}
1180
Shrey Baid688b4242020-07-10 20:40:10 +05301181func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001182 pon, err := o.GetPonById(omci_msg.IntfId)
1183 if err != nil {
1184 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001185 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001186 "onu_id": omci_msg.OnuId,
1187 "pon_id": omci_msg.IntfId,
1188 }).Error("pon ID not found")
1189 return nil, err
1190 }
1191
1192 onu, err := pon.GetOnuById(omci_msg.OnuId)
1193 if err != nil {
1194 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001195 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001196 "onu_id": omci_msg.OnuId,
1197 "pon_id": omci_msg.IntfId,
1198 }).Error("onu ID not found")
1199 return nil, err
1200 }
1201
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001202 oltLogger.WithFields(log.Fields{
1203 "IntfId": onu.PonPortID,
1204 "OnuId": onu.ID,
1205 "OnuSn": onu.Sn(),
1206 }).Tracef("Received OmciMsgOut")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001207 msg := types.Message{
1208 Type: types.OMCI,
1209 Data: types.OmciMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001210 OnuSN: onu.SerialNumber,
1211 OnuID: onu.ID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001212 OmciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001213 },
1214 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001215 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001216 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001217}
1218
Shrey Baid688b4242020-07-10 20:40:10 +05301219func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001220 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001221 if err != nil {
1222 oltLogger.WithFields(log.Fields{
1223 "OnuId": onuPkt.OnuId,
1224 "IntfId": onuPkt.IntfId,
1225 "err": err,
1226 }).Error("Can't find PonPort")
1227 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001228 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001229 if err != nil {
1230 oltLogger.WithFields(log.Fields{
1231 "OnuId": onuPkt.OnuId,
1232 "IntfId": onuPkt.IntfId,
1233 "err": err,
1234 }).Error("Can't find Onu")
1235 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001236
Matteo Scandolo075b1892019-10-07 12:11:07 -07001237 oltLogger.WithFields(log.Fields{
1238 "IntfId": onu.PonPortID,
1239 "OnuId": onu.ID,
1240 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001241 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001242 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001243
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001244 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001245
1246 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001247 if err != nil {
1248 onuLogger.WithFields(log.Fields{
1249 "IntfId": onu.PonPortID,
1250 "OnuId": onu.ID,
1251 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001252 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001253 }).Error("Can't find pktType in packet, droppint it")
1254 return new(openolt.Empty), nil
1255 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001256
Matteo Scandolo4a036262020-08-17 15:56:13 -07001257 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001258 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001259 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001260 "IntfId": onu.PonPortID,
1261 "OnuId": onu.ID,
1262 "OnuSn": onu.Sn(),
1263 "Pkt": rawpkt.Data(),
1264 }).Error("Can't find Dst MacAddress in packet, droppint it")
1265 return new(openolt.Empty), nil
1266 }
1267
Matteo Scandolof9d43412021-01-12 11:11:34 -08001268 msg := types.Message{
1269 Type: types.OnuPacketOut,
1270 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001271 IntfId: onuPkt.IntfId,
1272 OnuId: onuPkt.OnuId,
1273 Packet: rawpkt,
1274 Type: pktType,
1275 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001276 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001277 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001278
Matteo Scandolo075b1892019-10-07 12:11:07 -07001279 onu.Channel <- msg
1280
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001281 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001282}
1283
Shrey Baid688b4242020-07-10 20:40:10 +05301284func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001285
1286 // OLT Reboot is called in two cases:
1287 // - 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)
1288 // - when an OLT needs to be rebooted (voltcl device reboot)
1289
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001290 oltLogger.WithFields(log.Fields{
1291 "oltId": o.ID,
1292 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301293 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301294 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001295 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001296}
1297
Shrey Baid688b4242020-07-10 20:40:10 +05301298func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301299 oltLogger.WithFields(log.Fields{
1300 "oltId": o.ID,
1301 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301302 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301303
Pragya Arya2225f202020-01-29 18:05:01 +05301304 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001305 oltMsg := types.Message{
1306 Type: types.OltIndication,
1307 Data: types.OltIndicationMessage{
1308 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301309 },
Pragya Arya1881df02020-01-29 18:05:01 +05301310 }
Pragya Arya2225f202020-01-29 18:05:01 +05301311 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301312
Pragya Arya2225f202020-01-29 18:05:01 +05301313 for _, pon := range o.Pons {
1314 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001315 msg := types.Message{
1316 Type: types.PonIndication,
1317 Data: types.PonIndicationMessage{
1318 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301319 PonPortID: pon.ID,
1320 },
1321 }
1322 o.channel <- msg
1323 }
1324 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001325
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001326 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001327}
1328
Shrey Baid688b4242020-07-10 20:40:10 +05301329func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001330 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1331
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001332 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1333
1334 if err != nil {
1335 return nil, err
1336 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001337 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001338}
1339
Shrey Baid688b4242020-07-10 20:40:10 +05301340func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001341 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001342 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001343}
1344
Shrey Baid688b4242020-07-10 20:40:10 +05301345func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001346 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001347 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001348}
1349
Shrey Baid688b4242020-07-10 20:40:10 +05301350func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001351 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001352 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001353}
1354
Shrey Baid688b4242020-07-10 20:40:10 +05301355func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001356 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001357 return new(openolt.Empty), nil
1358}
1359
Shrey Baid688b4242020-07-10 20:40:10 +05301360func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001361 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001362 return new(openolt.Empty), nil
1363}
1364
Shrey Baid688b4242020-07-10 20:40:10 +05301365func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301366 oltLogger.WithFields(log.Fields{
1367 "OnuId": trafficSchedulers.OnuId,
1368 "IntfId": trafficSchedulers.IntfId,
1369 "OnuPortNo": trafficSchedulers.PortNo,
1370 }).Info("received CreateTrafficSchedulers")
1371
1372 if !s.enablePerf {
1373 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1374 if err != nil {
1375 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1376 return new(openolt.Empty), err
1377 }
1378 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1379 if err != nil {
1380 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1381 return new(openolt.Empty), err
1382 }
1383 onu.TrafficSchedulers = trafficSchedulers
1384 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001385 return new(openolt.Empty), nil
1386}
1387
Shrey Baid688b4242020-07-10 20:40:10 +05301388func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301389 oltLogger.WithFields(log.Fields{
1390 "OnuId": trafficSchedulers.OnuId,
1391 "IntfId": trafficSchedulers.IntfId,
1392 "OnuPortNo": trafficSchedulers.PortNo,
1393 }).Info("received RemoveTrafficSchedulers")
1394 if !s.enablePerf {
1395 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1396 if err != nil {
1397 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1398 return new(openolt.Empty), err
1399 }
1400 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1401 if err != nil {
1402 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1403 return new(openolt.Empty), err
1404 }
1405
1406 onu.TrafficSchedulers = nil
1407 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001408 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001409}
Scott Baker41724b82020-01-21 19:54:53 -08001410
Matteo Scandolo618a6582020-09-09 12:21:29 -07001411func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1412 oltLogger.WithFields(log.Fields{
1413 "GroupId": group.GroupId,
1414 "Command": group.Command,
1415 "Members": group.Members,
1416 "Action": group.Action,
1417 }).Debug("received PerformGroupOperation")
1418 return &openolt.Empty{}, nil
1419}
1420
1421func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1422 oltLogger.WithFields(log.Fields{
1423 "GroupId": group.GroupId,
1424 "Command": group.Command,
1425 "Members": group.Members,
1426 "Action": group.Action,
1427 }).Debug("received PerformGroupOperation")
1428 return &openolt.Empty{}, nil
1429}
1430
1431func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1432 return &common_protos.ReturnValues{}, nil
1433}
1434
1435func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1436 return &openolt.Empty{}, nil
1437}
1438
1439func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1440 return &openolt.OnuLogicalDistance{}, nil
1441}
1442
1443func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1444 return &openolt.OnuLogicalDistance{}, nil
1445}