blob: 4ffcaa7f68c771856325bfd19d72944ab97019bc [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 Scandolo635b2bf2020-09-04 10:23:40 -0700312 if softReboot {
313 for _, pon := range o.Pons {
314 if pon.InternalState.Current() == "enabled" {
315 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800316 msg := types.Message{
317 Type: types.PonIndication,
318 Data: types.PonIndicationMessage{
319 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700320 PonPortID: pon.ID,
321 },
322 }
323 o.channel <- msg
324 }
325
326 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800327 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700328 }
329 }
330 } else {
331 // PONs are already handled in the Disable call
332 for _, pon := range olt.Pons {
333 // ONUs are not automatically disabled when a PON goes down
334 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
335 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800336 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700337 }
Pragya Arya2225f202020-01-29 18:05:01 +0530338 }
339 }
340
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700341 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
342 o.StopOltServer()
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 Bozakov3ddb2452019-11-29 14:33:41 +0100348 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100349
350 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800351 oltLogger.WithFields(log.Fields{
352 "oltId": o.ID,
353 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100354 return err
355 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800356 oltLogger.WithFields(log.Fields{
357 "oltId": o.ID,
358 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100359 return nil
360}
361
362// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800363func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700364 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700365 lis, err := net.Listen("tcp", address)
366 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700367 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700368 }
369 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100370
Matteo Scandolo4747d292019-08-05 11:50:18 -0700371 openolt.RegisterOpenoltServer(grpcServer, o)
372
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100373 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700374
Shrey Baid688b4242020-07-10 20:40:10 +0530375 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100376 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700377
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100378 return grpcServer, nil
379}
380
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800381// StartOltServer will create the grpc server that VOLTHA uses
382// to communicate with the device
383func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
384 oltServer, err := o.newOltServer()
385 if err != nil {
386 oltLogger.WithFields(log.Fields{
387 "err": err,
388 }).Error("Cannot OLT gRPC server")
389 return nil, err
390 }
391 return oltServer, nil
392}
393
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100394// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800395func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000396 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800397 oltLogger.WithFields(log.Fields{
398 "oltId": o.SerialNumber,
399 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000400 o.OltServer.Stop()
401 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700402 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700403}
404
405// Device Methods
406
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100407// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530408func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700409 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530410 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700411
David Bainbridge103cf022019-12-16 20:11:35 +0000412 // If enabled has already been called then an enabled context has
413 // been created. If this is the case then we want to cancel all the
414 // proessing loops associated with that enable before we recreate
415 // new ones
416 o.Lock()
417 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700418 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000419 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530420 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700421 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000422 }
423 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
424 o.Unlock()
425
Matteo Scandolo4747d292019-08-05 11:50:18 -0700426 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700427
Matteo Scandolo4a036262020-08-17 15:56:13 -0700428 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530429
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100430 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700431 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000432 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700433
434 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800435 oltMsg := types.Message{
436 Type: types.OltIndication,
437 Data: types.OltIndicationMessage{
438 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700439 },
440 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100441 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700442
443 // send NNI Port Indications
444 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800445 msg := types.Message{
446 Type: types.NniIndication,
447 Data: types.NniIndicationMessage{
448 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700449 NniPortID: nni.ID,
450 },
451 }
452 o.channel <- msg
453 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100454
Shrey Baid688b4242020-07-10 20:40:10 +0530455 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530456 for _, pon := range o.Pons {
457 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800458 msg := types.Message{
459 Type: types.PonIndication,
460 Data: types.PonIndicationMessage{
461 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530462 PonPortID: pon.ID,
463 },
464 }
465 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000466 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700467 // when the enableContext was canceled the ONUs stopped listening on the channel
468 for _, onu := range pon.Onus {
469 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
470
471 // update the stream on all the services
472 for _, service := range onu.Services {
473 service.UpdateStream(stream)
474 }
475 }
Pragya Arya2225f202020-01-29 18:05:01 +0530476 }
477 } else {
478
479 // 1. controlledActivation == Default: Send both PON and ONUs indications
480 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
481
482 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
483 // send PON Port indications
484 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800485 msg := types.Message{
486 Type: types.PonIndication,
487 Data: types.PonIndicationMessage{
488 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530489 PonPortID: pon.ID,
490 },
491 }
492 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700493 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700494 }
495 }
496
Pragya Arya996a0892020-03-09 21:47:52 +0530497 if !o.enablePerf {
498 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700499 wg.Add(1)
500 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530501 }
502
Matteo Scandolo4747d292019-08-05 11:50:18 -0700503 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700504 oltLogger.WithFields(log.Fields{
505 "stream": stream,
506 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700507}
508
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700509func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530510 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700511
512loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530513 for {
514 select {
515 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
516 // send NNI port stats
517 for _, port := range o.Nnis {
518 incrementStat := true
519 if port.OperState.Current() == "down" {
520 incrementStat = false
521 }
522 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700523 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530524 }
525
526 // send PON port stats
527 for _, port := range o.Pons {
528 incrementStat := true
529 // do not increment port stats if PON port is down or no ONU is activated on PON port
530 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
531 incrementStat = false
532 }
533 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700534 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530535 }
536 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700537 oltLogger.Debug("Stop sending port stats")
538 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530539 }
Pragya Arya996a0892020-03-09 21:47:52 +0530540 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700541 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530542}
543
Matteo Scandolo4747d292019-08-05 11:50:18 -0700544// Helpers method
545
Matteo Scandolof9d43412021-01-12 11:11:34 -0800546func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
547
548 switch interfaceType {
549 case "nni":
550 if !o.HasNni(interfaceId) {
551 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
552 }
553
554 case "pon":
555 if !o.HasPon(interfaceId) {
556 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
557 }
558 }
559
560 alarmIndication := &openolt.AlarmIndication{
561 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
562 Status: alarmStatus,
563 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
564 }},
565 }
566
567 msg := types.Message{
568 Type: types.AlarmIndication,
569 Data: alarmIndication,
570 }
571
572 o.channel <- msg
573
574 return nil
575}
576
577func (o *OltDevice) HasNni(id uint32) bool {
578 for _, intf := range o.Nnis {
579 if intf.ID == id {
580 return true
581 }
582 }
583 return false
584}
585
586func (o *OltDevice) HasPon(id uint32) bool {
587 for _, intf := range o.Pons {
588 if intf.ID == id {
589 return true
590 }
591 }
592 return false
593}
594
Shrey Baid688b4242020-07-10 20:40:10 +0530595func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700596 for _, pon := range o.Pons {
597 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700598 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700599 }
600 }
Shrey Baid688b4242020-07-10 20:40:10 +0530601 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700602}
603
Shrey Baid688b4242020-07-10 20:40:10 +0530604func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700605 for _, nni := range o.Nnis {
606 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700607 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700608 }
609 }
Shrey Baid688b4242020-07-10 20:40:10 +0530610 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700611}
612
Scott Baker41724b82020-01-21 19:54:53 -0800613func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
614 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
615 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
616 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
617 return
618 }
619
620 oltLogger.WithFields(log.Fields{
621 "AlarmIndication": alarmInd,
622 }).Debug("Sent Indication_AlarmInd")
623}
624
Matteo Scandolof9d43412021-01-12 11:11:34 -0800625func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700626 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
627 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700628 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800629 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700630 }
631
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700632 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700633 "OperState": msg.OperState,
634 }).Debug("Sent Indication_OltInd")
635}
636
Matteo Scandolof9d43412021-01-12 11:11:34 -0800637func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700638 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800639 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800640 if err := nni.OperState.Event("enable"); err != nil {
641 log.WithFields(log.Fields{
642 "Type": nni.Type,
643 "IntfId": nni.ID,
644 "OperState": nni.OperState.Current(),
645 }).Errorf("Can't move NNI Port to enabled state: %v", err)
646 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800647 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800648 if err := nni.OperState.Event("disable"); err != nil {
649 log.WithFields(log.Fields{
650 "Type": nni.Type,
651 "IntfId": nni.ID,
652 "OperState": nni.OperState.Current(),
653 }).Errorf("Can't move NNI Port to disable state: %v", err)
654 }
655 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700656 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700657 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700658 Type: nni.Type,
659 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700660 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700661 }}
662
663 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700664 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800665 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666 }
667
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700668 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700669 "Type": nni.Type,
670 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700671 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700672 }).Debug("Sent Indication_IntfOperInd for NNI")
673}
674
Pragya Arya2225f202020-01-29 18:05:01 +0530675func (o *OltDevice) sendPonIndication(ponPortID uint32) {
676
Matteo Scandolo4a036262020-08-17 15:56:13 -0700677 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530678 pon, _ := o.GetPonById(ponPortID)
679 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700680 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700681 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: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700686 oltLogger.Errorf("Failed to send Indication_IntfInd: %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 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700692 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700693 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700694
Pragya Arya2225f202020-01-29 18:05:01 +0530695 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700696 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700697 Type: pon.Type,
698 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700699 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700700 }}
701
702 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700703 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800704 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700705 }
706
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700707 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700708 "Type": pon.Type,
709 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700710 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700711 }).Debug("Sent Indication_IntfOperInd for PON")
712}
713
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700714func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530715 if o.InternalState.Current() == "enabled" {
716 oltLogger.WithFields(log.Fields{
717 "Type": portType,
718 "IntfId": portID,
719 }).Trace("Sending port stats")
720 stats.IntfId = InterfaceIDToPortNo(portID, portType)
721 data := &openolt.Indication_PortStats{
722 PortStats: stats,
723 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700724
Shrey Baid55f328c2020-07-07 19:20:42 +0530725 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
726 oltLogger.Errorf("Failed to send PortStats: %v", err)
727 return
728 }
Pragya Arya996a0892020-03-09 21:47:52 +0530729 }
730}
731
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100732// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700733func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
734 oltLogger.WithFields(log.Fields{
735 "stream": stream,
736 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000737 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700738
David Bainbridge103cf022019-12-16 20:11:35 +0000739loop:
740 for {
741 select {
742 case <-ctx.Done():
743 oltLogger.Debug("OLT Indication processing canceled via context")
744 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700745 // do not terminate this loop if the stream is closed,
746 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
747 //case <-stream.Context().Done():
748 // oltLogger.Debug("OLT Indication processing canceled via stream context")
749 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000750 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700751 if !ok {
752 if ctx.Err() != nil {
753 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
754 }
755 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000756 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700757 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700758
David Bainbridge103cf022019-12-16 20:11:35 +0000759 oltLogger.WithFields(log.Fields{
760 "oltId": o.ID,
761 "messageType": message.Type,
762 }).Trace("Received message")
763
764 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800765 case types.OltIndication:
766 msg, _ := message.Data.(types.OltIndicationMessage)
767 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530768 _ = o.InternalState.Event("enable")
769 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800770 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530771 _ = o.InternalState.Event("disable")
772 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000773 }
774 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800775 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800776 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
777 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800778 case types.NniIndication:
779 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000780 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800781 case types.PonIndication:
782 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530783 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800784 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530785 if err := pon.OperState.Event("enable"); err != nil {
786 oltLogger.WithFields(log.Fields{
787 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800788 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530789 }).Error("Can't Enable Oper state for PON Port")
790 }
791 if err := pon.InternalState.Event("enable"); err != nil {
792 oltLogger.WithFields(log.Fields{
793 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800794 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530795 }).Error("Can't Enable Internal state for PON Port")
796 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800797 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530798 if err := pon.OperState.Event("disable"); err != nil {
799 oltLogger.WithFields(log.Fields{
800 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800801 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530802 }).Error("Can't Disable Oper state for PON Port")
803 }
804 if err := pon.InternalState.Event("disable"); err != nil {
805 oltLogger.WithFields(log.Fields{
806 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800807 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530808 }).Error("Can't Disable Internal state for PON Port")
809 }
Pragya Arya2225f202020-01-29 18:05:01 +0530810 }
David Bainbridge103cf022019-12-16 20:11:35 +0000811 default:
812 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
813 }
814 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700815 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100816 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700817 oltLogger.WithFields(log.Fields{
818 "stream": stream,
819 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700820}
821
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700822// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530823func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200824 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700825 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700826 for _, pon := range o.Pons {
827 for _, onu := range pon.Onus {
828 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700829 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700830 }
831 }
832 }
833
Shrey Baid688b4242020-07-10 20:40:10 +0530834 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700835}
836
William Kurkian9dadc5b2019-10-22 13:51:57 -0400837// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530838func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200839 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400840 // memoizing it will remove the bottleneck
841 for _, pon := range o.Pons {
842 if pon.ID == intfId {
843 for _, onu := range pon.Onus {
844 if onu.ID == onuId {
845 return onu, nil
846 }
847 }
848 }
849 }
Shrey Baid688b4242020-07-10 20:40:10 +0530850 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400851}
852
Matteo Scandolo4a036262020-08-17 15:56:13 -0700853// returns a Service with a given Mac Address
854func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200855 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700856 // memoizing it will remove the bottleneck
857 for _, pon := range o.Pons {
858 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700859 s, err := onu.findServiceByMacAddress(mac)
860 if err == nil {
861 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700862 }
863 }
864 }
865
Matteo Scandolo4a036262020-08-17 15:56:13 -0700866 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700867}
868
Matteo Scandolo4747d292019-08-05 11:50:18 -0700869// GRPC Endpoints
870
Shrey Baid688b4242020-07-10 20:40:10 +0530871func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700872
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700873 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800874
875 // Initialize the resource maps for this ONU
876 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
877 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
878
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700879 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700880
881 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
882 oltLogger.WithFields(log.Fields{
883 "OnuSn": _onu.Sn(),
884 }).Info("Received ActivateOnu call from VOLTHA")
885
William Kurkian0418bc82019-11-06 12:16:24 -0500886 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700887
Matteo Scandolocedde462021-03-09 17:37:16 -0800888 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700889 oltLogger.WithFields(log.Fields{
890 "IntfId": _onu.PonPortID,
891 "OnuSn": _onu.Sn(),
892 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800893 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700894 }
895
896 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
897
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700898 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700899}
900
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800901func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700902 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700903 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700904}
905
Shrey Baid688b4242020-07-10 20:40:10 +0530906func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530907 oltLogger.WithFields(log.Fields{
908 "IntfId": onu.IntfId,
909 "OnuId": onu.OnuId,
910 }).Info("Received DeleteOnu call from VOLTHA")
911
912 pon, err := o.GetPonById(onu.IntfId)
913 if err != nil {
914 oltLogger.WithFields(log.Fields{
915 "OnuId": onu.OnuId,
916 "IntfId": onu.IntfId,
917 "err": err,
918 }).Error("Can't find PonPort")
919 }
920 _onu, err := pon.GetOnuById(onu.OnuId)
921 if err != nil {
922 oltLogger.WithFields(log.Fields{
923 "OnuId": onu.OnuId,
924 "IntfId": onu.IntfId,
925 "err": err,
926 }).Error("Can't find Onu")
927 }
928
Matteo Scandolocedde462021-03-09 17:37:16 -0800929 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530930 oltLogger.WithFields(log.Fields{
931 "IntfId": _onu.PonPortID,
932 "OnuSn": _onu.Sn(),
933 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800934 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530935 }
936
Hardik Windlassad790cb2020-06-17 21:26:22 +0530937 // ONU Re-Discovery
938 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530939 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530940 }
941
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700942 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700943}
944
Shrey Baid688b4242020-07-10 20:40:10 +0530945func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700946 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800947 oltLogger.WithFields(log.Fields{
948 "oltId": o.ID,
949 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530950 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800951
Matteo Scandolo401503a2019-12-11 14:48:14 -0800952 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530953 if pon.InternalState.Current() == "enabled" {
954 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800955 msg := types.Message{
956 Type: types.PonIndication,
957 Data: types.PonIndicationMessage{
958 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530959 PonPortID: pon.ID,
960 },
961 }
962 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800963 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800964 }
965
Matteo Scandolo401503a2019-12-11 14:48:14 -0800966 // Note that we are not disabling the NNI as the real OLT does not.
967 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800968
969 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800970 oltMsg := types.Message{
971 Type: types.OltIndication,
972 Data: types.OltIndicationMessage{
973 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700974 },
975 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100976 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700977
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700978 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700979}
980
Shrey Baid688b4242020-07-10 20:40:10 +0530981func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530982 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200983 ponID := intf.GetIntfId()
984 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200985
Matteo Scandolof9d43412021-01-12 11:11:34 -0800986 msg := types.Message{
987 Type: types.PonIndication,
988 Data: types.PonIndicationMessage{
989 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200990 PonPortID: ponID,
991 },
992 }
993 o.channel <- msg
994
995 for _, onu := range pon.Onus {
996
Matteo Scandolof9d43412021-01-12 11:11:34 -0800997 onuIndication := types.OnuIndicationMessage{
998 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200999 PonPortID: ponID,
1000 OnuID: onu.ID,
1001 OnuSN: onu.SerialNumber,
1002 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001003 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001004
1005 }
1006
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001007 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001008}
1009
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001010func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001011 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301012 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001013 o.Enable(stream)
1014 return nil
1015}
1016
Shrey Baid688b4242020-07-10 20:40:10 +05301017func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301018 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301019 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001020 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001021
Matteo Scandolof9d43412021-01-12 11:11:34 -08001022 msg := types.Message{
1023 Type: types.PonIndication,
1024 Data: types.PonIndicationMessage{
1025 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301026 PonPortID: ponID,
1027 },
1028 }
1029 o.channel <- msg
1030
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001031 for _, onu := range pon.Onus {
1032
Matteo Scandolof9d43412021-01-12 11:11:34 -08001033 onuIndication := types.OnuIndicationMessage{
1034 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001035 PonPortID: ponID,
1036 OnuID: onu.ID,
1037 OnuSN: onu.SerialNumber,
1038 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001039 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001040
1041 }
1042
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001043 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001044}
1045
Shrey Baid688b4242020-07-10 20:40:10 +05301046func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001047 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001048 "IntfId": flow.AccessIntfId,
1049 "OnuId": flow.OnuId,
1050 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001051 "InnerVlan": flow.Classifier.IVid,
1052 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001053 "FlowType": flow.FlowType,
1054 "FlowId": flow.FlowId,
1055 "UniID": flow.UniId,
1056 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301057 }).Tracef("OLT receives FlowAdd")
1058
1059 flowKey := FlowKey{}
1060 if !o.enablePerf {
1061 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001062 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301063 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001064
1065 if flow.AccessIntfId == -1 {
1066 oltLogger.WithFields(log.Fields{
1067 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001068 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001069 } else if flow.FlowType == "multicast" {
1070 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001071 "Cookie": flow.Cookie,
1072 "DstPort": flow.Classifier.DstPort,
1073 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1074 "FlowId": flow.FlowId,
1075 "FlowType": flow.FlowType,
1076 "GemportId": flow.GemportId,
1077 "InnerVlan": flow.Classifier.IVid,
1078 "IntfId": flow.AccessIntfId,
1079 "IpProto": flow.Classifier.IpProto,
1080 "OnuId": flow.OnuId,
1081 "OuterVlan": flow.Classifier.OVid,
1082 "PortNo": flow.PortNo,
1083 "SrcPort": flow.Classifier.SrcPort,
1084 "UniID": flow.UniId,
1085 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001086 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001087 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001088 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001089 if err != nil {
1090 oltLogger.WithFields(log.Fields{
1091 "OnuId": flow.OnuId,
1092 "IntfId": flow.AccessIntfId,
1093 "err": err,
1094 }).Error("Can't find PonPort")
1095 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001096 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001097 if err != nil {
1098 oltLogger.WithFields(log.Fields{
1099 "OnuId": flow.OnuId,
1100 "IntfId": flow.AccessIntfId,
1101 "err": err,
1102 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001103 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001104 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001105
1106 // if the ONU is disabled reject the flow
1107 // as per VOL-4061 there is a small window during which the ONU is disabled
1108 // but the port has not been reported as down to ONOS
1109 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1110 oltLogger.WithFields(log.Fields{
1111 "OnuId": flow.OnuId,
1112 "IntfId": flow.AccessIntfId,
1113 "Flow": flow,
1114 "SerialNumber": onu.Sn(),
1115 "InternalState": onu.InternalState.Current(),
1116 }).Error("rejected-flow-because-of-onu-state")
1117 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1118 }
1119
Pragya Arya8bdb4532020-03-02 17:08:09 +05301120 if !o.enablePerf {
1121 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301122 // Generate event on first flow for ONU
1123 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001124 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301125 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301126 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001127
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001128 // validate that the flow reference correct IDs (Alloc, Gem)
1129 if err := o.validateFlow(flow); err != nil {
1130 oltLogger.WithFields(log.Fields{
1131 "OnuId": flow.OnuId,
1132 "IntfId": flow.AccessIntfId,
1133 "Flow": flow,
1134 "SerialNumber": onu.Sn(),
1135 "err": err,
1136 }).Error("invalid-flow-for-onu")
1137 return nil, err
1138 }
1139
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001140 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001141 o.storeAllocId(flow)
1142
Matteo Scandolof9d43412021-01-12 11:11:34 -08001143 msg := types.Message{
1144 Type: types.FlowAdd,
1145 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001146 PonPortID: pon.ID,
1147 OnuID: onu.ID,
1148 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001149 },
1150 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001151 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001152 }
1153
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001154 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001155}
1156
Pragya Arya8bdb4532020-03-02 17:08:09 +05301157// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301158func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001159
Pragya Arya8bdb4532020-03-02 17:08:09 +05301160 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001161 "AllocId": flow.AllocId,
1162 "Cookie": flow.Cookie,
1163 "FlowId": flow.FlowId,
1164 "FlowType": flow.FlowType,
1165 "GemportId": flow.GemportId,
1166 "IntfId": flow.AccessIntfId,
1167 "OnuId": flow.OnuId,
1168 "PortNo": flow.PortNo,
1169 "UniID": flow.UniId,
1170 "ReplicateFlow": flow.ReplicateFlow,
1171 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001172 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301173
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001174 olt.freeGemPortId(flow)
1175 olt.freeAllocId(flow)
1176
Pragya Arya8bdb4532020-03-02 17:08:09 +05301177 if !o.enablePerf { // remove only if flow were stored
1178 flowKey := FlowKey{
1179 ID: flow.FlowId,
1180 Direction: flow.FlowType,
1181 }
1182
1183 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001184 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301185 if !ok {
1186 oltLogger.Errorf("Flow %v not found", flow)
1187 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1188 }
1189
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001190 storedFlow := storedFlowIntf.(openolt.Flow)
1191
Pragya Arya8bdb4532020-03-02 17:08:09 +05301192 // if its ONU flow remove it from ONU also
1193 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001194 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1195 if err != nil {
1196 oltLogger.WithFields(log.Fields{
1197 "OnuId": storedFlow.OnuId,
1198 "IntfId": storedFlow.AccessIntfId,
1199 "PONs": olt.Pons,
1200 "err": err,
1201 }).Error("PON-port-not-found")
1202 return new(openolt.Empty), nil
1203 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301204 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1205 if err != nil {
1206 oltLogger.WithFields(log.Fields{
1207 "OnuId": storedFlow.OnuId,
1208 "IntfId": storedFlow.AccessIntfId,
1209 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001210 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301211 return new(openolt.Empty), nil
1212 }
1213 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001214 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301215 }
1216
1217 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001218 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301219 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001220
1221 if flow.AccessIntfId == -1 {
1222 oltLogger.WithFields(log.Fields{
1223 "FlowId": flow.FlowId,
1224 }).Debug("Removing OLT flow")
1225 } else if flow.FlowType == "multicast" {
1226 oltLogger.WithFields(log.Fields{
1227 "FlowId": flow.FlowId,
1228 }).Debug("Removing OLT multicast flow")
1229 } else {
1230
1231 onu, err := o.GetOnuByFlowId(flow.FlowId)
1232 if err != nil {
1233 oltLogger.WithFields(log.Fields{
1234 "OnuId": flow.OnuId,
1235 "IntfId": flow.AccessIntfId,
1236 "err": err,
1237 }).Error("Can't find Onu")
1238 return nil, err
1239 }
1240
Matteo Scandolof9d43412021-01-12 11:11:34 -08001241 msg := types.Message{
1242 Type: types.FlowRemoved,
1243 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301244 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001245 },
1246 }
1247 onu.Channel <- msg
1248 }
1249
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001250 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001251}
1252
Shrey Baid688b4242020-07-10 20:40:10 +05301253func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001254 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1255 oltLogger.WithFields(log.Fields{
1256 "signature": res.HeartbeatSignature,
1257 }).Trace("HeartbeatCheck")
1258 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001259}
1260
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001261func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001262 for _, pon := range o.Pons {
1263 for _, onu := range pon.Onus {
1264 for _, fId := range onu.FlowIds {
1265 if fId == flowId {
1266 return onu, nil
1267 }
1268 }
1269 }
1270 }
Shrey Baid688b4242020-07-10 20:40:10 +05301271 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001272}
1273
Shrey Baid688b4242020-07-10 20:40:10 +05301274func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001275
Matteo Scandolocedde462021-03-09 17:37:16 -08001276 intfIDs := []uint32{}
1277 for i := 0; i < o.NumPon; i++ {
1278 intfIDs = append(intfIDs, uint32(i))
1279 }
1280
1281 devinfo := &openolt.DeviceInfo{
1282 Vendor: common.Config.Olt.Vendor,
1283 Model: common.Config.Olt.Model,
1284 HardwareVersion: common.Config.Olt.HardwareVersion,
1285 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1286 Technology: common.Config.Olt.Technology,
1287 PonPorts: uint32(o.NumPon),
1288 OnuIdStart: onuIdStart,
1289 OnuIdEnd: onuIdEnd,
1290 AllocIdStart: allocIdStart,
1291 AllocIdEnd: allocIdEnd,
1292 GemportIdStart: gemportIdStart,
1293 GemportIdEnd: gemportIdEnd,
1294 FlowIdStart: flowIdStart,
1295 FlowIdEnd: flowIdEnd,
1296 DeviceSerialNumber: o.SerialNumber,
1297 DeviceId: common.Config.Olt.DeviceId,
1298 PreviouslyConnected: o.PreviouslyConnected,
1299 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1300 {
1301 IntfIds: intfIDs,
1302 Technology: common.Config.Olt.Technology,
1303 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1304 {
1305 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1306 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1307 Start: onuIdStart,
1308 End: onuIdEnd,
1309 },
1310 {
1311 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1312 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1313 Start: allocIdStart,
1314 End: allocIdEnd,
1315 },
1316 {
1317 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1318 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1319 Start: gemportIdStart,
1320 End: gemportIdEnd,
1321 },
1322 {
1323 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1324 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1325 Start: flowIdStart,
1326 End: flowIdEnd,
1327 },
1328 },
1329 },
1330 },
1331 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001332
1333 oltLogger.WithFields(log.Fields{
1334 "Vendor": devinfo.Vendor,
1335 "Model": devinfo.Model,
1336 "HardwareVersion": devinfo.HardwareVersion,
1337 "FirmwareVersion": devinfo.FirmwareVersion,
1338 "Technology": devinfo.Technology,
1339 "PonPorts": devinfo.PonPorts,
1340 "OnuIdStart": devinfo.OnuIdStart,
1341 "OnuIdEnd": devinfo.OnuIdEnd,
1342 "AllocIdStart": devinfo.AllocIdStart,
1343 "AllocIdEnd": devinfo.AllocIdEnd,
1344 "GemportIdStart": devinfo.GemportIdStart,
1345 "GemportIdEnd": devinfo.GemportIdEnd,
1346 "FlowIdStart": devinfo.FlowIdStart,
1347 "FlowIdEnd": devinfo.FlowIdEnd,
1348 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1349 "DeviceId": devinfo.DeviceId,
1350 "PreviouslyConnected": devinfo.PreviouslyConnected,
1351 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1352
1353 // once we connect, set the flag
1354 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001355
1356 return devinfo, nil
1357}
1358
Shrey Baid688b4242020-07-10 20:40:10 +05301359func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001360 pon, err := o.GetPonById(omci_msg.IntfId)
1361 if err != nil {
1362 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001363 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001364 "onu_id": omci_msg.OnuId,
1365 "pon_id": omci_msg.IntfId,
1366 }).Error("pon ID not found")
1367 return nil, err
1368 }
1369
1370 onu, err := pon.GetOnuById(omci_msg.OnuId)
1371 if err != nil {
1372 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001373 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001374 "onu_id": omci_msg.OnuId,
1375 "pon_id": omci_msg.IntfId,
1376 }).Error("onu ID not found")
1377 return nil, err
1378 }
1379
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001380 oltLogger.WithFields(log.Fields{
1381 "IntfId": onu.PonPortID,
1382 "OnuId": onu.ID,
1383 "OnuSn": onu.Sn(),
1384 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001385 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1386 if err != nil {
1387 log.WithFields(log.Fields{
1388 "IntfId": onu.PonPortID,
1389 "SerialNumber": onu.Sn(),
1390 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1391 "err": err.Error(),
1392 }).Error("cannot-parse-OMCI-packet")
1393 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001394 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001395 if onu.InternalState.Current() == OnuStateDisabled {
1396 // if the ONU is disabled just drop the message
1397 log.WithFields(log.Fields{
1398 "IntfId": onu.PonPortID,
1399 "SerialNumber": onu.Sn(),
1400 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1401 "omciPkt": omciPkt,
1402 "omciMsgType": omciMsg.MessageType,
1403 }).Warn("dropping-omci-message")
1404 } else {
1405 msg := types.Message{
1406 Type: types.OMCI,
1407 Data: types.OmciMessage{
1408 OnuSN: onu.SerialNumber,
1409 OnuID: onu.ID,
1410 OmciMsg: omciMsg,
1411 OmciPkt: omciPkt,
1412 },
1413 }
1414 onu.Channel <- msg
1415 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001416 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001417}
1418
Shrey Baid688b4242020-07-10 20:40:10 +05301419func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001420 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001421 if err != nil {
1422 oltLogger.WithFields(log.Fields{
1423 "OnuId": onuPkt.OnuId,
1424 "IntfId": onuPkt.IntfId,
1425 "err": err,
1426 }).Error("Can't find PonPort")
1427 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001428 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001429 if err != nil {
1430 oltLogger.WithFields(log.Fields{
1431 "OnuId": onuPkt.OnuId,
1432 "IntfId": onuPkt.IntfId,
1433 "err": err,
1434 }).Error("Can't find Onu")
1435 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001436
Matteo Scandolo075b1892019-10-07 12:11:07 -07001437 oltLogger.WithFields(log.Fields{
1438 "IntfId": onu.PonPortID,
1439 "OnuId": onu.ID,
1440 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001441 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001442 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001443
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001444 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001445
1446 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001447 if err != nil {
1448 onuLogger.WithFields(log.Fields{
1449 "IntfId": onu.PonPortID,
1450 "OnuId": onu.ID,
1451 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001452 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001453 }).Error("Can't find pktType in packet, droppint it")
1454 return new(openolt.Empty), nil
1455 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001456
Matteo Scandolo4a036262020-08-17 15:56:13 -07001457 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001458 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001459 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001460 "IntfId": onu.PonPortID,
1461 "OnuId": onu.ID,
1462 "OnuSn": onu.Sn(),
1463 "Pkt": rawpkt.Data(),
1464 }).Error("Can't find Dst MacAddress in packet, droppint it")
1465 return new(openolt.Empty), nil
1466 }
1467
Matteo Scandolof9d43412021-01-12 11:11:34 -08001468 msg := types.Message{
1469 Type: types.OnuPacketOut,
1470 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001471 IntfId: onuPkt.IntfId,
1472 OnuId: onuPkt.OnuId,
1473 Packet: rawpkt,
1474 Type: pktType,
1475 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001476 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001477 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001478
Matteo Scandolo075b1892019-10-07 12:11:07 -07001479 onu.Channel <- msg
1480
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001481 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001482}
1483
Shrey Baid688b4242020-07-10 20:40:10 +05301484func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001485
1486 // OLT Reboot is called in two cases:
1487 // - 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)
1488 // - when an OLT needs to be rebooted (voltcl device reboot)
1489
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001490 oltLogger.WithFields(log.Fields{
1491 "oltId": o.ID,
1492 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301493 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301494 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001495 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001496}
1497
Shrey Baid688b4242020-07-10 20:40:10 +05301498func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301499 oltLogger.WithFields(log.Fields{
1500 "oltId": o.ID,
1501 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301502 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301503
Pragya Arya2225f202020-01-29 18:05:01 +05301504 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001505 oltMsg := types.Message{
1506 Type: types.OltIndication,
1507 Data: types.OltIndicationMessage{
1508 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301509 },
Pragya Arya1881df02020-01-29 18:05:01 +05301510 }
Pragya Arya2225f202020-01-29 18:05:01 +05301511 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301512
Pragya Arya2225f202020-01-29 18:05:01 +05301513 for _, pon := range o.Pons {
1514 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001515 msg := types.Message{
1516 Type: types.PonIndication,
1517 Data: types.PonIndicationMessage{
1518 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301519 PonPortID: pon.ID,
1520 },
1521 }
1522 o.channel <- msg
1523 }
1524 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001525
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001526 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001527}
1528
Shrey Baid688b4242020-07-10 20:40:10 +05301529func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001530 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1531
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001532 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1533
1534 if err != nil {
1535 return nil, err
1536 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001537 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001538}
1539
Shrey Baid688b4242020-07-10 20:40:10 +05301540func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001541 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001542 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001543}
1544
Shrey Baid688b4242020-07-10 20:40:10 +05301545func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001546 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001547 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001548}
1549
Shrey Baid688b4242020-07-10 20:40:10 +05301550func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001551 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001552 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001553}
1554
Shrey Baid688b4242020-07-10 20:40:10 +05301555func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001556 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001557 return new(openolt.Empty), nil
1558}
1559
Shrey Baid688b4242020-07-10 20:40:10 +05301560func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001561 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001562 return new(openolt.Empty), nil
1563}
1564
Shrey Baid688b4242020-07-10 20:40:10 +05301565func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301566 oltLogger.WithFields(log.Fields{
1567 "OnuId": trafficSchedulers.OnuId,
1568 "IntfId": trafficSchedulers.IntfId,
1569 "OnuPortNo": trafficSchedulers.PortNo,
1570 }).Info("received CreateTrafficSchedulers")
1571
1572 if !s.enablePerf {
1573 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1574 if err != nil {
1575 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1576 return new(openolt.Empty), err
1577 }
1578 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1579 if err != nil {
1580 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1581 return new(openolt.Empty), err
1582 }
1583 onu.TrafficSchedulers = trafficSchedulers
1584 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001585 return new(openolt.Empty), nil
1586}
1587
Shrey Baid688b4242020-07-10 20:40:10 +05301588func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301589 oltLogger.WithFields(log.Fields{
1590 "OnuId": trafficSchedulers.OnuId,
1591 "IntfId": trafficSchedulers.IntfId,
1592 "OnuPortNo": trafficSchedulers.PortNo,
1593 }).Info("received RemoveTrafficSchedulers")
1594 if !s.enablePerf {
1595 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1596 if err != nil {
1597 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1598 return new(openolt.Empty), err
1599 }
1600 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1601 if err != nil {
1602 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1603 return new(openolt.Empty), err
1604 }
1605
1606 onu.TrafficSchedulers = nil
1607 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001608 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001609}
Scott Baker41724b82020-01-21 19:54:53 -08001610
Matteo Scandolo618a6582020-09-09 12:21:29 -07001611func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1612 oltLogger.WithFields(log.Fields{
1613 "GroupId": group.GroupId,
1614 "Command": group.Command,
1615 "Members": group.Members,
1616 "Action": group.Action,
1617 }).Debug("received PerformGroupOperation")
1618 return &openolt.Empty{}, nil
1619}
1620
1621func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1622 oltLogger.WithFields(log.Fields{
1623 "GroupId": group.GroupId,
1624 "Command": group.Command,
1625 "Members": group.Members,
1626 "Action": group.Action,
1627 }).Debug("received PerformGroupOperation")
1628 return &openolt.Empty{}, nil
1629}
1630
1631func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1632 return &common_protos.ReturnValues{}, nil
1633}
1634
1635func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1636 return &openolt.Empty{}, nil
1637}
1638
1639func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1640 return &openolt.OnuLogicalDistance{}, nil
1641}
1642
1643func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1644 return &openolt.OnuLogicalDistance{}, nil
1645}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001646
1647func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1648 return &openolt.GemPortStatistics{}, nil
1649}
1650
1651func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1652 return &openolt.OnuStatistics{}, nil
1653}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001654
1655func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1656 o.AllocIDsLock.Lock()
1657 defer o.AllocIDsLock.Unlock()
1658
Matteo Scandolo21195d62021-04-07 14:31:23 -07001659 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1660 oltLogger.WithFields(log.Fields{
1661 "IntfId": flow.AccessIntfId,
1662 "OnuId": flow.OnuId,
1663 "PortNo": flow.PortNo,
1664 "GemportId": flow.GemportId,
1665 "FlowId": flow.FlowId,
1666 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1667 }
1668
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001669 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001670 "IntfId": flow.AccessIntfId,
1671 "OnuId": flow.OnuId,
1672 "PortNo": flow.PortNo,
1673 "GemportId": flow.GemportId,
1674 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001675 }).Trace("storing-alloc-id-via-flow")
1676
1677 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1678 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1679 }
1680 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1681 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1682 }
1683 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1684}
1685
1686func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1687 // if this is the last flow referencing the AllocId then remove it
1688 o.AllocIDsLock.Lock()
1689 defer o.AllocIDsLock.Unlock()
1690
1691 oltLogger.WithFields(log.Fields{
1692 "IntfId": flow.AccessIntfId,
1693 "OnuId": flow.OnuId,
1694 "PortNo": flow.PortNo,
1695 "GemportId": flow.GemportId,
1696 }).Trace("freeing-alloc-id-via-flow")
1697
1698 // NOTE look at the freeGemPortId implementation for comments and context
1699 for ponId, ponValues := range o.AllocIDs {
1700 for onuId, onuValues := range ponValues {
1701 for uniId, uniValues := range onuValues {
1702 for allocId, flows := range uniValues {
1703 for flowId := range flows {
1704 // if the flow matches, remove it from the map.
1705 if flow.FlowId == flowId {
1706 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1707 }
1708 // if that was the last flow for a particular allocId, remove the entire allocId
1709 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1710 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1711 }
1712 }
1713 }
1714 }
1715 }
1716 }
1717}
1718
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001719func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001720 o.GemPortIDsLock.Lock()
1721 defer o.GemPortIDsLock.Unlock()
1722
1723 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1724 oltLogger.WithFields(log.Fields{
1725 "IntfId": ponId,
1726 "OnuId": onuId,
1727 "PortNo": portNo,
1728 "GemportId": gemId,
1729 "FlowId": flowId,
1730 }).Error("trying-to-store-gemport-for-unknown-onu")
1731 }
1732
1733 oltLogger.WithFields(log.Fields{
1734 "IntfId": ponId,
1735 "OnuId": onuId,
1736 "PortNo": portNo,
1737 "GemportId": gemId,
1738 "FlowId": flowId,
1739 }).Trace("storing-alloc-id-via-flow")
1740
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001741 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1742 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1743 }
1744 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1745 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1746 }
1747 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1748}
1749
1750func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001751 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001752 "IntfId": flow.AccessIntfId,
1753 "OnuId": flow.OnuId,
1754 "PortNo": flow.PortNo,
1755 "GemportId": flow.GemportId,
1756 "FlowId": flow.FlowId,
1757 "ReplicateFlow": flow.ReplicateFlow,
1758 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001759 }).Trace("storing-gem-port-id-via-flow")
1760
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001761 if flow.ReplicateFlow {
1762 for _, gem := range flow.PbitToGemport {
1763 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1764 }
1765 } else {
1766 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001767 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001768}
1769
1770func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1771 // if this is the last flow referencing the GemPort then remove it
1772 o.GemPortIDsLock.Lock()
1773 defer o.GemPortIDsLock.Unlock()
1774
1775 oltLogger.WithFields(log.Fields{
1776 "IntfId": flow.AccessIntfId,
1777 "OnuId": flow.OnuId,
1778 "PortNo": flow.PortNo,
1779 "GemportId": flow.GemportId,
1780 }).Trace("freeing-gem-port-id-via-flow")
1781
1782 // NOTE that this loop is not very performant, it would be better if the flow carries
1783 // the same information that it carries during a FlowAdd. If so we can directly remove
1784 // items from the map
1785
1786 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1787 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1788 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1789 //}
1790
1791 // NOTE this loop assumes that flow IDs are unique per device
1792 for ponId, ponValues := range o.GemPortIDs {
1793 for onuId, onuValues := range ponValues {
1794 for uniId, uniValues := range onuValues {
1795 for gemId, flows := range uniValues {
1796 for flowId := range flows {
1797 // if the flow matches, remove it from the map.
1798 if flow.FlowId == flowId {
1799 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1800 }
1801 // if that was the last flow for a particular gem, remove the entire gem
1802 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1803 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1804 }
1805 }
1806 }
1807 }
1808 }
1809 }
1810}
1811
1812// validateFlow checks that:
1813// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1814// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1815func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001816 // validate gemPort
1817 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001818 defer o.GemPortIDsLock.RUnlock()
1819 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001820 if onuId == uint32(flow.OnuId) {
1821 continue
1822 }
1823 for uniId, uni := range onu {
1824 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001825 if flow.ReplicateFlow {
1826 for _, flowGem := range flow.PbitToGemport {
1827 if gem == int32(flowGem) {
1828 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1829 }
1830 }
1831 } else {
1832 if gem == flow.GemportId {
1833 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1834 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001835 }
1836 }
1837 }
1838 }
1839
1840 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001841 defer o.AllocIDsLock.RUnlock()
1842 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001843 if onuId == uint32(flow.OnuId) {
1844 continue
1845 }
1846 for uniId, uni := range onu {
1847 for allocId := range uni {
1848 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001849 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 -08001850 }
1851 }
1852 }
1853 }
1854
1855 return nil
1856}
1857
1858// clearAllResources is invoked up OLT Reboot to remove all the allocated
1859// GemPorts, AllocId and ONU-IDs across the PONs
1860func (o *OltDevice) clearAllResources() {
1861
1862 // remove the resources received via flows
1863 o.GemPortIDsLock.Lock()
1864 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1865 o.GemPortIDsLock.Unlock()
1866 o.AllocIDsLock.Lock()
1867 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1868 o.AllocIDsLock.Unlock()
1869
1870 // remove the resources received via OMCI
1871 for _, pon := range o.Pons {
1872 pon.removeAllAllocIds()
1873 pon.removeAllGemPorts()
1874 pon.removeAllOnuIds()
1875 }
1876}