blob: 51c0f143ee9f1e8572ccda316dff9fe4a5c3d2cc [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")
nikesh.krishnan5e83f702023-11-10 23:40:48 +0530966 return nil, err
Pragya Arya1cbefa42020-01-13 12:15:29 +0530967 }
968 _onu, err := pon.GetOnuById(onu.OnuId)
969 if err != nil {
970 oltLogger.WithFields(log.Fields{
971 "OnuId": onu.OnuId,
972 "IntfId": onu.IntfId,
973 "err": err,
974 }).Error("Can't find Onu")
nikesh.krishnan5e83f702023-11-10 23:40:48 +0530975 return nil, err
Pragya Arya1cbefa42020-01-13 12:15:29 +0530976 }
977
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530978 if _onu.InternalState.Current() != OnuStateDisabled {
979 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
980 oltLogger.WithFields(log.Fields{
981 "IntfId": _onu.PonPortID,
982 "OnuSn": _onu.Sn(),
983 "OnuId": _onu.ID,
984 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
985 }
Hardik Windlassad790cb2020-06-17 21:26:22 +0530986 }
987
Hardik Windlassad790cb2020-06-17 21:26:22 +0530988 // ONU Re-Discovery
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100989 if o.InternalState.Current() == OltInternalStateEnabled && pon.InternalState.Current() == "enabled" {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530990 go _onu.ReDiscoverOnu(false)
Pragya Arya1cbefa42020-01-13 12:15:29 +0530991 }
992
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700993 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700994}
995
Shrey Baid688b4242020-07-10 20:40:10 +0530996func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700997 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800998 oltLogger.WithFields(log.Fields{
999 "oltId": o.ID,
1000 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +05301001 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001002
Matteo Scandolo401503a2019-12-11 14:48:14 -08001003 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +05301004 if pon.InternalState.Current() == "enabled" {
1005 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -08001006 msg := types.Message{
1007 Type: types.PonIndication,
1008 Data: types.PonIndicationMessage{
1009 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +05301010 PonPortID: pon.ID,
1011 },
1012 }
1013 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001014 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001015 }
1016
Matteo Scandolo401503a2019-12-11 14:48:14 -08001017 // Note that we are not disabling the NNI as the real OLT does not.
1018 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001019
1020 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001021 oltMsg := types.Message{
1022 Type: types.OltIndication,
1023 Data: types.OltIndicationMessage{
1024 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001025 },
1026 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001027 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001028
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001029 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001030}
1031
Shrey Baid688b4242020-07-10 20:40:10 +05301032func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301033 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001034 ponID := intf.GetIntfId()
1035 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001036
Matteo Scandolof9d43412021-01-12 11:11:34 -08001037 msg := types.Message{
1038 Type: types.PonIndication,
1039 Data: types.PonIndicationMessage{
1040 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001041 PonPortID: ponID,
1042 },
1043 }
1044 o.channel <- msg
1045
1046 for _, onu := range pon.Onus {
1047
Matteo Scandolof9d43412021-01-12 11:11:34 -08001048 onuIndication := types.OnuIndicationMessage{
1049 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001050 PonPortID: ponID,
1051 OnuID: onu.ID,
1052 OnuSN: onu.SerialNumber,
1053 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001054 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001055
1056 }
1057
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001058 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001059}
1060
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001061func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001062 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301063 publishEvent("OLT-enable-received", -1, -1, "")
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001064 return o.Enable(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001065}
1066
Shrey Baid688b4242020-07-10 20:40:10 +05301067func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301068 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301069 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001070 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001071
Matteo Scandolof9d43412021-01-12 11:11:34 -08001072 msg := types.Message{
1073 Type: types.PonIndication,
1074 Data: types.PonIndicationMessage{
1075 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301076 PonPortID: ponID,
1077 },
1078 }
1079 o.channel <- msg
1080
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001081 for _, onu := range pon.Onus {
1082
Matteo Scandolof9d43412021-01-12 11:11:34 -08001083 onuIndication := types.OnuIndicationMessage{
1084 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001085 PonPortID: ponID,
1086 OnuID: onu.ID,
1087 OnuSN: onu.SerialNumber,
1088 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001089 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001090
1091 }
1092
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001093 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001094}
1095
Shrey Baid688b4242020-07-10 20:40:10 +05301096func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001097 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001098 "IntfId": flow.AccessIntfId,
1099 "OnuId": flow.OnuId,
1100 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001101 "InnerVlan": flow.Classifier.IVid,
1102 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001103 "FlowType": flow.FlowType,
1104 "FlowId": flow.FlowId,
1105 "UniID": flow.UniId,
1106 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301107 }).Tracef("OLT receives FlowAdd")
1108
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001109 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301110 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001111 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001112 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301113 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001114
1115 if flow.AccessIntfId == -1 {
1116 oltLogger.WithFields(log.Fields{
1117 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001118 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001119 } else if flow.FlowType == "multicast" {
1120 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001121 "Cookie": flow.Cookie,
1122 "DstPort": flow.Classifier.DstPort,
1123 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1124 "FlowId": flow.FlowId,
1125 "FlowType": flow.FlowType,
1126 "GemportId": flow.GemportId,
1127 "InnerVlan": flow.Classifier.IVid,
1128 "IntfId": flow.AccessIntfId,
1129 "IpProto": flow.Classifier.IpProto,
1130 "OnuId": flow.OnuId,
1131 "OuterVlan": flow.Classifier.OVid,
1132 "PortNo": flow.PortNo,
1133 "SrcPort": flow.Classifier.SrcPort,
1134 "UniID": flow.UniId,
1135 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001136 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001137 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001138 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001139 if err != nil {
1140 oltLogger.WithFields(log.Fields{
1141 "OnuId": flow.OnuId,
1142 "IntfId": flow.AccessIntfId,
1143 "err": err,
1144 }).Error("Can't find PonPort")
1145 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001146 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001147 if err != nil {
1148 oltLogger.WithFields(log.Fields{
1149 "OnuId": flow.OnuId,
1150 "IntfId": flow.AccessIntfId,
1151 "err": err,
1152 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001153 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001154 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001155
1156 // if the ONU is disabled reject the flow
1157 // as per VOL-4061 there is a small window during which the ONU is disabled
1158 // but the port has not been reported as down to ONOS
1159 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1160 oltLogger.WithFields(log.Fields{
1161 "OnuId": flow.OnuId,
1162 "IntfId": flow.AccessIntfId,
1163 "Flow": flow,
1164 "SerialNumber": onu.Sn(),
1165 "InternalState": onu.InternalState.Current(),
1166 }).Error("rejected-flow-because-of-onu-state")
1167 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1168 }
1169
Pragya Arya8bdb4532020-03-02 17:08:09 +05301170 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001171 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301172 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001173 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001174 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301175 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301176 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001177
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001178 // validate that the flow reference correct IDs (Alloc, Gem)
1179 if err := o.validateFlow(flow); err != nil {
1180 oltLogger.WithFields(log.Fields{
1181 "OnuId": flow.OnuId,
1182 "IntfId": flow.AccessIntfId,
1183 "Flow": flow,
1184 "SerialNumber": onu.Sn(),
1185 "err": err,
1186 }).Error("invalid-flow-for-onu")
1187 return nil, err
1188 }
1189
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301190 if err := o.storeGemPortIdByFlow(flow); err != nil {
1191 return nil, err
1192 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001193 o.storeAllocId(flow)
1194
Matteo Scandolof9d43412021-01-12 11:11:34 -08001195 msg := types.Message{
1196 Type: types.FlowAdd,
1197 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001198 PonPortID: pon.ID,
1199 OnuID: onu.ID,
1200 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001201 },
1202 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001203 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001204 }
1205
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001206 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001207}
1208
Pragya Arya8bdb4532020-03-02 17:08:09 +05301209// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301210func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001211
Pragya Arya8bdb4532020-03-02 17:08:09 +05301212 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001213 "AllocId": flow.AllocId,
1214 "Cookie": flow.Cookie,
1215 "FlowId": flow.FlowId,
1216 "FlowType": flow.FlowType,
1217 "GemportId": flow.GemportId,
1218 "IntfId": flow.AccessIntfId,
1219 "OnuId": flow.OnuId,
1220 "PortNo": flow.PortNo,
1221 "UniID": flow.UniId,
1222 "ReplicateFlow": flow.ReplicateFlow,
1223 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001224 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301225
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001226 olt.freeGemPortId(flow)
1227 olt.freeAllocId(flow)
1228
Pragya Arya8bdb4532020-03-02 17:08:09 +05301229 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001230 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301231 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001232 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301233 if !ok {
1234 oltLogger.Errorf("Flow %v not found", flow)
1235 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1236 }
1237
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001238 storedFlow := storedFlowIntf.(openolt.Flow)
1239
Pragya Arya8bdb4532020-03-02 17:08:09 +05301240 // if its ONU flow remove it from ONU also
1241 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001242 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1243 if err != nil {
1244 oltLogger.WithFields(log.Fields{
1245 "OnuId": storedFlow.OnuId,
1246 "IntfId": storedFlow.AccessIntfId,
1247 "PONs": olt.Pons,
1248 "err": err,
1249 }).Error("PON-port-not-found")
1250 return new(openolt.Empty), nil
1251 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301252 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1253 if err != nil {
1254 oltLogger.WithFields(log.Fields{
1255 "OnuId": storedFlow.OnuId,
1256 "IntfId": storedFlow.AccessIntfId,
1257 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001258 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301259 return new(openolt.Empty), nil
1260 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001261 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001262 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301263 }
1264
1265 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001266 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301267 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001268
1269 if flow.AccessIntfId == -1 {
1270 oltLogger.WithFields(log.Fields{
1271 "FlowId": flow.FlowId,
1272 }).Debug("Removing OLT flow")
1273 } else if flow.FlowType == "multicast" {
1274 oltLogger.WithFields(log.Fields{
1275 "FlowId": flow.FlowId,
1276 }).Debug("Removing OLT multicast flow")
1277 } else {
1278
1279 onu, err := o.GetOnuByFlowId(flow.FlowId)
1280 if err != nil {
1281 oltLogger.WithFields(log.Fields{
1282 "OnuId": flow.OnuId,
1283 "IntfId": flow.AccessIntfId,
1284 "err": err,
1285 }).Error("Can't find Onu")
1286 return nil, err
1287 }
1288
Matteo Scandolof9d43412021-01-12 11:11:34 -08001289 msg := types.Message{
1290 Type: types.FlowRemoved,
1291 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301292 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001293 },
1294 }
1295 onu.Channel <- msg
1296 }
1297
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001298 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001299}
1300
Shrey Baid688b4242020-07-10 20:40:10 +05301301func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301302 res := openolt.Heartbeat{HeartbeatSignature: o.signature}
Matteo Scandolo18859852020-01-15 13:33:57 -08001303 oltLogger.WithFields(log.Fields{
1304 "signature": res.HeartbeatSignature,
1305 }).Trace("HeartbeatCheck")
1306 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001307}
1308
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001309func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001310 for _, pon := range o.Pons {
1311 for _, onu := range pon.Onus {
1312 for _, fId := range onu.FlowIds {
1313 if fId == flowId {
1314 return onu, nil
1315 }
1316 }
1317 }
1318 }
Shrey Baid688b4242020-07-10 20:40:10 +05301319 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001320}
1321
Shrey Baid688b4242020-07-10 20:40:10 +05301322func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolocedde462021-03-09 17:37:16 -08001323 devinfo := &openolt.DeviceInfo{
1324 Vendor: common.Config.Olt.Vendor,
1325 Model: common.Config.Olt.Model,
1326 HardwareVersion: common.Config.Olt.HardwareVersion,
1327 FirmwareVersion: common.Config.Olt.FirmwareVersion,
Matteo Scandolocedde462021-03-09 17:37:16 -08001328 PonPorts: uint32(o.NumPon),
Matteo Scandolocedde462021-03-09 17:37:16 -08001329 DeviceSerialNumber: o.SerialNumber,
1330 DeviceId: common.Config.Olt.DeviceId,
1331 PreviouslyConnected: o.PreviouslyConnected,
Elia Battistonb7bea222022-02-18 16:25:00 +01001332 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{},
1333 }
1334
1335 for _, resRange := range common.PonsConfig.Ranges {
1336 intfIDs := []uint32{}
1337 for i := resRange.PonRange.StartId; i <= resRange.PonRange.EndId; i++ {
1338 intfIDs = append(intfIDs, uint32(i))
1339 }
1340
1341 devinfo.Ranges = append(devinfo.Ranges, &openolt.DeviceInfo_DeviceResourceRanges{
1342 IntfIds: intfIDs,
1343 Technology: resRange.Technology,
1344 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1345 {
1346 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1347 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1348 Start: resRange.OnuRange.StartId,
1349 End: resRange.OnuRange.EndId,
1350 },
1351 {
1352 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1353 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1354 Start: resRange.AllocIdRange.StartId,
1355 End: resRange.AllocIdRange.EndId,
1356 },
1357 {
1358 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1359 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1360 Start: resRange.GemportRange.StartId,
1361 End: resRange.GemportRange.EndId,
Matteo Scandolocedde462021-03-09 17:37:16 -08001362 },
1363 },
Elia Battistonb7bea222022-02-18 16:25:00 +01001364 })
Matteo Scandolocedde462021-03-09 17:37:16 -08001365 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001366
1367 oltLogger.WithFields(log.Fields{
1368 "Vendor": devinfo.Vendor,
1369 "Model": devinfo.Model,
1370 "HardwareVersion": devinfo.HardwareVersion,
1371 "FirmwareVersion": devinfo.FirmwareVersion,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001372 "PonPorts": devinfo.PonPorts,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001373 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1374 "DeviceId": devinfo.DeviceId,
1375 "PreviouslyConnected": devinfo.PreviouslyConnected,
1376 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1377
1378 // once we connect, set the flag
1379 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001380
1381 return devinfo, nil
1382}
1383
Shrey Baid688b4242020-07-10 20:40:10 +05301384func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001385 pon, err := o.GetPonById(omci_msg.IntfId)
1386 if err != nil {
1387 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001388 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001389 "onu_id": omci_msg.OnuId,
1390 "pon_id": omci_msg.IntfId,
1391 }).Error("pon ID not found")
1392 return nil, err
1393 }
1394
1395 onu, err := pon.GetOnuById(omci_msg.OnuId)
1396 if err != nil {
1397 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001398 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001399 "onu_id": omci_msg.OnuId,
1400 "pon_id": omci_msg.IntfId,
1401 }).Error("onu ID not found")
1402 return nil, err
1403 }
1404
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001405 oltLogger.WithFields(log.Fields{
1406 "IntfId": onu.PonPortID,
1407 "OnuId": onu.ID,
1408 "OnuSn": onu.Sn(),
1409 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001410 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1411 if err != nil {
1412 log.WithFields(log.Fields{
1413 "IntfId": onu.PonPortID,
1414 "SerialNumber": onu.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001415 "omciPacket": hex.EncodeToString(omci_msg.Pkt),
Matteo Scandolob5913142021-03-19 16:10:18 -07001416 "err": err.Error(),
1417 }).Error("cannot-parse-OMCI-packet")
1418 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001419 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001420 if onu.InternalState.Current() == OnuStateDisabled {
1421 // if the ONU is disabled just drop the message
1422 log.WithFields(log.Fields{
1423 "IntfId": onu.PonPortID,
1424 "SerialNumber": onu.Sn(),
1425 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1426 "omciPkt": omciPkt,
1427 "omciMsgType": omciMsg.MessageType,
1428 }).Warn("dropping-omci-message")
1429 } else {
1430 msg := types.Message{
1431 Type: types.OMCI,
1432 Data: types.OmciMessage{
1433 OnuSN: onu.SerialNumber,
1434 OnuID: onu.ID,
1435 OmciMsg: omciMsg,
1436 OmciPkt: omciPkt,
1437 },
1438 }
1439 onu.Channel <- msg
1440 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001441 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001442}
1443
Matteo Scandolo8a574812021-05-20 15:18:53 -07001444// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301445func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001446 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001447 if err != nil {
1448 oltLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001449 "OnuId": onuPkt.OnuId,
1450 "IntfId": onuPkt.IntfId,
1451 "GemportId": onuPkt.GemportId,
1452 "err": err,
Matteo Scandolo27428702019-10-11 16:21:16 -07001453 }).Error("Can't find PonPort")
1454 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001455
Baris Ertas53ab13c2023-05-25 16:31:48 +03001456 onus := make([]*Onu, 1)
1457 // If it's not addressed to multicast gem port
1458 if onuPkt.GemportId != multicastGemPortId {
1459 onus[0], err = pon.GetOnuById(onuPkt.OnuId)
1460 if err != nil {
1461 oltLogger.WithFields(log.Fields{
1462 "OnuId": onuPkt.OnuId,
1463 "IntfId": onuPkt.IntfId,
1464 "GemportId": onuPkt.GemportId,
1465 "err": err,
1466 }).Error("Can't find Onu")
1467 return new(openolt.Empty), errors.New("cant-find-onu-by-id")
1468 }
1469 oltLogger.WithFields(log.Fields{
1470 "IntfId": onus[0].PonPortID,
1471 "OnuId": onus[0].ID,
1472 "OnuSn": onus[0].Sn(),
1473 "GemportId": onuPkt.GemportId,
1474 "Packet": hex.EncodeToString(onuPkt.Pkt),
1475 }).Trace("Received OnuPacketOut")
1476 } else {
1477 onus = pon.GetAllOnus()
1478 oltLogger.WithFields(log.Fields{
1479 "IntfId": onuPkt.IntfId,
1480 "GemportId": onuPkt.GemportId,
1481 "Packet": hex.EncodeToString(onuPkt.Pkt),
1482 }).Trace("Received OnuPacketOut to multicast gem port")
1483 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001484
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001485 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001486
1487 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001488 if err != nil {
1489 onuLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001490 "IntfId": onuPkt.IntfId,
1491 "OnuId": onuPkt.OnuId,
1492 "GemportId": onuPkt.GemportId,
1493 "Pkt": hex.EncodeToString(rawpkt.Data()),
1494 }).Debug("Can't find pktType in packet, dropping it")
1495 return new(openolt.Empty), errors.New("malformed-packet")
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001496 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001497
Matteo Scandolo4a036262020-08-17 15:56:13 -07001498 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001499 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001500 onuLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001501 "IntfId": onuPkt.IntfId,
1502 "OnuId": onuPkt.OnuId,
1503 "GemportId": onuPkt.GemportId,
1504 "Pkt": rawpkt.Data(),
1505 }).Debug("Can't find Dst MacAddress in packet, droppint it")
1506 return new(openolt.Empty), errors.New("dst-mac-can-not-found-in-packet")
Matteo Scandolo4a036262020-08-17 15:56:13 -07001507 }
1508
Matteo Scandolof9d43412021-01-12 11:11:34 -08001509 msg := types.Message{
1510 Type: types.OnuPacketOut,
1511 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001512 IntfId: onuPkt.IntfId,
1513 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001514 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001515 Packet: rawpkt,
1516 Type: pktType,
1517 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001518 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001519 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001520
Baris Ertas53ab13c2023-05-25 16:31:48 +03001521 for _, onu := range onus {
1522 if onu.InternalState.Current() == OnuStateEnabled {
1523 oltLogger.WithFields(log.Fields{
1524 "IntfId": onu.PonPortID,
1525 "OnuId": onu.ID,
1526 "OnuSn": onu.Sn(),
1527 }).Trace("Sending to onuchannel")
1528 onu.Channel <- msg
1529 } else {
1530 oltLogger.WithFields(log.Fields{
1531 "IntfId": onu.PonPortID,
1532 "OnuId": onu.ID,
1533 "OnuSn": onu.Sn(),
1534 }).Debug("can-not-send-onu-packet-out-to-onu")
1535 }
1536 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001537
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001538 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001539}
1540
Shrey Baid688b4242020-07-10 20:40:10 +05301541func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001542
1543 // OLT Reboot is called in two cases:
1544 // - 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)
1545 // - when an OLT needs to be rebooted (voltcl device reboot)
1546
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001547 oltLogger.WithFields(log.Fields{
1548 "oltId": o.ID,
1549 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301550 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301551 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001552 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001553}
1554
Shrey Baid688b4242020-07-10 20:40:10 +05301555func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301556 oltLogger.WithFields(log.Fields{
1557 "oltId": o.ID,
1558 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301559 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301560
Pragya Arya2225f202020-01-29 18:05:01 +05301561 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001562 oltMsg := types.Message{
1563 Type: types.OltIndication,
1564 Data: types.OltIndicationMessage{
1565 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301566 },
Pragya Arya1881df02020-01-29 18:05:01 +05301567 }
Pragya Arya2225f202020-01-29 18:05:01 +05301568 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301569
Pragya Arya2225f202020-01-29 18:05:01 +05301570 for _, pon := range o.Pons {
1571 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001572 msg := types.Message{
1573 Type: types.PonIndication,
1574 Data: types.PonIndicationMessage{
1575 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301576 PonPortID: pon.ID,
1577 },
1578 }
1579 o.channel <- msg
1580 }
1581 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001582
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001583 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001584}
1585
Shrey Baid688b4242020-07-10 20:40:10 +05301586func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001587 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1588
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001589 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1590
1591 if err != nil {
1592 return nil, err
1593 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001594 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001595}
1596
Shrey Baid688b4242020-07-10 20:40:10 +05301597func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001598 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001599 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001600}
1601
nikesh.krishnandd07b922023-07-05 23:55:42 +05301602func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuInfo, error) {
1603 pon, err := o.GetPonById(packet.GetIntfId())
1604 if err != nil {
1605 log.WithFields(log.Fields{
1606 "OnuId": packet.GetOnuId(),
1607 "IntfId": packet.GetIntfId(),
1608 "err": err,
1609 }).Error("Can't find PonPort")
1610 return nil, err
1611 }
1612 onu, _ := pon.GetOnuById(packet.GetOnuId())
1613 if err != nil {
1614 log.WithFields(log.Fields{
1615 "OnuId": packet.GetOnuId(),
1616 "IntfId": packet.GetIntfId(),
1617 "err": err,
1618 }).Error("Can't find Onu")
1619 return nil, err
1620 }
1621
1622 resp := new(openolt.OnuInfo)
1623 resp.OnuId = packet.GetOnuId()
1624 if onu.OperState.Current() == "up" {
1625 resp.Losi = openolt.AlarmState_OFF
1626 resp.Lofi = openolt.AlarmState_OFF
1627 resp.Loami = openolt.AlarmState_OFF
1628 } else if onu.OperState.Current() == "down" {
1629 resp.Losi = openolt.AlarmState_ON
1630 resp.Lofi = openolt.AlarmState_ON
1631 resp.Loami = openolt.AlarmState_ON
1632 }
1633 if onu.InternalState.Current() == OnuStateEnabled {
1634 resp.State = openolt.OnuInfo_ACTIVE
1635 } else if onu.InternalState.Current() == OnuStateDisabled {
1636 resp.State = openolt.OnuInfo_INACTIVE
1637 } else if onu.InternalState.Current() == OnuStateCreated || (onu.InternalState.Current() == OnuStateInitialized) {
1638 resp.State = openolt.OnuInfo_NOT_CONFIGURED
1639 } else {
1640 resp.State = openolt.OnuInfo_UNKNOWN
1641 }
1642 log.WithFields(log.Fields{
1643 "OnuId": packet.GetOnuId(),
1644 "IntfId": packet.GetIntfId(),
1645 "response": resp,
1646 }).Info("Response for onu info")
1647 return resp, nil
1648}
1649
1650func (o *OltDevice) GetPonInterfaceInfo(context context.Context, packet *openolt.Interface) (*openolt.PonIntfInfo, error) {
1651 ponPort, err := o.GetPonById(packet.GetIntfId())
1652 if err != nil {
1653 log.WithFields(log.Fields{
1654 "IntfId": packet.GetIntfId(),
1655 "err": err,
1656 }).Error("Can't find PonPort")
1657 return nil, err
1658 }
1659 resp := new(openolt.PonIntfInfo)
1660 resp.IntfId = packet.GetIntfId()
1661 if ponPort.OperState.Current() == "up" {
1662 resp.Los = openolt.AlarmState_OFF
1663 } else if ponPort.OperState.Current() == "down" {
1664 resp.Los = openolt.AlarmState_ON
1665 }
1666 if ponPort.InternalState.Current() == "enabled" {
1667 resp.State = openolt.PonIntfInfo_ACTIVE_WORKING
1668 } else if ponPort.InternalState.Current() == "disabled" {
1669 resp.State = openolt.PonIntfInfo_INACTIVE
1670 } else if ponPort.InternalState.Current() == "created" {
1671 resp.State = openolt.PonIntfInfo_ACTIVE_STANDBY
1672 } else {
1673 resp.State = openolt.PonIntfInfo_UNKNOWN
1674 }
1675 log.WithFields(log.Fields{
1676 "IntfId": packet.GetIntfId(),
1677 "response": resp,
1678 }).Info("Response for pon info")
1679 return resp, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001680}
1681
Shrey Baid688b4242020-07-10 20:40:10 +05301682func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001683 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001684 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001685}
1686
Shrey Baid688b4242020-07-10 20:40:10 +05301687func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001688 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001689 return new(openolt.Empty), nil
1690}
1691
Matteo Scandolo8a574812021-05-20 15:18:53 -07001692func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1693 oltLogger.WithFields(log.Fields{
1694 "OnuId": tq.OnuId,
1695 "IntfId": tq.IntfId,
1696 "OnuPortNo": tq.PortNo,
1697 "UniId": tq.UniId,
1698 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001699 return new(openolt.Empty), nil
1700}
1701
Matteo Scandolo8a574812021-05-20 15:18:53 -07001702func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301703 oltLogger.WithFields(log.Fields{
1704 "OnuId": trafficSchedulers.OnuId,
1705 "IntfId": trafficSchedulers.IntfId,
1706 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001707 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301708 }).Info("received CreateTrafficSchedulers")
1709
1710 if !s.enablePerf {
1711 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1712 if err != nil {
1713 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1714 return new(openolt.Empty), err
1715 }
1716 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1717 if err != nil {
1718 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1719 return new(openolt.Empty), err
1720 }
1721 onu.TrafficSchedulers = trafficSchedulers
1722 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001723 return new(openolt.Empty), nil
1724}
1725
Shrey Baid688b4242020-07-10 20:40:10 +05301726func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301727 oltLogger.WithFields(log.Fields{
1728 "OnuId": trafficSchedulers.OnuId,
1729 "IntfId": trafficSchedulers.IntfId,
1730 "OnuPortNo": trafficSchedulers.PortNo,
1731 }).Info("received RemoveTrafficSchedulers")
1732 if !s.enablePerf {
1733 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1734 if err != nil {
1735 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1736 return new(openolt.Empty), err
1737 }
1738 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1739 if err != nil {
1740 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1741 return new(openolt.Empty), err
1742 }
1743
1744 onu.TrafficSchedulers = nil
1745 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001746 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001747}
Scott Baker41724b82020-01-21 19:54:53 -08001748
Matteo Scandolo618a6582020-09-09 12:21:29 -07001749func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1750 oltLogger.WithFields(log.Fields{
1751 "GroupId": group.GroupId,
1752 "Command": group.Command,
1753 "Members": group.Members,
1754 "Action": group.Action,
1755 }).Debug("received PerformGroupOperation")
1756 return &openolt.Empty{}, nil
1757}
1758
1759func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1760 oltLogger.WithFields(log.Fields{
1761 "GroupId": group.GroupId,
1762 "Command": group.Command,
1763 "Members": group.Members,
1764 "Action": group.Action,
1765 }).Debug("received PerformGroupOperation")
1766 return &openolt.Empty{}, nil
1767}
1768
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001769func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1770 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001771}
1772
1773func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1774 return &openolt.Empty{}, nil
1775}
1776
1777func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1778 return &openolt.OnuLogicalDistance{}, nil
1779}
1780
1781func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1782 return &openolt.OnuLogicalDistance{}, nil
1783}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001784
Girish Gowdra62f24292021-05-12 16:28:39 -07001785func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
praneeth.nalmas7aa24df2023-03-24 10:49:43 +05301786 //VOL-4878:Hardcoding the power levels for testing as BBSIM is a simulator
1787 return &openolt.PonRxPowerData{IntfId: in.IntfId, OnuId: in.OnuId, Status: "success", FailReason: 0, RxPowerMeanDbm: -6}, nil
Girish Gowdra62f24292021-05-12 16:28:39 -07001788}
1789
Matteo Scandolo96f89192021-03-12 13:17:26 -08001790func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1791 return &openolt.GemPortStatistics{}, nil
1792}
1793
1794func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1795 return &openolt.OnuStatistics{}, nil
1796}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001797
1798func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1799 o.AllocIDsLock.Lock()
1800 defer o.AllocIDsLock.Unlock()
1801
Matteo Scandolo21195d62021-04-07 14:31:23 -07001802 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1803 oltLogger.WithFields(log.Fields{
1804 "IntfId": flow.AccessIntfId,
1805 "OnuId": flow.OnuId,
1806 "PortNo": flow.PortNo,
1807 "GemportId": flow.GemportId,
1808 "FlowId": flow.FlowId,
1809 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1810 }
1811
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001812 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001813 "IntfId": flow.AccessIntfId,
1814 "OnuId": flow.OnuId,
1815 "PortNo": flow.PortNo,
1816 "GemportId": flow.GemportId,
1817 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001818 }).Trace("storing-alloc-id-via-flow")
1819
1820 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1821 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1822 }
1823 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1824 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1825 }
1826 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1827}
1828
1829func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1830 // if this is the last flow referencing the AllocId then remove it
1831 o.AllocIDsLock.Lock()
1832 defer o.AllocIDsLock.Unlock()
1833
1834 oltLogger.WithFields(log.Fields{
1835 "IntfId": flow.AccessIntfId,
1836 "OnuId": flow.OnuId,
1837 "PortNo": flow.PortNo,
1838 "GemportId": flow.GemportId,
1839 }).Trace("freeing-alloc-id-via-flow")
1840
1841 // NOTE look at the freeGemPortId implementation for comments and context
1842 for ponId, ponValues := range o.AllocIDs {
1843 for onuId, onuValues := range ponValues {
1844 for uniId, uniValues := range onuValues {
1845 for allocId, flows := range uniValues {
1846 for flowId := range flows {
1847 // if the flow matches, remove it from the map.
1848 if flow.FlowId == flowId {
1849 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1850 }
1851 // if that was the last flow for a particular allocId, remove the entire allocId
1852 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1853 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1854 }
1855 }
1856 }
1857 }
1858 }
1859 }
1860}
1861
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301862func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) error {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001863 o.GemPortIDsLock.Lock()
1864 defer o.GemPortIDsLock.Unlock()
1865
1866 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1867 oltLogger.WithFields(log.Fields{
1868 "IntfId": ponId,
1869 "OnuId": onuId,
1870 "PortNo": portNo,
1871 "GemportId": gemId,
1872 "FlowId": flowId,
1873 }).Error("trying-to-store-gemport-for-unknown-onu")
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301874 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 -07001875 }
1876
1877 oltLogger.WithFields(log.Fields{
1878 "IntfId": ponId,
1879 "OnuId": onuId,
1880 "PortNo": portNo,
1881 "GemportId": gemId,
1882 "FlowId": flowId,
1883 }).Trace("storing-alloc-id-via-flow")
1884
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001885 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1886 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1887 }
1888 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1889 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1890 }
1891 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301892
1893 return nil
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001894}
1895
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301896func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001897 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001898 "IntfId": flow.AccessIntfId,
1899 "OnuId": flow.OnuId,
1900 "PortNo": flow.PortNo,
1901 "GemportId": flow.GemportId,
1902 "FlowId": flow.FlowId,
1903 "ReplicateFlow": flow.ReplicateFlow,
1904 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001905 }).Trace("storing-gem-port-id-via-flow")
1906
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001907 if flow.ReplicateFlow {
1908 for _, gem := range flow.PbitToGemport {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301909 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1910 if err != nil {
1911 return err
1912 }
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001913 }
1914 } else {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301915 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
1916 if err != nil {
1917 return err
1918 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001919 }
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301920
1921 return nil
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001922}
1923
1924func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1925 // if this is the last flow referencing the GemPort then remove it
1926 o.GemPortIDsLock.Lock()
1927 defer o.GemPortIDsLock.Unlock()
1928
1929 oltLogger.WithFields(log.Fields{
1930 "IntfId": flow.AccessIntfId,
1931 "OnuId": flow.OnuId,
1932 "PortNo": flow.PortNo,
1933 "GemportId": flow.GemportId,
1934 }).Trace("freeing-gem-port-id-via-flow")
1935
1936 // NOTE that this loop is not very performant, it would be better if the flow carries
1937 // the same information that it carries during a FlowAdd. If so we can directly remove
1938 // items from the map
1939
1940 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1941 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1942 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1943 //}
1944
1945 // NOTE this loop assumes that flow IDs are unique per device
1946 for ponId, ponValues := range o.GemPortIDs {
1947 for onuId, onuValues := range ponValues {
1948 for uniId, uniValues := range onuValues {
1949 for gemId, flows := range uniValues {
1950 for flowId := range flows {
1951 // if the flow matches, remove it from the map.
1952 if flow.FlowId == flowId {
1953 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1954 }
1955 // if that was the last flow for a particular gem, remove the entire gem
1956 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1957 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1958 }
1959 }
1960 }
1961 }
1962 }
1963 }
1964}
1965
1966// validateFlow checks that:
1967// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1968// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1969func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001970 // validate gemPort
1971 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001972 defer o.GemPortIDsLock.RUnlock()
1973 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001974 if onuId == uint32(flow.OnuId) {
1975 continue
1976 }
1977 for uniId, uni := range onu {
1978 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001979 if flow.ReplicateFlow {
1980 for _, flowGem := range flow.PbitToGemport {
1981 if gem == int32(flowGem) {
1982 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1983 }
1984 }
1985 } else {
1986 if gem == flow.GemportId {
1987 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1988 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001989 }
1990 }
1991 }
1992 }
1993
1994 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001995 defer o.AllocIDsLock.RUnlock()
1996 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001997 if onuId == uint32(flow.OnuId) {
1998 continue
1999 }
2000 for uniId, uni := range onu {
2001 for allocId := range uni {
2002 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07002003 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 -08002004 }
2005 }
2006 }
2007 }
2008
2009 return nil
2010}
2011
2012// clearAllResources is invoked up OLT Reboot to remove all the allocated
2013// GemPorts, AllocId and ONU-IDs across the PONs
2014func (o *OltDevice) clearAllResources() {
2015
2016 // remove the resources received via flows
2017 o.GemPortIDsLock.Lock()
2018 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
2019 o.GemPortIDsLock.Unlock()
2020 o.AllocIDsLock.Lock()
2021 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
2022 o.AllocIDsLock.Unlock()
2023
2024 // remove the resources received via OMCI
2025 for _, pon := range o.Pons {
2026 pon.removeAllAllocIds()
2027 pon.removeAllGemPorts()
2028 pon.removeAllOnuIds()
2029 }
2030}