blob: d9578feb38038391e32b558af706ed6cf2f703fa [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"
Andrea Campanella6515c582020-10-05 11:25:00 +020024 "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 +000036
37//definitions for TechProfileProcessing - copied from OltAdapter:openolt_flowmgr.go
38// could perhaps be defined more globally
39const (
Himani Chawla6d2ae152020-09-02 13:11:20 +053040 // binaryStringPrefix is binary string prefix
41 binaryStringPrefix = "0b"
42 // binaryBit1 is binary bit 1 expressed as a character
43 //binaryBit1 = '1'
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000044)
mpagenkoaf801632020-07-03 10:00:42 +000045
46type resourceEntry int
47
48const (
49 cResourceGemPort resourceEntry = 1
50 cResourceTcont resourceEntry = 2
51)
52
mpagenko3dbcdd22020-07-22 07:38:45 +000053type tTechProfileIndication struct {
mpagenkodff5dda2020-08-28 11:52:01 +000054 techProfileType string
55 techProfileID uint16
56 techProfileConfigDone bool
mpagenko3dbcdd22020-07-22 07:38:45 +000057}
58
59type tcontParamStruct struct {
60 allocID uint16
61 schedPolicy uint8
62}
63type gemPortParamStruct struct {
Himani Chawla4d908332020-08-31 12:30:20 +053064 //ponOmciCC bool
mpagenko3dbcdd22020-07-22 07:38:45 +000065 gemPortID uint16
66 direction uint8
67 gemPortEncState uint8
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000068 prioQueueIndex uint8
69 pbitString string
mpagenko3dbcdd22020-07-22 07:38:45 +000070 discardPolicy string
Himani Chawla4d908332020-08-31 12:30:20 +053071 //could also be a queue specific parameter, not used that way here
72 //maxQueueSize uint16
mpagenko3dbcdd22020-07-22 07:38:45 +000073 queueSchedPolicy string
74 queueWeight uint8
75}
76
77//refers to one tcont and its properties and all assigned GemPorts and their properties
78type tcontGemList struct {
79 tcontParams tcontParamStruct
80 mapGemPortParams map[uint16]*gemPortParamStruct
81}
82
83//refers to all tcont and their Tcont/GemPort Parameters
84type tMapPonAniConfig map[uint16]*tcontGemList
85
Himani Chawla6d2ae152020-09-02 13:11:20 +053086//onuUniTechProf structure holds information about the TechProfiles attached to Uni Ports of the ONU
87type onuUniTechProf struct {
mpagenkodff5dda2020-08-28 11:52:01 +000088 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +053089 baseDeviceHandler *deviceHandler
mpagenkodff5dda2020-08-28 11:52:01 +000090 tpProcMutex sync.RWMutex
mpagenkodff5dda2020-08-28 11:52:01 +000091 techProfileKVStore *db.Backend
mpagenkodff5dda2020-08-28 11:52:01 +000092 chTpConfigProcessingStep chan uint8
mpagenkodff5dda2020-08-28 11:52:01 +000093 mapUniTpIndication map[uint8]*tTechProfileIndication //use pointer values to ease assignments to the map
94 mapPonAniConfig map[uint8]*tMapPonAniConfig //per UNI: use pointer values to ease assignments to the map
Himani Chawla6d2ae152020-09-02 13:11:20 +053095 pAniConfigFsm *uniPonAniConfigFsm
mpagenkodff5dda2020-08-28 11:52:01 +000096 procResult error //error indication of processing
97 mutexTPState sync.Mutex
mpagenkoaf801632020-07-03 10:00:42 +000098}
99
Himani Chawla6d2ae152020-09-02 13:11:20 +0530100//newOnuUniTechProf returns the instance of a OnuUniTechProf
mpagenkoaf801632020-07-03 10:00:42 +0000101//(one instance per ONU/deviceHandler for all possible UNI's)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530102func newOnuUniTechProf(ctx context.Context, aDeviceID string, aDeviceHandler *deviceHandler) *onuUniTechProf {
divyadesai4d299552020-08-18 07:13:49 +0000103 logger.Infow("init-OnuUniTechProf", log.Fields{"device-id": aDeviceID})
Himani Chawla6d2ae152020-09-02 13:11:20 +0530104 var onuTP onuUniTechProf
mpagenkoaf801632020-07-03 10:00:42 +0000105 onuTP.deviceID = aDeviceID
106 onuTP.baseDeviceHandler = aDeviceHandler
107 onuTP.tpProcMutex = sync.RWMutex{}
mpagenkodff5dda2020-08-28 11:52:01 +0000108 onuTP.chTpConfigProcessingStep = make(chan uint8)
mpagenkodff5dda2020-08-28 11:52:01 +0000109 onuTP.mapUniTpIndication = make(map[uint8]*tTechProfileIndication)
110 onuTP.mapPonAniConfig = make(map[uint8]*tMapPonAniConfig)
mpagenko1cc3cb42020-07-27 15:24:38 +0000111 onuTP.procResult = nil //default assumption processing done with success
mpagenkoaf801632020-07-03 10:00:42 +0000112
Himani Chawla6d2ae152020-09-02 13:11:20 +0530113 onuTP.techProfileKVStore = aDeviceHandler.setBackend(cBasePathTechProfileKVStore)
mpagenkoaf801632020-07-03 10:00:42 +0000114 if onuTP.techProfileKVStore == nil {
115 logger.Errorw("Can't access techProfileKVStore - no backend connection to service",
divyadesai4d299552020-08-18 07:13:49 +0000116 log.Fields{"device-id": aDeviceID, "service": cBasePathTechProfileKVStore})
mpagenkoaf801632020-07-03 10:00:42 +0000117 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000118
mpagenkoaf801632020-07-03 10:00:42 +0000119 return &onuTP
120}
121
122// lockTpProcMutex locks OnuUniTechProf processing mutex
Himani Chawla6d2ae152020-09-02 13:11:20 +0530123func (onuTP *onuUniTechProf) lockTpProcMutex() {
mpagenkoaf801632020-07-03 10:00:42 +0000124 onuTP.tpProcMutex.Lock()
125}
126
127// unlockTpProcMutex unlocks OnuUniTechProf processing mutex
Himani Chawla6d2ae152020-09-02 13:11:20 +0530128func (onuTP *onuUniTechProf) unlockTpProcMutex() {
mpagenkoaf801632020-07-03 10:00:42 +0000129 onuTP.tpProcMutex.Unlock()
130}
131
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000132// resetTpProcessingErrorIndication resets the internal error indication
mpagenko1cc3cb42020-07-27 15:24:38 +0000133// need to be called before evaluation of any subsequent processing (given by waitForTpCompletion())
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000134func (onuTP *onuUniTechProf) resetTpProcessingErrorIndication() {
mpagenko1cc3cb42020-07-27 15:24:38 +0000135 onuTP.procResult = nil
136}
137
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000138func (onuTP *onuUniTechProf) getTpProcessingErrorIndication() error {
mpagenko1cc3cb42020-07-27 15:24:38 +0000139 return onuTP.procResult
mpagenko3dbcdd22020-07-22 07:38:45 +0000140}
141
142// configureUniTp checks existing tp resources to delete and starts the corresponding OMCI configuation of the UNI port
143// all possibly blocking processing must be run in background to allow for deadline supervision!
144// but take care on sequential background processing when needed (logical dependencies)
Himani Chawla4d908332020-08-31 12:30:20 +0530145// use waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) for internal synchronization
Himani Chawla6d2ae152020-09-02 13:11:20 +0530146func (onuTP *onuUniTechProf) configureUniTp(ctx context.Context,
mpagenkodff5dda2020-08-28 11:52:01 +0000147 aUniID uint8, aPathString string, wg *sync.WaitGroup) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000148 defer wg.Done() //always decrement the waitGroup on return
mpagenkoaf801632020-07-03 10:00:42 +0000149 logger.Debugw("configure the Uni according to TpPath", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000150 "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
mpagenkoaf801632020-07-03 10:00:42 +0000151
mpagenkoaf801632020-07-03 10:00:42 +0000152 if onuTP.techProfileKVStore == nil {
153 logger.Debug("techProfileKVStore not set - abort")
Himani Chawla26e555c2020-08-31 12:30:20 +0530154 onuTP.procResult = errors.New("techProfile config aborted: techProfileKVStore not set")
mpagenkoaf801632020-07-03 10:00:42 +0000155 return
156 }
157
mpagenko3dbcdd22020-07-22 07:38:45 +0000158 //ensure that the given uniID is available (configured) in the UniPort class (used for OMCI entities)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530159 var pCurrentUniPort *onuUniPort
mpagenko3dbcdd22020-07-22 07:38:45 +0000160 for _, uniPort := range onuTP.baseDeviceHandler.uniEntityMap {
161 // only if this port is validated for operState transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530162 if uniPort.uniID == uint8(aUniID) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000163 pCurrentUniPort = uniPort
164 break //found - end search loop
165 }
166 }
167 if pCurrentUniPort == nil {
168 logger.Errorw("TechProfile configuration aborted: requested uniID not found in PortDB",
169 log.Fields{"device-id": onuTP.deviceID, "uniID": aUniID})
Andrea Campanella6515c582020-10-05 11:25:00 +0200170 onuTP.procResult = fmt.Errorf("techProfile config aborted: requested uniID not found %d on %s",
171 aUniID, onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000172 return
173 }
mpagenkoaf801632020-07-03 10:00:42 +0000174
mpagenkodff5dda2020-08-28 11:52:01 +0000175 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
mpagenkoaf801632020-07-03 10:00:42 +0000176
mpagenko3dbcdd22020-07-22 07:38:45 +0000177 //according to updateOnuUniTpPath() logic the assumption here is, that this configuration is only called
178 // in case the KVPath has changed for the given UNI,
179 // as T-Cont and Gem-Id's are dependent on TechProfile-Id this means, that possibly previously existing
180 // (ANI) configuration of this port has to be removed first
181 // (moreover in this case a possibly existing flow configuration is also not valid anymore and needs clean-up as well)
182 // existence of configuration can be detected based on tp stored TCONT's
Andrea Campanella6515c582020-10-05 11:25:00 +0200183 //TODO:
mpagenko3dbcdd22020-07-22 07:38:45 +0000184 /* if tcontMap not empty {
185 go onuTP.deleteAniSideConfig(ctx, aUniID, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000186 if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000187 //timeout or error detected
188 return
189 }
190 clear tcontMap
191 }
192
193 processingStep++
194 */
195 go onuTP.readAniSideConfigFromTechProfile(ctx, aUniID, aPathString, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000196 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000197 //timeout or error detected
198 logger.Debugw("tech-profile related configuration aborted on read",
199 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
Andrea Campanella6515c582020-10-05 11:25:00 +0200200 onuTP.procResult = fmt.Errorf("techProfile config aborted: tech-profile read issue for %d on %s",
201 aUniID, onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000202 return
203 }
204
205 processingStep++
206 if valuePA, existPA := onuTP.mapPonAniConfig[aUniID]; existPA {
207 if _, existTG := (*valuePA)[0]; existTG {
208 //Config data for this uni and and at least TCont Index 0 exist
209 go onuTP.setAniSideConfigFromTechProfile(ctx, aUniID, pCurrentUniPort, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000210 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000211 //timeout or error detected
212 logger.Debugw("tech-profile related configuration aborted on set",
213 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
Andrea Campanella6515c582020-10-05 11:25:00 +0200214 onuTP.procResult = fmt.Errorf("techProfile config aborted: Omci AniSideConfig failed %d on %s",
215 aUniID, onuTP.deviceID)
Himani Chawla4d908332020-08-31 12:30:20 +0530216 //this issue here means that the AniConfigFsm has not finished successfully
mpagenko3dbcdd22020-07-22 07:38:45 +0000217 //which requires to reset it to allow for new usage, e.g. also on a different UNI
218 //(without that it would be reset on device down indication latest)
Himani Chawla4d908332020-08-31 12:30:20 +0530219 _ = onuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000220 return
mpagenkoaf801632020-07-03 10:00:42 +0000221 }
222 } else {
mpagenko3dbcdd22020-07-22 07:38:45 +0000223 // strange: UNI entry exists, but no ANI data, maybe such situation should be cleared up (if observed)
224 logger.Debugw("no Tcont/Gem data for this UNI found - abort", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000225 "device-id": onuTP.deviceID, "uniID": aUniID})
Andrea Campanella6515c582020-10-05 11:25:00 +0200226 onuTP.procResult = fmt.Errorf("techProfile config aborted: no Tcont/Gem data found for this UNI %d on %s",
227 aUniID, onuTP.deviceID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000228 return
mpagenkoaf801632020-07-03 10:00:42 +0000229 }
230 } else {
mpagenko3dbcdd22020-07-22 07:38:45 +0000231 logger.Debugw("no PonAni data for this UNI found - abort", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000232 "device-id": onuTP.deviceID, "uniID": aUniID})
Andrea Campanella6515c582020-10-05 11:25:00 +0200233 onuTP.procResult = fmt.Errorf("techProfile config aborted: no AniSide data found for this UNI %d on %s",
234 aUniID, onuTP.deviceID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000235 return
mpagenkoaf801632020-07-03 10:00:42 +0000236 }
237}
238
mpagenko3dbcdd22020-07-22 07:38:45 +0000239/* internal methods *********************/
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000240
Himani Chawla6d2ae152020-09-02 13:11:20 +0530241func (onuTP *onuUniTechProf) readAniSideConfigFromTechProfile(
mpagenkodff5dda2020-08-28 11:52:01 +0000242 ctx context.Context, aUniID uint8, aPathString string, aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000243 var tpInst tp.TechProfile
244
245 //store profile type and identifier for later usage within the OMCI identifier and possibly ME setup
246 //pathstring is defined to be in the form of <ProfType>/<profID>/<Interface/../Identifier>
247 subStringSlice := strings.Split(aPathString, "/")
248 if len(subStringSlice) <= 2 {
249 logger.Errorw("invalid path name format",
250 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000251 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000252 return
253 }
254
255 //just some logical check to avoid unexpected behavior
256 //at this point it is assumed that a new TechProfile is assigned to the UNI
257 //expectation is that no TPIndication entry exists here, if yes,
258 // then we throw a warning and remove it (and the possible ANIConfig) simply
259 // note that the ONU config state may be ambivalent in such a case
260 // also note, that the PonAniConfig map is not checked additionally
261 // consistency to TPIndication is assumed
262 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
263 logger.Warnw("Some active profile entry at reading new TechProfile",
264 log.Fields{"path": aPathString, "device-id": onuTP.deviceID,
265 "UniId": aUniID, "wrongProfile": onuTP.mapUniTpIndication[aUniID].techProfileID})
266 //delete on the mapUniTpIndication map not needed, just overwritten later
267 //delete on the PonAniConfig map should be safe, even if not existing
268 delete(onuTP.mapPonAniConfig, aUniID)
269 } else {
270 // this is normal processing
271 onuTP.mapUniTpIndication[aUniID] = &tTechProfileIndication{} //need to assign some (empty) struct memory first!
272 }
273
274 onuTP.mapUniTpIndication[aUniID].techProfileType = subStringSlice[0]
275 profID, err := strconv.ParseUint(subStringSlice[1], 10, 32)
276 if err != nil {
277 logger.Errorw("invalid ProfileId from path",
278 log.Fields{"ParseErr": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000279 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000280 return
281 }
282
283 //note the limitation on ID range (probably even more limited) - based on usage within OMCI EntityID
284 onuTP.mapUniTpIndication[aUniID].techProfileID = uint16(profID)
285 logger.Debugw("tech-profile path indications",
286 log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID,
287 "profType": onuTP.mapUniTpIndication[aUniID].techProfileType,
288 "profID": onuTP.mapUniTpIndication[aUniID].techProfileID})
289
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000290 Value, err := onuTP.techProfileKVStore.Get(ctx, aPathString)
mpagenko3dbcdd22020-07-22 07:38:45 +0000291 if err == nil {
292 if Value != nil {
293 logger.Debugw("tech-profile read",
294 log.Fields{"Key": Value.Key, "device-id": onuTP.deviceID})
295 tpTmpBytes, _ := kvstore.ToByte(Value.Value)
296
297 if err = json.Unmarshal(tpTmpBytes, &tpInst); err != nil {
298 logger.Errorw("TechProf - Failed to unmarshal tech-profile into tpInst",
299 log.Fields{"error": err, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000300 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000301 return
302 }
303 logger.Debugw("TechProf - tpInst", log.Fields{"tpInst": tpInst})
304 // access examples
305 logger.Debugw("TechProf content", log.Fields{"Name": tpInst.Name,
306 "MaxGemPayloadSize": tpInst.InstanceCtrl.MaxGemPayloadSize,
307 "DownstreamGemDiscardmaxThreshold": tpInst.DownstreamGemPortAttributeList[0].DiscardConfig.MaxThreshold})
308 } else {
309 logger.Errorw("No tech-profile found",
310 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000311 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000312 return
313 }
314 } else {
315 logger.Errorw("kvstore-get failed for path",
316 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000317 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000318 return
319 }
320
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000321 //default start with 1Tcont1Gem profile, later extend for multi GemPerTcont and perhaps even MultiTcontMultiGem
mpagenko3dbcdd22020-07-22 07:38:45 +0000322 localMapGemPortParams := make(map[uint16]*gemPortParamStruct)
323 localMapGemPortParams[0] = &gemPortParamStruct{}
324 localMapPonAniConfig := make(map[uint16]*tcontGemList)
325 localMapPonAniConfig[0] = &tcontGemList{tcontParamStruct{}, localMapGemPortParams}
326 onuTP.mapPonAniConfig[aUniID] = (*tMapPonAniConfig)(&localMapPonAniConfig)
327
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000328 //note: the code is currently restricted to one TCcont per Onu (index [0])
mpagenko3dbcdd22020-07-22 07:38:45 +0000329 //get the relevant values from the profile and store to mapPonAniConfig
330 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.allocID = uint16(tpInst.UsScheduler.AllocID)
Himani Chawla4d908332020-08-31 12:30:20 +0530331 //maybe tCont scheduling not (yet) needed - just to basically have it for future
mpagenko3dbcdd22020-07-22 07:38:45 +0000332 // (would only be relevant in case of ONU-2G QOS configuration flexibility)
333 if tpInst.UsScheduler.QSchedPolicy == "StrictPrio" {
334 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.schedPolicy = 1 //for the moment fixed value acc. G.988 //TODO: defines!
335 } else {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000336 //default profile defines "Hybrid" - which probably comes down to WRR with some weigthts for SP
mpagenko3dbcdd22020-07-22 07:38:45 +0000337 (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.schedPolicy = 2 //for G.988 WRR
338 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000339 loNumGemPorts := tpInst.NumGemPorts
340 loGemPortRead := false
mpagenko3dbcdd22020-07-22 07:38:45 +0000341 for pos, content := range tpInst.UpstreamGemPortAttributeList {
mpagenko1cc3cb42020-07-27 15:24:38 +0000342 if uint32(pos) == loNumGemPorts {
343 logger.Debugw("PonAniConfig abort GemPortList - GemList exceeds set NumberOfGemPorts",
344 log.Fields{"device-id": onuTP.deviceID, "index": pos, "NumGem": loNumGemPorts})
mpagenko3dbcdd22020-07-22 07:38:45 +0000345 break
346 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000347 if pos == 0 {
348 //at least one upstream GemPort should always exist (else traffic profile makes no sense)
349 loGemPortRead = true
350 } else {
351 //for all further GemPorts we need to extend the mapGemPortParams
352 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)] = &gemPortParamStruct{}
353 }
354 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortID =
355 uint16(content.GemportID)
356 //direction can be correlated later with Downstream list,
357 // for now just assume bidirectional (upstream never exists alone)
mpagenko3dbcdd22020-07-22 07:38:45 +0000358 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].direction = 3 //as defined in G.988
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000359 // expected Prio-Queue values 0..7 with 7 for highest PrioQueue, QueueIndex=Prio = 0..7
360 if 7 < content.PriorityQueue {
361 logger.Errorw("PonAniConfig reject on GemPortList - PrioQueue value invalid",
362 log.Fields{"device-id": onuTP.deviceID, "index": pos, "PrioQueue": content.PriorityQueue})
363 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
364 delete(onuTP.mapPonAniConfig, aUniID)
mpagenkodff5dda2020-08-28 11:52:01 +0000365 onuTP.chTpConfigProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000366 return
367 }
368 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].prioQueueIndex =
369 uint8(content.PriorityQueue)
370 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].pbitString =
Himani Chawla6d2ae152020-09-02 13:11:20 +0530371 strings.TrimPrefix(content.PbitMap, binaryStringPrefix)
mpagenko3dbcdd22020-07-22 07:38:45 +0000372 if content.AesEncryption == "True" {
373 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortEncState = 1
374 } else {
375 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].gemPortEncState = 0
376 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000377 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].discardPolicy =
378 content.DiscardPolicy
379 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].queueSchedPolicy =
380 content.SchedulingPolicy
mpagenko3dbcdd22020-07-22 07:38:45 +0000381 //'GemWeight' looks strange in default profile, for now we just copy the weight to first queue
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000382 (*(onuTP.mapPonAniConfig[aUniID]))[0].mapGemPortParams[uint16(pos)].queueWeight =
383 uint8(content.Weight)
mpagenko3dbcdd22020-07-22 07:38:45 +0000384 }
Himani Chawla4d908332020-08-31 12:30:20 +0530385 if !loGemPortRead {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000386 logger.Errorw("PonAniConfig reject - no GemPort could be read from TechProfile",
mpagenko1cc3cb42020-07-27 15:24:38 +0000387 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000388 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
389 delete(onuTP.mapPonAniConfig, aUniID)
mpagenkodff5dda2020-08-28 11:52:01 +0000390 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko1cc3cb42020-07-27 15:24:38 +0000391 return
392 }
Himani Chawla4d908332020-08-31 12:30:20 +0530393 //TODO!! MC (downstream) GemPorts can be set using DownstreamGemPortAttributeList separately
mpagenko3dbcdd22020-07-22 07:38:45 +0000394
395 //logger does not simply output the given structures, just give some example debug values
396 logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000397 "device-id": onuTP.deviceID,
398 "AllocId": (*(onuTP.mapPonAniConfig[aUniID]))[0].tcontParams.allocID})
399 for gemIndex, gemEntry := range (*(onuTP.mapPonAniConfig[0]))[0].mapGemPortParams {
400 logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
401 "GemIndex": gemIndex,
402 "GemPort": gemEntry.gemPortID,
403 "QueueScheduling": gemEntry.queueSchedPolicy})
404 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000405
mpagenkodff5dda2020-08-28 11:52:01 +0000406 onuTP.chTpConfigProcessingStep <- aProcessingStep //done
mpagenko3dbcdd22020-07-22 07:38:45 +0000407}
408
Himani Chawla6d2ae152020-09-02 13:11:20 +0530409func (onuTP *onuUniTechProf) setAniSideConfigFromTechProfile(
410 ctx context.Context, aUniID uint8, apCurrentUniPort *onuUniPort, aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000411
412 //OMCI transfer of ANI data acc. to mapPonAniConfig
413 // also the FSM's are running in background,
mpagenkodff5dda2020-08-28 11:52:01 +0000414 // hence we have to make sure they indicate 'success' success on chTpConfigProcessingStep with aProcessingStep
mpagenko3dbcdd22020-07-22 07:38:45 +0000415 if onuTP.pAniConfigFsm == nil {
416 onuTP.createAniConfigFsm(aUniID, apCurrentUniPort, OmciAniConfigDone, aProcessingStep)
417 } else { //AniConfigFsm already init
418 onuTP.runAniConfigFsm(aProcessingStep)
419 }
420}
421
Himani Chawla6d2ae152020-09-02 13:11:20 +0530422func (onuTP *onuUniTechProf) waitForTimeoutOrCompletion(
mpagenkodff5dda2020-08-28 11:52:01 +0000423 ctx context.Context, aChTpProcessingStep <-chan uint8, aProcessingStep uint8) bool {
mpagenko3dbcdd22020-07-22 07:38:45 +0000424 select {
425 case <-ctx.Done():
426 logger.Warnw("processing not completed in-time: force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000427 log.Fields{"device-id": onuTP.deviceID, "error": ctx.Err()})
mpagenko3dbcdd22020-07-22 07:38:45 +0000428 return false
mpagenkodff5dda2020-08-28 11:52:01 +0000429 case rxStep := <-aChTpProcessingStep:
mpagenko3dbcdd22020-07-22 07:38:45 +0000430 if rxStep == aProcessingStep {
431 return true
432 }
433 //all other values are not accepted - including 0 for error indication
434 logger.Warnw("Invalid processing step received: abort and force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000435 log.Fields{"device-id": onuTP.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000436 "wantedStep": aProcessingStep, "haveStep": rxStep})
437 return false
438 }
439}
440
Himani Chawla4d908332020-08-31 12:30:20 +0530441// createUniLockFsm initializes and runs the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
Himani Chawla6d2ae152020-09-02 13:11:20 +0530442func (onuTP *onuUniTechProf) createAniConfigFsm(aUniID uint8,
443 apCurrentUniPort *onuUniPort, devEvent OnuDeviceEvent, aProcessingStep uint8) {
divyadesai4d299552020-08-18 07:13:49 +0000444 logger.Debugw("createAniConfigFsm", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000445 chAniConfigFsm := make(chan Message, 2048)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530446 pDevEntry := onuTP.baseDeviceHandler.getOnuDeviceEntry(true)
mpagenko3dbcdd22020-07-22 07:38:45 +0000447 if pDevEntry == nil {
divyadesai4d299552020-08-18 07:13:49 +0000448 logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000449 return
450 }
Himani Chawla6d2ae152020-09-02 13:11:20 +0530451 pAniCfgFsm := newUniPonAniConfigFsm(pDevEntry.PDevOmciCC, apCurrentUniPort, onuTP,
mpagenko3dbcdd22020-07-22 07:38:45 +0000452 pDevEntry.pOnuDB, onuTP.mapUniTpIndication[aUniID].techProfileID, devEvent,
453 "AniConfigFsm", onuTP.deviceID, chAniConfigFsm)
454 if pAniCfgFsm != nil {
455 onuTP.pAniConfigFsm = pAniCfgFsm
456 onuTP.runAniConfigFsm(aProcessingStep)
457 } else {
divyadesai4d299552020-08-18 07:13:49 +0000458 logger.Errorw("AniConfigFSM could not be created - abort!!", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000459 }
460}
461
462// runAniConfigFsm starts the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
Himani Chawla6d2ae152020-09-02 13:11:20 +0530463func (onuTP *onuUniTechProf) runAniConfigFsm(aProcessingStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000464 /* Uni related ANI config procedure -
465 ***** should run via 'aniConfigDone' state and generate the argument requested event *****
466 */
Himani Chawla4d908332020-08-31 12:30:20 +0530467 pACStatemachine := onuTP.pAniConfigFsm.pAdaptFsm.pFsm
mpagenko3dbcdd22020-07-22 07:38:45 +0000468 if pACStatemachine != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000469 if pACStatemachine.Is(aniStDisabled) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000470 //FSM init requirement to get informed abou FSM completion! (otherwise timeout of the TechProf config)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530471 onuTP.pAniConfigFsm.setFsmCompleteChannel(onuTP.chTpConfigProcessingStep, aProcessingStep)
mpagenko1cc3cb42020-07-27 15:24:38 +0000472 if err := pACStatemachine.Event(aniEvStart); err != nil {
mpagenko3dbcdd22020-07-22 07:38:45 +0000473 logger.Warnw("AniConfigFSM: can't start", log.Fields{"err": err})
474 // maybe try a FSM reset and then again ... - TODO!!!
475 } else {
476 /***** AniConfigFSM started */
477 logger.Debugw("AniConfigFSM started", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000478 "state": pACStatemachine.Current(), "device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000479 }
480 } else {
481 logger.Warnw("wrong state of AniConfigFSM - want: disabled", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000482 "have": pACStatemachine.Current(), "device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000483 // maybe try a FSM reset and then again ... - TODO!!!
484 }
485 } else {
divyadesai4d299552020-08-18 07:13:49 +0000486 logger.Errorw("AniConfigFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": onuTP.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000487 // maybe try a FSM reset and then again ... - TODO!!!
488 }
mpagenkoaf801632020-07-03 10:00:42 +0000489}
mpagenkodff5dda2020-08-28 11:52:01 +0000490
491// setConfigDone sets the requested techProfile config state (if possible)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530492func (onuTP *onuUniTechProf) setConfigDone(aUniID uint8, aState bool) {
mpagenkodff5dda2020-08-28 11:52:01 +0000493 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
494 onuTP.mutexTPState.Lock()
495 onuTP.mapUniTpIndication[aUniID].techProfileConfigDone = aState
496 onuTP.mutexTPState.Unlock()
497 } //else: the state is just ignored (does not exist)
498}
499
500// getTechProfileDone checks if the Techprofile processing with the requested TechProfile ID was done
Himani Chawla6d2ae152020-09-02 13:11:20 +0530501func (onuTP *onuUniTechProf) getTechProfileDone(aUniID uint8, aTpID uint16) bool {
mpagenkodff5dda2020-08-28 11:52:01 +0000502 if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
503 if onuTP.mapUniTpIndication[aUniID].techProfileID == aTpID {
504 onuTP.mutexTPState.Lock()
505 defer onuTP.mutexTPState.Unlock()
506 return onuTP.mapUniTpIndication[aUniID].techProfileConfigDone
507 }
508 }
509 //for all other constellations indicate false = Config not done
510 return false
511}