blob: a6e55c0c695cc31d0afd8782e925fe8f9b684341 [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 (
Matteo Scandolo52d12e32022-02-02 15:30:20 -080054 onuIdStart = 1
Girish Gowdra3015ff72021-06-28 11:48:56 -070055 allocIdStart = 1024
Girish Gowdra3015ff72021-06-28 11:48:56 -070056 gemPortIdPerAllocId = 8
57 gemportIdStart = 1024
Girish Gowdra3015ff72021-06-28 11:48:56 -070058 // The flow ids are no more necessary by the adapter, but still need to pass something dummy. Pass a very small valid range.
59 flowIdStart = 1
60 flowIdEnd = flowIdStart + 1
Matteo Scandolocedde462021-03-09 17:37:16 -080061)
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
Elia Battiston420c9092022-02-02 12:17:54 +010071 NniSpeed uint32
Pragya Arya2225f202020-01-29 18:05:01 +053072 NumPon int
73 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070074 NumUni int
Elia Battistonac63b112022-01-12 18:40:49 +010075 NumPots int
Pragya Arya2225f202020-01-29 18:05:01 +053076 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080077 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070078 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010079 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053080 Delay int
81 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053082 EventChannel chan common.Event
83 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053084 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080085 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070086
Matteo Scandolo27428702019-10-11 16:21:16 -070087 Pons []*PonPort
88 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070089
90 // OLT Attributes
91 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000092
93 enableContext context.Context
94 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053095
Matteo Scandolo4a036262020-08-17 15:56:13 -070096 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053097 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080098
Matteo Scandolo52d12e32022-02-02 15:30:20 -080099 // resource ranges (only the ones that depends on the topology size)
100 onuIdEnd uint32
101 allocIdPerOnu uint32
102 allocIdEnd uint32
103 gemportIdEnd uint32
104
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800105 // Allocated Resources
106 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000107 AllocIDsLock sync.RWMutex
108 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
109 GemPortIDsLock sync.RWMutex
110 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
111 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700112}
113
Matteo Scandolo27428702019-10-11 16:21:16 -0700114var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700115
Matteo Scandolo27428702019-10-11 16:21:16 -0700116func GetOLT() *OltDevice {
117 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700118}
119
Matteo Scandolo4a036262020-08-17 15:56:13 -0700120func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700121 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530122 "ID": options.Olt.ID,
123 "NumNni": options.Olt.NniPorts,
Elia Battiston420c9092022-02-02 12:17:54 +0100124 "NniSpeed": options.Olt.NniSpeed,
Pragya Arya996a0892020-03-09 21:47:52 +0530125 "NumPon": options.Olt.PonPorts,
126 "NumOnuPerPon": options.Olt.OnusPonPort,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700127 "NumUni": options.Olt.UniPorts,
Elia Battistonac63b112022-01-12 18:40:49 +0100128 "NumPots": options.Olt.PotsPorts,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700129 }).Debug("CreateOLT")
130
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700131 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530132 ID: options.Olt.ID,
133 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700134 OperState: getOperStateFSM(func(e *fsm.Event) {
135 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
136 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800137 NumNni: int(options.Olt.NniPorts),
Elia Battiston420c9092022-02-02 12:17:54 +0100138 NniSpeed: options.Olt.NniSpeed,
Matteo Scandolo96f89192021-03-12 13:17:26 -0800139 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
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800156 // create the resource ranges based on the configuration
157 olt.onuIdEnd = onuIdStart + (options.Olt.OnusPonPort - 1) // we need one ONU ID available per ONU, but the smaller the range the smaller the pool created in the openolt adapter
158 olt.allocIdPerOnu = uint32(olt.NumUni * len(common.Services)) // 1 allocId per Service * UNI
159 olt.allocIdEnd = allocIdStart + (options.Olt.OnusPonPort * olt.allocIdPerOnu) // 1 allocId per Service * UNI * ONU
160 olt.gemportIdEnd = gemportIdStart + (options.Olt.OnusPonPort * olt.allocIdPerOnu * gemPortIdPerAllocId) // up to 8 gemport-id per tcont/alloc-id
161
Pragya Arya996a0892020-03-09 21:47:52 +0530162 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530163 olt.ControlledActivation = val
164 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700165 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530166 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
167 olt.ControlledActivation = Default
168 }
169
Matteo Scandolo4747d292019-08-05 11:50:18 -0700170 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700171 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700172 olt.InternalState = fsm.NewFSM(
173 "created",
174 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800175 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100176 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700177 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700178 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800179 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700180 },
181 fsm.Callbacks{
182 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700183 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700184 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100185 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800186 "enter_deleted": func(e *fsm.Event) {
187 // remove all the resource allocations
188 olt.clearAllResources()
189 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700190 },
191 )
192
Shrey Baid688b4242020-07-10 20:40:10 +0530193 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700194 // create NNI Port
195 nniPort, err := CreateNNI(&olt)
196 if err != nil {
197 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
198 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700199
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700200 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700201 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700202
Matteo Scandolo4a036262020-08-17 15:56:13 -0700203 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700204 nextCtag := map[string]int{}
205 nextStag := map[string]int{}
206
Matteo Scandolo4747d292019-08-05 11:50:18 -0700207 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700208 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800209
210 // initialize the resource maps for every PON Ports
211 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
212 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
213
Matteo Scandolo4a036262020-08-17 15:56:13 -0700214 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700215
Matteo Scandolo4a036262020-08-17 15:56:13 -0700216 // create ONU devices
217 for j := 0; j < olt.NumOnuPerPon; j++ {
218 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700219 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700220
Matteo Scandolo4a036262020-08-17 15:56:13 -0700221 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700222 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700223 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700224 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100225
Shrey Baid688b4242020-07-10 20:40:10 +0530226 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700227 if err := olt.InternalState.Event("initialize"); err != nil {
228 log.Errorf("Error initializing OLT: %v", err)
229 return nil
230 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231 }
232
Pragya Arya324337e2020-02-20 14:35:08 +0530233 if olt.PublishEvents {
234 log.Debugf("BBSim event publishing is enabled")
235 // Create a channel to write event messages
236 olt.EventChannel = make(chan common.Event, 100)
237 }
238
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700239 return &olt
240}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700241
Shrey Baid688b4242020-07-10 20:40:10 +0530242func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000244 if o.OltServer == nil {
245 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100246 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800247 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100248 }
249
250 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800251 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100252
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100253 // FIXME we are assuming we have only one NNI
254 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800255 // NOTE we want to make sure the state is down when we initialize the OLT,
256 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
257 // in-band management
258 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100259 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800260
261 for ponId := range o.Pons {
262 // initialize the resource maps for every PON Ports
263 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
264 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
265 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700266}
267
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800268func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100269
Matteo Scandolo96f89192021-03-12 13:17:26 -0800270 o.PreviouslyConnected = false
271
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700272 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700273 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800274
275 oltLogger.WithFields(log.Fields{
276 "oltId": o.ID,
277 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
278
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700279 if o.InternalState.Is("enabled") {
280 oltLogger.WithFields(log.Fields{
281 "oltId": o.ID,
282 }).Info("This is an OLT soft reboot")
283 softReboot = true
284 }
285
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800286 // transition internal state to deleted
287 if err := o.InternalState.Event("delete"); err != nil {
288 oltLogger.WithFields(log.Fields{
289 "oltId": o.ID,
290 }).Errorf("Error deleting OLT: %v", err)
291 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100292 }
293
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700294 if softReboot {
295 for _, pon := range o.Pons {
296 if pon.InternalState.Current() == "enabled" {
297 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800298 msg := types.Message{
299 Type: types.PonIndication,
300 Data: types.PonIndicationMessage{
301 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700302 PonPortID: pon.ID,
303 },
304 }
305 o.channel <- msg
306 }
307
308 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800309 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700310 }
311 }
312 } else {
313 // PONs are already handled in the Disable call
314 for _, pon := range olt.Pons {
315 // ONUs are not automatically disabled when a PON goes down
316 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
317 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800318 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700319 }
Pragya Arya2225f202020-01-29 18:05:01 +0530320 }
321 }
322
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700323 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
324 o.StopOltServer()
325
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100326 // terminate the OLT's processOltMessages go routine
327 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700328
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700329 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100330 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100331
332 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800333 oltLogger.WithFields(log.Fields{
334 "oltId": o.ID,
335 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100336 return err
337 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800338 oltLogger.WithFields(log.Fields{
339 "oltId": o.ID,
340 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100341 return nil
342}
343
344// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800345func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700346 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700347 lis, err := net.Listen("tcp", address)
348 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700349 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700350 }
351 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100352
Matteo Scandolo4747d292019-08-05 11:50:18 -0700353 openolt.RegisterOpenoltServer(grpcServer, o)
354
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100355 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700356
Shrey Baid688b4242020-07-10 20:40:10 +0530357 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100358 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700359
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100360 return grpcServer, nil
361}
362
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800363// StartOltServer will create the grpc server that VOLTHA uses
364// to communicate with the device
365func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
366 oltServer, err := o.newOltServer()
367 if err != nil {
368 oltLogger.WithFields(log.Fields{
369 "err": err,
370 }).Error("Cannot OLT gRPC server")
371 return nil, err
372 }
373 return oltServer, nil
374}
375
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100376// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800377func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000378 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800379 oltLogger.WithFields(log.Fields{
380 "oltId": o.SerialNumber,
381 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000382 o.OltServer.Stop()
383 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700384 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700385}
386
387// Device Methods
388
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100389// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530390func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700391 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530392 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700393
David Bainbridge103cf022019-12-16 20:11:35 +0000394 // If enabled has already been called then an enabled context has
395 // been created. If this is the case then we want to cancel all the
396 // proessing loops associated with that enable before we recreate
397 // new ones
398 o.Lock()
399 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700400 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000401 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530402 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700403 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000404 }
405 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
406 o.Unlock()
407
Matteo Scandolo4747d292019-08-05 11:50:18 -0700408 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700409
Matteo Scandolo4a036262020-08-17 15:56:13 -0700410 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530411
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100412 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700413 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000414 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700415
416 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800417 oltMsg := types.Message{
418 Type: types.OltIndication,
419 Data: types.OltIndicationMessage{
420 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700421 },
422 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100423 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700424
425 // send NNI Port Indications
426 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800427 msg := types.Message{
428 Type: types.NniIndication,
429 Data: types.NniIndicationMessage{
430 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700431 NniPortID: nni.ID,
432 },
433 }
434 o.channel <- msg
435 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100436
Shrey Baid688b4242020-07-10 20:40:10 +0530437 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530438 for _, pon := range o.Pons {
439 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800440 msg := types.Message{
441 Type: types.PonIndication,
442 Data: types.PonIndicationMessage{
443 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530444 PonPortID: pon.ID,
445 },
446 }
447 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000448 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700449 // when the enableContext was canceled the ONUs stopped listening on the channel
450 for _, onu := range pon.Onus {
451 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
452
453 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700454 for _, uni := range onu.UniPorts {
455 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700456 }
457 }
Pragya Arya2225f202020-01-29 18:05:01 +0530458 }
459 } else {
460
461 // 1. controlledActivation == Default: Send both PON and ONUs indications
462 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
463
464 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
465 // send PON Port indications
466 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800467 msg := types.Message{
468 Type: types.PonIndication,
469 Data: types.PonIndicationMessage{
470 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530471 PonPortID: pon.ID,
472 },
473 }
474 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700475 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700476 }
477 }
478
Pragya Arya996a0892020-03-09 21:47:52 +0530479 if !o.enablePerf {
480 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700481 wg.Add(1)
482 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530483 }
484
Matteo Scandolo4747d292019-08-05 11:50:18 -0700485 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700486 oltLogger.WithFields(log.Fields{
487 "stream": stream,
488 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700489}
490
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700491func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530492 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700493
494loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530495 for {
496 select {
497 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
498 // send NNI port stats
499 for _, port := range o.Nnis {
500 incrementStat := true
501 if port.OperState.Current() == "down" {
502 incrementStat = false
503 }
504 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700505 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530506 }
507
508 // send PON port stats
509 for _, port := range o.Pons {
510 incrementStat := true
511 // do not increment port stats if PON port is down or no ONU is activated on PON port
512 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
513 incrementStat = false
514 }
515 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700516 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530517 }
518 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700519 oltLogger.Debug("Stop sending port stats")
520 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530521 }
Pragya Arya996a0892020-03-09 21:47:52 +0530522 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700523 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530524}
525
Matteo Scandolo4747d292019-08-05 11:50:18 -0700526// Helpers method
527
Matteo Scandolof9d43412021-01-12 11:11:34 -0800528func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
529
530 switch interfaceType {
531 case "nni":
532 if !o.HasNni(interfaceId) {
533 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
534 }
535
536 case "pon":
537 if !o.HasPon(interfaceId) {
538 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
539 }
540 }
541
542 alarmIndication := &openolt.AlarmIndication{
543 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
544 Status: alarmStatus,
545 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
546 }},
547 }
548
549 msg := types.Message{
550 Type: types.AlarmIndication,
551 Data: alarmIndication,
552 }
553
554 o.channel <- msg
555
556 return nil
557}
558
559func (o *OltDevice) HasNni(id uint32) bool {
560 for _, intf := range o.Nnis {
561 if intf.ID == id {
562 return true
563 }
564 }
565 return false
566}
567
568func (o *OltDevice) HasPon(id uint32) bool {
569 for _, intf := range o.Pons {
570 if intf.ID == id {
571 return true
572 }
573 }
574 return false
575}
576
Shrey Baid688b4242020-07-10 20:40:10 +0530577func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700578 for _, pon := range o.Pons {
579 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700580 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700581 }
582 }
Shrey Baid688b4242020-07-10 20:40:10 +0530583 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700584}
585
Shrey Baid688b4242020-07-10 20:40:10 +0530586func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700587 for _, nni := range o.Nnis {
588 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700589 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700590 }
591 }
Shrey Baid688b4242020-07-10 20:40:10 +0530592 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700593}
594
Scott Baker41724b82020-01-21 19:54:53 -0800595func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
596 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
597 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
598 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
599 return
600 }
601
602 oltLogger.WithFields(log.Fields{
603 "AlarmIndication": alarmInd,
604 }).Debug("Sent Indication_AlarmInd")
605}
606
Matteo Scandolof9d43412021-01-12 11:11:34 -0800607func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700608 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
609 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700610 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800611 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612 }
613
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700614 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700615 "OperState": msg.OperState,
616 }).Debug("Sent Indication_OltInd")
617}
618
Matteo Scandolof9d43412021-01-12 11:11:34 -0800619func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700620 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800621 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800622 if err := nni.OperState.Event("enable"); err != nil {
623 log.WithFields(log.Fields{
624 "Type": nni.Type,
625 "IntfId": nni.ID,
626 "OperState": nni.OperState.Current(),
627 }).Errorf("Can't move NNI Port to enabled state: %v", err)
628 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800629 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800630 if err := nni.OperState.Event("disable"); err != nil {
631 log.WithFields(log.Fields{
632 "Type": nni.Type,
633 "IntfId": nni.ID,
634 "OperState": nni.OperState.Current(),
635 }).Errorf("Can't move NNI Port to disable state: %v", err)
636 }
637 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700638 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700639 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700640 Type: nni.Type,
641 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700642 OperState: nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100643 Speed: o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 }}
645
646 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700647 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800648 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700649 }
650
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700651 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700652 "Type": nni.Type,
653 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700654 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100655 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700656 }).Debug("Sent Indication_IntfOperInd for NNI")
657}
658
Pragya Arya2225f202020-01-29 18:05:01 +0530659func (o *OltDevice) sendPonIndication(ponPortID uint32) {
660
Matteo Scandolo4a036262020-08-17 15:56:13 -0700661 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530662 pon, _ := o.GetPonById(ponPortID)
663 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700665 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700666 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700667 }}
668
669 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700670 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800671 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700672 }
673
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700674 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700675 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700676 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700677 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700678
Pragya Arya2225f202020-01-29 18:05:01 +0530679 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700680 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700681 Type: pon.Type,
682 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700683 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700684 }}
685
686 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700687 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800688 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700689 }
690
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700691 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700692 "Type": pon.Type,
693 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700694 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700695 }).Debug("Sent Indication_IntfOperInd for PON")
696}
697
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700698func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530699 if o.InternalState.Current() == "enabled" {
700 oltLogger.WithFields(log.Fields{
701 "Type": portType,
702 "IntfId": portID,
703 }).Trace("Sending port stats")
704 stats.IntfId = InterfaceIDToPortNo(portID, portType)
705 data := &openolt.Indication_PortStats{
706 PortStats: stats,
707 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700708
Shrey Baid55f328c2020-07-07 19:20:42 +0530709 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
710 oltLogger.Errorf("Failed to send PortStats: %v", err)
711 return
712 }
Pragya Arya996a0892020-03-09 21:47:52 +0530713 }
714}
715
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100716// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700717func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
718 oltLogger.WithFields(log.Fields{
719 "stream": stream,
720 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000721 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700722
David Bainbridge103cf022019-12-16 20:11:35 +0000723loop:
724 for {
725 select {
726 case <-ctx.Done():
727 oltLogger.Debug("OLT Indication processing canceled via context")
728 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700729 // do not terminate this loop if the stream is closed,
730 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
731 //case <-stream.Context().Done():
732 // oltLogger.Debug("OLT Indication processing canceled via stream context")
733 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000734 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700735 if !ok {
736 if ctx.Err() != nil {
737 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
738 }
739 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000740 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700741 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700742
David Bainbridge103cf022019-12-16 20:11:35 +0000743 oltLogger.WithFields(log.Fields{
744 "oltId": o.ID,
745 "messageType": message.Type,
746 }).Trace("Received message")
747
748 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800749 case types.OltIndication:
750 msg, _ := message.Data.(types.OltIndicationMessage)
751 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530752 _ = o.InternalState.Event("enable")
753 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800754 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530755 _ = o.InternalState.Event("disable")
756 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000757 }
758 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800759 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800760 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
761 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800762 case types.NniIndication:
763 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000764 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800765 case types.PonIndication:
766 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530767 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800768 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530769 if err := pon.OperState.Event("enable"); err != nil {
770 oltLogger.WithFields(log.Fields{
771 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800772 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530773 }).Error("Can't Enable Oper state for PON Port")
774 }
775 if err := pon.InternalState.Event("enable"); err != nil {
776 oltLogger.WithFields(log.Fields{
777 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800778 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530779 }).Error("Can't Enable Internal state for PON Port")
780 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800781 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530782 if err := pon.OperState.Event("disable"); err != nil {
783 oltLogger.WithFields(log.Fields{
784 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800785 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530786 }).Error("Can't Disable Oper state for PON Port")
787 }
788 if err := pon.InternalState.Event("disable"); err != nil {
789 oltLogger.WithFields(log.Fields{
790 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800791 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530792 }).Error("Can't Disable Internal state for PON Port")
793 }
Pragya Arya2225f202020-01-29 18:05:01 +0530794 }
David Bainbridge103cf022019-12-16 20:11:35 +0000795 default:
796 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
797 }
798 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700799 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100800 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700801 oltLogger.WithFields(log.Fields{
802 "stream": stream,
803 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700804}
805
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700806// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530807func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700808 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700809 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700810 for _, pon := range o.Pons {
811 for _, onu := range pon.Onus {
812 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700813 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700814 }
815 }
816 }
817
Shrey Baid688b4242020-07-10 20:40:10 +0530818 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700819}
820
William Kurkian9dadc5b2019-10-22 13:51:57 -0400821// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530822func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700823 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400824 // memoizing it will remove the bottleneck
825 for _, pon := range o.Pons {
826 if pon.ID == intfId {
827 for _, onu := range pon.Onus {
828 if onu.ID == onuId {
829 return onu, nil
830 }
831 }
832 }
833 }
Shrey Baid688b4242020-07-10 20:40:10 +0530834 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400835}
836
Matteo Scandolo4a036262020-08-17 15:56:13 -0700837// returns a Service with a given Mac Address
838func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700839 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700840 // memoizing it will remove the bottleneck
841 for _, pon := range o.Pons {
842 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700843 s, err := onu.findServiceByMacAddress(mac)
844 if err == nil {
845 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700846 }
847 }
848 }
849
Matteo Scandolo4a036262020-08-17 15:56:13 -0700850 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700851}
852
Matteo Scandolo4747d292019-08-05 11:50:18 -0700853// GRPC Endpoints
854
Shrey Baid688b4242020-07-10 20:40:10 +0530855func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700856
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700857 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800858
Matteo Scandolo8a574812021-05-20 15:18:53 -0700859 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800860 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
861 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
862
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700863 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700864
865 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
866 oltLogger.WithFields(log.Fields{
867 "OnuSn": _onu.Sn(),
868 }).Info("Received ActivateOnu call from VOLTHA")
869
William Kurkian0418bc82019-11-06 12:16:24 -0500870 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700871
Matteo Scandolocedde462021-03-09 17:37:16 -0800872 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700873 oltLogger.WithFields(log.Fields{
874 "IntfId": _onu.PonPortID,
875 "OnuSn": _onu.Sn(),
876 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800877 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700878 }
879
880 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
881
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700882 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700883}
884
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800885func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700886 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700887 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700888}
889
Shrey Baid688b4242020-07-10 20:40:10 +0530890func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530891 oltLogger.WithFields(log.Fields{
892 "IntfId": onu.IntfId,
893 "OnuId": onu.OnuId,
894 }).Info("Received DeleteOnu call from VOLTHA")
895
896 pon, err := o.GetPonById(onu.IntfId)
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 PonPort")
903 }
904 _onu, err := pon.GetOnuById(onu.OnuId)
905 if err != nil {
906 oltLogger.WithFields(log.Fields{
907 "OnuId": onu.OnuId,
908 "IntfId": onu.IntfId,
909 "err": err,
910 }).Error("Can't find Onu")
911 }
912
Matteo Scandolocedde462021-03-09 17:37:16 -0800913 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530914 oltLogger.WithFields(log.Fields{
915 "IntfId": _onu.PonPortID,
916 "OnuSn": _onu.Sn(),
917 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800918 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530919 }
920
Hardik Windlassad790cb2020-06-17 21:26:22 +0530921 // ONU Re-Discovery
922 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530923 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530924 }
925
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700926 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700927}
928
Shrey Baid688b4242020-07-10 20:40:10 +0530929func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700930 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800931 oltLogger.WithFields(log.Fields{
932 "oltId": o.ID,
933 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530934 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800935
Matteo Scandolo401503a2019-12-11 14:48:14 -0800936 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530937 if pon.InternalState.Current() == "enabled" {
938 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800939 msg := types.Message{
940 Type: types.PonIndication,
941 Data: types.PonIndicationMessage{
942 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530943 PonPortID: pon.ID,
944 },
945 }
946 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800947 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800948 }
949
Matteo Scandolo401503a2019-12-11 14:48:14 -0800950 // Note that we are not disabling the NNI as the real OLT does not.
951 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800952
953 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800954 oltMsg := types.Message{
955 Type: types.OltIndication,
956 Data: types.OltIndicationMessage{
957 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700958 },
959 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100960 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700961
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700962 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700963}
964
Shrey Baid688b4242020-07-10 20:40:10 +0530965func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530966 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200967 ponID := intf.GetIntfId()
968 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200969
Matteo Scandolof9d43412021-01-12 11:11:34 -0800970 msg := types.Message{
971 Type: types.PonIndication,
972 Data: types.PonIndicationMessage{
973 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200974 PonPortID: ponID,
975 },
976 }
977 o.channel <- msg
978
979 for _, onu := range pon.Onus {
980
Matteo Scandolof9d43412021-01-12 11:11:34 -0800981 onuIndication := types.OnuIndicationMessage{
982 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200983 PonPortID: ponID,
984 OnuID: onu.ID,
985 OnuSN: onu.SerialNumber,
986 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700987 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200988
989 }
990
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700991 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700992}
993
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100994func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700995 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530996 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700997 o.Enable(stream)
998 return nil
999}
1000
Shrey Baid688b4242020-07-10 20:40:10 +05301001func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301002 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301003 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001004 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001005
Matteo Scandolof9d43412021-01-12 11:11:34 -08001006 msg := types.Message{
1007 Type: types.PonIndication,
1008 Data: types.PonIndicationMessage{
1009 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301010 PonPortID: ponID,
1011 },
1012 }
1013 o.channel <- msg
1014
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001015 for _, onu := range pon.Onus {
1016
Matteo Scandolof9d43412021-01-12 11:11:34 -08001017 onuIndication := types.OnuIndicationMessage{
1018 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001019 PonPortID: ponID,
1020 OnuID: onu.ID,
1021 OnuSN: onu.SerialNumber,
1022 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001023 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001024
1025 }
1026
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001027 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001028}
1029
Shrey Baid688b4242020-07-10 20:40:10 +05301030func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001031 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001032 "IntfId": flow.AccessIntfId,
1033 "OnuId": flow.OnuId,
1034 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001035 "InnerVlan": flow.Classifier.IVid,
1036 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001037 "FlowType": flow.FlowType,
1038 "FlowId": flow.FlowId,
1039 "UniID": flow.UniId,
1040 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301041 }).Tracef("OLT receives FlowAdd")
1042
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001043 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301044 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001045 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001046 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301047 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001048
1049 if flow.AccessIntfId == -1 {
1050 oltLogger.WithFields(log.Fields{
1051 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001052 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001053 } else if flow.FlowType == "multicast" {
1054 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001055 "Cookie": flow.Cookie,
1056 "DstPort": flow.Classifier.DstPort,
1057 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1058 "FlowId": flow.FlowId,
1059 "FlowType": flow.FlowType,
1060 "GemportId": flow.GemportId,
1061 "InnerVlan": flow.Classifier.IVid,
1062 "IntfId": flow.AccessIntfId,
1063 "IpProto": flow.Classifier.IpProto,
1064 "OnuId": flow.OnuId,
1065 "OuterVlan": flow.Classifier.OVid,
1066 "PortNo": flow.PortNo,
1067 "SrcPort": flow.Classifier.SrcPort,
1068 "UniID": flow.UniId,
1069 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001070 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001071 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001072 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
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 PonPort")
1079 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001080 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001081 if err != nil {
1082 oltLogger.WithFields(log.Fields{
1083 "OnuId": flow.OnuId,
1084 "IntfId": flow.AccessIntfId,
1085 "err": err,
1086 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001087 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001088 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001089
1090 // if the ONU is disabled reject the flow
1091 // as per VOL-4061 there is a small window during which the ONU is disabled
1092 // but the port has not been reported as down to ONOS
1093 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1094 oltLogger.WithFields(log.Fields{
1095 "OnuId": flow.OnuId,
1096 "IntfId": flow.AccessIntfId,
1097 "Flow": flow,
1098 "SerialNumber": onu.Sn(),
1099 "InternalState": onu.InternalState.Current(),
1100 }).Error("rejected-flow-because-of-onu-state")
1101 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1102 }
1103
Pragya Arya8bdb4532020-03-02 17:08:09 +05301104 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001105 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301106 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001107 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001108 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301109 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301110 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001111
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001112 // validate that the flow reference correct IDs (Alloc, Gem)
1113 if err := o.validateFlow(flow); err != nil {
1114 oltLogger.WithFields(log.Fields{
1115 "OnuId": flow.OnuId,
1116 "IntfId": flow.AccessIntfId,
1117 "Flow": flow,
1118 "SerialNumber": onu.Sn(),
1119 "err": err,
1120 }).Error("invalid-flow-for-onu")
1121 return nil, err
1122 }
1123
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001124 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001125 o.storeAllocId(flow)
1126
Matteo Scandolof9d43412021-01-12 11:11:34 -08001127 msg := types.Message{
1128 Type: types.FlowAdd,
1129 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001130 PonPortID: pon.ID,
1131 OnuID: onu.ID,
1132 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001133 },
1134 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001135 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001136 }
1137
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001138 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001139}
1140
Pragya Arya8bdb4532020-03-02 17:08:09 +05301141// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301142func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001143
Pragya Arya8bdb4532020-03-02 17:08:09 +05301144 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001145 "AllocId": flow.AllocId,
1146 "Cookie": flow.Cookie,
1147 "FlowId": flow.FlowId,
1148 "FlowType": flow.FlowType,
1149 "GemportId": flow.GemportId,
1150 "IntfId": flow.AccessIntfId,
1151 "OnuId": flow.OnuId,
1152 "PortNo": flow.PortNo,
1153 "UniID": flow.UniId,
1154 "ReplicateFlow": flow.ReplicateFlow,
1155 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001156 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301157
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001158 olt.freeGemPortId(flow)
1159 olt.freeAllocId(flow)
1160
Pragya Arya8bdb4532020-03-02 17:08:09 +05301161 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001162 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301163 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001164 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301165 if !ok {
1166 oltLogger.Errorf("Flow %v not found", flow)
1167 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1168 }
1169
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001170 storedFlow := storedFlowIntf.(openolt.Flow)
1171
Pragya Arya8bdb4532020-03-02 17:08:09 +05301172 // if its ONU flow remove it from ONU also
1173 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001174 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1175 if err != nil {
1176 oltLogger.WithFields(log.Fields{
1177 "OnuId": storedFlow.OnuId,
1178 "IntfId": storedFlow.AccessIntfId,
1179 "PONs": olt.Pons,
1180 "err": err,
1181 }).Error("PON-port-not-found")
1182 return new(openolt.Empty), nil
1183 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301184 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1185 if err != nil {
1186 oltLogger.WithFields(log.Fields{
1187 "OnuId": storedFlow.OnuId,
1188 "IntfId": storedFlow.AccessIntfId,
1189 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001190 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301191 return new(openolt.Empty), nil
1192 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001193 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001194 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301195 }
1196
1197 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001198 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301199 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001200
1201 if flow.AccessIntfId == -1 {
1202 oltLogger.WithFields(log.Fields{
1203 "FlowId": flow.FlowId,
1204 }).Debug("Removing OLT flow")
1205 } else if flow.FlowType == "multicast" {
1206 oltLogger.WithFields(log.Fields{
1207 "FlowId": flow.FlowId,
1208 }).Debug("Removing OLT multicast flow")
1209 } else {
1210
1211 onu, err := o.GetOnuByFlowId(flow.FlowId)
1212 if err != nil {
1213 oltLogger.WithFields(log.Fields{
1214 "OnuId": flow.OnuId,
1215 "IntfId": flow.AccessIntfId,
1216 "err": err,
1217 }).Error("Can't find Onu")
1218 return nil, err
1219 }
1220
Matteo Scandolof9d43412021-01-12 11:11:34 -08001221 msg := types.Message{
1222 Type: types.FlowRemoved,
1223 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301224 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001225 },
1226 }
1227 onu.Channel <- msg
1228 }
1229
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001230 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001231}
1232
Shrey Baid688b4242020-07-10 20:40:10 +05301233func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001234 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1235 oltLogger.WithFields(log.Fields{
1236 "signature": res.HeartbeatSignature,
1237 }).Trace("HeartbeatCheck")
1238 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001239}
1240
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001241func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001242 for _, pon := range o.Pons {
1243 for _, onu := range pon.Onus {
1244 for _, fId := range onu.FlowIds {
1245 if fId == flowId {
1246 return onu, nil
1247 }
1248 }
1249 }
1250 }
Shrey Baid688b4242020-07-10 20:40:10 +05301251 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001252}
1253
Shrey Baid688b4242020-07-10 20:40:10 +05301254func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001255
Matteo Scandolocedde462021-03-09 17:37:16 -08001256 intfIDs := []uint32{}
1257 for i := 0; i < o.NumPon; i++ {
1258 intfIDs = append(intfIDs, uint32(i))
1259 }
1260
1261 devinfo := &openolt.DeviceInfo{
1262 Vendor: common.Config.Olt.Vendor,
1263 Model: common.Config.Olt.Model,
1264 HardwareVersion: common.Config.Olt.HardwareVersion,
1265 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1266 Technology: common.Config.Olt.Technology,
1267 PonPorts: uint32(o.NumPon),
1268 OnuIdStart: onuIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001269 OnuIdEnd: o.onuIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001270 AllocIdStart: allocIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001271 AllocIdEnd: o.allocIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001272 GemportIdStart: gemportIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001273 GemportIdEnd: o.gemportIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001274 FlowIdStart: flowIdStart,
1275 FlowIdEnd: flowIdEnd,
1276 DeviceSerialNumber: o.SerialNumber,
1277 DeviceId: common.Config.Olt.DeviceId,
1278 PreviouslyConnected: o.PreviouslyConnected,
1279 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1280 {
1281 IntfIds: intfIDs,
1282 Technology: common.Config.Olt.Technology,
1283 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1284 {
1285 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1286 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1287 Start: onuIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001288 End: o.onuIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001289 },
1290 {
1291 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1292 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1293 Start: allocIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001294 End: o.allocIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001295 },
1296 {
1297 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1298 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1299 Start: gemportIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001300 End: o.gemportIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001301 },
1302 {
1303 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1304 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1305 Start: flowIdStart,
1306 End: flowIdEnd,
1307 },
1308 },
1309 },
1310 },
1311 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001312
1313 oltLogger.WithFields(log.Fields{
1314 "Vendor": devinfo.Vendor,
1315 "Model": devinfo.Model,
1316 "HardwareVersion": devinfo.HardwareVersion,
1317 "FirmwareVersion": devinfo.FirmwareVersion,
1318 "Technology": devinfo.Technology,
1319 "PonPorts": devinfo.PonPorts,
1320 "OnuIdStart": devinfo.OnuIdStart,
1321 "OnuIdEnd": devinfo.OnuIdEnd,
1322 "AllocIdStart": devinfo.AllocIdStart,
1323 "AllocIdEnd": devinfo.AllocIdEnd,
1324 "GemportIdStart": devinfo.GemportIdStart,
1325 "GemportIdEnd": devinfo.GemportIdEnd,
1326 "FlowIdStart": devinfo.FlowIdStart,
1327 "FlowIdEnd": devinfo.FlowIdEnd,
1328 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1329 "DeviceId": devinfo.DeviceId,
1330 "PreviouslyConnected": devinfo.PreviouslyConnected,
1331 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1332
1333 // once we connect, set the flag
1334 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001335
1336 return devinfo, nil
1337}
1338
Shrey Baid688b4242020-07-10 20:40:10 +05301339func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001340 pon, err := o.GetPonById(omci_msg.IntfId)
1341 if err != nil {
1342 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001343 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001344 "onu_id": omci_msg.OnuId,
1345 "pon_id": omci_msg.IntfId,
1346 }).Error("pon ID not found")
1347 return nil, err
1348 }
1349
1350 onu, err := pon.GetOnuById(omci_msg.OnuId)
1351 if err != nil {
1352 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001353 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001354 "onu_id": omci_msg.OnuId,
1355 "pon_id": omci_msg.IntfId,
1356 }).Error("onu ID not found")
1357 return nil, err
1358 }
1359
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001360 oltLogger.WithFields(log.Fields{
1361 "IntfId": onu.PonPortID,
1362 "OnuId": onu.ID,
1363 "OnuSn": onu.Sn(),
1364 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001365 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1366 if err != nil {
1367 log.WithFields(log.Fields{
1368 "IntfId": onu.PonPortID,
1369 "SerialNumber": onu.Sn(),
1370 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1371 "err": err.Error(),
1372 }).Error("cannot-parse-OMCI-packet")
1373 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001374 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001375 if onu.InternalState.Current() == OnuStateDisabled {
1376 // if the ONU is disabled just drop the message
1377 log.WithFields(log.Fields{
1378 "IntfId": onu.PonPortID,
1379 "SerialNumber": onu.Sn(),
1380 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1381 "omciPkt": omciPkt,
1382 "omciMsgType": omciMsg.MessageType,
1383 }).Warn("dropping-omci-message")
1384 } else {
1385 msg := types.Message{
1386 Type: types.OMCI,
1387 Data: types.OmciMessage{
1388 OnuSN: onu.SerialNumber,
1389 OnuID: onu.ID,
1390 OmciMsg: omciMsg,
1391 OmciPkt: omciPkt,
1392 },
1393 }
1394 onu.Channel <- msg
1395 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001396 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001397}
1398
Matteo Scandolo8a574812021-05-20 15:18:53 -07001399// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301400func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001401 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001402 if err != nil {
1403 oltLogger.WithFields(log.Fields{
1404 "OnuId": onuPkt.OnuId,
1405 "IntfId": onuPkt.IntfId,
1406 "err": err,
1407 }).Error("Can't find PonPort")
1408 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001409 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001410 if err != nil {
1411 oltLogger.WithFields(log.Fields{
1412 "OnuId": onuPkt.OnuId,
1413 "IntfId": onuPkt.IntfId,
1414 "err": err,
1415 }).Error("Can't find Onu")
1416 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001417
Matteo Scandolo075b1892019-10-07 12:11:07 -07001418 oltLogger.WithFields(log.Fields{
1419 "IntfId": onu.PonPortID,
1420 "OnuId": onu.ID,
1421 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001422 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001423 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001424
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001425 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001426
1427 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001428 if err != nil {
1429 onuLogger.WithFields(log.Fields{
1430 "IntfId": onu.PonPortID,
1431 "OnuId": onu.ID,
1432 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001433 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001434 }).Error("Can't find pktType in packet, droppint it")
1435 return new(openolt.Empty), nil
1436 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001437
Matteo Scandolo4a036262020-08-17 15:56:13 -07001438 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001439 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001440 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001441 "IntfId": onu.PonPortID,
1442 "OnuId": onu.ID,
1443 "OnuSn": onu.Sn(),
1444 "Pkt": rawpkt.Data(),
1445 }).Error("Can't find Dst MacAddress in packet, droppint it")
1446 return new(openolt.Empty), nil
1447 }
1448
Matteo Scandolof9d43412021-01-12 11:11:34 -08001449 msg := types.Message{
1450 Type: types.OnuPacketOut,
1451 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001452 IntfId: onuPkt.IntfId,
1453 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001454 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001455 Packet: rawpkt,
1456 Type: pktType,
1457 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001458 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001459 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001460
Matteo Scandolo075b1892019-10-07 12:11:07 -07001461 onu.Channel <- msg
1462
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001463 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001464}
1465
Shrey Baid688b4242020-07-10 20:40:10 +05301466func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001467
1468 // OLT Reboot is called in two cases:
1469 // - 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)
1470 // - when an OLT needs to be rebooted (voltcl device reboot)
1471
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001472 oltLogger.WithFields(log.Fields{
1473 "oltId": o.ID,
1474 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301475 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301476 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001477 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001478}
1479
Shrey Baid688b4242020-07-10 20:40:10 +05301480func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301481 oltLogger.WithFields(log.Fields{
1482 "oltId": o.ID,
1483 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301484 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301485
Pragya Arya2225f202020-01-29 18:05:01 +05301486 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001487 oltMsg := types.Message{
1488 Type: types.OltIndication,
1489 Data: types.OltIndicationMessage{
1490 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301491 },
Pragya Arya1881df02020-01-29 18:05:01 +05301492 }
Pragya Arya2225f202020-01-29 18:05:01 +05301493 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301494
Pragya Arya2225f202020-01-29 18:05:01 +05301495 for _, pon := range o.Pons {
1496 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001497 msg := types.Message{
1498 Type: types.PonIndication,
1499 Data: types.PonIndicationMessage{
1500 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301501 PonPortID: pon.ID,
1502 },
1503 }
1504 o.channel <- msg
1505 }
1506 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001507
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001508 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001509}
1510
Shrey Baid688b4242020-07-10 20:40:10 +05301511func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001512 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1513
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001514 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1515
1516 if err != nil {
1517 return nil, err
1518 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001519 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001520}
1521
Shrey Baid688b4242020-07-10 20:40:10 +05301522func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001523 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001524 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001525}
1526
Shrey Baid688b4242020-07-10 20:40:10 +05301527func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001528 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001529 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001530}
1531
Shrey Baid688b4242020-07-10 20:40:10 +05301532func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001533 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001534 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001535}
1536
Shrey Baid688b4242020-07-10 20:40:10 +05301537func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001538 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001539 return new(openolt.Empty), nil
1540}
1541
Matteo Scandolo8a574812021-05-20 15:18:53 -07001542func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1543 oltLogger.WithFields(log.Fields{
1544 "OnuId": tq.OnuId,
1545 "IntfId": tq.IntfId,
1546 "OnuPortNo": tq.PortNo,
1547 "UniId": tq.UniId,
1548 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001549 return new(openolt.Empty), nil
1550}
1551
Matteo Scandolo8a574812021-05-20 15:18:53 -07001552func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301553 oltLogger.WithFields(log.Fields{
1554 "OnuId": trafficSchedulers.OnuId,
1555 "IntfId": trafficSchedulers.IntfId,
1556 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001557 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301558 }).Info("received CreateTrafficSchedulers")
1559
1560 if !s.enablePerf {
1561 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1562 if err != nil {
1563 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1564 return new(openolt.Empty), err
1565 }
1566 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1567 if err != nil {
1568 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1569 return new(openolt.Empty), err
1570 }
1571 onu.TrafficSchedulers = trafficSchedulers
1572 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001573 return new(openolt.Empty), nil
1574}
1575
Shrey Baid688b4242020-07-10 20:40:10 +05301576func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301577 oltLogger.WithFields(log.Fields{
1578 "OnuId": trafficSchedulers.OnuId,
1579 "IntfId": trafficSchedulers.IntfId,
1580 "OnuPortNo": trafficSchedulers.PortNo,
1581 }).Info("received RemoveTrafficSchedulers")
1582 if !s.enablePerf {
1583 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1584 if err != nil {
1585 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1586 return new(openolt.Empty), err
1587 }
1588 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1589 if err != nil {
1590 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1591 return new(openolt.Empty), err
1592 }
1593
1594 onu.TrafficSchedulers = nil
1595 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001596 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001597}
Scott Baker41724b82020-01-21 19:54:53 -08001598
Matteo Scandolo618a6582020-09-09 12:21:29 -07001599func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1600 oltLogger.WithFields(log.Fields{
1601 "GroupId": group.GroupId,
1602 "Command": group.Command,
1603 "Members": group.Members,
1604 "Action": group.Action,
1605 }).Debug("received PerformGroupOperation")
1606 return &openolt.Empty{}, nil
1607}
1608
1609func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1610 oltLogger.WithFields(log.Fields{
1611 "GroupId": group.GroupId,
1612 "Command": group.Command,
1613 "Members": group.Members,
1614 "Action": group.Action,
1615 }).Debug("received PerformGroupOperation")
1616 return &openolt.Empty{}, nil
1617}
1618
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001619func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1620 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001621}
1622
1623func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1624 return &openolt.Empty{}, nil
1625}
1626
1627func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1628 return &openolt.OnuLogicalDistance{}, nil
1629}
1630
1631func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1632 return &openolt.OnuLogicalDistance{}, nil
1633}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001634
Girish Gowdra62f24292021-05-12 16:28:39 -07001635func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1636 return &openolt.PonRxPowerData{}, nil
1637}
1638
Matteo Scandolo96f89192021-03-12 13:17:26 -08001639func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1640 return &openolt.GemPortStatistics{}, nil
1641}
1642
1643func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1644 return &openolt.OnuStatistics{}, nil
1645}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001646
1647func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1648 o.AllocIDsLock.Lock()
1649 defer o.AllocIDsLock.Unlock()
1650
Matteo Scandolo21195d62021-04-07 14:31:23 -07001651 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1652 oltLogger.WithFields(log.Fields{
1653 "IntfId": flow.AccessIntfId,
1654 "OnuId": flow.OnuId,
1655 "PortNo": flow.PortNo,
1656 "GemportId": flow.GemportId,
1657 "FlowId": flow.FlowId,
1658 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1659 }
1660
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001661 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001662 "IntfId": flow.AccessIntfId,
1663 "OnuId": flow.OnuId,
1664 "PortNo": flow.PortNo,
1665 "GemportId": flow.GemportId,
1666 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001667 }).Trace("storing-alloc-id-via-flow")
1668
1669 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1670 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1671 }
1672 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1673 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1674 }
1675 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1676}
1677
1678func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1679 // if this is the last flow referencing the AllocId then remove it
1680 o.AllocIDsLock.Lock()
1681 defer o.AllocIDsLock.Unlock()
1682
1683 oltLogger.WithFields(log.Fields{
1684 "IntfId": flow.AccessIntfId,
1685 "OnuId": flow.OnuId,
1686 "PortNo": flow.PortNo,
1687 "GemportId": flow.GemportId,
1688 }).Trace("freeing-alloc-id-via-flow")
1689
1690 // NOTE look at the freeGemPortId implementation for comments and context
1691 for ponId, ponValues := range o.AllocIDs {
1692 for onuId, onuValues := range ponValues {
1693 for uniId, uniValues := range onuValues {
1694 for allocId, flows := range uniValues {
1695 for flowId := range flows {
1696 // if the flow matches, remove it from the map.
1697 if flow.FlowId == flowId {
1698 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1699 }
1700 // if that was the last flow for a particular allocId, remove the entire allocId
1701 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1702 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1703 }
1704 }
1705 }
1706 }
1707 }
1708 }
1709}
1710
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001711func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001712 o.GemPortIDsLock.Lock()
1713 defer o.GemPortIDsLock.Unlock()
1714
1715 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1716 oltLogger.WithFields(log.Fields{
1717 "IntfId": ponId,
1718 "OnuId": onuId,
1719 "PortNo": portNo,
1720 "GemportId": gemId,
1721 "FlowId": flowId,
1722 }).Error("trying-to-store-gemport-for-unknown-onu")
1723 }
1724
1725 oltLogger.WithFields(log.Fields{
1726 "IntfId": ponId,
1727 "OnuId": onuId,
1728 "PortNo": portNo,
1729 "GemportId": gemId,
1730 "FlowId": flowId,
1731 }).Trace("storing-alloc-id-via-flow")
1732
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001733 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1734 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1735 }
1736 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1737 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1738 }
1739 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1740}
1741
1742func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001743 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001744 "IntfId": flow.AccessIntfId,
1745 "OnuId": flow.OnuId,
1746 "PortNo": flow.PortNo,
1747 "GemportId": flow.GemportId,
1748 "FlowId": flow.FlowId,
1749 "ReplicateFlow": flow.ReplicateFlow,
1750 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001751 }).Trace("storing-gem-port-id-via-flow")
1752
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001753 if flow.ReplicateFlow {
1754 for _, gem := range flow.PbitToGemport {
1755 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1756 }
1757 } else {
1758 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001759 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001760}
1761
1762func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1763 // if this is the last flow referencing the GemPort then remove it
1764 o.GemPortIDsLock.Lock()
1765 defer o.GemPortIDsLock.Unlock()
1766
1767 oltLogger.WithFields(log.Fields{
1768 "IntfId": flow.AccessIntfId,
1769 "OnuId": flow.OnuId,
1770 "PortNo": flow.PortNo,
1771 "GemportId": flow.GemportId,
1772 }).Trace("freeing-gem-port-id-via-flow")
1773
1774 // NOTE that this loop is not very performant, it would be better if the flow carries
1775 // the same information that it carries during a FlowAdd. If so we can directly remove
1776 // items from the map
1777
1778 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1779 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1780 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1781 //}
1782
1783 // NOTE this loop assumes that flow IDs are unique per device
1784 for ponId, ponValues := range o.GemPortIDs {
1785 for onuId, onuValues := range ponValues {
1786 for uniId, uniValues := range onuValues {
1787 for gemId, flows := range uniValues {
1788 for flowId := range flows {
1789 // if the flow matches, remove it from the map.
1790 if flow.FlowId == flowId {
1791 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1792 }
1793 // if that was the last flow for a particular gem, remove the entire gem
1794 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1795 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1796 }
1797 }
1798 }
1799 }
1800 }
1801 }
1802}
1803
1804// validateFlow checks that:
1805// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1806// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1807func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001808 // validate gemPort
1809 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001810 defer o.GemPortIDsLock.RUnlock()
1811 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001812 if onuId == uint32(flow.OnuId) {
1813 continue
1814 }
1815 for uniId, uni := range onu {
1816 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001817 if flow.ReplicateFlow {
1818 for _, flowGem := range flow.PbitToGemport {
1819 if gem == int32(flowGem) {
1820 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1821 }
1822 }
1823 } else {
1824 if gem == flow.GemportId {
1825 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1826 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001827 }
1828 }
1829 }
1830 }
1831
1832 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001833 defer o.AllocIDsLock.RUnlock()
1834 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001835 if onuId == uint32(flow.OnuId) {
1836 continue
1837 }
1838 for uniId, uni := range onu {
1839 for allocId := range uni {
1840 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001841 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 -08001842 }
1843 }
1844 }
1845 }
1846
1847 return nil
1848}
1849
1850// clearAllResources is invoked up OLT Reboot to remove all the allocated
1851// GemPorts, AllocId and ONU-IDs across the PONs
1852func (o *OltDevice) clearAllResources() {
1853
1854 // remove the resources received via flows
1855 o.GemPortIDsLock.Lock()
1856 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1857 o.GemPortIDsLock.Unlock()
1858 o.AllocIDsLock.Lock()
1859 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1860 o.AllocIDsLock.Unlock()
1861
1862 // remove the resources received via OMCI
1863 for _, pon := range o.Pons {
1864 pon.removeAllAllocIds()
1865 pon.removeAllGemPorts()
1866 pon.removeAllOnuIds()
1867 }
1868}