blob: 0a50d5966818fddb9e43e5b31620473d4f0c5660 [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
Elia Battiston67e9e4c2022-02-15 16:38:40 +010061
62 //InternalState FSM states and transitions
63 OltInternalStateCreated = "created"
64 OltInternalStateInitialized = "initialized"
65 OltInternalStateEnabled = "enabled"
66 OltInternalStateDisabled = "disabled"
67 OltInternalStateDeleted = "deleted"
68
69 OltInternalTxInitialize = "initialize"
70 OltInternalTxEnable = "enable"
71 OltInternalTxDisable = "disable"
72 OltInternalTxDelete = "delete"
Matteo Scandolocedde462021-03-09 17:37:16 -080073)
74
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070075type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000076 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000077 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000078
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070079 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053080 ID int
81 SerialNumber string
82 NumNni int
Elia Battiston420c9092022-02-02 12:17:54 +010083 NniSpeed uint32
Pragya Arya2225f202020-01-29 18:05:01 +053084 NumPon int
85 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070086 NumUni int
Elia Battistonac63b112022-01-12 18:40:49 +010087 NumPots int
Pragya Arya2225f202020-01-29 18:05:01 +053088 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080089 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070090 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010091 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053092 Delay int
93 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053094 EventChannel chan common.Event
95 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053096 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080097 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070098
Matteo Scandolo27428702019-10-11 16:21:16 -070099 Pons []*PonPort
100 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700101
102 // OLT Attributes
103 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +0000104
105 enableContext context.Context
106 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +0530107
Matteo Scandolo4a036262020-08-17 15:56:13 -0700108 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +0530109 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800110
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800111 // resource ranges (only the ones that depends on the topology size)
112 onuIdEnd uint32
113 allocIdPerOnu uint32
114 allocIdEnd uint32
115 gemportIdEnd uint32
116
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800117 // Allocated Resources
118 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000119 AllocIDsLock sync.RWMutex
120 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
121 GemPortIDsLock sync.RWMutex
122 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
123 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700124}
125
Matteo Scandolo27428702019-10-11 16:21:16 -0700126var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700127
Matteo Scandolo27428702019-10-11 16:21:16 -0700128func GetOLT() *OltDevice {
129 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700130}
131
Matteo Scandolo4a036262020-08-17 15:56:13 -0700132func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700133 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530134 "ID": options.Olt.ID,
135 "NumNni": options.Olt.NniPorts,
Elia Battiston420c9092022-02-02 12:17:54 +0100136 "NniSpeed": options.Olt.NniSpeed,
Pragya Arya996a0892020-03-09 21:47:52 +0530137 "NumPon": options.Olt.PonPorts,
138 "NumOnuPerPon": options.Olt.OnusPonPort,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700139 "NumUni": options.Olt.UniPorts,
Elia Battistonac63b112022-01-12 18:40:49 +0100140 "NumPots": options.Olt.PotsPorts,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700141 }).Debug("CreateOLT")
142
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700143 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530144 ID: options.Olt.ID,
145 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700146 OperState: getOperStateFSM(func(e *fsm.Event) {
147 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
148 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800149 NumNni: int(options.Olt.NniPorts),
Elia Battiston420c9092022-02-02 12:17:54 +0100150 NniSpeed: options.Olt.NniSpeed,
Matteo Scandolo96f89192021-03-12 13:17:26 -0800151 NumPon: int(options.Olt.PonPorts),
152 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700153 NumUni: int(options.Olt.UniPorts),
Elia Battistonac63b112022-01-12 18:40:49 +0100154 NumPots: int(options.Olt.PotsPorts),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800155 Pons: []*PonPort{},
156 Nnis: []*NniPort{},
157 Delay: options.BBSim.Delay,
158 enablePerf: options.BBSim.EnablePerf,
159 PublishEvents: options.BBSim.Events,
160 PortStatsInterval: options.Olt.PortStatsInterval,
161 dhcpServer: dhcp.NewDHCPServer(),
162 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800163 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
164 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000165 OmciResponseRate: options.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700166 }
167
Matteo Scandolo52d12e32022-02-02 15:30:20 -0800168 // create the resource ranges based on the configuration
169 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
170 olt.allocIdPerOnu = uint32(olt.NumUni * len(common.Services)) // 1 allocId per Service * UNI
171 olt.allocIdEnd = allocIdStart + (options.Olt.OnusPonPort * olt.allocIdPerOnu) // 1 allocId per Service * UNI * ONU
172 olt.gemportIdEnd = gemportIdStart + (options.Olt.OnusPonPort * olt.allocIdPerOnu * gemPortIdPerAllocId) // up to 8 gemport-id per tcont/alloc-id
173
Pragya Arya996a0892020-03-09 21:47:52 +0530174 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530175 olt.ControlledActivation = val
176 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700177 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530178 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
179 olt.ControlledActivation = Default
180 }
181
Matteo Scandolo4747d292019-08-05 11:50:18 -0700182 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700183 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700184 olt.InternalState = fsm.NewFSM(
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100185 OltInternalStateCreated,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700186 fsm.Events{
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100187 {Name: OltInternalTxInitialize, Src: []string{OltInternalStateCreated, OltInternalStateDeleted}, Dst: OltInternalStateInitialized},
188 {Name: OltInternalTxEnable, Src: []string{OltInternalStateInitialized, OltInternalStateDisabled}, Dst: OltInternalStateEnabled},
189 {Name: OltInternalTxDisable, Src: []string{OltInternalStateEnabled}, Dst: OltInternalStateDisabled},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700190 // delete event in enabled state below is for reboot OLT case.
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100191 {Name: OltInternalTxDelete, Src: []string{OltInternalStateDisabled, OltInternalStateEnabled}, Dst: OltInternalStateDeleted},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700192 },
193 fsm.Callbacks{
194 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700195 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700196 },
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100197 fmt.Sprintf("enter_%s", OltInternalStateInitialized): func(e *fsm.Event) { olt.InitOlt() },
198 fmt.Sprintf("enter_%s", OltInternalStateDeleted): func(e *fsm.Event) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800199 // remove all the resource allocations
200 olt.clearAllResources()
201 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700202 },
203 )
204
Shrey Baid688b4242020-07-10 20:40:10 +0530205 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700206 // create NNI Port
207 nniPort, err := CreateNNI(&olt)
208 if err != nil {
209 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
210 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700211
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700212 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700213 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700214
Matteo Scandolo4a036262020-08-17 15:56:13 -0700215 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700216 nextCtag := map[string]int{}
217 nextStag := map[string]int{}
218
Matteo Scandolo4747d292019-08-05 11:50:18 -0700219 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700220 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800221
222 // initialize the resource maps for every PON Ports
223 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
224 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
225
Matteo Scandolo4a036262020-08-17 15:56:13 -0700226 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700227
Matteo Scandolo4a036262020-08-17 15:56:13 -0700228 // create ONU devices
229 for j := 0; j < olt.NumOnuPerPon; j++ {
230 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700231 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700232
Matteo Scandolo4a036262020-08-17 15:56:13 -0700233 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700234 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700235 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700236 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100237
Shrey Baid688b4242020-07-10 20:40:10 +0530238 if !isMock {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100239 if err := olt.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700240 log.Errorf("Error initializing OLT: %v", err)
241 return nil
242 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243 }
244
Pragya Arya324337e2020-02-20 14:35:08 +0530245 if olt.PublishEvents {
246 log.Debugf("BBSim event publishing is enabled")
247 // Create a channel to write event messages
248 olt.EventChannel = make(chan common.Event, 100)
249 }
250
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700251 return &olt
252}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700253
Shrey Baid688b4242020-07-10 20:40:10 +0530254func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100255
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000256 if o.OltServer == nil {
257 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100258 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800259 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100260 }
261
262 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800263 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100264
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100265 // FIXME we are assuming we have only one NNI
266 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800267 // NOTE we want to make sure the state is down when we initialize the OLT,
268 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
269 // in-band management
270 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100271 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800272
273 for ponId := range o.Pons {
274 // initialize the resource maps for every PON Ports
275 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
276 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
277 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700278}
279
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800280func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100281
Matteo Scandolo96f89192021-03-12 13:17:26 -0800282 o.PreviouslyConnected = false
283
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700284 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700285 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800286
287 oltLogger.WithFields(log.Fields{
288 "oltId": o.ID,
289 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
290
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100291 if o.InternalState.Is(OltInternalStateEnabled) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700292 oltLogger.WithFields(log.Fields{
293 "oltId": o.ID,
294 }).Info("This is an OLT soft reboot")
295 softReboot = true
296 }
297
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800298 // transition internal state to deleted
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100299 if err := o.InternalState.Event(OltInternalTxDelete); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800300 oltLogger.WithFields(log.Fields{
301 "oltId": o.ID,
302 }).Errorf("Error deleting OLT: %v", err)
303 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100304 }
305
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700306 if softReboot {
307 for _, pon := range o.Pons {
308 if pon.InternalState.Current() == "enabled" {
309 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800310 msg := types.Message{
311 Type: types.PonIndication,
312 Data: types.PonIndicationMessage{
313 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700314 PonPortID: pon.ID,
315 },
316 }
317 o.channel <- msg
318 }
319
320 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800321 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700322 }
323 }
324 } else {
325 // PONs are already handled in the Disable call
326 for _, pon := range olt.Pons {
327 // ONUs are not automatically disabled when a PON goes down
328 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
329 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800330 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700331 }
Pragya Arya2225f202020-01-29 18:05:01 +0530332 }
333 }
334
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700335 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
336 o.StopOltServer()
337
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100338 // terminate the OLT's processOltMessages go routine
339 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700340
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100341 //Prevents Enable to progress before the reboot is completed (VOL-4616)
342 o.Lock()
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700343 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100344 time.Sleep(time.Duration(rebootDelay) * time.Second)
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100345 o.Unlock()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100346
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100347 if err := o.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800348 oltLogger.WithFields(log.Fields{
349 "oltId": o.ID,
350 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100351 return err
352 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800353 oltLogger.WithFields(log.Fields{
354 "oltId": o.ID,
355 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100356 return nil
357}
358
359// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800360func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700361 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700362 lis, err := net.Listen("tcp", address)
363 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700364 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700365 }
366 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100367
Matteo Scandolo4747d292019-08-05 11:50:18 -0700368 openolt.RegisterOpenoltServer(grpcServer, o)
369
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100370 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700371
Shrey Baid688b4242020-07-10 20:40:10 +0530372 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100373 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700374
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100375 return grpcServer, nil
376}
377
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800378// StartOltServer will create the grpc server that VOLTHA uses
379// to communicate with the device
380func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
381 oltServer, err := o.newOltServer()
382 if err != nil {
383 oltLogger.WithFields(log.Fields{
384 "err": err,
385 }).Error("Cannot OLT gRPC server")
386 return nil, err
387 }
388 return oltServer, nil
389}
390
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100391// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800392func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000393 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800394 oltLogger.WithFields(log.Fields{
395 "oltId": o.SerialNumber,
396 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000397 o.OltServer.Stop()
398 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700399 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700400}
401
402// Device Methods
403
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100404// Enable implements the OpenOLT EnableIndicationServer functionality
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100405func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700406 oltLogger.Debug("Enable OLT called")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100407
408 if o.InternalState.Is(OltInternalStateDeleted) {
409 err := fmt.Errorf("Cannot enable OLT while it is rebooting")
410 oltLogger.WithFields(log.Fields{
411 "oltId": o.SerialNumber,
412 "internalState": o.InternalState.Current(),
413 }).Error(err)
414 return err
415 }
416
Pragya Arya2225f202020-01-29 18:05:01 +0530417 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700418
David Bainbridge103cf022019-12-16 20:11:35 +0000419 // If enabled has already been called then an enabled context has
420 // been created. If this is the case then we want to cancel all the
421 // proessing loops associated with that enable before we recreate
422 // new ones
423 o.Lock()
424 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700425 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000426 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530427 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700428 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000429 }
430 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
431 o.Unlock()
432
Matteo Scandolo4747d292019-08-05 11:50:18 -0700433 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700434
Matteo Scandolo4a036262020-08-17 15:56:13 -0700435 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530436
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100437 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700438 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000439 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700440
441 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800442 oltMsg := types.Message{
443 Type: types.OltIndication,
444 Data: types.OltIndicationMessage{
445 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700446 },
447 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100448 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700449
450 // send NNI Port Indications
451 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800452 msg := types.Message{
453 Type: types.NniIndication,
454 Data: types.NniIndicationMessage{
455 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700456 NniPortID: nni.ID,
457 },
458 }
459 o.channel <- msg
460 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100461
Shrey Baid688b4242020-07-10 20:40:10 +0530462 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530463 for _, pon := range o.Pons {
464 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800465 msg := types.Message{
466 Type: types.PonIndication,
467 Data: types.PonIndicationMessage{
468 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530469 PonPortID: pon.ID,
470 },
471 }
472 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000473 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700474 // when the enableContext was canceled the ONUs stopped listening on the channel
475 for _, onu := range pon.Onus {
476 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
477
478 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700479 for _, uni := range onu.UniPorts {
480 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700481 }
482 }
Pragya Arya2225f202020-01-29 18:05:01 +0530483 }
484 } else {
485
486 // 1. controlledActivation == Default: Send both PON and ONUs indications
487 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
488
489 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
490 // send PON Port indications
491 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800492 msg := types.Message{
493 Type: types.PonIndication,
494 Data: types.PonIndicationMessage{
495 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530496 PonPortID: pon.ID,
497 },
498 }
499 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700500 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700501 }
502 }
503
Pragya Arya996a0892020-03-09 21:47:52 +0530504 if !o.enablePerf {
505 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700506 wg.Add(1)
507 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530508 }
509
Matteo Scandolo4747d292019-08-05 11:50:18 -0700510 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700511 oltLogger.WithFields(log.Fields{
512 "stream": stream,
513 }).Debug("OpenOLT Stream closed")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100514
515 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700516}
517
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700518func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530519 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700520
521loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530522 for {
523 select {
524 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
525 // send NNI port stats
526 for _, port := range o.Nnis {
527 incrementStat := true
528 if port.OperState.Current() == "down" {
529 incrementStat = false
530 }
531 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700532 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530533 }
534
535 // send PON port stats
536 for _, port := range o.Pons {
537 incrementStat := true
538 // do not increment port stats if PON port is down or no ONU is activated on PON port
539 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
540 incrementStat = false
541 }
542 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700543 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530544 }
545 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700546 oltLogger.Debug("Stop sending port stats")
547 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530548 }
Pragya Arya996a0892020-03-09 21:47:52 +0530549 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700550 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530551}
552
Matteo Scandolo4747d292019-08-05 11:50:18 -0700553// Helpers method
554
Matteo Scandolof9d43412021-01-12 11:11:34 -0800555func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
556
557 switch interfaceType {
558 case "nni":
559 if !o.HasNni(interfaceId) {
560 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
561 }
562
563 case "pon":
564 if !o.HasPon(interfaceId) {
565 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
566 }
567 }
568
569 alarmIndication := &openolt.AlarmIndication{
570 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
571 Status: alarmStatus,
572 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
573 }},
574 }
575
576 msg := types.Message{
577 Type: types.AlarmIndication,
578 Data: alarmIndication,
579 }
580
581 o.channel <- msg
582
583 return nil
584}
585
586func (o *OltDevice) HasNni(id uint32) bool {
587 for _, intf := range o.Nnis {
588 if intf.ID == id {
589 return true
590 }
591 }
592 return false
593}
594
595func (o *OltDevice) HasPon(id uint32) bool {
596 for _, intf := range o.Pons {
597 if intf.ID == id {
598 return true
599 }
600 }
601 return false
602}
603
Shrey Baid688b4242020-07-10 20:40:10 +0530604func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700605 for _, pon := range o.Pons {
606 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700607 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700608 }
609 }
Shrey Baid688b4242020-07-10 20:40:10 +0530610 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700611}
612
Shrey Baid688b4242020-07-10 20:40:10 +0530613func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700614 for _, nni := range o.Nnis {
615 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700616 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700617 }
618 }
Shrey Baid688b4242020-07-10 20:40:10 +0530619 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700620}
621
Scott Baker41724b82020-01-21 19:54:53 -0800622func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
623 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
624 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
625 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
626 return
627 }
628
629 oltLogger.WithFields(log.Fields{
630 "AlarmIndication": alarmInd,
631 }).Debug("Sent Indication_AlarmInd")
632}
633
Matteo Scandolof9d43412021-01-12 11:11:34 -0800634func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700635 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
636 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700637 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800638 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700639 }
640
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700641 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700642 "OperState": msg.OperState,
643 }).Debug("Sent Indication_OltInd")
644}
645
Matteo Scandolof9d43412021-01-12 11:11:34 -0800646func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700647 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800648 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800649 if err := nni.OperState.Event("enable"); err != nil {
650 log.WithFields(log.Fields{
651 "Type": nni.Type,
652 "IntfId": nni.ID,
653 "OperState": nni.OperState.Current(),
654 }).Errorf("Can't move NNI Port to enabled state: %v", err)
655 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800656 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800657 if err := nni.OperState.Event("disable"); err != nil {
658 log.WithFields(log.Fields{
659 "Type": nni.Type,
660 "IntfId": nni.ID,
661 "OperState": nni.OperState.Current(),
662 }).Errorf("Can't move NNI Port to disable state: %v", err)
663 }
664 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700665 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700667 Type: nni.Type,
668 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700669 OperState: nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100670 Speed: o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700671 }}
672
673 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700674 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800675 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700676 }
677
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700678 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700679 "Type": nni.Type,
680 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700681 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100682 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700683 }).Debug("Sent Indication_IntfOperInd for NNI")
684}
685
Pragya Arya2225f202020-01-29 18:05:01 +0530686func (o *OltDevice) sendPonIndication(ponPortID uint32) {
687
Matteo Scandolo4a036262020-08-17 15:56:13 -0700688 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530689 pon, _ := o.GetPonById(ponPortID)
690 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700691 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700692 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700693 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700694 }}
695
696 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700697 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800698 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700699 }
700
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700701 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700702 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700703 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700704 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700705
Pragya Arya2225f202020-01-29 18:05:01 +0530706 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700707 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700708 Type: pon.Type,
709 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700710 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700711 }}
712
713 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700714 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800715 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700716 }
717
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700718 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700719 "Type": pon.Type,
720 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700721 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700722 }).Debug("Sent Indication_IntfOperInd for PON")
723}
724
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700725func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100726 if o.InternalState.Current() == OltInternalStateEnabled {
Shrey Baid55f328c2020-07-07 19:20:42 +0530727 oltLogger.WithFields(log.Fields{
728 "Type": portType,
729 "IntfId": portID,
730 }).Trace("Sending port stats")
731 stats.IntfId = InterfaceIDToPortNo(portID, portType)
732 data := &openolt.Indication_PortStats{
733 PortStats: stats,
734 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700735
Shrey Baid55f328c2020-07-07 19:20:42 +0530736 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
737 oltLogger.Errorf("Failed to send PortStats: %v", err)
738 return
739 }
Pragya Arya996a0892020-03-09 21:47:52 +0530740 }
741}
742
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100743// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700744func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
745 oltLogger.WithFields(log.Fields{
746 "stream": stream,
747 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000748 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700749
David Bainbridge103cf022019-12-16 20:11:35 +0000750loop:
751 for {
752 select {
753 case <-ctx.Done():
754 oltLogger.Debug("OLT Indication processing canceled via context")
755 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700756 // do not terminate this loop if the stream is closed,
757 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
758 //case <-stream.Context().Done():
759 // oltLogger.Debug("OLT Indication processing canceled via stream context")
760 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000761 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700762 if !ok {
763 if ctx.Err() != nil {
764 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
765 }
766 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000767 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700768 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700769
David Bainbridge103cf022019-12-16 20:11:35 +0000770 oltLogger.WithFields(log.Fields{
771 "oltId": o.ID,
772 "messageType": message.Type,
773 }).Trace("Received message")
774
775 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800776 case types.OltIndication:
777 msg, _ := message.Data.(types.OltIndicationMessage)
778 if msg.OperState == types.UP {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100779 _ = o.InternalState.Event(OltInternalTxEnable)
Shrey Baid688b4242020-07-10 20:40:10 +0530780 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800781 } else if msg.OperState == types.DOWN {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100782 _ = o.InternalState.Event(OltInternalTxDisable)
Shrey Baid688b4242020-07-10 20:40:10 +0530783 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000784 }
785 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800786 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800787 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
788 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800789 case types.NniIndication:
790 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000791 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800792 case types.PonIndication:
793 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530794 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800795 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530796 if err := pon.OperState.Event("enable"); err != nil {
797 oltLogger.WithFields(log.Fields{
798 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800799 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530800 }).Error("Can't Enable Oper state for PON Port")
801 }
802 if err := pon.InternalState.Event("enable"); err != nil {
803 oltLogger.WithFields(log.Fields{
804 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800805 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530806 }).Error("Can't Enable Internal state for PON Port")
807 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800808 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530809 if err := pon.OperState.Event("disable"); err != nil {
810 oltLogger.WithFields(log.Fields{
811 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800812 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530813 }).Error("Can't Disable Oper state for PON Port")
814 }
815 if err := pon.InternalState.Event("disable"); err != nil {
816 oltLogger.WithFields(log.Fields{
817 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800818 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530819 }).Error("Can't Disable Internal state for PON Port")
820 }
Pragya Arya2225f202020-01-29 18:05:01 +0530821 }
David Bainbridge103cf022019-12-16 20:11:35 +0000822 default:
823 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
824 }
825 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700826 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100827 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700828 oltLogger.WithFields(log.Fields{
829 "stream": stream,
830 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700831}
832
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700833// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530834func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700835 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700836 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700837 for _, pon := range o.Pons {
838 for _, onu := range pon.Onus {
839 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700840 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700841 }
842 }
843 }
844
Shrey Baid688b4242020-07-10 20:40:10 +0530845 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700846}
847
William Kurkian9dadc5b2019-10-22 13:51:57 -0400848// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530849func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700850 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400851 // memoizing it will remove the bottleneck
852 for _, pon := range o.Pons {
853 if pon.ID == intfId {
854 for _, onu := range pon.Onus {
855 if onu.ID == onuId {
856 return onu, nil
857 }
858 }
859 }
860 }
Shrey Baid688b4242020-07-10 20:40:10 +0530861 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400862}
863
Matteo Scandolo4a036262020-08-17 15:56:13 -0700864// returns a Service with a given Mac Address
865func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700866 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700867 // memoizing it will remove the bottleneck
868 for _, pon := range o.Pons {
869 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700870 s, err := onu.findServiceByMacAddress(mac)
871 if err == nil {
872 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700873 }
874 }
875 }
876
Matteo Scandolo4a036262020-08-17 15:56:13 -0700877 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700878}
879
Matteo Scandolo4747d292019-08-05 11:50:18 -0700880// GRPC Endpoints
881
Shrey Baid688b4242020-07-10 20:40:10 +0530882func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700883
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700884 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800885
Matteo Scandolo8a574812021-05-20 15:18:53 -0700886 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800887 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
888 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
889
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700890 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700891
892 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
893 oltLogger.WithFields(log.Fields{
894 "OnuSn": _onu.Sn(),
895 }).Info("Received ActivateOnu call from VOLTHA")
896
William Kurkian0418bc82019-11-06 12:16:24 -0500897 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700898
Matteo Scandolocedde462021-03-09 17:37:16 -0800899 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700900 oltLogger.WithFields(log.Fields{
901 "IntfId": _onu.PonPortID,
902 "OnuSn": _onu.Sn(),
903 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800904 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700905 }
906
907 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
908
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700909 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700910}
911
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800912func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700913 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700914 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700915}
916
Shrey Baid688b4242020-07-10 20:40:10 +0530917func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530918 oltLogger.WithFields(log.Fields{
919 "IntfId": onu.IntfId,
920 "OnuId": onu.OnuId,
921 }).Info("Received DeleteOnu call from VOLTHA")
922
923 pon, err := o.GetPonById(onu.IntfId)
924 if err != nil {
925 oltLogger.WithFields(log.Fields{
926 "OnuId": onu.OnuId,
927 "IntfId": onu.IntfId,
928 "err": err,
929 }).Error("Can't find PonPort")
930 }
931 _onu, err := pon.GetOnuById(onu.OnuId)
932 if err != nil {
933 oltLogger.WithFields(log.Fields{
934 "OnuId": onu.OnuId,
935 "IntfId": onu.IntfId,
936 "err": err,
937 }).Error("Can't find Onu")
938 }
939
Matteo Scandolocedde462021-03-09 17:37:16 -0800940 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530941 oltLogger.WithFields(log.Fields{
942 "IntfId": _onu.PonPortID,
943 "OnuSn": _onu.Sn(),
944 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800945 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530946 }
947
Hardik Windlassad790cb2020-06-17 21:26:22 +0530948 // ONU Re-Discovery
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100949 if o.InternalState.Current() == OltInternalStateEnabled && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530950 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530951 }
952
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700953 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700954}
955
Shrey Baid688b4242020-07-10 20:40:10 +0530956func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700957 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800958 oltLogger.WithFields(log.Fields{
959 "oltId": o.ID,
960 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530961 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800962
Matteo Scandolo401503a2019-12-11 14:48:14 -0800963 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530964 if pon.InternalState.Current() == "enabled" {
965 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800966 msg := types.Message{
967 Type: types.PonIndication,
968 Data: types.PonIndicationMessage{
969 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530970 PonPortID: pon.ID,
971 },
972 }
973 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800974 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800975 }
976
Matteo Scandolo401503a2019-12-11 14:48:14 -0800977 // Note that we are not disabling the NNI as the real OLT does not.
978 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800979
980 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800981 oltMsg := types.Message{
982 Type: types.OltIndication,
983 Data: types.OltIndicationMessage{
984 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700985 },
986 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100987 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700988
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700989 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700990}
991
Shrey Baid688b4242020-07-10 20:40:10 +0530992func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530993 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200994 ponID := intf.GetIntfId()
995 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200996
Matteo Scandolof9d43412021-01-12 11:11:34 -0800997 msg := types.Message{
998 Type: types.PonIndication,
999 Data: types.PonIndicationMessage{
1000 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001001 PonPortID: ponID,
1002 },
1003 }
1004 o.channel <- msg
1005
1006 for _, onu := range pon.Onus {
1007
Matteo Scandolof9d43412021-01-12 11:11:34 -08001008 onuIndication := types.OnuIndicationMessage{
1009 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001010 PonPortID: ponID,
1011 OnuID: onu.ID,
1012 OnuSN: onu.SerialNumber,
1013 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001014 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001015
1016 }
1017
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001018 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001019}
1020
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001021func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001022 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301023 publishEvent("OLT-enable-received", -1, -1, "")
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001024 return o.Enable(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001025}
1026
Shrey Baid688b4242020-07-10 20:40:10 +05301027func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301028 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301029 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001030 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001031
Matteo Scandolof9d43412021-01-12 11:11:34 -08001032 msg := types.Message{
1033 Type: types.PonIndication,
1034 Data: types.PonIndicationMessage{
1035 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301036 PonPortID: ponID,
1037 },
1038 }
1039 o.channel <- msg
1040
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001041 for _, onu := range pon.Onus {
1042
Matteo Scandolof9d43412021-01-12 11:11:34 -08001043 onuIndication := types.OnuIndicationMessage{
1044 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001045 PonPortID: ponID,
1046 OnuID: onu.ID,
1047 OnuSN: onu.SerialNumber,
1048 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001049 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001050
1051 }
1052
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001053 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001054}
1055
Shrey Baid688b4242020-07-10 20:40:10 +05301056func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001057 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001058 "IntfId": flow.AccessIntfId,
1059 "OnuId": flow.OnuId,
1060 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001061 "InnerVlan": flow.Classifier.IVid,
1062 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001063 "FlowType": flow.FlowType,
1064 "FlowId": flow.FlowId,
1065 "UniID": flow.UniId,
1066 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301067 }).Tracef("OLT receives FlowAdd")
1068
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001069 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301070 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001071 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001072 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301073 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001074
1075 if flow.AccessIntfId == -1 {
1076 oltLogger.WithFields(log.Fields{
1077 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001078 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001079 } else if flow.FlowType == "multicast" {
1080 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001081 "Cookie": flow.Cookie,
1082 "DstPort": flow.Classifier.DstPort,
1083 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1084 "FlowId": flow.FlowId,
1085 "FlowType": flow.FlowType,
1086 "GemportId": flow.GemportId,
1087 "InnerVlan": flow.Classifier.IVid,
1088 "IntfId": flow.AccessIntfId,
1089 "IpProto": flow.Classifier.IpProto,
1090 "OnuId": flow.OnuId,
1091 "OuterVlan": flow.Classifier.OVid,
1092 "PortNo": flow.PortNo,
1093 "SrcPort": flow.Classifier.SrcPort,
1094 "UniID": flow.UniId,
1095 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001096 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001097 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001098 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001099 if err != nil {
1100 oltLogger.WithFields(log.Fields{
1101 "OnuId": flow.OnuId,
1102 "IntfId": flow.AccessIntfId,
1103 "err": err,
1104 }).Error("Can't find PonPort")
1105 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001106 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001107 if err != nil {
1108 oltLogger.WithFields(log.Fields{
1109 "OnuId": flow.OnuId,
1110 "IntfId": flow.AccessIntfId,
1111 "err": err,
1112 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001113 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001114 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001115
1116 // if the ONU is disabled reject the flow
1117 // as per VOL-4061 there is a small window during which the ONU is disabled
1118 // but the port has not been reported as down to ONOS
1119 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1120 oltLogger.WithFields(log.Fields{
1121 "OnuId": flow.OnuId,
1122 "IntfId": flow.AccessIntfId,
1123 "Flow": flow,
1124 "SerialNumber": onu.Sn(),
1125 "InternalState": onu.InternalState.Current(),
1126 }).Error("rejected-flow-because-of-onu-state")
1127 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1128 }
1129
Pragya Arya8bdb4532020-03-02 17:08:09 +05301130 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001131 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301132 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001133 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001134 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301135 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301136 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001137
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001138 // validate that the flow reference correct IDs (Alloc, Gem)
1139 if err := o.validateFlow(flow); err != nil {
1140 oltLogger.WithFields(log.Fields{
1141 "OnuId": flow.OnuId,
1142 "IntfId": flow.AccessIntfId,
1143 "Flow": flow,
1144 "SerialNumber": onu.Sn(),
1145 "err": err,
1146 }).Error("invalid-flow-for-onu")
1147 return nil, err
1148 }
1149
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001150 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001151 o.storeAllocId(flow)
1152
Matteo Scandolof9d43412021-01-12 11:11:34 -08001153 msg := types.Message{
1154 Type: types.FlowAdd,
1155 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001156 PonPortID: pon.ID,
1157 OnuID: onu.ID,
1158 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001159 },
1160 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001161 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001162 }
1163
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001164 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001165}
1166
Pragya Arya8bdb4532020-03-02 17:08:09 +05301167// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301168func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001169
Pragya Arya8bdb4532020-03-02 17:08:09 +05301170 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001171 "AllocId": flow.AllocId,
1172 "Cookie": flow.Cookie,
1173 "FlowId": flow.FlowId,
1174 "FlowType": flow.FlowType,
1175 "GemportId": flow.GemportId,
1176 "IntfId": flow.AccessIntfId,
1177 "OnuId": flow.OnuId,
1178 "PortNo": flow.PortNo,
1179 "UniID": flow.UniId,
1180 "ReplicateFlow": flow.ReplicateFlow,
1181 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001182 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301183
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001184 olt.freeGemPortId(flow)
1185 olt.freeAllocId(flow)
1186
Pragya Arya8bdb4532020-03-02 17:08:09 +05301187 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001188 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301189 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001190 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301191 if !ok {
1192 oltLogger.Errorf("Flow %v not found", flow)
1193 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1194 }
1195
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001196 storedFlow := storedFlowIntf.(openolt.Flow)
1197
Pragya Arya8bdb4532020-03-02 17:08:09 +05301198 // if its ONU flow remove it from ONU also
1199 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001200 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1201 if err != nil {
1202 oltLogger.WithFields(log.Fields{
1203 "OnuId": storedFlow.OnuId,
1204 "IntfId": storedFlow.AccessIntfId,
1205 "PONs": olt.Pons,
1206 "err": err,
1207 }).Error("PON-port-not-found")
1208 return new(openolt.Empty), nil
1209 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301210 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1211 if err != nil {
1212 oltLogger.WithFields(log.Fields{
1213 "OnuId": storedFlow.OnuId,
1214 "IntfId": storedFlow.AccessIntfId,
1215 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001216 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301217 return new(openolt.Empty), nil
1218 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001219 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001220 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301221 }
1222
1223 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001224 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301225 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001226
1227 if flow.AccessIntfId == -1 {
1228 oltLogger.WithFields(log.Fields{
1229 "FlowId": flow.FlowId,
1230 }).Debug("Removing OLT flow")
1231 } else if flow.FlowType == "multicast" {
1232 oltLogger.WithFields(log.Fields{
1233 "FlowId": flow.FlowId,
1234 }).Debug("Removing OLT multicast flow")
1235 } else {
1236
1237 onu, err := o.GetOnuByFlowId(flow.FlowId)
1238 if err != nil {
1239 oltLogger.WithFields(log.Fields{
1240 "OnuId": flow.OnuId,
1241 "IntfId": flow.AccessIntfId,
1242 "err": err,
1243 }).Error("Can't find Onu")
1244 return nil, err
1245 }
1246
Matteo Scandolof9d43412021-01-12 11:11:34 -08001247 msg := types.Message{
1248 Type: types.FlowRemoved,
1249 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301250 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001251 },
1252 }
1253 onu.Channel <- msg
1254 }
1255
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001256 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001257}
1258
Shrey Baid688b4242020-07-10 20:40:10 +05301259func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001260 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1261 oltLogger.WithFields(log.Fields{
1262 "signature": res.HeartbeatSignature,
1263 }).Trace("HeartbeatCheck")
1264 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001265}
1266
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001267func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001268 for _, pon := range o.Pons {
1269 for _, onu := range pon.Onus {
1270 for _, fId := range onu.FlowIds {
1271 if fId == flowId {
1272 return onu, nil
1273 }
1274 }
1275 }
1276 }
Shrey Baid688b4242020-07-10 20:40:10 +05301277 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001278}
1279
Shrey Baid688b4242020-07-10 20:40:10 +05301280func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001281
Matteo Scandolocedde462021-03-09 17:37:16 -08001282 intfIDs := []uint32{}
1283 for i := 0; i < o.NumPon; i++ {
1284 intfIDs = append(intfIDs, uint32(i))
1285 }
1286
1287 devinfo := &openolt.DeviceInfo{
1288 Vendor: common.Config.Olt.Vendor,
1289 Model: common.Config.Olt.Model,
1290 HardwareVersion: common.Config.Olt.HardwareVersion,
1291 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1292 Technology: common.Config.Olt.Technology,
1293 PonPorts: uint32(o.NumPon),
1294 OnuIdStart: onuIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001295 OnuIdEnd: o.onuIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001296 AllocIdStart: allocIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001297 AllocIdEnd: o.allocIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001298 GemportIdStart: gemportIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001299 GemportIdEnd: o.gemportIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001300 FlowIdStart: flowIdStart,
1301 FlowIdEnd: flowIdEnd,
1302 DeviceSerialNumber: o.SerialNumber,
1303 DeviceId: common.Config.Olt.DeviceId,
1304 PreviouslyConnected: o.PreviouslyConnected,
1305 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1306 {
1307 IntfIds: intfIDs,
1308 Technology: common.Config.Olt.Technology,
1309 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1310 {
1311 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1312 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1313 Start: onuIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001314 End: o.onuIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001315 },
1316 {
1317 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1318 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1319 Start: allocIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001320 End: o.allocIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001321 },
1322 {
1323 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1324 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1325 Start: gemportIdStart,
Matteo Scandolo52d12e32022-02-02 15:30:20 -08001326 End: o.gemportIdEnd,
Matteo Scandolocedde462021-03-09 17:37:16 -08001327 },
1328 {
1329 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1330 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1331 Start: flowIdStart,
1332 End: flowIdEnd,
1333 },
1334 },
1335 },
1336 },
1337 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001338
1339 oltLogger.WithFields(log.Fields{
1340 "Vendor": devinfo.Vendor,
1341 "Model": devinfo.Model,
1342 "HardwareVersion": devinfo.HardwareVersion,
1343 "FirmwareVersion": devinfo.FirmwareVersion,
1344 "Technology": devinfo.Technology,
1345 "PonPorts": devinfo.PonPorts,
1346 "OnuIdStart": devinfo.OnuIdStart,
1347 "OnuIdEnd": devinfo.OnuIdEnd,
1348 "AllocIdStart": devinfo.AllocIdStart,
1349 "AllocIdEnd": devinfo.AllocIdEnd,
1350 "GemportIdStart": devinfo.GemportIdStart,
1351 "GemportIdEnd": devinfo.GemportIdEnd,
1352 "FlowIdStart": devinfo.FlowIdStart,
1353 "FlowIdEnd": devinfo.FlowIdEnd,
1354 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1355 "DeviceId": devinfo.DeviceId,
1356 "PreviouslyConnected": devinfo.PreviouslyConnected,
1357 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1358
1359 // once we connect, set the flag
1360 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001361
1362 return devinfo, nil
1363}
1364
Shrey Baid688b4242020-07-10 20:40:10 +05301365func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001366 pon, err := o.GetPonById(omci_msg.IntfId)
1367 if err != nil {
1368 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001369 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001370 "onu_id": omci_msg.OnuId,
1371 "pon_id": omci_msg.IntfId,
1372 }).Error("pon ID not found")
1373 return nil, err
1374 }
1375
1376 onu, err := pon.GetOnuById(omci_msg.OnuId)
1377 if err != nil {
1378 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001379 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001380 "onu_id": omci_msg.OnuId,
1381 "pon_id": omci_msg.IntfId,
1382 }).Error("onu ID not found")
1383 return nil, err
1384 }
1385
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001386 oltLogger.WithFields(log.Fields{
1387 "IntfId": onu.PonPortID,
1388 "OnuId": onu.ID,
1389 "OnuSn": onu.Sn(),
1390 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001391 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1392 if err != nil {
1393 log.WithFields(log.Fields{
1394 "IntfId": onu.PonPortID,
1395 "SerialNumber": onu.Sn(),
1396 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1397 "err": err.Error(),
1398 }).Error("cannot-parse-OMCI-packet")
1399 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001400 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001401 if onu.InternalState.Current() == OnuStateDisabled {
1402 // if the ONU is disabled just drop the message
1403 log.WithFields(log.Fields{
1404 "IntfId": onu.PonPortID,
1405 "SerialNumber": onu.Sn(),
1406 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1407 "omciPkt": omciPkt,
1408 "omciMsgType": omciMsg.MessageType,
1409 }).Warn("dropping-omci-message")
1410 } else {
1411 msg := types.Message{
1412 Type: types.OMCI,
1413 Data: types.OmciMessage{
1414 OnuSN: onu.SerialNumber,
1415 OnuID: onu.ID,
1416 OmciMsg: omciMsg,
1417 OmciPkt: omciPkt,
1418 },
1419 }
1420 onu.Channel <- msg
1421 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001422 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001423}
1424
Matteo Scandolo8a574812021-05-20 15:18:53 -07001425// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301426func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001427 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001428 if err != nil {
1429 oltLogger.WithFields(log.Fields{
1430 "OnuId": onuPkt.OnuId,
1431 "IntfId": onuPkt.IntfId,
1432 "err": err,
1433 }).Error("Can't find PonPort")
1434 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001435 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001436 if err != nil {
1437 oltLogger.WithFields(log.Fields{
1438 "OnuId": onuPkt.OnuId,
1439 "IntfId": onuPkt.IntfId,
1440 "err": err,
1441 }).Error("Can't find Onu")
1442 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001443
Matteo Scandolo075b1892019-10-07 12:11:07 -07001444 oltLogger.WithFields(log.Fields{
1445 "IntfId": onu.PonPortID,
1446 "OnuId": onu.ID,
1447 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001448 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001449 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001450
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001451 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001452
1453 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001454 if err != nil {
1455 onuLogger.WithFields(log.Fields{
1456 "IntfId": onu.PonPortID,
1457 "OnuId": onu.ID,
1458 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001459 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001460 }).Error("Can't find pktType in packet, droppint it")
1461 return new(openolt.Empty), nil
1462 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001463
Matteo Scandolo4a036262020-08-17 15:56:13 -07001464 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001465 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001466 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001467 "IntfId": onu.PonPortID,
1468 "OnuId": onu.ID,
1469 "OnuSn": onu.Sn(),
1470 "Pkt": rawpkt.Data(),
1471 }).Error("Can't find Dst MacAddress in packet, droppint it")
1472 return new(openolt.Empty), nil
1473 }
1474
Matteo Scandolof9d43412021-01-12 11:11:34 -08001475 msg := types.Message{
1476 Type: types.OnuPacketOut,
1477 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001478 IntfId: onuPkt.IntfId,
1479 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001480 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001481 Packet: rawpkt,
1482 Type: pktType,
1483 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001484 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001485 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001486
Matteo Scandolo075b1892019-10-07 12:11:07 -07001487 onu.Channel <- msg
1488
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001489 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001490}
1491
Shrey Baid688b4242020-07-10 20:40:10 +05301492func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001493
1494 // OLT Reboot is called in two cases:
1495 // - 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)
1496 // - when an OLT needs to be rebooted (voltcl device reboot)
1497
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001498 oltLogger.WithFields(log.Fields{
1499 "oltId": o.ID,
1500 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301501 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301502 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001503 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001504}
1505
Shrey Baid688b4242020-07-10 20:40:10 +05301506func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301507 oltLogger.WithFields(log.Fields{
1508 "oltId": o.ID,
1509 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301510 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301511
Pragya Arya2225f202020-01-29 18:05:01 +05301512 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001513 oltMsg := types.Message{
1514 Type: types.OltIndication,
1515 Data: types.OltIndicationMessage{
1516 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301517 },
Pragya Arya1881df02020-01-29 18:05:01 +05301518 }
Pragya Arya2225f202020-01-29 18:05:01 +05301519 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301520
Pragya Arya2225f202020-01-29 18:05:01 +05301521 for _, pon := range o.Pons {
1522 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001523 msg := types.Message{
1524 Type: types.PonIndication,
1525 Data: types.PonIndicationMessage{
1526 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301527 PonPortID: pon.ID,
1528 },
1529 }
1530 o.channel <- msg
1531 }
1532 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001533
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001534 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001535}
1536
Shrey Baid688b4242020-07-10 20:40:10 +05301537func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001538 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1539
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001540 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1541
1542 if err != nil {
1543 return nil, err
1544 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001545 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001546}
1547
Shrey Baid688b4242020-07-10 20:40:10 +05301548func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001549 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001550 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001551}
1552
Shrey Baid688b4242020-07-10 20:40:10 +05301553func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001554 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001555 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001556}
1557
Shrey Baid688b4242020-07-10 20:40:10 +05301558func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001559 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001560 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001561}
1562
Shrey Baid688b4242020-07-10 20:40:10 +05301563func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001564 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001565 return new(openolt.Empty), nil
1566}
1567
Matteo Scandolo8a574812021-05-20 15:18:53 -07001568func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1569 oltLogger.WithFields(log.Fields{
1570 "OnuId": tq.OnuId,
1571 "IntfId": tq.IntfId,
1572 "OnuPortNo": tq.PortNo,
1573 "UniId": tq.UniId,
1574 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001575 return new(openolt.Empty), nil
1576}
1577
Matteo Scandolo8a574812021-05-20 15:18:53 -07001578func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301579 oltLogger.WithFields(log.Fields{
1580 "OnuId": trafficSchedulers.OnuId,
1581 "IntfId": trafficSchedulers.IntfId,
1582 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001583 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301584 }).Info("received CreateTrafficSchedulers")
1585
1586 if !s.enablePerf {
1587 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1588 if err != nil {
1589 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1590 return new(openolt.Empty), err
1591 }
1592 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1593 if err != nil {
1594 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1595 return new(openolt.Empty), err
1596 }
1597 onu.TrafficSchedulers = trafficSchedulers
1598 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001599 return new(openolt.Empty), nil
1600}
1601
Shrey Baid688b4242020-07-10 20:40:10 +05301602func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301603 oltLogger.WithFields(log.Fields{
1604 "OnuId": trafficSchedulers.OnuId,
1605 "IntfId": trafficSchedulers.IntfId,
1606 "OnuPortNo": trafficSchedulers.PortNo,
1607 }).Info("received RemoveTrafficSchedulers")
1608 if !s.enablePerf {
1609 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1610 if err != nil {
1611 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1612 return new(openolt.Empty), err
1613 }
1614 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1615 if err != nil {
1616 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1617 return new(openolt.Empty), err
1618 }
1619
1620 onu.TrafficSchedulers = nil
1621 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001622 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001623}
Scott Baker41724b82020-01-21 19:54:53 -08001624
Matteo Scandolo618a6582020-09-09 12:21:29 -07001625func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1626 oltLogger.WithFields(log.Fields{
1627 "GroupId": group.GroupId,
1628 "Command": group.Command,
1629 "Members": group.Members,
1630 "Action": group.Action,
1631 }).Debug("received PerformGroupOperation")
1632 return &openolt.Empty{}, nil
1633}
1634
1635func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1636 oltLogger.WithFields(log.Fields{
1637 "GroupId": group.GroupId,
1638 "Command": group.Command,
1639 "Members": group.Members,
1640 "Action": group.Action,
1641 }).Debug("received PerformGroupOperation")
1642 return &openolt.Empty{}, nil
1643}
1644
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001645func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1646 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001647}
1648
1649func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1650 return &openolt.Empty{}, nil
1651}
1652
1653func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1654 return &openolt.OnuLogicalDistance{}, nil
1655}
1656
1657func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1658 return &openolt.OnuLogicalDistance{}, nil
1659}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001660
Girish Gowdra62f24292021-05-12 16:28:39 -07001661func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1662 return &openolt.PonRxPowerData{}, nil
1663}
1664
Matteo Scandolo96f89192021-03-12 13:17:26 -08001665func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1666 return &openolt.GemPortStatistics{}, nil
1667}
1668
1669func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1670 return &openolt.OnuStatistics{}, nil
1671}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001672
1673func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1674 o.AllocIDsLock.Lock()
1675 defer o.AllocIDsLock.Unlock()
1676
Matteo Scandolo21195d62021-04-07 14:31:23 -07001677 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1678 oltLogger.WithFields(log.Fields{
1679 "IntfId": flow.AccessIntfId,
1680 "OnuId": flow.OnuId,
1681 "PortNo": flow.PortNo,
1682 "GemportId": flow.GemportId,
1683 "FlowId": flow.FlowId,
1684 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1685 }
1686
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001687 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001688 "IntfId": flow.AccessIntfId,
1689 "OnuId": flow.OnuId,
1690 "PortNo": flow.PortNo,
1691 "GemportId": flow.GemportId,
1692 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001693 }).Trace("storing-alloc-id-via-flow")
1694
1695 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1696 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1697 }
1698 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1699 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1700 }
1701 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1702}
1703
1704func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1705 // if this is the last flow referencing the AllocId then remove it
1706 o.AllocIDsLock.Lock()
1707 defer o.AllocIDsLock.Unlock()
1708
1709 oltLogger.WithFields(log.Fields{
1710 "IntfId": flow.AccessIntfId,
1711 "OnuId": flow.OnuId,
1712 "PortNo": flow.PortNo,
1713 "GemportId": flow.GemportId,
1714 }).Trace("freeing-alloc-id-via-flow")
1715
1716 // NOTE look at the freeGemPortId implementation for comments and context
1717 for ponId, ponValues := range o.AllocIDs {
1718 for onuId, onuValues := range ponValues {
1719 for uniId, uniValues := range onuValues {
1720 for allocId, flows := range uniValues {
1721 for flowId := range flows {
1722 // if the flow matches, remove it from the map.
1723 if flow.FlowId == flowId {
1724 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1725 }
1726 // if that was the last flow for a particular allocId, remove the entire allocId
1727 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1728 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1729 }
1730 }
1731 }
1732 }
1733 }
1734 }
1735}
1736
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001737func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001738 o.GemPortIDsLock.Lock()
1739 defer o.GemPortIDsLock.Unlock()
1740
1741 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1742 oltLogger.WithFields(log.Fields{
1743 "IntfId": ponId,
1744 "OnuId": onuId,
1745 "PortNo": portNo,
1746 "GemportId": gemId,
1747 "FlowId": flowId,
1748 }).Error("trying-to-store-gemport-for-unknown-onu")
1749 }
1750
1751 oltLogger.WithFields(log.Fields{
1752 "IntfId": ponId,
1753 "OnuId": onuId,
1754 "PortNo": portNo,
1755 "GemportId": gemId,
1756 "FlowId": flowId,
1757 }).Trace("storing-alloc-id-via-flow")
1758
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001759 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1760 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1761 }
1762 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1763 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1764 }
1765 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1766}
1767
1768func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001769 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001770 "IntfId": flow.AccessIntfId,
1771 "OnuId": flow.OnuId,
1772 "PortNo": flow.PortNo,
1773 "GemportId": flow.GemportId,
1774 "FlowId": flow.FlowId,
1775 "ReplicateFlow": flow.ReplicateFlow,
1776 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001777 }).Trace("storing-gem-port-id-via-flow")
1778
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001779 if flow.ReplicateFlow {
1780 for _, gem := range flow.PbitToGemport {
1781 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1782 }
1783 } else {
1784 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001785 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001786}
1787
1788func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1789 // if this is the last flow referencing the GemPort then remove it
1790 o.GemPortIDsLock.Lock()
1791 defer o.GemPortIDsLock.Unlock()
1792
1793 oltLogger.WithFields(log.Fields{
1794 "IntfId": flow.AccessIntfId,
1795 "OnuId": flow.OnuId,
1796 "PortNo": flow.PortNo,
1797 "GemportId": flow.GemportId,
1798 }).Trace("freeing-gem-port-id-via-flow")
1799
1800 // NOTE that this loop is not very performant, it would be better if the flow carries
1801 // the same information that it carries during a FlowAdd. If so we can directly remove
1802 // items from the map
1803
1804 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1805 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1806 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1807 //}
1808
1809 // NOTE this loop assumes that flow IDs are unique per device
1810 for ponId, ponValues := range o.GemPortIDs {
1811 for onuId, onuValues := range ponValues {
1812 for uniId, uniValues := range onuValues {
1813 for gemId, flows := range uniValues {
1814 for flowId := range flows {
1815 // if the flow matches, remove it from the map.
1816 if flow.FlowId == flowId {
1817 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1818 }
1819 // if that was the last flow for a particular gem, remove the entire gem
1820 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1821 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1822 }
1823 }
1824 }
1825 }
1826 }
1827 }
1828}
1829
1830// validateFlow checks that:
1831// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1832// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1833func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001834 // validate gemPort
1835 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001836 defer o.GemPortIDsLock.RUnlock()
1837 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001838 if onuId == uint32(flow.OnuId) {
1839 continue
1840 }
1841 for uniId, uni := range onu {
1842 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001843 if flow.ReplicateFlow {
1844 for _, flowGem := range flow.PbitToGemport {
1845 if gem == int32(flowGem) {
1846 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1847 }
1848 }
1849 } else {
1850 if gem == flow.GemportId {
1851 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1852 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001853 }
1854 }
1855 }
1856 }
1857
1858 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001859 defer o.AllocIDsLock.RUnlock()
1860 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001861 if onuId == uint32(flow.OnuId) {
1862 continue
1863 }
1864 for uniId, uni := range onu {
1865 for allocId := range uni {
1866 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001867 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 -08001868 }
1869 }
1870 }
1871 }
1872
1873 return nil
1874}
1875
1876// clearAllResources is invoked up OLT Reboot to remove all the allocated
1877// GemPorts, AllocId and ONU-IDs across the PONs
1878func (o *OltDevice) clearAllResources() {
1879
1880 // remove the resources received via flows
1881 o.GemPortIDsLock.Lock()
1882 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1883 o.GemPortIDsLock.Unlock()
1884 o.AllocIDsLock.Lock()
1885 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1886 o.AllocIDsLock.Unlock()
1887
1888 // remove the resources received via OMCI
1889 for _, pon := range o.Pons {
1890 pon.removeAllAllocIds()
1891 pon.removeAllGemPorts()
1892 pon.removeAllOnuIds()
1893 }
1894}