blob: 008e3be9d7c6be0bab7b01dc6badb249dd00bd3e [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
Pragya Arya8bdb4532020-03-02 17:08:09 +053062 Flows map[FlowKey]openolt.Flow
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,
108 Flows: make(map[FlowKey]openolt.Flow),
109 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
234 o.channel = make(chan Message)
235
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
276 msg := Message{
277 Type: PonIndication,
278 Data: PonIndicationMessage{
279 OperState: DOWN,
280 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
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100392 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700393 Type: OltIndication,
394 Data: OltIndicationMessage{
395 OperState: UP,
396 },
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 {
402 msg := Message{
403 Type: NniIndication,
404 Data: NniIndicationMessage{
405 OperState: UP,
406 NniPortID: nni.ID,
407 },
408 }
409 o.channel <- msg
410 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100411
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800412 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100413
Shrey Baid688b4242020-07-10 20:40:10 +0530414 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530415 for _, pon := range o.Pons {
416 if pon.InternalState.Current() == "disabled" {
417 msg := Message{
418 Type: PonIndication,
419 Data: PonIndicationMessage{
420 OperState: UP,
421 PonPortID: pon.ID,
422 },
423 }
424 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000425 }
Pragya Arya2225f202020-01-29 18:05:01 +0530426 }
427 } else {
428
429 // 1. controlledActivation == Default: Send both PON and ONUs indications
430 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
431
432 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
433 // send PON Port indications
434 for _, pon := range o.Pons {
435 msg := Message{
436 Type: PonIndication,
437 Data: PonIndicationMessage{
438 OperState: UP,
439 PonPortID: pon.ID,
440 },
441 }
442 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700443 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700444 }
445 }
446
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800447 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530448
449 if !o.enablePerf {
450 // Start a go routine to send periodic port stats to openolt adapter
451 go o.periodicPortStats(o.enableContext)
452 }
453
Matteo Scandolo4747d292019-08-05 11:50:18 -0700454 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700455}
456
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800457func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400458 ch := omcisim.GetChannel()
459
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100460 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400461
David Bainbridge103cf022019-12-16 20:11:35 +0000462loop:
463 for {
464 select {
465 case <-ctx.Done():
466 oltLogger.Debug("OMCI processing canceled via context")
467 break loop
468 case message, ok := <-ch:
469 if !ok || ctx.Err() != nil {
470 oltLogger.Debug("OMCI processing canceled via channel close")
471 break loop
472 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800473
474 oltLogger.WithFields(log.Fields{
475 "messageType": message.Type,
476 "OnuId": message.Data.OnuId,
477 "IntfId": message.Data.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700478 }).Debug("Received message on OMCI Sim channel")
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800479
David Bainbridge103cf022019-12-16 20:11:35 +0000480 onuId := message.Data.OnuId
481 intfId := message.Data.IntfId
482 onu, err := o.FindOnuById(intfId, onuId)
483 if err != nil {
484 oltLogger.Errorf("Failed to find onu: %v", err)
485 continue
486 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800487 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400488 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400489 }
David Bainbridge103cf022019-12-16 20:11:35 +0000490
491 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400492}
493
Pragya Arya996a0892020-03-09 21:47:52 +0530494func (o *OltDevice) periodicPortStats(ctx context.Context) {
495 var portStats *openolt.PortStatistics
496 for {
497 select {
498 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
499 // send NNI port stats
500 for _, port := range o.Nnis {
501 incrementStat := true
502 if port.OperState.Current() == "down" {
503 incrementStat = false
504 }
505 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
506 o.sendPortStatsIndication(portStats, port.ID, port.Type)
507 }
508
509 // send PON port stats
510 for _, port := range o.Pons {
511 incrementStat := true
512 // do not increment port stats if PON port is down or no ONU is activated on PON port
513 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
514 incrementStat = false
515 }
516 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
517 o.sendPortStatsIndication(portStats, port.ID, port.Type)
518 }
519 case <-ctx.Done():
520 log.Debug("Stop sending port stats")
521 return
522 }
523
524 }
525}
526
Matteo Scandolo4747d292019-08-05 11:50:18 -0700527// Helpers method
528
Shrey Baid688b4242020-07-10 20:40:10 +0530529func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700530 for _, pon := range o.Pons {
531 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700532 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700533 }
534 }
Shrey Baid688b4242020-07-10 20:40:10 +0530535 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700536}
537
Shrey Baid688b4242020-07-10 20:40:10 +0530538func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700539 for _, nni := range o.Nnis {
540 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700541 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700542 }
543 }
Shrey Baid688b4242020-07-10 20:40:10 +0530544 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700545}
546
Scott Baker41724b82020-01-21 19:54:53 -0800547func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
548 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
549 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
550 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
551 return
552 }
553
554 oltLogger.WithFields(log.Fields{
555 "AlarmIndication": alarmInd,
556 }).Debug("Sent Indication_AlarmInd")
557}
558
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100559func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700560 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
561 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700562 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800563 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700564 }
565
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700566 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700567 "OperState": msg.OperState,
568 }).Debug("Sent Indication_OltInd")
569}
570
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100571func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700572 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800573 if msg.OperState == UP {
574 if err := nni.OperState.Event("enable"); err != nil {
575 log.WithFields(log.Fields{
576 "Type": nni.Type,
577 "IntfId": nni.ID,
578 "OperState": nni.OperState.Current(),
579 }).Errorf("Can't move NNI Port to enabled state: %v", err)
580 }
581 } else if msg.OperState == DOWN {
582 if err := nni.OperState.Event("disable"); err != nil {
583 log.WithFields(log.Fields{
584 "Type": nni.Type,
585 "IntfId": nni.ID,
586 "OperState": nni.OperState.Current(),
587 }).Errorf("Can't move NNI Port to disable state: %v", err)
588 }
589 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700590 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700591 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700592 Type: nni.Type,
593 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700594 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700595 }}
596
597 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700598 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800599 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700600 }
601
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700602 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700603 "Type": nni.Type,
604 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700605 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700606 }).Debug("Sent Indication_IntfOperInd for NNI")
607}
608
Pragya Arya2225f202020-01-29 18:05:01 +0530609func (o *OltDevice) sendPonIndication(ponPortID uint32) {
610
Matteo Scandolo4a036262020-08-17 15:56:13 -0700611 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530612 pon, _ := o.GetPonById(ponPortID)
613 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700614 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700615 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700616 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700617 }}
618
619 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700620 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800621 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700622 }
623
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700624 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700625 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700626 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700627 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700628
Pragya Arya2225f202020-01-29 18:05:01 +0530629 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700630 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700631 Type: pon.Type,
632 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700633 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700634 }}
635
636 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700637 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800638 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700639 }
640
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700641 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700642 "Type": pon.Type,
643 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700644 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700645 }).Debug("Sent Indication_IntfOperInd for PON")
646}
647
Pragya Arya996a0892020-03-09 21:47:52 +0530648func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530649 if o.InternalState.Current() == "enabled" {
650 oltLogger.WithFields(log.Fields{
651 "Type": portType,
652 "IntfId": portID,
653 }).Trace("Sending port stats")
654 stats.IntfId = InterfaceIDToPortNo(portID, portType)
655 data := &openolt.Indication_PortStats{
656 PortStats: stats,
657 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700658 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530659 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
660 oltLogger.Errorf("Failed to send PortStats: %v", err)
661 return
662 }
Pragya Arya996a0892020-03-09 21:47:52 +0530663 }
664}
665
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100666// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000667func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100668 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000669 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700670
David Bainbridge103cf022019-12-16 20:11:35 +0000671loop:
672 for {
673 select {
674 case <-ctx.Done():
675 oltLogger.Debug("OLT Indication processing canceled via context")
676 break loop
677 case message, ok := <-ch:
678 if !ok || ctx.Err() != nil {
679 oltLogger.Debug("OLT Indication processing canceled via closed channel")
680 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700681 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700682
David Bainbridge103cf022019-12-16 20:11:35 +0000683 oltLogger.WithFields(log.Fields{
684 "oltId": o.ID,
685 "messageType": message.Type,
686 }).Trace("Received message")
687
688 switch message.Type {
689 case OltIndication:
690 msg, _ := message.Data.(OltIndicationMessage)
691 if msg.OperState == UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530692 _ = o.InternalState.Event("enable")
693 _ = o.OperState.Event("enable")
David Bainbridge103cf022019-12-16 20:11:35 +0000694 } else if msg.OperState == DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530695 _ = o.InternalState.Event("disable")
696 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000697 }
698 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800699 case AlarmIndication:
700 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
701 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000702 case NniIndication:
703 msg, _ := message.Data.(NniIndicationMessage)
704 o.sendNniIndication(msg, stream)
705 case PonIndication:
706 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530707 pon, _ := o.GetPonById(msg.PonPortID)
708 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530709 if err := pon.OperState.Event("enable"); err != nil {
710 oltLogger.WithFields(log.Fields{
711 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800712 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530713 }).Error("Can't Enable Oper state for PON Port")
714 }
715 if err := pon.InternalState.Event("enable"); err != nil {
716 oltLogger.WithFields(log.Fields{
717 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800718 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530719 }).Error("Can't Enable Internal state for PON Port")
720 }
Pragya Arya2225f202020-01-29 18:05:01 +0530721 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530722 if err := pon.OperState.Event("disable"); err != nil {
723 oltLogger.WithFields(log.Fields{
724 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800725 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530726 }).Error("Can't Disable Oper state for PON Port")
727 }
728 if err := pon.InternalState.Event("disable"); err != nil {
729 oltLogger.WithFields(log.Fields{
730 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800731 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530732 }).Error("Can't Disable Internal state for PON Port")
733 }
Pragya Arya2225f202020-01-29 18:05:01 +0530734 }
David Bainbridge103cf022019-12-16 20:11:35 +0000735 default:
736 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
737 }
738 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700739 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100740 wg.Done()
741 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700742}
743
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700744// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530745func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200746 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700747 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700748 for _, pon := range o.Pons {
749 for _, onu := range pon.Onus {
750 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700751 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700752 }
753 }
754 }
755
Shrey Baid688b4242020-07-10 20:40:10 +0530756 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700757}
758
William Kurkian9dadc5b2019-10-22 13:51:57 -0400759// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530760func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200761 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400762 // memoizing it will remove the bottleneck
763 for _, pon := range o.Pons {
764 if pon.ID == intfId {
765 for _, onu := range pon.Onus {
766 if onu.ID == onuId {
767 return onu, nil
768 }
769 }
770 }
771 }
Shrey Baid688b4242020-07-10 20:40:10 +0530772 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400773}
774
Matteo Scandolo4a036262020-08-17 15:56:13 -0700775// returns a Service with a given Mac Address
776func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200777 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700778 // memoizing it will remove the bottleneck
779 for _, pon := range o.Pons {
780 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700781 s, err := onu.findServiceByMacAddress(mac)
782 if err == nil {
783 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700784 }
785 }
786 }
787
Matteo Scandolo4a036262020-08-17 15:56:13 -0700788 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700789}
790
Matteo Scandolo4747d292019-08-05 11:50:18 -0700791// GRPC Endpoints
792
Shrey Baid688b4242020-07-10 20:40:10 +0530793func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700794 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700795 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700796 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530797 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700798
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700799 pon, _ := o.GetPonById(onu.IntfId)
800 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500801 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700802
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700803 if err := _onu.OperState.Event("enable"); err != nil {
804 oltLogger.WithFields(log.Fields{
805 "IntfId": _onu.PonPortID,
806 "OnuSn": _onu.Sn(),
807 "OnuId": _onu.ID,
808 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700809 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700810 if err := _onu.InternalState.Event("enable"); err != nil {
811 oltLogger.WithFields(log.Fields{
812 "IntfId": _onu.PonPortID,
813 "OnuSn": _onu.Sn(),
814 "OnuId": _onu.ID,
815 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
816 }
817
818 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
819
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700820 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700821}
822
Shrey Baid688b4242020-07-10 20:40:10 +0530823func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700824 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700825 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700826}
827
Shrey Baid688b4242020-07-10 20:40:10 +0530828func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530829 oltLogger.WithFields(log.Fields{
830 "IntfId": onu.IntfId,
831 "OnuId": onu.OnuId,
832 }).Info("Received DeleteOnu call from VOLTHA")
833
834 pon, err := o.GetPonById(onu.IntfId)
835 if err != nil {
836 oltLogger.WithFields(log.Fields{
837 "OnuId": onu.OnuId,
838 "IntfId": onu.IntfId,
839 "err": err,
840 }).Error("Can't find PonPort")
841 }
842 _onu, err := pon.GetOnuById(onu.OnuId)
843 if err != nil {
844 oltLogger.WithFields(log.Fields{
845 "OnuId": onu.OnuId,
846 "IntfId": onu.IntfId,
847 "err": err,
848 }).Error("Can't find Onu")
849 }
850
Hardik Windlassad790cb2020-06-17 21:26:22 +0530851 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530852 oltLogger.WithFields(log.Fields{
853 "IntfId": _onu.PonPortID,
854 "OnuSn": _onu.Sn(),
855 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530856 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
857 }
858
Hardik Windlassad790cb2020-06-17 21:26:22 +0530859 // ONU Re-Discovery
860 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530861 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530862 }
863
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700864 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700865}
866
Shrey Baid688b4242020-07-10 20:40:10 +0530867func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700868 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800869 oltLogger.WithFields(log.Fields{
870 "oltId": o.ID,
871 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530872 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800873
Matteo Scandolo401503a2019-12-11 14:48:14 -0800874 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530875 if pon.InternalState.Current() == "enabled" {
876 // disable PONs
877 msg := Message{
878 Type: PonIndication,
879 Data: PonIndicationMessage{
880 OperState: DOWN,
881 PonPortID: pon.ID,
882 },
883 }
884 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800885 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800886 }
887
Matteo Scandolo401503a2019-12-11 14:48:14 -0800888 // Note that we are not disabling the NNI as the real OLT does not.
889 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800890
891 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100892 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700893 Type: OltIndication,
894 Data: OltIndicationMessage{
895 OperState: DOWN,
896 },
897 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100898 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700899 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700900}
901
Shrey Baid688b4242020-07-10 20:40:10 +0530902func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530903 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200904 ponID := intf.GetIntfId()
905 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200906
907 msg := Message{
908 Type: PonIndication,
909 Data: PonIndicationMessage{
910 OperState: DOWN,
911 PonPortID: ponID,
912 },
913 }
914 o.channel <- msg
915
916 for _, onu := range pon.Onus {
917
918 onuIndication := OnuIndicationMessage{
919 OperState: DOWN,
920 PonPortID: ponID,
921 OnuID: onu.ID,
922 OnuSN: onu.SerialNumber,
923 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700924 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200925
926 }
927
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700928 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700929}
930
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100931func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700932 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530933 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700934 o.Enable(stream)
935 return nil
936}
937
Shrey Baid688b4242020-07-10 20:40:10 +0530938func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530939 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530940 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200941 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200942
Pragya Arya2225f202020-01-29 18:05:01 +0530943 msg := Message{
944 Type: PonIndication,
945 Data: PonIndicationMessage{
946 OperState: UP,
947 PonPortID: ponID,
948 },
949 }
950 o.channel <- msg
951
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200952 for _, onu := range pon.Onus {
953
954 onuIndication := OnuIndicationMessage{
955 OperState: UP,
956 PonPortID: ponID,
957 OnuID: onu.ID,
958 OnuSN: onu.SerialNumber,
959 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700960 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200961
962 }
963
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700964 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700965}
966
Shrey Baid688b4242020-07-10 20:40:10 +0530967func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700968 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700969 "IntfId": flow.AccessIntfId,
970 "OnuId": flow.OnuId,
971 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700972 "InnerVlan": flow.Classifier.IVid,
973 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700974 "FlowType": flow.FlowType,
975 "FlowId": flow.FlowId,
976 "UniID": flow.UniId,
977 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +0530978 }).Tracef("OLT receives FlowAdd")
979
980 flowKey := FlowKey{}
981 if !o.enablePerf {
982 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
983 olt.Flows[flowKey] = *flow
984 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700985
986 if flow.AccessIntfId == -1 {
987 oltLogger.WithFields(log.Fields{
988 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700989 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -0700990 } else if flow.FlowType == "multicast" {
991 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -0700992 "Cookie": flow.Cookie,
993 "DstPort": flow.Classifier.DstPort,
994 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
995 "FlowId": flow.FlowId,
996 "FlowType": flow.FlowType,
997 "GemportId": flow.GemportId,
998 "InnerVlan": flow.Classifier.IVid,
999 "IntfId": flow.AccessIntfId,
1000 "IpProto": flow.Classifier.IpProto,
1001 "OnuId": flow.OnuId,
1002 "OuterVlan": flow.Classifier.OVid,
1003 "PortNo": flow.PortNo,
1004 "SrcPort": flow.Classifier.SrcPort,
1005 "UniID": flow.UniId,
1006 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001007 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001008 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001009 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001010 if err != nil {
1011 oltLogger.WithFields(log.Fields{
1012 "OnuId": flow.OnuId,
1013 "IntfId": flow.AccessIntfId,
1014 "err": err,
1015 }).Error("Can't find PonPort")
1016 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001017 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001018 if err != nil {
1019 oltLogger.WithFields(log.Fields{
1020 "OnuId": flow.OnuId,
1021 "IntfId": flow.AccessIntfId,
1022 "err": err,
1023 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001024 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001025 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301026 if !o.enablePerf {
1027 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301028 // Generate event on first flow for ONU
1029 if len(onu.Flows) == 1 {
1030 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1031 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301032 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001033
1034 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001035 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001036 Data: OnuFlowUpdateMessage{
1037 PonPortID: pon.ID,
1038 OnuID: onu.ID,
1039 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001040 },
1041 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001042 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001043 }
1044
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001045 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001046}
1047
Pragya Arya8bdb4532020-03-02 17:08:09 +05301048// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301049func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001050
Pragya Arya8bdb4532020-03-02 17:08:09 +05301051 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301052 "FlowId": flow.FlowId,
1053 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001054 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301055
1056 if !o.enablePerf { // remove only if flow were stored
1057 flowKey := FlowKey{
1058 ID: flow.FlowId,
1059 Direction: flow.FlowType,
1060 }
1061
1062 // Check if flow exists
1063 storedFlow, ok := o.Flows[flowKey]
1064 if !ok {
1065 oltLogger.Errorf("Flow %v not found", flow)
1066 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1067 }
1068
1069 // if its ONU flow remove it from ONU also
1070 if storedFlow.AccessIntfId != -1 {
1071 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1072 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1073 if err != nil {
1074 oltLogger.WithFields(log.Fields{
1075 "OnuId": storedFlow.OnuId,
1076 "IntfId": storedFlow.AccessIntfId,
1077 "err": err,
1078 }).Error("ONU not found")
1079 return new(openolt.Empty), nil
1080 }
1081 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301082 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301083 }
1084
1085 // delete from olt flows
1086 delete(o.Flows, flowKey)
1087 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001088
1089 if flow.AccessIntfId == -1 {
1090 oltLogger.WithFields(log.Fields{
1091 "FlowId": flow.FlowId,
1092 }).Debug("Removing OLT flow")
1093 } else if flow.FlowType == "multicast" {
1094 oltLogger.WithFields(log.Fields{
1095 "FlowId": flow.FlowId,
1096 }).Debug("Removing OLT multicast flow")
1097 } else {
1098
1099 onu, err := o.GetOnuByFlowId(flow.FlowId)
1100 if err != nil {
1101 oltLogger.WithFields(log.Fields{
1102 "OnuId": flow.OnuId,
1103 "IntfId": flow.AccessIntfId,
1104 "err": err,
1105 }).Error("Can't find Onu")
1106 return nil, err
1107 }
1108
1109 msg := Message{
1110 Type: FlowRemoved,
1111 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301112 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001113 },
1114 }
1115 onu.Channel <- msg
1116 }
1117
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001118 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001119}
1120
Shrey Baid688b4242020-07-10 20:40:10 +05301121func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001122 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1123 oltLogger.WithFields(log.Fields{
1124 "signature": res.HeartbeatSignature,
1125 }).Trace("HeartbeatCheck")
1126 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001127}
1128
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001129func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001130 for _, pon := range o.Pons {
1131 for _, onu := range pon.Onus {
1132 for _, fId := range onu.FlowIds {
1133 if fId == flowId {
1134 return onu, nil
1135 }
1136 }
1137 }
1138 }
Shrey Baid688b4242020-07-10 20:40:10 +05301139 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001140}
1141
Shrey Baid688b4242020-07-10 20:40:10 +05301142func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001143
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001144 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001145 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001146 "PonPorts": o.NumPon,
1147 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001148 devinfo := new(openolt.DeviceInfo)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001149 devinfo.Vendor = common.Config.Olt.Vendor
1150 devinfo.Model = common.Config.Olt.Model
1151 devinfo.HardwareVersion = common.Config.Olt.HardwareVersion
1152 devinfo.FirmwareVersion = common.Config.Olt.FirmwareVersion
1153 devinfo.Technology = common.Config.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001154 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001155 devinfo.OnuIdStart = 1
1156 devinfo.OnuIdEnd = 255
1157 devinfo.AllocIdStart = 1024
1158 devinfo.AllocIdEnd = 16383
1159 devinfo.GemportIdStart = 1024
1160 devinfo.GemportIdEnd = 65535
1161 devinfo.FlowIdStart = 1
1162 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001163 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4a036262020-08-17 15:56:13 -07001164 devinfo.DeviceId = common.Config.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001165
1166 return devinfo, nil
1167}
1168
Shrey Baid688b4242020-07-10 20:40:10 +05301169func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001170 pon, err := o.GetPonById(omci_msg.IntfId)
1171 if err != nil {
1172 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001173 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001174 "onu_id": omci_msg.OnuId,
1175 "pon_id": omci_msg.IntfId,
1176 }).Error("pon ID not found")
1177 return nil, err
1178 }
1179
1180 onu, err := pon.GetOnuById(omci_msg.OnuId)
1181 if err != nil {
1182 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001183 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001184 "onu_id": omci_msg.OnuId,
1185 "pon_id": omci_msg.IntfId,
1186 }).Error("onu ID not found")
1187 return nil, err
1188 }
1189
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001190 oltLogger.WithFields(log.Fields{
1191 "IntfId": onu.PonPortID,
1192 "OnuId": onu.ID,
1193 "OnuSn": onu.Sn(),
1194 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001195 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001196 Type: OMCI,
1197 Data: OmciMessage{
1198 OnuSN: onu.SerialNumber,
1199 OnuID: onu.ID,
1200 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001201 },
1202 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001203 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001204 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001205}
1206
Shrey Baid688b4242020-07-10 20:40:10 +05301207func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001208 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001209 if err != nil {
1210 oltLogger.WithFields(log.Fields{
1211 "OnuId": onuPkt.OnuId,
1212 "IntfId": onuPkt.IntfId,
1213 "err": err,
1214 }).Error("Can't find PonPort")
1215 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001216 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001217 if err != nil {
1218 oltLogger.WithFields(log.Fields{
1219 "OnuId": onuPkt.OnuId,
1220 "IntfId": onuPkt.IntfId,
1221 "err": err,
1222 }).Error("Can't find Onu")
1223 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001224
Matteo Scandolo075b1892019-10-07 12:11:07 -07001225 oltLogger.WithFields(log.Fields{
1226 "IntfId": onu.PonPortID,
1227 "OnuId": onu.ID,
1228 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001229 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001230 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001231
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001232 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001233
1234 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001235 if err != nil {
1236 onuLogger.WithFields(log.Fields{
1237 "IntfId": onu.PonPortID,
1238 "OnuId": onu.ID,
1239 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001240 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001241 }).Error("Can't find pktType in packet, droppint it")
1242 return new(openolt.Empty), nil
1243 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001244
Matteo Scandolo4a036262020-08-17 15:56:13 -07001245 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001246 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001247 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001248 "IntfId": onu.PonPortID,
1249 "OnuId": onu.ID,
1250 "OnuSn": onu.Sn(),
1251 "Pkt": rawpkt.Data(),
1252 }).Error("Can't find Dst MacAddress in packet, droppint it")
1253 return new(openolt.Empty), nil
1254 }
1255
Matteo Scandolo075b1892019-10-07 12:11:07 -07001256 msg := Message{
1257 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001258 Data: OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001259 IntfId: onuPkt.IntfId,
1260 OnuId: onuPkt.OnuId,
1261 Packet: rawpkt,
1262 Type: pktType,
1263 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001264 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001265 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001266
Matteo Scandolo075b1892019-10-07 12:11:07 -07001267 onu.Channel <- msg
1268
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001269 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001270}
1271
Shrey Baid688b4242020-07-10 20:40:10 +05301272func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001273
1274 // OLT Reboot is called in two cases:
1275 // - 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)
1276 // - when an OLT needs to be rebooted (voltcl device reboot)
1277
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001278 oltLogger.WithFields(log.Fields{
1279 "oltId": o.ID,
1280 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301281 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301282 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001283 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001284}
1285
Shrey Baid688b4242020-07-10 20:40:10 +05301286func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301287 oltLogger.WithFields(log.Fields{
1288 "oltId": o.ID,
1289 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301290 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301291
Pragya Arya2225f202020-01-29 18:05:01 +05301292 // enable OLT
1293 oltMsg := Message{
1294 Type: OltIndication,
1295 Data: OltIndicationMessage{
1296 OperState: UP,
1297 },
Pragya Arya1881df02020-01-29 18:05:01 +05301298 }
Pragya Arya2225f202020-01-29 18:05:01 +05301299 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301300
Pragya Arya2225f202020-01-29 18:05:01 +05301301 for _, pon := range o.Pons {
1302 if pon.InternalState.Current() == "disabled" {
1303 msg := Message{
1304 Type: PonIndication,
1305 Data: PonIndicationMessage{
1306 OperState: UP,
1307 PonPortID: pon.ID,
1308 },
1309 }
1310 o.channel <- msg
1311 }
1312 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001313
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001314 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001315}
1316
Shrey Baid688b4242020-07-10 20:40:10 +05301317func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001318 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1319
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001320 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1321
1322 if err != nil {
1323 return nil, err
1324 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001325 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001326}
1327
Shrey Baid688b4242020-07-10 20:40:10 +05301328func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001329 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001330 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001331}
1332
Shrey Baid688b4242020-07-10 20:40:10 +05301333func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001334 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001335 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001336}
1337
Shrey Baid688b4242020-07-10 20:40:10 +05301338func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001339 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001340 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001341}
1342
Shrey Baid688b4242020-07-10 20:40:10 +05301343func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001344 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001345 return new(openolt.Empty), nil
1346}
1347
Shrey Baid688b4242020-07-10 20:40:10 +05301348func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001349 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001350 return new(openolt.Empty), nil
1351}
1352
Shrey Baid688b4242020-07-10 20:40:10 +05301353func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301354 oltLogger.WithFields(log.Fields{
1355 "OnuId": trafficSchedulers.OnuId,
1356 "IntfId": trafficSchedulers.IntfId,
1357 "OnuPortNo": trafficSchedulers.PortNo,
1358 }).Info("received CreateTrafficSchedulers")
1359
1360 if !s.enablePerf {
1361 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1362 if err != nil {
1363 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1364 return new(openolt.Empty), err
1365 }
1366 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1367 if err != nil {
1368 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1369 return new(openolt.Empty), err
1370 }
1371 onu.TrafficSchedulers = trafficSchedulers
1372 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001373 return new(openolt.Empty), nil
1374}
1375
Shrey Baid688b4242020-07-10 20:40:10 +05301376func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301377 oltLogger.WithFields(log.Fields{
1378 "OnuId": trafficSchedulers.OnuId,
1379 "IntfId": trafficSchedulers.IntfId,
1380 "OnuPortNo": trafficSchedulers.PortNo,
1381 }).Info("received RemoveTrafficSchedulers")
1382 if !s.enablePerf {
1383 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1384 if err != nil {
1385 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1386 return new(openolt.Empty), err
1387 }
1388 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1389 if err != nil {
1390 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1391 return new(openolt.Empty), err
1392 }
1393
1394 onu.TrafficSchedulers = nil
1395 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001396 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001397}
Scott Baker41724b82020-01-21 19:54:53 -08001398
1399// assumes caller has properly formulated an openolt.AlarmIndication
Shrey Baid688b4242020-07-10 20:40:10 +05301400func (o *OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
Scott Baker41724b82020-01-21 19:54:53 -08001401 msg := Message{
1402 Type: AlarmIndication,
1403 Data: ind,
1404 }
1405
1406 o.channel <- msg
1407 return nil
1408}
Matteo Scandolo618a6582020-09-09 12:21:29 -07001409
1410func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1411 oltLogger.WithFields(log.Fields{
1412 "GroupId": group.GroupId,
1413 "Command": group.Command,
1414 "Members": group.Members,
1415 "Action": group.Action,
1416 }).Debug("received PerformGroupOperation")
1417 return &openolt.Empty{}, nil
1418}
1419
1420func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1421 oltLogger.WithFields(log.Fields{
1422 "GroupId": group.GroupId,
1423 "Command": group.Command,
1424 "Members": group.Members,
1425 "Action": group.Action,
1426 }).Debug("received PerformGroupOperation")
1427 return &openolt.Empty{}, nil
1428}
1429
1430func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1431 return &common_protos.ReturnValues{}, nil
1432}
1433
1434func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1435 return &openolt.Empty{}, nil
1436}
1437
1438func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1439 return &openolt.OnuLogicalDistance{}, nil
1440}
1441
1442func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1443 return &openolt.OnuLogicalDistance{}, nil
1444}