blob: 96ee5f1e09c2cb5fbac3b90356fe3c3b91174f84 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
Joey Armstrong14628cd2023-01-10 08:38:31 -05002 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandolo11006992019-08-28 11:29:46 -07003
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"
Baris Ertas53ab13c2023-05-25 16:31:48 +030022 "errors"
Matteo Scandolo4747d292019-08-05 11:50:18 -070023 "fmt"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020024 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080025 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020026 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010027 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020028
Elia Battistonac63b112022-01-12 18:40:49 +010029 "github.com/opencord/voltha-protos/v5/go/extension"
30
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000031 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
32 "github.com/opencord/bbsim/internal/bbsim/types"
33 omcilib "github.com/opencord/bbsim/internal/common/omci"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000034 "github.com/opencord/voltha-protos/v5/go/ext/config"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000035
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070036 "github.com/google/gopacket"
37 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070038 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070039 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010040 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000041 "github.com/opencord/voltha-protos/v5/go/openolt"
42 "github.com/opencord/voltha-protos/v5/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070043 log "github.com/sirupsen/logrus"
44 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053045 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010046 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053047 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070048)
49
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070050var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070051 "module": "OLT",
52})
53
Matteo Scandolocedde462021-03-09 17:37:16 -080054const (
Baris Ertas53ab13c2023-05-25 16:31:48 +030055 multicastGemPortId = 4069
56)
57
58const (
Elia Battiston67e9e4c2022-02-15 16:38:40 +010059 //InternalState FSM states and transitions
60 OltInternalStateCreated = "created"
61 OltInternalStateInitialized = "initialized"
62 OltInternalStateEnabled = "enabled"
63 OltInternalStateDisabled = "disabled"
64 OltInternalStateDeleted = "deleted"
65
66 OltInternalTxInitialize = "initialize"
67 OltInternalTxEnable = "enable"
68 OltInternalTxDisable = "disable"
69 OltInternalTxDelete = "delete"
Matteo Scandolocedde462021-03-09 17:37:16 -080070)
71
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070072type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000073 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000074 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000075
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070076 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053077 ID int
78 SerialNumber string
79 NumNni int
Elia Battiston420c9092022-02-02 12:17:54 +010080 NniSpeed uint32
Pragya Arya2225f202020-01-29 18:05:01 +053081 NumPon int
82 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070083 NumUni int
Elia Battistonac63b112022-01-12 18:40:49 +010084 NumPots int
Andrea Campanella6f5f3552022-03-10 17:14:25 +010085 NniDhcpTrapVid int
Pragya Arya2225f202020-01-29 18:05:01 +053086 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080087 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070088 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010089 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053090 Delay int
91 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053092 EventChannel chan common.Event
93 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053094 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080095 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070096
Matteo Scandolo27428702019-10-11 16:21:16 -070097 Pons []*PonPort
98 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070099
100 // OLT Attributes
101 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +0000102
103 enableContext context.Context
104 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +0530105
Matteo Scandolo4a036262020-08-17 15:56:13 -0700106 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +0530107 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800108
109 // Allocated Resources
110 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000111 AllocIDsLock sync.RWMutex
112 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
113 GemPortIDsLock sync.RWMutex
114 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
115 OmciResponseRate uint8
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530116 signature uint32
Matteo Scandolo4747d292019-08-05 11:50:18 -0700117}
118
Matteo Scandolo27428702019-10-11 16:21:16 -0700119var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700120
Matteo Scandolo27428702019-10-11 16:21:16 -0700121func GetOLT() *OltDevice {
122 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700123}
124
Matteo Scandolo4a036262020-08-17 15:56:13 -0700125func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700126 oltLogger.WithFields(log.Fields{
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100127 "ID": options.Olt.ID,
128 "NumNni": options.Olt.NniPorts,
129 "NniSpeed": options.Olt.NniSpeed,
130 "NumPon": options.Olt.PonPorts,
131 "NumOnuPerPon": options.Olt.OnusPonPort,
132 "NumUni": options.Olt.UniPorts,
133 "NumPots": options.Olt.PotsPorts,
134 "NniDhcpTrapVid": options.Olt.NniDhcpTrapVid,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135 }).Debug("CreateOLT")
136
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700137 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530138 ID: options.Olt.ID,
139 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700140 OperState: getOperStateFSM(func(e *fsm.Event) {
141 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
142 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800143 NumNni: int(options.Olt.NniPorts),
Elia Battiston420c9092022-02-02 12:17:54 +0100144 NniSpeed: options.Olt.NniSpeed,
Matteo Scandolo96f89192021-03-12 13:17:26 -0800145 NumPon: int(options.Olt.PonPorts),
146 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700147 NumUni: int(options.Olt.UniPorts),
Elia Battistonac63b112022-01-12 18:40:49 +0100148 NumPots: int(options.Olt.PotsPorts),
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100149 NniDhcpTrapVid: int(options.Olt.NniDhcpTrapVid),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800150 Pons: []*PonPort{},
151 Nnis: []*NniPort{},
152 Delay: options.BBSim.Delay,
153 enablePerf: options.BBSim.EnablePerf,
154 PublishEvents: options.BBSim.Events,
155 PortStatsInterval: options.Olt.PortStatsInterval,
156 dhcpServer: dhcp.NewDHCPServer(),
157 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800158 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
159 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000160 OmciResponseRate: options.Olt.OmciResponseRate,
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530161 signature: uint32(time.Now().Unix()),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700162 }
163
Pragya Arya996a0892020-03-09 21:47:52 +0530164 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530165 olt.ControlledActivation = val
166 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700167 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530168 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
169 olt.ControlledActivation = Default
170 }
171
Matteo Scandolo4747d292019-08-05 11:50:18 -0700172 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700173 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700174 olt.InternalState = fsm.NewFSM(
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100175 OltInternalStateCreated,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700176 fsm.Events{
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100177 {Name: OltInternalTxInitialize, Src: []string{OltInternalStateCreated, OltInternalStateDeleted}, Dst: OltInternalStateInitialized},
178 {Name: OltInternalTxEnable, Src: []string{OltInternalStateInitialized, OltInternalStateDisabled}, Dst: OltInternalStateEnabled},
179 {Name: OltInternalTxDisable, Src: []string{OltInternalStateEnabled}, Dst: OltInternalStateDisabled},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700180 // delete event in enabled state below is for reboot OLT case.
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100181 {Name: OltInternalTxDelete, Src: []string{OltInternalStateDisabled, OltInternalStateEnabled}, Dst: OltInternalStateDeleted},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700182 },
183 fsm.Callbacks{
184 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700185 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700186 },
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100187 fmt.Sprintf("enter_%s", OltInternalStateInitialized): func(e *fsm.Event) { olt.InitOlt() },
188 fmt.Sprintf("enter_%s", OltInternalStateDeleted): func(e *fsm.Event) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800189 // remove all the resource allocations
190 olt.clearAllResources()
191 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700192 },
193 )
194
Shrey Baid688b4242020-07-10 20:40:10 +0530195 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700196 // create NNI Port
197 nniPort, err := CreateNNI(&olt)
198 if err != nil {
199 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
200 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700201
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700202 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700203 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700204
Matteo Scandolo4a036262020-08-17 15:56:13 -0700205 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700206 nextCtag := map[string]int{}
207 nextStag := map[string]int{}
208
Matteo Scandolo4747d292019-08-05 11:50:18 -0700209 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700210 for i := 0; i < olt.NumPon; i++ {
Elia Battistonb7bea222022-02-18 16:25:00 +0100211 ponConf, err := common.GetPonConfigById(uint32(i))
212 if err != nil {
213 oltLogger.WithFields(log.Fields{
214 "Err": err,
215 "IntfId": i,
216 }).Fatal("cannot-get-pon-configuration")
217 }
218
219 tech, err := common.PonTechnologyFromString(ponConf.Technology)
220 if err != nil {
221 oltLogger.WithFields(log.Fields{
222 "Err": err,
223 "IntfId": i,
224 }).Fatal("unkown-pon-port-technology")
225 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800226
227 // initialize the resource maps for every PON Ports
228 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
229 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
230
Elia Battistonb7bea222022-02-18 16:25:00 +0100231 p := CreatePonPort(&olt, uint32(i), tech)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700232
Matteo Scandolo4a036262020-08-17 15:56:13 -0700233 // create ONU devices
Elia Battistonb7bea222022-02-18 16:25:00 +0100234 if (ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1) < uint32(olt.NumOnuPerPon) {
235 oltLogger.WithFields(log.Fields{
236 "OnuRange": ponConf.OnuRange,
237 "RangeSize": ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1,
238 "NumOnuPerPon": olt.NumOnuPerPon,
239 "IntfId": i,
240 }).Fatal("onus-per-pon-bigger-than-resource-range-size")
241 }
242
Matteo Scandolo4a036262020-08-17 15:56:13 -0700243 for j := 0; j < olt.NumOnuPerPon; j++ {
244 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700245 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700246
Matteo Scandolo4a036262020-08-17 15:56:13 -0700247 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700248 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700249 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700250 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100251
Shrey Baid688b4242020-07-10 20:40:10 +0530252 if !isMock {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100253 if err := olt.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700254 log.Errorf("Error initializing OLT: %v", err)
255 return nil
256 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100257 }
258
Pragya Arya324337e2020-02-20 14:35:08 +0530259 if olt.PublishEvents {
260 log.Debugf("BBSim event publishing is enabled")
261 // Create a channel to write event messages
262 olt.EventChannel = make(chan common.Event, 100)
263 }
264
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700265 return &olt
266}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700267
Shrey Baid688b4242020-07-10 20:40:10 +0530268func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100269
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000270 if o.OltServer == nil {
271 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100272 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800273 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100274 }
275
276 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800277 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100278
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100279 // FIXME we are assuming we have only one NNI
280 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800281 // NOTE we want to make sure the state is down when we initialize the OLT,
282 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
283 // in-band management
284 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100285 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800286
287 for ponId := range o.Pons {
288 // initialize the resource maps for every PON Ports
289 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
290 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
291 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700292}
293
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800294func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100295
Matteo Scandolo96f89192021-03-12 13:17:26 -0800296 o.PreviouslyConnected = false
297
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700298 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700299 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800300
301 oltLogger.WithFields(log.Fields{
302 "oltId": o.ID,
303 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
304
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100305 if o.InternalState.Is(OltInternalStateEnabled) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700306 oltLogger.WithFields(log.Fields{
307 "oltId": o.ID,
308 }).Info("This is an OLT soft reboot")
309 softReboot = true
310 }
311
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800312 // transition internal state to deleted
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100313 if err := o.InternalState.Event(OltInternalTxDelete); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800314 oltLogger.WithFields(log.Fields{
315 "oltId": o.ID,
316 }).Errorf("Error deleting OLT: %v", err)
317 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100318 }
319
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700320 if softReboot {
321 for _, pon := range o.Pons {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530322 /* No need to send pon events on olt soft reboot
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700323 if pon.InternalState.Current() == "enabled" {
324 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800325 msg := types.Message{
326 Type: types.PonIndication,
327 Data: types.PonIndicationMessage{
328 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700329 PonPortID: pon.ID,
330 },
331 }
332 o.channel <- msg
333 }
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530334 */
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700335 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100336 err := onu.InternalState.Event(OnuTxDisable)
337 oltLogger.WithFields(log.Fields{
338 "oltId": o.ID,
339 "onuId": onu.ID,
340 }).Errorf("Error disabling ONUs on OLT soft reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700341 }
342 }
343 } else {
344 // PONs are already handled in the Disable call
345 for _, pon := range olt.Pons {
346 // ONUs are not automatically disabled when a PON goes down
347 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
348 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100349 err := onu.InternalState.Event(OnuTxDisable)
350 oltLogger.WithFields(log.Fields{
351 "oltId": o.ID,
352 "onuId": onu.ID,
Matteo Scandolofbb94ae2022-04-14 14:17:47 -0700353 "OnuSn": onu.Sn(),
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100354 }).Errorf("Error disabling ONUs on OLT reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700355 }
Pragya Arya2225f202020-01-29 18:05:01 +0530356 }
357 }
358
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700359 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
360 o.StopOltServer()
361
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100362 // terminate the OLT's processOltMessages go routine
363 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700364
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100365 oltLogger.WithFields(log.Fields{
366 "oltId": o.ID,
367 }).Infof("Waiting OLT restart for... (%ds)", rebootDelay)
368
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100369 //Prevents Enable to progress before the reboot is completed (VOL-4616)
370 o.Lock()
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700371 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100372 time.Sleep(time.Duration(rebootDelay) * time.Second)
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100373 o.Unlock()
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530374 o.signature = uint32(time.Now().Unix())
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100375
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100376 if err := o.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800377 oltLogger.WithFields(log.Fields{
378 "oltId": o.ID,
379 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100380 return err
381 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800382 oltLogger.WithFields(log.Fields{
383 "oltId": o.ID,
384 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100385 return nil
386}
387
388// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800389func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700390 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700391 lis, err := net.Listen("tcp", address)
392 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700393 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700394 }
395 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100396
Matteo Scandolo4747d292019-08-05 11:50:18 -0700397 openolt.RegisterOpenoltServer(grpcServer, o)
398
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100399 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700400
Shrey Baid688b4242020-07-10 20:40:10 +0530401 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100402 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700403
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100404 return grpcServer, nil
405}
406
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800407// StartOltServer will create the grpc server that VOLTHA uses
408// to communicate with the device
409func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
410 oltServer, err := o.newOltServer()
411 if err != nil {
412 oltLogger.WithFields(log.Fields{
413 "err": err,
414 }).Error("Cannot OLT gRPC server")
415 return nil, err
416 }
417 return oltServer, nil
418}
419
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100420// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800421func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000422 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800423 oltLogger.WithFields(log.Fields{
424 "oltId": o.SerialNumber,
425 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000426 o.OltServer.Stop()
427 o.OltServer = nil
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100428 } else {
429 oltLogger.WithFields(log.Fields{
430 "oltId": o.SerialNumber,
431 }).Warnf("OLT gRPC server is already stopped")
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700432 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700433}
434
435// Device Methods
436
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100437// Enable implements the OpenOLT EnableIndicationServer functionality
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100438func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700439 oltLogger.Debug("Enable OLT called")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100440
441 if o.InternalState.Is(OltInternalStateDeleted) {
442 err := fmt.Errorf("Cannot enable OLT while it is rebooting")
443 oltLogger.WithFields(log.Fields{
444 "oltId": o.SerialNumber,
445 "internalState": o.InternalState.Current(),
446 }).Error(err)
447 return err
448 }
449
Pragya Arya2225f202020-01-29 18:05:01 +0530450 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700451
David Bainbridge103cf022019-12-16 20:11:35 +0000452 // If enabled has already been called then an enabled context has
453 // been created. If this is the case then we want to cancel all the
454 // proessing loops associated with that enable before we recreate
455 // new ones
456 o.Lock()
457 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700458 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000459 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530460 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700461 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000462 }
463 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
464 o.Unlock()
465
Matteo Scandolo4747d292019-08-05 11:50:18 -0700466 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700467
Matteo Scandolo4a036262020-08-17 15:56:13 -0700468 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530469
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100470 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700471 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000472 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700473
474 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800475 oltMsg := types.Message{
476 Type: types.OltIndication,
477 Data: types.OltIndicationMessage{
478 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700479 },
480 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100481 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700482
483 // send NNI Port Indications
484 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800485 msg := types.Message{
486 Type: types.NniIndication,
487 Data: types.NniIndicationMessage{
488 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700489 NniPortID: nni.ID,
490 },
491 }
492 o.channel <- msg
493 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100494
Shrey Baid688b4242020-07-10 20:40:10 +0530495 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530496 for _, pon := range o.Pons {
497 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800498 msg := types.Message{
499 Type: types.PonIndication,
500 Data: types.PonIndicationMessage{
501 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530502 PonPortID: pon.ID,
503 },
504 }
505 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000506 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700507 // when the enableContext was canceled the ONUs stopped listening on the channel
508 for _, onu := range pon.Onus {
TorstenThieme37ddd392022-07-13 12:56:24 +0000509 if o.ControlledActivation != OnlyONU {
510 onu.ReDiscoverOnu(true)
511 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700512 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
513
514 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700515 for _, uni := range onu.UniPorts {
516 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700517 }
518 }
Pragya Arya2225f202020-01-29 18:05:01 +0530519 }
520 } else {
521
522 // 1. controlledActivation == Default: Send both PON and ONUs indications
523 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
524
525 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
526 // send PON Port indications
527 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800528 msg := types.Message{
529 Type: types.PonIndication,
530 Data: types.PonIndicationMessage{
531 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530532 PonPortID: pon.ID,
533 },
534 }
535 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700536 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700537 }
538 }
539
Pragya Arya996a0892020-03-09 21:47:52 +0530540 if !o.enablePerf {
541 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700542 wg.Add(1)
543 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530544 }
545
Matteo Scandolo4747d292019-08-05 11:50:18 -0700546 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700547 oltLogger.WithFields(log.Fields{
548 "stream": stream,
549 }).Debug("OpenOLT Stream closed")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100550
551 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700552}
553
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700554func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530555 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700556
557loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530558 for {
559 select {
560 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
561 // send NNI port stats
562 for _, port := range o.Nnis {
563 incrementStat := true
564 if port.OperState.Current() == "down" {
565 incrementStat = false
566 }
567 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700568 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530569 }
570
571 // send PON port stats
572 for _, port := range o.Pons {
573 incrementStat := true
574 // do not increment port stats if PON port is down or no ONU is activated on PON port
575 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
576 incrementStat = false
577 }
578 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700579 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530580 }
581 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700582 oltLogger.Debug("Stop sending port stats")
583 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530584 }
Pragya Arya996a0892020-03-09 21:47:52 +0530585 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700586 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530587}
588
Matteo Scandolo4747d292019-08-05 11:50:18 -0700589// Helpers method
590
Matteo Scandolof9d43412021-01-12 11:11:34 -0800591func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
592
593 switch interfaceType {
594 case "nni":
595 if !o.HasNni(interfaceId) {
596 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
597 }
598
599 case "pon":
600 if !o.HasPon(interfaceId) {
601 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
602 }
603 }
604
605 alarmIndication := &openolt.AlarmIndication{
606 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
607 Status: alarmStatus,
608 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
609 }},
610 }
611
612 msg := types.Message{
613 Type: types.AlarmIndication,
614 Data: alarmIndication,
615 }
616
617 o.channel <- msg
618
619 return nil
620}
621
622func (o *OltDevice) HasNni(id uint32) bool {
623 for _, intf := range o.Nnis {
624 if intf.ID == id {
625 return true
626 }
627 }
628 return false
629}
630
631func (o *OltDevice) HasPon(id uint32) bool {
632 for _, intf := range o.Pons {
633 if intf.ID == id {
634 return true
635 }
636 }
637 return false
638}
639
Shrey Baid688b4242020-07-10 20:40:10 +0530640func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700641 for _, pon := range o.Pons {
642 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700643 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 }
645 }
Shrey Baid688b4242020-07-10 20:40:10 +0530646 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700647}
648
Shrey Baid688b4242020-07-10 20:40:10 +0530649func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700650 for _, nni := range o.Nnis {
651 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700652 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700653 }
654 }
Shrey Baid688b4242020-07-10 20:40:10 +0530655 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700656}
657
Scott Baker41724b82020-01-21 19:54:53 -0800658func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
659 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
660 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
661 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
662 return
663 }
664
665 oltLogger.WithFields(log.Fields{
666 "AlarmIndication": alarmInd,
667 }).Debug("Sent Indication_AlarmInd")
668}
669
Matteo Scandolof9d43412021-01-12 11:11:34 -0800670func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700671 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
672 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700673 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800674 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700675 }
676
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700677 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700678 "OperState": msg.OperState,
679 }).Debug("Sent Indication_OltInd")
680}
681
Matteo Scandolof9d43412021-01-12 11:11:34 -0800682func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700683 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800684 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800685 if err := nni.OperState.Event("enable"); err != nil {
686 log.WithFields(log.Fields{
687 "Type": nni.Type,
688 "IntfId": nni.ID,
689 "OperState": nni.OperState.Current(),
690 }).Errorf("Can't move NNI Port to enabled state: %v", err)
691 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800692 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800693 if err := nni.OperState.Event("disable"); err != nil {
694 log.WithFields(log.Fields{
695 "Type": nni.Type,
696 "IntfId": nni.ID,
697 "OperState": nni.OperState.Current(),
698 }).Errorf("Can't move NNI Port to disable state: %v", err)
699 }
700 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700701 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700702 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
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 }}
708
709 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700710 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800711 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700712 }
713
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700714 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700715 "Type": nni.Type,
716 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700717 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100718 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700719 }).Debug("Sent Indication_IntfOperInd for NNI")
720}
721
Pragya Arya2225f202020-01-29 18:05:01 +0530722func (o *OltDevice) sendPonIndication(ponPortID uint32) {
723
Matteo Scandolo4a036262020-08-17 15:56:13 -0700724 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530725 pon, _ := o.GetPonById(ponPortID)
726 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700727 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700728 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700729 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700730 }}
731
732 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700733 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800734 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700735 }
736
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700737 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700738 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700739 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700740 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700741
Pragya Arya2225f202020-01-29 18:05:01 +0530742 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700743 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700744 Type: pon.Type,
745 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700746 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700747 }}
748
749 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700750 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800751 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700752 }
753
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700754 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700755 "Type": pon.Type,
756 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700757 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700758 }).Debug("Sent Indication_IntfOperInd for PON")
759}
760
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700761func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100762 if o.InternalState.Current() == OltInternalStateEnabled {
Shrey Baid55f328c2020-07-07 19:20:42 +0530763 oltLogger.WithFields(log.Fields{
764 "Type": portType,
765 "IntfId": portID,
766 }).Trace("Sending port stats")
767 stats.IntfId = InterfaceIDToPortNo(portID, portType)
768 data := &openolt.Indication_PortStats{
769 PortStats: stats,
770 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700771
Shrey Baid55f328c2020-07-07 19:20:42 +0530772 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
773 oltLogger.Errorf("Failed to send PortStats: %v", err)
774 return
775 }
Pragya Arya996a0892020-03-09 21:47:52 +0530776 }
777}
778
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100779// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700780func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
781 oltLogger.WithFields(log.Fields{
782 "stream": stream,
783 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000784 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700785
David Bainbridge103cf022019-12-16 20:11:35 +0000786loop:
787 for {
788 select {
789 case <-ctx.Done():
790 oltLogger.Debug("OLT Indication processing canceled via context")
791 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700792 // do not terminate this loop if the stream is closed,
793 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
794 //case <-stream.Context().Done():
795 // oltLogger.Debug("OLT Indication processing canceled via stream context")
796 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000797 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700798 if !ok {
799 if ctx.Err() != nil {
800 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
801 }
802 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000803 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700804 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700805
David Bainbridge103cf022019-12-16 20:11:35 +0000806 oltLogger.WithFields(log.Fields{
807 "oltId": o.ID,
808 "messageType": message.Type,
809 }).Trace("Received message")
810
811 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800812 case types.OltIndication:
813 msg, _ := message.Data.(types.OltIndicationMessage)
814 if msg.OperState == types.UP {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100815 _ = o.InternalState.Event(OltInternalTxEnable)
Shrey Baid688b4242020-07-10 20:40:10 +0530816 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800817 } else if msg.OperState == types.DOWN {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100818 _ = o.InternalState.Event(OltInternalTxDisable)
Shrey Baid688b4242020-07-10 20:40:10 +0530819 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000820 }
821 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800822 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800823 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
824 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800825 case types.NniIndication:
826 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000827 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800828 case types.PonIndication:
829 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530830 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800831 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530832 if err := pon.OperState.Event("enable"); err != nil {
833 oltLogger.WithFields(log.Fields{
834 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800835 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530836 }).Error("Can't Enable Oper state for PON Port")
837 }
838 if err := pon.InternalState.Event("enable"); err != nil {
839 oltLogger.WithFields(log.Fields{
840 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800841 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530842 }).Error("Can't Enable Internal state for PON Port")
843 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800844 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530845 if err := pon.OperState.Event("disable"); err != nil {
846 oltLogger.WithFields(log.Fields{
847 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800848 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530849 }).Error("Can't Disable Oper state for PON Port")
850 }
851 if err := pon.InternalState.Event("disable"); err != nil {
852 oltLogger.WithFields(log.Fields{
853 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800854 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530855 }).Error("Can't Disable Internal state for PON Port")
856 }
Pragya Arya2225f202020-01-29 18:05:01 +0530857 }
David Bainbridge103cf022019-12-16 20:11:35 +0000858 default:
859 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
860 }
861 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700862 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100863 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700864 oltLogger.WithFields(log.Fields{
865 "stream": stream,
866 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700867}
868
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700869// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530870func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700871 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700872 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700873 for _, pon := range o.Pons {
874 for _, onu := range pon.Onus {
875 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700876 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700877 }
878 }
879 }
880
Shrey Baid688b4242020-07-10 20:40:10 +0530881 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700882}
883
William Kurkian9dadc5b2019-10-22 13:51:57 -0400884// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530885func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700886 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400887 // memoizing it will remove the bottleneck
888 for _, pon := range o.Pons {
889 if pon.ID == intfId {
890 for _, onu := range pon.Onus {
891 if onu.ID == onuId {
892 return onu, nil
893 }
894 }
895 }
896 }
Shrey Baid688b4242020-07-10 20:40:10 +0530897 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400898}
899
Matteo Scandolo4a036262020-08-17 15:56:13 -0700900// returns a Service with a given Mac Address
901func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700902 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700903 // memoizing it will remove the bottleneck
904 for _, pon := range o.Pons {
905 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700906 s, err := onu.findServiceByMacAddress(mac)
907 if err == nil {
908 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700909 }
910 }
911 }
912
Matteo Scandolo4a036262020-08-17 15:56:13 -0700913 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700914}
915
Matteo Scandolo4747d292019-08-05 11:50:18 -0700916// GRPC Endpoints
917
Shrey Baid688b4242020-07-10 20:40:10 +0530918func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700919
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700920 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800921
Matteo Scandolo8a574812021-05-20 15:18:53 -0700922 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800923 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
924 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
925
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700926 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700927
928 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
929 oltLogger.WithFields(log.Fields{
930 "OnuSn": _onu.Sn(),
931 }).Info("Received ActivateOnu call from VOLTHA")
932
William Kurkian0418bc82019-11-06 12:16:24 -0500933 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700934
Matteo Scandolocedde462021-03-09 17:37:16 -0800935 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700936 oltLogger.WithFields(log.Fields{
937 "IntfId": _onu.PonPortID,
938 "OnuSn": _onu.Sn(),
939 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800940 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700941 }
942
943 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
944
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700945 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700946}
947
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800948func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700949 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700950 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700951}
952
Shrey Baid688b4242020-07-10 20:40:10 +0530953func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530954 oltLogger.WithFields(log.Fields{
955 "IntfId": onu.IntfId,
956 "OnuId": onu.OnuId,
957 }).Info("Received DeleteOnu call from VOLTHA")
958
959 pon, err := o.GetPonById(onu.IntfId)
960 if err != nil {
961 oltLogger.WithFields(log.Fields{
962 "OnuId": onu.OnuId,
963 "IntfId": onu.IntfId,
964 "err": err,
965 }).Error("Can't find PonPort")
966 }
967 _onu, err := pon.GetOnuById(onu.OnuId)
968 if err != nil {
969 oltLogger.WithFields(log.Fields{
970 "OnuId": onu.OnuId,
971 "IntfId": onu.IntfId,
972 "err": err,
973 }).Error("Can't find Onu")
974 }
975
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530976 if _onu.InternalState.Current() != OnuStateDisabled {
977 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
978 oltLogger.WithFields(log.Fields{
979 "IntfId": _onu.PonPortID,
980 "OnuSn": _onu.Sn(),
981 "OnuId": _onu.ID,
982 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
983 }
Hardik Windlassad790cb2020-06-17 21:26:22 +0530984 }
985
Hardik Windlassad790cb2020-06-17 21:26:22 +0530986 // ONU Re-Discovery
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100987 if o.InternalState.Current() == OltInternalStateEnabled && pon.InternalState.Current() == "enabled" {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530988 go _onu.ReDiscoverOnu(false)
Pragya Arya1cbefa42020-01-13 12:15:29 +0530989 }
990
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700991 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700992}
993
Shrey Baid688b4242020-07-10 20:40:10 +0530994func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700995 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800996 oltLogger.WithFields(log.Fields{
997 "oltId": o.ID,
998 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530999 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001000
Matteo Scandolo401503a2019-12-11 14:48:14 -08001001 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +05301002 if pon.InternalState.Current() == "enabled" {
1003 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -08001004 msg := types.Message{
1005 Type: types.PonIndication,
1006 Data: types.PonIndicationMessage{
1007 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +05301008 PonPortID: pon.ID,
1009 },
1010 }
1011 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001012 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001013 }
1014
Matteo Scandolo401503a2019-12-11 14:48:14 -08001015 // Note that we are not disabling the NNI as the real OLT does not.
1016 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001017
1018 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001019 oltMsg := types.Message{
1020 Type: types.OltIndication,
1021 Data: types.OltIndicationMessage{
1022 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001023 },
1024 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001025 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001026
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001027 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001028}
1029
Shrey Baid688b4242020-07-10 20:40:10 +05301030func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301031 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001032 ponID := intf.GetIntfId()
1033 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001034
Matteo Scandolof9d43412021-01-12 11:11:34 -08001035 msg := types.Message{
1036 Type: types.PonIndication,
1037 Data: types.PonIndicationMessage{
1038 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001039 PonPortID: ponID,
1040 },
1041 }
1042 o.channel <- msg
1043
1044 for _, onu := range pon.Onus {
1045
Matteo Scandolof9d43412021-01-12 11:11:34 -08001046 onuIndication := types.OnuIndicationMessage{
1047 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001048 PonPortID: ponID,
1049 OnuID: onu.ID,
1050 OnuSN: onu.SerialNumber,
1051 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001052 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001053
1054 }
1055
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001056 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001057}
1058
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001059func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001060 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301061 publishEvent("OLT-enable-received", -1, -1, "")
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001062 return o.Enable(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001063}
1064
Shrey Baid688b4242020-07-10 20:40:10 +05301065func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301066 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301067 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001068 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001069
Matteo Scandolof9d43412021-01-12 11:11:34 -08001070 msg := types.Message{
1071 Type: types.PonIndication,
1072 Data: types.PonIndicationMessage{
1073 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301074 PonPortID: ponID,
1075 },
1076 }
1077 o.channel <- msg
1078
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001079 for _, onu := range pon.Onus {
1080
Matteo Scandolof9d43412021-01-12 11:11:34 -08001081 onuIndication := types.OnuIndicationMessage{
1082 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001083 PonPortID: ponID,
1084 OnuID: onu.ID,
1085 OnuSN: onu.SerialNumber,
1086 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001087 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001088
1089 }
1090
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001091 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001092}
1093
Shrey Baid688b4242020-07-10 20:40:10 +05301094func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001095 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001096 "IntfId": flow.AccessIntfId,
1097 "OnuId": flow.OnuId,
1098 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001099 "InnerVlan": flow.Classifier.IVid,
1100 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001101 "FlowType": flow.FlowType,
1102 "FlowId": flow.FlowId,
1103 "UniID": flow.UniId,
1104 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301105 }).Tracef("OLT receives FlowAdd")
1106
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001107 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301108 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001109 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001110 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301111 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001112
1113 if flow.AccessIntfId == -1 {
1114 oltLogger.WithFields(log.Fields{
1115 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001116 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001117 } else if flow.FlowType == "multicast" {
1118 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001119 "Cookie": flow.Cookie,
1120 "DstPort": flow.Classifier.DstPort,
1121 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1122 "FlowId": flow.FlowId,
1123 "FlowType": flow.FlowType,
1124 "GemportId": flow.GemportId,
1125 "InnerVlan": flow.Classifier.IVid,
1126 "IntfId": flow.AccessIntfId,
1127 "IpProto": flow.Classifier.IpProto,
1128 "OnuId": flow.OnuId,
1129 "OuterVlan": flow.Classifier.OVid,
1130 "PortNo": flow.PortNo,
1131 "SrcPort": flow.Classifier.SrcPort,
1132 "UniID": flow.UniId,
1133 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001134 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001135 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001136 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001137 if err != nil {
1138 oltLogger.WithFields(log.Fields{
1139 "OnuId": flow.OnuId,
1140 "IntfId": flow.AccessIntfId,
1141 "err": err,
1142 }).Error("Can't find PonPort")
1143 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001144 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001145 if err != nil {
1146 oltLogger.WithFields(log.Fields{
1147 "OnuId": flow.OnuId,
1148 "IntfId": flow.AccessIntfId,
1149 "err": err,
1150 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001151 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001152 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001153
1154 // if the ONU is disabled reject the flow
1155 // as per VOL-4061 there is a small window during which the ONU is disabled
1156 // but the port has not been reported as down to ONOS
1157 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1158 oltLogger.WithFields(log.Fields{
1159 "OnuId": flow.OnuId,
1160 "IntfId": flow.AccessIntfId,
1161 "Flow": flow,
1162 "SerialNumber": onu.Sn(),
1163 "InternalState": onu.InternalState.Current(),
1164 }).Error("rejected-flow-because-of-onu-state")
1165 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1166 }
1167
Pragya Arya8bdb4532020-03-02 17:08:09 +05301168 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001169 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301170 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001171 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001172 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301173 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301174 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001175
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001176 // validate that the flow reference correct IDs (Alloc, Gem)
1177 if err := o.validateFlow(flow); err != nil {
1178 oltLogger.WithFields(log.Fields{
1179 "OnuId": flow.OnuId,
1180 "IntfId": flow.AccessIntfId,
1181 "Flow": flow,
1182 "SerialNumber": onu.Sn(),
1183 "err": err,
1184 }).Error("invalid-flow-for-onu")
1185 return nil, err
1186 }
1187
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301188 if err := o.storeGemPortIdByFlow(flow); err != nil {
1189 return nil, err
1190 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001191 o.storeAllocId(flow)
1192
Matteo Scandolof9d43412021-01-12 11:11:34 -08001193 msg := types.Message{
1194 Type: types.FlowAdd,
1195 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001196 PonPortID: pon.ID,
1197 OnuID: onu.ID,
1198 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001199 },
1200 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001201 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001202 }
1203
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001204 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001205}
1206
Pragya Arya8bdb4532020-03-02 17:08:09 +05301207// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301208func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001209
Pragya Arya8bdb4532020-03-02 17:08:09 +05301210 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001211 "AllocId": flow.AllocId,
1212 "Cookie": flow.Cookie,
1213 "FlowId": flow.FlowId,
1214 "FlowType": flow.FlowType,
1215 "GemportId": flow.GemportId,
1216 "IntfId": flow.AccessIntfId,
1217 "OnuId": flow.OnuId,
1218 "PortNo": flow.PortNo,
1219 "UniID": flow.UniId,
1220 "ReplicateFlow": flow.ReplicateFlow,
1221 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001222 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301223
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001224 olt.freeGemPortId(flow)
1225 olt.freeAllocId(flow)
1226
Pragya Arya8bdb4532020-03-02 17:08:09 +05301227 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001228 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301229 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001230 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301231 if !ok {
1232 oltLogger.Errorf("Flow %v not found", flow)
1233 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1234 }
1235
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001236 storedFlow := storedFlowIntf.(openolt.Flow)
1237
Pragya Arya8bdb4532020-03-02 17:08:09 +05301238 // if its ONU flow remove it from ONU also
1239 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001240 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1241 if err != nil {
1242 oltLogger.WithFields(log.Fields{
1243 "OnuId": storedFlow.OnuId,
1244 "IntfId": storedFlow.AccessIntfId,
1245 "PONs": olt.Pons,
1246 "err": err,
1247 }).Error("PON-port-not-found")
1248 return new(openolt.Empty), nil
1249 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301250 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1251 if err != nil {
1252 oltLogger.WithFields(log.Fields{
1253 "OnuId": storedFlow.OnuId,
1254 "IntfId": storedFlow.AccessIntfId,
1255 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001256 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301257 return new(openolt.Empty), nil
1258 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001259 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001260 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301261 }
1262
1263 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001264 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301265 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001266
1267 if flow.AccessIntfId == -1 {
1268 oltLogger.WithFields(log.Fields{
1269 "FlowId": flow.FlowId,
1270 }).Debug("Removing OLT flow")
1271 } else if flow.FlowType == "multicast" {
1272 oltLogger.WithFields(log.Fields{
1273 "FlowId": flow.FlowId,
1274 }).Debug("Removing OLT multicast flow")
1275 } else {
1276
1277 onu, err := o.GetOnuByFlowId(flow.FlowId)
1278 if err != nil {
1279 oltLogger.WithFields(log.Fields{
1280 "OnuId": flow.OnuId,
1281 "IntfId": flow.AccessIntfId,
1282 "err": err,
1283 }).Error("Can't find Onu")
1284 return nil, err
1285 }
1286
Matteo Scandolof9d43412021-01-12 11:11:34 -08001287 msg := types.Message{
1288 Type: types.FlowRemoved,
1289 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301290 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001291 },
1292 }
1293 onu.Channel <- msg
1294 }
1295
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001296 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001297}
1298
Shrey Baid688b4242020-07-10 20:40:10 +05301299func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301300 res := openolt.Heartbeat{HeartbeatSignature: o.signature}
Matteo Scandolo18859852020-01-15 13:33:57 -08001301 oltLogger.WithFields(log.Fields{
1302 "signature": res.HeartbeatSignature,
1303 }).Trace("HeartbeatCheck")
1304 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001305}
1306
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001307func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001308 for _, pon := range o.Pons {
1309 for _, onu := range pon.Onus {
1310 for _, fId := range onu.FlowIds {
1311 if fId == flowId {
1312 return onu, nil
1313 }
1314 }
1315 }
1316 }
Shrey Baid688b4242020-07-10 20:40:10 +05301317 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001318}
1319
Shrey Baid688b4242020-07-10 20:40:10 +05301320func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolocedde462021-03-09 17:37:16 -08001321 devinfo := &openolt.DeviceInfo{
1322 Vendor: common.Config.Olt.Vendor,
1323 Model: common.Config.Olt.Model,
1324 HardwareVersion: common.Config.Olt.HardwareVersion,
1325 FirmwareVersion: common.Config.Olt.FirmwareVersion,
Matteo Scandolocedde462021-03-09 17:37:16 -08001326 PonPorts: uint32(o.NumPon),
Matteo Scandolocedde462021-03-09 17:37:16 -08001327 DeviceSerialNumber: o.SerialNumber,
1328 DeviceId: common.Config.Olt.DeviceId,
1329 PreviouslyConnected: o.PreviouslyConnected,
Elia Battistonb7bea222022-02-18 16:25:00 +01001330 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{},
1331 }
1332
1333 for _, resRange := range common.PonsConfig.Ranges {
1334 intfIDs := []uint32{}
1335 for i := resRange.PonRange.StartId; i <= resRange.PonRange.EndId; i++ {
1336 intfIDs = append(intfIDs, uint32(i))
1337 }
1338
1339 devinfo.Ranges = append(devinfo.Ranges, &openolt.DeviceInfo_DeviceResourceRanges{
1340 IntfIds: intfIDs,
1341 Technology: resRange.Technology,
1342 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1343 {
1344 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1345 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1346 Start: resRange.OnuRange.StartId,
1347 End: resRange.OnuRange.EndId,
1348 },
1349 {
1350 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1351 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1352 Start: resRange.AllocIdRange.StartId,
1353 End: resRange.AllocIdRange.EndId,
1354 },
1355 {
1356 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1357 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1358 Start: resRange.GemportRange.StartId,
1359 End: resRange.GemportRange.EndId,
Matteo Scandolocedde462021-03-09 17:37:16 -08001360 },
1361 },
Elia Battistonb7bea222022-02-18 16:25:00 +01001362 })
Matteo Scandolocedde462021-03-09 17:37:16 -08001363 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001364
1365 oltLogger.WithFields(log.Fields{
1366 "Vendor": devinfo.Vendor,
1367 "Model": devinfo.Model,
1368 "HardwareVersion": devinfo.HardwareVersion,
1369 "FirmwareVersion": devinfo.FirmwareVersion,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001370 "PonPorts": devinfo.PonPorts,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001371 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1372 "DeviceId": devinfo.DeviceId,
1373 "PreviouslyConnected": devinfo.PreviouslyConnected,
1374 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1375
1376 // once we connect, set the flag
1377 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001378
1379 return devinfo, nil
1380}
1381
Shrey Baid688b4242020-07-10 20:40:10 +05301382func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001383 pon, err := o.GetPonById(omci_msg.IntfId)
1384 if err != nil {
1385 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001386 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001387 "onu_id": omci_msg.OnuId,
1388 "pon_id": omci_msg.IntfId,
1389 }).Error("pon ID not found")
1390 return nil, err
1391 }
1392
1393 onu, err := pon.GetOnuById(omci_msg.OnuId)
1394 if err != nil {
1395 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001396 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001397 "onu_id": omci_msg.OnuId,
1398 "pon_id": omci_msg.IntfId,
1399 }).Error("onu ID not found")
1400 return nil, err
1401 }
1402
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001403 oltLogger.WithFields(log.Fields{
1404 "IntfId": onu.PonPortID,
1405 "OnuId": onu.ID,
1406 "OnuSn": onu.Sn(),
1407 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001408 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1409 if err != nil {
1410 log.WithFields(log.Fields{
1411 "IntfId": onu.PonPortID,
1412 "SerialNumber": onu.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001413 "omciPacket": hex.EncodeToString(omci_msg.Pkt),
Matteo Scandolob5913142021-03-19 16:10:18 -07001414 "err": err.Error(),
1415 }).Error("cannot-parse-OMCI-packet")
1416 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001417 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001418 if onu.InternalState.Current() == OnuStateDisabled {
1419 // if the ONU is disabled just drop the message
1420 log.WithFields(log.Fields{
1421 "IntfId": onu.PonPortID,
1422 "SerialNumber": onu.Sn(),
1423 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1424 "omciPkt": omciPkt,
1425 "omciMsgType": omciMsg.MessageType,
1426 }).Warn("dropping-omci-message")
1427 } else {
1428 msg := types.Message{
1429 Type: types.OMCI,
1430 Data: types.OmciMessage{
1431 OnuSN: onu.SerialNumber,
1432 OnuID: onu.ID,
1433 OmciMsg: omciMsg,
1434 OmciPkt: omciPkt,
1435 },
1436 }
1437 onu.Channel <- msg
1438 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001439 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001440}
1441
Matteo Scandolo8a574812021-05-20 15:18:53 -07001442// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301443func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001444 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001445 if err != nil {
1446 oltLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001447 "OnuId": onuPkt.OnuId,
1448 "IntfId": onuPkt.IntfId,
1449 "GemportId": onuPkt.GemportId,
1450 "err": err,
Matteo Scandolo27428702019-10-11 16:21:16 -07001451 }).Error("Can't find PonPort")
1452 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001453
Baris Ertas53ab13c2023-05-25 16:31:48 +03001454 onus := make([]*Onu, 1)
1455 // If it's not addressed to multicast gem port
1456 if onuPkt.GemportId != multicastGemPortId {
1457 onus[0], err = pon.GetOnuById(onuPkt.OnuId)
1458 if err != nil {
1459 oltLogger.WithFields(log.Fields{
1460 "OnuId": onuPkt.OnuId,
1461 "IntfId": onuPkt.IntfId,
1462 "GemportId": onuPkt.GemportId,
1463 "err": err,
1464 }).Error("Can't find Onu")
1465 return new(openolt.Empty), errors.New("cant-find-onu-by-id")
1466 }
1467 oltLogger.WithFields(log.Fields{
1468 "IntfId": onus[0].PonPortID,
1469 "OnuId": onus[0].ID,
1470 "OnuSn": onus[0].Sn(),
1471 "GemportId": onuPkt.GemportId,
1472 "Packet": hex.EncodeToString(onuPkt.Pkt),
1473 }).Trace("Received OnuPacketOut")
1474 } else {
1475 onus = pon.GetAllOnus()
1476 oltLogger.WithFields(log.Fields{
1477 "IntfId": onuPkt.IntfId,
1478 "GemportId": onuPkt.GemportId,
1479 "Packet": hex.EncodeToString(onuPkt.Pkt),
1480 }).Trace("Received OnuPacketOut to multicast gem port")
1481 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001482
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001483 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001484
1485 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001486 if err != nil {
1487 onuLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001488 "IntfId": onuPkt.IntfId,
1489 "OnuId": onuPkt.OnuId,
1490 "GemportId": onuPkt.GemportId,
1491 "Pkt": hex.EncodeToString(rawpkt.Data()),
1492 }).Debug("Can't find pktType in packet, dropping it")
1493 return new(openolt.Empty), errors.New("malformed-packet")
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001494 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001495
Matteo Scandolo4a036262020-08-17 15:56:13 -07001496 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001497 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001498 onuLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001499 "IntfId": onuPkt.IntfId,
1500 "OnuId": onuPkt.OnuId,
1501 "GemportId": onuPkt.GemportId,
1502 "Pkt": rawpkt.Data(),
1503 }).Debug("Can't find Dst MacAddress in packet, droppint it")
1504 return new(openolt.Empty), errors.New("dst-mac-can-not-found-in-packet")
Matteo Scandolo4a036262020-08-17 15:56:13 -07001505 }
1506
Matteo Scandolof9d43412021-01-12 11:11:34 -08001507 msg := types.Message{
1508 Type: types.OnuPacketOut,
1509 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001510 IntfId: onuPkt.IntfId,
1511 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001512 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001513 Packet: rawpkt,
1514 Type: pktType,
1515 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001516 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001517 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001518
Baris Ertas53ab13c2023-05-25 16:31:48 +03001519 for _, onu := range onus {
1520 if onu.InternalState.Current() == OnuStateEnabled {
1521 oltLogger.WithFields(log.Fields{
1522 "IntfId": onu.PonPortID,
1523 "OnuId": onu.ID,
1524 "OnuSn": onu.Sn(),
1525 }).Trace("Sending to onuchannel")
1526 onu.Channel <- msg
1527 } else {
1528 oltLogger.WithFields(log.Fields{
1529 "IntfId": onu.PonPortID,
1530 "OnuId": onu.ID,
1531 "OnuSn": onu.Sn(),
1532 }).Debug("can-not-send-onu-packet-out-to-onu")
1533 }
1534 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001535
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001536 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001537}
1538
Shrey Baid688b4242020-07-10 20:40:10 +05301539func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001540
1541 // OLT Reboot is called in two cases:
1542 // - 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)
1543 // - when an OLT needs to be rebooted (voltcl device reboot)
1544
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001545 oltLogger.WithFields(log.Fields{
1546 "oltId": o.ID,
1547 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301548 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301549 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001550 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001551}
1552
Shrey Baid688b4242020-07-10 20:40:10 +05301553func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301554 oltLogger.WithFields(log.Fields{
1555 "oltId": o.ID,
1556 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301557 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301558
Pragya Arya2225f202020-01-29 18:05:01 +05301559 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001560 oltMsg := types.Message{
1561 Type: types.OltIndication,
1562 Data: types.OltIndicationMessage{
1563 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301564 },
Pragya Arya1881df02020-01-29 18:05:01 +05301565 }
Pragya Arya2225f202020-01-29 18:05:01 +05301566 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301567
Pragya Arya2225f202020-01-29 18:05:01 +05301568 for _, pon := range o.Pons {
1569 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001570 msg := types.Message{
1571 Type: types.PonIndication,
1572 Data: types.PonIndicationMessage{
1573 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301574 PonPortID: pon.ID,
1575 },
1576 }
1577 o.channel <- msg
1578 }
1579 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001580
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001581 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001582}
1583
Shrey Baid688b4242020-07-10 20:40:10 +05301584func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001585 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1586
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001587 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1588
1589 if err != nil {
1590 return nil, err
1591 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001592 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001593}
1594
Shrey Baid688b4242020-07-10 20:40:10 +05301595func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001596 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001597 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001598}
1599
Shrey Baid688b4242020-07-10 20:40:10 +05301600func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001601 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001602 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001603}
1604
Shrey Baid688b4242020-07-10 20:40:10 +05301605func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001606 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001607 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001608}
1609
Shrey Baid688b4242020-07-10 20:40:10 +05301610func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001611 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001612 return new(openolt.Empty), nil
1613}
1614
Matteo Scandolo8a574812021-05-20 15:18:53 -07001615func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1616 oltLogger.WithFields(log.Fields{
1617 "OnuId": tq.OnuId,
1618 "IntfId": tq.IntfId,
1619 "OnuPortNo": tq.PortNo,
1620 "UniId": tq.UniId,
1621 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001622 return new(openolt.Empty), nil
1623}
1624
Matteo Scandolo8a574812021-05-20 15:18:53 -07001625func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301626 oltLogger.WithFields(log.Fields{
1627 "OnuId": trafficSchedulers.OnuId,
1628 "IntfId": trafficSchedulers.IntfId,
1629 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001630 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301631 }).Info("received CreateTrafficSchedulers")
1632
1633 if !s.enablePerf {
1634 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1635 if err != nil {
1636 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1637 return new(openolt.Empty), err
1638 }
1639 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1640 if err != nil {
1641 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1642 return new(openolt.Empty), err
1643 }
1644 onu.TrafficSchedulers = trafficSchedulers
1645 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001646 return new(openolt.Empty), nil
1647}
1648
Shrey Baid688b4242020-07-10 20:40:10 +05301649func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301650 oltLogger.WithFields(log.Fields{
1651 "OnuId": trafficSchedulers.OnuId,
1652 "IntfId": trafficSchedulers.IntfId,
1653 "OnuPortNo": trafficSchedulers.PortNo,
1654 }).Info("received RemoveTrafficSchedulers")
1655 if !s.enablePerf {
1656 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1657 if err != nil {
1658 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1659 return new(openolt.Empty), err
1660 }
1661 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1662 if err != nil {
1663 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1664 return new(openolt.Empty), err
1665 }
1666
1667 onu.TrafficSchedulers = nil
1668 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001669 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001670}
Scott Baker41724b82020-01-21 19:54:53 -08001671
Matteo Scandolo618a6582020-09-09 12:21:29 -07001672func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1673 oltLogger.WithFields(log.Fields{
1674 "GroupId": group.GroupId,
1675 "Command": group.Command,
1676 "Members": group.Members,
1677 "Action": group.Action,
1678 }).Debug("received PerformGroupOperation")
1679 return &openolt.Empty{}, nil
1680}
1681
1682func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1683 oltLogger.WithFields(log.Fields{
1684 "GroupId": group.GroupId,
1685 "Command": group.Command,
1686 "Members": group.Members,
1687 "Action": group.Action,
1688 }).Debug("received PerformGroupOperation")
1689 return &openolt.Empty{}, nil
1690}
1691
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001692func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1693 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001694}
1695
1696func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1697 return &openolt.Empty{}, nil
1698}
1699
1700func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1701 return &openolt.OnuLogicalDistance{}, nil
1702}
1703
1704func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1705 return &openolt.OnuLogicalDistance{}, nil
1706}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001707
Girish Gowdra62f24292021-05-12 16:28:39 -07001708func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
praneeth.nalmas7aa24df2023-03-24 10:49:43 +05301709 //VOL-4878:Hardcoding the power levels for testing as BBSIM is a simulator
1710 return &openolt.PonRxPowerData{IntfId: in.IntfId, OnuId: in.OnuId, Status: "success", FailReason: 0, RxPowerMeanDbm: -6}, nil
Girish Gowdra62f24292021-05-12 16:28:39 -07001711}
1712
Matteo Scandolo96f89192021-03-12 13:17:26 -08001713func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1714 return &openolt.GemPortStatistics{}, nil
1715}
1716
1717func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1718 return &openolt.OnuStatistics{}, nil
1719}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001720
1721func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1722 o.AllocIDsLock.Lock()
1723 defer o.AllocIDsLock.Unlock()
1724
Matteo Scandolo21195d62021-04-07 14:31:23 -07001725 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1726 oltLogger.WithFields(log.Fields{
1727 "IntfId": flow.AccessIntfId,
1728 "OnuId": flow.OnuId,
1729 "PortNo": flow.PortNo,
1730 "GemportId": flow.GemportId,
1731 "FlowId": flow.FlowId,
1732 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1733 }
1734
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001735 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001736 "IntfId": flow.AccessIntfId,
1737 "OnuId": flow.OnuId,
1738 "PortNo": flow.PortNo,
1739 "GemportId": flow.GemportId,
1740 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001741 }).Trace("storing-alloc-id-via-flow")
1742
1743 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1744 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1745 }
1746 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1747 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1748 }
1749 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1750}
1751
1752func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1753 // if this is the last flow referencing the AllocId then remove it
1754 o.AllocIDsLock.Lock()
1755 defer o.AllocIDsLock.Unlock()
1756
1757 oltLogger.WithFields(log.Fields{
1758 "IntfId": flow.AccessIntfId,
1759 "OnuId": flow.OnuId,
1760 "PortNo": flow.PortNo,
1761 "GemportId": flow.GemportId,
1762 }).Trace("freeing-alloc-id-via-flow")
1763
1764 // NOTE look at the freeGemPortId implementation for comments and context
1765 for ponId, ponValues := range o.AllocIDs {
1766 for onuId, onuValues := range ponValues {
1767 for uniId, uniValues := range onuValues {
1768 for allocId, flows := range uniValues {
1769 for flowId := range flows {
1770 // if the flow matches, remove it from the map.
1771 if flow.FlowId == flowId {
1772 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1773 }
1774 // if that was the last flow for a particular allocId, remove the entire allocId
1775 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1776 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1777 }
1778 }
1779 }
1780 }
1781 }
1782 }
1783}
1784
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301785func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) error {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001786 o.GemPortIDsLock.Lock()
1787 defer o.GemPortIDsLock.Unlock()
1788
1789 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1790 oltLogger.WithFields(log.Fields{
1791 "IntfId": ponId,
1792 "OnuId": onuId,
1793 "PortNo": portNo,
1794 "GemportId": gemId,
1795 "FlowId": flowId,
1796 }).Error("trying-to-store-gemport-for-unknown-onu")
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301797 return fmt.Errorf("failed-trying-to-store-gemport-%d-for-unknown-onu-%d-and-IntfId-%d", gemId, onuId, ponId)
Matteo Scandolo21195d62021-04-07 14:31:23 -07001798 }
1799
1800 oltLogger.WithFields(log.Fields{
1801 "IntfId": ponId,
1802 "OnuId": onuId,
1803 "PortNo": portNo,
1804 "GemportId": gemId,
1805 "FlowId": flowId,
1806 }).Trace("storing-alloc-id-via-flow")
1807
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001808 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1809 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1810 }
1811 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1812 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1813 }
1814 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301815
1816 return nil
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001817}
1818
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301819func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001820 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001821 "IntfId": flow.AccessIntfId,
1822 "OnuId": flow.OnuId,
1823 "PortNo": flow.PortNo,
1824 "GemportId": flow.GemportId,
1825 "FlowId": flow.FlowId,
1826 "ReplicateFlow": flow.ReplicateFlow,
1827 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001828 }).Trace("storing-gem-port-id-via-flow")
1829
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001830 if flow.ReplicateFlow {
1831 for _, gem := range flow.PbitToGemport {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301832 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1833 if err != nil {
1834 return err
1835 }
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001836 }
1837 } else {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301838 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
1839 if err != nil {
1840 return err
1841 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001842 }
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301843
1844 return nil
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001845}
1846
1847func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1848 // if this is the last flow referencing the GemPort then remove it
1849 o.GemPortIDsLock.Lock()
1850 defer o.GemPortIDsLock.Unlock()
1851
1852 oltLogger.WithFields(log.Fields{
1853 "IntfId": flow.AccessIntfId,
1854 "OnuId": flow.OnuId,
1855 "PortNo": flow.PortNo,
1856 "GemportId": flow.GemportId,
1857 }).Trace("freeing-gem-port-id-via-flow")
1858
1859 // NOTE that this loop is not very performant, it would be better if the flow carries
1860 // the same information that it carries during a FlowAdd. If so we can directly remove
1861 // items from the map
1862
1863 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1864 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1865 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1866 //}
1867
1868 // NOTE this loop assumes that flow IDs are unique per device
1869 for ponId, ponValues := range o.GemPortIDs {
1870 for onuId, onuValues := range ponValues {
1871 for uniId, uniValues := range onuValues {
1872 for gemId, flows := range uniValues {
1873 for flowId := range flows {
1874 // if the flow matches, remove it from the map.
1875 if flow.FlowId == flowId {
1876 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1877 }
1878 // if that was the last flow for a particular gem, remove the entire gem
1879 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1880 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1881 }
1882 }
1883 }
1884 }
1885 }
1886 }
1887}
1888
1889// validateFlow checks that:
1890// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1891// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1892func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001893 // validate gemPort
1894 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001895 defer o.GemPortIDsLock.RUnlock()
1896 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001897 if onuId == uint32(flow.OnuId) {
1898 continue
1899 }
1900 for uniId, uni := range onu {
1901 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001902 if flow.ReplicateFlow {
1903 for _, flowGem := range flow.PbitToGemport {
1904 if gem == int32(flowGem) {
1905 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1906 }
1907 }
1908 } else {
1909 if gem == flow.GemportId {
1910 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1911 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001912 }
1913 }
1914 }
1915 }
1916
1917 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001918 defer o.AllocIDsLock.RUnlock()
1919 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001920 if onuId == uint32(flow.OnuId) {
1921 continue
1922 }
1923 for uniId, uni := range onu {
1924 for allocId := range uni {
1925 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001926 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 -08001927 }
1928 }
1929 }
1930 }
1931
1932 return nil
1933}
1934
1935// clearAllResources is invoked up OLT Reboot to remove all the allocated
1936// GemPorts, AllocId and ONU-IDs across the PONs
1937func (o *OltDevice) clearAllResources() {
1938
1939 // remove the resources received via flows
1940 o.GemPortIDsLock.Lock()
1941 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1942 o.GemPortIDsLock.Unlock()
1943 o.AllocIDsLock.Lock()
1944 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1945 o.AllocIDsLock.Unlock()
1946
1947 // remove the resources received via OMCI
1948 for _, pon := range o.Pons {
1949 pon.removeAllAllocIds()
1950 pon.removeAllGemPorts()
1951 pon.removeAllOnuIds()
1952 }
1953}