blob: 4f452a7bd9b54e49ab98f5412ffeca0df4155a89 [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
29 "github.com/opencord/voltha-lib-go/v3/pkg/db"
30 "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
31 "github.com/opencord/voltha-lib-go/v3/pkg/log"
32 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
33)
34
35const cBasePathTechProfileKVStore = "service/voltha/technology_profiles"
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000036const cBasePathOnuKVStore = "service/voltha/openonu"
37
38//definitions for TechProfileProcessing - copied from OltAdapter:openolt_flowmgr.go
39// could perhaps be defined more globally
40const (
Himani Chawla6d2ae152020-09-02 13:11:20 +053041 // binaryStringPrefix is binary string prefix
42 binaryStringPrefix = "0b"
43 // binaryBit1 is binary bit 1 expressed as a character
44 //binaryBit1 = '1'
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000045)
mpagenkoaf801632020-07-03 10:00:42 +000046
47type resourceEntry int
48
49const (
50 cResourceGemPort resourceEntry = 1
51 cResourceTcont resourceEntry = 2
52)
53
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000054type uniPersData struct {
Himani Chawla26e555c2020-08-31 12:30:20 +053055 PersUniID uint32 `json:"uni_id"`
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000056 PersTpPath string `json:"tp_path"`
mpagenkoaf801632020-07-03 10:00:42 +000057}
58
59type onuPersistentData struct {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000060 PersOnuID uint32 `json:"onu_id"`
61 PersIntfID uint32 `json:"intf_id"`
62 PersSnr string `json:"serial_number"`
63 PersAdminState string `json:"admin_state"`
64 PersOperState string `json:"oper_state"`
65 PersUniTpPath []uniPersData `json:"uni_config"`
mpagenkoaf801632020-07-03 10:00:42 +000066}
67
mpagenko3dbcdd22020-07-22 07:38:45 +000068type tTechProfileIndication struct {
mpagenkodff5dda2020-08-28 11:52:01 +000069 techProfileType string
70 techProfileID uint16
71 techProfileConfigDone bool
mpagenko3dbcdd22020-07-22 07:38:45 +000072}
73
74type tcontParamStruct struct {
75 allocID uint16
76 schedPolicy uint8
77}
78type gemPortParamStruct struct {
Himani Chawla4d908332020-08-31 12:30:20 +053079 //ponOmciCC bool
mpagenko3dbcdd22020-07-22 07:38:45 +000080 gemPortID uint16
81 direction uint8
82 gemPortEncState uint8
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000083 prioQueueIndex uint8
84 pbitString string
mpagenko3dbcdd22020-07-22 07:38:45 +000085 discardPolicy string
Himani Chawla4d908332020-08-31 12:30:20 +053086 //could also be a queue specific parameter, not used that way here
87 //maxQueueSize uint16
mpagenko3dbcdd22020-07-22 07:38:45 +000088 queueSchedPolicy string
89 queueWeight uint8
90}
91
92//refers to one tcont and its properties and all assigned GemPorts and their properties
93type tcontGemList struct {
94 tcontParams tcontParamStruct
95 mapGemPortParams map[uint16]*gemPortParamStruct
96}
97
98//refers to all tcont and their Tcont/GemPort Parameters
99type tMapPonAniConfig map[uint16]*tcontGemList
100
Himani Chawla6d2ae152020-09-02 13:11:20 +0530101//onuUniTechProf structure holds information about the TechProfiles attached to Uni Ports of the ONU
102type onuUniTechProf struct {
mpagenkodff5dda2020-08-28 11:52:01 +0000103 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530104 baseDeviceHandler *deviceHandler
mpagenkodff5dda2020-08-28 11:52:01 +0000105 tpProcMutex sync.RWMutex
106 mapUniTpPath map[uint32]string
107 sOnuPersistentData onuPersistentData
108 techProfileKVStore *db.Backend
109 onuKVStore *db.Backend
110 onuKVStorePath string
111 chTpConfigProcessingStep chan uint8
112 chTpKvProcessingStep chan uint8
113 mapUniTpIndication map[uint8]*tTechProfileIndication //use pointer values to ease assignments to the map
114 mapPonAniConfig map[uint8]*tMapPonAniConfig //per UNI: use pointer values to ease assignments to the map
Himani Chawla6d2ae152020-09-02 13:11:20 +0530115 pAniConfigFsm *uniPonAniConfigFsm
mpagenkodff5dda2020-08-28 11:52:01 +0000116 procResult error //error indication of processing
117 mutexTPState sync.Mutex
mpagenkoaf801632020-07-03 10:00:42 +0000118}
119
Himani Chawla6d2ae152020-09-02 13:11:20 +0530120//newOnuUniTechProf returns the instance of a OnuUniTechProf
mpagenkoaf801632020-07-03 10:00:42 +0000121//(one instance per ONU/deviceHandler for all possible UNI's)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530122func newOnuUniTechProf(ctx context.Context, aDeviceID string, aDeviceHandler *deviceHandler) *onuUniTechProf {
divyadesai4d299552020-08-18 07:13:49 +0000123 logger.Infow("init-OnuUniTechProf", log.Fields{"device-id": aDeviceID})
Himani Chawla6d2ae152020-09-02 13:11:20 +0530124 var onuTP onuUniTechProf
mpagenkoaf801632020-07-03 10:00:42 +0000125 onuTP.deviceID = aDeviceID
126 onuTP.baseDeviceHandler = aDeviceHandler
127 onuTP.tpProcMutex = sync.RWMutex{}
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000128 onuTP.mapUniTpPath = make(map[uint32]string)
129 onuTP.sOnuPersistentData.PersUniTpPath = make([]uniPersData, 1)
mpagenkodff5dda2020-08-28 11:52:01 +0000130 onuTP.chTpConfigProcessingStep = make(chan uint8)
131 onuTP.chTpKvProcessingStep = make(chan uint8)
132 onuTP.mapUniTpIndication = make(map[uint8]*tTechProfileIndication)
133 onuTP.mapPonAniConfig = make(map[uint8]*tMapPonAniConfig)
mpagenko1cc3cb42020-07-27 15:24:38 +0000134 onuTP.procResult = nil //default assumption processing done with success
mpagenkoaf801632020-07-03 10:00:42 +0000135
Himani Chawla6d2ae152020-09-02 13:11:20 +0530136 onuTP.techProfileKVStore = aDeviceHandler.setBackend(cBasePathTechProfileKVStore)
mpagenkoaf801632020-07-03 10:00:42 +0000137 if onuTP.techProfileKVStore == nil {
138 logger.Errorw("Can't access techProfileKVStore - no backend connection to service",
divyadesai4d299552020-08-18 07:13:49 +0000139 log.Fields{"device-id": aDeviceID, "service": cBasePathTechProfileKVStore})
mpagenkoaf801632020-07-03 10:00:42 +0000140 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000141
142 onuTP.onuKVStorePath = onuTP.deviceID
Himani Chawla6d2ae152020-09-02 13:11:20 +0530143 onuTP.onuKVStore = aDeviceHandler.setBackend(cBasePathOnuKVStore)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000144 if onuTP.onuKVStore == nil {
145 logger.Errorw("Can't access onuKVStore - no backend connection to service",
divyadesai4d299552020-08-18 07:13:49 +0000146 log.Fields{"device-id": aDeviceID, "service": cBasePathOnuKVStore})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000147 }
mpagenkoaf801632020-07-03 10:00:42 +0000148 return &onuTP
149}
150
151// lockTpProcMutex locks OnuUniTechProf processing mutex
Himani Chawla6d2ae152020-09-02 13:11:20 +0530152func (onuTP *onuUniTechProf) lockTpProcMutex() {
mpagenkoaf801632020-07-03 10:00:42 +0000153 onuTP.tpProcMutex.Lock()
154}
155
156// unlockTpProcMutex unlocks OnuUniTechProf processing mutex
Himani Chawla6d2ae152020-09-02 13:11:20 +0530157func (onuTP *onuUniTechProf) unlockTpProcMutex() {
mpagenkoaf801632020-07-03 10:00:42 +0000158 onuTP.tpProcMutex.Unlock()
159}
160
mpagenko1cc3cb42020-07-27 15:24:38 +0000161// resetProcessingErrorIndication resets the internal error indication
162// need to be called before evaluation of any subsequent processing (given by waitForTpCompletion())
Himani Chawla6d2ae152020-09-02 13:11:20 +0530163func (onuTP *onuUniTechProf) resetProcessingErrorIndication() {
mpagenko1cc3cb42020-07-27 15:24:38 +0000164 onuTP.procResult = nil
165}
166
mpagenkoaf801632020-07-03 10:00:42 +0000167// updateOnuUniTpPath verifies and updates changes in the kvStore onuUniTpPath
Himani Chawla6d2ae152020-09-02 13:11:20 +0530168func (onuTP *onuUniTechProf) updateOnuUniTpPath(aUniID uint32, aPathString string) bool {
mpagenkoaf801632020-07-03 10:00:42 +0000169 /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
170 as also the complete sequence is ensured to 'run to completion' before some new request is accepted
171 no specific concurrency protection to sOnuPersistentData is required here
172 */
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000173 if existingPath, present := onuTP.mapUniTpPath[aUniID]; present {
mpagenkoaf801632020-07-03 10:00:42 +0000174 // uni entry already exists
175 //logger.Debugw(" already exists", log.Fields{"for InstanceId": a_uniInstNo})
176 if existingPath != aPathString {
177 if aPathString == "" {
178 //existing entry to be deleted
179 logger.Debugw("UniTp path delete", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000180 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000181 delete(onuTP.mapUniTpPath, aUniID)
mpagenkoaf801632020-07-03 10:00:42 +0000182 } else {
183 //existing entry to be modified
184 logger.Debugw("UniTp path modify", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000185 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000186 onuTP.mapUniTpPath[aUniID] = aPathString
mpagenkoaf801632020-07-03 10:00:42 +0000187 }
188 return true
189 }
190 //entry already exists
191 logger.Debugw("UniTp path already exists", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000192 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
mpagenkoaf801632020-07-03 10:00:42 +0000193 return false
194 }
195 //uni entry does not exist
196 if aPathString == "" {
197 //delete request in non-existing state , accept as no change
198 logger.Debugw("UniTp path already removed", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000199 "device-id": onuTP.deviceID, "uniID": aUniID})
mpagenkoaf801632020-07-03 10:00:42 +0000200 return false
201 }
202 //new entry to be set
203 logger.Debugw("New UniTp path set", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000204 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000205 onuTP.mapUniTpPath[aUniID] = aPathString
mpagenkoaf801632020-07-03 10:00:42 +0000206 return true
207}
208
Himani Chawla6d2ae152020-09-02 13:11:20 +0530209func (onuTP *onuUniTechProf) waitForTpCompletion(cancel context.CancelFunc, wg *sync.WaitGroup) error {
mpagenko3dbcdd22020-07-22 07:38:45 +0000210 defer cancel() //ensure termination of context (may be pro forma)
211 wg.Wait()
212 logger.Debug("some TechProfile Processing completed")
213 onuTP.tpProcMutex.Unlock() //allow further TP related processing
mpagenko1cc3cb42020-07-27 15:24:38 +0000214 return onuTP.procResult
mpagenko3dbcdd22020-07-22 07:38:45 +0000215}
216
217// configureUniTp checks existing tp resources to delete and starts the corresponding OMCI configuation of the UNI port
218// all possibly blocking processing must be run in background to allow for deadline supervision!
219// but take care on sequential background processing when needed (logical dependencies)
Himani Chawla4d908332020-08-31 12:30:20 +0530220// use waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) for internal synchronization
Himani Chawla6d2ae152020-09-02 13:11:20 +0530221func (onuTP *onuUniTechProf) configureUniTp(ctx context.Context,
mpagenkodff5dda2020-08-28 11:52:01 +0000222 aUniID uint8, aPathString string, wg *sync.WaitGroup) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000223 defer wg.Done() //always decrement the waitGroup on return
mpagenkoaf801632020-07-03 10:00:42 +0000224 logger.Debugw("configure the Uni according to TpPath", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000225 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
mpagenkoaf801632020-07-03 10:00:42 +0000226
mpagenkoaf801632020-07-03 10:00:42 +0000227 if onuTP.techProfileKVStore == nil {
228 logger.Debug("techProfileKVStore not set - abort")
Himani Chawla26e555c2020-08-31 12:30:20 +0530229 onuTP.procResult = errors.New("techProfile config aborted: techProfileKVStore not set")
mpagenkoaf801632020-07-03 10:00:42 +0000230 return
231 }
232
mpagenko3dbcdd22020-07-22 07:38:45 +0000233 //ensure that the given uniID is available (configured) in the UniPort class (used for OMCI entities)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530234 var pCurrentUniPort *onuUniPort
mpagenko3dbcdd22020-07-22 07:38:45 +0000235 for _, uniPort := range onuTP.baseDeviceHandler.uniEntityMap {
236 // only if this port is validated for operState transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530237 if uniPort.uniID == uint8(aUniID) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000238 pCurrentUniPort = uniPort
239 break //found - end search loop
240 }
241 }
242 if pCurrentUniPort == nil {
243 logger.Errorw("TechProfile configuration aborted: requested uniID not found in PortDB",
244 log.Fields{"device-id": onuTP.deviceID, "uniID": aUniID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530245 onuTP.procResult = errors.New("techProfile config aborted: requested uniID not found")
mpagenko3dbcdd22020-07-22 07:38:45 +0000246 return
247 }
mpagenkoaf801632020-07-03 10:00:42 +0000248
mpagenkodff5dda2020-08-28 11:52:01 +0000249 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
mpagenkoaf801632020-07-03 10:00:42 +0000250
mpagenko3dbcdd22020-07-22 07:38:45 +0000251 //according to updateOnuUniTpPath() logic the assumption here is, that this configuration is only called
252 // in case the KVPath has changed for the given UNI,
253 // as T-Cont and Gem-Id's are dependent on TechProfile-Id this means, that possibly previously existing
254 // (ANI) configuration of this port has to be removed first
255 // (moreover in this case a possibly existing flow configuration is also not valid anymore and needs clean-up as well)
256 // existence of configuration can be detected based on tp stored TCONT's
257 //TODO!!!:
258 /* if tcontMap not empty {
259 go onuTP.deleteAniSideConfig(ctx, aUniID, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000260 if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000261 //timeout or error detected
262 return
263 }
264 clear tcontMap
265 }
266
267 processingStep++
268 */
269 go onuTP.readAniSideConfigFromTechProfile(ctx, aUniID, aPathString, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000270 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000271 //timeout or error detected
272 logger.Debugw("tech-profile related configuration aborted on read",
273 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530274 onuTP.procResult = errors.New("techProfile config aborted: tech-profile read issue")
mpagenko3dbcdd22020-07-22 07:38:45 +0000275 return
276 }
277
278 processingStep++
279 if valuePA, existPA := onuTP.mapPonAniConfig[aUniID]; existPA {
280 if _, existTG := (*valuePA)[0]; existTG {
281 //Config data for this uni and and at least TCont Index 0 exist
282 go onuTP.setAniSideConfigFromTechProfile(ctx, aUniID, pCurrentUniPort, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000283 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000284 //timeout or error detected
285 logger.Debugw("tech-profile related configuration aborted on set",
286 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530287 onuTP.procResult = errors.New("techProfile config aborted: Omci AniSideConfig failed")
Himani Chawla4d908332020-08-31 12:30:20 +0530288 //this issue here means that the AniConfigFsm has not finished successfully
mpagenko3dbcdd22020-07-22 07:38:45 +0000289 //which requires to reset it to allow for new usage, e.g. also on a different UNI
290 //(without that it would be reset on device down indication latest)
Himani Chawla4d908332020-08-31 12:30:20 +0530291 _ = onuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000292 return
mpagenkoaf801632020-07-03 10:00:42 +0000293 }
294 } else {
mpagenko3dbcdd22020-07-22 07:38:45 +0000295 // strange: UNI entry exists, but no ANI data, maybe such situation should be cleared up (if observed)
296 logger.Debugw("no Tcont/Gem data for this UNI found - abort", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000297 "device-id": onuTP.deviceID, "uniID": aUniID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530298 onuTP.procResult = errors.New("techProfile config aborted: no Tcont/Gem data found for this UNI")
mpagenko1cc3cb42020-07-27 15:24:38 +0000299 return
mpagenkoaf801632020-07-03 10:00:42 +0000300 }
301 } else {
mpagenko3dbcdd22020-07-22 07:38:45 +0000302 logger.Debugw("no PonAni data for this UNI found - abort", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000303 "device-id": onuTP.deviceID, "uniID": aUniID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530304 onuTP.procResult = errors.New("techProfile config aborted: no AniSide data found for this UNI")
mpagenko1cc3cb42020-07-27 15:24:38 +0000305 return
mpagenkoaf801632020-07-03 10:00:42 +0000306 }
307}
308
Himani Chawla6d2ae152020-09-02 13:11:20 +0530309func (onuTP *onuUniTechProf) updateOnuTpPathKvStore(ctx context.Context, wg *sync.WaitGroup) {
mpagenkoaf801632020-07-03 10:00:42 +0000310 defer wg.Done()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000311
312 if onuTP.onuKVStore == nil {
313 logger.Debugw("onuKVStore not set - abort", log.Fields{"device-id": onuTP.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530314 onuTP.procResult = errors.New("onu/tp-data update aborted: onuKVStore not set")
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000315 return
316 }
mpagenkodff5dda2020-08-28 11:52:01 +0000317 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpKvProcessingStep
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000318 go onuTP.storePersistentData(ctx, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000319 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpKvProcessingStep, processingStep) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000320 //timeout or error detected
321 logger.Debugw("ONU/TP-data not written - abort", log.Fields{"device-id": onuTP.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530322 onuTP.procResult = errors.New("onu/tp-data update aborted: during writing process")
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000323 return
324 }
325}
326
Himani Chawla6d2ae152020-09-02 13:11:20 +0530327func (onuTP *onuUniTechProf) restoreFromOnuTpPathKvStore(ctx context.Context) error {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000328 if onuTP.onuKVStore == nil {
329 logger.Debugw("onuKVStore not set - abort", log.Fields{"device-id": onuTP.deviceID})
330 return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", onuTP.deviceID))
331 }
332 if err := onuTP.restorePersistentData(ctx); err != nil {
333 logger.Debugw("ONU/TP-data not read - abort", log.Fields{"device-id": onuTP.deviceID})
334 return err
335 }
336 return nil
337}
338
Himani Chawla6d2ae152020-09-02 13:11:20 +0530339func (onuTP *onuUniTechProf) deleteOnuTpPathKvStore(ctx context.Context) error {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000340 if onuTP.onuKVStore == nil {
341 logger.Debugw("onuKVStore not set - abort", log.Fields{"device-id": onuTP.deviceID})
342 return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", onuTP.deviceID))
343 }
344 if err := onuTP.deletePersistentData(ctx); err != nil {
345 logger.Debugw("ONU/TP-data not read - abort", log.Fields{"device-id": onuTP.deviceID})
346 return err
347 }
348 return nil
mpagenkoaf801632020-07-03 10:00:42 +0000349}
350
mpagenko3dbcdd22020-07-22 07:38:45 +0000351// deleteTpResource removes Resources from the ONU's specified Uni
Himani Chawla6d2ae152020-09-02 13:11:20 +0530352func (onuTP *onuUniTechProf) deleteTpResource(ctx context.Context,
mpagenko3dbcdd22020-07-22 07:38:45 +0000353 aUniID uint32, aPathString string, aResource resourceEntry, aEntryID uint32,
354 wg *sync.WaitGroup) {
mpagenkoaf801632020-07-03 10:00:42 +0000355 defer wg.Done()
356 logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000357 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "Resource": aResource})
mpagenkoaf801632020-07-03 10:00:42 +0000358 //TODO!!!
mpagenko3dbcdd22020-07-22 07:38:45 +0000359 //delete the given resource from ONU OMCI config and data base - as background routine
360 /*
mpagenkodff5dda2020-08-28 11:52:01 +0000361 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
mpagenko3dbcdd22020-07-22 07:38:45 +0000362 go onuTp.deleteAniResource(ctx, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000363 if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000364 //timeout or error detected
365 return
366 }
367 */
mpagenkoaf801632020-07-03 10:00:42 +0000368}
369
mpagenko3dbcdd22020-07-22 07:38:45 +0000370/* internal methods *********************/
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000371
Himani Chawla6d2ae152020-09-02 13:11:20 +0530372func (onuTP *onuUniTechProf) storePersistentData(ctx context.Context, aProcessingStep uint8) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000373
374 onuTP.sOnuPersistentData.PersOnuID = onuTP.baseDeviceHandler.pOnuIndication.OnuId
375 onuTP.sOnuPersistentData.PersIntfID = onuTP.baseDeviceHandler.pOnuIndication.IntfId
376 onuTP.sOnuPersistentData.PersSnr = onuTP.baseDeviceHandler.pOnuOmciDevice.serialNumber
377 //TODO: verify usage of these values during restart UC
378 onuTP.sOnuPersistentData.PersAdminState = "up"
379 onuTP.sOnuPersistentData.PersOperState = "active"
380
381 onuTP.sOnuPersistentData.PersUniTpPath = onuTP.sOnuPersistentData.PersUniTpPath[:0]
382
383 for k, v := range onuTP.mapUniTpPath {
384 onuTP.sOnuPersistentData.PersUniTpPath =
Himani Chawla26e555c2020-08-31 12:30:20 +0530385 append(onuTP.sOnuPersistentData.PersUniTpPath, uniPersData{PersUniID: k, PersTpPath: v})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000386 }
divyadesai4d299552020-08-18 07:13:49 +0000387 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 +0000388
389 Value, err := json.Marshal(onuTP.sOnuPersistentData)
390 if err != nil {
391 logger.Errorw("unable to marshal ONU/TP-data", log.Fields{"onuTP.sOnuPersistentData": onuTP.sOnuPersistentData,
392 "device-id": onuTP.deviceID, "err": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000393 onuTP.chTpKvProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000394 return
395 }
396 err = onuTP.onuKVStore.Put(ctx, onuTP.onuKVStorePath, Value)
397 if err != nil {
398 logger.Errorw("unable to write ONU/TP-data into KVstore", log.Fields{"device-id": onuTP.deviceID, "err": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000399 onuTP.chTpKvProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000400 return
401 }
mpagenkodff5dda2020-08-28 11:52:01 +0000402 onuTP.chTpKvProcessingStep <- aProcessingStep //done
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000403}
404
Himani Chawla6d2ae152020-09-02 13:11:20 +0530405func (onuTP *onuUniTechProf) restorePersistentData(ctx context.Context) error {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000406
407 onuTP.mapUniTpPath = make(map[uint32]string)
408 onuTP.sOnuPersistentData = onuPersistentData{0, 0, "", "", "", make([]uniPersData, 0)}
409
410 Value, err := onuTP.onuKVStore.Get(ctx, onuTP.onuKVStorePath)
411 if err == nil {
412 if Value != nil {
413 logger.Debugw("ONU/TP-data read",
414 log.Fields{"Key": Value.Key, "device-id": onuTP.deviceID})
415 tpTmpBytes, _ := kvstore.ToByte(Value.Value)
416
417 if err = json.Unmarshal(tpTmpBytes, &onuTP.sOnuPersistentData); err != nil {
418 logger.Errorw("unable to unmarshal ONU/TP-data", log.Fields{"error": err, "device-id": onuTP.deviceID})
419 return fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-ONU/TP-data-%s", onuTP.deviceID))
420 }
421 logger.Debugw("ONU/TP-data", log.Fields{"onuTP.sOnuPersistentData": onuTP.sOnuPersistentData,
422 "device-id": onuTP.deviceID})
423
424 for _, uniData := range onuTP.sOnuPersistentData.PersUniTpPath {
Himani Chawla26e555c2020-08-31 12:30:20 +0530425 onuTP.mapUniTpPath[uniData.PersUniID] = uniData.PersTpPath
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000426 }
427 logger.Debugw("TpPath map", log.Fields{"onuTP.mapUniTpPath": onuTP.mapUniTpPath,
428 "device-id": onuTP.deviceID})
429 } else {
430 logger.Errorw("no ONU/TP-data found", log.Fields{"path": onuTP.onuKVStorePath, "device-id": onuTP.deviceID})
431 return fmt.Errorf(fmt.Sprintf("no-ONU/TP-data-found-%s", onuTP.deviceID))
432 }
433 } else {
434 logger.Errorw("unable to read from KVstore", log.Fields{"device-id": onuTP.deviceID})
435 return fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s", onuTP.deviceID))
436 }
437 return nil
438}
439
Himani Chawla6d2ae152020-09-02 13:11:20 +0530440func (onuTP *onuUniTechProf) deletePersistentData(ctx context.Context) error {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000441
divyadesai4d299552020-08-18 07:13:49 +0000442 logger.Debugw("delete ONU/TP-data in KVStore", log.Fields{"device-id": onuTP.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000443 err := onuTP.onuKVStore.Delete(ctx, onuTP.onuKVStorePath)
444 if err != nil {
445 logger.Errorw("unable to delete in KVstore", log.Fields{"device-id": onuTP.deviceID, "err": err})
446 return fmt.Errorf(fmt.Sprintf("unable-delete-in-KVstore-%s", onuTP.deviceID))
447 }
448 return nil
449}
450
Himani Chawla6d2ae152020-09-02 13:11:20 +0530451func (onuTP *onuUniTechProf) readAniSideConfigFromTechProfile(
mpagenkodff5dda2020-08-28 11:52:01 +0000452 ctx context.Context, aUniID uint8, aPathString string, aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000453 var tpInst tp.TechProfile
454
455 //store profile type and identifier for later usage within the OMCI identifier and possibly ME setup
456 //pathstring is defined to be in the form of <ProfType>/<profID>/<Interface/../Identifier>
457 subStringSlice := strings.Split(aPathString, "/")
458 if len(subStringSlice) <= 2 {
459 logger.Errorw("invalid path name format",
460 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000461 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000462 return
463 }
464
465 //just some logical check to avoid unexpected behavior
466 //at this point it is assumed that a new TechProfile is assigned to the UNI
467 //expectation is that no TPIndication entry exists here, if yes,
468 // then we throw a warning and remove it (and the possible ANIConfig) simply
469 // note that the ONU config state may be ambivalent in such a case
470 // also note, that the PonAniConfig map is not checked additionally
471 // consistency to TPIndication is assumed
472 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
473 logger.Warnw("Some active profile entry at reading new TechProfile",
474 log.Fields{"path": aPathString, "device-id": onuTP.deviceID,
475 "UniId": aUniID, "wrongProfile": onuTP.mapUniTpIndication[aUniID].techProfileID})
476 //delete on the mapUniTpIndication map not needed, just overwritten later
477 //delete on the PonAniConfig map should be safe, even if not existing
478 delete(onuTP.mapPonAniConfig, aUniID)
479 } else {
480 // this is normal processing
481 onuTP.mapUniTpIndication[aUniID] = &tTechProfileIndication{} //need to assign some (empty) struct memory first!
482 }
483
484 onuTP.mapUniTpIndication[aUniID].techProfileType = subStringSlice[0]
485 profID, err := strconv.ParseUint(subStringSlice[1], 10, 32)
486 if err != nil {
487 logger.Errorw("invalid ProfileId from path",
488 log.Fields{"ParseErr": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000489 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000490 return
491 }
492
493 //note the limitation on ID range (probably even more limited) - based on usage within OMCI EntityID
494 onuTP.mapUniTpIndication[aUniID].techProfileID = uint16(profID)
495 logger.Debugw("tech-profile path indications",
496 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID,
497 "profType": onuTP.mapUniTpIndication[aUniID].techProfileType,
498 "profID": onuTP.mapUniTpIndication[aUniID].techProfileID})
499
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000500 Value, err := onuTP.techProfileKVStore.Get(ctx, aPathString)
mpagenko3dbcdd22020-07-22 07:38:45 +0000501 if err == nil {
502 if Value != nil {
503 logger.Debugw("tech-profile read",
504 log.Fields{"Key": Value.Key, "device-id": onuTP.deviceID})
505 tpTmpBytes, _ := kvstore.ToByte(Value.Value)
506
507 if err = json.Unmarshal(tpTmpBytes, &tpInst); err != nil {
508 logger.Errorw("TechProf - Failed to unmarshal tech-profile into tpInst",
509 log.Fields{"error": err, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000510 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000511 return
512 }
513 logger.Debugw("TechProf - tpInst", log.Fields{"tpInst": tpInst})
514 // access examples
515 logger.Debugw("TechProf content", log.Fields{"Name": tpInst.Name,
516 "MaxGemPayloadSize": tpInst.InstanceCtrl.MaxGemPayloadSize,
517 "DownstreamGemDiscardmaxThreshold": tpInst.DownstreamGemPortAttributeList[0].DiscardConfig.MaxThreshold})
518 } else {
519 logger.Errorw("No tech-profile found",
520 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000521 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000522 return
523 }
524 } else {
525 logger.Errorw("kvstore-get failed for path",
526 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000527 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000528 return
529 }
530
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000531 //default start with 1Tcont1Gem profile, later extend for multi GemPerTcont and perhaps even MultiTcontMultiGem
mpagenko3dbcdd22020-07-22 07:38:45 +0000532 localMapGemPortParams := make(map[uint16]*gemPortParamStruct)
533 localMapGemPortParams[0] = &gemPortParamStruct{}
534 localMapPonAniConfig := make(map[uint16]*tcontGemList)
535 localMapPonAniConfig[0] = &tcontGemList{tcontParamStruct{}, localMapGemPortParams}
536 onuTP.mapPonAniConfig[aUniID] = (*tMapPonAniConfig)(&localMapPonAniConfig)
537
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000538 //note: the code is currently restricted to one TCcont per Onu (index [0])
mpagenko3dbcdd22020-07-22 07:38:45 +0000539 //get the relevant values from the profile and store to mapPonAniConfig
540 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.allocID = uint16(tpInst.UsScheduler.AllocID)
Himani Chawla4d908332020-08-31 12:30:20 +0530541 //maybe tCont scheduling not (yet) needed - just to basically have it for future
mpagenko3dbcdd22020-07-22 07:38:45 +0000542 // (would only be relevant in case of ONU-2G QOS configuration flexibility)
543 if tpInst.UsScheduler.QSchedPolicy == "StrictPrio" {
544 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.schedPolicy = 1 //for the moment fixed value acc. G.988 //TODO: defines!
545 } else {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000546 //default profile defines "Hybrid" - which probably comes down to WRR with some weigthts for SP
mpagenko3dbcdd22020-07-22 07:38:45 +0000547 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.schedPolicy = 2 //for G.988 WRR
548 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000549 loNumGemPorts := tpInst.NumGemPorts
550 loGemPortRead := false
mpagenko3dbcdd22020-07-22 07:38:45 +0000551 for pos, content := range tpInst.UpstreamGemPortAttributeList {
mpagenko1cc3cb42020-07-27 15:24:38 +0000552 if uint32(pos) == loNumGemPorts {
553 logger.Debugw("PonAniConfig abort GemPortList - GemList exceeds set NumberOfGemPorts",
554 log.Fields{"device-id": onuTP.deviceID, "index": pos, "NumGem": loNumGemPorts})
mpagenko3dbcdd22020-07-22 07:38:45 +0000555 break
556 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000557 if pos == 0 {
558 //at least one upstream GemPort should always exist (else traffic profile makes no sense)
559 loGemPortRead = true
560 } else {
561 //for all further GemPorts we need to extend the mapGemPortParams
562 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)] = &gemPortParamStruct{}
563 }
564 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortID =
565 uint16(content.GemportID)
566 //direction can be correlated later with Downstream list,
567 // for now just assume bidirectional (upstream never exists alone)
mpagenko3dbcdd22020-07-22 07:38:45 +0000568 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].direction = 3 //as defined in G.988
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000569 // expected Prio-Queue values 0..7 with 7 for highest PrioQueue, QueueIndex=Prio = 0..7
570 if 7 < content.PriorityQueue {
571 logger.Errorw("PonAniConfig reject on GemPortList - PrioQueue value invalid",
572 log.Fields{"device-id": onuTP.deviceID, "index": pos, "PrioQueue": content.PriorityQueue})
573 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
574 delete(onuTP.mapPonAniConfig, aUniID)
mpagenkodff5dda2020-08-28 11:52:01 +0000575 onuTP.chTpConfigProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000576 return
577 }
578 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].prioQueueIndex =
579 uint8(content.PriorityQueue)
580 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].pbitString =
Himani Chawla6d2ae152020-09-02 13:11:20 +0530581 strings.TrimPrefix(content.PbitMap, binaryStringPrefix)
mpagenko3dbcdd22020-07-22 07:38:45 +0000582 if content.AesEncryption == "True" {
583 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortEncState = 1
584 } else {
585 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortEncState = 0
586 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000587 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].discardPolicy =
588 content.DiscardPolicy
589 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].queueSchedPolicy =
590 content.SchedulingPolicy
mpagenko3dbcdd22020-07-22 07:38:45 +0000591 //'GemWeight' looks strange in default profile, for now we just copy the weight to first queue
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000592 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].queueWeight =
593 uint8(content.Weight)
mpagenko3dbcdd22020-07-22 07:38:45 +0000594 }
Himani Chawla4d908332020-08-31 12:30:20 +0530595 if !loGemPortRead {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000596 logger.Errorw("PonAniConfig reject - no GemPort could be read from TechProfile",
mpagenko1cc3cb42020-07-27 15:24:38 +0000597 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000598 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
599 delete(onuTP.mapPonAniConfig, aUniID)
mpagenkodff5dda2020-08-28 11:52:01 +0000600 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko1cc3cb42020-07-27 15:24:38 +0000601 return
602 }
Himani Chawla4d908332020-08-31 12:30:20 +0530603 //TODO!! MC (downstream) GemPorts can be set using DownstreamGemPortAttributeList separately
mpagenko3dbcdd22020-07-22 07:38:45 +0000604
605 //logger does not simply output the given structures, just give some example debug values
606 logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000607 "device-id": onuTP.deviceID,
608 "AllocId": (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.allocID})
609 for gemIndex, gemEntry := range (*(onuTP.mapPonAniConfig[0]))[0].mapGemPortParams {
610 logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
611 "GemIndex": gemIndex,
612 "GemPort": gemEntry.gemPortID,
613 "QueueScheduling": gemEntry.queueSchedPolicy})
614 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000615
mpagenkodff5dda2020-08-28 11:52:01 +0000616 onuTP.chTpConfigProcessingStep <- aProcessingStep //done
mpagenko3dbcdd22020-07-22 07:38:45 +0000617}
618
Himani Chawla6d2ae152020-09-02 13:11:20 +0530619func (onuTP *onuUniTechProf) setAniSideConfigFromTechProfile(
620 ctx context.Context, aUniID uint8, apCurrentUniPort *onuUniPort, aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000621
622 //OMCI transfer of ANI data acc. to mapPonAniConfig
623 // also the FSM's are running in background,
mpagenkodff5dda2020-08-28 11:52:01 +0000624 // hence we have to make sure they indicate 'success' success on chTpConfigProcessingStep with aProcessingStep
mpagenko3dbcdd22020-07-22 07:38:45 +0000625 if onuTP.pAniConfigFsm == nil {
626 onuTP.createAniConfigFsm(aUniID, apCurrentUniPort, OmciAniConfigDone, aProcessingStep)
627 } else { //AniConfigFsm already init
628 onuTP.runAniConfigFsm(aProcessingStep)
629 }
630}
631
Himani Chawla6d2ae152020-09-02 13:11:20 +0530632func (onuTP *onuUniTechProf) waitForTimeoutOrCompletion(
mpagenkodff5dda2020-08-28 11:52:01 +0000633 ctx context.Context, aChTpProcessingStep <-chan uint8, aProcessingStep uint8) bool {
mpagenko3dbcdd22020-07-22 07:38:45 +0000634 select {
635 case <-ctx.Done():
636 logger.Warnw("processing not completed in-time: force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000637 log.Fields{"device-id": onuTP.deviceID, "error": ctx.Err()})
mpagenko3dbcdd22020-07-22 07:38:45 +0000638 return false
mpagenkodff5dda2020-08-28 11:52:01 +0000639 case rxStep := <-aChTpProcessingStep:
mpagenko3dbcdd22020-07-22 07:38:45 +0000640 if rxStep == aProcessingStep {
641 return true
642 }
643 //all other values are not accepted - including 0 for error indication
644 logger.Warnw("Invalid processing step received: abort and force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000645 log.Fields{"device-id": onuTP.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000646 "wantedStep": aProcessingStep, "haveStep": rxStep})
647 return false
648 }
649}
650
Himani Chawla4d908332020-08-31 12:30:20 +0530651// createUniLockFsm initializes and runs the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
Himani Chawla6d2ae152020-09-02 13:11:20 +0530652func (onuTP *onuUniTechProf) createAniConfigFsm(aUniID uint8,
653 apCurrentUniPort *onuUniPort, devEvent OnuDeviceEvent, aProcessingStep uint8) {
divyadesai4d299552020-08-18 07:13:49 +0000654 logger.Debugw("createAniConfigFsm", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000655 chAniConfigFsm := make(chan Message, 2048)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530656 pDevEntry := onuTP.baseDeviceHandler.getOnuDeviceEntry(true)
mpagenko3dbcdd22020-07-22 07:38:45 +0000657 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +0000658 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000659 return
660 }
Himani Chawla6d2ae152020-09-02 13:11:20 +0530661 pAniCfgFsm := newUniPonAniConfigFsm(pDevEntry.PDevOmciCC, apCurrentUniPort, onuTP,
mpagenko3dbcdd22020-07-22 07:38:45 +0000662 pDevEntry.pOnuDB, onuTP.mapUniTpIndication[aUniID].techProfileID, devEvent,
663 "AniConfigFsm", onuTP.deviceID, chAniConfigFsm)
664 if pAniCfgFsm != nil {
665 onuTP.pAniConfigFsm = pAniCfgFsm
666 onuTP.runAniConfigFsm(aProcessingStep)
667 } else {
divyadesai4d299552020-08-18 07:13:49 +0000668 logger.Errorw("AniConfigFSM could not be created - abort!!", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000669 }
670}
671
672// runAniConfigFsm starts the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
Himani Chawla6d2ae152020-09-02 13:11:20 +0530673func (onuTP *onuUniTechProf) runAniConfigFsm(aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000674 /* Uni related ANI config procedure -
675 ***** should run via 'aniConfigDone' state and generate the argument requested event *****
676 */
Himani Chawla4d908332020-08-31 12:30:20 +0530677 pACStatemachine := onuTP.pAniConfigFsm.pAdaptFsm.pFsm
mpagenko3dbcdd22020-07-22 07:38:45 +0000678 if pACStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000679 if pACStatemachine.Is(aniStDisabled) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000680 //FSM init requirement to get informed abou FSM completion! (otherwise timeout of the TechProf config)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530681 onuTP.pAniConfigFsm.setFsmCompleteChannel(onuTP.chTpConfigProcessingStep, aProcessingStep)
mpagenko1cc3cb42020-07-27 15:24:38 +0000682 if err := pACStatemachine.Event(aniEvStart); err != nil {
mpagenko3dbcdd22020-07-22 07:38:45 +0000683 logger.Warnw("AniConfigFSM: can't start", log.Fields{"err": err})
684 // maybe try a FSM reset and then again ... - TODO!!!
685 } else {
686 /***** AniConfigFSM started */
687 logger.Debugw("AniConfigFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000688 "state": pACStatemachine.Current(), "device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000689 }
690 } else {
691 logger.Warnw("wrong state of AniConfigFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000692 "have": pACStatemachine.Current(), "device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000693 // maybe try a FSM reset and then again ... - TODO!!!
694 }
695 } else {
divyadesai4d299552020-08-18 07:13:49 +0000696 logger.Errorw("AniConfigFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000697 // maybe try a FSM reset and then again ... - TODO!!!
698 }
mpagenkoaf801632020-07-03 10:00:42 +0000699}
mpagenkodff5dda2020-08-28 11:52:01 +0000700
701// setConfigDone sets the requested techProfile config state (if possible)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530702func (onuTP *onuUniTechProf) setConfigDone(aUniID uint8, aState bool) {
mpagenkodff5dda2020-08-28 11:52:01 +0000703 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
704 onuTP.mutexTPState.Lock()
705 onuTP.mapUniTpIndication[aUniID].techProfileConfigDone = aState
706 onuTP.mutexTPState.Unlock()
707 } //else: the state is just ignored (does not exist)
708}
709
710// getTechProfileDone checks if the Techprofile processing with the requested TechProfile ID was done
Himani Chawla6d2ae152020-09-02 13:11:20 +0530711func (onuTP *onuUniTechProf) getTechProfileDone(aUniID uint8, aTpID uint16) bool {
mpagenkodff5dda2020-08-28 11:52:01 +0000712 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
713 if onuTP.mapUniTpIndication[aUniID].techProfileID == aTpID {
714 onuTP.mutexTPState.Lock()
715 defer onuTP.mutexTPState.Unlock()
716 return onuTP.mapUniTpIndication[aUniID].techProfileConfigDone
717 }
718 }
719 //for all other constellations indicate false = Config not done
720 return false
721}