blob: 417e316481de697bdf24158642f6d97c9ad22ba9 [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
Abhay Kumar31af8542023-12-02 11:00:39 +0530228 olt.AllocIDsLock.Lock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800229 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
Abhay Kumar31af8542023-12-02 11:00:39 +0530230 olt.AllocIDsLock.Unlock()
231 olt.GemPortIDsLock.Lock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800232 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
Abhay Kumar31af8542023-12-02 11:00:39 +0530233 olt.GemPortIDsLock.Unlock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800234
Elia Battistonb7bea222022-02-18 16:25:00 +0100235 p := CreatePonPort(&olt, uint32(i), tech)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700236
Matteo Scandolo4a036262020-08-17 15:56:13 -0700237 // create ONU devices
Elia Battistonb7bea222022-02-18 16:25:00 +0100238 if (ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1) < uint32(olt.NumOnuPerPon) {
239 oltLogger.WithFields(log.Fields{
240 "OnuRange": ponConf.OnuRange,
241 "RangeSize": ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1,
242 "NumOnuPerPon": olt.NumOnuPerPon,
243 "IntfId": i,
244 }).Fatal("onus-per-pon-bigger-than-resource-range-size")
245 }
246
Matteo Scandolo4a036262020-08-17 15:56:13 -0700247 for j := 0; j < olt.NumOnuPerPon; j++ {
248 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700249 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700250
Matteo Scandolo4a036262020-08-17 15:56:13 -0700251 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700252 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700253 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700254 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100255
Shrey Baid688b4242020-07-10 20:40:10 +0530256 if !isMock {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100257 if err := olt.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700258 log.Errorf("Error initializing OLT: %v", err)
259 return nil
260 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100261 }
262
Pragya Arya324337e2020-02-20 14:35:08 +0530263 if olt.PublishEvents {
264 log.Debugf("BBSim event publishing is enabled")
265 // Create a channel to write event messages
266 olt.EventChannel = make(chan common.Event, 100)
267 }
268
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700269 return &olt
270}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700271
Shrey Baid688b4242020-07-10 20:40:10 +0530272func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100273
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000274 if o.OltServer == nil {
275 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100276 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800277 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100278 }
279
280 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800281 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100282
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100283 // FIXME we are assuming we have only one NNI
284 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800285 // NOTE we want to make sure the state is down when we initialize the OLT,
286 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
287 // in-band management
288 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100289 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800290
291 for ponId := range o.Pons {
292 // initialize the resource maps for every PON Ports
Abhay Kumar31af8542023-12-02 11:00:39 +0530293 olt.AllocIDsLock.Lock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800294 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
Abhay Kumar31af8542023-12-02 11:00:39 +0530295 olt.AllocIDsLock.Unlock()
296 olt.GemPortIDsLock.Lock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800297 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
Abhay Kumar31af8542023-12-02 11:00:39 +0530298 olt.GemPortIDsLock.Unlock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800299 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700300}
301
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800302func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100303
Matteo Scandolo96f89192021-03-12 13:17:26 -0800304 o.PreviouslyConnected = false
305
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700306 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700307 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800308
309 oltLogger.WithFields(log.Fields{
310 "oltId": o.ID,
311 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
312
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100313 if o.InternalState.Is(OltInternalStateEnabled) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700314 oltLogger.WithFields(log.Fields{
315 "oltId": o.ID,
316 }).Info("This is an OLT soft reboot")
317 softReboot = true
318 }
319
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800320 // transition internal state to deleted
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100321 if err := o.InternalState.Event(OltInternalTxDelete); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800322 oltLogger.WithFields(log.Fields{
323 "oltId": o.ID,
324 }).Errorf("Error deleting OLT: %v", err)
325 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100326 }
327
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700328 if softReboot {
329 for _, pon := range o.Pons {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530330 /* No need to send pon events on olt soft reboot
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700331 if pon.InternalState.Current() == "enabled" {
332 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800333 msg := types.Message{
334 Type: types.PonIndication,
335 Data: types.PonIndicationMessage{
336 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700337 PonPortID: pon.ID,
338 },
339 }
340 o.channel <- msg
341 }
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530342 */
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700343 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100344 err := onu.InternalState.Event(OnuTxDisable)
345 oltLogger.WithFields(log.Fields{
346 "oltId": o.ID,
347 "onuId": onu.ID,
348 }).Errorf("Error disabling ONUs on OLT soft reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700349 }
350 }
351 } else {
352 // PONs are already handled in the Disable call
353 for _, pon := range olt.Pons {
354 // ONUs are not automatically disabled when a PON goes down
355 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
356 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100357 err := onu.InternalState.Event(OnuTxDisable)
358 oltLogger.WithFields(log.Fields{
359 "oltId": o.ID,
360 "onuId": onu.ID,
Matteo Scandolofbb94ae2022-04-14 14:17:47 -0700361 "OnuSn": onu.Sn(),
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100362 }).Errorf("Error disabling ONUs on OLT reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700363 }
Pragya Arya2225f202020-01-29 18:05:01 +0530364 }
365 }
366
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700367 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
368 o.StopOltServer()
369
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100370 // terminate the OLT's processOltMessages go routine
371 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700372
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100373 oltLogger.WithFields(log.Fields{
374 "oltId": o.ID,
375 }).Infof("Waiting OLT restart for... (%ds)", rebootDelay)
376
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100377 //Prevents Enable to progress before the reboot is completed (VOL-4616)
378 o.Lock()
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700379 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100380 time.Sleep(time.Duration(rebootDelay) * time.Second)
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100381 o.Unlock()
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530382 o.signature = uint32(time.Now().Unix())
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100383
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100384 if err := o.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800385 oltLogger.WithFields(log.Fields{
386 "oltId": o.ID,
387 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100388 return err
389 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800390 oltLogger.WithFields(log.Fields{
391 "oltId": o.ID,
392 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100393 return nil
394}
395
396// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800397func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700398 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700399 lis, err := net.Listen("tcp", address)
400 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700401 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700402 }
403 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100404
Matteo Scandolo4747d292019-08-05 11:50:18 -0700405 openolt.RegisterOpenoltServer(grpcServer, o)
406
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100407 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700408
Shrey Baid688b4242020-07-10 20:40:10 +0530409 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100410 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700411
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100412 return grpcServer, nil
413}
414
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800415// StartOltServer will create the grpc server that VOLTHA uses
416// to communicate with the device
417func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
418 oltServer, err := o.newOltServer()
419 if err != nil {
420 oltLogger.WithFields(log.Fields{
421 "err": err,
422 }).Error("Cannot OLT gRPC server")
423 return nil, err
424 }
425 return oltServer, nil
426}
427
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100428// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800429func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000430 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800431 oltLogger.WithFields(log.Fields{
432 "oltId": o.SerialNumber,
433 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000434 o.OltServer.Stop()
435 o.OltServer = nil
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100436 } else {
437 oltLogger.WithFields(log.Fields{
438 "oltId": o.SerialNumber,
439 }).Warnf("OLT gRPC server is already stopped")
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700440 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700441}
442
443// Device Methods
444
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100445// Enable implements the OpenOLT EnableIndicationServer functionality
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100446func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700447 oltLogger.Debug("Enable OLT called")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100448
449 if o.InternalState.Is(OltInternalStateDeleted) {
450 err := fmt.Errorf("Cannot enable OLT while it is rebooting")
451 oltLogger.WithFields(log.Fields{
452 "oltId": o.SerialNumber,
453 "internalState": o.InternalState.Current(),
454 }).Error(err)
455 return err
456 }
457
Pragya Arya2225f202020-01-29 18:05:01 +0530458 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700459
David Bainbridge103cf022019-12-16 20:11:35 +0000460 // If enabled has already been called then an enabled context has
461 // been created. If this is the case then we want to cancel all the
462 // proessing loops associated with that enable before we recreate
463 // new ones
464 o.Lock()
465 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700466 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000467 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530468 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700469 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000470 }
471 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
472 o.Unlock()
473
Matteo Scandolo4747d292019-08-05 11:50:18 -0700474 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700475
Matteo Scandolo4a036262020-08-17 15:56:13 -0700476 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530477
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100478 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700479 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000480 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700481
482 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800483 oltMsg := types.Message{
484 Type: types.OltIndication,
485 Data: types.OltIndicationMessage{
486 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700487 },
488 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100489 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700490
491 // send NNI Port Indications
492 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800493 msg := types.Message{
494 Type: types.NniIndication,
495 Data: types.NniIndicationMessage{
496 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700497 NniPortID: nni.ID,
498 },
499 }
500 o.channel <- msg
501 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100502
Shrey Baid688b4242020-07-10 20:40:10 +0530503 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530504 for _, pon := range o.Pons {
505 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800506 msg := types.Message{
507 Type: types.PonIndication,
508 Data: types.PonIndicationMessage{
509 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530510 PonPortID: pon.ID,
511 },
512 }
513 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000514 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700515 // when the enableContext was canceled the ONUs stopped listening on the channel
516 for _, onu := range pon.Onus {
TorstenThieme37ddd392022-07-13 12:56:24 +0000517 if o.ControlledActivation != OnlyONU {
518 onu.ReDiscoverOnu(true)
519 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700520 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
521
522 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700523 for _, uni := range onu.UniPorts {
524 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700525 }
526 }
Pragya Arya2225f202020-01-29 18:05:01 +0530527 }
528 } else {
529
530 // 1. controlledActivation == Default: Send both PON and ONUs indications
531 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
532
533 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
534 // send PON Port indications
535 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800536 msg := types.Message{
537 Type: types.PonIndication,
538 Data: types.PonIndicationMessage{
539 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530540 PonPortID: pon.ID,
541 },
542 }
543 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700544 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700545 }
546 }
547
Pragya Arya996a0892020-03-09 21:47:52 +0530548 if !o.enablePerf {
549 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700550 wg.Add(1)
551 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530552 }
553
Matteo Scandolo4747d292019-08-05 11:50:18 -0700554 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700555 oltLogger.WithFields(log.Fields{
556 "stream": stream,
557 }).Debug("OpenOLT Stream closed")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100558
559 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700560}
561
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700562func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530563 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700564
565loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530566 for {
567 select {
568 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
569 // send NNI port stats
570 for _, port := range o.Nnis {
571 incrementStat := true
572 if port.OperState.Current() == "down" {
573 incrementStat = false
574 }
575 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700576 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530577 }
578
579 // send PON port stats
580 for _, port := range o.Pons {
581 incrementStat := true
582 // do not increment port stats if PON port is down or no ONU is activated on PON port
583 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
584 incrementStat = false
585 }
586 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700587 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530588 }
589 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700590 oltLogger.Debug("Stop sending port stats")
591 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530592 }
Pragya Arya996a0892020-03-09 21:47:52 +0530593 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700594 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530595}
596
Matteo Scandolo4747d292019-08-05 11:50:18 -0700597// Helpers method
598
Matteo Scandolof9d43412021-01-12 11:11:34 -0800599func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
600
601 switch interfaceType {
602 case "nni":
603 if !o.HasNni(interfaceId) {
604 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
605 }
606
607 case "pon":
608 if !o.HasPon(interfaceId) {
609 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
610 }
611 }
612
613 alarmIndication := &openolt.AlarmIndication{
614 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
615 Status: alarmStatus,
616 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
617 }},
618 }
619
620 msg := types.Message{
621 Type: types.AlarmIndication,
622 Data: alarmIndication,
623 }
624
625 o.channel <- msg
626
627 return nil
628}
629
630func (o *OltDevice) HasNni(id uint32) bool {
631 for _, intf := range o.Nnis {
632 if intf.ID == id {
633 return true
634 }
635 }
636 return false
637}
638
639func (o *OltDevice) HasPon(id uint32) bool {
640 for _, intf := range o.Pons {
641 if intf.ID == id {
642 return true
643 }
644 }
645 return false
646}
647
Shrey Baid688b4242020-07-10 20:40:10 +0530648func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700649 for _, pon := range o.Pons {
650 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700651 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700652 }
653 }
Shrey Baid688b4242020-07-10 20:40:10 +0530654 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655}
656
Shrey Baid688b4242020-07-10 20:40:10 +0530657func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700658 for _, nni := range o.Nnis {
659 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700660 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700661 }
662 }
Shrey Baid688b4242020-07-10 20:40:10 +0530663 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664}
665
Scott Baker41724b82020-01-21 19:54:53 -0800666func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
667 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
668 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
669 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
670 return
671 }
672
673 oltLogger.WithFields(log.Fields{
674 "AlarmIndication": alarmInd,
675 }).Debug("Sent Indication_AlarmInd")
676}
677
Matteo Scandolof9d43412021-01-12 11:11:34 -0800678func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700679 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
680 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700681 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800682 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700683 }
684
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700685 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700686 "OperState": msg.OperState,
687 }).Debug("Sent Indication_OltInd")
688}
689
Matteo Scandolof9d43412021-01-12 11:11:34 -0800690func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700691 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800692 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800693 if err := nni.OperState.Event("enable"); 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 enabled state: %v", err)
699 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800700 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800701 if err := nni.OperState.Event("disable"); err != nil {
702 log.WithFields(log.Fields{
703 "Type": nni.Type,
704 "IntfId": nni.ID,
705 "OperState": nni.OperState.Current(),
706 }).Errorf("Can't move NNI Port to disable state: %v", err)
707 }
708 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700709 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700710 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700711 Type: nni.Type,
712 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700713 OperState: nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100714 Speed: o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700715 }}
716
717 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700718 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800719 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700720 }
721
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700722 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700723 "Type": nni.Type,
724 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700725 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100726 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700727 }).Debug("Sent Indication_IntfOperInd for NNI")
728}
729
Pragya Arya2225f202020-01-29 18:05:01 +0530730func (o *OltDevice) sendPonIndication(ponPortID uint32) {
731
Matteo Scandolo4a036262020-08-17 15:56:13 -0700732 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530733 pon, _ := o.GetPonById(ponPortID)
734 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700735 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700736 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700737 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700738 }}
739
740 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700741 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800742 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700743 }
744
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700745 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700746 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700747 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700748 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700749
Pragya Arya2225f202020-01-29 18:05:01 +0530750 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700751 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700752 Type: pon.Type,
753 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700754 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700755 }}
756
757 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700758 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800759 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700760 }
761
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700762 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700763 "Type": pon.Type,
764 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700765 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700766 }).Debug("Sent Indication_IntfOperInd for PON")
767}
768
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700769func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100770 if o.InternalState.Current() == OltInternalStateEnabled {
Shrey Baid55f328c2020-07-07 19:20:42 +0530771 oltLogger.WithFields(log.Fields{
772 "Type": portType,
773 "IntfId": portID,
774 }).Trace("Sending port stats")
775 stats.IntfId = InterfaceIDToPortNo(portID, portType)
776 data := &openolt.Indication_PortStats{
777 PortStats: stats,
778 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700779
Shrey Baid55f328c2020-07-07 19:20:42 +0530780 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
781 oltLogger.Errorf("Failed to send PortStats: %v", err)
782 return
783 }
Pragya Arya996a0892020-03-09 21:47:52 +0530784 }
785}
786
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100787// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700788func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
789 oltLogger.WithFields(log.Fields{
790 "stream": stream,
791 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000792 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700793
David Bainbridge103cf022019-12-16 20:11:35 +0000794loop:
795 for {
796 select {
797 case <-ctx.Done():
798 oltLogger.Debug("OLT Indication processing canceled via context")
799 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700800 // do not terminate this loop if the stream is closed,
801 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
802 //case <-stream.Context().Done():
803 // oltLogger.Debug("OLT Indication processing canceled via stream context")
804 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000805 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700806 if !ok {
807 if ctx.Err() != nil {
808 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
809 }
810 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000811 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700812 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700813
David Bainbridge103cf022019-12-16 20:11:35 +0000814 oltLogger.WithFields(log.Fields{
815 "oltId": o.ID,
816 "messageType": message.Type,
817 }).Trace("Received message")
818
819 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800820 case types.OltIndication:
821 msg, _ := message.Data.(types.OltIndicationMessage)
822 if msg.OperState == types.UP {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100823 _ = o.InternalState.Event(OltInternalTxEnable)
Shrey Baid688b4242020-07-10 20:40:10 +0530824 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800825 } else if msg.OperState == types.DOWN {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100826 _ = o.InternalState.Event(OltInternalTxDisable)
Shrey Baid688b4242020-07-10 20:40:10 +0530827 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000828 }
829 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800830 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800831 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
832 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800833 case types.NniIndication:
834 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000835 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800836 case types.PonIndication:
837 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530838 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800839 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530840 if err := pon.OperState.Event("enable"); err != nil {
841 oltLogger.WithFields(log.Fields{
842 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800843 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530844 }).Error("Can't Enable Oper state for PON Port")
845 }
846 if err := pon.InternalState.Event("enable"); err != nil {
847 oltLogger.WithFields(log.Fields{
848 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800849 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530850 }).Error("Can't Enable Internal state for PON Port")
851 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800852 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530853 if err := pon.OperState.Event("disable"); err != nil {
854 oltLogger.WithFields(log.Fields{
855 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800856 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530857 }).Error("Can't Disable Oper state for PON Port")
858 }
859 if err := pon.InternalState.Event("disable"); err != nil {
860 oltLogger.WithFields(log.Fields{
861 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800862 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530863 }).Error("Can't Disable Internal state for PON Port")
864 }
Pragya Arya2225f202020-01-29 18:05:01 +0530865 }
David Bainbridge103cf022019-12-16 20:11:35 +0000866 default:
867 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
868 }
869 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700870 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100871 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700872 oltLogger.WithFields(log.Fields{
873 "stream": stream,
874 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700875}
876
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700877// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530878func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700879 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700880 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700881 for _, pon := range o.Pons {
882 for _, onu := range pon.Onus {
883 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700884 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700885 }
886 }
887 }
888
Shrey Baid688b4242020-07-10 20:40:10 +0530889 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700890}
891
William Kurkian9dadc5b2019-10-22 13:51:57 -0400892// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530893func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700894 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400895 // memoizing it will remove the bottleneck
896 for _, pon := range o.Pons {
897 if pon.ID == intfId {
898 for _, onu := range pon.Onus {
899 if onu.ID == onuId {
900 return onu, nil
901 }
902 }
903 }
904 }
Shrey Baid688b4242020-07-10 20:40:10 +0530905 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400906}
907
Matteo Scandolo4a036262020-08-17 15:56:13 -0700908// returns a Service with a given Mac Address
909func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700910 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700911 // memoizing it will remove the bottleneck
912 for _, pon := range o.Pons {
913 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700914 s, err := onu.findServiceByMacAddress(mac)
915 if err == nil {
916 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700917 }
918 }
919 }
920
Matteo Scandolo4a036262020-08-17 15:56:13 -0700921 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700922}
923
Matteo Scandolo4747d292019-08-05 11:50:18 -0700924// GRPC Endpoints
925
Shrey Baid688b4242020-07-10 20:40:10 +0530926func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700927
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700928 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800929
Matteo Scandolo8a574812021-05-20 15:18:53 -0700930 // Enable the resource maps for this ONU
Abhay Kumar31af8542023-12-02 11:00:39 +0530931 olt.AllocIDsLock.Lock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800932 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
Abhay Kumar31af8542023-12-02 11:00:39 +0530933 olt.AllocIDsLock.Unlock()
934 olt.GemPortIDsLock.Lock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800935 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
Abhay Kumar31af8542023-12-02 11:00:39 +0530936 olt.GemPortIDsLock.Unlock()
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800937
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700938 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700939
940 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
941 oltLogger.WithFields(log.Fields{
942 "OnuSn": _onu.Sn(),
943 }).Info("Received ActivateOnu call from VOLTHA")
944
William Kurkian0418bc82019-11-06 12:16:24 -0500945 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700946
Matteo Scandolocedde462021-03-09 17:37:16 -0800947 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700948 oltLogger.WithFields(log.Fields{
949 "IntfId": _onu.PonPortID,
950 "OnuSn": _onu.Sn(),
951 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800952 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700953 }
954
955 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
956
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700957 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700958}
959
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800960func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700961 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700962 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700963}
964
Shrey Baid688b4242020-07-10 20:40:10 +0530965func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530966 oltLogger.WithFields(log.Fields{
967 "IntfId": onu.IntfId,
968 "OnuId": onu.OnuId,
969 }).Info("Received DeleteOnu call from VOLTHA")
970
971 pon, err := o.GetPonById(onu.IntfId)
972 if err != nil {
973 oltLogger.WithFields(log.Fields{
974 "OnuId": onu.OnuId,
975 "IntfId": onu.IntfId,
976 "err": err,
977 }).Error("Can't find PonPort")
nikesh.krishnan5e83f702023-11-10 23:40:48 +0530978 return nil, err
Pragya Arya1cbefa42020-01-13 12:15:29 +0530979 }
980 _onu, err := pon.GetOnuById(onu.OnuId)
981 if err != nil {
982 oltLogger.WithFields(log.Fields{
983 "OnuId": onu.OnuId,
984 "IntfId": onu.IntfId,
985 "err": err,
986 }).Error("Can't find Onu")
nikesh.krishnan5e83f702023-11-10 23:40:48 +0530987 return nil, err
Pragya Arya1cbefa42020-01-13 12:15:29 +0530988 }
989
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530990 if _onu.InternalState.Current() != OnuStateDisabled {
991 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
992 oltLogger.WithFields(log.Fields{
993 "IntfId": _onu.PonPortID,
994 "OnuSn": _onu.Sn(),
995 "OnuId": _onu.ID,
996 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
997 }
Hardik Windlassad790cb2020-06-17 21:26:22 +0530998 }
999
Hardik Windlassad790cb2020-06-17 21:26:22 +05301000 // ONU Re-Discovery
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001001 if o.InternalState.Current() == OltInternalStateEnabled && pon.InternalState.Current() == "enabled" {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301002 go _onu.ReDiscoverOnu(false)
Pragya Arya1cbefa42020-01-13 12:15:29 +05301003 }
1004
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001005 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001006}
1007
Shrey Baid688b4242020-07-10 20:40:10 +05301008func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001009 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001010 oltLogger.WithFields(log.Fields{
1011 "oltId": o.ID,
1012 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +05301013 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001014
Matteo Scandolo401503a2019-12-11 14:48:14 -08001015 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +05301016 if pon.InternalState.Current() == "enabled" {
1017 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -08001018 msg := types.Message{
1019 Type: types.PonIndication,
1020 Data: types.PonIndicationMessage{
1021 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +05301022 PonPortID: pon.ID,
1023 },
1024 }
1025 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001026 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001027 }
1028
Matteo Scandolo401503a2019-12-11 14:48:14 -08001029 // Note that we are not disabling the NNI as the real OLT does not.
1030 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001031
1032 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001033 oltMsg := types.Message{
1034 Type: types.OltIndication,
1035 Data: types.OltIndicationMessage{
1036 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001037 },
1038 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001039 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001040
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001041 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001042}
1043
Shrey Baid688b4242020-07-10 20:40:10 +05301044func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301045 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001046 ponID := intf.GetIntfId()
1047 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001048
Matteo Scandolof9d43412021-01-12 11:11:34 -08001049 msg := types.Message{
1050 Type: types.PonIndication,
1051 Data: types.PonIndicationMessage{
1052 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001053 PonPortID: ponID,
1054 },
1055 }
1056 o.channel <- msg
1057
1058 for _, onu := range pon.Onus {
1059
Matteo Scandolof9d43412021-01-12 11:11:34 -08001060 onuIndication := types.OnuIndicationMessage{
1061 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001062 PonPortID: ponID,
1063 OnuID: onu.ID,
1064 OnuSN: onu.SerialNumber,
1065 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001066 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001067
1068 }
1069
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001070 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001071}
1072
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001073func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001074 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301075 publishEvent("OLT-enable-received", -1, -1, "")
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001076 return o.Enable(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001077}
1078
Shrey Baid688b4242020-07-10 20:40:10 +05301079func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301080 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301081 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001082 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001083
Matteo Scandolof9d43412021-01-12 11:11:34 -08001084 msg := types.Message{
1085 Type: types.PonIndication,
1086 Data: types.PonIndicationMessage{
1087 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301088 PonPortID: ponID,
1089 },
1090 }
1091 o.channel <- msg
1092
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001093 for _, onu := range pon.Onus {
1094
Matteo Scandolof9d43412021-01-12 11:11:34 -08001095 onuIndication := types.OnuIndicationMessage{
1096 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001097 PonPortID: ponID,
1098 OnuID: onu.ID,
1099 OnuSN: onu.SerialNumber,
1100 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001101 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001102
1103 }
1104
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001105 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001106}
1107
Shrey Baid688b4242020-07-10 20:40:10 +05301108func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001109 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001110 "IntfId": flow.AccessIntfId,
1111 "OnuId": flow.OnuId,
1112 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001113 "InnerVlan": flow.Classifier.IVid,
1114 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001115 "FlowType": flow.FlowType,
1116 "FlowId": flow.FlowId,
1117 "UniID": flow.UniId,
1118 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301119 }).Tracef("OLT receives FlowAdd")
1120
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001121 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301122 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001123 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001124 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301125 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001126
1127 if flow.AccessIntfId == -1 {
1128 oltLogger.WithFields(log.Fields{
1129 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001130 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001131 } else if flow.FlowType == "multicast" {
1132 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001133 "Cookie": flow.Cookie,
1134 "DstPort": flow.Classifier.DstPort,
1135 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1136 "FlowId": flow.FlowId,
1137 "FlowType": flow.FlowType,
1138 "GemportId": flow.GemportId,
1139 "InnerVlan": flow.Classifier.IVid,
1140 "IntfId": flow.AccessIntfId,
1141 "IpProto": flow.Classifier.IpProto,
1142 "OnuId": flow.OnuId,
1143 "OuterVlan": flow.Classifier.OVid,
1144 "PortNo": flow.PortNo,
1145 "SrcPort": flow.Classifier.SrcPort,
1146 "UniID": flow.UniId,
1147 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001148 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001149 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001150 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001151 if err != nil {
1152 oltLogger.WithFields(log.Fields{
1153 "OnuId": flow.OnuId,
1154 "IntfId": flow.AccessIntfId,
1155 "err": err,
1156 }).Error("Can't find PonPort")
1157 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001158 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001159 if err != nil {
1160 oltLogger.WithFields(log.Fields{
1161 "OnuId": flow.OnuId,
1162 "IntfId": flow.AccessIntfId,
1163 "err": err,
1164 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001165 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001166 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001167
1168 // if the ONU is disabled reject the flow
1169 // as per VOL-4061 there is a small window during which the ONU is disabled
1170 // but the port has not been reported as down to ONOS
1171 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1172 oltLogger.WithFields(log.Fields{
1173 "OnuId": flow.OnuId,
1174 "IntfId": flow.AccessIntfId,
1175 "Flow": flow,
1176 "SerialNumber": onu.Sn(),
1177 "InternalState": onu.InternalState.Current(),
1178 }).Error("rejected-flow-because-of-onu-state")
1179 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1180 }
1181
Pragya Arya8bdb4532020-03-02 17:08:09 +05301182 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001183 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301184 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001185 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001186 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301187 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301188 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001189
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001190 // validate that the flow reference correct IDs (Alloc, Gem)
1191 if err := o.validateFlow(flow); err != nil {
1192 oltLogger.WithFields(log.Fields{
1193 "OnuId": flow.OnuId,
1194 "IntfId": flow.AccessIntfId,
1195 "Flow": flow,
1196 "SerialNumber": onu.Sn(),
1197 "err": err,
1198 }).Error("invalid-flow-for-onu")
1199 return nil, err
1200 }
1201
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301202 if err := o.storeGemPortIdByFlow(flow); err != nil {
1203 return nil, err
1204 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001205 o.storeAllocId(flow)
1206
Matteo Scandolof9d43412021-01-12 11:11:34 -08001207 msg := types.Message{
1208 Type: types.FlowAdd,
1209 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001210 PonPortID: pon.ID,
1211 OnuID: onu.ID,
1212 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001213 },
1214 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001215 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001216 }
1217
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001218 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001219}
1220
Pragya Arya8bdb4532020-03-02 17:08:09 +05301221// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301222func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001223
Pragya Arya8bdb4532020-03-02 17:08:09 +05301224 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001225 "AllocId": flow.AllocId,
1226 "Cookie": flow.Cookie,
1227 "FlowId": flow.FlowId,
1228 "FlowType": flow.FlowType,
1229 "GemportId": flow.GemportId,
1230 "IntfId": flow.AccessIntfId,
1231 "OnuId": flow.OnuId,
1232 "PortNo": flow.PortNo,
1233 "UniID": flow.UniId,
1234 "ReplicateFlow": flow.ReplicateFlow,
1235 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001236 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301237
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001238 olt.freeGemPortId(flow)
1239 olt.freeAllocId(flow)
1240
Pragya Arya8bdb4532020-03-02 17:08:09 +05301241 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001242 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301243 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001244 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301245 if !ok {
1246 oltLogger.Errorf("Flow %v not found", flow)
1247 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1248 }
1249
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001250 storedFlow := storedFlowIntf.(openolt.Flow)
1251
Pragya Arya8bdb4532020-03-02 17:08:09 +05301252 // if its ONU flow remove it from ONU also
1253 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001254 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1255 if err != nil {
1256 oltLogger.WithFields(log.Fields{
1257 "OnuId": storedFlow.OnuId,
1258 "IntfId": storedFlow.AccessIntfId,
1259 "PONs": olt.Pons,
1260 "err": err,
1261 }).Error("PON-port-not-found")
1262 return new(openolt.Empty), nil
1263 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301264 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1265 if err != nil {
1266 oltLogger.WithFields(log.Fields{
1267 "OnuId": storedFlow.OnuId,
1268 "IntfId": storedFlow.AccessIntfId,
1269 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001270 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301271 return new(openolt.Empty), nil
1272 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001273 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001274 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301275 }
1276
1277 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001278 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301279 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001280
1281 if flow.AccessIntfId == -1 {
1282 oltLogger.WithFields(log.Fields{
1283 "FlowId": flow.FlowId,
1284 }).Debug("Removing OLT flow")
1285 } else if flow.FlowType == "multicast" {
1286 oltLogger.WithFields(log.Fields{
1287 "FlowId": flow.FlowId,
1288 }).Debug("Removing OLT multicast flow")
1289 } else {
1290
1291 onu, err := o.GetOnuByFlowId(flow.FlowId)
1292 if err != nil {
1293 oltLogger.WithFields(log.Fields{
1294 "OnuId": flow.OnuId,
1295 "IntfId": flow.AccessIntfId,
1296 "err": err,
1297 }).Error("Can't find Onu")
1298 return nil, err
1299 }
1300
Matteo Scandolof9d43412021-01-12 11:11:34 -08001301 msg := types.Message{
1302 Type: types.FlowRemoved,
1303 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301304 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001305 },
1306 }
1307 onu.Channel <- msg
1308 }
1309
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001310 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001311}
1312
Shrey Baid688b4242020-07-10 20:40:10 +05301313func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301314 res := openolt.Heartbeat{HeartbeatSignature: o.signature}
Matteo Scandolo18859852020-01-15 13:33:57 -08001315 oltLogger.WithFields(log.Fields{
1316 "signature": res.HeartbeatSignature,
1317 }).Trace("HeartbeatCheck")
1318 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001319}
1320
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001321func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001322 for _, pon := range o.Pons {
1323 for _, onu := range pon.Onus {
1324 for _, fId := range onu.FlowIds {
1325 if fId == flowId {
1326 return onu, nil
1327 }
1328 }
1329 }
1330 }
Shrey Baid688b4242020-07-10 20:40:10 +05301331 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001332}
1333
Shrey Baid688b4242020-07-10 20:40:10 +05301334func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolocedde462021-03-09 17:37:16 -08001335 devinfo := &openolt.DeviceInfo{
1336 Vendor: common.Config.Olt.Vendor,
1337 Model: common.Config.Olt.Model,
1338 HardwareVersion: common.Config.Olt.HardwareVersion,
1339 FirmwareVersion: common.Config.Olt.FirmwareVersion,
Matteo Scandolocedde462021-03-09 17:37:16 -08001340 PonPorts: uint32(o.NumPon),
Matteo Scandolocedde462021-03-09 17:37:16 -08001341 DeviceSerialNumber: o.SerialNumber,
1342 DeviceId: common.Config.Olt.DeviceId,
1343 PreviouslyConnected: o.PreviouslyConnected,
Elia Battistonb7bea222022-02-18 16:25:00 +01001344 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{},
1345 }
1346
1347 for _, resRange := range common.PonsConfig.Ranges {
1348 intfIDs := []uint32{}
1349 for i := resRange.PonRange.StartId; i <= resRange.PonRange.EndId; i++ {
1350 intfIDs = append(intfIDs, uint32(i))
1351 }
1352
1353 devinfo.Ranges = append(devinfo.Ranges, &openolt.DeviceInfo_DeviceResourceRanges{
1354 IntfIds: intfIDs,
1355 Technology: resRange.Technology,
1356 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1357 {
1358 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1359 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1360 Start: resRange.OnuRange.StartId,
1361 End: resRange.OnuRange.EndId,
1362 },
1363 {
1364 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1365 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1366 Start: resRange.AllocIdRange.StartId,
1367 End: resRange.AllocIdRange.EndId,
1368 },
1369 {
1370 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1371 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1372 Start: resRange.GemportRange.StartId,
1373 End: resRange.GemportRange.EndId,
Matteo Scandolocedde462021-03-09 17:37:16 -08001374 },
1375 },
Elia Battistonb7bea222022-02-18 16:25:00 +01001376 })
Matteo Scandolocedde462021-03-09 17:37:16 -08001377 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001378
1379 oltLogger.WithFields(log.Fields{
1380 "Vendor": devinfo.Vendor,
1381 "Model": devinfo.Model,
1382 "HardwareVersion": devinfo.HardwareVersion,
1383 "FirmwareVersion": devinfo.FirmwareVersion,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001384 "PonPorts": devinfo.PonPorts,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001385 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1386 "DeviceId": devinfo.DeviceId,
1387 "PreviouslyConnected": devinfo.PreviouslyConnected,
1388 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1389
1390 // once we connect, set the flag
1391 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001392
1393 return devinfo, nil
1394}
1395
Shrey Baid688b4242020-07-10 20:40:10 +05301396func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001397 pon, err := o.GetPonById(omci_msg.IntfId)
1398 if err != nil {
1399 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001400 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001401 "onu_id": omci_msg.OnuId,
1402 "pon_id": omci_msg.IntfId,
1403 }).Error("pon ID not found")
1404 return nil, err
1405 }
1406
1407 onu, err := pon.GetOnuById(omci_msg.OnuId)
1408 if err != nil {
1409 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001410 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001411 "onu_id": omci_msg.OnuId,
1412 "pon_id": omci_msg.IntfId,
1413 }).Error("onu ID not found")
1414 return nil, err
1415 }
1416
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001417 oltLogger.WithFields(log.Fields{
1418 "IntfId": onu.PonPortID,
1419 "OnuId": onu.ID,
1420 "OnuSn": onu.Sn(),
1421 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001422 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1423 if err != nil {
1424 log.WithFields(log.Fields{
1425 "IntfId": onu.PonPortID,
1426 "SerialNumber": onu.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001427 "omciPacket": hex.EncodeToString(omci_msg.Pkt),
Matteo Scandolob5913142021-03-19 16:10:18 -07001428 "err": err.Error(),
1429 }).Error("cannot-parse-OMCI-packet")
1430 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001431 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001432 if onu.InternalState.Current() == OnuStateDisabled {
1433 // if the ONU is disabled just drop the message
1434 log.WithFields(log.Fields{
1435 "IntfId": onu.PonPortID,
1436 "SerialNumber": onu.Sn(),
1437 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1438 "omciPkt": omciPkt,
1439 "omciMsgType": omciMsg.MessageType,
1440 }).Warn("dropping-omci-message")
1441 } else {
1442 msg := types.Message{
1443 Type: types.OMCI,
1444 Data: types.OmciMessage{
1445 OnuSN: onu.SerialNumber,
1446 OnuID: onu.ID,
1447 OmciMsg: omciMsg,
1448 OmciPkt: omciPkt,
1449 },
1450 }
1451 onu.Channel <- msg
1452 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001453 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001454}
1455
Matteo Scandolo8a574812021-05-20 15:18:53 -07001456// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301457func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001458 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001459 if err != nil {
1460 oltLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001461 "OnuId": onuPkt.OnuId,
1462 "IntfId": onuPkt.IntfId,
1463 "GemportId": onuPkt.GemportId,
1464 "err": err,
Matteo Scandolo27428702019-10-11 16:21:16 -07001465 }).Error("Can't find PonPort")
1466 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001467
Baris Ertas53ab13c2023-05-25 16:31:48 +03001468 onus := make([]*Onu, 1)
1469 // If it's not addressed to multicast gem port
1470 if onuPkt.GemportId != multicastGemPortId {
1471 onus[0], err = pon.GetOnuById(onuPkt.OnuId)
1472 if err != nil {
1473 oltLogger.WithFields(log.Fields{
1474 "OnuId": onuPkt.OnuId,
1475 "IntfId": onuPkt.IntfId,
1476 "GemportId": onuPkt.GemportId,
1477 "err": err,
1478 }).Error("Can't find Onu")
1479 return new(openolt.Empty), errors.New("cant-find-onu-by-id")
1480 }
1481 oltLogger.WithFields(log.Fields{
1482 "IntfId": onus[0].PonPortID,
1483 "OnuId": onus[0].ID,
1484 "OnuSn": onus[0].Sn(),
1485 "GemportId": onuPkt.GemportId,
1486 "Packet": hex.EncodeToString(onuPkt.Pkt),
1487 }).Trace("Received OnuPacketOut")
1488 } else {
1489 onus = pon.GetAllOnus()
1490 oltLogger.WithFields(log.Fields{
1491 "IntfId": onuPkt.IntfId,
1492 "GemportId": onuPkt.GemportId,
1493 "Packet": hex.EncodeToString(onuPkt.Pkt),
1494 }).Trace("Received OnuPacketOut to multicast gem port")
1495 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001496
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001497 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001498
1499 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001500 if err != nil {
1501 onuLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001502 "IntfId": onuPkt.IntfId,
1503 "OnuId": onuPkt.OnuId,
1504 "GemportId": onuPkt.GemportId,
1505 "Pkt": hex.EncodeToString(rawpkt.Data()),
1506 }).Debug("Can't find pktType in packet, dropping it")
1507 return new(openolt.Empty), errors.New("malformed-packet")
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001508 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001509
Matteo Scandolo4a036262020-08-17 15:56:13 -07001510 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001511 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001512 onuLogger.WithFields(log.Fields{
Baris Ertas53ab13c2023-05-25 16:31:48 +03001513 "IntfId": onuPkt.IntfId,
1514 "OnuId": onuPkt.OnuId,
1515 "GemportId": onuPkt.GemportId,
1516 "Pkt": rawpkt.Data(),
1517 }).Debug("Can't find Dst MacAddress in packet, droppint it")
1518 return new(openolt.Empty), errors.New("dst-mac-can-not-found-in-packet")
Matteo Scandolo4a036262020-08-17 15:56:13 -07001519 }
1520
Matteo Scandolof9d43412021-01-12 11:11:34 -08001521 msg := types.Message{
1522 Type: types.OnuPacketOut,
1523 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001524 IntfId: onuPkt.IntfId,
1525 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001526 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001527 Packet: rawpkt,
1528 Type: pktType,
1529 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001530 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001531 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001532
Baris Ertas53ab13c2023-05-25 16:31:48 +03001533 for _, onu := range onus {
1534 if onu.InternalState.Current() == OnuStateEnabled {
1535 oltLogger.WithFields(log.Fields{
1536 "IntfId": onu.PonPortID,
1537 "OnuId": onu.ID,
1538 "OnuSn": onu.Sn(),
1539 }).Trace("Sending to onuchannel")
1540 onu.Channel <- msg
1541 } else {
1542 oltLogger.WithFields(log.Fields{
1543 "IntfId": onu.PonPortID,
1544 "OnuId": onu.ID,
1545 "OnuSn": onu.Sn(),
1546 }).Debug("can-not-send-onu-packet-out-to-onu")
1547 }
1548 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001549
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001550 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001551}
1552
Shrey Baid688b4242020-07-10 20:40:10 +05301553func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001554
1555 // OLT Reboot is called in two cases:
1556 // - 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)
1557 // - when an OLT needs to be rebooted (voltcl device reboot)
1558
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001559 oltLogger.WithFields(log.Fields{
1560 "oltId": o.ID,
1561 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301562 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301563 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001564 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001565}
1566
Shrey Baid688b4242020-07-10 20:40:10 +05301567func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301568 oltLogger.WithFields(log.Fields{
1569 "oltId": o.ID,
1570 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301571 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301572
Pragya Arya2225f202020-01-29 18:05:01 +05301573 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001574 oltMsg := types.Message{
1575 Type: types.OltIndication,
1576 Data: types.OltIndicationMessage{
1577 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301578 },
Pragya Arya1881df02020-01-29 18:05:01 +05301579 }
Pragya Arya2225f202020-01-29 18:05:01 +05301580 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301581
Pragya Arya2225f202020-01-29 18:05:01 +05301582 for _, pon := range o.Pons {
1583 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001584 msg := types.Message{
1585 Type: types.PonIndication,
1586 Data: types.PonIndicationMessage{
1587 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301588 PonPortID: pon.ID,
1589 },
1590 }
1591 o.channel <- msg
1592 }
1593 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001594
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001595 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001596}
1597
Shrey Baid688b4242020-07-10 20:40:10 +05301598func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001599 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1600
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001601 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1602
1603 if err != nil {
1604 return nil, err
1605 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001606 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001607}
1608
Shrey Baid688b4242020-07-10 20:40:10 +05301609func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001610 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001611 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001612}
1613
nikesh.krishnandd07b922023-07-05 23:55:42 +05301614func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuInfo, error) {
1615 pon, err := o.GetPonById(packet.GetIntfId())
1616 if err != nil {
1617 log.WithFields(log.Fields{
1618 "OnuId": packet.GetOnuId(),
1619 "IntfId": packet.GetIntfId(),
1620 "err": err,
1621 }).Error("Can't find PonPort")
1622 return nil, err
1623 }
1624 onu, _ := pon.GetOnuById(packet.GetOnuId())
1625 if err != nil {
1626 log.WithFields(log.Fields{
1627 "OnuId": packet.GetOnuId(),
1628 "IntfId": packet.GetIntfId(),
1629 "err": err,
1630 }).Error("Can't find Onu")
1631 return nil, err
1632 }
1633
1634 resp := new(openolt.OnuInfo)
1635 resp.OnuId = packet.GetOnuId()
1636 if onu.OperState.Current() == "up" {
1637 resp.Losi = openolt.AlarmState_OFF
1638 resp.Lofi = openolt.AlarmState_OFF
1639 resp.Loami = openolt.AlarmState_OFF
1640 } else if onu.OperState.Current() == "down" {
1641 resp.Losi = openolt.AlarmState_ON
1642 resp.Lofi = openolt.AlarmState_ON
1643 resp.Loami = openolt.AlarmState_ON
1644 }
1645 if onu.InternalState.Current() == OnuStateEnabled {
1646 resp.State = openolt.OnuInfo_ACTIVE
1647 } else if onu.InternalState.Current() == OnuStateDisabled {
1648 resp.State = openolt.OnuInfo_INACTIVE
1649 } else if onu.InternalState.Current() == OnuStateCreated || (onu.InternalState.Current() == OnuStateInitialized) {
1650 resp.State = openolt.OnuInfo_NOT_CONFIGURED
1651 } else {
1652 resp.State = openolt.OnuInfo_UNKNOWN
1653 }
1654 log.WithFields(log.Fields{
1655 "OnuId": packet.GetOnuId(),
1656 "IntfId": packet.GetIntfId(),
1657 "response": resp,
1658 }).Info("Response for onu info")
1659 return resp, nil
1660}
1661
1662func (o *OltDevice) GetPonInterfaceInfo(context context.Context, packet *openolt.Interface) (*openolt.PonIntfInfo, error) {
1663 ponPort, err := o.GetPonById(packet.GetIntfId())
1664 if err != nil {
1665 log.WithFields(log.Fields{
1666 "IntfId": packet.GetIntfId(),
1667 "err": err,
1668 }).Error("Can't find PonPort")
1669 return nil, err
1670 }
1671 resp := new(openolt.PonIntfInfo)
1672 resp.IntfId = packet.GetIntfId()
1673 if ponPort.OperState.Current() == "up" {
1674 resp.Los = openolt.AlarmState_OFF
1675 } else if ponPort.OperState.Current() == "down" {
1676 resp.Los = openolt.AlarmState_ON
1677 }
1678 if ponPort.InternalState.Current() == "enabled" {
1679 resp.State = openolt.PonIntfInfo_ACTIVE_WORKING
1680 } else if ponPort.InternalState.Current() == "disabled" {
1681 resp.State = openolt.PonIntfInfo_INACTIVE
1682 } else if ponPort.InternalState.Current() == "created" {
1683 resp.State = openolt.PonIntfInfo_ACTIVE_STANDBY
1684 } else {
1685 resp.State = openolt.PonIntfInfo_UNKNOWN
1686 }
1687 log.WithFields(log.Fields{
1688 "IntfId": packet.GetIntfId(),
1689 "response": resp,
1690 }).Info("Response for pon info")
1691 return resp, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001692}
1693
Shrey Baid688b4242020-07-10 20:40:10 +05301694func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001695 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001696 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001697}
1698
Shrey Baid688b4242020-07-10 20:40:10 +05301699func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001700 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001701 return new(openolt.Empty), nil
1702}
1703
Matteo Scandolo8a574812021-05-20 15:18:53 -07001704func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1705 oltLogger.WithFields(log.Fields{
1706 "OnuId": tq.OnuId,
1707 "IntfId": tq.IntfId,
1708 "OnuPortNo": tq.PortNo,
1709 "UniId": tq.UniId,
1710 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001711 return new(openolt.Empty), nil
1712}
1713
Matteo Scandolo8a574812021-05-20 15:18:53 -07001714func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301715 oltLogger.WithFields(log.Fields{
1716 "OnuId": trafficSchedulers.OnuId,
1717 "IntfId": trafficSchedulers.IntfId,
1718 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001719 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301720 }).Info("received CreateTrafficSchedulers")
1721
1722 if !s.enablePerf {
1723 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1724 if err != nil {
1725 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1726 return new(openolt.Empty), err
1727 }
1728 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1729 if err != nil {
1730 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1731 return new(openolt.Empty), err
1732 }
1733 onu.TrafficSchedulers = trafficSchedulers
1734 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001735 return new(openolt.Empty), nil
1736}
1737
Shrey Baid688b4242020-07-10 20:40:10 +05301738func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301739 oltLogger.WithFields(log.Fields{
1740 "OnuId": trafficSchedulers.OnuId,
1741 "IntfId": trafficSchedulers.IntfId,
1742 "OnuPortNo": trafficSchedulers.PortNo,
1743 }).Info("received RemoveTrafficSchedulers")
1744 if !s.enablePerf {
1745 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1746 if err != nil {
1747 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1748 return new(openolt.Empty), err
1749 }
1750 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1751 if err != nil {
1752 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1753 return new(openolt.Empty), err
1754 }
1755
1756 onu.TrafficSchedulers = nil
1757 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001758 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001759}
Scott Baker41724b82020-01-21 19:54:53 -08001760
Matteo Scandolo618a6582020-09-09 12:21:29 -07001761func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1762 oltLogger.WithFields(log.Fields{
1763 "GroupId": group.GroupId,
1764 "Command": group.Command,
1765 "Members": group.Members,
1766 "Action": group.Action,
1767 }).Debug("received PerformGroupOperation")
1768 return &openolt.Empty{}, nil
1769}
1770
1771func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1772 oltLogger.WithFields(log.Fields{
1773 "GroupId": group.GroupId,
1774 "Command": group.Command,
1775 "Members": group.Members,
1776 "Action": group.Action,
1777 }).Debug("received PerformGroupOperation")
1778 return &openolt.Empty{}, nil
1779}
1780
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001781func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1782 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001783}
1784
1785func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1786 return &openolt.Empty{}, nil
1787}
1788
1789func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1790 return &openolt.OnuLogicalDistance{}, nil
1791}
1792
1793func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1794 return &openolt.OnuLogicalDistance{}, nil
1795}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001796
Girish Gowdra62f24292021-05-12 16:28:39 -07001797func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
praneeth.nalmas7aa24df2023-03-24 10:49:43 +05301798 //VOL-4878:Hardcoding the power levels for testing as BBSIM is a simulator
1799 return &openolt.PonRxPowerData{IntfId: in.IntfId, OnuId: in.OnuId, Status: "success", FailReason: 0, RxPowerMeanDbm: -6}, nil
Girish Gowdra62f24292021-05-12 16:28:39 -07001800}
1801
Matteo Scandolo96f89192021-03-12 13:17:26 -08001802func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1803 return &openolt.GemPortStatistics{}, nil
1804}
1805
1806func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1807 return &openolt.OnuStatistics{}, nil
1808}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001809
1810func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1811 o.AllocIDsLock.Lock()
1812 defer o.AllocIDsLock.Unlock()
1813
Matteo Scandolo21195d62021-04-07 14:31:23 -07001814 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1815 oltLogger.WithFields(log.Fields{
1816 "IntfId": flow.AccessIntfId,
1817 "OnuId": flow.OnuId,
1818 "PortNo": flow.PortNo,
1819 "GemportId": flow.GemportId,
1820 "FlowId": flow.FlowId,
1821 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1822 }
1823
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001824 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001825 "IntfId": flow.AccessIntfId,
1826 "OnuId": flow.OnuId,
1827 "PortNo": flow.PortNo,
1828 "GemportId": flow.GemportId,
1829 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001830 }).Trace("storing-alloc-id-via-flow")
1831
1832 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1833 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1834 }
1835 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1836 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1837 }
1838 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1839}
1840
1841func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1842 // if this is the last flow referencing the AllocId then remove it
1843 o.AllocIDsLock.Lock()
1844 defer o.AllocIDsLock.Unlock()
1845
1846 oltLogger.WithFields(log.Fields{
1847 "IntfId": flow.AccessIntfId,
1848 "OnuId": flow.OnuId,
1849 "PortNo": flow.PortNo,
1850 "GemportId": flow.GemportId,
1851 }).Trace("freeing-alloc-id-via-flow")
1852
1853 // NOTE look at the freeGemPortId implementation for comments and context
1854 for ponId, ponValues := range o.AllocIDs {
1855 for onuId, onuValues := range ponValues {
1856 for uniId, uniValues := range onuValues {
1857 for allocId, flows := range uniValues {
1858 for flowId := range flows {
1859 // if the flow matches, remove it from the map.
1860 if flow.FlowId == flowId {
1861 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1862 }
1863 // if that was the last flow for a particular allocId, remove the entire allocId
1864 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1865 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1866 }
1867 }
1868 }
1869 }
1870 }
1871 }
1872}
1873
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301874func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) error {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001875 o.GemPortIDsLock.Lock()
1876 defer o.GemPortIDsLock.Unlock()
1877
1878 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1879 oltLogger.WithFields(log.Fields{
1880 "IntfId": ponId,
1881 "OnuId": onuId,
1882 "PortNo": portNo,
1883 "GemportId": gemId,
1884 "FlowId": flowId,
1885 }).Error("trying-to-store-gemport-for-unknown-onu")
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301886 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 -07001887 }
1888
1889 oltLogger.WithFields(log.Fields{
1890 "IntfId": ponId,
1891 "OnuId": onuId,
1892 "PortNo": portNo,
1893 "GemportId": gemId,
1894 "FlowId": flowId,
1895 }).Trace("storing-alloc-id-via-flow")
1896
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001897 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1898 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1899 }
1900 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1901 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1902 }
1903 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301904
1905 return nil
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001906}
1907
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301908func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001909 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001910 "IntfId": flow.AccessIntfId,
1911 "OnuId": flow.OnuId,
1912 "PortNo": flow.PortNo,
1913 "GemportId": flow.GemportId,
1914 "FlowId": flow.FlowId,
1915 "ReplicateFlow": flow.ReplicateFlow,
1916 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001917 }).Trace("storing-gem-port-id-via-flow")
1918
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001919 if flow.ReplicateFlow {
1920 for _, gem := range flow.PbitToGemport {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301921 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1922 if err != nil {
1923 return err
1924 }
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001925 }
1926 } else {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301927 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
1928 if err != nil {
1929 return err
1930 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001931 }
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301932
1933 return nil
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001934}
1935
1936func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1937 // if this is the last flow referencing the GemPort then remove it
1938 o.GemPortIDsLock.Lock()
1939 defer o.GemPortIDsLock.Unlock()
1940
1941 oltLogger.WithFields(log.Fields{
1942 "IntfId": flow.AccessIntfId,
1943 "OnuId": flow.OnuId,
1944 "PortNo": flow.PortNo,
1945 "GemportId": flow.GemportId,
1946 }).Trace("freeing-gem-port-id-via-flow")
1947
1948 // NOTE that this loop is not very performant, it would be better if the flow carries
1949 // the same information that it carries during a FlowAdd. If so we can directly remove
1950 // items from the map
1951
1952 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1953 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1954 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1955 //}
1956
1957 // NOTE this loop assumes that flow IDs are unique per device
1958 for ponId, ponValues := range o.GemPortIDs {
1959 for onuId, onuValues := range ponValues {
1960 for uniId, uniValues := range onuValues {
1961 for gemId, flows := range uniValues {
1962 for flowId := range flows {
1963 // if the flow matches, remove it from the map.
1964 if flow.FlowId == flowId {
1965 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1966 }
1967 // if that was the last flow for a particular gem, remove the entire gem
1968 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1969 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1970 }
1971 }
1972 }
1973 }
1974 }
1975 }
1976}
1977
1978// validateFlow checks that:
1979// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1980// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1981func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001982 // validate gemPort
1983 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001984 defer o.GemPortIDsLock.RUnlock()
1985 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001986 if onuId == uint32(flow.OnuId) {
1987 continue
1988 }
1989 for uniId, uni := range onu {
1990 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001991 if flow.ReplicateFlow {
1992 for _, flowGem := range flow.PbitToGemport {
1993 if gem == int32(flowGem) {
1994 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1995 }
1996 }
1997 } else {
1998 if gem == flow.GemportId {
1999 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
2000 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08002001 }
2002 }
2003 }
2004 }
2005
2006 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07002007 defer o.AllocIDsLock.RUnlock()
2008 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08002009 if onuId == uint32(flow.OnuId) {
2010 continue
2011 }
2012 for uniId, uni := range onu {
2013 for allocId := range uni {
2014 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07002015 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 -08002016 }
2017 }
2018 }
2019 }
2020
2021 return nil
2022}
2023
2024// clearAllResources is invoked up OLT Reboot to remove all the allocated
2025// GemPorts, AllocId and ONU-IDs across the PONs
2026func (o *OltDevice) clearAllResources() {
2027
2028 // remove the resources received via flows
2029 o.GemPortIDsLock.Lock()
2030 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
2031 o.GemPortIDsLock.Unlock()
2032 o.AllocIDsLock.Lock()
2033 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
2034 o.AllocIDsLock.Unlock()
2035
2036 // remove the resources received via OMCI
2037 for _, pon := range o.Pons {
2038 pon.removeAllAllocIds()
2039 pon.removeAllGemPorts()
2040 pon.removeAllOnuIds()
2041 }
2042}