blob: 4db0e09b10c8925c015d136d45eb8f0e12206469 [file] [log] [blame]
Matteo Scandolo86e8ce62019-10-11 12:03:10 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
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"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000025 "github.com/opencord/voltha-protos/v5/go/openolt"
Pragya Arya6a708d62020-01-01 17:17:20 +053026 log "github.com/sirupsen/logrus"
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070027)
28
Matteo Scandolod15c0b42021-03-22 11:38:13 -070029var ponLogger = log.WithFields(log.Fields{
30 "module": "PON",
31})
32
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070033type PonPort struct {
34 // BBSIM Internals
Pragya Arya996a0892020-03-09 21:47:52 +053035 ID uint32
36 NumOnu int
37 Onus []*Onu
38 Olt *OltDevice
39 PacketCount uint64
40 InternalState *fsm.FSM
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070041
42 // PON Attributes
43 OperState *fsm.FSM
44 Type string
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080045
46 // Allocated resources
47 // Some resources (eg: OnuId, AllocId and GemPorts) have to be unique per PON port
48 // we are keeping a list so that we can throw an error in cases we receive duplicates
49 AllocatedGemPorts map[uint16]*openolt.SerialNumber
50 allocatedGemPortsLock sync.RWMutex
51 AllocatedOnuIds map[uint32]*openolt.SerialNumber
52 allocatedOnuIdsLock sync.RWMutex
53 AllocatedAllocIds map[uint16]*openolt.SerialNumber
54 allocatedAllocIdsLock sync.RWMutex
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070055}
56
Pragya Arya6a708d62020-01-01 17:17:20 +053057// CreatePonPort creates pon port object
Pragya Arya2225f202020-01-29 18:05:01 +053058func CreatePonPort(olt *OltDevice, id uint32) *PonPort {
Pragya Arya6a708d62020-01-01 17:17:20 +053059
60 ponPort := PonPort{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080061 NumOnu: olt.NumOnuPerPon,
62 ID: id,
63 Type: "pon",
64 Olt: olt,
65 Onus: []*Onu{},
66 AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
67 AllocatedOnuIds: make(map[uint32]*openolt.SerialNumber),
68 AllocatedAllocIds: make(map[uint16]*openolt.SerialNumber),
Pragya Arya6a708d62020-01-01 17:17:20 +053069 }
70
Pragya Arya2225f202020-01-29 18:05:01 +053071 ponPort.InternalState = fsm.NewFSM(
72 "created",
73 fsm.Events{
74 {Name: "enable", Src: []string{"created", "disabled"}, Dst: "enabled"},
75 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
76 },
77 fsm.Callbacks{
78 "enter_enabled": func(e *fsm.Event) {
Matteo Scandolod15c0b42021-03-22 11:38:13 -070079 ponLogger.WithFields(log.Fields{
Pragya Arya2225f202020-01-29 18:05:01 +053080 "ID": ponPort.ID,
81 }).Debugf("Changing PON Port InternalState from %s to %s", e.Src, e.Dst)
82
83 if e.Src == "created" {
84 if olt.ControlledActivation == Default || olt.ControlledActivation == OnlyPON {
85 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -080086 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -070087 ponLogger.Errorf("Error initializing ONU: %v", err)
Pragya Arya2225f202020-01-29 18:05:01 +053088 continue
89 }
Matteo Scandolocedde462021-03-09 17:37:16 -080090 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -070091 ponLogger.Errorf("Error discover ONU: %v", err)
Pragya Arya2225f202020-01-29 18:05:01 +053092 }
93 }
94 }
95 } else if e.Src == "disabled" {
Matteo Scandolo0de43d12020-10-05 13:54:41 -070096 if ponPort.Olt.ControlledActivation == OnlyONU || ponPort.Olt.ControlledActivation == Both {
97 // if ONUs are manually activated then only initialize them
98 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -080099 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700100 ponLogger.WithFields(log.Fields{
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800101 "Err": err,
102 "OnuSn": onu.Sn(),
Hardik Windlassad790cb2020-06-17 21:26:22 +0530103 "IntfId": onu.PonPortID,
104 }).Error("Error initializing ONU")
Pragya Arya2225f202020-01-29 18:05:01 +0530105 continue
106 }
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700107 }
108 } else {
109 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800110 if onu.InternalState.Current() == OnuStatePonDisabled {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700111 if err := onu.InternalState.Event(OnuTxEnable); err != nil {
112 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700113 "Err": err,
114 "OnuSn": onu.Sn(),
115 "IntfId": onu.PonPortID,
116 }).Error("Error enabling ONU")
117 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800118 } else if onu.InternalState.Current() == OnuStateDisabled {
119 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700120 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700121 "Err": err,
122 "OnuSn": onu.Sn(),
123 "IntfId": onu.PonPortID,
124 }).Error("Error initializing ONU")
125 continue
126 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800127 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700128 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700129 "Err": err,
130 "OnuSn": onu.Sn(),
131 "IntfId": onu.PonPortID,
132 }).Error("Error discovering ONU")
133 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800134 } else if onu.InternalState.Current() == OnuStateInitialized {
135 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700136 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700137 "Err": err,
138 "OnuSn": onu.Sn(),
139 "IntfId": onu.PonPortID,
140 }).Error("Error discovering ONU")
141 }
142 } else {
143 // this is to loudly report unexpected states in order to address them
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700144 ponLogger.WithFields(log.Fields{
Matteo Scandolo0de43d12020-10-05 13:54:41 -0700145 "OnuSn": onu.Sn(),
146 "IntfId": onu.PonPortID,
147 "InternalState": onu.InternalState.Current(),
148 }).Error("Unexpected ONU state in PON enabling")
Pragya Arya2225f202020-01-29 18:05:01 +0530149 }
150 }
151 }
152 }
153 },
154 "enter_disabled": func(e *fsm.Event) {
155 for _, onu := range ponPort.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800156 if onu.InternalState.Current() == OnuStateInitialized || onu.InternalState.Current() == OnuStateDisabled {
Pragya Arya2225f202020-01-29 18:05:01 +0530157 continue
158 }
Matteo Scandolocedde462021-03-09 17:37:16 -0800159 if err := onu.InternalState.Event(OnuTxPonDisable); err != nil {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700160 ponLogger.Errorf("Failed to move ONU in %s states: %v", OnuStatePonDisabled, err)
Pragya Arya2225f202020-01-29 18:05:01 +0530161 }
162 }
163 },
164 },
165 )
166
Pragya Arya6a708d62020-01-01 17:17:20 +0530167 ponPort.OperState = fsm.NewFSM(
168 "down",
169 fsm.Events{
170 {Name: "enable", Src: []string{"down"}, Dst: "up"},
171 {Name: "disable", Src: []string{"up"}, Dst: "down"},
172 },
173 fsm.Callbacks{
174 "enter_up": func(e *fsm.Event) {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700175 ponLogger.WithFields(log.Fields{
Pragya Arya6a708d62020-01-01 17:17:20 +0530176 "ID": ponPort.ID,
177 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
Pragya Arya2225f202020-01-29 18:05:01 +0530178 olt.sendPonIndication(ponPort.ID)
Pragya Arya6a708d62020-01-01 17:17:20 +0530179 },
180 "enter_down": func(e *fsm.Event) {
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700181 ponLogger.WithFields(log.Fields{
Pragya Arya6a708d62020-01-01 17:17:20 +0530182 "ID": ponPort.ID,
183 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
Pragya Arya2225f202020-01-29 18:05:01 +0530184 olt.sendPonIndication(ponPort.ID)
Pragya Arya6a708d62020-01-01 17:17:20 +0530185 },
186 },
187 )
188 return &ponPort
189}
190
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800191func (p *PonPort) GetOnuBySn(sn *openolt.SerialNumber) (*Onu, error) {
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700192 for _, onu := range p.Onus {
193 if bytes.Equal(onu.SerialNumber.VendorSpecific, sn.VendorSpecific) {
Matteo Scandolo27428702019-10-11 16:21:16 -0700194 return onu, nil
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700195 }
196 }
Shrey Baid688b4242020-07-10 20:40:10 +0530197 return nil, fmt.Errorf("Cannot find Onu with serial number %d in PonPort %d", sn, p.ID)
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700198}
199
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800200func (p *PonPort) GetOnuById(id uint32) (*Onu, error) {
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700201 for _, onu := range p.Onus {
202 if onu.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700203 return onu, nil
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700204 }
205 }
Shrey Baid688b4242020-07-10 20:40:10 +0530206 return nil, fmt.Errorf("Cannot find Onu with id %d in PonPort %d", id, p.ID)
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700207}
Pragya Arya996a0892020-03-09 21:47:52 +0530208
209// GetNumOfActiveOnus returns number of active ONUs for PON port
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800210func (p *PonPort) GetNumOfActiveOnus() uint32 {
Pragya Arya996a0892020-03-09 21:47:52 +0530211 var count uint32 = 0
212 for _, onu := range p.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800213 if onu.InternalState.Current() == OnuStateInitialized || onu.InternalState.Current() == OnuStateCreated || onu.InternalState.Current() == OnuStateDisabled {
Pragya Arya996a0892020-03-09 21:47:52 +0530214 continue
215 }
216 count++
217 }
218 return count
219}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800220
221// storeOnuId adds the Id to the ONU Ids already allocated to this PON port
222func (p *PonPort) storeOnuId(onuId uint32, onuSn *openolt.SerialNumber) {
223 p.allocatedOnuIdsLock.Lock()
224 defer p.allocatedOnuIdsLock.Unlock()
225 p.AllocatedOnuIds[onuId] = onuSn
226}
227
228// removeOnuId removes the OnuId from the allocated resources
229func (p *PonPort) removeOnuId(onuId uint32) {
230 p.allocatedOnuIdsLock.Lock()
231 defer p.allocatedOnuIdsLock.Unlock()
232 delete(p.AllocatedOnuIds, onuId)
233}
234
235func (p *PonPort) removeAllOnuIds() {
236 p.allocatedOnuIdsLock.Lock()
237 defer p.allocatedOnuIdsLock.Unlock()
238 p.AllocatedOnuIds = make(map[uint32]*openolt.SerialNumber)
239}
240
241// isOnuIdAllocated returns whether this OnuId is already in use on this PON
242func (p *PonPort) isOnuIdAllocated(onuId uint32) (bool, *openolt.SerialNumber) {
243 p.allocatedOnuIdsLock.RLock()
244 defer p.allocatedOnuIdsLock.RUnlock()
245
246 if _, ok := p.AllocatedOnuIds[onuId]; ok {
247 return true, p.AllocatedOnuIds[onuId]
248 }
249 return false, nil
250}
251
252// storeGemPort adds the gemPortId to the gemports already allocated to this PON port
253func (p *PonPort) storeGemPort(gemPortId uint16, onuSn *openolt.SerialNumber) {
254 p.allocatedGemPortsLock.Lock()
255 defer p.allocatedGemPortsLock.Unlock()
256 p.AllocatedGemPorts[gemPortId] = onuSn
257}
258
259// removeGemPort removes the gemPortId from the allocated resources
260func (p *PonPort) removeGemPort(gemPortId uint16) {
261 p.allocatedGemPortsLock.Lock()
262 defer p.allocatedGemPortsLock.Unlock()
263 delete(p.AllocatedGemPorts, gemPortId)
264}
265
266func (p *PonPort) removeGemPortBySn(onuSn *openolt.SerialNumber) {
267 p.allocatedGemPortsLock.Lock()
268 defer p.allocatedGemPortsLock.Unlock()
269 for gemPort, sn := range p.AllocatedGemPorts {
270 if sn == onuSn {
271 delete(p.AllocatedGemPorts, gemPort)
272 }
273 }
274}
275
276func (p *PonPort) removeAllGemPorts() {
277 p.allocatedGemPortsLock.Lock()
278 defer p.allocatedGemPortsLock.Unlock()
279 p.AllocatedGemPorts = make(map[uint16]*openolt.SerialNumber)
280}
281
282// isGemPortAllocated returns whether this gemPort is already in use on this PON
283func (p *PonPort) isGemPortAllocated(gemPortId uint16) (bool, *openolt.SerialNumber) {
284 p.allocatedGemPortsLock.RLock()
285 defer p.allocatedGemPortsLock.RUnlock()
286
287 if _, ok := p.AllocatedGemPorts[gemPortId]; ok {
288 return true, p.AllocatedGemPorts[gemPortId]
289 }
290 return false, nil
291}
292
293// storeAllocId adds the Id to the ONU Ids already allocated to this PON port
294func (p *PonPort) storeAllocId(allocId uint16, onuSn *openolt.SerialNumber) {
295 p.allocatedAllocIdsLock.Lock()
296 defer p.allocatedAllocIdsLock.Unlock()
297 p.AllocatedAllocIds[allocId] = onuSn
298}
299
300// removeAllocId removes the AllocId from the allocated resources
301// this is done via SN as the AllocId is not remove but set to a default value
302func (p *PonPort) removeAllocId(onuSn *openolt.SerialNumber) {
303 p.allocatedAllocIdsLock.Lock()
304 defer p.allocatedAllocIdsLock.Unlock()
305 for allocId, sn := range p.AllocatedAllocIds {
306 if sn == onuSn {
307 delete(p.AllocatedAllocIds, allocId)
308 }
309 }
310}
311
312func (p *PonPort) removeAllAllocIds() {
313 p.allocatedAllocIdsLock.Lock()
314 defer p.allocatedAllocIdsLock.Unlock()
315 p.AllocatedAllocIds = make(map[uint16]*openolt.SerialNumber)
316}
317
318// isAllocIdAllocated returns whether this AllocId is already in use on this PON
319func (p *PonPort) isAllocIdAllocated(allocId uint16) (bool, *openolt.SerialNumber) {
320 p.allocatedAllocIdsLock.RLock()
321 defer p.allocatedAllocIdsLock.RUnlock()
322
323 if _, ok := p.AllocatedAllocIds[allocId]; ok {
324 return true, p.AllocatedAllocIds[allocId]
325 }
326 return false, nil
327}