blob: 746a58ba452444f3c9c89de0bf161fa488784bab [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"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020023 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080024 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020025 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010026 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020027
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000028 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
29 "github.com/opencord/bbsim/internal/bbsim/types"
30 omcilib "github.com/opencord/bbsim/internal/common/omci"
31 "github.com/opencord/voltha-protos/v4/go/ext/config"
32
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070033 "github.com/google/gopacket"
34 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070035 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070036 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010037 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070038 common_protos "github.com/opencord/voltha-protos/v4/go/common"
39 "github.com/opencord/voltha-protos/v4/go/openolt"
40 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070041 log "github.com/sirupsen/logrus"
42 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053043 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010044 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053045 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070046)
47
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070048var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070049 "module": "OLT",
50})
51
Matteo Scandolocedde462021-03-09 17:37:16 -080052const (
53 onuIdStart = 1
54 onuIdEnd = 127
55 allocIdStart = 1024
56 allocIdEnd = 16383
57 gemportIdStart = 1024
58 gemportIdEnd = 65535
59 flowIdStart = 1
60 flowIdEnd = 65535
61)
62
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070063type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000064 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000065 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000066
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070067 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053068 ID int
69 SerialNumber string
70 NumNni int
71 NumPon int
72 NumOnuPerPon int
73 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080074 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070075 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010076 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053077 Delay int
78 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053079 EventChannel chan common.Event
80 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053081 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080082 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070083
Matteo Scandolo27428702019-10-11 16:21:16 -070084 Pons []*PonPort
85 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070086
87 // OLT Attributes
88 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000089
90 enableContext context.Context
91 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053092
Matteo Scandolo4a036262020-08-17 15:56:13 -070093 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053094 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080095
96 // Allocated Resources
97 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000098 AllocIDsLock sync.RWMutex
99 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
100 GemPortIDsLock sync.RWMutex
101 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
102 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700103}
104
Matteo Scandolo27428702019-10-11 16:21:16 -0700105var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700106
Matteo Scandolo27428702019-10-11 16:21:16 -0700107func GetOLT() *OltDevice {
108 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700109}
110
Matteo Scandolo4a036262020-08-17 15:56:13 -0700111func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700112 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530113 "ID": options.Olt.ID,
114 "NumNni": options.Olt.NniPorts,
115 "NumPon": options.Olt.PonPorts,
116 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700117 }).Debug("CreateOLT")
118
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700119 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530120 ID: options.Olt.ID,
121 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700122 OperState: getOperStateFSM(func(e *fsm.Event) {
123 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
124 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800125 NumNni: int(options.Olt.NniPorts),
126 NumPon: int(options.Olt.PonPorts),
127 NumOnuPerPon: int(options.Olt.OnusPonPort),
128 Pons: []*PonPort{},
129 Nnis: []*NniPort{},
130 Delay: options.BBSim.Delay,
131 enablePerf: options.BBSim.EnablePerf,
132 PublishEvents: options.BBSim.Events,
133 PortStatsInterval: options.Olt.PortStatsInterval,
134 dhcpServer: dhcp.NewDHCPServer(),
135 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800136 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
137 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000138 OmciResponseRate: options.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700139 }
140
Pragya Arya996a0892020-03-09 21:47:52 +0530141 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530142 olt.ControlledActivation = val
143 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700144 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530145 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
146 olt.ControlledActivation = Default
147 }
148
Matteo Scandolo4747d292019-08-05 11:50:18 -0700149 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700150 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700151 olt.InternalState = fsm.NewFSM(
152 "created",
153 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800154 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100155 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700156 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700157 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800158 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159 },
160 fsm.Callbacks{
161 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700162 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700163 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100164 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800165 "enter_deleted": func(e *fsm.Event) {
166 // remove all the resource allocations
167 olt.clearAllResources()
168 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700169 },
170 )
171
Shrey Baid688b4242020-07-10 20:40:10 +0530172 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700173 // create NNI Port
174 nniPort, err := CreateNNI(&olt)
175 if err != nil {
176 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
177 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700178
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700179 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700180 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700181
Matteo Scandolo4a036262020-08-17 15:56:13 -0700182 // Create device and Services
183
184 nextCtag := map[string]int{}
185 nextStag := map[string]int{}
186
Matteo Scandolo4747d292019-08-05 11:50:18 -0700187 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700188 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800189
190 // initialize the resource maps for every PON Ports
191 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
192 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
193
Matteo Scandolo4a036262020-08-17 15:56:13 -0700194 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700195
Matteo Scandolo4a036262020-08-17 15:56:13 -0700196 // create ONU devices
197 for j := 0; j < olt.NumOnuPerPon; j++ {
198 delay := time.Duration(olt.Delay*j) * time.Millisecond
199 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700200
Matteo Scandolo4a036262020-08-17 15:56:13 -0700201 for k, s := range common.Services {
202
203 // find the correct cTag for this service
204 if _, ok := nextCtag[s.Name]; !ok {
205 // it's the first time we iterate over this service,
206 // so we start from the config value
207 nextCtag[s.Name] = s.CTag
208 } else {
209 // we have a previous value, so we check it
210 // if Allocation is unique, we increment,
211 // otherwise (shared) we do nothing
212 if s.CTagAllocation == common.TagAllocationUnique.String() {
213 nextCtag[s.Name] = nextCtag[s.Name] + 1
214 }
215 }
216
217 // find the correct sTag for this service
218 if _, ok := nextStag[s.Name]; !ok {
219 nextStag[s.Name] = s.STag
220 } else {
221 if s.STagAllocation == common.TagAllocationUnique.String() {
222 nextStag[s.Name] = nextStag[s.Name] + 1
223 }
224 }
225
226 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
227 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
228 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
229 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
230
231 if err != nil {
232 oltLogger.WithFields(log.Fields{
233 "Err": err.Error(),
234 }).Fatal("Can't create Service")
235 }
236
237 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700238 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700239 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700240 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700241 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700242 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243
Shrey Baid688b4242020-07-10 20:40:10 +0530244 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700245 if err := olt.InternalState.Event("initialize"); err != nil {
246 log.Errorf("Error initializing OLT: %v", err)
247 return nil
248 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100249 }
250
Pragya Arya324337e2020-02-20 14:35:08 +0530251 if olt.PublishEvents {
252 log.Debugf("BBSim event publishing is enabled")
253 // Create a channel to write event messages
254 olt.EventChannel = make(chan common.Event, 100)
255 }
256
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700257 return &olt
258}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700259
Shrey Baid688b4242020-07-10 20:40:10 +0530260func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100261
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000262 if o.OltServer == nil {
263 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100264 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800265 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100266 }
267
268 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800269 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100270
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100271 // FIXME we are assuming we have only one NNI
272 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800273 // NOTE we want to make sure the state is down when we initialize the OLT,
274 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
275 // in-band management
276 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100277 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800278
279 for ponId := range o.Pons {
280 // initialize the resource maps for every PON Ports
281 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
282 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
283 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700284}
285
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800286func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100287
Matteo Scandolo96f89192021-03-12 13:17:26 -0800288 o.PreviouslyConnected = false
289
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700290 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700291 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800292
293 oltLogger.WithFields(log.Fields{
294 "oltId": o.ID,
295 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
296
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700297 if o.InternalState.Is("enabled") {
298 oltLogger.WithFields(log.Fields{
299 "oltId": o.ID,
300 }).Info("This is an OLT soft reboot")
301 softReboot = true
302 }
303
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800304 // transition internal state to deleted
305 if err := o.InternalState.Event("delete"); err != nil {
306 oltLogger.WithFields(log.Fields{
307 "oltId": o.ID,
308 }).Errorf("Error deleting OLT: %v", err)
309 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100310 }
311
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800312 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 -0800313 o.StopOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100314
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700315 if softReboot {
316 for _, pon := range o.Pons {
317 if pon.InternalState.Current() == "enabled" {
318 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800319 msg := types.Message{
320 Type: types.PonIndication,
321 Data: types.PonIndicationMessage{
322 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700323 PonPortID: pon.ID,
324 },
325 }
326 o.channel <- msg
327 }
328
329 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800330 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700331 }
332 }
333 } else {
334 // PONs are already handled in the Disable call
335 for _, pon := range olt.Pons {
336 // ONUs are not automatically disabled when a PON goes down
337 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
338 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800339 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700340 }
Pragya Arya2225f202020-01-29 18:05:01 +0530341 }
342 }
343
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100344 // terminate the OLT's processOltMessages go routine
345 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700346
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700347 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100348
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100349 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100350
351 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800352 oltLogger.WithFields(log.Fields{
353 "oltId": o.ID,
354 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100355 return err
356 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800357 oltLogger.WithFields(log.Fields{
358 "oltId": o.ID,
359 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100360 return nil
361}
362
363// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800364func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700365 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700366 lis, err := net.Listen("tcp", address)
367 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700368 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700369 }
370 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100371
Matteo Scandolo4747d292019-08-05 11:50:18 -0700372 openolt.RegisterOpenoltServer(grpcServer, o)
373
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100374 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700375
Shrey Baid688b4242020-07-10 20:40:10 +0530376 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100377 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700378
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100379 return grpcServer, nil
380}
381
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800382// StartOltServer will create the grpc server that VOLTHA uses
383// to communicate with the device
384func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
385 oltServer, err := o.newOltServer()
386 if err != nil {
387 oltLogger.WithFields(log.Fields{
388 "err": err,
389 }).Error("Cannot OLT gRPC server")
390 return nil, err
391 }
392 return oltServer, nil
393}
394
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100395// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800396func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000397 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800398 oltLogger.WithFields(log.Fields{
399 "oltId": o.SerialNumber,
400 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000401 o.OltServer.Stop()
402 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700403 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700404}
405
406// Device Methods
407
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100408// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530409func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700410 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530411 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700412
David Bainbridge103cf022019-12-16 20:11:35 +0000413 // If enabled has already been called then an enabled context has
414 // been created. If this is the case then we want to cancel all the
415 // proessing loops associated with that enable before we recreate
416 // new ones
417 o.Lock()
418 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700419 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000420 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530421 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700422 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000423 }
424 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
425 o.Unlock()
426
Matteo Scandolo4747d292019-08-05 11:50:18 -0700427 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700428
Matteo Scandolo4a036262020-08-17 15:56:13 -0700429 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530430
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100431 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700432 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000433 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700434
435 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800436 oltMsg := types.Message{
437 Type: types.OltIndication,
438 Data: types.OltIndicationMessage{
439 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700440 },
441 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100442 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700443
444 // send NNI Port Indications
445 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800446 msg := types.Message{
447 Type: types.NniIndication,
448 Data: types.NniIndicationMessage{
449 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700450 NniPortID: nni.ID,
451 },
452 }
453 o.channel <- msg
454 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100455
Shrey Baid688b4242020-07-10 20:40:10 +0530456 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530457 for _, pon := range o.Pons {
458 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800459 msg := types.Message{
460 Type: types.PonIndication,
461 Data: types.PonIndicationMessage{
462 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530463 PonPortID: pon.ID,
464 },
465 }
466 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000467 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700468 // when the enableContext was canceled the ONUs stopped listening on the channel
469 for _, onu := range pon.Onus {
470 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
471
472 // update the stream on all the services
473 for _, service := range onu.Services {
474 service.UpdateStream(stream)
475 }
476 }
Pragya Arya2225f202020-01-29 18:05:01 +0530477 }
478 } else {
479
480 // 1. controlledActivation == Default: Send both PON and ONUs indications
481 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
482
483 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
484 // send PON Port indications
485 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800486 msg := types.Message{
487 Type: types.PonIndication,
488 Data: types.PonIndicationMessage{
489 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530490 PonPortID: pon.ID,
491 },
492 }
493 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700494 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700495 }
496 }
497
Pragya Arya996a0892020-03-09 21:47:52 +0530498 if !o.enablePerf {
499 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700500 wg.Add(1)
501 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530502 }
503
Matteo Scandolo4747d292019-08-05 11:50:18 -0700504 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700505 oltLogger.WithFields(log.Fields{
506 "stream": stream,
507 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700508}
509
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700510func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530511 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700512
513loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530514 for {
515 select {
516 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
517 // send NNI port stats
518 for _, port := range o.Nnis {
519 incrementStat := true
520 if port.OperState.Current() == "down" {
521 incrementStat = false
522 }
523 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700524 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530525 }
526
527 // send PON port stats
528 for _, port := range o.Pons {
529 incrementStat := true
530 // do not increment port stats if PON port is down or no ONU is activated on PON port
531 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
532 incrementStat = false
533 }
534 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700535 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530536 }
537 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700538 oltLogger.Debug("Stop sending port stats")
539 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530540 }
Pragya Arya996a0892020-03-09 21:47:52 +0530541 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700542 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530543}
544
Matteo Scandolo4747d292019-08-05 11:50:18 -0700545// Helpers method
546
Matteo Scandolof9d43412021-01-12 11:11:34 -0800547func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
548
549 switch interfaceType {
550 case "nni":
551 if !o.HasNni(interfaceId) {
552 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
553 }
554
555 case "pon":
556 if !o.HasPon(interfaceId) {
557 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
558 }
559 }
560
561 alarmIndication := &openolt.AlarmIndication{
562 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
563 Status: alarmStatus,
564 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
565 }},
566 }
567
568 msg := types.Message{
569 Type: types.AlarmIndication,
570 Data: alarmIndication,
571 }
572
573 o.channel <- msg
574
575 return nil
576}
577
578func (o *OltDevice) HasNni(id uint32) bool {
579 for _, intf := range o.Nnis {
580 if intf.ID == id {
581 return true
582 }
583 }
584 return false
585}
586
587func (o *OltDevice) HasPon(id uint32) bool {
588 for _, intf := range o.Pons {
589 if intf.ID == id {
590 return true
591 }
592 }
593 return false
594}
595
Shrey Baid688b4242020-07-10 20:40:10 +0530596func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700597 for _, pon := range o.Pons {
598 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700599 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700600 }
601 }
Shrey Baid688b4242020-07-10 20:40:10 +0530602 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700603}
604
Shrey Baid688b4242020-07-10 20:40:10 +0530605func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700606 for _, nni := range o.Nnis {
607 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700608 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 }
610 }
Shrey Baid688b4242020-07-10 20:40:10 +0530611 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612}
613
Scott Baker41724b82020-01-21 19:54:53 -0800614func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
615 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
616 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
617 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
618 return
619 }
620
621 oltLogger.WithFields(log.Fields{
622 "AlarmIndication": alarmInd,
623 }).Debug("Sent Indication_AlarmInd")
624}
625
Matteo Scandolof9d43412021-01-12 11:11:34 -0800626func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700627 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
628 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700629 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800630 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700631 }
632
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700633 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700634 "OperState": msg.OperState,
635 }).Debug("Sent Indication_OltInd")
636}
637
Matteo Scandolof9d43412021-01-12 11:11:34 -0800638func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700639 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800640 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800641 if err := nni.OperState.Event("enable"); err != nil {
642 log.WithFields(log.Fields{
643 "Type": nni.Type,
644 "IntfId": nni.ID,
645 "OperState": nni.OperState.Current(),
646 }).Errorf("Can't move NNI Port to enabled state: %v", err)
647 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800648 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800649 if err := nni.OperState.Event("disable"); err != nil {
650 log.WithFields(log.Fields{
651 "Type": nni.Type,
652 "IntfId": nni.ID,
653 "OperState": nni.OperState.Current(),
654 }).Errorf("Can't move NNI Port to disable state: %v", err)
655 }
656 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700657 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700658 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700659 Type: nni.Type,
660 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700661 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700662 }}
663
664 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700665 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800666 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700667 }
668
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700669 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700670 "Type": nni.Type,
671 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700672 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700673 }).Debug("Sent Indication_IntfOperInd for NNI")
674}
675
Pragya Arya2225f202020-01-29 18:05:01 +0530676func (o *OltDevice) sendPonIndication(ponPortID uint32) {
677
Matteo Scandolo4a036262020-08-17 15:56:13 -0700678 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530679 pon, _ := o.GetPonById(ponPortID)
680 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700681 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700682 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700683 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700684 }}
685
686 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700687 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800688 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700689 }
690
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700691 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700692 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700693 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700694 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700695
Pragya Arya2225f202020-01-29 18:05:01 +0530696 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700697 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700698 Type: pon.Type,
699 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700700 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700701 }}
702
703 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700704 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800705 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700706 }
707
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700708 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700709 "Type": pon.Type,
710 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700711 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700712 }).Debug("Sent Indication_IntfOperInd for PON")
713}
714
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700715func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530716 if o.InternalState.Current() == "enabled" {
717 oltLogger.WithFields(log.Fields{
718 "Type": portType,
719 "IntfId": portID,
720 }).Trace("Sending port stats")
721 stats.IntfId = InterfaceIDToPortNo(portID, portType)
722 data := &openolt.Indication_PortStats{
723 PortStats: stats,
724 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700725
Shrey Baid55f328c2020-07-07 19:20:42 +0530726 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
727 oltLogger.Errorf("Failed to send PortStats: %v", err)
728 return
729 }
Pragya Arya996a0892020-03-09 21:47:52 +0530730 }
731}
732
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100733// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700734func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
735 oltLogger.WithFields(log.Fields{
736 "stream": stream,
737 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000738 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700739
David Bainbridge103cf022019-12-16 20:11:35 +0000740loop:
741 for {
742 select {
743 case <-ctx.Done():
744 oltLogger.Debug("OLT Indication processing canceled via context")
745 break loop
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700746 case <-stream.Context().Done():
747 oltLogger.Debug("OLT Indication processing canceled via stream context")
748 break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000749 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700750 if !ok {
751 if ctx.Err() != nil {
752 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
753 }
754 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000755 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700756 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700757
David Bainbridge103cf022019-12-16 20:11:35 +0000758 oltLogger.WithFields(log.Fields{
759 "oltId": o.ID,
760 "messageType": message.Type,
761 }).Trace("Received message")
762
763 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800764 case types.OltIndication:
765 msg, _ := message.Data.(types.OltIndicationMessage)
766 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530767 _ = o.InternalState.Event("enable")
768 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800769 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530770 _ = o.InternalState.Event("disable")
771 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000772 }
773 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800774 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800775 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
776 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800777 case types.NniIndication:
778 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000779 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800780 case types.PonIndication:
781 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530782 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800783 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530784 if err := pon.OperState.Event("enable"); err != nil {
785 oltLogger.WithFields(log.Fields{
786 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800787 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530788 }).Error("Can't Enable Oper state for PON Port")
789 }
790 if err := pon.InternalState.Event("enable"); err != nil {
791 oltLogger.WithFields(log.Fields{
792 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800793 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530794 }).Error("Can't Enable Internal state for PON Port")
795 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800796 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530797 if err := pon.OperState.Event("disable"); err != nil {
798 oltLogger.WithFields(log.Fields{
799 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800800 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530801 }).Error("Can't Disable Oper state for PON Port")
802 }
803 if err := pon.InternalState.Event("disable"); err != nil {
804 oltLogger.WithFields(log.Fields{
805 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800806 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530807 }).Error("Can't Disable Internal state for PON Port")
808 }
Pragya Arya2225f202020-01-29 18:05:01 +0530809 }
David Bainbridge103cf022019-12-16 20:11:35 +0000810 default:
811 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
812 }
813 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700814 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100815 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700816 oltLogger.WithFields(log.Fields{
817 "stream": stream,
818 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700819}
820
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700821// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530822func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200823 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700824 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700825 for _, pon := range o.Pons {
826 for _, onu := range pon.Onus {
827 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700828 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700829 }
830 }
831 }
832
Shrey Baid688b4242020-07-10 20:40:10 +0530833 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700834}
835
William Kurkian9dadc5b2019-10-22 13:51:57 -0400836// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530837func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200838 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400839 // memoizing it will remove the bottleneck
840 for _, pon := range o.Pons {
841 if pon.ID == intfId {
842 for _, onu := range pon.Onus {
843 if onu.ID == onuId {
844 return onu, nil
845 }
846 }
847 }
848 }
Shrey Baid688b4242020-07-10 20:40:10 +0530849 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400850}
851
Matteo Scandolo4a036262020-08-17 15:56:13 -0700852// returns a Service with a given Mac Address
853func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200854 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700855 // memoizing it will remove the bottleneck
856 for _, pon := range o.Pons {
857 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700858 s, err := onu.findServiceByMacAddress(mac)
859 if err == nil {
860 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700861 }
862 }
863 }
864
Matteo Scandolo4a036262020-08-17 15:56:13 -0700865 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700866}
867
Matteo Scandolo4747d292019-08-05 11:50:18 -0700868// GRPC Endpoints
869
Shrey Baid688b4242020-07-10 20:40:10 +0530870func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700871 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700872 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700873 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530874 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700875
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700876 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800877
878 // Initialize the resource maps for this ONU
879 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
880 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
881
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700882 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500883 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700884
Matteo Scandolocedde462021-03-09 17:37:16 -0800885 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700886 oltLogger.WithFields(log.Fields{
887 "IntfId": _onu.PonPortID,
888 "OnuSn": _onu.Sn(),
889 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800890 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700891 }
892
893 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
894
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700895 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700896}
897
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800898func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700899 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700900 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700901}
902
Shrey Baid688b4242020-07-10 20:40:10 +0530903func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530904 oltLogger.WithFields(log.Fields{
905 "IntfId": onu.IntfId,
906 "OnuId": onu.OnuId,
907 }).Info("Received DeleteOnu call from VOLTHA")
908
909 pon, err := o.GetPonById(onu.IntfId)
910 if err != nil {
911 oltLogger.WithFields(log.Fields{
912 "OnuId": onu.OnuId,
913 "IntfId": onu.IntfId,
914 "err": err,
915 }).Error("Can't find PonPort")
916 }
917 _onu, err := pon.GetOnuById(onu.OnuId)
918 if err != nil {
919 oltLogger.WithFields(log.Fields{
920 "OnuId": onu.OnuId,
921 "IntfId": onu.IntfId,
922 "err": err,
923 }).Error("Can't find Onu")
924 }
925
Matteo Scandolocedde462021-03-09 17:37:16 -0800926 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530927 oltLogger.WithFields(log.Fields{
928 "IntfId": _onu.PonPortID,
929 "OnuSn": _onu.Sn(),
930 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800931 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530932 }
933
Hardik Windlassad790cb2020-06-17 21:26:22 +0530934 // ONU Re-Discovery
935 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530936 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530937 }
938
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700939 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700940}
941
Shrey Baid688b4242020-07-10 20:40:10 +0530942func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700943 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800944 oltLogger.WithFields(log.Fields{
945 "oltId": o.ID,
946 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530947 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800948
Matteo Scandolo401503a2019-12-11 14:48:14 -0800949 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530950 if pon.InternalState.Current() == "enabled" {
951 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800952 msg := types.Message{
953 Type: types.PonIndication,
954 Data: types.PonIndicationMessage{
955 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530956 PonPortID: pon.ID,
957 },
958 }
959 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800960 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800961 }
962
Matteo Scandolo401503a2019-12-11 14:48:14 -0800963 // Note that we are not disabling the NNI as the real OLT does not.
964 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800965
966 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800967 oltMsg := types.Message{
968 Type: types.OltIndication,
969 Data: types.OltIndicationMessage{
970 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700971 },
972 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100973 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700974 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700975}
976
Shrey Baid688b4242020-07-10 20:40:10 +0530977func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530978 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200979 ponID := intf.GetIntfId()
980 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200981
Matteo Scandolof9d43412021-01-12 11:11:34 -0800982 msg := types.Message{
983 Type: types.PonIndication,
984 Data: types.PonIndicationMessage{
985 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200986 PonPortID: ponID,
987 },
988 }
989 o.channel <- msg
990
991 for _, onu := range pon.Onus {
992
Matteo Scandolof9d43412021-01-12 11:11:34 -0800993 onuIndication := types.OnuIndicationMessage{
994 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200995 PonPortID: ponID,
996 OnuID: onu.ID,
997 OnuSN: onu.SerialNumber,
998 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700999 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001000
1001 }
1002
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001003 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001004}
1005
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001006func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001007 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301008 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001009 o.Enable(stream)
1010 return nil
1011}
1012
Shrey Baid688b4242020-07-10 20:40:10 +05301013func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301014 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301015 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001016 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001017
Matteo Scandolof9d43412021-01-12 11:11:34 -08001018 msg := types.Message{
1019 Type: types.PonIndication,
1020 Data: types.PonIndicationMessage{
1021 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301022 PonPortID: ponID,
1023 },
1024 }
1025 o.channel <- msg
1026
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001027 for _, onu := range pon.Onus {
1028
Matteo Scandolof9d43412021-01-12 11:11:34 -08001029 onuIndication := types.OnuIndicationMessage{
1030 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001031 PonPortID: ponID,
1032 OnuID: onu.ID,
1033 OnuSN: onu.SerialNumber,
1034 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001035 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001036
1037 }
1038
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001039 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001040}
1041
Shrey Baid688b4242020-07-10 20:40:10 +05301042func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001043 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001044 "IntfId": flow.AccessIntfId,
1045 "OnuId": flow.OnuId,
1046 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001047 "InnerVlan": flow.Classifier.IVid,
1048 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001049 "FlowType": flow.FlowType,
1050 "FlowId": flow.FlowId,
1051 "UniID": flow.UniId,
1052 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301053 }).Tracef("OLT receives FlowAdd")
1054
1055 flowKey := FlowKey{}
1056 if !o.enablePerf {
1057 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001058 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301059 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001060
1061 if flow.AccessIntfId == -1 {
1062 oltLogger.WithFields(log.Fields{
1063 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001064 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001065 } else if flow.FlowType == "multicast" {
1066 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001067 "Cookie": flow.Cookie,
1068 "DstPort": flow.Classifier.DstPort,
1069 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1070 "FlowId": flow.FlowId,
1071 "FlowType": flow.FlowType,
1072 "GemportId": flow.GemportId,
1073 "InnerVlan": flow.Classifier.IVid,
1074 "IntfId": flow.AccessIntfId,
1075 "IpProto": flow.Classifier.IpProto,
1076 "OnuId": flow.OnuId,
1077 "OuterVlan": flow.Classifier.OVid,
1078 "PortNo": flow.PortNo,
1079 "SrcPort": flow.Classifier.SrcPort,
1080 "UniID": flow.UniId,
1081 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001082 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001083 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001084 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001085 if err != nil {
1086 oltLogger.WithFields(log.Fields{
1087 "OnuId": flow.OnuId,
1088 "IntfId": flow.AccessIntfId,
1089 "err": err,
1090 }).Error("Can't find PonPort")
1091 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001092 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001093 if err != nil {
1094 oltLogger.WithFields(log.Fields{
1095 "OnuId": flow.OnuId,
1096 "IntfId": flow.AccessIntfId,
1097 "err": err,
1098 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001099 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001100 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301101 if !o.enablePerf {
1102 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301103 // Generate event on first flow for ONU
1104 if len(onu.Flows) == 1 {
1105 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1106 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301107 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001108
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001109 // validate that the flow reference correct IDs (Alloc, Gem)
1110 if err := o.validateFlow(flow); err != nil {
1111 oltLogger.WithFields(log.Fields{
1112 "OnuId": flow.OnuId,
1113 "IntfId": flow.AccessIntfId,
1114 "Flow": flow,
1115 "SerialNumber": onu.Sn(),
1116 "err": err,
1117 }).Error("invalid-flow-for-onu")
1118 return nil, err
1119 }
1120
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001121 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001122 o.storeAllocId(flow)
1123
Matteo Scandolof9d43412021-01-12 11:11:34 -08001124 msg := types.Message{
1125 Type: types.FlowAdd,
1126 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001127 PonPortID: pon.ID,
1128 OnuID: onu.ID,
1129 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001130 },
1131 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001132 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001133 }
1134
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001135 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001136}
1137
Pragya Arya8bdb4532020-03-02 17:08:09 +05301138// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301139func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001140
Pragya Arya8bdb4532020-03-02 17:08:09 +05301141 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001142 "AllocId": flow.AllocId,
1143 "Cookie": flow.Cookie,
1144 "FlowId": flow.FlowId,
1145 "FlowType": flow.FlowType,
1146 "GemportId": flow.GemportId,
1147 "IntfId": flow.AccessIntfId,
1148 "OnuId": flow.OnuId,
1149 "PortNo": flow.PortNo,
1150 "UniID": flow.UniId,
1151 "ReplicateFlow": flow.ReplicateFlow,
1152 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001153 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301154
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001155 olt.freeGemPortId(flow)
1156 olt.freeAllocId(flow)
1157
Pragya Arya8bdb4532020-03-02 17:08:09 +05301158 if !o.enablePerf { // remove only if flow were stored
1159 flowKey := FlowKey{
1160 ID: flow.FlowId,
1161 Direction: flow.FlowType,
1162 }
1163
1164 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001165 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301166 if !ok {
1167 oltLogger.Errorf("Flow %v not found", flow)
1168 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1169 }
1170
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001171 storedFlow := storedFlowIntf.(openolt.Flow)
1172
Pragya Arya8bdb4532020-03-02 17:08:09 +05301173 // if its ONU flow remove it from ONU also
1174 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001175 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1176 if err != nil {
1177 oltLogger.WithFields(log.Fields{
1178 "OnuId": storedFlow.OnuId,
1179 "IntfId": storedFlow.AccessIntfId,
1180 "PONs": olt.Pons,
1181 "err": err,
1182 }).Error("PON-port-not-found")
1183 return new(openolt.Empty), nil
1184 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301185 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1186 if err != nil {
1187 oltLogger.WithFields(log.Fields{
1188 "OnuId": storedFlow.OnuId,
1189 "IntfId": storedFlow.AccessIntfId,
1190 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001191 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301192 return new(openolt.Empty), nil
1193 }
1194 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301195 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301196 }
1197
1198 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001199 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301200 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001201
1202 if flow.AccessIntfId == -1 {
1203 oltLogger.WithFields(log.Fields{
1204 "FlowId": flow.FlowId,
1205 }).Debug("Removing OLT flow")
1206 } else if flow.FlowType == "multicast" {
1207 oltLogger.WithFields(log.Fields{
1208 "FlowId": flow.FlowId,
1209 }).Debug("Removing OLT multicast flow")
1210 } else {
1211
1212 onu, err := o.GetOnuByFlowId(flow.FlowId)
1213 if err != nil {
1214 oltLogger.WithFields(log.Fields{
1215 "OnuId": flow.OnuId,
1216 "IntfId": flow.AccessIntfId,
1217 "err": err,
1218 }).Error("Can't find Onu")
1219 return nil, err
1220 }
1221
Matteo Scandolof9d43412021-01-12 11:11:34 -08001222 msg := types.Message{
1223 Type: types.FlowRemoved,
1224 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301225 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001226 },
1227 }
1228 onu.Channel <- msg
1229 }
1230
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001231 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001232}
1233
Shrey Baid688b4242020-07-10 20:40:10 +05301234func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001235 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1236 oltLogger.WithFields(log.Fields{
1237 "signature": res.HeartbeatSignature,
1238 }).Trace("HeartbeatCheck")
1239 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001240}
1241
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001242func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001243 for _, pon := range o.Pons {
1244 for _, onu := range pon.Onus {
1245 for _, fId := range onu.FlowIds {
1246 if fId == flowId {
1247 return onu, nil
1248 }
1249 }
1250 }
1251 }
Shrey Baid688b4242020-07-10 20:40:10 +05301252 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001253}
1254
Shrey Baid688b4242020-07-10 20:40:10 +05301255func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001256
Matteo Scandolocedde462021-03-09 17:37:16 -08001257 intfIDs := []uint32{}
1258 for i := 0; i < o.NumPon; i++ {
1259 intfIDs = append(intfIDs, uint32(i))
1260 }
1261
1262 devinfo := &openolt.DeviceInfo{
1263 Vendor: common.Config.Olt.Vendor,
1264 Model: common.Config.Olt.Model,
1265 HardwareVersion: common.Config.Olt.HardwareVersion,
1266 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1267 Technology: common.Config.Olt.Technology,
1268 PonPorts: uint32(o.NumPon),
1269 OnuIdStart: onuIdStart,
1270 OnuIdEnd: onuIdEnd,
1271 AllocIdStart: allocIdStart,
1272 AllocIdEnd: allocIdEnd,
1273 GemportIdStart: gemportIdStart,
1274 GemportIdEnd: gemportIdEnd,
1275 FlowIdStart: flowIdStart,
1276 FlowIdEnd: flowIdEnd,
1277 DeviceSerialNumber: o.SerialNumber,
1278 DeviceId: common.Config.Olt.DeviceId,
1279 PreviouslyConnected: o.PreviouslyConnected,
1280 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1281 {
1282 IntfIds: intfIDs,
1283 Technology: common.Config.Olt.Technology,
1284 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1285 {
1286 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1287 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1288 Start: onuIdStart,
1289 End: onuIdEnd,
1290 },
1291 {
1292 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1293 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1294 Start: allocIdStart,
1295 End: allocIdEnd,
1296 },
1297 {
1298 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1299 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1300 Start: gemportIdStart,
1301 End: gemportIdEnd,
1302 },
1303 {
1304 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1305 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1306 Start: flowIdStart,
1307 End: flowIdEnd,
1308 },
1309 },
1310 },
1311 },
1312 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001313
1314 oltLogger.WithFields(log.Fields{
1315 "Vendor": devinfo.Vendor,
1316 "Model": devinfo.Model,
1317 "HardwareVersion": devinfo.HardwareVersion,
1318 "FirmwareVersion": devinfo.FirmwareVersion,
1319 "Technology": devinfo.Technology,
1320 "PonPorts": devinfo.PonPorts,
1321 "OnuIdStart": devinfo.OnuIdStart,
1322 "OnuIdEnd": devinfo.OnuIdEnd,
1323 "AllocIdStart": devinfo.AllocIdStart,
1324 "AllocIdEnd": devinfo.AllocIdEnd,
1325 "GemportIdStart": devinfo.GemportIdStart,
1326 "GemportIdEnd": devinfo.GemportIdEnd,
1327 "FlowIdStart": devinfo.FlowIdStart,
1328 "FlowIdEnd": devinfo.FlowIdEnd,
1329 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1330 "DeviceId": devinfo.DeviceId,
1331 "PreviouslyConnected": devinfo.PreviouslyConnected,
1332 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1333
1334 // once we connect, set the flag
1335 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001336
1337 return devinfo, nil
1338}
1339
Shrey Baid688b4242020-07-10 20:40:10 +05301340func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001341 pon, err := o.GetPonById(omci_msg.IntfId)
1342 if err != nil {
1343 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001344 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001345 "onu_id": omci_msg.OnuId,
1346 "pon_id": omci_msg.IntfId,
1347 }).Error("pon ID not found")
1348 return nil, err
1349 }
1350
1351 onu, err := pon.GetOnuById(omci_msg.OnuId)
1352 if err != nil {
1353 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001354 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001355 "onu_id": omci_msg.OnuId,
1356 "pon_id": omci_msg.IntfId,
1357 }).Error("onu ID not found")
1358 return nil, err
1359 }
1360
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001361 oltLogger.WithFields(log.Fields{
1362 "IntfId": onu.PonPortID,
1363 "OnuId": onu.ID,
1364 "OnuSn": onu.Sn(),
1365 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001366 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1367 if err != nil {
1368 log.WithFields(log.Fields{
1369 "IntfId": onu.PonPortID,
1370 "SerialNumber": onu.Sn(),
1371 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1372 "err": err.Error(),
1373 }).Error("cannot-parse-OMCI-packet")
1374 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001375 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001376 if onu.InternalState.Current() == OnuStateDisabled {
1377 // if the ONU is disabled just drop the message
1378 log.WithFields(log.Fields{
1379 "IntfId": onu.PonPortID,
1380 "SerialNumber": onu.Sn(),
1381 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1382 "omciPkt": omciPkt,
1383 "omciMsgType": omciMsg.MessageType,
1384 }).Warn("dropping-omci-message")
1385 } else {
1386 msg := types.Message{
1387 Type: types.OMCI,
1388 Data: types.OmciMessage{
1389 OnuSN: onu.SerialNumber,
1390 OnuID: onu.ID,
1391 OmciMsg: omciMsg,
1392 OmciPkt: omciPkt,
1393 },
1394 }
1395 onu.Channel <- msg
1396 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001397 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001398}
1399
Shrey Baid688b4242020-07-10 20:40:10 +05301400func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001401 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001402 if err != nil {
1403 oltLogger.WithFields(log.Fields{
1404 "OnuId": onuPkt.OnuId,
1405 "IntfId": onuPkt.IntfId,
1406 "err": err,
1407 }).Error("Can't find PonPort")
1408 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001409 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001410 if err != nil {
1411 oltLogger.WithFields(log.Fields{
1412 "OnuId": onuPkt.OnuId,
1413 "IntfId": onuPkt.IntfId,
1414 "err": err,
1415 }).Error("Can't find Onu")
1416 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001417
Matteo Scandolo075b1892019-10-07 12:11:07 -07001418 oltLogger.WithFields(log.Fields{
1419 "IntfId": onu.PonPortID,
1420 "OnuId": onu.ID,
1421 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001422 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001423 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001424
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001425 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001426
1427 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001428 if err != nil {
1429 onuLogger.WithFields(log.Fields{
1430 "IntfId": onu.PonPortID,
1431 "OnuId": onu.ID,
1432 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001433 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001434 }).Error("Can't find pktType in packet, droppint it")
1435 return new(openolt.Empty), nil
1436 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001437
Matteo Scandolo4a036262020-08-17 15:56:13 -07001438 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001439 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001440 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001441 "IntfId": onu.PonPortID,
1442 "OnuId": onu.ID,
1443 "OnuSn": onu.Sn(),
1444 "Pkt": rawpkt.Data(),
1445 }).Error("Can't find Dst MacAddress in packet, droppint it")
1446 return new(openolt.Empty), nil
1447 }
1448
Matteo Scandolof9d43412021-01-12 11:11:34 -08001449 msg := types.Message{
1450 Type: types.OnuPacketOut,
1451 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001452 IntfId: onuPkt.IntfId,
1453 OnuId: onuPkt.OnuId,
1454 Packet: rawpkt,
1455 Type: pktType,
1456 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001457 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001458 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001459
Matteo Scandolo075b1892019-10-07 12:11:07 -07001460 onu.Channel <- msg
1461
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001462 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001463}
1464
Shrey Baid688b4242020-07-10 20:40:10 +05301465func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001466
1467 // OLT Reboot is called in two cases:
1468 // - 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)
1469 // - when an OLT needs to be rebooted (voltcl device reboot)
1470
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001471 oltLogger.WithFields(log.Fields{
1472 "oltId": o.ID,
1473 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301474 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301475 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001476 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001477}
1478
Shrey Baid688b4242020-07-10 20:40:10 +05301479func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301480 oltLogger.WithFields(log.Fields{
1481 "oltId": o.ID,
1482 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301483 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301484
Pragya Arya2225f202020-01-29 18:05:01 +05301485 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001486 oltMsg := types.Message{
1487 Type: types.OltIndication,
1488 Data: types.OltIndicationMessage{
1489 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301490 },
Pragya Arya1881df02020-01-29 18:05:01 +05301491 }
Pragya Arya2225f202020-01-29 18:05:01 +05301492 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301493
Pragya Arya2225f202020-01-29 18:05:01 +05301494 for _, pon := range o.Pons {
1495 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001496 msg := types.Message{
1497 Type: types.PonIndication,
1498 Data: types.PonIndicationMessage{
1499 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301500 PonPortID: pon.ID,
1501 },
1502 }
1503 o.channel <- msg
1504 }
1505 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001506
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001507 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001508}
1509
Shrey Baid688b4242020-07-10 20:40:10 +05301510func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001511 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1512
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001513 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1514
1515 if err != nil {
1516 return nil, err
1517 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001518 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001519}
1520
Shrey Baid688b4242020-07-10 20:40:10 +05301521func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001522 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001523 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001524}
1525
Shrey Baid688b4242020-07-10 20:40:10 +05301526func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001527 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001528 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001529}
1530
Shrey Baid688b4242020-07-10 20:40:10 +05301531func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001532 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001533 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001534}
1535
Shrey Baid688b4242020-07-10 20:40:10 +05301536func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001537 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001538 return new(openolt.Empty), nil
1539}
1540
Shrey Baid688b4242020-07-10 20:40:10 +05301541func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001542 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001543 return new(openolt.Empty), nil
1544}
1545
Shrey Baid688b4242020-07-10 20:40:10 +05301546func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301547 oltLogger.WithFields(log.Fields{
1548 "OnuId": trafficSchedulers.OnuId,
1549 "IntfId": trafficSchedulers.IntfId,
1550 "OnuPortNo": trafficSchedulers.PortNo,
1551 }).Info("received CreateTrafficSchedulers")
1552
1553 if !s.enablePerf {
1554 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1555 if err != nil {
1556 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1557 return new(openolt.Empty), err
1558 }
1559 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1560 if err != nil {
1561 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1562 return new(openolt.Empty), err
1563 }
1564 onu.TrafficSchedulers = trafficSchedulers
1565 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001566 return new(openolt.Empty), nil
1567}
1568
Shrey Baid688b4242020-07-10 20:40:10 +05301569func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301570 oltLogger.WithFields(log.Fields{
1571 "OnuId": trafficSchedulers.OnuId,
1572 "IntfId": trafficSchedulers.IntfId,
1573 "OnuPortNo": trafficSchedulers.PortNo,
1574 }).Info("received RemoveTrafficSchedulers")
1575 if !s.enablePerf {
1576 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1577 if err != nil {
1578 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1579 return new(openolt.Empty), err
1580 }
1581 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1582 if err != nil {
1583 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1584 return new(openolt.Empty), err
1585 }
1586
1587 onu.TrafficSchedulers = nil
1588 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001589 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001590}
Scott Baker41724b82020-01-21 19:54:53 -08001591
Matteo Scandolo618a6582020-09-09 12:21:29 -07001592func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1593 oltLogger.WithFields(log.Fields{
1594 "GroupId": group.GroupId,
1595 "Command": group.Command,
1596 "Members": group.Members,
1597 "Action": group.Action,
1598 }).Debug("received PerformGroupOperation")
1599 return &openolt.Empty{}, nil
1600}
1601
1602func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1603 oltLogger.WithFields(log.Fields{
1604 "GroupId": group.GroupId,
1605 "Command": group.Command,
1606 "Members": group.Members,
1607 "Action": group.Action,
1608 }).Debug("received PerformGroupOperation")
1609 return &openolt.Empty{}, nil
1610}
1611
1612func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1613 return &common_protos.ReturnValues{}, nil
1614}
1615
1616func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1617 return &openolt.Empty{}, nil
1618}
1619
1620func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1621 return &openolt.OnuLogicalDistance{}, nil
1622}
1623
1624func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1625 return &openolt.OnuLogicalDistance{}, nil
1626}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001627
1628func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1629 return &openolt.GemPortStatistics{}, nil
1630}
1631
1632func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1633 return &openolt.OnuStatistics{}, nil
1634}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001635
1636func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1637 o.AllocIDsLock.Lock()
1638 defer o.AllocIDsLock.Unlock()
1639
Matteo Scandolo21195d62021-04-07 14:31:23 -07001640 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1641 oltLogger.WithFields(log.Fields{
1642 "IntfId": flow.AccessIntfId,
1643 "OnuId": flow.OnuId,
1644 "PortNo": flow.PortNo,
1645 "GemportId": flow.GemportId,
1646 "FlowId": flow.FlowId,
1647 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1648 }
1649
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001650 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001651 "IntfId": flow.AccessIntfId,
1652 "OnuId": flow.OnuId,
1653 "PortNo": flow.PortNo,
1654 "GemportId": flow.GemportId,
1655 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001656 }).Trace("storing-alloc-id-via-flow")
1657
1658 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1659 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1660 }
1661 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1662 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1663 }
1664 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1665}
1666
1667func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1668 // if this is the last flow referencing the AllocId then remove it
1669 o.AllocIDsLock.Lock()
1670 defer o.AllocIDsLock.Unlock()
1671
1672 oltLogger.WithFields(log.Fields{
1673 "IntfId": flow.AccessIntfId,
1674 "OnuId": flow.OnuId,
1675 "PortNo": flow.PortNo,
1676 "GemportId": flow.GemportId,
1677 }).Trace("freeing-alloc-id-via-flow")
1678
1679 // NOTE look at the freeGemPortId implementation for comments and context
1680 for ponId, ponValues := range o.AllocIDs {
1681 for onuId, onuValues := range ponValues {
1682 for uniId, uniValues := range onuValues {
1683 for allocId, flows := range uniValues {
1684 for flowId := range flows {
1685 // if the flow matches, remove it from the map.
1686 if flow.FlowId == flowId {
1687 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1688 }
1689 // if that was the last flow for a particular allocId, remove the entire allocId
1690 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1691 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1692 }
1693 }
1694 }
1695 }
1696 }
1697 }
1698}
1699
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001700func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001701 o.GemPortIDsLock.Lock()
1702 defer o.GemPortIDsLock.Unlock()
1703
1704 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1705 oltLogger.WithFields(log.Fields{
1706 "IntfId": ponId,
1707 "OnuId": onuId,
1708 "PortNo": portNo,
1709 "GemportId": gemId,
1710 "FlowId": flowId,
1711 }).Error("trying-to-store-gemport-for-unknown-onu")
1712 }
1713
1714 oltLogger.WithFields(log.Fields{
1715 "IntfId": ponId,
1716 "OnuId": onuId,
1717 "PortNo": portNo,
1718 "GemportId": gemId,
1719 "FlowId": flowId,
1720 }).Trace("storing-alloc-id-via-flow")
1721
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001722 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1723 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1724 }
1725 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1726 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1727 }
1728 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1729}
1730
1731func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001732 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001733 "IntfId": flow.AccessIntfId,
1734 "OnuId": flow.OnuId,
1735 "PortNo": flow.PortNo,
1736 "GemportId": flow.GemportId,
1737 "FlowId": flow.FlowId,
1738 "ReplicateFlow": flow.ReplicateFlow,
1739 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001740 }).Trace("storing-gem-port-id-via-flow")
1741
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001742 if flow.ReplicateFlow {
1743 for _, gem := range flow.PbitToGemport {
1744 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1745 }
1746 } else {
1747 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001748 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001749}
1750
1751func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1752 // if this is the last flow referencing the GemPort then remove it
1753 o.GemPortIDsLock.Lock()
1754 defer o.GemPortIDsLock.Unlock()
1755
1756 oltLogger.WithFields(log.Fields{
1757 "IntfId": flow.AccessIntfId,
1758 "OnuId": flow.OnuId,
1759 "PortNo": flow.PortNo,
1760 "GemportId": flow.GemportId,
1761 }).Trace("freeing-gem-port-id-via-flow")
1762
1763 // NOTE that this loop is not very performant, it would be better if the flow carries
1764 // the same information that it carries during a FlowAdd. If so we can directly remove
1765 // items from the map
1766
1767 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1768 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1769 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1770 //}
1771
1772 // NOTE this loop assumes that flow IDs are unique per device
1773 for ponId, ponValues := range o.GemPortIDs {
1774 for onuId, onuValues := range ponValues {
1775 for uniId, uniValues := range onuValues {
1776 for gemId, flows := range uniValues {
1777 for flowId := range flows {
1778 // if the flow matches, remove it from the map.
1779 if flow.FlowId == flowId {
1780 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1781 }
1782 // if that was the last flow for a particular gem, remove the entire gem
1783 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1784 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1785 }
1786 }
1787 }
1788 }
1789 }
1790 }
1791}
1792
1793// validateFlow checks that:
1794// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1795// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1796func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001797 // validate gemPort
1798 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001799 defer o.GemPortIDsLock.RUnlock()
1800 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001801 if onuId == uint32(flow.OnuId) {
1802 continue
1803 }
1804 for uniId, uni := range onu {
1805 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001806 if flow.ReplicateFlow {
1807 for _, flowGem := range flow.PbitToGemport {
1808 if gem == int32(flowGem) {
1809 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1810 }
1811 }
1812 } else {
1813 if gem == flow.GemportId {
1814 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1815 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001816 }
1817 }
1818 }
1819 }
1820
1821 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001822 defer o.AllocIDsLock.RUnlock()
1823 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001824 if onuId == uint32(flow.OnuId) {
1825 continue
1826 }
1827 for uniId, uni := range onu {
1828 for allocId := range uni {
1829 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001830 return fmt.Errorf("allocId-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", allocId, uniId, onuId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001831 }
1832 }
1833 }
1834 }
1835
1836 return nil
1837}
1838
1839// clearAllResources is invoked up OLT Reboot to remove all the allocated
1840// GemPorts, AllocId and ONU-IDs across the PONs
1841func (o *OltDevice) clearAllResources() {
1842
1843 // remove the resources received via flows
1844 o.GemPortIDsLock.Lock()
1845 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1846 o.GemPortIDsLock.Unlock()
1847 o.AllocIDsLock.Lock()
1848 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1849 o.AllocIDsLock.Unlock()
1850
1851 // remove the resources received via OMCI
1852 for _, pon := range o.Pons {
1853 pon.removeAllAllocIds()
1854 pon.removeAllGemPorts()
1855 pon.removeAllOnuIds()
1856 }
1857}