blob: 9e26ad2dedf5e4a176c08e5e501c89971accf366 [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 Scandolo4f4ac792020-10-01 16:33:21 -070024 "github.com/opencord/voltha-protos/v4/go/ext/config"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020025 "net"
26 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010027 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020028
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070029 "github.com/google/gopacket"
30 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070031 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070032 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010033 "github.com/opencord/bbsim/internal/common"
William Kurkian9dadc5b2019-10-22 13:51:57 -040034 omcisim "github.com/opencord/omci-sim"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070035 common_protos "github.com/opencord/voltha-protos/v4/go/common"
36 "github.com/opencord/voltha-protos/v4/go/openolt"
37 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070038 log "github.com/sirupsen/logrus"
39 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053040 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010041 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053042 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070043)
44
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070045var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070046 "module": "OLT",
47})
48
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070049type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000050 sync.Mutex
Matteo Scandolo88c204a2020-11-03 10:34:24 -080051 oltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000052
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070053 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053054 ID int
55 SerialNumber string
56 NumNni int
57 NumPon int
58 NumOnuPerPon int
59 InternalState *fsm.FSM
60 channel chan Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070061 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010062 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053063 Delay int
64 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053065 EventChannel chan common.Event
66 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053067 PortStatsInterval int
Matteo Scandoloe33447a2019-10-31 12:38:23 -070068
Matteo Scandolo27428702019-10-11 16:21:16 -070069 Pons []*PonPort
70 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070071
72 // OLT Attributes
73 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000074
75 enableContext context.Context
76 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053077
Matteo Scandolo4a036262020-08-17 15:56:13 -070078 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053079 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070080}
81
Matteo Scandolo27428702019-10-11 16:21:16 -070082var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -070083
Matteo Scandolo27428702019-10-11 16:21:16 -070084func GetOLT() *OltDevice {
85 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070086}
87
Matteo Scandolo4a036262020-08-17 15:56:13 -070088func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070089 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +053090 "ID": options.Olt.ID,
91 "NumNni": options.Olt.NniPorts,
92 "NumPon": options.Olt.PonPorts,
93 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -070094 }).Debug("CreateOLT")
95
Matteo Scandolo84f7d482019-08-08 19:00:47 -070096 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +053097 ID: options.Olt.ID,
98 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070099 OperState: getOperStateFSM(func(e *fsm.Event) {
100 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
101 }),
Pragya Arya996a0892020-03-09 21:47:52 +0530102 NumNni: int(options.Olt.NniPorts),
103 NumPon: int(options.Olt.PonPorts),
104 NumOnuPerPon: int(options.Olt.OnusPonPort),
105 Pons: []*PonPort{},
106 Nnis: []*NniPort{},
107 Delay: options.BBSim.Delay,
Pragya Arya996a0892020-03-09 21:47:52 +0530108 enablePerf: options.BBSim.EnablePerf,
109 PublishEvents: options.BBSim.Events,
110 PortStatsInterval: options.Olt.PortStatsInterval,
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700111 dhcpServer: dhcp.NewDHCPServer(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700112 }
113
Pragya Arya996a0892020-03-09 21:47:52 +0530114 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530115 olt.ControlledActivation = val
116 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700117 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530118 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
119 olt.ControlledActivation = Default
120 }
121
Matteo Scandolo4747d292019-08-05 11:50:18 -0700122 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700123 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700124 olt.InternalState = fsm.NewFSM(
125 "created",
126 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800127 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100128 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700129 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700130 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800131 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700132 },
133 fsm.Callbacks{
134 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700135 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700136 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100137 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700138 },
139 )
140
Shrey Baid688b4242020-07-10 20:40:10 +0530141 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700142 // create NNI Port
143 nniPort, err := CreateNNI(&olt)
144 if err != nil {
145 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
146 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700147
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700148 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700149 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700150
Matteo Scandolo4a036262020-08-17 15:56:13 -0700151 // Create device and Services
152
153 nextCtag := map[string]int{}
154 nextStag := map[string]int{}
155
Matteo Scandolo4747d292019-08-05 11:50:18 -0700156 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700157 for i := 0; i < olt.NumPon; i++ {
158 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159
Matteo Scandolo4a036262020-08-17 15:56:13 -0700160 // create ONU devices
161 for j := 0; j < olt.NumOnuPerPon; j++ {
162 delay := time.Duration(olt.Delay*j) * time.Millisecond
163 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700164
Matteo Scandolo4a036262020-08-17 15:56:13 -0700165 for k, s := range common.Services {
166
167 // find the correct cTag for this service
168 if _, ok := nextCtag[s.Name]; !ok {
169 // it's the first time we iterate over this service,
170 // so we start from the config value
171 nextCtag[s.Name] = s.CTag
172 } else {
173 // we have a previous value, so we check it
174 // if Allocation is unique, we increment,
175 // otherwise (shared) we do nothing
176 if s.CTagAllocation == common.TagAllocationUnique.String() {
177 nextCtag[s.Name] = nextCtag[s.Name] + 1
178 }
179 }
180
181 // find the correct sTag for this service
182 if _, ok := nextStag[s.Name]; !ok {
183 nextStag[s.Name] = s.STag
184 } else {
185 if s.STagAllocation == common.TagAllocationUnique.String() {
186 nextStag[s.Name] = nextStag[s.Name] + 1
187 }
188 }
189
190 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
191 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
192 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
193 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
194
195 if err != nil {
196 oltLogger.WithFields(log.Fields{
197 "Err": err.Error(),
198 }).Fatal("Can't create Service")
199 }
200
201 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700202 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700203 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700204 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700205 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700206 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100207
Shrey Baid688b4242020-07-10 20:40:10 +0530208 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700209 if err := olt.InternalState.Event("initialize"); err != nil {
210 log.Errorf("Error initializing OLT: %v", err)
211 return nil
212 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100213 }
214
Pragya Arya324337e2020-02-20 14:35:08 +0530215 if olt.PublishEvents {
216 log.Debugf("BBSim event publishing is enabled")
217 // Create a channel to write event messages
218 olt.EventChannel = make(chan common.Event, 100)
219 }
220
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700221 return &olt
222}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700223
Shrey Baid688b4242020-07-10 20:40:10 +0530224func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100225
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800226 if o.oltServer == nil {
227 o.oltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100228 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800229 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100230 }
231
232 // create new channel for processOltMessages Go routine
233 o.channel = make(chan Message)
234
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100235 // FIXME we are assuming we have only one NNI
236 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800237 // NOTE we want to make sure the state is down when we initialize the OLT,
238 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
239 // in-band management
240 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100241 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700242}
243
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800244func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100245
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700246 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700247 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800248
249 oltLogger.WithFields(log.Fields{
250 "oltId": o.ID,
251 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
252
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700253 if o.InternalState.Is("enabled") {
254 oltLogger.WithFields(log.Fields{
255 "oltId": o.ID,
256 }).Info("This is an OLT soft reboot")
257 softReboot = true
258 }
259
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800260 // transition internal state to deleted
261 if err := o.InternalState.Event("delete"); err != nil {
262 oltLogger.WithFields(log.Fields{
263 "oltId": o.ID,
264 }).Errorf("Error deleting OLT: %v", err)
265 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100266 }
267
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800268 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 -0800269 o.StopOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100270
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700271 if softReboot {
272 for _, pon := range o.Pons {
273 if pon.InternalState.Current() == "enabled" {
274 // disable PONs
275 msg := Message{
276 Type: PonIndication,
277 Data: PonIndicationMessage{
278 OperState: DOWN,
279 PonPortID: pon.ID,
280 },
281 }
282 o.channel <- msg
283 }
284
285 for _, onu := range pon.Onus {
286 _ = onu.InternalState.Event("disable")
287 }
288 }
289 } else {
290 // PONs are already handled in the Disable call
291 for _, pon := range olt.Pons {
292 // ONUs are not automatically disabled when a PON goes down
293 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
294 for _, onu := range pon.Onus {
295 _ = onu.InternalState.Event("disable")
296 }
Pragya Arya2225f202020-01-29 18:05:01 +0530297 }
298 }
299
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100300 // terminate the OLT's processOltMessages go routine
301 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700302
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700303 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100304
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100305 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100306
307 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800308 oltLogger.WithFields(log.Fields{
309 "oltId": o.ID,
310 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100311 return err
312 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800313 oltLogger.WithFields(log.Fields{
314 "oltId": o.ID,
315 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100316 return nil
317}
318
319// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800320func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700321 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700322 lis, err := net.Listen("tcp", address)
323 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700324 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700325 }
326 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100327
Matteo Scandolo4747d292019-08-05 11:50:18 -0700328 openolt.RegisterOpenoltServer(grpcServer, o)
329
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100330 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700331
Shrey Baid688b4242020-07-10 20:40:10 +0530332 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100333 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700334
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100335 return grpcServer, nil
336}
337
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800338// StartOltServer will create the grpc server that VOLTHA uses
339// to communicate with the device
340func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
341 oltServer, err := o.newOltServer()
342 if err != nil {
343 oltLogger.WithFields(log.Fields{
344 "err": err,
345 }).Error("Cannot OLT gRPC server")
346 return nil, err
347 }
348 return oltServer, nil
349}
350
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100351// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800352func (o *OltDevice) StopOltServer() {
353 if o.oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800354 oltLogger.WithFields(log.Fields{
355 "oltId": o.SerialNumber,
356 }).Warnf("Stopping OLT gRPC server")
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800357 o.oltServer.Stop()
358 o.oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700359 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700360}
361
362// Device Methods
363
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100364// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530365func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700366 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530367 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700368
David Bainbridge103cf022019-12-16 20:11:35 +0000369 // If enabled has already been called then an enabled context has
370 // been created. If this is the case then we want to cancel all the
371 // proessing loops associated with that enable before we recreate
372 // new ones
373 o.Lock()
374 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700375 oltLogger.Info("This is an OLT reboot")
David Bainbridge103cf022019-12-16 20:11:35 +0000376 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530377 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000378 }
379 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
380 o.Unlock()
381
Matteo Scandolo4747d292019-08-05 11:50:18 -0700382 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800383 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700384
Matteo Scandolo4a036262020-08-17 15:56:13 -0700385 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530386
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100387 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000388 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700389
390 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100391 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700392 Type: OltIndication,
393 Data: OltIndicationMessage{
394 OperState: UP,
395 },
396 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100397 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700398
399 // send NNI Port Indications
400 for _, nni := range o.Nnis {
401 msg := Message{
402 Type: NniIndication,
403 Data: NniIndicationMessage{
404 OperState: UP,
405 NniPortID: nni.ID,
406 },
407 }
408 o.channel <- msg
409 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100410
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800411 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100412
Shrey Baid688b4242020-07-10 20:40:10 +0530413 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530414 for _, pon := range o.Pons {
415 if pon.InternalState.Current() == "disabled" {
416 msg := Message{
417 Type: PonIndication,
418 Data: PonIndicationMessage{
419 OperState: UP,
420 PonPortID: pon.ID,
421 },
422 }
423 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000424 }
Pragya Arya2225f202020-01-29 18:05:01 +0530425 }
426 } else {
427
428 // 1. controlledActivation == Default: Send both PON and ONUs indications
429 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
430
431 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
432 // send PON Port indications
433 for _, pon := range o.Pons {
434 msg := Message{
435 Type: PonIndication,
436 Data: PonIndicationMessage{
437 OperState: UP,
438 PonPortID: pon.ID,
439 },
440 }
441 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700442 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700443 }
444 }
445
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800446 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530447
448 if !o.enablePerf {
449 // Start a go routine to send periodic port stats to openolt adapter
450 go o.periodicPortStats(o.enableContext)
451 }
452
Matteo Scandolo4747d292019-08-05 11:50:18 -0700453 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700454}
455
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800456func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400457 ch := omcisim.GetChannel()
458
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100459 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400460
David Bainbridge103cf022019-12-16 20:11:35 +0000461loop:
462 for {
463 select {
464 case <-ctx.Done():
465 oltLogger.Debug("OMCI processing canceled via context")
466 break loop
467 case message, ok := <-ch:
468 if !ok || ctx.Err() != nil {
469 oltLogger.Debug("OMCI processing canceled via channel close")
470 break loop
471 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800472
473 oltLogger.WithFields(log.Fields{
474 "messageType": message.Type,
475 "OnuId": message.Data.OnuId,
476 "IntfId": message.Data.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700477 }).Debug("Received message on OMCI Sim channel")
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800478
David Bainbridge103cf022019-12-16 20:11:35 +0000479 onuId := message.Data.OnuId
480 intfId := message.Data.IntfId
481 onu, err := o.FindOnuById(intfId, onuId)
482 if err != nil {
483 oltLogger.Errorf("Failed to find onu: %v", err)
484 continue
485 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800486 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400487 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400488 }
David Bainbridge103cf022019-12-16 20:11:35 +0000489
490 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400491}
492
Pragya Arya996a0892020-03-09 21:47:52 +0530493func (o *OltDevice) periodicPortStats(ctx context.Context) {
494 var portStats *openolt.PortStatistics
495 for {
496 select {
497 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
498 // send NNI port stats
499 for _, port := range o.Nnis {
500 incrementStat := true
501 if port.OperState.Current() == "down" {
502 incrementStat = false
503 }
504 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
505 o.sendPortStatsIndication(portStats, port.ID, port.Type)
506 }
507
508 // send PON port stats
509 for _, port := range o.Pons {
510 incrementStat := true
511 // do not increment port stats if PON port is down or no ONU is activated on PON port
512 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
513 incrementStat = false
514 }
515 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
516 o.sendPortStatsIndication(portStats, port.ID, port.Type)
517 }
518 case <-ctx.Done():
519 log.Debug("Stop sending port stats")
520 return
521 }
522
523 }
524}
525
Matteo Scandolo4747d292019-08-05 11:50:18 -0700526// Helpers method
527
Shrey Baid688b4242020-07-10 20:40:10 +0530528func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700529 for _, pon := range o.Pons {
530 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700531 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700532 }
533 }
Shrey Baid688b4242020-07-10 20:40:10 +0530534 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700535}
536
Shrey Baid688b4242020-07-10 20:40:10 +0530537func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700538 for _, nni := range o.Nnis {
539 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700540 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700541 }
542 }
Shrey Baid688b4242020-07-10 20:40:10 +0530543 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700544}
545
Scott Baker41724b82020-01-21 19:54:53 -0800546func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
547 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
548 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
549 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
550 return
551 }
552
553 oltLogger.WithFields(log.Fields{
554 "AlarmIndication": alarmInd,
555 }).Debug("Sent Indication_AlarmInd")
556}
557
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100558func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700559 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
560 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700561 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800562 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700563 }
564
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700565 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700566 "OperState": msg.OperState,
567 }).Debug("Sent Indication_OltInd")
568}
569
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100570func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700571 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800572 if msg.OperState == UP {
573 if err := nni.OperState.Event("enable"); err != nil {
574 log.WithFields(log.Fields{
575 "Type": nni.Type,
576 "IntfId": nni.ID,
577 "OperState": nni.OperState.Current(),
578 }).Errorf("Can't move NNI Port to enabled state: %v", err)
579 }
580 } else if msg.OperState == DOWN {
581 if err := nni.OperState.Event("disable"); err != nil {
582 log.WithFields(log.Fields{
583 "Type": nni.Type,
584 "IntfId": nni.ID,
585 "OperState": nni.OperState.Current(),
586 }).Errorf("Can't move NNI Port to disable state: %v", err)
587 }
588 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700589 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700590 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700591 Type: nni.Type,
592 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700593 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700594 }}
595
596 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700597 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800598 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700599 }
600
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700601 oltLogger.WithFields(log.Fields{
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 }).Debug("Sent Indication_IntfOperInd for NNI")
606}
607
Pragya Arya2225f202020-01-29 18:05:01 +0530608func (o *OltDevice) sendPonIndication(ponPortID uint32) {
609
Matteo Scandolo4a036262020-08-17 15:56:13 -0700610 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530611 pon, _ := o.GetPonById(ponPortID)
612 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700613 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700614 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700615 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700616 }}
617
618 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700619 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800620 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700621 }
622
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700623 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700624 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700625 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700626 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700627
Pragya Arya2225f202020-01-29 18:05:01 +0530628 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700629 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700630 Type: pon.Type,
631 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700632 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700633 }}
634
635 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700636 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800637 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700638 }
639
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700640 oltLogger.WithFields(log.Fields{
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 }).Debug("Sent Indication_IntfOperInd for PON")
645}
646
Pragya Arya996a0892020-03-09 21:47:52 +0530647func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530648 if o.InternalState.Current() == "enabled" {
649 oltLogger.WithFields(log.Fields{
650 "Type": portType,
651 "IntfId": portID,
652 }).Trace("Sending port stats")
653 stats.IntfId = InterfaceIDToPortNo(portID, portType)
654 data := &openolt.Indication_PortStats{
655 PortStats: stats,
656 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700657 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530658 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
659 oltLogger.Errorf("Failed to send PortStats: %v", err)
660 return
661 }
Pragya Arya996a0892020-03-09 21:47:52 +0530662 }
663}
664
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100665// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000666func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100667 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000668 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700669
David Bainbridge103cf022019-12-16 20:11:35 +0000670loop:
671 for {
672 select {
673 case <-ctx.Done():
674 oltLogger.Debug("OLT Indication processing canceled via context")
675 break loop
676 case message, ok := <-ch:
677 if !ok || ctx.Err() != nil {
678 oltLogger.Debug("OLT Indication processing canceled via closed channel")
679 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700680 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700681
David Bainbridge103cf022019-12-16 20:11:35 +0000682 oltLogger.WithFields(log.Fields{
683 "oltId": o.ID,
684 "messageType": message.Type,
685 }).Trace("Received message")
686
687 switch message.Type {
688 case OltIndication:
689 msg, _ := message.Data.(OltIndicationMessage)
690 if msg.OperState == UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530691 _ = o.InternalState.Event("enable")
692 _ = o.OperState.Event("enable")
David Bainbridge103cf022019-12-16 20:11:35 +0000693 } else if msg.OperState == DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530694 _ = o.InternalState.Event("disable")
695 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000696 }
697 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800698 case AlarmIndication:
699 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
700 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000701 case NniIndication:
702 msg, _ := message.Data.(NniIndicationMessage)
703 o.sendNniIndication(msg, stream)
704 case PonIndication:
705 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530706 pon, _ := o.GetPonById(msg.PonPortID)
707 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530708 if err := pon.OperState.Event("enable"); err != nil {
709 oltLogger.WithFields(log.Fields{
710 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800711 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530712 }).Error("Can't Enable Oper state for PON Port")
713 }
714 if err := pon.InternalState.Event("enable"); err != nil {
715 oltLogger.WithFields(log.Fields{
716 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800717 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530718 }).Error("Can't Enable Internal state for PON Port")
719 }
Pragya Arya2225f202020-01-29 18:05:01 +0530720 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530721 if err := pon.OperState.Event("disable"); err != nil {
722 oltLogger.WithFields(log.Fields{
723 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800724 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530725 }).Error("Can't Disable Oper state for PON Port")
726 }
727 if err := pon.InternalState.Event("disable"); err != nil {
728 oltLogger.WithFields(log.Fields{
729 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800730 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530731 }).Error("Can't Disable Internal state for PON Port")
732 }
Pragya Arya2225f202020-01-29 18:05:01 +0530733 }
David Bainbridge103cf022019-12-16 20:11:35 +0000734 default:
735 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
736 }
737 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700738 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100739 wg.Done()
740 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700741}
742
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700743// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530744func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200745 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700746 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700747 for _, pon := range o.Pons {
748 for _, onu := range pon.Onus {
749 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700750 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700751 }
752 }
753 }
754
Shrey Baid688b4242020-07-10 20:40:10 +0530755 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700756}
757
William Kurkian9dadc5b2019-10-22 13:51:57 -0400758// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530759func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200760 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400761 // memoizing it will remove the bottleneck
762 for _, pon := range o.Pons {
763 if pon.ID == intfId {
764 for _, onu := range pon.Onus {
765 if onu.ID == onuId {
766 return onu, nil
767 }
768 }
769 }
770 }
Shrey Baid688b4242020-07-10 20:40:10 +0530771 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400772}
773
Matteo Scandolo4a036262020-08-17 15:56:13 -0700774// returns a Service with a given Mac Address
775func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200776 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700777 // memoizing it will remove the bottleneck
778 for _, pon := range o.Pons {
779 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700780 s, err := onu.findServiceByMacAddress(mac)
781 if err == nil {
782 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700783 }
784 }
785 }
786
Matteo Scandolo4a036262020-08-17 15:56:13 -0700787 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700788}
789
Matteo Scandolo4747d292019-08-05 11:50:18 -0700790// GRPC Endpoints
791
Shrey Baid688b4242020-07-10 20:40:10 +0530792func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700793 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700794 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700795 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530796 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700797
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700798 pon, _ := o.GetPonById(onu.IntfId)
799 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500800 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700801
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700802 if err := _onu.OperState.Event("enable"); err != nil {
803 oltLogger.WithFields(log.Fields{
804 "IntfId": _onu.PonPortID,
805 "OnuSn": _onu.Sn(),
806 "OnuId": _onu.ID,
807 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700808 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700809 if err := _onu.InternalState.Event("enable"); err != nil {
810 oltLogger.WithFields(log.Fields{
811 "IntfId": _onu.PonPortID,
812 "OnuSn": _onu.Sn(),
813 "OnuId": _onu.ID,
814 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
815 }
816
817 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
818
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700819 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700820}
821
Shrey Baid688b4242020-07-10 20:40:10 +0530822func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700823 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700824 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700825}
826
Shrey Baid688b4242020-07-10 20:40:10 +0530827func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530828 oltLogger.WithFields(log.Fields{
829 "IntfId": onu.IntfId,
830 "OnuId": onu.OnuId,
831 }).Info("Received DeleteOnu call from VOLTHA")
832
833 pon, err := o.GetPonById(onu.IntfId)
834 if err != nil {
835 oltLogger.WithFields(log.Fields{
836 "OnuId": onu.OnuId,
837 "IntfId": onu.IntfId,
838 "err": err,
839 }).Error("Can't find PonPort")
840 }
841 _onu, err := pon.GetOnuById(onu.OnuId)
842 if err != nil {
843 oltLogger.WithFields(log.Fields{
844 "OnuId": onu.OnuId,
845 "IntfId": onu.IntfId,
846 "err": err,
847 }).Error("Can't find Onu")
848 }
849
Hardik Windlassad790cb2020-06-17 21:26:22 +0530850 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530851 oltLogger.WithFields(log.Fields{
852 "IntfId": _onu.PonPortID,
853 "OnuSn": _onu.Sn(),
854 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530855 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
856 }
857
Hardik Windlassad790cb2020-06-17 21:26:22 +0530858 // ONU Re-Discovery
859 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530860 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530861 }
862
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700863 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700864}
865
Shrey Baid688b4242020-07-10 20:40:10 +0530866func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700867 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800868 oltLogger.WithFields(log.Fields{
869 "oltId": o.ID,
870 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530871 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800872
Matteo Scandolo401503a2019-12-11 14:48:14 -0800873 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530874 if pon.InternalState.Current() == "enabled" {
875 // disable PONs
876 msg := Message{
877 Type: PonIndication,
878 Data: PonIndicationMessage{
879 OperState: DOWN,
880 PonPortID: pon.ID,
881 },
882 }
883 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800884 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800885 }
886
Matteo Scandolo401503a2019-12-11 14:48:14 -0800887 // Note that we are not disabling the NNI as the real OLT does not.
888 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800889
890 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100891 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700892 Type: OltIndication,
893 Data: OltIndicationMessage{
894 OperState: DOWN,
895 },
896 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100897 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700898 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700899}
900
Shrey Baid688b4242020-07-10 20:40:10 +0530901func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530902 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200903 ponID := intf.GetIntfId()
904 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200905
906 msg := Message{
907 Type: PonIndication,
908 Data: PonIndicationMessage{
909 OperState: DOWN,
910 PonPortID: ponID,
911 },
912 }
913 o.channel <- msg
914
915 for _, onu := range pon.Onus {
916
917 onuIndication := OnuIndicationMessage{
918 OperState: DOWN,
919 PonPortID: ponID,
920 OnuID: onu.ID,
921 OnuSN: onu.SerialNumber,
922 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700923 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200924
925 }
926
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700927 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700928}
929
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100930func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700931 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530932 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700933 o.Enable(stream)
934 return nil
935}
936
Shrey Baid688b4242020-07-10 20:40:10 +0530937func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530938 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530939 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200940 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200941
Pragya Arya2225f202020-01-29 18:05:01 +0530942 msg := Message{
943 Type: PonIndication,
944 Data: PonIndicationMessage{
945 OperState: UP,
946 PonPortID: ponID,
947 },
948 }
949 o.channel <- msg
950
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200951 for _, onu := range pon.Onus {
952
953 onuIndication := OnuIndicationMessage{
954 OperState: UP,
955 PonPortID: ponID,
956 OnuID: onu.ID,
957 OnuSN: onu.SerialNumber,
958 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700959 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200960
961 }
962
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700963 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700964}
965
Shrey Baid688b4242020-07-10 20:40:10 +0530966func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700967 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700968 "IntfId": flow.AccessIntfId,
969 "OnuId": flow.OnuId,
970 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700971 "InnerVlan": flow.Classifier.IVid,
972 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700973 "FlowType": flow.FlowType,
974 "FlowId": flow.FlowId,
975 "UniID": flow.UniId,
976 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +0530977 }).Tracef("OLT receives FlowAdd")
978
979 flowKey := FlowKey{}
980 if !o.enablePerf {
981 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +0100982 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +0530983 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700984
985 if flow.AccessIntfId == -1 {
986 oltLogger.WithFields(log.Fields{
987 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700988 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -0700989 } else if flow.FlowType == "multicast" {
990 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -0700991 "Cookie": flow.Cookie,
992 "DstPort": flow.Classifier.DstPort,
993 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
994 "FlowId": flow.FlowId,
995 "FlowType": flow.FlowType,
996 "GemportId": flow.GemportId,
997 "InnerVlan": flow.Classifier.IVid,
998 "IntfId": flow.AccessIntfId,
999 "IpProto": flow.Classifier.IpProto,
1000 "OnuId": flow.OnuId,
1001 "OuterVlan": flow.Classifier.OVid,
1002 "PortNo": flow.PortNo,
1003 "SrcPort": flow.Classifier.SrcPort,
1004 "UniID": flow.UniId,
1005 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001006 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001007 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001008 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001009 if err != nil {
1010 oltLogger.WithFields(log.Fields{
1011 "OnuId": flow.OnuId,
1012 "IntfId": flow.AccessIntfId,
1013 "err": err,
1014 }).Error("Can't find PonPort")
1015 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001016 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001017 if err != nil {
1018 oltLogger.WithFields(log.Fields{
1019 "OnuId": flow.OnuId,
1020 "IntfId": flow.AccessIntfId,
1021 "err": err,
1022 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001023 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001024 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301025 if !o.enablePerf {
1026 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301027 // Generate event on first flow for ONU
1028 if len(onu.Flows) == 1 {
1029 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1030 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301031 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001032
1033 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001034 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001035 Data: OnuFlowUpdateMessage{
1036 PonPortID: pon.ID,
1037 OnuID: onu.ID,
1038 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001039 },
1040 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001041 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001042 }
1043
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001044 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001045}
1046
Pragya Arya8bdb4532020-03-02 17:08:09 +05301047// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301048func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001049
Pragya Arya8bdb4532020-03-02 17:08:09 +05301050 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301051 "FlowId": flow.FlowId,
1052 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001053 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301054
1055 if !o.enablePerf { // remove only if flow were stored
1056 flowKey := FlowKey{
1057 ID: flow.FlowId,
1058 Direction: flow.FlowType,
1059 }
1060
1061 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001062 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301063 if !ok {
1064 oltLogger.Errorf("Flow %v not found", flow)
1065 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1066 }
1067
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001068 storedFlow := storedFlowIntf.(openolt.Flow)
1069
Pragya Arya8bdb4532020-03-02 17:08:09 +05301070 // if its ONU flow remove it from ONU also
1071 if storedFlow.AccessIntfId != -1 {
1072 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1073 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1074 if err != nil {
1075 oltLogger.WithFields(log.Fields{
1076 "OnuId": storedFlow.OnuId,
1077 "IntfId": storedFlow.AccessIntfId,
1078 "err": err,
1079 }).Error("ONU not found")
1080 return new(openolt.Empty), nil
1081 }
1082 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301083 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301084 }
1085
1086 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001087 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301088 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001089
1090 if flow.AccessIntfId == -1 {
1091 oltLogger.WithFields(log.Fields{
1092 "FlowId": flow.FlowId,
1093 }).Debug("Removing OLT flow")
1094 } else if flow.FlowType == "multicast" {
1095 oltLogger.WithFields(log.Fields{
1096 "FlowId": flow.FlowId,
1097 }).Debug("Removing OLT multicast flow")
1098 } else {
1099
1100 onu, err := o.GetOnuByFlowId(flow.FlowId)
1101 if err != nil {
1102 oltLogger.WithFields(log.Fields{
1103 "OnuId": flow.OnuId,
1104 "IntfId": flow.AccessIntfId,
1105 "err": err,
1106 }).Error("Can't find Onu")
1107 return nil, err
1108 }
1109
1110 msg := Message{
1111 Type: FlowRemoved,
1112 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301113 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001114 },
1115 }
1116 onu.Channel <- msg
1117 }
1118
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001119 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001120}
1121
Shrey Baid688b4242020-07-10 20:40:10 +05301122func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001123 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1124 oltLogger.WithFields(log.Fields{
1125 "signature": res.HeartbeatSignature,
1126 }).Trace("HeartbeatCheck")
1127 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001128}
1129
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001130func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001131 for _, pon := range o.Pons {
1132 for _, onu := range pon.Onus {
1133 for _, fId := range onu.FlowIds {
1134 if fId == flowId {
1135 return onu, nil
1136 }
1137 }
1138 }
1139 }
Shrey Baid688b4242020-07-10 20:40:10 +05301140 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001141}
1142
Shrey Baid688b4242020-07-10 20:40:10 +05301143func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001144
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001145 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001146 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001147 "PonPorts": o.NumPon,
1148 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001149 devinfo := new(openolt.DeviceInfo)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001150 devinfo.Vendor = common.Config.Olt.Vendor
1151 devinfo.Model = common.Config.Olt.Model
1152 devinfo.HardwareVersion = common.Config.Olt.HardwareVersion
1153 devinfo.FirmwareVersion = common.Config.Olt.FirmwareVersion
1154 devinfo.Technology = common.Config.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001155 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001156 devinfo.OnuIdStart = 1
1157 devinfo.OnuIdEnd = 255
1158 devinfo.AllocIdStart = 1024
1159 devinfo.AllocIdEnd = 16383
1160 devinfo.GemportIdStart = 1024
1161 devinfo.GemportIdEnd = 65535
1162 devinfo.FlowIdStart = 1
1163 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001164 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4a036262020-08-17 15:56:13 -07001165 devinfo.DeviceId = common.Config.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001166
1167 return devinfo, nil
1168}
1169
Shrey Baid688b4242020-07-10 20:40:10 +05301170func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001171 pon, err := o.GetPonById(omci_msg.IntfId)
1172 if err != nil {
1173 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001174 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001175 "onu_id": omci_msg.OnuId,
1176 "pon_id": omci_msg.IntfId,
1177 }).Error("pon ID not found")
1178 return nil, err
1179 }
1180
1181 onu, err := pon.GetOnuById(omci_msg.OnuId)
1182 if err != nil {
1183 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001184 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001185 "onu_id": omci_msg.OnuId,
1186 "pon_id": omci_msg.IntfId,
1187 }).Error("onu ID not found")
1188 return nil, err
1189 }
1190
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001191 oltLogger.WithFields(log.Fields{
1192 "IntfId": onu.PonPortID,
1193 "OnuId": onu.ID,
1194 "OnuSn": onu.Sn(),
1195 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001196 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001197 Type: OMCI,
1198 Data: OmciMessage{
1199 OnuSN: onu.SerialNumber,
1200 OnuID: onu.ID,
1201 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001202 },
1203 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001204 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001205 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001206}
1207
Shrey Baid688b4242020-07-10 20:40:10 +05301208func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001209 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001210 if err != nil {
1211 oltLogger.WithFields(log.Fields{
1212 "OnuId": onuPkt.OnuId,
1213 "IntfId": onuPkt.IntfId,
1214 "err": err,
1215 }).Error("Can't find PonPort")
1216 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001217 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001218 if err != nil {
1219 oltLogger.WithFields(log.Fields{
1220 "OnuId": onuPkt.OnuId,
1221 "IntfId": onuPkt.IntfId,
1222 "err": err,
1223 }).Error("Can't find Onu")
1224 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001225
Matteo Scandolo075b1892019-10-07 12:11:07 -07001226 oltLogger.WithFields(log.Fields{
1227 "IntfId": onu.PonPortID,
1228 "OnuId": onu.ID,
1229 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001230 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001231 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001232
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001233 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001234
1235 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001236 if err != nil {
1237 onuLogger.WithFields(log.Fields{
1238 "IntfId": onu.PonPortID,
1239 "OnuId": onu.ID,
1240 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001241 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001242 }).Error("Can't find pktType in packet, droppint it")
1243 return new(openolt.Empty), nil
1244 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001245
Matteo Scandolo4a036262020-08-17 15:56:13 -07001246 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001247 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001248 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001249 "IntfId": onu.PonPortID,
1250 "OnuId": onu.ID,
1251 "OnuSn": onu.Sn(),
1252 "Pkt": rawpkt.Data(),
1253 }).Error("Can't find Dst MacAddress in packet, droppint it")
1254 return new(openolt.Empty), nil
1255 }
1256
Matteo Scandolo075b1892019-10-07 12:11:07 -07001257 msg := Message{
1258 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001259 Data: OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001260 IntfId: onuPkt.IntfId,
1261 OnuId: onuPkt.OnuId,
1262 Packet: rawpkt,
1263 Type: pktType,
1264 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001265 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001266 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001267
Matteo Scandolo075b1892019-10-07 12:11:07 -07001268 onu.Channel <- msg
1269
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001270 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001271}
1272
Shrey Baid688b4242020-07-10 20:40:10 +05301273func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001274
1275 // OLT Reboot is called in two cases:
1276 // - 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)
1277 // - when an OLT needs to be rebooted (voltcl device reboot)
1278
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001279 oltLogger.WithFields(log.Fields{
1280 "oltId": o.ID,
1281 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301282 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301283 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001284 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001285}
1286
Shrey Baid688b4242020-07-10 20:40:10 +05301287func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301288 oltLogger.WithFields(log.Fields{
1289 "oltId": o.ID,
1290 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301291 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301292
Pragya Arya2225f202020-01-29 18:05:01 +05301293 // enable OLT
1294 oltMsg := Message{
1295 Type: OltIndication,
1296 Data: OltIndicationMessage{
1297 OperState: UP,
1298 },
Pragya Arya1881df02020-01-29 18:05:01 +05301299 }
Pragya Arya2225f202020-01-29 18:05:01 +05301300 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301301
Pragya Arya2225f202020-01-29 18:05:01 +05301302 for _, pon := range o.Pons {
1303 if pon.InternalState.Current() == "disabled" {
1304 msg := Message{
1305 Type: PonIndication,
1306 Data: PonIndicationMessage{
1307 OperState: UP,
1308 PonPortID: pon.ID,
1309 },
1310 }
1311 o.channel <- msg
1312 }
1313 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001314
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001315 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001316}
1317
Shrey Baid688b4242020-07-10 20:40:10 +05301318func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001319 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1320
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001321 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1322
1323 if err != nil {
1324 return nil, err
1325 }
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) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001330 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001331 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001332}
1333
Shrey Baid688b4242020-07-10 20:40:10 +05301334func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001335 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001336 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001337}
1338
Shrey Baid688b4242020-07-10 20:40:10 +05301339func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001340 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001341 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001342}
1343
Shrey Baid688b4242020-07-10 20:40:10 +05301344func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001345 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001346 return new(openolt.Empty), nil
1347}
1348
Shrey Baid688b4242020-07-10 20:40:10 +05301349func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001350 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001351 return new(openolt.Empty), nil
1352}
1353
Shrey Baid688b4242020-07-10 20:40:10 +05301354func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301355 oltLogger.WithFields(log.Fields{
1356 "OnuId": trafficSchedulers.OnuId,
1357 "IntfId": trafficSchedulers.IntfId,
1358 "OnuPortNo": trafficSchedulers.PortNo,
1359 }).Info("received CreateTrafficSchedulers")
1360
1361 if !s.enablePerf {
1362 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1363 if err != nil {
1364 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1365 return new(openolt.Empty), err
1366 }
1367 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1368 if err != nil {
1369 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1370 return new(openolt.Empty), err
1371 }
1372 onu.TrafficSchedulers = trafficSchedulers
1373 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001374 return new(openolt.Empty), nil
1375}
1376
Shrey Baid688b4242020-07-10 20:40:10 +05301377func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301378 oltLogger.WithFields(log.Fields{
1379 "OnuId": trafficSchedulers.OnuId,
1380 "IntfId": trafficSchedulers.IntfId,
1381 "OnuPortNo": trafficSchedulers.PortNo,
1382 }).Info("received RemoveTrafficSchedulers")
1383 if !s.enablePerf {
1384 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1385 if err != nil {
1386 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1387 return new(openolt.Empty), err
1388 }
1389 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1390 if err != nil {
1391 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1392 return new(openolt.Empty), err
1393 }
1394
1395 onu.TrafficSchedulers = nil
1396 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001397 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001398}
Scott Baker41724b82020-01-21 19:54:53 -08001399
1400// assumes caller has properly formulated an openolt.AlarmIndication
Shrey Baid688b4242020-07-10 20:40:10 +05301401func (o *OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
Scott Baker41724b82020-01-21 19:54:53 -08001402 msg := Message{
1403 Type: AlarmIndication,
1404 Data: ind,
1405 }
1406
1407 o.channel <- msg
1408 return nil
1409}
Matteo Scandolo618a6582020-09-09 12:21:29 -07001410
1411func (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}