blob: a5a8ba4585e6026c35e0de532657038dc6947476 [file] [log] [blame]
mpagenkoaf801632020-07-03 10:00:42 +00001/*
2 * Copyright 2020-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
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
22 "encoding/json"
mpagenko1cc3cb42020-07-27 15:24:38 +000023 "errors"
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000024 "fmt"
mpagenko3dbcdd22020-07-22 07:38:45 +000025 "strconv"
26 "strings"
mpagenkoaf801632020-07-03 10:00:42 +000027 "sync"
28
mpagenko3dbcdd22020-07-22 07:38:45 +000029 "github.com/looplab/fsm"
mpagenkoaf801632020-07-03 10:00:42 +000030 "github.com/opencord/voltha-lib-go/v3/pkg/db"
31 "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
33 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
34)
35
36const cBasePathTechProfileKVStore = "service/voltha/technology_profiles"
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000037const cBasePathOnuKVStore = "service/voltha/openonu"
38
39//definitions for TechProfileProcessing - copied from OltAdapter:openolt_flowmgr.go
40// could perhaps be defined more globally
41const (
42 // BinaryStringPrefix is binary string prefix
43 BinaryStringPrefix = "0b"
44 // BinaryBit1 is binary bit 1 expressed as a character
45 BinaryBit1 = '1'
46)
mpagenkoaf801632020-07-03 10:00:42 +000047
48type resourceEntry int
49
50const (
51 cResourceGemPort resourceEntry = 1
52 cResourceTcont resourceEntry = 2
53)
54
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000055type uniPersData struct {
56 PersUniId uint32 `json:"uni_id"`
57 PersTpPath string `json:"tp_path"`
mpagenkoaf801632020-07-03 10:00:42 +000058}
59
60type onuPersistentData struct {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000061 PersOnuID uint32 `json:"onu_id"`
62 PersIntfID uint32 `json:"intf_id"`
63 PersSnr string `json:"serial_number"`
64 PersAdminState string `json:"admin_state"`
65 PersOperState string `json:"oper_state"`
66 PersUniTpPath []uniPersData `json:"uni_config"`
mpagenkoaf801632020-07-03 10:00:42 +000067}
68
mpagenko3dbcdd22020-07-22 07:38:45 +000069type tTechProfileIndication struct {
mpagenkodff5dda2020-08-28 11:52:01 +000070 techProfileType string
71 techProfileID uint16
72 techProfileConfigDone bool
mpagenko3dbcdd22020-07-22 07:38:45 +000073}
74
75type tcontParamStruct struct {
76 allocID uint16
77 schedPolicy uint8
78}
79type gemPortParamStruct struct {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000080 ponOmciCC bool
mpagenko3dbcdd22020-07-22 07:38:45 +000081 gemPortID uint16
82 direction uint8
83 gemPortEncState uint8
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000084 prioQueueIndex uint8
85 pbitString string
mpagenko3dbcdd22020-07-22 07:38:45 +000086 discardPolicy string
87 //could also be a queue specific paramter, not used that way here
88 maxQueueSize uint16
89 queueSchedPolicy string
90 queueWeight uint8
91}
92
93//refers to one tcont and its properties and all assigned GemPorts and their properties
94type tcontGemList struct {
95 tcontParams tcontParamStruct
96 mapGemPortParams map[uint16]*gemPortParamStruct
97}
98
99//refers to all tcont and their Tcont/GemPort Parameters
100type tMapPonAniConfig map[uint16]*tcontGemList
101
mpagenkoaf801632020-07-03 10:00:42 +0000102//OnuUniTechProf structure holds information about the TechProfiles attached to Uni Ports of the ONU
103type OnuUniTechProf struct {
mpagenkodff5dda2020-08-28 11:52:01 +0000104 deviceID string
105 baseDeviceHandler *DeviceHandler
106 tpProcMutex sync.RWMutex
107 mapUniTpPath map[uint32]string
108 sOnuPersistentData onuPersistentData
109 techProfileKVStore *db.Backend
110 onuKVStore *db.Backend
111 onuKVStorePath string
112 chTpConfigProcessingStep chan uint8
113 chTpKvProcessingStep chan uint8
114 mapUniTpIndication map[uint8]*tTechProfileIndication //use pointer values to ease assignments to the map
115 mapPonAniConfig map[uint8]*tMapPonAniConfig //per UNI: use pointer values to ease assignments to the map
116 pAniConfigFsm *UniPonAniConfigFsm
117 procResult error //error indication of processing
118 mutexTPState sync.Mutex
mpagenkoaf801632020-07-03 10:00:42 +0000119}
120
121//NewOnuUniTechProf returns the instance of a OnuUniTechProf
122//(one instance per ONU/deviceHandler for all possible UNI's)
123func NewOnuUniTechProf(ctx context.Context, aDeviceID string, aDeviceHandler *DeviceHandler) *OnuUniTechProf {
divyadesai4d299552020-08-18 07:13:49 +0000124 logger.Infow("init-OnuUniTechProf", log.Fields{"device-id": aDeviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000125 var onuTP OnuUniTechProf
126 onuTP.deviceID = aDeviceID
127 onuTP.baseDeviceHandler = aDeviceHandler
128 onuTP.tpProcMutex = sync.RWMutex{}
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000129 onuTP.mapUniTpPath = make(map[uint32]string)
130 onuTP.sOnuPersistentData.PersUniTpPath = make([]uniPersData, 1)
mpagenkodff5dda2020-08-28 11:52:01 +0000131 onuTP.chTpConfigProcessingStep = make(chan uint8)
132 onuTP.chTpKvProcessingStep = make(chan uint8)
133 onuTP.mapUniTpIndication = make(map[uint8]*tTechProfileIndication)
134 onuTP.mapPonAniConfig = make(map[uint8]*tMapPonAniConfig)
mpagenko1cc3cb42020-07-27 15:24:38 +0000135 onuTP.procResult = nil //default assumption processing done with success
mpagenkoaf801632020-07-03 10:00:42 +0000136
137 onuTP.techProfileKVStore = aDeviceHandler.SetBackend(cBasePathTechProfileKVStore)
138 if onuTP.techProfileKVStore == nil {
139 logger.Errorw("Can't access techProfileKVStore - no backend connection to service",
divyadesai4d299552020-08-18 07:13:49 +0000140 log.Fields{"device-id": aDeviceID, "service": cBasePathTechProfileKVStore})
mpagenkoaf801632020-07-03 10:00:42 +0000141 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000142
143 onuTP.onuKVStorePath = onuTP.deviceID
144 onuTP.onuKVStore = aDeviceHandler.SetBackend(cBasePathOnuKVStore)
145 if onuTP.onuKVStore == nil {
146 logger.Errorw("Can't access onuKVStore - no backend connection to service",
divyadesai4d299552020-08-18 07:13:49 +0000147 log.Fields{"device-id": aDeviceID, "service": cBasePathOnuKVStore})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000148 }
mpagenkoaf801632020-07-03 10:00:42 +0000149 return &onuTP
150}
151
152// lockTpProcMutex locks OnuUniTechProf processing mutex
153func (onuTP *OnuUniTechProf) lockTpProcMutex() {
154 onuTP.tpProcMutex.Lock()
155}
156
157// unlockTpProcMutex unlocks OnuUniTechProf processing mutex
158func (onuTP *OnuUniTechProf) unlockTpProcMutex() {
159 onuTP.tpProcMutex.Unlock()
160}
161
mpagenko1cc3cb42020-07-27 15:24:38 +0000162// resetProcessingErrorIndication resets the internal error indication
163// need to be called before evaluation of any subsequent processing (given by waitForTpCompletion())
164func (onuTP *OnuUniTechProf) resetProcessingErrorIndication() {
165 onuTP.procResult = nil
166}
167
mpagenkoaf801632020-07-03 10:00:42 +0000168// updateOnuUniTpPath verifies and updates changes in the kvStore onuUniTpPath
169func (onuTP *OnuUniTechProf) updateOnuUniTpPath(aUniID uint32, aPathString string) bool {
170 /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
171 as also the complete sequence is ensured to 'run to completion' before some new request is accepted
172 no specific concurrency protection to sOnuPersistentData is required here
173 */
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000174 if existingPath, present := onuTP.mapUniTpPath[aUniID]; present {
mpagenkoaf801632020-07-03 10:00:42 +0000175 // uni entry already exists
176 //logger.Debugw(" already exists", log.Fields{"for InstanceId": a_uniInstNo})
177 if existingPath != aPathString {
178 if aPathString == "" {
179 //existing entry to be deleted
180 logger.Debugw("UniTp path delete", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000181 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000182 delete(onuTP.mapUniTpPath, aUniID)
mpagenkoaf801632020-07-03 10:00:42 +0000183 } else {
184 //existing entry to be modified
185 logger.Debugw("UniTp path modify", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000186 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000187 onuTP.mapUniTpPath[aUniID] = aPathString
mpagenkoaf801632020-07-03 10:00:42 +0000188 }
189 return true
190 }
191 //entry already exists
192 logger.Debugw("UniTp path already exists", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000193 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
mpagenkoaf801632020-07-03 10:00:42 +0000194 return false
195 }
196 //uni entry does not exist
197 if aPathString == "" {
198 //delete request in non-existing state , accept as no change
199 logger.Debugw("UniTp path already removed", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000200 "device-id": onuTP.deviceID, "uniID": aUniID})
mpagenkoaf801632020-07-03 10:00:42 +0000201 return false
202 }
203 //new entry to be set
204 logger.Debugw("New UniTp path set", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000205 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000206 onuTP.mapUniTpPath[aUniID] = aPathString
mpagenkoaf801632020-07-03 10:00:42 +0000207 return true
208}
209
mpagenko1cc3cb42020-07-27 15:24:38 +0000210func (onuTP *OnuUniTechProf) waitForTpCompletion(cancel context.CancelFunc, wg *sync.WaitGroup) error {
mpagenko3dbcdd22020-07-22 07:38:45 +0000211 defer cancel() //ensure termination of context (may be pro forma)
212 wg.Wait()
213 logger.Debug("some TechProfile Processing completed")
214 onuTP.tpProcMutex.Unlock() //allow further TP related processing
mpagenko1cc3cb42020-07-27 15:24:38 +0000215 return onuTP.procResult
mpagenko3dbcdd22020-07-22 07:38:45 +0000216}
217
218// configureUniTp checks existing tp resources to delete and starts the corresponding OMCI configuation of the UNI port
219// all possibly blocking processing must be run in background to allow for deadline supervision!
220// but take care on sequential background processing when needed (logical dependencies)
mpagenkodff5dda2020-08-28 11:52:01 +0000221// use waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) for internal synchronisation
mpagenko3dbcdd22020-07-22 07:38:45 +0000222func (onuTP *OnuUniTechProf) configureUniTp(ctx context.Context,
mpagenkodff5dda2020-08-28 11:52:01 +0000223 aUniID uint8, aPathString string, wg *sync.WaitGroup) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000224 defer wg.Done() //always decrement the waitGroup on return
mpagenkoaf801632020-07-03 10:00:42 +0000225 logger.Debugw("configure the Uni according to TpPath", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000226 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
mpagenkoaf801632020-07-03 10:00:42 +0000227
mpagenkoaf801632020-07-03 10:00:42 +0000228 if onuTP.techProfileKVStore == nil {
229 logger.Debug("techProfileKVStore not set - abort")
mpagenko1cc3cb42020-07-27 15:24:38 +0000230 onuTP.procResult = errors.New("TechProfile config aborted: techProfileKVStore not set")
mpagenkoaf801632020-07-03 10:00:42 +0000231 return
232 }
233
mpagenko3dbcdd22020-07-22 07:38:45 +0000234 //ensure that the given uniID is available (configured) in the UniPort class (used for OMCI entities)
235 var pCurrentUniPort *OnuUniPort
236 for _, uniPort := range onuTP.baseDeviceHandler.uniEntityMap {
237 // only if this port is validated for operState transfer
238 if uniPort.uniId == uint8(aUniID) {
239 pCurrentUniPort = uniPort
240 break //found - end search loop
241 }
242 }
243 if pCurrentUniPort == nil {
244 logger.Errorw("TechProfile configuration aborted: requested uniID not found in PortDB",
245 log.Fields{"device-id": onuTP.deviceID, "uniID": aUniID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000246 onuTP.procResult = errors.New("TechProfile config aborted: requested uniID not found")
mpagenko3dbcdd22020-07-22 07:38:45 +0000247 return
248 }
mpagenkoaf801632020-07-03 10:00:42 +0000249
mpagenkodff5dda2020-08-28 11:52:01 +0000250 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
mpagenkoaf801632020-07-03 10:00:42 +0000251
mpagenko3dbcdd22020-07-22 07:38:45 +0000252 //according to updateOnuUniTpPath() logic the assumption here is, that this configuration is only called
253 // in case the KVPath has changed for the given UNI,
254 // as T-Cont and Gem-Id's are dependent on TechProfile-Id this means, that possibly previously existing
255 // (ANI) configuration of this port has to be removed first
256 // (moreover in this case a possibly existing flow configuration is also not valid anymore and needs clean-up as well)
257 // existence of configuration can be detected based on tp stored TCONT's
258 //TODO!!!:
259 /* if tcontMap not empty {
260 go onuTP.deleteAniSideConfig(ctx, aUniID, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000261 if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000262 //timeout or error detected
263 return
264 }
265 clear tcontMap
266 }
267
268 processingStep++
269 */
270 go onuTP.readAniSideConfigFromTechProfile(ctx, aUniID, aPathString, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000271 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000272 //timeout or error detected
273 logger.Debugw("tech-profile related configuration aborted on read",
274 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000275 onuTP.procResult = errors.New("TechProfile config aborted: tech-profile read issue")
mpagenko3dbcdd22020-07-22 07:38:45 +0000276 return
277 }
278
279 processingStep++
280 if valuePA, existPA := onuTP.mapPonAniConfig[aUniID]; existPA {
281 if _, existTG := (*valuePA)[0]; existTG {
282 //Config data for this uni and and at least TCont Index 0 exist
283 go onuTP.setAniSideConfigFromTechProfile(ctx, aUniID, pCurrentUniPort, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000284 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000285 //timeout or error detected
286 logger.Debugw("tech-profile related configuration aborted on set",
287 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000288 onuTP.procResult = errors.New("TechProfile config aborted: Omci AniSideConfig failed")
mpagenko3dbcdd22020-07-22 07:38:45 +0000289 //this issue here means that the AniConfigFsm has not finished succesfully
290 //which requires to reset it to allow for new usage, e.g. also on a different UNI
291 //(without that it would be reset on device down indication latest)
mpagenko1cc3cb42020-07-27 15:24:38 +0000292 onuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000293 return
mpagenkoaf801632020-07-03 10:00:42 +0000294 }
295 } else {
mpagenko3dbcdd22020-07-22 07:38:45 +0000296 // strange: UNI entry exists, but no ANI data, maybe such situation should be cleared up (if observed)
297 logger.Debugw("no Tcont/Gem data for this UNI found - abort", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000298 "device-id": onuTP.deviceID, "uniID": aUniID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000299 onuTP.procResult = errors.New("TechProfile config aborted: no Tcont/Gem data found for this UNI")
300 return
mpagenkoaf801632020-07-03 10:00:42 +0000301 }
302 } else {
mpagenko3dbcdd22020-07-22 07:38:45 +0000303 logger.Debugw("no PonAni data for this UNI found - abort", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000304 "device-id": onuTP.deviceID, "uniID": aUniID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000305 onuTP.procResult = errors.New("TechProfile config aborted: no AniSide data found for this UNI")
306 return
mpagenkoaf801632020-07-03 10:00:42 +0000307 }
308}
309
mpagenko3dbcdd22020-07-22 07:38:45 +0000310func (onuTP *OnuUniTechProf) updateOnuTpPathKvStore(ctx context.Context, wg *sync.WaitGroup) {
mpagenkoaf801632020-07-03 10:00:42 +0000311 defer wg.Done()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000312
313 if onuTP.onuKVStore == nil {
314 logger.Debugw("onuKVStore not set - abort", log.Fields{"device-id": onuTP.deviceID})
315 onuTP.procResult = errors.New("ONU/TP-data update aborted: onuKVStore not set")
316 return
317 }
mpagenkodff5dda2020-08-28 11:52:01 +0000318 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpKvProcessingStep
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000319 go onuTP.storePersistentData(ctx, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000320 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpKvProcessingStep, processingStep) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000321 //timeout or error detected
322 logger.Debugw("ONU/TP-data not written - abort", log.Fields{"device-id": onuTP.deviceID})
323 onuTP.procResult = errors.New("ONU/TP-data update aborted: during writing process")
324 return
325 }
326}
327
328func (onuTP *OnuUniTechProf) restoreFromOnuTpPathKvStore(ctx context.Context) error {
329 if onuTP.onuKVStore == nil {
330 logger.Debugw("onuKVStore not set - abort", log.Fields{"device-id": onuTP.deviceID})
331 return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", onuTP.deviceID))
332 }
333 if err := onuTP.restorePersistentData(ctx); err != nil {
334 logger.Debugw("ONU/TP-data not read - abort", log.Fields{"device-id": onuTP.deviceID})
335 return err
336 }
337 return nil
338}
339
340func (onuTP *OnuUniTechProf) deleteOnuTpPathKvStore(ctx context.Context) error {
341 if onuTP.onuKVStore == nil {
342 logger.Debugw("onuKVStore not set - abort", log.Fields{"device-id": onuTP.deviceID})
343 return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", onuTP.deviceID))
344 }
345 if err := onuTP.deletePersistentData(ctx); err != nil {
346 logger.Debugw("ONU/TP-data not read - abort", log.Fields{"device-id": onuTP.deviceID})
347 return err
348 }
349 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000350}
351
mpagenko3dbcdd22020-07-22 07:38:45 +0000352// deleteTpResource removes Resources from the ONU's specified Uni
353func (onuTP *OnuUniTechProf) deleteTpResource(ctx context.Context,
354 aUniID uint32, aPathString string, aResource resourceEntry, aEntryID uint32,
355 wg *sync.WaitGroup) {
mpagenkoaf801632020-07-03 10:00:42 +0000356 defer wg.Done()
357 logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000358 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "Resource": aResource})
mpagenkoaf801632020-07-03 10:00:42 +0000359 //TODO!!!
mpagenko3dbcdd22020-07-22 07:38:45 +0000360 //delete the given resource from ONU OMCI config and data base - as background routine
361 /*
mpagenkodff5dda2020-08-28 11:52:01 +0000362 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
mpagenko3dbcdd22020-07-22 07:38:45 +0000363 go onuTp.deleteAniResource(ctx, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000364 if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000365 //timeout or error detected
366 return
367 }
368 */
mpagenkoaf801632020-07-03 10:00:42 +0000369}
370
mpagenko3dbcdd22020-07-22 07:38:45 +0000371/* internal methods *********************/
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000372
373func (onuTP *OnuUniTechProf) storePersistentData(ctx context.Context, aProcessingStep uint8) {
374
375 onuTP.sOnuPersistentData.PersOnuID = onuTP.baseDeviceHandler.pOnuIndication.OnuId
376 onuTP.sOnuPersistentData.PersIntfID = onuTP.baseDeviceHandler.pOnuIndication.IntfId
377 onuTP.sOnuPersistentData.PersSnr = onuTP.baseDeviceHandler.pOnuOmciDevice.serialNumber
378 //TODO: verify usage of these values during restart UC
379 onuTP.sOnuPersistentData.PersAdminState = "up"
380 onuTP.sOnuPersistentData.PersOperState = "active"
381
382 onuTP.sOnuPersistentData.PersUniTpPath = onuTP.sOnuPersistentData.PersUniTpPath[:0]
383
384 for k, v := range onuTP.mapUniTpPath {
385 onuTP.sOnuPersistentData.PersUniTpPath =
386 append(onuTP.sOnuPersistentData.PersUniTpPath, uniPersData{PersUniId: k, PersTpPath: v})
387 }
divyadesai4d299552020-08-18 07:13:49 +0000388 logger.Debugw("Update ONU/TP-data in KVStore", log.Fields{"device-id": onuTP.deviceID, "onuTP.sOnuPersistentData": onuTP.sOnuPersistentData})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000389
390 Value, err := json.Marshal(onuTP.sOnuPersistentData)
391 if err != nil {
392 logger.Errorw("unable to marshal ONU/TP-data", log.Fields{"onuTP.sOnuPersistentData": onuTP.sOnuPersistentData,
393 "device-id": onuTP.deviceID, "err": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000394 onuTP.chTpKvProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000395 return
396 }
397 err = onuTP.onuKVStore.Put(ctx, onuTP.onuKVStorePath, Value)
398 if err != nil {
399 logger.Errorw("unable to write ONU/TP-data into KVstore", log.Fields{"device-id": onuTP.deviceID, "err": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000400 onuTP.chTpKvProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000401 return
402 }
mpagenkodff5dda2020-08-28 11:52:01 +0000403 onuTP.chTpKvProcessingStep <- aProcessingStep //done
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000404}
405
406func (onuTP *OnuUniTechProf) restorePersistentData(ctx context.Context) error {
407
408 onuTP.mapUniTpPath = make(map[uint32]string)
409 onuTP.sOnuPersistentData = onuPersistentData{0, 0, "", "", "", make([]uniPersData, 0)}
410
411 Value, err := onuTP.onuKVStore.Get(ctx, onuTP.onuKVStorePath)
412 if err == nil {
413 if Value != nil {
414 logger.Debugw("ONU/TP-data read",
415 log.Fields{"Key": Value.Key, "device-id": onuTP.deviceID})
416 tpTmpBytes, _ := kvstore.ToByte(Value.Value)
417
418 if err = json.Unmarshal(tpTmpBytes, &onuTP.sOnuPersistentData); err != nil {
419 logger.Errorw("unable to unmarshal ONU/TP-data", log.Fields{"error": err, "device-id": onuTP.deviceID})
420 return fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-ONU/TP-data-%s", onuTP.deviceID))
421 }
422 logger.Debugw("ONU/TP-data", log.Fields{"onuTP.sOnuPersistentData": onuTP.sOnuPersistentData,
423 "device-id": onuTP.deviceID})
424
425 for _, uniData := range onuTP.sOnuPersistentData.PersUniTpPath {
426 onuTP.mapUniTpPath[uniData.PersUniId] = uniData.PersTpPath
427 }
428 logger.Debugw("TpPath map", log.Fields{"onuTP.mapUniTpPath": onuTP.mapUniTpPath,
429 "device-id": onuTP.deviceID})
430 } else {
431 logger.Errorw("no ONU/TP-data found", log.Fields{"path": onuTP.onuKVStorePath, "device-id": onuTP.deviceID})
432 return fmt.Errorf(fmt.Sprintf("no-ONU/TP-data-found-%s", onuTP.deviceID))
433 }
434 } else {
435 logger.Errorw("unable to read from KVstore", log.Fields{"device-id": onuTP.deviceID})
436 return fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s", onuTP.deviceID))
437 }
438 return nil
439}
440
441func (onuTP *OnuUniTechProf) deletePersistentData(ctx context.Context) error {
442
divyadesai4d299552020-08-18 07:13:49 +0000443 logger.Debugw("delete ONU/TP-data in KVStore", log.Fields{"device-id": onuTP.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000444 err := onuTP.onuKVStore.Delete(ctx, onuTP.onuKVStorePath)
445 if err != nil {
446 logger.Errorw("unable to delete in KVstore", log.Fields{"device-id": onuTP.deviceID, "err": err})
447 return fmt.Errorf(fmt.Sprintf("unable-delete-in-KVstore-%s", onuTP.deviceID))
448 }
449 return nil
450}
451
mpagenko3dbcdd22020-07-22 07:38:45 +0000452func (onuTP *OnuUniTechProf) readAniSideConfigFromTechProfile(
mpagenkodff5dda2020-08-28 11:52:01 +0000453 ctx context.Context, aUniID uint8, aPathString string, aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000454 var tpInst tp.TechProfile
455
456 //store profile type and identifier for later usage within the OMCI identifier and possibly ME setup
457 //pathstring is defined to be in the form of <ProfType>/<profID>/<Interface/../Identifier>
458 subStringSlice := strings.Split(aPathString, "/")
459 if len(subStringSlice) <= 2 {
460 logger.Errorw("invalid path name format",
461 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000462 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000463 return
464 }
465
466 //just some logical check to avoid unexpected behavior
467 //at this point it is assumed that a new TechProfile is assigned to the UNI
468 //expectation is that no TPIndication entry exists here, if yes,
469 // then we throw a warning and remove it (and the possible ANIConfig) simply
470 // note that the ONU config state may be ambivalent in such a case
471 // also note, that the PonAniConfig map is not checked additionally
472 // consistency to TPIndication is assumed
473 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
474 logger.Warnw("Some active profile entry at reading new TechProfile",
475 log.Fields{"path": aPathString, "device-id": onuTP.deviceID,
476 "UniId": aUniID, "wrongProfile": onuTP.mapUniTpIndication[aUniID].techProfileID})
477 //delete on the mapUniTpIndication map not needed, just overwritten later
478 //delete on the PonAniConfig map should be safe, even if not existing
479 delete(onuTP.mapPonAniConfig, aUniID)
480 } else {
481 // this is normal processing
482 onuTP.mapUniTpIndication[aUniID] = &tTechProfileIndication{} //need to assign some (empty) struct memory first!
483 }
484
485 onuTP.mapUniTpIndication[aUniID].techProfileType = subStringSlice[0]
486 profID, err := strconv.ParseUint(subStringSlice[1], 10, 32)
487 if err != nil {
488 logger.Errorw("invalid ProfileId from path",
489 log.Fields{"ParseErr": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000490 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000491 return
492 }
493
494 //note the limitation on ID range (probably even more limited) - based on usage within OMCI EntityID
495 onuTP.mapUniTpIndication[aUniID].techProfileID = uint16(profID)
496 logger.Debugw("tech-profile path indications",
497 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID,
498 "profType": onuTP.mapUniTpIndication[aUniID].techProfileType,
499 "profID": onuTP.mapUniTpIndication[aUniID].techProfileID})
500
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000501 Value, err := onuTP.techProfileKVStore.Get(ctx, aPathString)
mpagenko3dbcdd22020-07-22 07:38:45 +0000502 if err == nil {
503 if Value != nil {
504 logger.Debugw("tech-profile read",
505 log.Fields{"Key": Value.Key, "device-id": onuTP.deviceID})
506 tpTmpBytes, _ := kvstore.ToByte(Value.Value)
507
508 if err = json.Unmarshal(tpTmpBytes, &tpInst); err != nil {
509 logger.Errorw("TechProf - Failed to unmarshal tech-profile into tpInst",
510 log.Fields{"error": err, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000511 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000512 return
513 }
514 logger.Debugw("TechProf - tpInst", log.Fields{"tpInst": tpInst})
515 // access examples
516 logger.Debugw("TechProf content", log.Fields{"Name": tpInst.Name,
517 "MaxGemPayloadSize": tpInst.InstanceCtrl.MaxGemPayloadSize,
518 "DownstreamGemDiscardmaxThreshold": tpInst.DownstreamGemPortAttributeList[0].DiscardConfig.MaxThreshold})
519 } else {
520 logger.Errorw("No tech-profile found",
521 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000522 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000523 return
524 }
525 } else {
526 logger.Errorw("kvstore-get failed for path",
527 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000528 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000529 return
530 }
531
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000532 //default start with 1Tcont1Gem profile, later extend for multi GemPerTcont and perhaps even MultiTcontMultiGem
mpagenko3dbcdd22020-07-22 07:38:45 +0000533 localMapGemPortParams := make(map[uint16]*gemPortParamStruct)
534 localMapGemPortParams[0] = &gemPortParamStruct{}
535 localMapPonAniConfig := make(map[uint16]*tcontGemList)
536 localMapPonAniConfig[0] = &tcontGemList{tcontParamStruct{}, localMapGemPortParams}
537 onuTP.mapPonAniConfig[aUniID] = (*tMapPonAniConfig)(&localMapPonAniConfig)
538
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000539 //note: the code is currently restricted to one TCcont per Onu (index [0])
mpagenko3dbcdd22020-07-22 07:38:45 +0000540 //get the relevant values from the profile and store to mapPonAniConfig
541 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.allocID = uint16(tpInst.UsScheduler.AllocID)
542 //maybe tCont scheduling not (yet) needed - just to basicaly have it for future
543 // (would only be relevant in case of ONU-2G QOS configuration flexibility)
544 if tpInst.UsScheduler.QSchedPolicy == "StrictPrio" {
545 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.schedPolicy = 1 //for the moment fixed value acc. G.988 //TODO: defines!
546 } else {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000547 //default profile defines "Hybrid" - which probably comes down to WRR with some weigthts for SP
mpagenko3dbcdd22020-07-22 07:38:45 +0000548 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.schedPolicy = 2 //for G.988 WRR
549 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000550 loNumGemPorts := tpInst.NumGemPorts
551 loGemPortRead := false
mpagenko3dbcdd22020-07-22 07:38:45 +0000552 for pos, content := range tpInst.UpstreamGemPortAttributeList {
mpagenko1cc3cb42020-07-27 15:24:38 +0000553 if uint32(pos) == loNumGemPorts {
554 logger.Debugw("PonAniConfig abort GemPortList - GemList exceeds set NumberOfGemPorts",
555 log.Fields{"device-id": onuTP.deviceID, "index": pos, "NumGem": loNumGemPorts})
mpagenko3dbcdd22020-07-22 07:38:45 +0000556 break
557 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000558 if pos == 0 {
559 //at least one upstream GemPort should always exist (else traffic profile makes no sense)
560 loGemPortRead = true
561 } else {
562 //for all further GemPorts we need to extend the mapGemPortParams
563 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)] = &gemPortParamStruct{}
564 }
565 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortID =
566 uint16(content.GemportID)
567 //direction can be correlated later with Downstream list,
568 // for now just assume bidirectional (upstream never exists alone)
mpagenko3dbcdd22020-07-22 07:38:45 +0000569 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].direction = 3 //as defined in G.988
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000570 // expected Prio-Queue values 0..7 with 7 for highest PrioQueue, QueueIndex=Prio = 0..7
571 if 7 < content.PriorityQueue {
572 logger.Errorw("PonAniConfig reject on GemPortList - PrioQueue value invalid",
573 log.Fields{"device-id": onuTP.deviceID, "index": pos, "PrioQueue": content.PriorityQueue})
574 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
575 delete(onuTP.mapPonAniConfig, aUniID)
mpagenkodff5dda2020-08-28 11:52:01 +0000576 onuTP.chTpConfigProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000577 return
578 }
579 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].prioQueueIndex =
580 uint8(content.PriorityQueue)
581 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].pbitString =
582 strings.TrimPrefix(content.PbitMap, BinaryStringPrefix)
mpagenko3dbcdd22020-07-22 07:38:45 +0000583 if content.AesEncryption == "True" {
584 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortEncState = 1
585 } else {
586 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortEncState = 0
587 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000588 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].discardPolicy =
589 content.DiscardPolicy
590 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].queueSchedPolicy =
591 content.SchedulingPolicy
mpagenko3dbcdd22020-07-22 07:38:45 +0000592 //'GemWeight' looks strange in default profile, for now we just copy the weight to first queue
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000593 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].queueWeight =
594 uint8(content.Weight)
mpagenko3dbcdd22020-07-22 07:38:45 +0000595 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000596 if loGemPortRead == false {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000597 logger.Errorw("PonAniConfig reject - no GemPort could be read from TechProfile",
mpagenko1cc3cb42020-07-27 15:24:38 +0000598 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000599 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
600 delete(onuTP.mapPonAniConfig, aUniID)
mpagenkodff5dda2020-08-28 11:52:01 +0000601 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko1cc3cb42020-07-27 15:24:38 +0000602 return
603 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000604 //TODO!! MC (downstream) GemPorts can be set using DownstreamGemPortAttributeList seperately
605
606 //logger does not simply output the given structures, just give some example debug values
607 logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000608 "device-id": onuTP.deviceID,
609 "AllocId": (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.allocID})
610 for gemIndex, gemEntry := range (*(onuTP.mapPonAniConfig[0]))[0].mapGemPortParams {
611 logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
612 "GemIndex": gemIndex,
613 "GemPort": gemEntry.gemPortID,
614 "QueueScheduling": gemEntry.queueSchedPolicy})
615 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000616
mpagenkodff5dda2020-08-28 11:52:01 +0000617 onuTP.chTpConfigProcessingStep <- aProcessingStep //done
mpagenko3dbcdd22020-07-22 07:38:45 +0000618}
619
620func (onuTP *OnuUniTechProf) setAniSideConfigFromTechProfile(
mpagenkodff5dda2020-08-28 11:52:01 +0000621 ctx context.Context, aUniID uint8, apCurrentUniPort *OnuUniPort, aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000622
623 //OMCI transfer of ANI data acc. to mapPonAniConfig
624 // also the FSM's are running in background,
mpagenkodff5dda2020-08-28 11:52:01 +0000625 // hence we have to make sure they indicate 'success' success on chTpConfigProcessingStep with aProcessingStep
mpagenko3dbcdd22020-07-22 07:38:45 +0000626 if onuTP.pAniConfigFsm == nil {
627 onuTP.createAniConfigFsm(aUniID, apCurrentUniPort, OmciAniConfigDone, aProcessingStep)
628 } else { //AniConfigFsm already init
629 onuTP.runAniConfigFsm(aProcessingStep)
630 }
631}
632
633func (onuTP *OnuUniTechProf) waitForTimeoutOrCompletion(
mpagenkodff5dda2020-08-28 11:52:01 +0000634 ctx context.Context, aChTpProcessingStep <-chan uint8, aProcessingStep uint8) bool {
mpagenko3dbcdd22020-07-22 07:38:45 +0000635 select {
636 case <-ctx.Done():
637 logger.Warnw("processing not completed in-time: force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000638 log.Fields{"device-id": onuTP.deviceID, "error": ctx.Err()})
mpagenko3dbcdd22020-07-22 07:38:45 +0000639 return false
mpagenkodff5dda2020-08-28 11:52:01 +0000640 case rxStep := <-aChTpProcessingStep:
mpagenko3dbcdd22020-07-22 07:38:45 +0000641 if rxStep == aProcessingStep {
642 return true
643 }
644 //all other values are not accepted - including 0 for error indication
645 logger.Warnw("Invalid processing step received: abort and force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000646 log.Fields{"device-id": onuTP.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000647 "wantedStep": aProcessingStep, "haveStep": rxStep})
648 return false
649 }
650}
651
652// createUniLockFsm initialises and runs the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
mpagenkodff5dda2020-08-28 11:52:01 +0000653func (onuTP *OnuUniTechProf) createAniConfigFsm(aUniID uint8,
mpagenko3dbcdd22020-07-22 07:38:45 +0000654 apCurrentUniPort *OnuUniPort, devEvent OnuDeviceEvent, aProcessingStep uint8) {
divyadesai4d299552020-08-18 07:13:49 +0000655 logger.Debugw("createAniConfigFsm", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000656 chAniConfigFsm := make(chan Message, 2048)
657 pDevEntry := onuTP.baseDeviceHandler.GetOnuDeviceEntry(true)
658 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +0000659 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000660 return
661 }
662 pAniCfgFsm := NewUniPonAniConfigFsm(pDevEntry.PDevOmciCC, apCurrentUniPort, onuTP,
663 pDevEntry.pOnuDB, onuTP.mapUniTpIndication[aUniID].techProfileID, devEvent,
664 "AniConfigFsm", onuTP.deviceID, chAniConfigFsm)
665 if pAniCfgFsm != nil {
666 onuTP.pAniConfigFsm = pAniCfgFsm
667 onuTP.runAniConfigFsm(aProcessingStep)
668 } else {
divyadesai4d299552020-08-18 07:13:49 +0000669 logger.Errorw("AniConfigFSM could not be created - abort!!", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000670 }
671}
672
673// runAniConfigFsm starts the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
674func (onuTP *OnuUniTechProf) runAniConfigFsm(aProcessingStep uint8) {
675 /* Uni related ANI config procedure -
676 ***** should run via 'aniConfigDone' state and generate the argument requested event *****
677 */
678 var pACStatemachine *fsm.FSM
679 pACStatemachine = onuTP.pAniConfigFsm.pAdaptFsm.pFsm
680 if pACStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000681 if pACStatemachine.Is(aniStDisabled) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000682 //FSM init requirement to get informed abou FSM completion! (otherwise timeout of the TechProf config)
mpagenkodff5dda2020-08-28 11:52:01 +0000683 onuTP.pAniConfigFsm.SetFsmCompleteChannel(onuTP.chTpConfigProcessingStep, aProcessingStep)
mpagenko1cc3cb42020-07-27 15:24:38 +0000684 if err := pACStatemachine.Event(aniEvStart); err != nil {
mpagenko3dbcdd22020-07-22 07:38:45 +0000685 logger.Warnw("AniConfigFSM: can't start", log.Fields{"err": err})
686 // maybe try a FSM reset and then again ... - TODO!!!
687 } else {
688 /***** AniConfigFSM started */
689 logger.Debugw("AniConfigFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000690 "state": pACStatemachine.Current(), "device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000691 }
692 } else {
693 logger.Warnw("wrong state of AniConfigFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000694 "have": pACStatemachine.Current(), "device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000695 // maybe try a FSM reset and then again ... - TODO!!!
696 }
697 } else {
divyadesai4d299552020-08-18 07:13:49 +0000698 logger.Errorw("AniConfigFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000699 // maybe try a FSM reset and then again ... - TODO!!!
700 }
mpagenkoaf801632020-07-03 10:00:42 +0000701}
mpagenkodff5dda2020-08-28 11:52:01 +0000702
703// setConfigDone sets the requested techProfile config state (if possible)
704func (onuTP *OnuUniTechProf) setConfigDone(aUniID uint8, aState bool) {
705 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
706 onuTP.mutexTPState.Lock()
707 onuTP.mapUniTpIndication[aUniID].techProfileConfigDone = aState
708 onuTP.mutexTPState.Unlock()
709 } //else: the state is just ignored (does not exist)
710}
711
712// getTechProfileDone checks if the Techprofile processing with the requested TechProfile ID was done
713func (onuTP *OnuUniTechProf) getTechProfileDone(aUniID uint8, aTpID uint16) bool {
714 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
715 if onuTP.mapUniTpIndication[aUniID].techProfileID == aTpID {
716 onuTP.mutexTPState.Lock()
717 defer onuTP.mutexTPState.Unlock()
718 return onuTP.mapUniTpIndication[aUniID].techProfileConfigDone
719 }
720 }
721 //for all other constellations indicate false = Config not done
722 return false
723}