blob: f83d35c3ea8bc668eda95c0aa9f7bb0f78ca8b91 [file] [log] [blame]
Matteo Scandolo86e8ce62019-10-11 12:03:10 -07001/*
Joey Armstrong2c039362024-02-04 18:51:52 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandolo86e8ce62019-10-11 12:03:10 -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
17package devices
18
19import (
20 "bytes"
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070021 "fmt"
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080022 "sync"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020023
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070024 "github.com/looplab/fsm"
Elia Battistonb7bea222022-02-18 16:25:00 +010025 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000026 "github.com/opencord/voltha-protos/v5/go/openolt"
Pragya Arya6a708d62020-01-01 17:17:20 +053027 log "github.com/sirupsen/logrus"
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070028)
29
Matteo Scandolod15c0b42021-03-22 11:38:13 -070030var ponLogger = log.WithFields(log.Fields{
31 "module": "PON",
32})
33
Girish Gowdra574834a2022-02-04 15:15:15 -080034type AllocIDVal struct {
35 OnuSn *openolt.SerialNumber
36 AllocID uint16
37}
38
39type AllocIDKey struct {
40 PonID uint32
41 OnuID uint32
42 EntityID uint16
43}
44
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070045type PonPort struct {
46 // BBSIM Internals
Pragya Arya996a0892020-03-09 21:47:52 +053047 ID uint32
Elia Battistonb7bea222022-02-18 16:25:00 +010048 Technology common.PonTechnology
Pragya Arya996a0892020-03-09 21:47:52 +053049 NumOnu int
50 Onus []*Onu
51 Olt *OltDevice
52 PacketCount uint64
53 InternalState *fsm.FSM
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070054
55 // PON Attributes
56 OperState *fsm.FSM
57 Type string
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080058
59 // Allocated resources
60 // Some resources (eg: OnuId, AllocId and GemPorts) have to be unique per PON port
61 // we are keeping a list so that we can throw an error in cases we receive duplicates
62 AllocatedGemPorts map[uint16]*openolt.SerialNumber
63 allocatedGemPortsLock sync.RWMutex
64 AllocatedOnuIds map[uint32]*openolt.SerialNumber
65 allocatedOnuIdsLock sync.RWMutex
Girish Gowdra574834a2022-02-04 15:15:15 -080066 AllocatedAllocIds map[AllocIDKey]*AllocIDVal // key is AllocIDKey
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080067 allocatedAllocIdsLock sync.RWMutex
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070068}
69
Baris Ertas53ab13c2023-05-25 16:31:48 +030070func (p *PonPort) GetAllOnus() []*Onu {
71 return p.Onus
72}
73
Pragya Arya6a708d62020-01-01 17:17:20 +053074// CreatePonPort creates pon port object
Elia Battistonb7bea222022-02-18 16:25:00 +010075func CreatePonPort(olt *OltDevice, id uint32, tech common.PonTechnology) *PonPort {
Pragya Arya6a708d62020-01-01 17:17:20 +053076 ponPort := PonPort{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080077 NumOnu: olt.NumOnuPerPon,
78 ID: id,
Elia Battistonb7bea222022-02-18 16:25:00 +010079 Technology: tech,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080080 Type: "pon",
81 Olt: olt,
82 Onus: []*Onu{},
83 AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
84 AllocatedOnuIds: make(map[uint32]*openolt.SerialNumber),
Girish Gowdra574834a2022-02-04 15:15:15 -080085 AllocatedAllocIds: make(map[AllocIDKey]*AllocIDVal),
Pragya Arya6a708d62020-01-01 17:17:20 +053086 }
87
Pragya Arya2225f202020-01-29 18:05:01 +053088 ponPort.InternalState = fsm.NewFSM(
89 "created",
90 fsm.Events{
91 {Name: "enable", Src: []string{"created", "disabled"}, Dst: "enabled"},
92 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
93 },
94 fsm.Callbacks{
95 "enter_enabled": func(e *fsm.Event) {
Matteo Scandolod15c0b42021-03-22 11:38:13 -070096 ponLogger.WithFields(log.Fields{
Pragya Arya2225f202020-01-29 18:05:01 +053097 "ID": ponPort.ID,
98 }).Debugf("Changing PON Port InternalState from %s to %s", e.Src, e.Dst)
99
100 if e.Src == "created" {
101 if olt.ControlledActivation == Default || olt.ControlledActivation == OnlyPON {
102 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800103 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700104 ponLogger.Errorf("Error initializing ONU: %v", err)
Pragya Arya2225f202020-01-29 18:05:01 +0530105 continue
106 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800107 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700108 ponLogger.Errorf("Error discover ONU: %v", err)
Pragya Arya2225f202020-01-29 18:05:01 +0530109 }
110 }
111 }
112 } else if e.Src == "disabled" {
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700113 if ponPort.Olt.ControlledActivation == OnlyONU || ponPort.Olt.ControlledActivation == Both {
114 // if ONUs are manually activated then only initialize them
115 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800116 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700117 ponLogger.WithFields(log.Fields{
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800118 "Err": err,
119 "OnuSn": onu.Sn(),
Hardik Windlassad790cb2020-06-17 21:26:22 +0530120 "IntfId": onu.PonPortID,
121 }).Error("Error initializing ONU")
Pragya Arya2225f202020-01-29 18:05:01 +0530122 continue
123 }
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700124 }
125 } else {
126 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800127 if onu.InternalState.Current() == OnuStatePonDisabled {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700128 if err := onu.InternalState.Event(OnuTxEnable); err != nil {
129 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700130 "Err": err,
131 "OnuSn": onu.Sn(),
132 "IntfId": onu.PonPortID,
133 }).Error("Error enabling ONU")
134 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800135 } else if onu.InternalState.Current() == OnuStateDisabled {
136 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700137 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700138 "Err": err,
139 "OnuSn": onu.Sn(),
140 "IntfId": onu.PonPortID,
141 }).Error("Error initializing ONU")
142 continue
143 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800144 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700145 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700146 "Err": err,
147 "OnuSn": onu.Sn(),
148 "IntfId": onu.PonPortID,
149 }).Error("Error discovering ONU")
150 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800151 } else if onu.InternalState.Current() == OnuStateInitialized {
152 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700153 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700154 "Err": err,
155 "OnuSn": onu.Sn(),
156 "IntfId": onu.PonPortID,
157 }).Error("Error discovering ONU")
158 }
159 } else {
160 // this is to loudly report unexpected states in order to address them
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700161 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700162 "OnuSn": onu.Sn(),
163 "IntfId": onu.PonPortID,
164 "InternalState": onu.InternalState.Current(),
165 }).Error("Unexpected ONU state in PON enabling")
Pragya Arya2225f202020-01-29 18:05:01 +0530166 }
167 }
168 }
169 }
170 },
171 "enter_disabled": func(e *fsm.Event) {
172 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800173 if onu.InternalState.Current() == OnuStateInitialized || onu.InternalState.Current() == OnuStateDisabled {
Pragya Arya2225f202020-01-29 18:05:01 +0530174 continue
175 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800176 if err := onu.InternalState.Event(OnuTxPonDisable); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700177 ponLogger.Errorf("Failed to move ONU in %s states: %v", OnuStatePonDisabled, err)
Pragya Arya2225f202020-01-29 18:05:01 +0530178 }
179 }
180 },
181 },
182 )
183
Pragya Arya6a708d62020-01-01 17:17:20 +0530184 ponPort.OperState = fsm.NewFSM(
185 "down",
186 fsm.Events{
187 {Name: "enable", Src: []string{"down"}, Dst: "up"},
188 {Name: "disable", Src: []string{"up"}, Dst: "down"},
189 },
190 fsm.Callbacks{
191 "enter_up": func(e *fsm.Event) {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700192 ponLogger.WithFields(log.Fields{
Pragya Arya6a708d62020-01-01 17:17:20 +0530193 "ID": ponPort.ID,
194 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
Pragya Arya2225f202020-01-29 18:05:01 +0530195 olt.sendPonIndication(ponPort.ID)
Pragya Arya6a708d62020-01-01 17:17:20 +0530196 },
197 "enter_down": func(e *fsm.Event) {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700198 ponLogger.WithFields(log.Fields{
Pragya Arya6a708d62020-01-01 17:17:20 +0530199 "ID": ponPort.ID,
200 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
Pragya Arya2225f202020-01-29 18:05:01 +0530201 olt.sendPonIndication(ponPort.ID)
Pragya Arya6a708d62020-01-01 17:17:20 +0530202 },
203 },
204 )
205 return &ponPort
206}
207
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800208func (p *PonPort) GetOnuBySn(sn *openolt.SerialNumber) (*Onu, error) {
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700209 for _, onu := range p.Onus {
210 if bytes.Equal(onu.SerialNumber.VendorSpecific, sn.VendorSpecific) {
Matteo Scandolo27428702019-10-11 16:21:16 -0700211 return onu, nil
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700212 }
213 }
Shrey Baid688b4242020-07-10 20:40:10 +0530214 return nil, fmt.Errorf("Cannot find Onu with serial number %d in PonPort %d", sn, p.ID)
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700215}
216
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800217func (p *PonPort) GetOnuById(id uint32) (*Onu, error) {
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700218 for _, onu := range p.Onus {
219 if onu.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700220 return onu, nil
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700221 }
222 }
Shrey Baid688b4242020-07-10 20:40:10 +0530223 return nil, fmt.Errorf("Cannot find Onu with id %d in PonPort %d", id, p.ID)
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700224}
Pragya Arya996a0892020-03-09 21:47:52 +0530225
226// GetNumOfActiveOnus returns number of active ONUs for PON port
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800227func (p *PonPort) GetNumOfActiveOnus() uint32 {
Pragya Arya996a0892020-03-09 21:47:52 +0530228 var count uint32 = 0
229 for _, onu := range p.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800230 if onu.InternalState.Current() == OnuStateInitialized || onu.InternalState.Current() == OnuStateCreated || onu.InternalState.Current() == OnuStateDisabled {
Pragya Arya996a0892020-03-09 21:47:52 +0530231 continue
232 }
233 count++
234 }
235 return count
236}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800237
238// storeOnuId adds the Id to the ONU Ids already allocated to this PON port
239func (p *PonPort) storeOnuId(onuId uint32, onuSn *openolt.SerialNumber) {
240 p.allocatedOnuIdsLock.Lock()
241 defer p.allocatedOnuIdsLock.Unlock()
242 p.AllocatedOnuIds[onuId] = onuSn
243}
244
245// removeOnuId removes the OnuId from the allocated resources
246func (p *PonPort) removeOnuId(onuId uint32) {
247 p.allocatedOnuIdsLock.Lock()
248 defer p.allocatedOnuIdsLock.Unlock()
249 delete(p.AllocatedOnuIds, onuId)
250}
251
252func (p *PonPort) removeAllOnuIds() {
253 p.allocatedOnuIdsLock.Lock()
254 defer p.allocatedOnuIdsLock.Unlock()
255 p.AllocatedOnuIds = make(map[uint32]*openolt.SerialNumber)
256}
257
258// isOnuIdAllocated returns whether this OnuId is already in use on this PON
259func (p *PonPort) isOnuIdAllocated(onuId uint32) (bool, *openolt.SerialNumber) {
260 p.allocatedOnuIdsLock.RLock()
261 defer p.allocatedOnuIdsLock.RUnlock()
262
263 if _, ok := p.AllocatedOnuIds[onuId]; ok {
264 return true, p.AllocatedOnuIds[onuId]
265 }
266 return false, nil
267}
268
269// storeGemPort adds the gemPortId to the gemports already allocated to this PON port
270func (p *PonPort) storeGemPort(gemPortId uint16, onuSn *openolt.SerialNumber) {
271 p.allocatedGemPortsLock.Lock()
272 defer p.allocatedGemPortsLock.Unlock()
273 p.AllocatedGemPorts[gemPortId] = onuSn
274}
275
276// removeGemPort removes the gemPortId from the allocated resources
277func (p *PonPort) removeGemPort(gemPortId uint16) {
278 p.allocatedGemPortsLock.Lock()
279 defer p.allocatedGemPortsLock.Unlock()
280 delete(p.AllocatedGemPorts, gemPortId)
281}
282
283func (p *PonPort) removeGemPortBySn(onuSn *openolt.SerialNumber) {
284 p.allocatedGemPortsLock.Lock()
285 defer p.allocatedGemPortsLock.Unlock()
286 for gemPort, sn := range p.AllocatedGemPorts {
287 if sn == onuSn {
288 delete(p.AllocatedGemPorts, gemPort)
289 }
290 }
291}
292
293func (p *PonPort) removeAllGemPorts() {
294 p.allocatedGemPortsLock.Lock()
295 defer p.allocatedGemPortsLock.Unlock()
296 p.AllocatedGemPorts = make(map[uint16]*openolt.SerialNumber)
297}
298
299// isGemPortAllocated returns whether this gemPort is already in use on this PON
300func (p *PonPort) isGemPortAllocated(gemPortId uint16) (bool, *openolt.SerialNumber) {
301 p.allocatedGemPortsLock.RLock()
302 defer p.allocatedGemPortsLock.RUnlock()
303
304 if _, ok := p.AllocatedGemPorts[gemPortId]; ok {
305 return true, p.AllocatedGemPorts[gemPortId]
306 }
307 return false, nil
308}
309
310// storeAllocId adds the Id to the ONU Ids already allocated to this PON port
Girish Gowdra574834a2022-02-04 15:15:15 -0800311func (p *PonPort) storeAllocId(ponID uint32, onuID uint32, entityID uint16, allocId uint16, onuSn *openolt.SerialNumber) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800312 p.allocatedAllocIdsLock.Lock()
313 defer p.allocatedAllocIdsLock.Unlock()
Girish Gowdra574834a2022-02-04 15:15:15 -0800314 p.AllocatedAllocIds[AllocIDKey{ponID, onuID, entityID}] = &AllocIDVal{onuSn, allocId}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800315}
316
317// removeAllocId removes the AllocId from the allocated resources
Girish Gowdra574834a2022-02-04 15:15:15 -0800318func (p *PonPort) removeAllocId(ponID uint32, onuID uint32, entityID uint16) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800319 p.allocatedAllocIdsLock.Lock()
320 defer p.allocatedAllocIdsLock.Unlock()
Girish Gowdra574834a2022-02-04 15:15:15 -0800321 allocKey := AllocIDKey{ponID, onuID, entityID}
322 delete(p.AllocatedAllocIds, allocKey)
323}
324
325// removeAllocIdsForOnuSn removes the all AllocIds for the given onu serial number
326func (p *PonPort) removeAllocIdsForOnuSn(onuSn *openolt.SerialNumber) {
327 p.allocatedAllocIdsLock.Lock()
328 defer p.allocatedAllocIdsLock.Unlock()
329 for id, allocObj := range p.AllocatedAllocIds {
330 if onuSn == allocObj.OnuSn {
331 delete(p.AllocatedAllocIds, id)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800332 }
333 }
334}
335
336func (p *PonPort) removeAllAllocIds() {
337 p.allocatedAllocIdsLock.Lock()
338 defer p.allocatedAllocIdsLock.Unlock()
Girish Gowdra574834a2022-02-04 15:15:15 -0800339 p.AllocatedAllocIds = make(map[AllocIDKey]*AllocIDVal)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800340}
341
342// isAllocIdAllocated returns whether this AllocId is already in use on this PON
Girish Gowdra574834a2022-02-04 15:15:15 -0800343func (p *PonPort) isAllocIdAllocated(ponID uint32, onuID uint32, entityID uint16) (bool, *AllocIDVal) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800344 p.allocatedAllocIdsLock.RLock()
345 defer p.allocatedAllocIdsLock.RUnlock()
Girish Gowdra574834a2022-02-04 15:15:15 -0800346 allocKey := AllocIDKey{ponID, onuID, entityID}
347 if _, ok := p.AllocatedAllocIds[allocKey]; ok {
348 return true, p.AllocatedAllocIds[allocKey]
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800349 }
350 return false, nil
351}