blob: 4d830180df2b01bf295cb6bebf280aab385af082 [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 (
Elia Battiston67e9e4c2022-02-15 16:38:40 +010054 //InternalState FSM states and transitions
55 OltInternalStateCreated = "created"
56 OltInternalStateInitialized = "initialized"
57 OltInternalStateEnabled = "enabled"
58 OltInternalStateDisabled = "disabled"
59 OltInternalStateDeleted = "deleted"
60
61 OltInternalTxInitialize = "initialize"
62 OltInternalTxEnable = "enable"
63 OltInternalTxDisable = "disable"
64 OltInternalTxDelete = "delete"
Matteo Scandolocedde462021-03-09 17:37:16 -080065)
66
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070067type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000068 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000069 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000070
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070071 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053072 ID int
73 SerialNumber string
74 NumNni int
Elia Battiston420c9092022-02-02 12:17:54 +010075 NniSpeed uint32
Pragya Arya2225f202020-01-29 18:05:01 +053076 NumPon int
77 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070078 NumUni int
Elia Battistonac63b112022-01-12 18:40:49 +010079 NumPots int
Andrea Campanella6f5f3552022-03-10 17:14:25 +010080 NniDhcpTrapVid int
Pragya Arya2225f202020-01-29 18:05:01 +053081 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080082 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070083 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010084 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053085 Delay int
86 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053087 EventChannel chan common.Event
88 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053089 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080090 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070091
Matteo Scandolo27428702019-10-11 16:21:16 -070092 Pons []*PonPort
93 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070094
95 // OLT Attributes
96 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000097
98 enableContext context.Context
99 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +0530100
Matteo Scandolo4a036262020-08-17 15:56:13 -0700101 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +0530102 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800103
104 // Allocated Resources
105 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000106 AllocIDsLock sync.RWMutex
107 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
108 GemPortIDsLock sync.RWMutex
109 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
110 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700111}
112
Matteo Scandolo27428702019-10-11 16:21:16 -0700113var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700114
Matteo Scandolo27428702019-10-11 16:21:16 -0700115func GetOLT() *OltDevice {
116 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700117}
118
Matteo Scandolo4a036262020-08-17 15:56:13 -0700119func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700120 oltLogger.WithFields(log.Fields{
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100121 "ID": options.Olt.ID,
122 "NumNni": options.Olt.NniPorts,
123 "NniSpeed": options.Olt.NniSpeed,
124 "NumPon": options.Olt.PonPorts,
125 "NumOnuPerPon": options.Olt.OnusPonPort,
126 "NumUni": options.Olt.UniPorts,
127 "NumPots": options.Olt.PotsPorts,
128 "NniDhcpTrapVid": options.Olt.NniDhcpTrapVid,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700129 }).Debug("CreateOLT")
130
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700131 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530132 ID: options.Olt.ID,
133 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700134 OperState: getOperStateFSM(func(e *fsm.Event) {
135 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
136 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800137 NumNni: int(options.Olt.NniPorts),
Elia Battiston420c9092022-02-02 12:17:54 +0100138 NniSpeed: options.Olt.NniSpeed,
Matteo Scandolo96f89192021-03-12 13:17:26 -0800139 NumPon: int(options.Olt.PonPorts),
140 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700141 NumUni: int(options.Olt.UniPorts),
Elia Battistonac63b112022-01-12 18:40:49 +0100142 NumPots: int(options.Olt.PotsPorts),
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100143 NniDhcpTrapVid: int(options.Olt.NniDhcpTrapVid),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800144 Pons: []*PonPort{},
145 Nnis: []*NniPort{},
146 Delay: options.BBSim.Delay,
147 enablePerf: options.BBSim.EnablePerf,
148 PublishEvents: options.BBSim.Events,
149 PortStatsInterval: options.Olt.PortStatsInterval,
150 dhcpServer: dhcp.NewDHCPServer(),
151 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800152 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
153 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000154 OmciResponseRate: options.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700155 }
156
Pragya Arya996a0892020-03-09 21:47:52 +0530157 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530158 olt.ControlledActivation = val
159 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700160 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530161 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
162 olt.ControlledActivation = Default
163 }
164
Matteo Scandolo4747d292019-08-05 11:50:18 -0700165 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700166 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700167 olt.InternalState = fsm.NewFSM(
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100168 OltInternalStateCreated,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700169 fsm.Events{
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100170 {Name: OltInternalTxInitialize, Src: []string{OltInternalStateCreated, OltInternalStateDeleted}, Dst: OltInternalStateInitialized},
171 {Name: OltInternalTxEnable, Src: []string{OltInternalStateInitialized, OltInternalStateDisabled}, Dst: OltInternalStateEnabled},
172 {Name: OltInternalTxDisable, Src: []string{OltInternalStateEnabled}, Dst: OltInternalStateDisabled},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700173 // delete event in enabled state below is for reboot OLT case.
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100174 {Name: OltInternalTxDelete, Src: []string{OltInternalStateDisabled, OltInternalStateEnabled}, Dst: OltInternalStateDeleted},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700175 },
176 fsm.Callbacks{
177 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700178 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700179 },
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100180 fmt.Sprintf("enter_%s", OltInternalStateInitialized): func(e *fsm.Event) { olt.InitOlt() },
181 fmt.Sprintf("enter_%s", OltInternalStateDeleted): func(e *fsm.Event) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800182 // remove all the resource allocations
183 olt.clearAllResources()
184 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700185 },
186 )
187
Shrey Baid688b4242020-07-10 20:40:10 +0530188 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700189 // create NNI Port
190 nniPort, err := CreateNNI(&olt)
191 if err != nil {
192 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
193 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700194
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700195 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700196 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700197
Matteo Scandolo4a036262020-08-17 15:56:13 -0700198 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700199 nextCtag := map[string]int{}
200 nextStag := map[string]int{}
201
Matteo Scandolo4747d292019-08-05 11:50:18 -0700202 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700203 for i := 0; i < olt.NumPon; i++ {
Elia Battistonb7bea222022-02-18 16:25:00 +0100204 ponConf, err := common.GetPonConfigById(uint32(i))
205 if err != nil {
206 oltLogger.WithFields(log.Fields{
207 "Err": err,
208 "IntfId": i,
209 }).Fatal("cannot-get-pon-configuration")
210 }
211
212 tech, err := common.PonTechnologyFromString(ponConf.Technology)
213 if err != nil {
214 oltLogger.WithFields(log.Fields{
215 "Err": err,
216 "IntfId": i,
217 }).Fatal("unkown-pon-port-technology")
218 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800219
220 // initialize the resource maps for every PON Ports
221 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
222 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
223
Elia Battistonb7bea222022-02-18 16:25:00 +0100224 p := CreatePonPort(&olt, uint32(i), tech)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700225
Matteo Scandolo4a036262020-08-17 15:56:13 -0700226 // create ONU devices
Elia Battistonb7bea222022-02-18 16:25:00 +0100227 if (ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1) < uint32(olt.NumOnuPerPon) {
228 oltLogger.WithFields(log.Fields{
229 "OnuRange": ponConf.OnuRange,
230 "RangeSize": ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1,
231 "NumOnuPerPon": olt.NumOnuPerPon,
232 "IntfId": i,
233 }).Fatal("onus-per-pon-bigger-than-resource-range-size")
234 }
235
Matteo Scandolo4a036262020-08-17 15:56:13 -0700236 for j := 0; j < olt.NumOnuPerPon; j++ {
237 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700238 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700239
Matteo Scandolo4a036262020-08-17 15:56:13 -0700240 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700241 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700242 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700243 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100244
Shrey Baid688b4242020-07-10 20:40:10 +0530245 if !isMock {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100246 if err := olt.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700247 log.Errorf("Error initializing OLT: %v", err)
248 return nil
249 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100250 }
251
Pragya Arya324337e2020-02-20 14:35:08 +0530252 if olt.PublishEvents {
253 log.Debugf("BBSim event publishing is enabled")
254 // Create a channel to write event messages
255 olt.EventChannel = make(chan common.Event, 100)
256 }
257
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700258 return &olt
259}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700260
Shrey Baid688b4242020-07-10 20:40:10 +0530261func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100262
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000263 if o.OltServer == nil {
264 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100265 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800266 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100267 }
268
269 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800270 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100271
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100272 // FIXME we are assuming we have only one NNI
273 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800274 // NOTE we want to make sure the state is down when we initialize the OLT,
275 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
276 // in-band management
277 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100278 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800279
280 for ponId := range o.Pons {
281 // initialize the resource maps for every PON Ports
282 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
283 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
284 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700285}
286
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800287func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100288
Matteo Scandolo96f89192021-03-12 13:17:26 -0800289 o.PreviouslyConnected = false
290
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700291 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700292 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800293
294 oltLogger.WithFields(log.Fields{
295 "oltId": o.ID,
296 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
297
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100298 if o.InternalState.Is(OltInternalStateEnabled) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700299 oltLogger.WithFields(log.Fields{
300 "oltId": o.ID,
301 }).Info("This is an OLT soft reboot")
302 softReboot = true
303 }
304
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800305 // transition internal state to deleted
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100306 if err := o.InternalState.Event(OltInternalTxDelete); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800307 oltLogger.WithFields(log.Fields{
308 "oltId": o.ID,
309 }).Errorf("Error deleting OLT: %v", err)
310 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100311 }
312
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700313 if softReboot {
314 for _, pon := range o.Pons {
315 if pon.InternalState.Current() == "enabled" {
316 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800317 msg := types.Message{
318 Type: types.PonIndication,
319 Data: types.PonIndicationMessage{
320 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700321 PonPortID: pon.ID,
322 },
323 }
324 o.channel <- msg
325 }
326
327 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100328 err := onu.InternalState.Event(OnuTxDisable)
329 oltLogger.WithFields(log.Fields{
330 "oltId": o.ID,
331 "onuId": onu.ID,
332 }).Errorf("Error disabling ONUs on OLT soft reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700333 }
334 }
335 } else {
336 // PONs are already handled in the Disable call
337 for _, pon := range olt.Pons {
338 // ONUs are not automatically disabled when a PON goes down
339 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
340 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100341 err := onu.InternalState.Event(OnuTxDisable)
342 oltLogger.WithFields(log.Fields{
343 "oltId": o.ID,
344 "onuId": onu.ID,
Matteo Scandolofbb94ae2022-04-14 14:17:47 -0700345 "OnuSn": onu.Sn(),
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100346 }).Errorf("Error disabling ONUs on OLT reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700347 }
Pragya Arya2225f202020-01-29 18:05:01 +0530348 }
349 }
350
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700351 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
352 o.StopOltServer()
353
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100354 // terminate the OLT's processOltMessages go routine
355 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700356
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100357 oltLogger.WithFields(log.Fields{
358 "oltId": o.ID,
359 }).Infof("Waiting OLT restart for... (%ds)", rebootDelay)
360
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100361 //Prevents Enable to progress before the reboot is completed (VOL-4616)
362 o.Lock()
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700363 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100364 time.Sleep(time.Duration(rebootDelay) * time.Second)
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100365 o.Unlock()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100366
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100367 if err := o.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800368 oltLogger.WithFields(log.Fields{
369 "oltId": o.ID,
370 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100371 return err
372 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800373 oltLogger.WithFields(log.Fields{
374 "oltId": o.ID,
375 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100376 return nil
377}
378
379// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800380func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700381 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700382 lis, err := net.Listen("tcp", address)
383 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700384 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700385 }
386 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100387
Matteo Scandolo4747d292019-08-05 11:50:18 -0700388 openolt.RegisterOpenoltServer(grpcServer, o)
389
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100390 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700391
Shrey Baid688b4242020-07-10 20:40:10 +0530392 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100393 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700394
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100395 return grpcServer, nil
396}
397
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800398// StartOltServer will create the grpc server that VOLTHA uses
399// to communicate with the device
400func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
401 oltServer, err := o.newOltServer()
402 if err != nil {
403 oltLogger.WithFields(log.Fields{
404 "err": err,
405 }).Error("Cannot OLT gRPC server")
406 return nil, err
407 }
408 return oltServer, nil
409}
410
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100411// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800412func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000413 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800414 oltLogger.WithFields(log.Fields{
415 "oltId": o.SerialNumber,
416 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000417 o.OltServer.Stop()
418 o.OltServer = nil
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100419 } else {
420 oltLogger.WithFields(log.Fields{
421 "oltId": o.SerialNumber,
422 }).Warnf("OLT gRPC server is already stopped")
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700423 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700424}
425
426// Device Methods
427
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100428// Enable implements the OpenOLT EnableIndicationServer functionality
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100429func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700430 oltLogger.Debug("Enable OLT called")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100431
432 if o.InternalState.Is(OltInternalStateDeleted) {
433 err := fmt.Errorf("Cannot enable OLT while it is rebooting")
434 oltLogger.WithFields(log.Fields{
435 "oltId": o.SerialNumber,
436 "internalState": o.InternalState.Current(),
437 }).Error(err)
438 return err
439 }
440
Pragya Arya2225f202020-01-29 18:05:01 +0530441 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700442
David Bainbridge103cf022019-12-16 20:11:35 +0000443 // If enabled has already been called then an enabled context has
444 // been created. If this is the case then we want to cancel all the
445 // proessing loops associated with that enable before we recreate
446 // new ones
447 o.Lock()
448 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700449 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000450 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530451 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700452 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000453 }
454 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
455 o.Unlock()
456
Matteo Scandolo4747d292019-08-05 11:50:18 -0700457 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700458
Matteo Scandolo4a036262020-08-17 15:56:13 -0700459 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530460
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100461 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700462 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000463 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700464
465 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800466 oltMsg := types.Message{
467 Type: types.OltIndication,
468 Data: types.OltIndicationMessage{
469 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700470 },
471 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100472 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700473
474 // send NNI Port Indications
475 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800476 msg := types.Message{
477 Type: types.NniIndication,
478 Data: types.NniIndicationMessage{
479 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700480 NniPortID: nni.ID,
481 },
482 }
483 o.channel <- msg
484 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100485
Shrey Baid688b4242020-07-10 20:40:10 +0530486 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530487 for _, pon := range o.Pons {
488 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800489 msg := types.Message{
490 Type: types.PonIndication,
491 Data: types.PonIndicationMessage{
492 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530493 PonPortID: pon.ID,
494 },
495 }
496 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000497 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700498 // when the enableContext was canceled the ONUs stopped listening on the channel
499 for _, onu := range pon.Onus {
500 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
501
502 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700503 for _, uni := range onu.UniPorts {
504 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700505 }
506 }
Pragya Arya2225f202020-01-29 18:05:01 +0530507 }
508 } else {
509
510 // 1. controlledActivation == Default: Send both PON and ONUs indications
511 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
512
513 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
514 // send PON Port indications
515 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800516 msg := types.Message{
517 Type: types.PonIndication,
518 Data: types.PonIndicationMessage{
519 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530520 PonPortID: pon.ID,
521 },
522 }
523 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700524 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700525 }
526 }
527
Pragya Arya996a0892020-03-09 21:47:52 +0530528 if !o.enablePerf {
529 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700530 wg.Add(1)
531 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530532 }
533
Matteo Scandolo4747d292019-08-05 11:50:18 -0700534 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700535 oltLogger.WithFields(log.Fields{
536 "stream": stream,
537 }).Debug("OpenOLT Stream closed")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100538
539 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700540}
541
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700542func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530543 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700544
545loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530546 for {
547 select {
548 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
549 // send NNI port stats
550 for _, port := range o.Nnis {
551 incrementStat := true
552 if port.OperState.Current() == "down" {
553 incrementStat = false
554 }
555 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700556 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530557 }
558
559 // send PON port stats
560 for _, port := range o.Pons {
561 incrementStat := true
562 // do not increment port stats if PON port is down or no ONU is activated on PON port
563 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
564 incrementStat = false
565 }
566 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700567 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530568 }
569 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700570 oltLogger.Debug("Stop sending port stats")
571 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530572 }
Pragya Arya996a0892020-03-09 21:47:52 +0530573 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700574 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530575}
576
Matteo Scandolo4747d292019-08-05 11:50:18 -0700577// Helpers method
578
Matteo Scandolof9d43412021-01-12 11:11:34 -0800579func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
580
581 switch interfaceType {
582 case "nni":
583 if !o.HasNni(interfaceId) {
584 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
585 }
586
587 case "pon":
588 if !o.HasPon(interfaceId) {
589 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
590 }
591 }
592
593 alarmIndication := &openolt.AlarmIndication{
594 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
595 Status: alarmStatus,
596 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
597 }},
598 }
599
600 msg := types.Message{
601 Type: types.AlarmIndication,
602 Data: alarmIndication,
603 }
604
605 o.channel <- msg
606
607 return nil
608}
609
610func (o *OltDevice) HasNni(id uint32) bool {
611 for _, intf := range o.Nnis {
612 if intf.ID == id {
613 return true
614 }
615 }
616 return false
617}
618
619func (o *OltDevice) HasPon(id uint32) bool {
620 for _, intf := range o.Pons {
621 if intf.ID == id {
622 return true
623 }
624 }
625 return false
626}
627
Shrey Baid688b4242020-07-10 20:40:10 +0530628func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700629 for _, pon := range o.Pons {
630 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700631 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700632 }
633 }
Shrey Baid688b4242020-07-10 20:40:10 +0530634 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700635}
636
Shrey Baid688b4242020-07-10 20:40:10 +0530637func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700638 for _, nni := range o.Nnis {
639 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700640 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700641 }
642 }
Shrey Baid688b4242020-07-10 20:40:10 +0530643 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644}
645
Scott Baker41724b82020-01-21 19:54:53 -0800646func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
647 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
648 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
649 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
650 return
651 }
652
653 oltLogger.WithFields(log.Fields{
654 "AlarmIndication": alarmInd,
655 }).Debug("Sent Indication_AlarmInd")
656}
657
Matteo Scandolof9d43412021-01-12 11:11:34 -0800658func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700659 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
660 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700661 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800662 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700663 }
664
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700665 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666 "OperState": msg.OperState,
667 }).Debug("Sent Indication_OltInd")
668}
669
Matteo Scandolof9d43412021-01-12 11:11:34 -0800670func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700671 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800672 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800673 if err := nni.OperState.Event("enable"); err != nil {
674 log.WithFields(log.Fields{
675 "Type": nni.Type,
676 "IntfId": nni.ID,
677 "OperState": nni.OperState.Current(),
678 }).Errorf("Can't move NNI Port to enabled state: %v", err)
679 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800680 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800681 if err := nni.OperState.Event("disable"); err != nil {
682 log.WithFields(log.Fields{
683 "Type": nni.Type,
684 "IntfId": nni.ID,
685 "OperState": nni.OperState.Current(),
686 }).Errorf("Can't move NNI Port to disable state: %v", err)
687 }
688 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700689 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700690 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700691 Type: nni.Type,
692 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700693 OperState: nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100694 Speed: o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700695 }}
696
697 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700698 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800699 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700700 }
701
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700702 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700703 "Type": nni.Type,
704 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700705 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100706 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700707 }).Debug("Sent Indication_IntfOperInd for NNI")
708}
709
Pragya Arya2225f202020-01-29 18:05:01 +0530710func (o *OltDevice) sendPonIndication(ponPortID uint32) {
711
Matteo Scandolo4a036262020-08-17 15:56:13 -0700712 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530713 pon, _ := o.GetPonById(ponPortID)
714 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700715 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700716 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700717 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700718 }}
719
720 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700721 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800722 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700723 }
724
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700725 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700726 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700727 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700728 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700729
Pragya Arya2225f202020-01-29 18:05:01 +0530730 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700731 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700732 Type: pon.Type,
733 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700734 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700735 }}
736
737 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700738 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800739 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700740 }
741
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700742 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700743 "Type": pon.Type,
744 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700745 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700746 }).Debug("Sent Indication_IntfOperInd for PON")
747}
748
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700749func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100750 if o.InternalState.Current() == OltInternalStateEnabled {
Shrey Baid55f328c2020-07-07 19:20:42 +0530751 oltLogger.WithFields(log.Fields{
752 "Type": portType,
753 "IntfId": portID,
754 }).Trace("Sending port stats")
755 stats.IntfId = InterfaceIDToPortNo(portID, portType)
756 data := &openolt.Indication_PortStats{
757 PortStats: stats,
758 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700759
Shrey Baid55f328c2020-07-07 19:20:42 +0530760 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
761 oltLogger.Errorf("Failed to send PortStats: %v", err)
762 return
763 }
Pragya Arya996a0892020-03-09 21:47:52 +0530764 }
765}
766
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100767// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700768func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
769 oltLogger.WithFields(log.Fields{
770 "stream": stream,
771 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000772 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700773
David Bainbridge103cf022019-12-16 20:11:35 +0000774loop:
775 for {
776 select {
777 case <-ctx.Done():
778 oltLogger.Debug("OLT Indication processing canceled via context")
779 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700780 // do not terminate this loop if the stream is closed,
781 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
782 //case <-stream.Context().Done():
783 // oltLogger.Debug("OLT Indication processing canceled via stream context")
784 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000785 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700786 if !ok {
787 if ctx.Err() != nil {
788 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
789 }
790 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000791 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700792 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700793
David Bainbridge103cf022019-12-16 20:11:35 +0000794 oltLogger.WithFields(log.Fields{
795 "oltId": o.ID,
796 "messageType": message.Type,
797 }).Trace("Received message")
798
799 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800800 case types.OltIndication:
801 msg, _ := message.Data.(types.OltIndicationMessage)
802 if msg.OperState == types.UP {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100803 _ = o.InternalState.Event(OltInternalTxEnable)
Shrey Baid688b4242020-07-10 20:40:10 +0530804 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800805 } else if msg.OperState == types.DOWN {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100806 _ = o.InternalState.Event(OltInternalTxDisable)
Shrey Baid688b4242020-07-10 20:40:10 +0530807 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000808 }
809 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800810 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800811 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
812 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800813 case types.NniIndication:
814 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000815 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800816 case types.PonIndication:
817 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530818 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800819 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530820 if err := pon.OperState.Event("enable"); err != nil {
821 oltLogger.WithFields(log.Fields{
822 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800823 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530824 }).Error("Can't Enable Oper state for PON Port")
825 }
826 if err := pon.InternalState.Event("enable"); err != nil {
827 oltLogger.WithFields(log.Fields{
828 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800829 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530830 }).Error("Can't Enable Internal state for PON Port")
831 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800832 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530833 if err := pon.OperState.Event("disable"); err != nil {
834 oltLogger.WithFields(log.Fields{
835 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800836 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530837 }).Error("Can't Disable Oper state for PON Port")
838 }
839 if err := pon.InternalState.Event("disable"); err != nil {
840 oltLogger.WithFields(log.Fields{
841 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800842 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530843 }).Error("Can't Disable Internal state for PON Port")
844 }
Pragya Arya2225f202020-01-29 18:05:01 +0530845 }
David Bainbridge103cf022019-12-16 20:11:35 +0000846 default:
847 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
848 }
849 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700850 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100851 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700852 oltLogger.WithFields(log.Fields{
853 "stream": stream,
854 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700855}
856
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700857// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530858func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700859 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700860 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700861 for _, pon := range o.Pons {
862 for _, onu := range pon.Onus {
863 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700864 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700865 }
866 }
867 }
868
Shrey Baid688b4242020-07-10 20:40:10 +0530869 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700870}
871
William Kurkian9dadc5b2019-10-22 13:51:57 -0400872// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530873func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700874 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400875 // memoizing it will remove the bottleneck
876 for _, pon := range o.Pons {
877 if pon.ID == intfId {
878 for _, onu := range pon.Onus {
879 if onu.ID == onuId {
880 return onu, nil
881 }
882 }
883 }
884 }
Shrey Baid688b4242020-07-10 20:40:10 +0530885 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400886}
887
Matteo Scandolo4a036262020-08-17 15:56:13 -0700888// returns a Service with a given Mac Address
889func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700890 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700891 // memoizing it will remove the bottleneck
892 for _, pon := range o.Pons {
893 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700894 s, err := onu.findServiceByMacAddress(mac)
895 if err == nil {
896 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700897 }
898 }
899 }
900
Matteo Scandolo4a036262020-08-17 15:56:13 -0700901 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700902}
903
Matteo Scandolo4747d292019-08-05 11:50:18 -0700904// GRPC Endpoints
905
Shrey Baid688b4242020-07-10 20:40:10 +0530906func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700907
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700908 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800909
Matteo Scandolo8a574812021-05-20 15:18:53 -0700910 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800911 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
912 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
913
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700914 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700915
916 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
917 oltLogger.WithFields(log.Fields{
918 "OnuSn": _onu.Sn(),
919 }).Info("Received ActivateOnu call from VOLTHA")
920
William Kurkian0418bc82019-11-06 12:16:24 -0500921 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700922
Matteo Scandolocedde462021-03-09 17:37:16 -0800923 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700924 oltLogger.WithFields(log.Fields{
925 "IntfId": _onu.PonPortID,
926 "OnuSn": _onu.Sn(),
927 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800928 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700929 }
930
931 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
932
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700933 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700934}
935
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800936func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700937 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700938 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700939}
940
Shrey Baid688b4242020-07-10 20:40:10 +0530941func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530942 oltLogger.WithFields(log.Fields{
943 "IntfId": onu.IntfId,
944 "OnuId": onu.OnuId,
945 }).Info("Received DeleteOnu call from VOLTHA")
946
947 pon, err := o.GetPonById(onu.IntfId)
948 if err != nil {
949 oltLogger.WithFields(log.Fields{
950 "OnuId": onu.OnuId,
951 "IntfId": onu.IntfId,
952 "err": err,
953 }).Error("Can't find PonPort")
954 }
955 _onu, err := pon.GetOnuById(onu.OnuId)
956 if err != nil {
957 oltLogger.WithFields(log.Fields{
958 "OnuId": onu.OnuId,
959 "IntfId": onu.IntfId,
960 "err": err,
961 }).Error("Can't find Onu")
962 }
963
Matteo Scandolocedde462021-03-09 17:37:16 -0800964 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530965 oltLogger.WithFields(log.Fields{
966 "IntfId": _onu.PonPortID,
967 "OnuSn": _onu.Sn(),
968 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800969 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530970 }
971
Hardik Windlassad790cb2020-06-17 21:26:22 +0530972 // ONU Re-Discovery
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100973 if o.InternalState.Current() == OltInternalStateEnabled && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530974 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530975 }
976
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700977 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700978}
979
Shrey Baid688b4242020-07-10 20:40:10 +0530980func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700981 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800982 oltLogger.WithFields(log.Fields{
983 "oltId": o.ID,
984 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530985 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800986
Matteo Scandolo401503a2019-12-11 14:48:14 -0800987 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530988 if pon.InternalState.Current() == "enabled" {
989 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800990 msg := types.Message{
991 Type: types.PonIndication,
992 Data: types.PonIndicationMessage{
993 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530994 PonPortID: pon.ID,
995 },
996 }
997 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800998 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800999 }
1000
Matteo Scandolo401503a2019-12-11 14:48:14 -08001001 // Note that we are not disabling the NNI as the real OLT does not.
1002 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001003
1004 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001005 oltMsg := types.Message{
1006 Type: types.OltIndication,
1007 Data: types.OltIndicationMessage{
1008 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001009 },
1010 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001011 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001012
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001013 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001014}
1015
Shrey Baid688b4242020-07-10 20:40:10 +05301016func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301017 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001018 ponID := intf.GetIntfId()
1019 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001020
Matteo Scandolof9d43412021-01-12 11:11:34 -08001021 msg := types.Message{
1022 Type: types.PonIndication,
1023 Data: types.PonIndicationMessage{
1024 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001025 PonPortID: ponID,
1026 },
1027 }
1028 o.channel <- msg
1029
1030 for _, onu := range pon.Onus {
1031
Matteo Scandolof9d43412021-01-12 11:11:34 -08001032 onuIndication := types.OnuIndicationMessage{
1033 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001034 PonPortID: ponID,
1035 OnuID: onu.ID,
1036 OnuSN: onu.SerialNumber,
1037 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001038 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001039
1040 }
1041
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001042 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001043}
1044
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001045func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001046 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301047 publishEvent("OLT-enable-received", -1, -1, "")
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001048 return o.Enable(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001049}
1050
Shrey Baid688b4242020-07-10 20:40:10 +05301051func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301052 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301053 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001054 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001055
Matteo Scandolof9d43412021-01-12 11:11:34 -08001056 msg := types.Message{
1057 Type: types.PonIndication,
1058 Data: types.PonIndicationMessage{
1059 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301060 PonPortID: ponID,
1061 },
1062 }
1063 o.channel <- msg
1064
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001065 for _, onu := range pon.Onus {
1066
Matteo Scandolof9d43412021-01-12 11:11:34 -08001067 onuIndication := types.OnuIndicationMessage{
1068 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001069 PonPortID: ponID,
1070 OnuID: onu.ID,
1071 OnuSN: onu.SerialNumber,
1072 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001073 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001074
1075 }
1076
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001077 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001078}
1079
Shrey Baid688b4242020-07-10 20:40:10 +05301080func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001081 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001082 "IntfId": flow.AccessIntfId,
1083 "OnuId": flow.OnuId,
1084 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001085 "InnerVlan": flow.Classifier.IVid,
1086 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001087 "FlowType": flow.FlowType,
1088 "FlowId": flow.FlowId,
1089 "UniID": flow.UniId,
1090 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301091 }).Tracef("OLT receives FlowAdd")
1092
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001093 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301094 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001095 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001096 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301097 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001098
1099 if flow.AccessIntfId == -1 {
1100 oltLogger.WithFields(log.Fields{
1101 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001102 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001103 } else if flow.FlowType == "multicast" {
1104 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001105 "Cookie": flow.Cookie,
1106 "DstPort": flow.Classifier.DstPort,
1107 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1108 "FlowId": flow.FlowId,
1109 "FlowType": flow.FlowType,
1110 "GemportId": flow.GemportId,
1111 "InnerVlan": flow.Classifier.IVid,
1112 "IntfId": flow.AccessIntfId,
1113 "IpProto": flow.Classifier.IpProto,
1114 "OnuId": flow.OnuId,
1115 "OuterVlan": flow.Classifier.OVid,
1116 "PortNo": flow.PortNo,
1117 "SrcPort": flow.Classifier.SrcPort,
1118 "UniID": flow.UniId,
1119 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001120 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001121 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001122 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001123 if err != nil {
1124 oltLogger.WithFields(log.Fields{
1125 "OnuId": flow.OnuId,
1126 "IntfId": flow.AccessIntfId,
1127 "err": err,
1128 }).Error("Can't find PonPort")
1129 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001130 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001131 if err != nil {
1132 oltLogger.WithFields(log.Fields{
1133 "OnuId": flow.OnuId,
1134 "IntfId": flow.AccessIntfId,
1135 "err": err,
1136 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001137 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001138 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001139
1140 // if the ONU is disabled reject the flow
1141 // as per VOL-4061 there is a small window during which the ONU is disabled
1142 // but the port has not been reported as down to ONOS
1143 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1144 oltLogger.WithFields(log.Fields{
1145 "OnuId": flow.OnuId,
1146 "IntfId": flow.AccessIntfId,
1147 "Flow": flow,
1148 "SerialNumber": onu.Sn(),
1149 "InternalState": onu.InternalState.Current(),
1150 }).Error("rejected-flow-because-of-onu-state")
1151 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1152 }
1153
Pragya Arya8bdb4532020-03-02 17:08:09 +05301154 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001155 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301156 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001157 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001158 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301159 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301160 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001161
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001162 // validate that the flow reference correct IDs (Alloc, Gem)
1163 if err := o.validateFlow(flow); err != nil {
1164 oltLogger.WithFields(log.Fields{
1165 "OnuId": flow.OnuId,
1166 "IntfId": flow.AccessIntfId,
1167 "Flow": flow,
1168 "SerialNumber": onu.Sn(),
1169 "err": err,
1170 }).Error("invalid-flow-for-onu")
1171 return nil, err
1172 }
1173
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001174 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001175 o.storeAllocId(flow)
1176
Matteo Scandolof9d43412021-01-12 11:11:34 -08001177 msg := types.Message{
1178 Type: types.FlowAdd,
1179 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001180 PonPortID: pon.ID,
1181 OnuID: onu.ID,
1182 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001183 },
1184 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001185 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001186 }
1187
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001188 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001189}
1190
Pragya Arya8bdb4532020-03-02 17:08:09 +05301191// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301192func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001193
Pragya Arya8bdb4532020-03-02 17:08:09 +05301194 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001195 "AllocId": flow.AllocId,
1196 "Cookie": flow.Cookie,
1197 "FlowId": flow.FlowId,
1198 "FlowType": flow.FlowType,
1199 "GemportId": flow.GemportId,
1200 "IntfId": flow.AccessIntfId,
1201 "OnuId": flow.OnuId,
1202 "PortNo": flow.PortNo,
1203 "UniID": flow.UniId,
1204 "ReplicateFlow": flow.ReplicateFlow,
1205 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001206 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301207
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001208 olt.freeGemPortId(flow)
1209 olt.freeAllocId(flow)
1210
Pragya Arya8bdb4532020-03-02 17:08:09 +05301211 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001212 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301213 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001214 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301215 if !ok {
1216 oltLogger.Errorf("Flow %v not found", flow)
1217 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1218 }
1219
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001220 storedFlow := storedFlowIntf.(openolt.Flow)
1221
Pragya Arya8bdb4532020-03-02 17:08:09 +05301222 // if its ONU flow remove it from ONU also
1223 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001224 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1225 if err != nil {
1226 oltLogger.WithFields(log.Fields{
1227 "OnuId": storedFlow.OnuId,
1228 "IntfId": storedFlow.AccessIntfId,
1229 "PONs": olt.Pons,
1230 "err": err,
1231 }).Error("PON-port-not-found")
1232 return new(openolt.Empty), nil
1233 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301234 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1235 if err != nil {
1236 oltLogger.WithFields(log.Fields{
1237 "OnuId": storedFlow.OnuId,
1238 "IntfId": storedFlow.AccessIntfId,
1239 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001240 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301241 return new(openolt.Empty), nil
1242 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001243 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001244 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301245 }
1246
1247 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001248 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301249 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001250
1251 if flow.AccessIntfId == -1 {
1252 oltLogger.WithFields(log.Fields{
1253 "FlowId": flow.FlowId,
1254 }).Debug("Removing OLT flow")
1255 } else if flow.FlowType == "multicast" {
1256 oltLogger.WithFields(log.Fields{
1257 "FlowId": flow.FlowId,
1258 }).Debug("Removing OLT multicast flow")
1259 } else {
1260
1261 onu, err := o.GetOnuByFlowId(flow.FlowId)
1262 if err != nil {
1263 oltLogger.WithFields(log.Fields{
1264 "OnuId": flow.OnuId,
1265 "IntfId": flow.AccessIntfId,
1266 "err": err,
1267 }).Error("Can't find Onu")
1268 return nil, err
1269 }
1270
Matteo Scandolof9d43412021-01-12 11:11:34 -08001271 msg := types.Message{
1272 Type: types.FlowRemoved,
1273 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301274 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001275 },
1276 }
1277 onu.Channel <- msg
1278 }
1279
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001280 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001281}
1282
Shrey Baid688b4242020-07-10 20:40:10 +05301283func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001284 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1285 oltLogger.WithFields(log.Fields{
1286 "signature": res.HeartbeatSignature,
1287 }).Trace("HeartbeatCheck")
1288 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001289}
1290
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001291func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001292 for _, pon := range o.Pons {
1293 for _, onu := range pon.Onus {
1294 for _, fId := range onu.FlowIds {
1295 if fId == flowId {
1296 return onu, nil
1297 }
1298 }
1299 }
1300 }
Shrey Baid688b4242020-07-10 20:40:10 +05301301 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001302}
1303
Shrey Baid688b4242020-07-10 20:40:10 +05301304func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolocedde462021-03-09 17:37:16 -08001305 devinfo := &openolt.DeviceInfo{
1306 Vendor: common.Config.Olt.Vendor,
1307 Model: common.Config.Olt.Model,
1308 HardwareVersion: common.Config.Olt.HardwareVersion,
1309 FirmwareVersion: common.Config.Olt.FirmwareVersion,
Matteo Scandolocedde462021-03-09 17:37:16 -08001310 PonPorts: uint32(o.NumPon),
Matteo Scandolocedde462021-03-09 17:37:16 -08001311 DeviceSerialNumber: o.SerialNumber,
1312 DeviceId: common.Config.Olt.DeviceId,
1313 PreviouslyConnected: o.PreviouslyConnected,
Elia Battistonb7bea222022-02-18 16:25:00 +01001314 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{},
1315 }
1316
1317 for _, resRange := range common.PonsConfig.Ranges {
1318 intfIDs := []uint32{}
1319 for i := resRange.PonRange.StartId; i <= resRange.PonRange.EndId; i++ {
1320 intfIDs = append(intfIDs, uint32(i))
1321 }
1322
1323 devinfo.Ranges = append(devinfo.Ranges, &openolt.DeviceInfo_DeviceResourceRanges{
1324 IntfIds: intfIDs,
1325 Technology: resRange.Technology,
1326 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1327 {
1328 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1329 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1330 Start: resRange.OnuRange.StartId,
1331 End: resRange.OnuRange.EndId,
1332 },
1333 {
1334 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1335 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1336 Start: resRange.AllocIdRange.StartId,
1337 End: resRange.AllocIdRange.EndId,
1338 },
1339 {
1340 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1341 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1342 Start: resRange.GemportRange.StartId,
1343 End: resRange.GemportRange.EndId,
Matteo Scandolocedde462021-03-09 17:37:16 -08001344 },
1345 },
Elia Battistonb7bea222022-02-18 16:25:00 +01001346 })
Matteo Scandolocedde462021-03-09 17:37:16 -08001347 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001348
1349 oltLogger.WithFields(log.Fields{
1350 "Vendor": devinfo.Vendor,
1351 "Model": devinfo.Model,
1352 "HardwareVersion": devinfo.HardwareVersion,
1353 "FirmwareVersion": devinfo.FirmwareVersion,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001354 "PonPorts": devinfo.PonPorts,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001355 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1356 "DeviceId": devinfo.DeviceId,
1357 "PreviouslyConnected": devinfo.PreviouslyConnected,
1358 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1359
1360 // once we connect, set the flag
1361 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001362
1363 return devinfo, nil
1364}
1365
Shrey Baid688b4242020-07-10 20:40:10 +05301366func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001367 pon, err := o.GetPonById(omci_msg.IntfId)
1368 if err != nil {
1369 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001370 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001371 "onu_id": omci_msg.OnuId,
1372 "pon_id": omci_msg.IntfId,
1373 }).Error("pon ID not found")
1374 return nil, err
1375 }
1376
1377 onu, err := pon.GetOnuById(omci_msg.OnuId)
1378 if err != nil {
1379 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001380 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001381 "onu_id": omci_msg.OnuId,
1382 "pon_id": omci_msg.IntfId,
1383 }).Error("onu ID not found")
1384 return nil, err
1385 }
1386
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001387 oltLogger.WithFields(log.Fields{
1388 "IntfId": onu.PonPortID,
1389 "OnuId": onu.ID,
1390 "OnuSn": onu.Sn(),
1391 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001392 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1393 if err != nil {
1394 log.WithFields(log.Fields{
1395 "IntfId": onu.PonPortID,
1396 "SerialNumber": onu.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001397 "omciPacket": hex.EncodeToString(omci_msg.Pkt),
Matteo Scandolob5913142021-03-19 16:10:18 -07001398 "err": err.Error(),
1399 }).Error("cannot-parse-OMCI-packet")
1400 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001401 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001402 if onu.InternalState.Current() == OnuStateDisabled {
1403 // if the ONU is disabled just drop the message
1404 log.WithFields(log.Fields{
1405 "IntfId": onu.PonPortID,
1406 "SerialNumber": onu.Sn(),
1407 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1408 "omciPkt": omciPkt,
1409 "omciMsgType": omciMsg.MessageType,
1410 }).Warn("dropping-omci-message")
1411 } else {
1412 msg := types.Message{
1413 Type: types.OMCI,
1414 Data: types.OmciMessage{
1415 OnuSN: onu.SerialNumber,
1416 OnuID: onu.ID,
1417 OmciMsg: omciMsg,
1418 OmciPkt: omciPkt,
1419 },
1420 }
1421 onu.Channel <- msg
1422 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001423 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001424}
1425
Matteo Scandolo8a574812021-05-20 15:18:53 -07001426// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301427func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001428 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001429 if err != nil {
1430 oltLogger.WithFields(log.Fields{
1431 "OnuId": onuPkt.OnuId,
1432 "IntfId": onuPkt.IntfId,
1433 "err": err,
1434 }).Error("Can't find PonPort")
1435 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001436 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001437 if err != nil {
1438 oltLogger.WithFields(log.Fields{
1439 "OnuId": onuPkt.OnuId,
1440 "IntfId": onuPkt.IntfId,
1441 "err": err,
1442 }).Error("Can't find Onu")
1443 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001444
Matteo Scandolo075b1892019-10-07 12:11:07 -07001445 oltLogger.WithFields(log.Fields{
1446 "IntfId": onu.PonPortID,
1447 "OnuId": onu.ID,
1448 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001449 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001450 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001451
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001452 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001453
1454 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001455 if err != nil {
1456 onuLogger.WithFields(log.Fields{
1457 "IntfId": onu.PonPortID,
1458 "OnuId": onu.ID,
1459 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001460 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001461 }).Error("Can't find pktType in packet, droppint it")
1462 return new(openolt.Empty), nil
1463 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001464
Matteo Scandolo4a036262020-08-17 15:56:13 -07001465 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001466 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001467 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001468 "IntfId": onu.PonPortID,
1469 "OnuId": onu.ID,
1470 "OnuSn": onu.Sn(),
1471 "Pkt": rawpkt.Data(),
1472 }).Error("Can't find Dst MacAddress in packet, droppint it")
1473 return new(openolt.Empty), nil
1474 }
1475
Matteo Scandolof9d43412021-01-12 11:11:34 -08001476 msg := types.Message{
1477 Type: types.OnuPacketOut,
1478 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001479 IntfId: onuPkt.IntfId,
1480 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001481 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001482 Packet: rawpkt,
1483 Type: pktType,
1484 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001485 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001486 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001487
Matteo Scandolo075b1892019-10-07 12:11:07 -07001488 onu.Channel <- msg
1489
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001490 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001491}
1492
Shrey Baid688b4242020-07-10 20:40:10 +05301493func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001494
1495 // OLT Reboot is called in two cases:
1496 // - 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)
1497 // - when an OLT needs to be rebooted (voltcl device reboot)
1498
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001499 oltLogger.WithFields(log.Fields{
1500 "oltId": o.ID,
1501 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301502 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301503 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001504 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001505}
1506
Shrey Baid688b4242020-07-10 20:40:10 +05301507func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301508 oltLogger.WithFields(log.Fields{
1509 "oltId": o.ID,
1510 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301511 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301512
Pragya Arya2225f202020-01-29 18:05:01 +05301513 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001514 oltMsg := types.Message{
1515 Type: types.OltIndication,
1516 Data: types.OltIndicationMessage{
1517 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301518 },
Pragya Arya1881df02020-01-29 18:05:01 +05301519 }
Pragya Arya2225f202020-01-29 18:05:01 +05301520 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301521
Pragya Arya2225f202020-01-29 18:05:01 +05301522 for _, pon := range o.Pons {
1523 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001524 msg := types.Message{
1525 Type: types.PonIndication,
1526 Data: types.PonIndicationMessage{
1527 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301528 PonPortID: pon.ID,
1529 },
1530 }
1531 o.channel <- msg
1532 }
1533 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001534
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001535 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001536}
1537
Shrey Baid688b4242020-07-10 20:40:10 +05301538func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001539 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1540
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001541 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1542
1543 if err != nil {
1544 return nil, err
1545 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001546 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001547}
1548
Shrey Baid688b4242020-07-10 20:40:10 +05301549func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001550 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001551 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001552}
1553
Shrey Baid688b4242020-07-10 20:40:10 +05301554func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001555 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001556 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001557}
1558
Shrey Baid688b4242020-07-10 20:40:10 +05301559func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001560 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001561 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001562}
1563
Shrey Baid688b4242020-07-10 20:40:10 +05301564func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001565 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001566 return new(openolt.Empty), nil
1567}
1568
Matteo Scandolo8a574812021-05-20 15:18:53 -07001569func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1570 oltLogger.WithFields(log.Fields{
1571 "OnuId": tq.OnuId,
1572 "IntfId": tq.IntfId,
1573 "OnuPortNo": tq.PortNo,
1574 "UniId": tq.UniId,
1575 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001576 return new(openolt.Empty), nil
1577}
1578
Matteo Scandolo8a574812021-05-20 15:18:53 -07001579func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301580 oltLogger.WithFields(log.Fields{
1581 "OnuId": trafficSchedulers.OnuId,
1582 "IntfId": trafficSchedulers.IntfId,
1583 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001584 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301585 }).Info("received CreateTrafficSchedulers")
1586
1587 if !s.enablePerf {
1588 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1589 if err != nil {
1590 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1591 return new(openolt.Empty), err
1592 }
1593 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1594 if err != nil {
1595 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1596 return new(openolt.Empty), err
1597 }
1598 onu.TrafficSchedulers = trafficSchedulers
1599 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001600 return new(openolt.Empty), nil
1601}
1602
Shrey Baid688b4242020-07-10 20:40:10 +05301603func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301604 oltLogger.WithFields(log.Fields{
1605 "OnuId": trafficSchedulers.OnuId,
1606 "IntfId": trafficSchedulers.IntfId,
1607 "OnuPortNo": trafficSchedulers.PortNo,
1608 }).Info("received RemoveTrafficSchedulers")
1609 if !s.enablePerf {
1610 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1611 if err != nil {
1612 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1613 return new(openolt.Empty), err
1614 }
1615 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1616 if err != nil {
1617 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1618 return new(openolt.Empty), err
1619 }
1620
1621 onu.TrafficSchedulers = nil
1622 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001623 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001624}
Scott Baker41724b82020-01-21 19:54:53 -08001625
Matteo Scandolo618a6582020-09-09 12:21:29 -07001626func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1627 oltLogger.WithFields(log.Fields{
1628 "GroupId": group.GroupId,
1629 "Command": group.Command,
1630 "Members": group.Members,
1631 "Action": group.Action,
1632 }).Debug("received PerformGroupOperation")
1633 return &openolt.Empty{}, nil
1634}
1635
1636func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1637 oltLogger.WithFields(log.Fields{
1638 "GroupId": group.GroupId,
1639 "Command": group.Command,
1640 "Members": group.Members,
1641 "Action": group.Action,
1642 }).Debug("received PerformGroupOperation")
1643 return &openolt.Empty{}, nil
1644}
1645
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001646func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1647 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001648}
1649
1650func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1651 return &openolt.Empty{}, nil
1652}
1653
1654func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1655 return &openolt.OnuLogicalDistance{}, nil
1656}
1657
1658func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1659 return &openolt.OnuLogicalDistance{}, nil
1660}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001661
Girish Gowdra62f24292021-05-12 16:28:39 -07001662func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1663 return &openolt.PonRxPowerData{}, nil
1664}
1665
Matteo Scandolo96f89192021-03-12 13:17:26 -08001666func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1667 return &openolt.GemPortStatistics{}, nil
1668}
1669
1670func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1671 return &openolt.OnuStatistics{}, nil
1672}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001673
1674func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1675 o.AllocIDsLock.Lock()
1676 defer o.AllocIDsLock.Unlock()
1677
Matteo Scandolo21195d62021-04-07 14:31:23 -07001678 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1679 oltLogger.WithFields(log.Fields{
1680 "IntfId": flow.AccessIntfId,
1681 "OnuId": flow.OnuId,
1682 "PortNo": flow.PortNo,
1683 "GemportId": flow.GemportId,
1684 "FlowId": flow.FlowId,
1685 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1686 }
1687
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001688 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001689 "IntfId": flow.AccessIntfId,
1690 "OnuId": flow.OnuId,
1691 "PortNo": flow.PortNo,
1692 "GemportId": flow.GemportId,
1693 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001694 }).Trace("storing-alloc-id-via-flow")
1695
1696 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1697 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1698 }
1699 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1700 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1701 }
1702 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1703}
1704
1705func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1706 // if this is the last flow referencing the AllocId then remove it
1707 o.AllocIDsLock.Lock()
1708 defer o.AllocIDsLock.Unlock()
1709
1710 oltLogger.WithFields(log.Fields{
1711 "IntfId": flow.AccessIntfId,
1712 "OnuId": flow.OnuId,
1713 "PortNo": flow.PortNo,
1714 "GemportId": flow.GemportId,
1715 }).Trace("freeing-alloc-id-via-flow")
1716
1717 // NOTE look at the freeGemPortId implementation for comments and context
1718 for ponId, ponValues := range o.AllocIDs {
1719 for onuId, onuValues := range ponValues {
1720 for uniId, uniValues := range onuValues {
1721 for allocId, flows := range uniValues {
1722 for flowId := range flows {
1723 // if the flow matches, remove it from the map.
1724 if flow.FlowId == flowId {
1725 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1726 }
1727 // if that was the last flow for a particular allocId, remove the entire allocId
1728 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1729 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1730 }
1731 }
1732 }
1733 }
1734 }
1735 }
1736}
1737
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001738func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001739 o.GemPortIDsLock.Lock()
1740 defer o.GemPortIDsLock.Unlock()
1741
1742 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1743 oltLogger.WithFields(log.Fields{
1744 "IntfId": ponId,
1745 "OnuId": onuId,
1746 "PortNo": portNo,
1747 "GemportId": gemId,
1748 "FlowId": flowId,
1749 }).Error("trying-to-store-gemport-for-unknown-onu")
1750 }
1751
1752 oltLogger.WithFields(log.Fields{
1753 "IntfId": ponId,
1754 "OnuId": onuId,
1755 "PortNo": portNo,
1756 "GemportId": gemId,
1757 "FlowId": flowId,
1758 }).Trace("storing-alloc-id-via-flow")
1759
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001760 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1761 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1762 }
1763 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1764 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1765 }
1766 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1767}
1768
1769func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001770 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001771 "IntfId": flow.AccessIntfId,
1772 "OnuId": flow.OnuId,
1773 "PortNo": flow.PortNo,
1774 "GemportId": flow.GemportId,
1775 "FlowId": flow.FlowId,
1776 "ReplicateFlow": flow.ReplicateFlow,
1777 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001778 }).Trace("storing-gem-port-id-via-flow")
1779
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001780 if flow.ReplicateFlow {
1781 for _, gem := range flow.PbitToGemport {
1782 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1783 }
1784 } else {
1785 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001786 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001787}
1788
1789func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1790 // if this is the last flow referencing the GemPort then remove it
1791 o.GemPortIDsLock.Lock()
1792 defer o.GemPortIDsLock.Unlock()
1793
1794 oltLogger.WithFields(log.Fields{
1795 "IntfId": flow.AccessIntfId,
1796 "OnuId": flow.OnuId,
1797 "PortNo": flow.PortNo,
1798 "GemportId": flow.GemportId,
1799 }).Trace("freeing-gem-port-id-via-flow")
1800
1801 // NOTE that this loop is not very performant, it would be better if the flow carries
1802 // the same information that it carries during a FlowAdd. If so we can directly remove
1803 // items from the map
1804
1805 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1806 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1807 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1808 //}
1809
1810 // NOTE this loop assumes that flow IDs are unique per device
1811 for ponId, ponValues := range o.GemPortIDs {
1812 for onuId, onuValues := range ponValues {
1813 for uniId, uniValues := range onuValues {
1814 for gemId, flows := range uniValues {
1815 for flowId := range flows {
1816 // if the flow matches, remove it from the map.
1817 if flow.FlowId == flowId {
1818 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1819 }
1820 // if that was the last flow for a particular gem, remove the entire gem
1821 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1822 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1823 }
1824 }
1825 }
1826 }
1827 }
1828 }
1829}
1830
1831// validateFlow checks that:
1832// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1833// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1834func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001835 // validate gemPort
1836 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001837 defer o.GemPortIDsLock.RUnlock()
1838 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001839 if onuId == uint32(flow.OnuId) {
1840 continue
1841 }
1842 for uniId, uni := range onu {
1843 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001844 if flow.ReplicateFlow {
1845 for _, flowGem := range flow.PbitToGemport {
1846 if gem == int32(flowGem) {
1847 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1848 }
1849 }
1850 } else {
1851 if gem == flow.GemportId {
1852 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1853 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001854 }
1855 }
1856 }
1857 }
1858
1859 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001860 defer o.AllocIDsLock.RUnlock()
1861 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001862 if onuId == uint32(flow.OnuId) {
1863 continue
1864 }
1865 for uniId, uni := range onu {
1866 for allocId := range uni {
1867 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001868 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 -08001869 }
1870 }
1871 }
1872 }
1873
1874 return nil
1875}
1876
1877// clearAllResources is invoked up OLT Reboot to remove all the allocated
1878// GemPorts, AllocId and ONU-IDs across the PONs
1879func (o *OltDevice) clearAllResources() {
1880
1881 // remove the resources received via flows
1882 o.GemPortIDsLock.Lock()
1883 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1884 o.GemPortIDsLock.Unlock()
1885 o.AllocIDsLock.Lock()
1886 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1887 o.AllocIDsLock.Unlock()
1888
1889 // remove the resources received via OMCI
1890 for _, pon := range o.Pons {
1891 pon.removeAllAllocIds()
1892 pon.removeAllGemPorts()
1893 pon.removeAllOnuIds()
1894 }
1895}