blob: 8520bf24ee4730423cf7f17933c3753cb00a0153 [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
Elia Battistonac63b112022-01-12 18:40:49 +010028 "github.com/opencord/voltha-protos/v5/go/extension"
29
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000030 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
31 "github.com/opencord/bbsim/internal/bbsim/types"
32 omcilib "github.com/opencord/bbsim/internal/common/omci"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000033 "github.com/opencord/voltha-protos/v5/go/ext/config"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000034
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070035 "github.com/google/gopacket"
36 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070037 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070038 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010039 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000040 "github.com/opencord/voltha-protos/v5/go/openolt"
41 "github.com/opencord/voltha-protos/v5/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070042 log "github.com/sirupsen/logrus"
43 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053044 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010045 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053046 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070047)
48
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070049var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070050 "module": "OLT",
51})
52
Matteo Scandolocedde462021-03-09 17:37:16 -080053const (
Girish Gowdra3015ff72021-06-28 11:48:56 -070054 onuIdStart = 1
55 // Least pon port on the real OLTs we test with today have 16 ports (not including the pluggable OLTs).
56 // Given that we have to support 512 ONUs per OLT, we have to have up to 32 ONU per PON (could be less
57 // on a higher density port OLT).
58 // We pass just enough limits here to ensure the resource pool is as
59 // compact as possible on the etcd to reduce storage.
60 onuIdEnd = onuIdStart + 31
61 allocIdStart = 1024
62 allocIdPerOnu = 4
63 allocIdEnd = allocIdStart + (onuIdEnd-onuIdStart+1)*allocIdPerOnu // up to 4 alloc-id per ONU
64 gemPortIdPerAllocId = 8
65 gemportIdStart = 1024
66 gemportIdEnd = gemportIdStart + (onuIdEnd-onuIdStart+1)*allocIdPerOnu*gemPortIdPerAllocId // up to 8 gemport-id per tcont/alloc-id
67 // The flow ids are no more necessary by the adapter, but still need to pass something dummy. Pass a very small valid range.
68 flowIdStart = 1
69 flowIdEnd = flowIdStart + 1
Matteo Scandolocedde462021-03-09 17:37:16 -080070)
71
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070072type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000073 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000074 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000075
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070076 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053077 ID int
78 SerialNumber string
79 NumNni int
80 NumPon int
81 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070082 NumUni int
Elia Battistonac63b112022-01-12 18:40:49 +010083 NumPots int
Pragya Arya2225f202020-01-29 18:05:01 +053084 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080085 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070086 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010087 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053088 Delay int
89 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053090 EventChannel chan common.Event
91 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053092 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080093 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070094
Matteo Scandolo27428702019-10-11 16:21:16 -070095 Pons []*PonPort
96 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070097
98 // OLT Attributes
99 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +0000100
101 enableContext context.Context
102 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +0530103
Matteo Scandolo4a036262020-08-17 15:56:13 -0700104 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +0530105 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800106
107 // Allocated Resources
108 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000109 AllocIDsLock sync.RWMutex
110 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
111 GemPortIDsLock sync.RWMutex
112 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
113 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700114}
115
Matteo Scandolo27428702019-10-11 16:21:16 -0700116var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700117
Matteo Scandolo27428702019-10-11 16:21:16 -0700118func GetOLT() *OltDevice {
119 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700120}
121
Matteo Scandolo4a036262020-08-17 15:56:13 -0700122func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700123 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530124 "ID": options.Olt.ID,
125 "NumNni": options.Olt.NniPorts,
126 "NumPon": options.Olt.PonPorts,
127 "NumOnuPerPon": options.Olt.OnusPonPort,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700128 "NumUni": options.Olt.UniPorts,
Elia Battistonac63b112022-01-12 18:40:49 +0100129 "NumPots": options.Olt.PotsPorts,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700130 }).Debug("CreateOLT")
131
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700132 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530133 ID: options.Olt.ID,
134 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700135 OperState: getOperStateFSM(func(e *fsm.Event) {
136 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
137 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800138 NumNni: int(options.Olt.NniPorts),
139 NumPon: int(options.Olt.PonPorts),
140 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700141 NumUni: int(options.Olt.UniPorts),
Elia Battistonac63b112022-01-12 18:40:49 +0100142 NumPots: int(options.Olt.PotsPorts),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800143 Pons: []*PonPort{},
144 Nnis: []*NniPort{},
145 Delay: options.BBSim.Delay,
146 enablePerf: options.BBSim.EnablePerf,
147 PublishEvents: options.BBSim.Events,
148 PortStatsInterval: options.Olt.PortStatsInterval,
149 dhcpServer: dhcp.NewDHCPServer(),
150 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800151 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
152 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000153 OmciResponseRate: options.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700154 }
155
Pragya Arya996a0892020-03-09 21:47:52 +0530156 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530157 olt.ControlledActivation = val
158 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700159 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530160 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
161 olt.ControlledActivation = Default
162 }
163
Matteo Scandolo4747d292019-08-05 11:50:18 -0700164 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700165 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700166 olt.InternalState = fsm.NewFSM(
167 "created",
168 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800169 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100170 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700171 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700172 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800173 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700174 },
175 fsm.Callbacks{
176 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700177 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700178 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100179 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800180 "enter_deleted": func(e *fsm.Event) {
181 // remove all the resource allocations
182 olt.clearAllResources()
183 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700184 },
185 )
186
Shrey Baid688b4242020-07-10 20:40:10 +0530187 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700188 // create NNI Port
189 nniPort, err := CreateNNI(&olt)
190 if err != nil {
191 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
192 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700193
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700194 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700195 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700196
Matteo Scandolo4a036262020-08-17 15:56:13 -0700197 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700198 nextCtag := map[string]int{}
199 nextStag := map[string]int{}
200
Matteo Scandolo4747d292019-08-05 11:50:18 -0700201 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700202 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800203
204 // initialize the resource maps for every PON Ports
205 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
206 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
207
Matteo Scandolo4a036262020-08-17 15:56:13 -0700208 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700209
Matteo Scandolo4a036262020-08-17 15:56:13 -0700210 // create ONU devices
211 for j := 0; j < olt.NumOnuPerPon; j++ {
212 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700213 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700214
Matteo Scandolo4a036262020-08-17 15:56:13 -0700215 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700216 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700217 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700218 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100219
Shrey Baid688b4242020-07-10 20:40:10 +0530220 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700221 if err := olt.InternalState.Event("initialize"); err != nil {
222 log.Errorf("Error initializing OLT: %v", err)
223 return nil
224 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100225 }
226
Pragya Arya324337e2020-02-20 14:35:08 +0530227 if olt.PublishEvents {
228 log.Debugf("BBSim event publishing is enabled")
229 // Create a channel to write event messages
230 olt.EventChannel = make(chan common.Event, 100)
231 }
232
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700233 return &olt
234}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700235
Shrey Baid688b4242020-07-10 20:40:10 +0530236func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100237
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000238 if o.OltServer == nil {
239 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100240 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800241 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100242 }
243
244 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800245 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100246
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100247 // FIXME we are assuming we have only one NNI
248 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800249 // NOTE we want to make sure the state is down when we initialize the OLT,
250 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
251 // in-band management
252 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100253 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800254
255 for ponId := range o.Pons {
256 // initialize the resource maps for every PON Ports
257 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
258 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
259 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700260}
261
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800262func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100263
Matteo Scandolo96f89192021-03-12 13:17:26 -0800264 o.PreviouslyConnected = false
265
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700266 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700267 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800268
269 oltLogger.WithFields(log.Fields{
270 "oltId": o.ID,
271 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
272
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700273 if o.InternalState.Is("enabled") {
274 oltLogger.WithFields(log.Fields{
275 "oltId": o.ID,
276 }).Info("This is an OLT soft reboot")
277 softReboot = true
278 }
279
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800280 // transition internal state to deleted
281 if err := o.InternalState.Event("delete"); err != nil {
282 oltLogger.WithFields(log.Fields{
283 "oltId": o.ID,
284 }).Errorf("Error deleting OLT: %v", err)
285 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100286 }
287
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700288 if softReboot {
289 for _, pon := range o.Pons {
290 if pon.InternalState.Current() == "enabled" {
291 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800292 msg := types.Message{
293 Type: types.PonIndication,
294 Data: types.PonIndicationMessage{
295 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700296 PonPortID: pon.ID,
297 },
298 }
299 o.channel <- msg
300 }
301
302 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800303 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700304 }
305 }
306 } else {
307 // PONs are already handled in the Disable call
308 for _, pon := range olt.Pons {
309 // ONUs are not automatically disabled when a PON goes down
310 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
311 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800312 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700313 }
Pragya Arya2225f202020-01-29 18:05:01 +0530314 }
315 }
316
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700317 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
318 o.StopOltServer()
319
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100320 // terminate the OLT's processOltMessages go routine
321 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700322
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700323 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100324 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100325
326 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800327 oltLogger.WithFields(log.Fields{
328 "oltId": o.ID,
329 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100330 return err
331 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800332 oltLogger.WithFields(log.Fields{
333 "oltId": o.ID,
334 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100335 return nil
336}
337
338// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800339func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700340 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700341 lis, err := net.Listen("tcp", address)
342 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700343 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700344 }
345 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100346
Matteo Scandolo4747d292019-08-05 11:50:18 -0700347 openolt.RegisterOpenoltServer(grpcServer, o)
348
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100349 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700350
Shrey Baid688b4242020-07-10 20:40:10 +0530351 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100352 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700353
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100354 return grpcServer, nil
355}
356
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800357// StartOltServer will create the grpc server that VOLTHA uses
358// to communicate with the device
359func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
360 oltServer, err := o.newOltServer()
361 if err != nil {
362 oltLogger.WithFields(log.Fields{
363 "err": err,
364 }).Error("Cannot OLT gRPC server")
365 return nil, err
366 }
367 return oltServer, nil
368}
369
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100370// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800371func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000372 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800373 oltLogger.WithFields(log.Fields{
374 "oltId": o.SerialNumber,
375 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000376 o.OltServer.Stop()
377 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700378 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700379}
380
381// Device Methods
382
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100383// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530384func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700385 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530386 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700387
David Bainbridge103cf022019-12-16 20:11:35 +0000388 // If enabled has already been called then an enabled context has
389 // been created. If this is the case then we want to cancel all the
390 // proessing loops associated with that enable before we recreate
391 // new ones
392 o.Lock()
393 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700394 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000395 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530396 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700397 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000398 }
399 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
400 o.Unlock()
401
Matteo Scandolo4747d292019-08-05 11:50:18 -0700402 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700403
Matteo Scandolo4a036262020-08-17 15:56:13 -0700404 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530405
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100406 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700407 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000408 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700409
410 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800411 oltMsg := types.Message{
412 Type: types.OltIndication,
413 Data: types.OltIndicationMessage{
414 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700415 },
416 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100417 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700418
419 // send NNI Port Indications
420 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800421 msg := types.Message{
422 Type: types.NniIndication,
423 Data: types.NniIndicationMessage{
424 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700425 NniPortID: nni.ID,
426 },
427 }
428 o.channel <- msg
429 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100430
Shrey Baid688b4242020-07-10 20:40:10 +0530431 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530432 for _, pon := range o.Pons {
433 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800434 msg := types.Message{
435 Type: types.PonIndication,
436 Data: types.PonIndicationMessage{
437 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530438 PonPortID: pon.ID,
439 },
440 }
441 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000442 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700443 // when the enableContext was canceled the ONUs stopped listening on the channel
444 for _, onu := range pon.Onus {
445 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
446
447 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700448 for _, uni := range onu.UniPorts {
449 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700450 }
451 }
Pragya Arya2225f202020-01-29 18:05:01 +0530452 }
453 } else {
454
455 // 1. controlledActivation == Default: Send both PON and ONUs indications
456 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
457
458 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
459 // send PON Port indications
460 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800461 msg := types.Message{
462 Type: types.PonIndication,
463 Data: types.PonIndicationMessage{
464 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530465 PonPortID: pon.ID,
466 },
467 }
468 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700469 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700470 }
471 }
472
Pragya Arya996a0892020-03-09 21:47:52 +0530473 if !o.enablePerf {
474 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700475 wg.Add(1)
476 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530477 }
478
Matteo Scandolo4747d292019-08-05 11:50:18 -0700479 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700480 oltLogger.WithFields(log.Fields{
481 "stream": stream,
482 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700483}
484
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700485func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530486 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700487
488loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530489 for {
490 select {
491 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
492 // send NNI port stats
493 for _, port := range o.Nnis {
494 incrementStat := true
495 if port.OperState.Current() == "down" {
496 incrementStat = false
497 }
498 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700499 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530500 }
501
502 // send PON port stats
503 for _, port := range o.Pons {
504 incrementStat := true
505 // do not increment port stats if PON port is down or no ONU is activated on PON port
506 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
507 incrementStat = false
508 }
509 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700510 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530511 }
512 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700513 oltLogger.Debug("Stop sending port stats")
514 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530515 }
Pragya Arya996a0892020-03-09 21:47:52 +0530516 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700517 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530518}
519
Matteo Scandolo4747d292019-08-05 11:50:18 -0700520// Helpers method
521
Matteo Scandolof9d43412021-01-12 11:11:34 -0800522func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
523
524 switch interfaceType {
525 case "nni":
526 if !o.HasNni(interfaceId) {
527 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
528 }
529
530 case "pon":
531 if !o.HasPon(interfaceId) {
532 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
533 }
534 }
535
536 alarmIndication := &openolt.AlarmIndication{
537 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
538 Status: alarmStatus,
539 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
540 }},
541 }
542
543 msg := types.Message{
544 Type: types.AlarmIndication,
545 Data: alarmIndication,
546 }
547
548 o.channel <- msg
549
550 return nil
551}
552
553func (o *OltDevice) HasNni(id uint32) bool {
554 for _, intf := range o.Nnis {
555 if intf.ID == id {
556 return true
557 }
558 }
559 return false
560}
561
562func (o *OltDevice) HasPon(id uint32) bool {
563 for _, intf := range o.Pons {
564 if intf.ID == id {
565 return true
566 }
567 }
568 return false
569}
570
Shrey Baid688b4242020-07-10 20:40:10 +0530571func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700572 for _, pon := range o.Pons {
573 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700574 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700575 }
576 }
Shrey Baid688b4242020-07-10 20:40:10 +0530577 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700578}
579
Shrey Baid688b4242020-07-10 20:40:10 +0530580func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700581 for _, nni := range o.Nnis {
582 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700583 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700584 }
585 }
Shrey Baid688b4242020-07-10 20:40:10 +0530586 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700587}
588
Scott Baker41724b82020-01-21 19:54:53 -0800589func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
590 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
591 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
592 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
593 return
594 }
595
596 oltLogger.WithFields(log.Fields{
597 "AlarmIndication": alarmInd,
598 }).Debug("Sent Indication_AlarmInd")
599}
600
Matteo Scandolof9d43412021-01-12 11:11:34 -0800601func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700602 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
603 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700604 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800605 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700606 }
607
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700608 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 "OperState": msg.OperState,
610 }).Debug("Sent Indication_OltInd")
611}
612
Matteo Scandolof9d43412021-01-12 11:11:34 -0800613func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700614 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800615 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800616 if err := nni.OperState.Event("enable"); err != nil {
617 log.WithFields(log.Fields{
618 "Type": nni.Type,
619 "IntfId": nni.ID,
620 "OperState": nni.OperState.Current(),
621 }).Errorf("Can't move NNI Port to enabled state: %v", err)
622 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800623 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800624 if err := nni.OperState.Event("disable"); err != nil {
625 log.WithFields(log.Fields{
626 "Type": nni.Type,
627 "IntfId": nni.ID,
628 "OperState": nni.OperState.Current(),
629 }).Errorf("Can't move NNI Port to disable state: %v", err)
630 }
631 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700632 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700633 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700634 Type: nni.Type,
635 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700636 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700637 }}
638
639 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700640 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800641 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700642 }
643
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700644 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700645 "Type": nni.Type,
646 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700647 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700648 }).Debug("Sent Indication_IntfOperInd for NNI")
649}
650
Pragya Arya2225f202020-01-29 18:05:01 +0530651func (o *OltDevice) sendPonIndication(ponPortID uint32) {
652
Matteo Scandolo4a036262020-08-17 15:56:13 -0700653 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530654 pon, _ := o.GetPonById(ponPortID)
655 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700656 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700657 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700658 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700659 }}
660
661 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700662 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800663 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664 }
665
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700666 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700667 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700668 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700669 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700670
Pragya Arya2225f202020-01-29 18:05:01 +0530671 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700672 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700673 Type: pon.Type,
674 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700675 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700676 }}
677
678 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700679 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800680 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700681 }
682
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700683 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700684 "Type": pon.Type,
685 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700686 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700687 }).Debug("Sent Indication_IntfOperInd for PON")
688}
689
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700690func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530691 if o.InternalState.Current() == "enabled" {
692 oltLogger.WithFields(log.Fields{
693 "Type": portType,
694 "IntfId": portID,
695 }).Trace("Sending port stats")
696 stats.IntfId = InterfaceIDToPortNo(portID, portType)
697 data := &openolt.Indication_PortStats{
698 PortStats: stats,
699 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700700
Shrey Baid55f328c2020-07-07 19:20:42 +0530701 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
702 oltLogger.Errorf("Failed to send PortStats: %v", err)
703 return
704 }
Pragya Arya996a0892020-03-09 21:47:52 +0530705 }
706}
707
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100708// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700709func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
710 oltLogger.WithFields(log.Fields{
711 "stream": stream,
712 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000713 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700714
David Bainbridge103cf022019-12-16 20:11:35 +0000715loop:
716 for {
717 select {
718 case <-ctx.Done():
719 oltLogger.Debug("OLT Indication processing canceled via context")
720 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700721 // do not terminate this loop if the stream is closed,
722 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
723 //case <-stream.Context().Done():
724 // oltLogger.Debug("OLT Indication processing canceled via stream context")
725 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000726 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700727 if !ok {
728 if ctx.Err() != nil {
729 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
730 }
731 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000732 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700733 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700734
David Bainbridge103cf022019-12-16 20:11:35 +0000735 oltLogger.WithFields(log.Fields{
736 "oltId": o.ID,
737 "messageType": message.Type,
738 }).Trace("Received message")
739
740 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800741 case types.OltIndication:
742 msg, _ := message.Data.(types.OltIndicationMessage)
743 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530744 _ = o.InternalState.Event("enable")
745 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800746 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530747 _ = o.InternalState.Event("disable")
748 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000749 }
750 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800751 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800752 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
753 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800754 case types.NniIndication:
755 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000756 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800757 case types.PonIndication:
758 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530759 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800760 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530761 if err := pon.OperState.Event("enable"); err != nil {
762 oltLogger.WithFields(log.Fields{
763 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800764 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530765 }).Error("Can't Enable Oper state for PON Port")
766 }
767 if err := pon.InternalState.Event("enable"); err != nil {
768 oltLogger.WithFields(log.Fields{
769 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800770 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530771 }).Error("Can't Enable Internal state for PON Port")
772 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800773 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530774 if err := pon.OperState.Event("disable"); err != nil {
775 oltLogger.WithFields(log.Fields{
776 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800777 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530778 }).Error("Can't Disable Oper state for PON Port")
779 }
780 if err := pon.InternalState.Event("disable"); err != nil {
781 oltLogger.WithFields(log.Fields{
782 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800783 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530784 }).Error("Can't Disable Internal state for PON Port")
785 }
Pragya Arya2225f202020-01-29 18:05:01 +0530786 }
David Bainbridge103cf022019-12-16 20:11:35 +0000787 default:
788 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
789 }
790 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700791 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100792 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700793 oltLogger.WithFields(log.Fields{
794 "stream": stream,
795 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700796}
797
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700798// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530799func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700800 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700801 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700802 for _, pon := range o.Pons {
803 for _, onu := range pon.Onus {
804 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700805 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700806 }
807 }
808 }
809
Shrey Baid688b4242020-07-10 20:40:10 +0530810 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700811}
812
William Kurkian9dadc5b2019-10-22 13:51:57 -0400813// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530814func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700815 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400816 // memoizing it will remove the bottleneck
817 for _, pon := range o.Pons {
818 if pon.ID == intfId {
819 for _, onu := range pon.Onus {
820 if onu.ID == onuId {
821 return onu, nil
822 }
823 }
824 }
825 }
Shrey Baid688b4242020-07-10 20:40:10 +0530826 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400827}
828
Matteo Scandolo4a036262020-08-17 15:56:13 -0700829// returns a Service with a given Mac Address
830func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700831 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700832 // memoizing it will remove the bottleneck
833 for _, pon := range o.Pons {
834 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700835 s, err := onu.findServiceByMacAddress(mac)
836 if err == nil {
837 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700838 }
839 }
840 }
841
Matteo Scandolo4a036262020-08-17 15:56:13 -0700842 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700843}
844
Matteo Scandolo4747d292019-08-05 11:50:18 -0700845// GRPC Endpoints
846
Shrey Baid688b4242020-07-10 20:40:10 +0530847func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700848
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700849 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800850
Matteo Scandolo8a574812021-05-20 15:18:53 -0700851 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800852 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
853 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
854
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700855 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700856
857 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
858 oltLogger.WithFields(log.Fields{
859 "OnuSn": _onu.Sn(),
860 }).Info("Received ActivateOnu call from VOLTHA")
861
William Kurkian0418bc82019-11-06 12:16:24 -0500862 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700863
Matteo Scandolocedde462021-03-09 17:37:16 -0800864 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700865 oltLogger.WithFields(log.Fields{
866 "IntfId": _onu.PonPortID,
867 "OnuSn": _onu.Sn(),
868 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800869 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700870 }
871
872 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
873
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700874 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700875}
876
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800877func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700878 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700879 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700880}
881
Shrey Baid688b4242020-07-10 20:40:10 +0530882func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530883 oltLogger.WithFields(log.Fields{
884 "IntfId": onu.IntfId,
885 "OnuId": onu.OnuId,
886 }).Info("Received DeleteOnu call from VOLTHA")
887
888 pon, err := o.GetPonById(onu.IntfId)
889 if err != nil {
890 oltLogger.WithFields(log.Fields{
891 "OnuId": onu.OnuId,
892 "IntfId": onu.IntfId,
893 "err": err,
894 }).Error("Can't find PonPort")
895 }
896 _onu, err := pon.GetOnuById(onu.OnuId)
897 if err != nil {
898 oltLogger.WithFields(log.Fields{
899 "OnuId": onu.OnuId,
900 "IntfId": onu.IntfId,
901 "err": err,
902 }).Error("Can't find Onu")
903 }
904
Matteo Scandolocedde462021-03-09 17:37:16 -0800905 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530906 oltLogger.WithFields(log.Fields{
907 "IntfId": _onu.PonPortID,
908 "OnuSn": _onu.Sn(),
909 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800910 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530911 }
912
Hardik Windlassad790cb2020-06-17 21:26:22 +0530913 // ONU Re-Discovery
914 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530915 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530916 }
917
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700918 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700919}
920
Shrey Baid688b4242020-07-10 20:40:10 +0530921func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700922 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800923 oltLogger.WithFields(log.Fields{
924 "oltId": o.ID,
925 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530926 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800927
Matteo Scandolo401503a2019-12-11 14:48:14 -0800928 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530929 if pon.InternalState.Current() == "enabled" {
930 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800931 msg := types.Message{
932 Type: types.PonIndication,
933 Data: types.PonIndicationMessage{
934 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530935 PonPortID: pon.ID,
936 },
937 }
938 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800939 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800940 }
941
Matteo Scandolo401503a2019-12-11 14:48:14 -0800942 // Note that we are not disabling the NNI as the real OLT does not.
943 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800944
945 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800946 oltMsg := types.Message{
947 Type: types.OltIndication,
948 Data: types.OltIndicationMessage{
949 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700950 },
951 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100952 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700953
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700954 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700955}
956
Shrey Baid688b4242020-07-10 20:40:10 +0530957func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530958 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200959 ponID := intf.GetIntfId()
960 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200961
Matteo Scandolof9d43412021-01-12 11:11:34 -0800962 msg := types.Message{
963 Type: types.PonIndication,
964 Data: types.PonIndicationMessage{
965 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200966 PonPortID: ponID,
967 },
968 }
969 o.channel <- msg
970
971 for _, onu := range pon.Onus {
972
Matteo Scandolof9d43412021-01-12 11:11:34 -0800973 onuIndication := types.OnuIndicationMessage{
974 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200975 PonPortID: ponID,
976 OnuID: onu.ID,
977 OnuSN: onu.SerialNumber,
978 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700979 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200980
981 }
982
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700983 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700984}
985
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100986func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700987 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530988 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700989 o.Enable(stream)
990 return nil
991}
992
Shrey Baid688b4242020-07-10 20:40:10 +0530993func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530994 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530995 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200996 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200997
Matteo Scandolof9d43412021-01-12 11:11:34 -0800998 msg := types.Message{
999 Type: types.PonIndication,
1000 Data: types.PonIndicationMessage{
1001 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301002 PonPortID: ponID,
1003 },
1004 }
1005 o.channel <- msg
1006
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001007 for _, onu := range pon.Onus {
1008
Matteo Scandolof9d43412021-01-12 11:11:34 -08001009 onuIndication := types.OnuIndicationMessage{
1010 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001011 PonPortID: ponID,
1012 OnuID: onu.ID,
1013 OnuSN: onu.SerialNumber,
1014 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001015 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001016
1017 }
1018
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001019 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001020}
1021
Shrey Baid688b4242020-07-10 20:40:10 +05301022func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001023 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001024 "IntfId": flow.AccessIntfId,
1025 "OnuId": flow.OnuId,
1026 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001027 "InnerVlan": flow.Classifier.IVid,
1028 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001029 "FlowType": flow.FlowType,
1030 "FlowId": flow.FlowId,
1031 "UniID": flow.UniId,
1032 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301033 }).Tracef("OLT receives FlowAdd")
1034
1035 flowKey := FlowKey{}
1036 if !o.enablePerf {
1037 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001038 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301039 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001040
1041 if flow.AccessIntfId == -1 {
1042 oltLogger.WithFields(log.Fields{
1043 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001044 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001045 } else if flow.FlowType == "multicast" {
1046 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001047 "Cookie": flow.Cookie,
1048 "DstPort": flow.Classifier.DstPort,
1049 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1050 "FlowId": flow.FlowId,
1051 "FlowType": flow.FlowType,
1052 "GemportId": flow.GemportId,
1053 "InnerVlan": flow.Classifier.IVid,
1054 "IntfId": flow.AccessIntfId,
1055 "IpProto": flow.Classifier.IpProto,
1056 "OnuId": flow.OnuId,
1057 "OuterVlan": flow.Classifier.OVid,
1058 "PortNo": flow.PortNo,
1059 "SrcPort": flow.Classifier.SrcPort,
1060 "UniID": flow.UniId,
1061 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001062 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001063 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001064 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
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 PonPort")
1071 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001072 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001073 if err != nil {
1074 oltLogger.WithFields(log.Fields{
1075 "OnuId": flow.OnuId,
1076 "IntfId": flow.AccessIntfId,
1077 "err": err,
1078 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001079 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001080 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001081
1082 // if the ONU is disabled reject the flow
1083 // as per VOL-4061 there is a small window during which the ONU is disabled
1084 // but the port has not been reported as down to ONOS
1085 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1086 oltLogger.WithFields(log.Fields{
1087 "OnuId": flow.OnuId,
1088 "IntfId": flow.AccessIntfId,
1089 "Flow": flow,
1090 "SerialNumber": onu.Sn(),
1091 "InternalState": onu.InternalState.Current(),
1092 }).Error("rejected-flow-because-of-onu-state")
1093 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1094 }
1095
Pragya Arya8bdb4532020-03-02 17:08:09 +05301096 if !o.enablePerf {
1097 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301098 // Generate event on first flow for ONU
1099 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001100 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301101 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301102 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001103
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001104 // validate that the flow reference correct IDs (Alloc, Gem)
1105 if err := o.validateFlow(flow); err != nil {
1106 oltLogger.WithFields(log.Fields{
1107 "OnuId": flow.OnuId,
1108 "IntfId": flow.AccessIntfId,
1109 "Flow": flow,
1110 "SerialNumber": onu.Sn(),
1111 "err": err,
1112 }).Error("invalid-flow-for-onu")
1113 return nil, err
1114 }
1115
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001116 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001117 o.storeAllocId(flow)
1118
Matteo Scandolof9d43412021-01-12 11:11:34 -08001119 msg := types.Message{
1120 Type: types.FlowAdd,
1121 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001122 PonPortID: pon.ID,
1123 OnuID: onu.ID,
1124 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001125 },
1126 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001127 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001128 }
1129
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001130 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001131}
1132
Pragya Arya8bdb4532020-03-02 17:08:09 +05301133// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301134func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001135
Pragya Arya8bdb4532020-03-02 17:08:09 +05301136 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001137 "AllocId": flow.AllocId,
1138 "Cookie": flow.Cookie,
1139 "FlowId": flow.FlowId,
1140 "FlowType": flow.FlowType,
1141 "GemportId": flow.GemportId,
1142 "IntfId": flow.AccessIntfId,
1143 "OnuId": flow.OnuId,
1144 "PortNo": flow.PortNo,
1145 "UniID": flow.UniId,
1146 "ReplicateFlow": flow.ReplicateFlow,
1147 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001148 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301149
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001150 olt.freeGemPortId(flow)
1151 olt.freeAllocId(flow)
1152
Pragya Arya8bdb4532020-03-02 17:08:09 +05301153 if !o.enablePerf { // remove only if flow were stored
1154 flowKey := FlowKey{
1155 ID: flow.FlowId,
1156 Direction: flow.FlowType,
1157 }
1158
1159 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001160 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301161 if !ok {
1162 oltLogger.Errorf("Flow %v not found", flow)
1163 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1164 }
1165
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001166 storedFlow := storedFlowIntf.(openolt.Flow)
1167
Pragya Arya8bdb4532020-03-02 17:08:09 +05301168 // if its ONU flow remove it from ONU also
1169 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001170 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1171 if err != nil {
1172 oltLogger.WithFields(log.Fields{
1173 "OnuId": storedFlow.OnuId,
1174 "IntfId": storedFlow.AccessIntfId,
1175 "PONs": olt.Pons,
1176 "err": err,
1177 }).Error("PON-port-not-found")
1178 return new(openolt.Empty), nil
1179 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301180 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1181 if err != nil {
1182 oltLogger.WithFields(log.Fields{
1183 "OnuId": storedFlow.OnuId,
1184 "IntfId": storedFlow.AccessIntfId,
1185 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001186 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301187 return new(openolt.Empty), nil
1188 }
1189 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001190 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301191 }
1192
1193 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001194 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301195 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001196
1197 if flow.AccessIntfId == -1 {
1198 oltLogger.WithFields(log.Fields{
1199 "FlowId": flow.FlowId,
1200 }).Debug("Removing OLT flow")
1201 } else if flow.FlowType == "multicast" {
1202 oltLogger.WithFields(log.Fields{
1203 "FlowId": flow.FlowId,
1204 }).Debug("Removing OLT multicast flow")
1205 } else {
1206
1207 onu, err := o.GetOnuByFlowId(flow.FlowId)
1208 if err != nil {
1209 oltLogger.WithFields(log.Fields{
1210 "OnuId": flow.OnuId,
1211 "IntfId": flow.AccessIntfId,
1212 "err": err,
1213 }).Error("Can't find Onu")
1214 return nil, err
1215 }
1216
Matteo Scandolof9d43412021-01-12 11:11:34 -08001217 msg := types.Message{
1218 Type: types.FlowRemoved,
1219 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301220 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001221 },
1222 }
1223 onu.Channel <- msg
1224 }
1225
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001226 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001227}
1228
Shrey Baid688b4242020-07-10 20:40:10 +05301229func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001230 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1231 oltLogger.WithFields(log.Fields{
1232 "signature": res.HeartbeatSignature,
1233 }).Trace("HeartbeatCheck")
1234 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001235}
1236
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001237func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001238 for _, pon := range o.Pons {
1239 for _, onu := range pon.Onus {
1240 for _, fId := range onu.FlowIds {
1241 if fId == flowId {
1242 return onu, nil
1243 }
1244 }
1245 }
1246 }
Shrey Baid688b4242020-07-10 20:40:10 +05301247 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001248}
1249
Shrey Baid688b4242020-07-10 20:40:10 +05301250func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001251
Matteo Scandolocedde462021-03-09 17:37:16 -08001252 intfIDs := []uint32{}
1253 for i := 0; i < o.NumPon; i++ {
1254 intfIDs = append(intfIDs, uint32(i))
1255 }
1256
1257 devinfo := &openolt.DeviceInfo{
1258 Vendor: common.Config.Olt.Vendor,
1259 Model: common.Config.Olt.Model,
1260 HardwareVersion: common.Config.Olt.HardwareVersion,
1261 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1262 Technology: common.Config.Olt.Technology,
1263 PonPorts: uint32(o.NumPon),
1264 OnuIdStart: onuIdStart,
1265 OnuIdEnd: onuIdEnd,
1266 AllocIdStart: allocIdStart,
1267 AllocIdEnd: allocIdEnd,
1268 GemportIdStart: gemportIdStart,
1269 GemportIdEnd: gemportIdEnd,
1270 FlowIdStart: flowIdStart,
1271 FlowIdEnd: flowIdEnd,
1272 DeviceSerialNumber: o.SerialNumber,
1273 DeviceId: common.Config.Olt.DeviceId,
1274 PreviouslyConnected: o.PreviouslyConnected,
1275 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1276 {
1277 IntfIds: intfIDs,
1278 Technology: common.Config.Olt.Technology,
1279 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1280 {
1281 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1282 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1283 Start: onuIdStart,
1284 End: onuIdEnd,
1285 },
1286 {
1287 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1288 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1289 Start: allocIdStart,
1290 End: allocIdEnd,
1291 },
1292 {
1293 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1294 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1295 Start: gemportIdStart,
1296 End: gemportIdEnd,
1297 },
1298 {
1299 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1300 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1301 Start: flowIdStart,
1302 End: flowIdEnd,
1303 },
1304 },
1305 },
1306 },
1307 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001308
1309 oltLogger.WithFields(log.Fields{
1310 "Vendor": devinfo.Vendor,
1311 "Model": devinfo.Model,
1312 "HardwareVersion": devinfo.HardwareVersion,
1313 "FirmwareVersion": devinfo.FirmwareVersion,
1314 "Technology": devinfo.Technology,
1315 "PonPorts": devinfo.PonPorts,
1316 "OnuIdStart": devinfo.OnuIdStart,
1317 "OnuIdEnd": devinfo.OnuIdEnd,
1318 "AllocIdStart": devinfo.AllocIdStart,
1319 "AllocIdEnd": devinfo.AllocIdEnd,
1320 "GemportIdStart": devinfo.GemportIdStart,
1321 "GemportIdEnd": devinfo.GemportIdEnd,
1322 "FlowIdStart": devinfo.FlowIdStart,
1323 "FlowIdEnd": devinfo.FlowIdEnd,
1324 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1325 "DeviceId": devinfo.DeviceId,
1326 "PreviouslyConnected": devinfo.PreviouslyConnected,
1327 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1328
1329 // once we connect, set the flag
1330 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001331
1332 return devinfo, nil
1333}
1334
Shrey Baid688b4242020-07-10 20:40:10 +05301335func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001336 pon, err := o.GetPonById(omci_msg.IntfId)
1337 if err != nil {
1338 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001339 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001340 "onu_id": omci_msg.OnuId,
1341 "pon_id": omci_msg.IntfId,
1342 }).Error("pon ID not found")
1343 return nil, err
1344 }
1345
1346 onu, err := pon.GetOnuById(omci_msg.OnuId)
1347 if err != nil {
1348 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001349 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001350 "onu_id": omci_msg.OnuId,
1351 "pon_id": omci_msg.IntfId,
1352 }).Error("onu ID not found")
1353 return nil, err
1354 }
1355
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001356 oltLogger.WithFields(log.Fields{
1357 "IntfId": onu.PonPortID,
1358 "OnuId": onu.ID,
1359 "OnuSn": onu.Sn(),
1360 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001361 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1362 if err != nil {
1363 log.WithFields(log.Fields{
1364 "IntfId": onu.PonPortID,
1365 "SerialNumber": onu.Sn(),
1366 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1367 "err": err.Error(),
1368 }).Error("cannot-parse-OMCI-packet")
1369 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001370 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001371 if onu.InternalState.Current() == OnuStateDisabled {
1372 // if the ONU is disabled just drop the message
1373 log.WithFields(log.Fields{
1374 "IntfId": onu.PonPortID,
1375 "SerialNumber": onu.Sn(),
1376 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1377 "omciPkt": omciPkt,
1378 "omciMsgType": omciMsg.MessageType,
1379 }).Warn("dropping-omci-message")
1380 } else {
1381 msg := types.Message{
1382 Type: types.OMCI,
1383 Data: types.OmciMessage{
1384 OnuSN: onu.SerialNumber,
1385 OnuID: onu.ID,
1386 OmciMsg: omciMsg,
1387 OmciPkt: omciPkt,
1388 },
1389 }
1390 onu.Channel <- msg
1391 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001392 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001393}
1394
Matteo Scandolo8a574812021-05-20 15:18:53 -07001395// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301396func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001397 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001398 if err != nil {
1399 oltLogger.WithFields(log.Fields{
1400 "OnuId": onuPkt.OnuId,
1401 "IntfId": onuPkt.IntfId,
1402 "err": err,
1403 }).Error("Can't find PonPort")
1404 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001405 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001406 if err != nil {
1407 oltLogger.WithFields(log.Fields{
1408 "OnuId": onuPkt.OnuId,
1409 "IntfId": onuPkt.IntfId,
1410 "err": err,
1411 }).Error("Can't find Onu")
1412 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001413
Matteo Scandolo075b1892019-10-07 12:11:07 -07001414 oltLogger.WithFields(log.Fields{
1415 "IntfId": onu.PonPortID,
1416 "OnuId": onu.ID,
1417 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001418 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001419 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001420
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001421 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001422
1423 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001424 if err != nil {
1425 onuLogger.WithFields(log.Fields{
1426 "IntfId": onu.PonPortID,
1427 "OnuId": onu.ID,
1428 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001429 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001430 }).Error("Can't find pktType in packet, droppint it")
1431 return new(openolt.Empty), nil
1432 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001433
Matteo Scandolo4a036262020-08-17 15:56:13 -07001434 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001435 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001436 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001437 "IntfId": onu.PonPortID,
1438 "OnuId": onu.ID,
1439 "OnuSn": onu.Sn(),
1440 "Pkt": rawpkt.Data(),
1441 }).Error("Can't find Dst MacAddress in packet, droppint it")
1442 return new(openolt.Empty), nil
1443 }
1444
Matteo Scandolof9d43412021-01-12 11:11:34 -08001445 msg := types.Message{
1446 Type: types.OnuPacketOut,
1447 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001448 IntfId: onuPkt.IntfId,
1449 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001450 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001451 Packet: rawpkt,
1452 Type: pktType,
1453 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001454 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001455 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001456
Matteo Scandolo075b1892019-10-07 12:11:07 -07001457 onu.Channel <- msg
1458
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001459 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001460}
1461
Shrey Baid688b4242020-07-10 20:40:10 +05301462func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001463
1464 // OLT Reboot is called in two cases:
1465 // - 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)
1466 // - when an OLT needs to be rebooted (voltcl device reboot)
1467
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001468 oltLogger.WithFields(log.Fields{
1469 "oltId": o.ID,
1470 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301471 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301472 go func() { _ = o.RestartOLT() }()
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) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301477 oltLogger.WithFields(log.Fields{
1478 "oltId": o.ID,
1479 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301480 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301481
Pragya Arya2225f202020-01-29 18:05:01 +05301482 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001483 oltMsg := types.Message{
1484 Type: types.OltIndication,
1485 Data: types.OltIndicationMessage{
1486 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301487 },
Pragya Arya1881df02020-01-29 18:05:01 +05301488 }
Pragya Arya2225f202020-01-29 18:05:01 +05301489 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301490
Pragya Arya2225f202020-01-29 18:05:01 +05301491 for _, pon := range o.Pons {
1492 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001493 msg := types.Message{
1494 Type: types.PonIndication,
1495 Data: types.PonIndicationMessage{
1496 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301497 PonPortID: pon.ID,
1498 },
1499 }
1500 o.channel <- msg
1501 }
1502 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001503
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001504 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001505}
1506
Shrey Baid688b4242020-07-10 20:40:10 +05301507func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001508 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1509
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001510 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1511
1512 if err != nil {
1513 return nil, err
1514 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001515 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001516}
1517
Shrey Baid688b4242020-07-10 20:40:10 +05301518func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001519 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001520 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001521}
1522
Shrey Baid688b4242020-07-10 20:40:10 +05301523func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001524 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001525 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001526}
1527
Shrey Baid688b4242020-07-10 20:40:10 +05301528func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001529 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001530 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001531}
1532
Shrey Baid688b4242020-07-10 20:40:10 +05301533func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001534 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001535 return new(openolt.Empty), nil
1536}
1537
Matteo Scandolo8a574812021-05-20 15:18:53 -07001538func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1539 oltLogger.WithFields(log.Fields{
1540 "OnuId": tq.OnuId,
1541 "IntfId": tq.IntfId,
1542 "OnuPortNo": tq.PortNo,
1543 "UniId": tq.UniId,
1544 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001545 return new(openolt.Empty), nil
1546}
1547
Matteo Scandolo8a574812021-05-20 15:18:53 -07001548func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301549 oltLogger.WithFields(log.Fields{
1550 "OnuId": trafficSchedulers.OnuId,
1551 "IntfId": trafficSchedulers.IntfId,
1552 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001553 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301554 }).Info("received CreateTrafficSchedulers")
1555
1556 if !s.enablePerf {
1557 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1558 if err != nil {
1559 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1560 return new(openolt.Empty), err
1561 }
1562 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1563 if err != nil {
1564 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1565 return new(openolt.Empty), err
1566 }
1567 onu.TrafficSchedulers = trafficSchedulers
1568 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001569 return new(openolt.Empty), nil
1570}
1571
Shrey Baid688b4242020-07-10 20:40:10 +05301572func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301573 oltLogger.WithFields(log.Fields{
1574 "OnuId": trafficSchedulers.OnuId,
1575 "IntfId": trafficSchedulers.IntfId,
1576 "OnuPortNo": trafficSchedulers.PortNo,
1577 }).Info("received RemoveTrafficSchedulers")
1578 if !s.enablePerf {
1579 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1580 if err != nil {
1581 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1582 return new(openolt.Empty), err
1583 }
1584 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1585 if err != nil {
1586 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1587 return new(openolt.Empty), err
1588 }
1589
1590 onu.TrafficSchedulers = nil
1591 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001592 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001593}
Scott Baker41724b82020-01-21 19:54:53 -08001594
Matteo Scandolo618a6582020-09-09 12:21:29 -07001595func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1596 oltLogger.WithFields(log.Fields{
1597 "GroupId": group.GroupId,
1598 "Command": group.Command,
1599 "Members": group.Members,
1600 "Action": group.Action,
1601 }).Debug("received PerformGroupOperation")
1602 return &openolt.Empty{}, nil
1603}
1604
1605func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1606 oltLogger.WithFields(log.Fields{
1607 "GroupId": group.GroupId,
1608 "Command": group.Command,
1609 "Members": group.Members,
1610 "Action": group.Action,
1611 }).Debug("received PerformGroupOperation")
1612 return &openolt.Empty{}, nil
1613}
1614
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001615func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1616 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001617}
1618
1619func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1620 return &openolt.Empty{}, nil
1621}
1622
1623func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1624 return &openolt.OnuLogicalDistance{}, nil
1625}
1626
1627func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1628 return &openolt.OnuLogicalDistance{}, nil
1629}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001630
Girish Gowdra62f24292021-05-12 16:28:39 -07001631func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1632 return &openolt.PonRxPowerData{}, nil
1633}
1634
Matteo Scandolo96f89192021-03-12 13:17:26 -08001635func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1636 return &openolt.GemPortStatistics{}, nil
1637}
1638
1639func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1640 return &openolt.OnuStatistics{}, nil
1641}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001642
1643func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1644 o.AllocIDsLock.Lock()
1645 defer o.AllocIDsLock.Unlock()
1646
Matteo Scandolo21195d62021-04-07 14:31:23 -07001647 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1648 oltLogger.WithFields(log.Fields{
1649 "IntfId": flow.AccessIntfId,
1650 "OnuId": flow.OnuId,
1651 "PortNo": flow.PortNo,
1652 "GemportId": flow.GemportId,
1653 "FlowId": flow.FlowId,
1654 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1655 }
1656
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001657 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001658 "IntfId": flow.AccessIntfId,
1659 "OnuId": flow.OnuId,
1660 "PortNo": flow.PortNo,
1661 "GemportId": flow.GemportId,
1662 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001663 }).Trace("storing-alloc-id-via-flow")
1664
1665 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1666 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1667 }
1668 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1669 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1670 }
1671 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1672}
1673
1674func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1675 // if this is the last flow referencing the AllocId then remove it
1676 o.AllocIDsLock.Lock()
1677 defer o.AllocIDsLock.Unlock()
1678
1679 oltLogger.WithFields(log.Fields{
1680 "IntfId": flow.AccessIntfId,
1681 "OnuId": flow.OnuId,
1682 "PortNo": flow.PortNo,
1683 "GemportId": flow.GemportId,
1684 }).Trace("freeing-alloc-id-via-flow")
1685
1686 // NOTE look at the freeGemPortId implementation for comments and context
1687 for ponId, ponValues := range o.AllocIDs {
1688 for onuId, onuValues := range ponValues {
1689 for uniId, uniValues := range onuValues {
1690 for allocId, flows := range uniValues {
1691 for flowId := range flows {
1692 // if the flow matches, remove it from the map.
1693 if flow.FlowId == flowId {
1694 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1695 }
1696 // if that was the last flow for a particular allocId, remove the entire allocId
1697 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1698 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1699 }
1700 }
1701 }
1702 }
1703 }
1704 }
1705}
1706
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001707func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001708 o.GemPortIDsLock.Lock()
1709 defer o.GemPortIDsLock.Unlock()
1710
1711 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1712 oltLogger.WithFields(log.Fields{
1713 "IntfId": ponId,
1714 "OnuId": onuId,
1715 "PortNo": portNo,
1716 "GemportId": gemId,
1717 "FlowId": flowId,
1718 }).Error("trying-to-store-gemport-for-unknown-onu")
1719 }
1720
1721 oltLogger.WithFields(log.Fields{
1722 "IntfId": ponId,
1723 "OnuId": onuId,
1724 "PortNo": portNo,
1725 "GemportId": gemId,
1726 "FlowId": flowId,
1727 }).Trace("storing-alloc-id-via-flow")
1728
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001729 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1730 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1731 }
1732 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1733 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1734 }
1735 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1736}
1737
1738func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001739 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001740 "IntfId": flow.AccessIntfId,
1741 "OnuId": flow.OnuId,
1742 "PortNo": flow.PortNo,
1743 "GemportId": flow.GemportId,
1744 "FlowId": flow.FlowId,
1745 "ReplicateFlow": flow.ReplicateFlow,
1746 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001747 }).Trace("storing-gem-port-id-via-flow")
1748
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001749 if flow.ReplicateFlow {
1750 for _, gem := range flow.PbitToGemport {
1751 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1752 }
1753 } else {
1754 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001755 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001756}
1757
1758func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1759 // if this is the last flow referencing the GemPort then remove it
1760 o.GemPortIDsLock.Lock()
1761 defer o.GemPortIDsLock.Unlock()
1762
1763 oltLogger.WithFields(log.Fields{
1764 "IntfId": flow.AccessIntfId,
1765 "OnuId": flow.OnuId,
1766 "PortNo": flow.PortNo,
1767 "GemportId": flow.GemportId,
1768 }).Trace("freeing-gem-port-id-via-flow")
1769
1770 // NOTE that this loop is not very performant, it would be better if the flow carries
1771 // the same information that it carries during a FlowAdd. If so we can directly remove
1772 // items from the map
1773
1774 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1775 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1776 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1777 //}
1778
1779 // NOTE this loop assumes that flow IDs are unique per device
1780 for ponId, ponValues := range o.GemPortIDs {
1781 for onuId, onuValues := range ponValues {
1782 for uniId, uniValues := range onuValues {
1783 for gemId, flows := range uniValues {
1784 for flowId := range flows {
1785 // if the flow matches, remove it from the map.
1786 if flow.FlowId == flowId {
1787 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1788 }
1789 // if that was the last flow for a particular gem, remove the entire gem
1790 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1791 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1792 }
1793 }
1794 }
1795 }
1796 }
1797 }
1798}
1799
1800// validateFlow checks that:
1801// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1802// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1803func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001804 // validate gemPort
1805 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001806 defer o.GemPortIDsLock.RUnlock()
1807 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001808 if onuId == uint32(flow.OnuId) {
1809 continue
1810 }
1811 for uniId, uni := range onu {
1812 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001813 if flow.ReplicateFlow {
1814 for _, flowGem := range flow.PbitToGemport {
1815 if gem == int32(flowGem) {
1816 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1817 }
1818 }
1819 } else {
1820 if gem == flow.GemportId {
1821 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1822 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001823 }
1824 }
1825 }
1826 }
1827
1828 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001829 defer o.AllocIDsLock.RUnlock()
1830 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001831 if onuId == uint32(flow.OnuId) {
1832 continue
1833 }
1834 for uniId, uni := range onu {
1835 for allocId := range uni {
1836 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001837 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 -08001838 }
1839 }
1840 }
1841 }
1842
1843 return nil
1844}
1845
1846// clearAllResources is invoked up OLT Reboot to remove all the allocated
1847// GemPorts, AllocId and ONU-IDs across the PONs
1848func (o *OltDevice) clearAllResources() {
1849
1850 // remove the resources received via flows
1851 o.GemPortIDsLock.Lock()
1852 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1853 o.GemPortIDsLock.Unlock()
1854 o.AllocIDsLock.Lock()
1855 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1856 o.AllocIDsLock.Unlock()
1857
1858 // remove the resources received via OMCI
1859 for _, pon := range o.Pons {
1860 pon.removeAllAllocIds()
1861 pon.removeAllGemPorts()
1862 pon.removeAllOnuIds()
1863 }
1864}