blob: 87b9da49bcb66065a5f6bb1ee40c8ee4d1f42968 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package devices
18
19import (
20 "context"
Matteo Scandolo4a036262020-08-17 15:56:13 -070021 "encoding/hex"
Matteo Scandolo4747d292019-08-05 11:50:18 -070022 "fmt"
Matteo Scandolo90d08f62020-10-29 12:06:55 -070023 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
Matteo Scandolof9d43412021-01-12 11:11:34 -080024 "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070025 "github.com/opencord/voltha-protos/v4/go/ext/config"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020026 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080027 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020028 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010029 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020030
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070031 "github.com/google/gopacket"
32 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070033 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070034 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010035 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070036 common_protos "github.com/opencord/voltha-protos/v4/go/common"
37 "github.com/opencord/voltha-protos/v4/go/openolt"
38 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070039 log "github.com/sirupsen/logrus"
40 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053041 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010042 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053043 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070044)
45
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070046var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070047 "module": "OLT",
48})
49
Matteo Scandolocedde462021-03-09 17:37:16 -080050const (
51 onuIdStart = 1
52 onuIdEnd = 127
53 allocIdStart = 1024
54 allocIdEnd = 16383
55 gemportIdStart = 1024
56 gemportIdEnd = 65535
57 flowIdStart = 1
58 flowIdEnd = 65535
59)
60
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070061type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000062 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000063 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000064
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070065 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053066 ID int
67 SerialNumber string
68 NumNni int
69 NumPon int
70 NumOnuPerPon int
71 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080072 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070073 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010074 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053075 Delay int
76 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053077 EventChannel chan common.Event
78 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053079 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080080 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070081
Matteo Scandolo27428702019-10-11 16:21:16 -070082 Pons []*PonPort
83 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070084
85 // OLT Attributes
86 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000087
88 enableContext context.Context
89 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053090
Matteo Scandolo4a036262020-08-17 15:56:13 -070091 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053092 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080093
94 // Allocated Resources
95 // this data are to verify that the openolt adapter does not duplicate resources
96 AllocIDsLock sync.RWMutex
97 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
98 GemPortIDsLock sync.RWMutex
99 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
Matteo Scandolo4747d292019-08-05 11:50:18 -0700100}
101
Matteo Scandolo27428702019-10-11 16:21:16 -0700102var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700103
Matteo Scandolo27428702019-10-11 16:21:16 -0700104func GetOLT() *OltDevice {
105 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700106}
107
Matteo Scandolo4a036262020-08-17 15:56:13 -0700108func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700109 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530110 "ID": options.Olt.ID,
111 "NumNni": options.Olt.NniPorts,
112 "NumPon": options.Olt.PonPorts,
113 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700114 }).Debug("CreateOLT")
115
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700116 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530117 ID: options.Olt.ID,
118 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700119 OperState: getOperStateFSM(func(e *fsm.Event) {
120 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
121 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800122 NumNni: int(options.Olt.NniPorts),
123 NumPon: int(options.Olt.PonPorts),
124 NumOnuPerPon: int(options.Olt.OnusPonPort),
125 Pons: []*PonPort{},
126 Nnis: []*NniPort{},
127 Delay: options.BBSim.Delay,
128 enablePerf: options.BBSim.EnablePerf,
129 PublishEvents: options.BBSim.Events,
130 PortStatsInterval: options.Olt.PortStatsInterval,
131 dhcpServer: dhcp.NewDHCPServer(),
132 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800133 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
134 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135 }
136
Pragya Arya996a0892020-03-09 21:47:52 +0530137 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530138 olt.ControlledActivation = val
139 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700140 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530141 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
142 olt.ControlledActivation = Default
143 }
144
Matteo Scandolo4747d292019-08-05 11:50:18 -0700145 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700146 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700147 olt.InternalState = fsm.NewFSM(
148 "created",
149 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800150 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100151 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700152 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700153 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800154 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700155 },
156 fsm.Callbacks{
157 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700158 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100160 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800161 "enter_deleted": func(e *fsm.Event) {
162 // remove all the resource allocations
163 olt.clearAllResources()
164 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700165 },
166 )
167
Shrey Baid688b4242020-07-10 20:40:10 +0530168 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700169 // create NNI Port
170 nniPort, err := CreateNNI(&olt)
171 if err != nil {
172 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
173 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700174
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700175 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700176 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700177
Matteo Scandolo4a036262020-08-17 15:56:13 -0700178 // Create device and Services
179
180 nextCtag := map[string]int{}
181 nextStag := map[string]int{}
182
Matteo Scandolo4747d292019-08-05 11:50:18 -0700183 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700184 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800185
186 // initialize the resource maps for every PON Ports
187 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
188 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
189
Matteo Scandolo4a036262020-08-17 15:56:13 -0700190 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700191
Matteo Scandolo4a036262020-08-17 15:56:13 -0700192 // create ONU devices
193 for j := 0; j < olt.NumOnuPerPon; j++ {
194 delay := time.Duration(olt.Delay*j) * time.Millisecond
195 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700196
Matteo Scandolo4a036262020-08-17 15:56:13 -0700197 for k, s := range common.Services {
198
199 // find the correct cTag for this service
200 if _, ok := nextCtag[s.Name]; !ok {
201 // it's the first time we iterate over this service,
202 // so we start from the config value
203 nextCtag[s.Name] = s.CTag
204 } else {
205 // we have a previous value, so we check it
206 // if Allocation is unique, we increment,
207 // otherwise (shared) we do nothing
208 if s.CTagAllocation == common.TagAllocationUnique.String() {
209 nextCtag[s.Name] = nextCtag[s.Name] + 1
210 }
211 }
212
213 // find the correct sTag for this service
214 if _, ok := nextStag[s.Name]; !ok {
215 nextStag[s.Name] = s.STag
216 } else {
217 if s.STagAllocation == common.TagAllocationUnique.String() {
218 nextStag[s.Name] = nextStag[s.Name] + 1
219 }
220 }
221
222 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
223 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
224 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
225 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
226
227 if err != nil {
228 oltLogger.WithFields(log.Fields{
229 "Err": err.Error(),
230 }).Fatal("Can't create Service")
231 }
232
233 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700234 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700235 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700236 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700237 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700238 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100239
Shrey Baid688b4242020-07-10 20:40:10 +0530240 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700241 if err := olt.InternalState.Event("initialize"); err != nil {
242 log.Errorf("Error initializing OLT: %v", err)
243 return nil
244 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100245 }
246
Pragya Arya324337e2020-02-20 14:35:08 +0530247 if olt.PublishEvents {
248 log.Debugf("BBSim event publishing is enabled")
249 // Create a channel to write event messages
250 olt.EventChannel = make(chan common.Event, 100)
251 }
252
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700253 return &olt
254}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700255
Shrey Baid688b4242020-07-10 20:40:10 +0530256func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100257
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000258 if o.OltServer == nil {
259 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100260 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800261 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100262 }
263
264 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800265 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100266
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100267 // FIXME we are assuming we have only one NNI
268 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800269 // NOTE we want to make sure the state is down when we initialize the OLT,
270 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
271 // in-band management
272 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100273 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800274
275 for ponId := range o.Pons {
276 // initialize the resource maps for every PON Ports
277 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
278 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
279 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700280}
281
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800282func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100283
Matteo Scandolo96f89192021-03-12 13:17:26 -0800284 o.PreviouslyConnected = false
285
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700286 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700287 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800288
289 oltLogger.WithFields(log.Fields{
290 "oltId": o.ID,
291 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
292
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700293 if o.InternalState.Is("enabled") {
294 oltLogger.WithFields(log.Fields{
295 "oltId": o.ID,
296 }).Info("This is an OLT soft reboot")
297 softReboot = true
298 }
299
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800300 // transition internal state to deleted
301 if err := o.InternalState.Event("delete"); err != nil {
302 oltLogger.WithFields(log.Fields{
303 "oltId": o.ID,
304 }).Errorf("Error deleting OLT: %v", err)
305 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100306 }
307
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800308 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 -0800309 o.StopOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100310
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700311 if softReboot {
312 for _, pon := range o.Pons {
313 if pon.InternalState.Current() == "enabled" {
314 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800315 msg := types.Message{
316 Type: types.PonIndication,
317 Data: types.PonIndicationMessage{
318 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700319 PonPortID: pon.ID,
320 },
321 }
322 o.channel <- msg
323 }
324
325 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800326 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700327 }
328 }
329 } else {
330 // PONs are already handled in the Disable call
331 for _, pon := range olt.Pons {
332 // ONUs are not automatically disabled when a PON goes down
333 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
334 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800335 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700336 }
Pragya Arya2225f202020-01-29 18:05:01 +0530337 }
338 }
339
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100340 // terminate the OLT's processOltMessages go routine
341 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700342
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700343 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100344
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100345 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100346
347 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800348 oltLogger.WithFields(log.Fields{
349 "oltId": o.ID,
350 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100351 return err
352 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800353 oltLogger.WithFields(log.Fields{
354 "oltId": o.ID,
355 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100356 return nil
357}
358
359// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800360func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700361 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700362 lis, err := net.Listen("tcp", address)
363 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700364 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700365 }
366 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100367
Matteo Scandolo4747d292019-08-05 11:50:18 -0700368 openolt.RegisterOpenoltServer(grpcServer, o)
369
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100370 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700371
Shrey Baid688b4242020-07-10 20:40:10 +0530372 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100373 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700374
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100375 return grpcServer, nil
376}
377
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800378// StartOltServer will create the grpc server that VOLTHA uses
379// to communicate with the device
380func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
381 oltServer, err := o.newOltServer()
382 if err != nil {
383 oltLogger.WithFields(log.Fields{
384 "err": err,
385 }).Error("Cannot OLT gRPC server")
386 return nil, err
387 }
388 return oltServer, nil
389}
390
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100391// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800392func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000393 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800394 oltLogger.WithFields(log.Fields{
395 "oltId": o.SerialNumber,
396 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000397 o.OltServer.Stop()
398 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700399 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700400}
401
402// Device Methods
403
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100404// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530405func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700406 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530407 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700408
David Bainbridge103cf022019-12-16 20:11:35 +0000409 // If enabled has already been called then an enabled context has
410 // been created. If this is the case then we want to cancel all the
411 // proessing loops associated with that enable before we recreate
412 // new ones
413 o.Lock()
414 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700415 oltLogger.Info("This is an OLT reboot")
David Bainbridge103cf022019-12-16 20:11:35 +0000416 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530417 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000418 }
419 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
420 o.Unlock()
421
Matteo Scandolo4747d292019-08-05 11:50:18 -0700422 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800423 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700424
Matteo Scandolo4a036262020-08-17 15:56:13 -0700425 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530426
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100427 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000428 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700429
430 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800431 oltMsg := types.Message{
432 Type: types.OltIndication,
433 Data: types.OltIndicationMessage{
434 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700435 },
436 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100437 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700438
439 // send NNI Port Indications
440 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800441 msg := types.Message{
442 Type: types.NniIndication,
443 Data: types.NniIndicationMessage{
444 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700445 NniPortID: nni.ID,
446 },
447 }
448 o.channel <- msg
449 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100450
Shrey Baid688b4242020-07-10 20:40:10 +0530451 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530452 for _, pon := range o.Pons {
453 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800454 msg := types.Message{
455 Type: types.PonIndication,
456 Data: types.PonIndicationMessage{
457 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530458 PonPortID: pon.ID,
459 },
460 }
461 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000462 }
Pragya Arya2225f202020-01-29 18:05:01 +0530463 }
464 } else {
465
466 // 1. controlledActivation == Default: Send both PON and ONUs indications
467 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
468
469 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
470 // send PON Port indications
471 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800472 msg := types.Message{
473 Type: types.PonIndication,
474 Data: types.PonIndicationMessage{
475 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530476 PonPortID: pon.ID,
477 },
478 }
479 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700480 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700481 }
482 }
483
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800484 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530485
486 if !o.enablePerf {
487 // Start a go routine to send periodic port stats to openolt adapter
488 go o.periodicPortStats(o.enableContext)
489 }
490
Matteo Scandolo4747d292019-08-05 11:50:18 -0700491 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700492}
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
Matteo Scandolof9d43412021-01-12 11:11:34 -0800529func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
530
531 switch interfaceType {
532 case "nni":
533 if !o.HasNni(interfaceId) {
534 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
535 }
536
537 case "pon":
538 if !o.HasPon(interfaceId) {
539 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
540 }
541 }
542
543 alarmIndication := &openolt.AlarmIndication{
544 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
545 Status: alarmStatus,
546 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
547 }},
548 }
549
550 msg := types.Message{
551 Type: types.AlarmIndication,
552 Data: alarmIndication,
553 }
554
555 o.channel <- msg
556
557 return nil
558}
559
560func (o *OltDevice) HasNni(id uint32) bool {
561 for _, intf := range o.Nnis {
562 if intf.ID == id {
563 return true
564 }
565 }
566 return false
567}
568
569func (o *OltDevice) HasPon(id uint32) bool {
570 for _, intf := range o.Pons {
571 if intf.ID == id {
572 return true
573 }
574 }
575 return false
576}
577
Shrey Baid688b4242020-07-10 20:40:10 +0530578func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700579 for _, pon := range o.Pons {
580 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700581 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700582 }
583 }
Shrey Baid688b4242020-07-10 20:40:10 +0530584 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700585}
586
Shrey Baid688b4242020-07-10 20:40:10 +0530587func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700588 for _, nni := range o.Nnis {
589 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700590 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700591 }
592 }
Shrey Baid688b4242020-07-10 20:40:10 +0530593 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700594}
595
Scott Baker41724b82020-01-21 19:54:53 -0800596func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
597 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
598 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
599 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
600 return
601 }
602
603 oltLogger.WithFields(log.Fields{
604 "AlarmIndication": alarmInd,
605 }).Debug("Sent Indication_AlarmInd")
606}
607
Matteo Scandolof9d43412021-01-12 11:11:34 -0800608func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
610 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700611 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800612 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700613 }
614
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700615 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700616 "OperState": msg.OperState,
617 }).Debug("Sent Indication_OltInd")
618}
619
Matteo Scandolof9d43412021-01-12 11:11:34 -0800620func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700621 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800622 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800623 if err := nni.OperState.Event("enable"); err != nil {
624 log.WithFields(log.Fields{
625 "Type": nni.Type,
626 "IntfId": nni.ID,
627 "OperState": nni.OperState.Current(),
628 }).Errorf("Can't move NNI Port to enabled state: %v", err)
629 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800630 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800631 if err := nni.OperState.Event("disable"); err != nil {
632 log.WithFields(log.Fields{
633 "Type": nni.Type,
634 "IntfId": nni.ID,
635 "OperState": nni.OperState.Current(),
636 }).Errorf("Can't move NNI Port to disable state: %v", err)
637 }
638 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700639 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700640 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700641 Type: nni.Type,
642 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700643 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 }}
645
646 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700647 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800648 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700649 }
650
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700651 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700652 "Type": nni.Type,
653 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700654 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655 }).Debug("Sent Indication_IntfOperInd for NNI")
656}
657
Pragya Arya2225f202020-01-29 18:05:01 +0530658func (o *OltDevice) sendPonIndication(ponPortID uint32) {
659
Matteo Scandolo4a036262020-08-17 15:56:13 -0700660 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530661 pon, _ := o.GetPonById(ponPortID)
662 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700663 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700664 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700665 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666 }}
667
668 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700669 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800670 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700671 }
672
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700673 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700674 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700675 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700676 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700677
Pragya Arya2225f202020-01-29 18:05:01 +0530678 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700679 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700680 Type: pon.Type,
681 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700682 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700683 }}
684
685 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700686 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800687 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700688 }
689
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700690 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700691 "Type": pon.Type,
692 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700693 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700694 }).Debug("Sent Indication_IntfOperInd for PON")
695}
696
Pragya Arya996a0892020-03-09 21:47:52 +0530697func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530698 if o.InternalState.Current() == "enabled" {
699 oltLogger.WithFields(log.Fields{
700 "Type": portType,
701 "IntfId": portID,
702 }).Trace("Sending port stats")
703 stats.IntfId = InterfaceIDToPortNo(portID, portType)
704 data := &openolt.Indication_PortStats{
705 PortStats: stats,
706 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700707 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530708 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
709 oltLogger.Errorf("Failed to send PortStats: %v", err)
710 return
711 }
Pragya Arya996a0892020-03-09 21:47:52 +0530712 }
713}
714
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100715// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000716func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100717 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000718 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700719
David Bainbridge103cf022019-12-16 20:11:35 +0000720loop:
721 for {
722 select {
723 case <-ctx.Done():
724 oltLogger.Debug("OLT Indication processing canceled via context")
725 break loop
726 case message, ok := <-ch:
727 if !ok || ctx.Err() != nil {
728 oltLogger.Debug("OLT Indication processing canceled via closed channel")
729 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700730 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700731
David Bainbridge103cf022019-12-16 20:11:35 +0000732 oltLogger.WithFields(log.Fields{
733 "oltId": o.ID,
734 "messageType": message.Type,
735 }).Trace("Received message")
736
737 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800738 case types.OltIndication:
739 msg, _ := message.Data.(types.OltIndicationMessage)
740 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530741 _ = o.InternalState.Event("enable")
742 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800743 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530744 _ = o.InternalState.Event("disable")
745 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000746 }
747 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800748 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800749 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
750 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800751 case types.NniIndication:
752 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000753 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800754 case types.PonIndication:
755 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530756 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800757 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530758 if err := pon.OperState.Event("enable"); err != nil {
759 oltLogger.WithFields(log.Fields{
760 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800761 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530762 }).Error("Can't Enable Oper state for PON Port")
763 }
764 if err := pon.InternalState.Event("enable"); err != nil {
765 oltLogger.WithFields(log.Fields{
766 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800767 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530768 }).Error("Can't Enable Internal state for PON Port")
769 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800770 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530771 if err := pon.OperState.Event("disable"); err != nil {
772 oltLogger.WithFields(log.Fields{
773 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800774 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530775 }).Error("Can't Disable Oper state for PON Port")
776 }
777 if err := pon.InternalState.Event("disable"); err != nil {
778 oltLogger.WithFields(log.Fields{
779 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800780 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530781 }).Error("Can't Disable Internal state for PON Port")
782 }
Pragya Arya2225f202020-01-29 18:05:01 +0530783 }
David Bainbridge103cf022019-12-16 20:11:35 +0000784 default:
785 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
786 }
787 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700788 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100789 wg.Done()
790 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700791}
792
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700793// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530794func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200795 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700796 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700797 for _, pon := range o.Pons {
798 for _, onu := range pon.Onus {
799 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700800 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700801 }
802 }
803 }
804
Shrey Baid688b4242020-07-10 20:40:10 +0530805 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700806}
807
William Kurkian9dadc5b2019-10-22 13:51:57 -0400808// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530809func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200810 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400811 // memoizing it will remove the bottleneck
812 for _, pon := range o.Pons {
813 if pon.ID == intfId {
814 for _, onu := range pon.Onus {
815 if onu.ID == onuId {
816 return onu, nil
817 }
818 }
819 }
820 }
Shrey Baid688b4242020-07-10 20:40:10 +0530821 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400822}
823
Matteo Scandolo4a036262020-08-17 15:56:13 -0700824// returns a Service with a given Mac Address
825func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200826 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700827 // memoizing it will remove the bottleneck
828 for _, pon := range o.Pons {
829 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700830 s, err := onu.findServiceByMacAddress(mac)
831 if err == nil {
832 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700833 }
834 }
835 }
836
Matteo Scandolo4a036262020-08-17 15:56:13 -0700837 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700838}
839
Matteo Scandolo4747d292019-08-05 11:50:18 -0700840// GRPC Endpoints
841
Shrey Baid688b4242020-07-10 20:40:10 +0530842func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700843 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700844 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700845 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530846 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700847
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700848 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800849
850 // Initialize the resource maps for this ONU
851 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
852 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
853
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700854 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500855 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700856
Matteo Scandolocedde462021-03-09 17:37:16 -0800857 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700858 oltLogger.WithFields(log.Fields{
859 "IntfId": _onu.PonPortID,
860 "OnuSn": _onu.Sn(),
861 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800862 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700863 }
864
865 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
866
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700867 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700868}
869
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800870func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700871 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700872 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700873}
874
Shrey Baid688b4242020-07-10 20:40:10 +0530875func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530876 oltLogger.WithFields(log.Fields{
877 "IntfId": onu.IntfId,
878 "OnuId": onu.OnuId,
879 }).Info("Received DeleteOnu call from VOLTHA")
880
881 pon, err := o.GetPonById(onu.IntfId)
882 if err != nil {
883 oltLogger.WithFields(log.Fields{
884 "OnuId": onu.OnuId,
885 "IntfId": onu.IntfId,
886 "err": err,
887 }).Error("Can't find PonPort")
888 }
889 _onu, err := pon.GetOnuById(onu.OnuId)
890 if err != nil {
891 oltLogger.WithFields(log.Fields{
892 "OnuId": onu.OnuId,
893 "IntfId": onu.IntfId,
894 "err": err,
895 }).Error("Can't find Onu")
896 }
897
Matteo Scandolocedde462021-03-09 17:37:16 -0800898 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530899 oltLogger.WithFields(log.Fields{
900 "IntfId": _onu.PonPortID,
901 "OnuSn": _onu.Sn(),
902 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800903 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530904 }
905
Hardik Windlassad790cb2020-06-17 21:26:22 +0530906 // ONU Re-Discovery
907 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530908 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530909 }
910
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700911 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700912}
913
Shrey Baid688b4242020-07-10 20:40:10 +0530914func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700915 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800916 oltLogger.WithFields(log.Fields{
917 "oltId": o.ID,
918 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530919 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800920
Matteo Scandolo401503a2019-12-11 14:48:14 -0800921 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530922 if pon.InternalState.Current() == "enabled" {
923 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800924 msg := types.Message{
925 Type: types.PonIndication,
926 Data: types.PonIndicationMessage{
927 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530928 PonPortID: pon.ID,
929 },
930 }
931 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800932 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800933 }
934
Matteo Scandolo401503a2019-12-11 14:48:14 -0800935 // Note that we are not disabling the NNI as the real OLT does not.
936 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800937
938 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800939 oltMsg := types.Message{
940 Type: types.OltIndication,
941 Data: types.OltIndicationMessage{
942 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700943 },
944 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100945 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700946 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700947}
948
Shrey Baid688b4242020-07-10 20:40:10 +0530949func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530950 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200951 ponID := intf.GetIntfId()
952 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200953
Matteo Scandolof9d43412021-01-12 11:11:34 -0800954 msg := types.Message{
955 Type: types.PonIndication,
956 Data: types.PonIndicationMessage{
957 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200958 PonPortID: ponID,
959 },
960 }
961 o.channel <- msg
962
963 for _, onu := range pon.Onus {
964
Matteo Scandolof9d43412021-01-12 11:11:34 -0800965 onuIndication := types.OnuIndicationMessage{
966 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200967 PonPortID: ponID,
968 OnuID: onu.ID,
969 OnuSN: onu.SerialNumber,
970 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700971 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200972
973 }
974
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700975 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700976}
977
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100978func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700979 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530980 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700981 o.Enable(stream)
982 return nil
983}
984
Shrey Baid688b4242020-07-10 20:40:10 +0530985func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530986 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530987 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200988 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200989
Matteo Scandolof9d43412021-01-12 11:11:34 -0800990 msg := types.Message{
991 Type: types.PonIndication,
992 Data: types.PonIndicationMessage{
993 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530994 PonPortID: ponID,
995 },
996 }
997 o.channel <- msg
998
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200999 for _, onu := range pon.Onus {
1000
Matteo Scandolof9d43412021-01-12 11:11:34 -08001001 onuIndication := types.OnuIndicationMessage{
1002 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001003 PonPortID: ponID,
1004 OnuID: onu.ID,
1005 OnuSN: onu.SerialNumber,
1006 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001007 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001008
1009 }
1010
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001011 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001012}
1013
Shrey Baid688b4242020-07-10 20:40:10 +05301014func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001015 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001016 "IntfId": flow.AccessIntfId,
1017 "OnuId": flow.OnuId,
1018 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001019 "InnerVlan": flow.Classifier.IVid,
1020 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001021 "FlowType": flow.FlowType,
1022 "FlowId": flow.FlowId,
1023 "UniID": flow.UniId,
1024 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301025 }).Tracef("OLT receives FlowAdd")
1026
1027 flowKey := FlowKey{}
1028 if !o.enablePerf {
1029 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001030 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301031 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001032
1033 if flow.AccessIntfId == -1 {
1034 oltLogger.WithFields(log.Fields{
1035 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001036 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001037 } else if flow.FlowType == "multicast" {
1038 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001039 "Cookie": flow.Cookie,
1040 "DstPort": flow.Classifier.DstPort,
1041 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1042 "FlowId": flow.FlowId,
1043 "FlowType": flow.FlowType,
1044 "GemportId": flow.GemportId,
1045 "InnerVlan": flow.Classifier.IVid,
1046 "IntfId": flow.AccessIntfId,
1047 "IpProto": flow.Classifier.IpProto,
1048 "OnuId": flow.OnuId,
1049 "OuterVlan": flow.Classifier.OVid,
1050 "PortNo": flow.PortNo,
1051 "SrcPort": flow.Classifier.SrcPort,
1052 "UniID": flow.UniId,
1053 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001054 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001055 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001056 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001057 if err != nil {
1058 oltLogger.WithFields(log.Fields{
1059 "OnuId": flow.OnuId,
1060 "IntfId": flow.AccessIntfId,
1061 "err": err,
1062 }).Error("Can't find PonPort")
1063 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001064 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001065 if err != nil {
1066 oltLogger.WithFields(log.Fields{
1067 "OnuId": flow.OnuId,
1068 "IntfId": flow.AccessIntfId,
1069 "err": err,
1070 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001071 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001072 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301073 if !o.enablePerf {
1074 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301075 // Generate event on first flow for ONU
1076 if len(onu.Flows) == 1 {
1077 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1078 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301079 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001080
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001081 // validate that the flow reference correct IDs (Alloc, Gem)
1082 if err := o.validateFlow(flow); err != nil {
1083 oltLogger.WithFields(log.Fields{
1084 "OnuId": flow.OnuId,
1085 "IntfId": flow.AccessIntfId,
1086 "Flow": flow,
1087 "SerialNumber": onu.Sn(),
1088 "err": err,
1089 }).Error("invalid-flow-for-onu")
1090 return nil, err
1091 }
1092
1093 o.storeGemPortId(flow)
1094 o.storeAllocId(flow)
1095
Matteo Scandolof9d43412021-01-12 11:11:34 -08001096 msg := types.Message{
1097 Type: types.FlowAdd,
1098 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001099 PonPortID: pon.ID,
1100 OnuID: onu.ID,
1101 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001102 },
1103 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001104 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001105 }
1106
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001107 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001108}
1109
Pragya Arya8bdb4532020-03-02 17:08:09 +05301110// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301111func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001112
Pragya Arya8bdb4532020-03-02 17:08:09 +05301113 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001114 "AllocId": flow.AllocId,
1115 "Cookie": flow.Cookie,
1116 "FlowId": flow.FlowId,
1117 "FlowType": flow.FlowType,
1118 "GemportId": flow.GemportId,
1119 "IntfId": flow.AccessIntfId,
1120 "OnuId": flow.OnuId,
1121 "PortNo": flow.PortNo,
1122 "UniID": flow.UniId,
1123 "ReplicateFlow": flow.ReplicateFlow,
1124 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001125 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301126
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001127 olt.freeGemPortId(flow)
1128 olt.freeAllocId(flow)
1129
Pragya Arya8bdb4532020-03-02 17:08:09 +05301130 if !o.enablePerf { // remove only if flow were stored
1131 flowKey := FlowKey{
1132 ID: flow.FlowId,
1133 Direction: flow.FlowType,
1134 }
1135
1136 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001137 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301138 if !ok {
1139 oltLogger.Errorf("Flow %v not found", flow)
1140 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1141 }
1142
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001143 storedFlow := storedFlowIntf.(openolt.Flow)
1144
Pragya Arya8bdb4532020-03-02 17:08:09 +05301145 // if its ONU flow remove it from ONU also
1146 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001147 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1148 if err != nil {
1149 oltLogger.WithFields(log.Fields{
1150 "OnuId": storedFlow.OnuId,
1151 "IntfId": storedFlow.AccessIntfId,
1152 "PONs": olt.Pons,
1153 "err": err,
1154 }).Error("PON-port-not-found")
1155 return new(openolt.Empty), nil
1156 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301157 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1158 if err != nil {
1159 oltLogger.WithFields(log.Fields{
1160 "OnuId": storedFlow.OnuId,
1161 "IntfId": storedFlow.AccessIntfId,
1162 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001163 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301164 return new(openolt.Empty), nil
1165 }
1166 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301167 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301168 }
1169
1170 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001171 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301172 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001173
1174 if flow.AccessIntfId == -1 {
1175 oltLogger.WithFields(log.Fields{
1176 "FlowId": flow.FlowId,
1177 }).Debug("Removing OLT flow")
1178 } else if flow.FlowType == "multicast" {
1179 oltLogger.WithFields(log.Fields{
1180 "FlowId": flow.FlowId,
1181 }).Debug("Removing OLT multicast flow")
1182 } else {
1183
1184 onu, err := o.GetOnuByFlowId(flow.FlowId)
1185 if err != nil {
1186 oltLogger.WithFields(log.Fields{
1187 "OnuId": flow.OnuId,
1188 "IntfId": flow.AccessIntfId,
1189 "err": err,
1190 }).Error("Can't find Onu")
1191 return nil, err
1192 }
1193
Matteo Scandolof9d43412021-01-12 11:11:34 -08001194 msg := types.Message{
1195 Type: types.FlowRemoved,
1196 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301197 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001198 },
1199 }
1200 onu.Channel <- msg
1201 }
1202
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001203 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001204}
1205
Shrey Baid688b4242020-07-10 20:40:10 +05301206func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001207 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1208 oltLogger.WithFields(log.Fields{
1209 "signature": res.HeartbeatSignature,
1210 }).Trace("HeartbeatCheck")
1211 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001212}
1213
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001214func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001215 for _, pon := range o.Pons {
1216 for _, onu := range pon.Onus {
1217 for _, fId := range onu.FlowIds {
1218 if fId == flowId {
1219 return onu, nil
1220 }
1221 }
1222 }
1223 }
Shrey Baid688b4242020-07-10 20:40:10 +05301224 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001225}
1226
Shrey Baid688b4242020-07-10 20:40:10 +05301227func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001228
Matteo Scandolocedde462021-03-09 17:37:16 -08001229 intfIDs := []uint32{}
1230 for i := 0; i < o.NumPon; i++ {
1231 intfIDs = append(intfIDs, uint32(i))
1232 }
1233
1234 devinfo := &openolt.DeviceInfo{
1235 Vendor: common.Config.Olt.Vendor,
1236 Model: common.Config.Olt.Model,
1237 HardwareVersion: common.Config.Olt.HardwareVersion,
1238 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1239 Technology: common.Config.Olt.Technology,
1240 PonPorts: uint32(o.NumPon),
1241 OnuIdStart: onuIdStart,
1242 OnuIdEnd: onuIdEnd,
1243 AllocIdStart: allocIdStart,
1244 AllocIdEnd: allocIdEnd,
1245 GemportIdStart: gemportIdStart,
1246 GemportIdEnd: gemportIdEnd,
1247 FlowIdStart: flowIdStart,
1248 FlowIdEnd: flowIdEnd,
1249 DeviceSerialNumber: o.SerialNumber,
1250 DeviceId: common.Config.Olt.DeviceId,
1251 PreviouslyConnected: o.PreviouslyConnected,
1252 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1253 {
1254 IntfIds: intfIDs,
1255 Technology: common.Config.Olt.Technology,
1256 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1257 {
1258 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1259 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1260 Start: onuIdStart,
1261 End: onuIdEnd,
1262 },
1263 {
1264 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1265 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1266 Start: allocIdStart,
1267 End: allocIdEnd,
1268 },
1269 {
1270 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1271 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1272 Start: gemportIdStart,
1273 End: gemportIdEnd,
1274 },
1275 {
1276 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1277 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1278 Start: flowIdStart,
1279 End: flowIdEnd,
1280 },
1281 },
1282 },
1283 },
1284 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001285
1286 oltLogger.WithFields(log.Fields{
1287 "Vendor": devinfo.Vendor,
1288 "Model": devinfo.Model,
1289 "HardwareVersion": devinfo.HardwareVersion,
1290 "FirmwareVersion": devinfo.FirmwareVersion,
1291 "Technology": devinfo.Technology,
1292 "PonPorts": devinfo.PonPorts,
1293 "OnuIdStart": devinfo.OnuIdStart,
1294 "OnuIdEnd": devinfo.OnuIdEnd,
1295 "AllocIdStart": devinfo.AllocIdStart,
1296 "AllocIdEnd": devinfo.AllocIdEnd,
1297 "GemportIdStart": devinfo.GemportIdStart,
1298 "GemportIdEnd": devinfo.GemportIdEnd,
1299 "FlowIdStart": devinfo.FlowIdStart,
1300 "FlowIdEnd": devinfo.FlowIdEnd,
1301 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1302 "DeviceId": devinfo.DeviceId,
1303 "PreviouslyConnected": devinfo.PreviouslyConnected,
1304 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1305
1306 // once we connect, set the flag
1307 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001308
1309 return devinfo, nil
1310}
1311
Shrey Baid688b4242020-07-10 20:40:10 +05301312func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001313 pon, err := o.GetPonById(omci_msg.IntfId)
1314 if err != nil {
1315 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001316 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001317 "onu_id": omci_msg.OnuId,
1318 "pon_id": omci_msg.IntfId,
1319 }).Error("pon ID not found")
1320 return nil, err
1321 }
1322
1323 onu, err := pon.GetOnuById(omci_msg.OnuId)
1324 if err != nil {
1325 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001326 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001327 "onu_id": omci_msg.OnuId,
1328 "pon_id": omci_msg.IntfId,
1329 }).Error("onu ID not found")
1330 return nil, err
1331 }
1332
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001333 oltLogger.WithFields(log.Fields{
1334 "IntfId": onu.PonPortID,
1335 "OnuId": onu.ID,
1336 "OnuSn": onu.Sn(),
1337 }).Tracef("Received OmciMsgOut")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001338 msg := types.Message{
1339 Type: types.OMCI,
1340 Data: types.OmciMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001341 OnuSN: onu.SerialNumber,
1342 OnuID: onu.ID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001343 OmciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001344 },
1345 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001346 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001347 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001348}
1349
Shrey Baid688b4242020-07-10 20:40:10 +05301350func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001351 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001352 if err != nil {
1353 oltLogger.WithFields(log.Fields{
1354 "OnuId": onuPkt.OnuId,
1355 "IntfId": onuPkt.IntfId,
1356 "err": err,
1357 }).Error("Can't find PonPort")
1358 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001359 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001360 if err != nil {
1361 oltLogger.WithFields(log.Fields{
1362 "OnuId": onuPkt.OnuId,
1363 "IntfId": onuPkt.IntfId,
1364 "err": err,
1365 }).Error("Can't find Onu")
1366 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001367
Matteo Scandolo075b1892019-10-07 12:11:07 -07001368 oltLogger.WithFields(log.Fields{
1369 "IntfId": onu.PonPortID,
1370 "OnuId": onu.ID,
1371 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001372 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001373 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001374
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001375 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001376
1377 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001378 if err != nil {
1379 onuLogger.WithFields(log.Fields{
1380 "IntfId": onu.PonPortID,
1381 "OnuId": onu.ID,
1382 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001383 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001384 }).Error("Can't find pktType in packet, droppint it")
1385 return new(openolt.Empty), nil
1386 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001387
Matteo Scandolo4a036262020-08-17 15:56:13 -07001388 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001389 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001390 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001391 "IntfId": onu.PonPortID,
1392 "OnuId": onu.ID,
1393 "OnuSn": onu.Sn(),
1394 "Pkt": rawpkt.Data(),
1395 }).Error("Can't find Dst MacAddress in packet, droppint it")
1396 return new(openolt.Empty), nil
1397 }
1398
Matteo Scandolof9d43412021-01-12 11:11:34 -08001399 msg := types.Message{
1400 Type: types.OnuPacketOut,
1401 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001402 IntfId: onuPkt.IntfId,
1403 OnuId: onuPkt.OnuId,
1404 Packet: rawpkt,
1405 Type: pktType,
1406 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001407 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001408 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001409
Matteo Scandolo075b1892019-10-07 12:11:07 -07001410 onu.Channel <- msg
1411
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001412 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001413}
1414
Shrey Baid688b4242020-07-10 20:40:10 +05301415func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001416
1417 // OLT Reboot is called in two cases:
1418 // - 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)
1419 // - when an OLT needs to be rebooted (voltcl device reboot)
1420
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001421 oltLogger.WithFields(log.Fields{
1422 "oltId": o.ID,
1423 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301424 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301425 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001426 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001427}
1428
Shrey Baid688b4242020-07-10 20:40:10 +05301429func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301430 oltLogger.WithFields(log.Fields{
1431 "oltId": o.ID,
1432 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301433 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301434
Pragya Arya2225f202020-01-29 18:05:01 +05301435 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001436 oltMsg := types.Message{
1437 Type: types.OltIndication,
1438 Data: types.OltIndicationMessage{
1439 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301440 },
Pragya Arya1881df02020-01-29 18:05:01 +05301441 }
Pragya Arya2225f202020-01-29 18:05:01 +05301442 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301443
Pragya Arya2225f202020-01-29 18:05:01 +05301444 for _, pon := range o.Pons {
1445 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001446 msg := types.Message{
1447 Type: types.PonIndication,
1448 Data: types.PonIndicationMessage{
1449 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301450 PonPortID: pon.ID,
1451 },
1452 }
1453 o.channel <- msg
1454 }
1455 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001456
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001457 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001458}
1459
Shrey Baid688b4242020-07-10 20:40:10 +05301460func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001461 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1462
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001463 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1464
1465 if err != nil {
1466 return nil, err
1467 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001468 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001469}
1470
Shrey Baid688b4242020-07-10 20:40:10 +05301471func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001472 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001473 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001474}
1475
Shrey Baid688b4242020-07-10 20:40:10 +05301476func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001477 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001478 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001479}
1480
Shrey Baid688b4242020-07-10 20:40:10 +05301481func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001482 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001483 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001484}
1485
Shrey Baid688b4242020-07-10 20:40:10 +05301486func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001487 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001488 return new(openolt.Empty), nil
1489}
1490
Shrey Baid688b4242020-07-10 20:40:10 +05301491func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001492 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001493 return new(openolt.Empty), nil
1494}
1495
Shrey Baid688b4242020-07-10 20:40:10 +05301496func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301497 oltLogger.WithFields(log.Fields{
1498 "OnuId": trafficSchedulers.OnuId,
1499 "IntfId": trafficSchedulers.IntfId,
1500 "OnuPortNo": trafficSchedulers.PortNo,
1501 }).Info("received CreateTrafficSchedulers")
1502
1503 if !s.enablePerf {
1504 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1505 if err != nil {
1506 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1507 return new(openolt.Empty), err
1508 }
1509 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1510 if err != nil {
1511 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1512 return new(openolt.Empty), err
1513 }
1514 onu.TrafficSchedulers = trafficSchedulers
1515 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001516 return new(openolt.Empty), nil
1517}
1518
Shrey Baid688b4242020-07-10 20:40:10 +05301519func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301520 oltLogger.WithFields(log.Fields{
1521 "OnuId": trafficSchedulers.OnuId,
1522 "IntfId": trafficSchedulers.IntfId,
1523 "OnuPortNo": trafficSchedulers.PortNo,
1524 }).Info("received RemoveTrafficSchedulers")
1525 if !s.enablePerf {
1526 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1527 if err != nil {
1528 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1529 return new(openolt.Empty), err
1530 }
1531 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1532 if err != nil {
1533 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1534 return new(openolt.Empty), err
1535 }
1536
1537 onu.TrafficSchedulers = nil
1538 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001539 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001540}
Scott Baker41724b82020-01-21 19:54:53 -08001541
Matteo Scandolo618a6582020-09-09 12:21:29 -07001542func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1543 oltLogger.WithFields(log.Fields{
1544 "GroupId": group.GroupId,
1545 "Command": group.Command,
1546 "Members": group.Members,
1547 "Action": group.Action,
1548 }).Debug("received PerformGroupOperation")
1549 return &openolt.Empty{}, nil
1550}
1551
1552func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1553 oltLogger.WithFields(log.Fields{
1554 "GroupId": group.GroupId,
1555 "Command": group.Command,
1556 "Members": group.Members,
1557 "Action": group.Action,
1558 }).Debug("received PerformGroupOperation")
1559 return &openolt.Empty{}, nil
1560}
1561
1562func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1563 return &common_protos.ReturnValues{}, nil
1564}
1565
1566func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1567 return &openolt.Empty{}, nil
1568}
1569
1570func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1571 return &openolt.OnuLogicalDistance{}, nil
1572}
1573
1574func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1575 return &openolt.OnuLogicalDistance{}, nil
1576}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001577
1578func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1579 return &openolt.GemPortStatistics{}, nil
1580}
1581
1582func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1583 return &openolt.OnuStatistics{}, nil
1584}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001585
1586func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1587 o.AllocIDsLock.Lock()
1588 defer o.AllocIDsLock.Unlock()
1589
1590 oltLogger.WithFields(log.Fields{
1591 "IntfId": flow.AccessIntfId,
1592 "OnuId": flow.OnuId,
1593 "PortNo": flow.PortNo,
1594 "AllocId": flow.AllocId,
1595 }).Trace("storing-alloc-id-via-flow")
1596
1597 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1598 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1599 }
1600 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1601 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1602 }
1603 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1604}
1605
1606func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1607 // if this is the last flow referencing the AllocId then remove it
1608 o.AllocIDsLock.Lock()
1609 defer o.AllocIDsLock.Unlock()
1610
1611 oltLogger.WithFields(log.Fields{
1612 "IntfId": flow.AccessIntfId,
1613 "OnuId": flow.OnuId,
1614 "PortNo": flow.PortNo,
1615 "GemportId": flow.GemportId,
1616 }).Trace("freeing-alloc-id-via-flow")
1617
1618 // NOTE look at the freeGemPortId implementation for comments and context
1619 for ponId, ponValues := range o.AllocIDs {
1620 for onuId, onuValues := range ponValues {
1621 for uniId, uniValues := range onuValues {
1622 for allocId, flows := range uniValues {
1623 for flowId := range flows {
1624 // if the flow matches, remove it from the map.
1625 if flow.FlowId == flowId {
1626 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1627 }
1628 // if that was the last flow for a particular allocId, remove the entire allocId
1629 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1630 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1631 }
1632 }
1633 }
1634 }
1635 }
1636 }
1637}
1638
1639func (o *OltDevice) storeGemPortId(flow *openolt.Flow) {
1640 o.GemPortIDsLock.Lock()
1641 defer o.GemPortIDsLock.Unlock()
1642
1643 oltLogger.WithFields(log.Fields{
1644 "IntfId": flow.AccessIntfId,
1645 "OnuId": flow.OnuId,
1646 "PortNo": flow.PortNo,
1647 "GemportId": flow.GemportId,
1648 }).Trace("storing-gem-port-id-via-flow")
1649
1650 if _, ok := o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1651 o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1652 }
1653 if _, ok := o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]; !ok {
1654 o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId] = make(map[uint64]bool)
1655 }
1656 o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId][flow.FlowId] = true
1657}
1658
1659func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1660 // if this is the last flow referencing the GemPort then remove it
1661 o.GemPortIDsLock.Lock()
1662 defer o.GemPortIDsLock.Unlock()
1663
1664 oltLogger.WithFields(log.Fields{
1665 "IntfId": flow.AccessIntfId,
1666 "OnuId": flow.OnuId,
1667 "PortNo": flow.PortNo,
1668 "GemportId": flow.GemportId,
1669 }).Trace("freeing-gem-port-id-via-flow")
1670
1671 // NOTE that this loop is not very performant, it would be better if the flow carries
1672 // the same information that it carries during a FlowAdd. If so we can directly remove
1673 // items from the map
1674
1675 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1676 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1677 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1678 //}
1679
1680 // NOTE this loop assumes that flow IDs are unique per device
1681 for ponId, ponValues := range o.GemPortIDs {
1682 for onuId, onuValues := range ponValues {
1683 for uniId, uniValues := range onuValues {
1684 for gemId, flows := range uniValues {
1685 for flowId := range flows {
1686 // if the flow matches, remove it from the map.
1687 if flow.FlowId == flowId {
1688 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1689 }
1690 // if that was the last flow for a particular gem, remove the entire gem
1691 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1692 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1693 }
1694 }
1695 }
1696 }
1697 }
1698 }
1699}
1700
1701// validateFlow checks that:
1702// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1703// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1704func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
1705
1706 // validate gemPort
1707 o.GemPortIDsLock.RLock()
1708 allocatedGems := o.GemPortIDs[uint32(flow.AccessIntfId)]
1709 o.GemPortIDsLock.RUnlock()
1710 for onuId, onu := range allocatedGems {
1711 if onuId == uint32(flow.OnuId) {
1712 continue
1713 }
1714 for uniId, uni := range onu {
1715 for gem := range uni {
1716 if gem == flow.GemportId {
1717 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d", gem, uniId, onuId)
1718 }
1719 }
1720 }
1721 }
1722
1723 o.AllocIDsLock.RLock()
1724 allocatedAllocIds := o.AllocIDs[uint32(flow.AccessIntfId)]
1725 o.AllocIDsLock.RUnlock()
1726 for onuId, onu := range allocatedAllocIds {
1727 if onuId == uint32(flow.OnuId) {
1728 continue
1729 }
1730 for uniId, uni := range onu {
1731 for allocId := range uni {
1732 if allocId == flow.AllocId {
1733 return fmt.Errorf("allocId-%d-already-in-use-on-uni-%d-onu-%d", allocId, uniId, onuId)
1734 }
1735 }
1736 }
1737 }
1738
1739 return nil
1740}
1741
1742// clearAllResources is invoked up OLT Reboot to remove all the allocated
1743// GemPorts, AllocId and ONU-IDs across the PONs
1744func (o *OltDevice) clearAllResources() {
1745
1746 // remove the resources received via flows
1747 o.GemPortIDsLock.Lock()
1748 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1749 o.GemPortIDsLock.Unlock()
1750 o.AllocIDsLock.Lock()
1751 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1752 o.AllocIDsLock.Unlock()
1753
1754 // remove the resources received via OMCI
1755 for _, pon := range o.Pons {
1756 pon.removeAllAllocIds()
1757 pon.removeAllGemPorts()
1758 pon.removeAllOnuIds()
1759 }
1760}