blob: c51c489ff82aa8f2859dbd06f2465fa701cddae8 [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
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000017//Package avcfg provides anig and vlan configuration functionality
18package avcfg
mpagenkoaf801632020-07-03 10:00:42 +000019
20import (
21 "context"
Andrea Campanella6515c582020-10-05 11:25:00 +020022 "fmt"
ozgecanetsia4b232302020-11-11 10:58:10 +030023 "strconv"
mpagenko3dbcdd22020-07-22 07:38:45 +000024 "strings"
mpagenkoaf801632020-07-03 10:00:42 +000025 "sync"
26
khenaidoo7d3c5582021-08-11 18:09:44 -040027 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000028 cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
khenaidoo7d3c5582021-08-11 18:09:44 -040029 "github.com/opencord/voltha-protos/v5/go/tech_profile"
mpagenkoaf801632020-07-03 10:00:42 +000030)
31
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000032//definitions for TechProfileProcessing - copied from OltAdapter:openolt_flowmgr.go
33// could perhaps be defined more globally
34const (
Himani Chawla6d2ae152020-09-02 13:11:20 +053035 // binaryStringPrefix is binary string prefix
36 binaryStringPrefix = "0b"
37 // binaryBit1 is binary bit 1 expressed as a character
38 //binaryBit1 = '1'
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000039)
mpagenkoaf801632020-07-03 10:00:42 +000040
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000041// ResourceEntry - TODO: add comment
42type ResourceEntry int
mpagenkoaf801632020-07-03 10:00:42 +000043
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000044// TODO: add comment
mpagenkoaf801632020-07-03 10:00:42 +000045const (
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000046 CResourceGemPort ResourceEntry = 1
47 CResourceTcont ResourceEntry = 2
mpagenkoaf801632020-07-03 10:00:42 +000048)
49
mpagenko3dbcdd22020-07-22 07:38:45 +000050type tTechProfileIndication struct {
mpagenkodff5dda2020-08-28 11:52:01 +000051 techProfileType string
Girish Gowdra041dcb32020-11-16 16:54:30 -080052 techProfileID uint8
mpagenkodff5dda2020-08-28 11:52:01 +000053 techProfileConfigDone bool
mpagenko2418ab02020-11-12 12:58:06 +000054 techProfileToDelete bool
mpagenko3dbcdd22020-07-22 07:38:45 +000055}
56
57type tcontParamStruct struct {
58 allocID uint16
59 schedPolicy uint8
60}
61type gemPortParamStruct struct {
Himani Chawla4d908332020-08-31 12:30:20 +053062 //ponOmciCC bool
mpagenko3dbcdd22020-07-22 07:38:45 +000063 gemPortID uint16
64 direction uint8
65 gemPortEncState uint8
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000066 prioQueueIndex uint8
67 pbitString string
mpagenko3dbcdd22020-07-22 07:38:45 +000068 discardPolicy string
Himani Chawla4d908332020-08-31 12:30:20 +053069 //could also be a queue specific parameter, not used that way here
70 //maxQueueSize uint16
mpagenko3dbcdd22020-07-22 07:38:45 +000071 queueSchedPolicy string
72 queueWeight uint8
Himani Chawla1c136902020-12-10 16:30:59 +053073 removeGemID uint16
ozgecanetsia4b232302020-11-11 10:58:10 +030074 isMulticast bool
75 //TODO check if this has any value/difference from gemPortId
76 multicastGemPortID uint16
77 staticACL string
78 dynamicACL string
mpagenko3dbcdd22020-07-22 07:38:45 +000079}
80
81//refers to one tcont and its properties and all assigned GemPorts and their properties
82type tcontGemList struct {
83 tcontParams tcontParamStruct
84 mapGemPortParams map[uint16]*gemPortParamStruct
85}
86
Girish Gowdra041dcb32020-11-16 16:54:30 -080087// refers a unique combination of uniID and tpID for a given ONU.
88type uniTP struct {
89 uniID uint8
90 tpID uint8
91}
mpagenko3dbcdd22020-07-22 07:38:45 +000092
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000093//OnuUniTechProf structure holds information about the TechProfiles attached to Uni Ports of the ONU
94type OnuUniTechProf struct {
mpagenko01e726e2020-10-23 09:45:29 +000095 deviceID string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000096 baseDeviceHandler cmn.IdeviceHandler
97 onuDevice cmn.IonuDeviceEntry
mpagenkodff5dda2020-08-28 11:52:01 +000098 tpProcMutex sync.RWMutex
mpagenkodff5dda2020-08-28 11:52:01 +000099 chTpConfigProcessingStep chan uint8
Girish Gowdra041dcb32020-11-16 16:54:30 -0800100 mapUniTpIndication map[uniTP]*tTechProfileIndication //use pointer values to ease assignments to the map
101 mapPonAniConfig map[uniTP]*tcontGemList //per UNI: use pointer values to ease assignments to the map
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000102 PAniConfigFsm map[uniTP]*UniPonAniConfigFsm
Girish Gowdra041dcb32020-11-16 16:54:30 -0800103 procResult map[uniTP]error //error indication of processing
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800104 mutexTPState sync.RWMutex
Girish Gowdra041dcb32020-11-16 16:54:30 -0800105 tpProfileExists map[uniTP]bool
mpagenko73143992021-04-09 15:17:10 +0000106 tpProfileResetting map[uniTP]bool
mpagenko8b07c1b2020-11-26 10:36:31 +0000107 mapRemoveGemEntry map[uniTP]*gemPortParamStruct //per UNI: pointer to GemEntry to be removed
mpagenkoaf801632020-07-03 10:00:42 +0000108}
109
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000110func (onuTP *OnuUniTechProf) multicastConfiguredForOtherUniTps(ctx context.Context, uniTpKey uniTP) bool {
111 for _, aniFsm := range onuTP.PAniConfigFsm {
ozgecanetsia72e1c9f2021-05-26 17:26:29 +0300112 if aniFsm.uniTpKey.uniID == uniTpKey.uniID && aniFsm.uniTpKey.tpID == uniTpKey.tpID {
113 continue
114 }
115 if aniFsm.hasMulticastGem(ctx) {
116 return true
117 }
118 }
119 return false
120}
121
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000122//NewOnuUniTechProf returns the instance of a OnuUniTechProf
mpagenkoaf801632020-07-03 10:00:42 +0000123//(one instance per ONU/deviceHandler for all possible UNI's)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000124func NewOnuUniTechProf(ctx context.Context, aDeviceHandler cmn.IdeviceHandler, aOnuDev cmn.IonuDeviceEntry) *OnuUniTechProf {
125
126 var onuTP OnuUniTechProf
127 onuTP.deviceID = aDeviceHandler.GetDeviceID()
128 logger.Debugw(ctx, "init-OnuUniTechProf", log.Fields{"device-id": onuTP.deviceID})
mpagenkoaf801632020-07-03 10:00:42 +0000129 onuTP.baseDeviceHandler = aDeviceHandler
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000130 onuTP.onuDevice = aOnuDev
mpagenkodff5dda2020-08-28 11:52:01 +0000131 onuTP.chTpConfigProcessingStep = make(chan uint8)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800132 onuTP.mapUniTpIndication = make(map[uniTP]*tTechProfileIndication)
133 onuTP.mapPonAniConfig = make(map[uniTP]*tcontGemList)
134 onuTP.procResult = make(map[uniTP]error)
135 onuTP.tpProfileExists = make(map[uniTP]bool)
mpagenko73143992021-04-09 15:17:10 +0000136 onuTP.tpProfileResetting = make(map[uniTP]bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000137 onuTP.mapRemoveGemEntry = make(map[uniTP]*gemPortParamStruct)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000138
mpagenkoaf801632020-07-03 10:00:42 +0000139 return &onuTP
140}
141
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000142// LockTpProcMutex locks OnuUniTechProf processing mutex
143func (onuTP *OnuUniTechProf) LockTpProcMutex() {
mpagenkoaf801632020-07-03 10:00:42 +0000144 onuTP.tpProcMutex.Lock()
145}
146
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000147// UnlockTpProcMutex unlocks OnuUniTechProf processing mutex
148func (onuTP *OnuUniTechProf) UnlockTpProcMutex() {
mpagenkoaf801632020-07-03 10:00:42 +0000149 onuTP.tpProcMutex.Unlock()
150}
151
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000152// ResetTpProcessingErrorIndication resets the internal error indication
mpagenko1cc3cb42020-07-27 15:24:38 +0000153// need to be called before evaluation of any subsequent processing (given by waitForTpCompletion())
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000154func (onuTP *OnuUniTechProf) ResetTpProcessingErrorIndication(aUniID uint8, aTpID uint8) {
mpagenko73143992021-04-09 15:17:10 +0000155 onuTP.mutexTPState.Lock()
156 defer onuTP.mutexTPState.Unlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800157 onuTP.procResult[uniTP{uniID: aUniID, tpID: aTpID}] = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000158}
159
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000160// GetTpProcessingErrorIndication - TODO: add comment
161func (onuTP *OnuUniTechProf) GetTpProcessingErrorIndication(aUniID uint8, aTpID uint8) error {
mpagenko73143992021-04-09 15:17:10 +0000162 onuTP.mutexTPState.RLock()
163 defer onuTP.mutexTPState.RUnlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800164 return onuTP.procResult[uniTP{uniID: aUniID, tpID: aTpID}]
mpagenko3dbcdd22020-07-22 07:38:45 +0000165}
166
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000167// ConfigureUniTp checks existing tp resources to configure and starts the corresponding OMCI configuation of the UNI port
mpagenko3dbcdd22020-07-22 07:38:45 +0000168// all possibly blocking processing must be run in background to allow for deadline supervision!
169// but take care on sequential background processing when needed (logical dependencies)
Himani Chawla4d908332020-08-31 12:30:20 +0530170// use waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) for internal synchronization
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000171func (onuTP *OnuUniTechProf) ConfigureUniTp(ctx context.Context,
Girish Gowdra50e56422021-06-01 16:46:04 -0700172 aUniID uint8, aPathString string, tpInst tech_profile.TechProfileInstance, wg *sync.WaitGroup) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000173 defer wg.Done() //always decrement the waitGroup on return
dbainbri4d3a0dc2020-12-02 00:33:42 +0000174 logger.Debugw(ctx, "configure the Uni according to TpPath", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000175 "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000176 tpID, err := cmn.GetTpIDFromTpPath(aPathString)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800177 uniTpKey := uniTP{uniID: aUniID, tpID: tpID}
178 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000179 logger.Errorw(ctx, "error-extracting-tp-id-from-tp-path", log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800180 return
181 }
mpagenkoaf801632020-07-03 10:00:42 +0000182
mpagenko3dbcdd22020-07-22 07:38:45 +0000183 //ensure that the given uniID is available (configured) in the UniPort class (used for OMCI entities)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000184 var pCurrentUniPort *cmn.OnuUniPort
185 for _, uniPort := range *onuTP.baseDeviceHandler.GetUniEntityMap() {
mpagenko3dbcdd22020-07-22 07:38:45 +0000186 // only if this port is validated for operState transfer
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000187 if uniPort.UniID == aUniID {
mpagenko3dbcdd22020-07-22 07:38:45 +0000188 pCurrentUniPort = uniPort
189 break //found - end search loop
190 }
191 }
192 if pCurrentUniPort == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000193 logger.Errorw(ctx, "TechProfile configuration aborted: requested uniID not found in PortDB",
mpagenko73143992021-04-09 15:17:10 +0000194 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": uniTpKey.tpID})
195 onuTP.mutexTPState.Lock()
196 defer onuTP.mutexTPState.Unlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800197 onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: requested uniID not found %d on %s",
Andrea Campanella6515c582020-10-05 11:25:00 +0200198 aUniID, onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000199 return
200 }
mpagenkoaf801632020-07-03 10:00:42 +0000201
mpagenko73143992021-04-09 15:17:10 +0000202 if onuTP.getProfileResetting(uniTpKey) {
203 logger.Debugw(ctx, "aborting TP configuration, reset requested in parallel", log.Fields{
204 "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": uniTpKey.tpID})
205 onuTP.mutexTPState.Lock()
206 defer onuTP.mutexTPState.Unlock()
207 onuTP.procResult[uniTpKey] = fmt.Errorf(
208 "techProfile config aborted - reset requested in parallel - for uniID %d on %s",
209 aUniID, onuTP.deviceID)
210 return
211 }
mpagenkodff5dda2020-08-28 11:52:01 +0000212 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
mpagenkoaf801632020-07-03 10:00:42 +0000213
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000214 //according to UpdateOnuUniTpPath() logic the assumption here is, that this configuration is only called
mpagenko3dbcdd22020-07-22 07:38:45 +0000215 // in case the KVPath has changed for the given UNI,
216 // as T-Cont and Gem-Id's are dependent on TechProfile-Id this means, that possibly previously existing
217 // (ANI) configuration of this port has to be removed first
218 // (moreover in this case a possibly existing flow configuration is also not valid anymore and needs clean-up as well)
219 // existence of configuration can be detected based on tp stored TCONT's
Andrea Campanella6515c582020-10-05 11:25:00 +0200220 //TODO:
mpagenko3dbcdd22020-07-22 07:38:45 +0000221 /* if tcontMap not empty {
222 go onuTP.deleteAniSideConfig(ctx, aUniID, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000223 if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000224 //timeout or error detected
225 return
226 }
227 clear tcontMap
228 }
229
230 processingStep++
231 */
Girish Gowdra50e56422021-06-01 16:46:04 -0700232 go onuTP.readAniSideConfigFromTechProfile(ctx, aUniID, tpID, aPathString, tpInst, processingStep)
mpagenkodff5dda2020-08-28 11:52:01 +0000233 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000234 //timeout or error detected
mpagenko73143992021-04-09 15:17:10 +0000235 onuTP.mutexTPState.RLock()
Girish Gowdra24dd1132021-07-06 15:25:40 -0700236 ok := onuTP.tpProfileExists[uniTpKey]
237 onuTP.mutexTPState.RUnlock()
238 if ok {
mpagenko01e726e2020-10-23 09:45:29 +0000239 //ignore the internal error in case the new profile is already configured
240 // and abort the processing here
241 return
242 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000243 logger.Errorw(ctx, "tech-profile related configuration aborted on read",
mpagenko01e726e2020-10-23 09:45:29 +0000244 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
mpagenko73143992021-04-09 15:17:10 +0000245 onuTP.mutexTPState.Lock()
246 defer onuTP.mutexTPState.Unlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800247 onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: tech-profile read issue for %d on %s",
Andrea Campanella6515c582020-10-05 11:25:00 +0200248 aUniID, onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000249 return
250 }
mpagenko73143992021-04-09 15:17:10 +0000251 if onuTP.getProfileResetting(uniTpKey) {
252 logger.Debugw(ctx, "aborting TP configuration, reset requested in parallel", log.Fields{
253 "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": uniTpKey.tpID})
254 onuTP.mutexTPState.Lock()
255 defer onuTP.mutexTPState.Unlock()
256 onuTP.procResult[uniTpKey] = fmt.Errorf(
257 "techProfile config aborted - reset requested in parallel - for uniID %d on %s",
258 aUniID, onuTP.deviceID)
259 return
260 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000261 processingStep++
Girish Gowdra041dcb32020-11-16 16:54:30 -0800262
mpagenko73143992021-04-09 15:17:10 +0000263 //ensure read protection for access to mapPonAniConfig
264 onuTP.mutexTPState.RLock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800265 valuePA, existPA := onuTP.mapPonAniConfig[uniTpKey]
mpagenko73143992021-04-09 15:17:10 +0000266 onuTP.mutexTPState.RUnlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800267 if existPA {
268 if valuePA != nil {
mpagenko3dbcdd22020-07-22 07:38:45 +0000269 //Config data for this uni and and at least TCont Index 0 exist
mpagenko8b07c1b2020-11-26 10:36:31 +0000270 if err := onuTP.setAniSideConfigFromTechProfile(ctx, aUniID, tpID, pCurrentUniPort, processingStep); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000271 logger.Errorw(ctx, "tech-profile related FSM could not be started",
mpagenko8b07c1b2020-11-26 10:36:31 +0000272 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
mpagenko73143992021-04-09 15:17:10 +0000273 onuTP.mutexTPState.Lock()
274 defer onuTP.mutexTPState.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000275 onuTP.procResult[uniTpKey] = err
276 return
277 }
mpagenkodff5dda2020-08-28 11:52:01 +0000278 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko73143992021-04-09 15:17:10 +0000279 //timeout or error detected (included wanted cancellation after e.g. disable device (FsmReset))
280 logger.Warnw(ctx, "tech-profile related configuration aborted on set",
mpagenko01e726e2020-10-23 09:45:29 +0000281 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800282
mpagenko73143992021-04-09 15:17:10 +0000283 onuTP.mutexTPState.Lock()
284 defer onuTP.mutexTPState.Unlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800285 onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: Omci AniSideConfig failed %d on %s",
Andrea Campanella6515c582020-10-05 11:25:00 +0200286 aUniID, onuTP.deviceID)
Himani Chawla4d908332020-08-31 12:30:20 +0530287 //this issue here means that the AniConfigFsm has not finished successfully
mpagenko3dbcdd22020-07-22 07:38:45 +0000288 //which requires to reset it to allow for new usage, e.g. also on a different UNI
289 //(without that it would be reset on device down indication latest)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000290 if _, ok := onuTP.PAniConfigFsm[uniTpKey]; ok {
291 _ = onuTP.PAniConfigFsm[uniTpKey].PAdaptFsm.PFsm.Event(aniEvReset)
mpagenko73143992021-04-09 15:17:10 +0000292 }
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)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000297 logger.Errorw(ctx, "no Tcont/Gem data for this UNI found - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000298 "device-id": onuTP.deviceID, "uni-id": aUniID})
mpagenko73143992021-04-09 15:17:10 +0000299 onuTP.mutexTPState.Lock()
300 defer onuTP.mutexTPState.Unlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800301 onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: no Tcont/Gem data found for this UNI %d on %s",
Andrea Campanella6515c582020-10-05 11:25:00 +0200302 aUniID, onuTP.deviceID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000303 return
mpagenkoaf801632020-07-03 10:00:42 +0000304 }
305 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000306 logger.Errorw(ctx, "no PonAni data for this UNI found - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000307 "device-id": onuTP.deviceID, "uni-id": aUniID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800308
mpagenko73143992021-04-09 15:17:10 +0000309 onuTP.mutexTPState.Lock()
310 defer onuTP.mutexTPState.Unlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800311 onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: no AniSide data found for this UNI %d on %s",
Andrea Campanella6515c582020-10-05 11:25:00 +0200312 aUniID, onuTP.deviceID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000313 return
mpagenkoaf801632020-07-03 10:00:42 +0000314 }
315}
316
mpagenko3dbcdd22020-07-22 07:38:45 +0000317/* internal methods *********************/
ozgecanetsia4b232302020-11-11 10:58:10 +0300318// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000319func (onuTP *OnuUniTechProf) readAniSideConfigFromTechProfile(
Girish Gowdra50e56422021-06-01 16:46:04 -0700320 ctx context.Context, aUniID uint8, aTpID uint8, aPathString string, tpInst tech_profile.TechProfileInstance, aProcessingStep uint8) {
321 var err error
mpagenko3dbcdd22020-07-22 07:38:45 +0000322 //store profile type and identifier for later usage within the OMCI identifier and possibly ME setup
323 //pathstring is defined to be in the form of <ProfType>/<profID>/<Interface/../Identifier>
324 subStringSlice := strings.Split(aPathString, "/")
325 if len(subStringSlice) <= 2 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000326 logger.Errorw(ctx, "invalid path name format",
mpagenko3dbcdd22020-07-22 07:38:45 +0000327 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000328 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko3dbcdd22020-07-22 07:38:45 +0000329 return
330 }
331
mpagenko73143992021-04-09 15:17:10 +0000332 //ensure write protection for access to used maps
333 onuTP.mutexTPState.Lock()
334 defer onuTP.mutexTPState.Unlock()
335
336 uniTPKey := uniTP{uniID: aUniID, tpID: aTpID}
337 onuTP.tpProfileExists[uniTP{uniID: aUniID, tpID: aTpID}] = false
338
mpagenko3dbcdd22020-07-22 07:38:45 +0000339 //at this point it is assumed that a new TechProfile is assigned to the UNI
mpagenko01e726e2020-10-23 09:45:29 +0000340 //expectation is that no TPIndication entry exists here, if exists and with the same TPId
341 // then we throw a warning, set an internal error and abort with error,
342 // which is later re-defined to success response to OLT adapter
343 // if TPId has changed, current data is removed (note that the ONU config state may be
344 // ambivalent in such a case)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800345 if _, existTP := onuTP.mapUniTpIndication[uniTPKey]; existTP {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000346 logger.Warnw(ctx, "Some active profile entry at reading new TechProfile",
mpagenko3dbcdd22020-07-22 07:38:45 +0000347 log.Fields{"path": aPathString, "device-id": onuTP.deviceID,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800348 "uni-id": aUniID, "wrongProfile": onuTP.mapUniTpIndication[uniTPKey].techProfileID})
349 if aTpID == onuTP.mapUniTpIndication[uniTPKey].techProfileID {
mpagenko01e726e2020-10-23 09:45:29 +0000350 // ProfId not changed - assume profile to be still the same
351 // anyway this should not appear after full support of profile (Gem/TCont) removal
dbainbri4d3a0dc2020-12-02 00:33:42 +0000352 logger.Warnw(ctx, "New TechProfile already exists - aborting configuration",
mpagenko01e726e2020-10-23 09:45:29 +0000353 log.Fields{"device-id": onuTP.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800354 onuTP.tpProfileExists[uniTPKey] = true
mpagenko01e726e2020-10-23 09:45:29 +0000355 onuTP.chTpConfigProcessingStep <- 0 //error indication
356 return
357 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000358 //delete on the mapUniTpIndication map not needed, just overwritten later
359 //delete on the PonAniConfig map should be safe, even if not existing
Girish Gowdra041dcb32020-11-16 16:54:30 -0800360 delete(onuTP.mapPonAniConfig, uniTPKey)
mpagenko3dbcdd22020-07-22 07:38:45 +0000361 } else {
362 // this is normal processing
Girish Gowdra041dcb32020-11-16 16:54:30 -0800363 onuTP.mapUniTpIndication[uniTPKey] = &tTechProfileIndication{} //need to assign some (empty) struct memory first!
mpagenko3dbcdd22020-07-22 07:38:45 +0000364 }
365
Girish Gowdra041dcb32020-11-16 16:54:30 -0800366 onuTP.mapUniTpIndication[uniTPKey].techProfileType = subStringSlice[0]
mpagenko3dbcdd22020-07-22 07:38:45 +0000367 //note the limitation on ID range (probably even more limited) - based on usage within OMCI EntityID
Girish Gowdra041dcb32020-11-16 16:54:30 -0800368 onuTP.mapUniTpIndication[uniTPKey].techProfileID = aTpID
369 onuTP.mapUniTpIndication[uniTPKey].techProfileConfigDone = false
370 onuTP.mapUniTpIndication[uniTPKey].techProfileToDelete = false
dbainbri4d3a0dc2020-12-02 00:33:42 +0000371 logger.Debugw(ctx, "tech-profile path indications",
mpagenko01e726e2020-10-23 09:45:29 +0000372 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800373 "profType": onuTP.mapUniTpIndication[uniTPKey].techProfileType,
374 "profID": onuTP.mapUniTpIndication[uniTPKey].techProfileID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000375
mpagenko01e726e2020-10-23 09:45:29 +0000376 //default start with 1Tcont profile, later perhaps extend to MultiTcontMultiGem
mpagenko3dbcdd22020-07-22 07:38:45 +0000377 localMapGemPortParams := make(map[uint16]*gemPortParamStruct)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800378 onuTP.mapPonAniConfig[uniTPKey] = &tcontGemList{tcontParamStruct{}, localMapGemPortParams}
mpagenko3dbcdd22020-07-22 07:38:45 +0000379
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000380 //note: the code is currently restricted to one TCcont per Onu (index [0])
mpagenko3dbcdd22020-07-22 07:38:45 +0000381 //get the relevant values from the profile and store to mapPonAniConfig
Girish Gowdra50e56422021-06-01 16:46:04 -0700382 onuTP.mapPonAniConfig[uniTPKey].tcontParams.allocID = uint16(tpInst.UsScheduler.AllocId)
Himani Chawla4d908332020-08-31 12:30:20 +0530383 //maybe tCont scheduling not (yet) needed - just to basically have it for future
mpagenko3dbcdd22020-07-22 07:38:45 +0000384 // (would only be relevant in case of ONU-2G QOS configuration flexibility)
Girish Gowdra50e56422021-06-01 16:46:04 -0700385 if tpInst.UsScheduler.QSchedPolicy == tech_profile.SchedulingPolicy_StrictPriority {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800386 onuTP.mapPonAniConfig[uniTPKey].tcontParams.schedPolicy = 1 //for the moment fixed value acc. G.988 //TODO: defines!
mpagenko3dbcdd22020-07-22 07:38:45 +0000387 } else {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000388 //default profile defines "Hybrid" - which probably comes down to WRR with some weigthts for SP
Girish Gowdra041dcb32020-11-16 16:54:30 -0800389 onuTP.mapPonAniConfig[uniTPKey].tcontParams.schedPolicy = 2 //for G.988 WRR
mpagenko3dbcdd22020-07-22 07:38:45 +0000390 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000391 loNumGemPorts := tpInst.NumGemPorts
392 loGemPortRead := false
mpagenko3dbcdd22020-07-22 07:38:45 +0000393 for pos, content := range tpInst.UpstreamGemPortAttributeList {
mpagenko1cc3cb42020-07-27 15:24:38 +0000394 if uint32(pos) == loNumGemPorts {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000395 logger.Debugw(ctx, "PonAniConfig abort GemPortList - GemList exceeds set NumberOfGemPorts",
mpagenko1cc3cb42020-07-27 15:24:38 +0000396 log.Fields{"device-id": onuTP.deviceID, "index": pos, "NumGem": loNumGemPorts})
mpagenko3dbcdd22020-07-22 07:38:45 +0000397 break
398 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000399 if pos == 0 {
400 //at least one upstream GemPort should always exist (else traffic profile makes no sense)
401 loGemPortRead = true
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000402 }
Himani Chawla1c136902020-12-10 16:30:59 +0530403 //for all GemPorts we need to extend the mapGemPortParams
Girish Gowdra50e56422021-06-01 16:46:04 -0700404 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)] = &gemPortParamStruct{}
Himani Chawla1c136902020-12-10 16:30:59 +0530405
Girish Gowdra50e56422021-06-01 16:46:04 -0700406 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].gemPortID =
407 uint16(content.GemportId)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000408 //direction can be correlated later with Downstream list,
409 // for now just assume bidirectional (upstream never exists alone)
Girish Gowdra50e56422021-06-01 16:46:04 -0700410 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].direction = 3 //as defined in G.988
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000411 // expected Prio-Queue values 0..7 with 7 for highest PrioQueue, QueueIndex=Prio = 0..7
Girish Gowdra50e56422021-06-01 16:46:04 -0700412 if content.PriorityQ > 7 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000413 logger.Errorw(ctx, "PonAniConfig reject on GemPortList - PrioQueue value invalid",
Girish Gowdra50e56422021-06-01 16:46:04 -0700414 log.Fields{"device-id": onuTP.deviceID, "index": pos, "PrioQueue": content.PriorityQ})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000415 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
Girish Gowdra041dcb32020-11-16 16:54:30 -0800416 delete(onuTP.mapPonAniConfig, uniTPKey)
mpagenkodff5dda2020-08-28 11:52:01 +0000417 onuTP.chTpConfigProcessingStep <- 0 //error indication
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000418 return
419 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700420 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].prioQueueIndex =
421 uint8(content.PriorityQ)
422 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].pbitString =
Himani Chawla6d2ae152020-09-02 13:11:20 +0530423 strings.TrimPrefix(content.PbitMap, binaryStringPrefix)
mpagenko3dbcdd22020-07-22 07:38:45 +0000424 if content.AesEncryption == "True" {
Girish Gowdra50e56422021-06-01 16:46:04 -0700425 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].gemPortEncState = 1
mpagenko3dbcdd22020-07-22 07:38:45 +0000426 } else {
Girish Gowdra50e56422021-06-01 16:46:04 -0700427 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].gemPortEncState = 0
mpagenko3dbcdd22020-07-22 07:38:45 +0000428 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700429 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].discardPolicy =
430 content.DiscardPolicy.String()
431 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].queueSchedPolicy =
432 content.SchedulingPolicy.String()
mpagenko3dbcdd22020-07-22 07:38:45 +0000433 //'GemWeight' looks strange in default profile, for now we just copy the weight to first queue
Girish Gowdra50e56422021-06-01 16:46:04 -0700434 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].queueWeight =
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000435 uint8(content.Weight)
mpagenko3dbcdd22020-07-22 07:38:45 +0000436 }
ozgecanetsia4b232302020-11-11 10:58:10 +0300437
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300438 for _, downstreamContent := range tpInst.DownstreamGemPortAttributeList {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000439 logger.Debugw(ctx, "Operating on Downstream Gem Port", log.Fields{"downstream-gem": downstreamContent})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300440 //Commenting this out due to faliure, needs investigation
441 //if uint32(pos) == loNumGemPorts {
442 // logger.Debugw("PonAniConfig abort GemPortList - GemList exceeds set NumberOfGemPorts",
443 // log.Fields{"device-id": onuTP.deviceID, "index": pos, "NumGem": loNumGemPorts})
444 // break
445 //}
446 isMulticast := false
ozgecanetsia4b232302020-11-11 10:58:10 +0300447 //Flag is defined as string in the TP in voltha-lib-go, parsing it from string
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300448 if downstreamContent.IsMulticast != "" {
449 isMulticast, err = strconv.ParseBool(downstreamContent.IsMulticast)
450 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000451 logger.Errorw(ctx, "multicast-error-config-unknown-flag-in-technology-profile",
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300452 log.Fields{"UniTpKey": uniTPKey, "downstream-gem": downstreamContent, "error": err})
453 continue
454 }
ozgecanetsia4b232302020-11-11 10:58:10 +0300455 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000456 logger.Infow(ctx, "Gem Port is multicast", log.Fields{"isMulticast": isMulticast})
ozgecanetsia4b232302020-11-11 10:58:10 +0300457 if isMulticast {
Girish Gowdra50e56422021-06-01 16:46:04 -0700458 mcastGemID := uint16(downstreamContent.MulticastGemId)
ozgecanetsia4b232302020-11-11 10:58:10 +0300459 _, existing := onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID]
460 if existing {
461 //GEM port was previously configured, avoid setting multicast attributes
dbainbri4d3a0dc2020-12-02 00:33:42 +0000462 logger.Errorw(ctx, "multicast-error-config-existing-gem-port-config", log.Fields{"UniTpKey": uniTPKey,
ozgecanetsia4b232302020-11-11 10:58:10 +0300463 "downstream-gem": downstreamContent, "key": mcastGemID})
464 continue
465 } else {
466 //GEM port is not configured, setting multicast attributes
dbainbri4d3a0dc2020-12-02 00:33:42 +0000467 logger.Infow(ctx, "creating-multicast-gem-port", log.Fields{"uniTpKey": uniTPKey,
ozgecanetsia4b232302020-11-11 10:58:10 +0300468 "gemPortId": mcastGemID, "key": mcastGemID})
469
470 //for all further GemPorts we need to extend the mapGemPortParams
471 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID] = &gemPortParamStruct{}
472
473 //Separate McastGemId is derived from OMCI-lib-go, if not needed first needs to be removed there.
474 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].gemPortID = mcastGemID
475 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].direction = 2 // for ANI to UNI as defined in G.988
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300476
477 if downstreamContent.AesEncryption == "True" {
478 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].gemPortEncState = 1
479 } else {
480 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].gemPortEncState = 0
481 }
482
483 // expected Prio-Queue values 0..7 with 7 for highest PrioQueue, QueueIndex=Prio = 0..7
Girish Gowdra50e56422021-06-01 16:46:04 -0700484 if downstreamContent.PriorityQ > 7 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000485 logger.Errorw(ctx, "PonAniConfig reject on GemPortList - PrioQueue value invalid",
Girish Gowdra50e56422021-06-01 16:46:04 -0700486 log.Fields{"device-id": onuTP.deviceID, "index": mcastGemID, "PrioQueue": downstreamContent.PriorityQ})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300487 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
488 delete(onuTP.mapPonAniConfig, uniTPKey)
489 onuTP.chTpConfigProcessingStep <- 0 //error indication
490 return
ozgecanetsia4b232302020-11-11 10:58:10 +0300491 }
492 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].prioQueueIndex =
Girish Gowdra50e56422021-06-01 16:46:04 -0700493 uint8(downstreamContent.PriorityQ)
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300494 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].pbitString =
495 strings.TrimPrefix(downstreamContent.PbitMap, binaryStringPrefix)
496
497 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].discardPolicy =
Girish Gowdra50e56422021-06-01 16:46:04 -0700498 downstreamContent.DiscardPolicy.String()
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300499 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].queueSchedPolicy =
Girish Gowdra50e56422021-06-01 16:46:04 -0700500 downstreamContent.SchedulingPolicy.String()
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300501 //'GemWeight' looks strange in default profile, for now we just copy the weight to first queue
502 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].queueWeight =
503 uint8(downstreamContent.Weight)
504
ozgecanetsia4b232302020-11-11 10:58:10 +0300505 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].isMulticast = isMulticast
506 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].multicastGemPortID =
Girish Gowdra50e56422021-06-01 16:46:04 -0700507 uint16(downstreamContent.MulticastGemId)
508 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].staticACL = downstreamContent.StaticAccessControlList
509 onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].dynamicACL = downstreamContent.DynamicAccessControlList
ozgecanetsia4b232302020-11-11 10:58:10 +0300510 }
511 }
512 }
513
Himani Chawla4d908332020-08-31 12:30:20 +0530514 if !loGemPortRead {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000515 logger.Errorw(ctx, "PonAniConfig reject - no GemPort could be read from TechProfile",
mpagenko1cc3cb42020-07-27 15:24:38 +0000516 log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000517 //remove PonAniConfig as done so far, delete map should be safe, even if not existing
Girish Gowdra041dcb32020-11-16 16:54:30 -0800518 delete(onuTP.mapPonAniConfig, uniTPKey)
mpagenkodff5dda2020-08-28 11:52:01 +0000519 onuTP.chTpConfigProcessingStep <- 0 //error indication
mpagenko1cc3cb42020-07-27 15:24:38 +0000520 return
521 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000522 //logger does not simply output the given structures, just give some example debug values
dbainbri4d3a0dc2020-12-02 00:33:42 +0000523 logger.Debugw(ctx, "PonAniConfig read from TechProfile", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000524 "device-id": onuTP.deviceID, "uni-id": aUniID,
525 "AllocId": onuTP.mapPonAniConfig[uniTPKey].tcontParams.allocID})
Himani Chawla1c136902020-12-10 16:30:59 +0530526 for gemPortID, gemEntry := range onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000527 logger.Debugw(ctx, "PonAniConfig read from TechProfile", log.Fields{
Himani Chawla1c136902020-12-10 16:30:59 +0530528 "GemPort": gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000529 "QueueScheduling": gemEntry.queueSchedPolicy})
530 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000531
mpagenkodff5dda2020-08-28 11:52:01 +0000532 onuTP.chTpConfigProcessingStep <- aProcessingStep //done
mpagenko3dbcdd22020-07-22 07:38:45 +0000533}
534
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000535func (onuTP *OnuUniTechProf) setAniSideConfigFromTechProfile(
536 ctx context.Context, aUniID uint8, aTpID uint8, apCurrentUniPort *cmn.OnuUniPort, aProcessingStep uint8) error {
mpagenko3dbcdd22020-07-22 07:38:45 +0000537
538 //OMCI transfer of ANI data acc. to mapPonAniConfig
539 // also the FSM's are running in background,
mpagenko8b07c1b2020-11-26 10:36:31 +0000540 // hence we have to make sure they indicate 'success' on chTpConfigProcessingStep with aProcessingStep
Girish Gowdra041dcb32020-11-16 16:54:30 -0800541 uniTPKey := uniTP{uniID: aUniID, tpID: aTpID}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000542 if onuTP.PAniConfigFsm == nil {
543 return onuTP.createAniConfigFsm(ctx, aUniID, aTpID, apCurrentUniPort, cmn.OmciAniConfigDone, aProcessingStep)
544 } else if _, ok := onuTP.PAniConfigFsm[uniTPKey]; !ok {
545 return onuTP.createAniConfigFsm(ctx, aUniID, aTpID, apCurrentUniPort, cmn.OmciAniConfigDone, aProcessingStep)
mpagenko3dbcdd22020-07-22 07:38:45 +0000546 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000547 //AniConfigFsm already init
dbainbri4d3a0dc2020-12-02 00:33:42 +0000548 return onuTP.runAniConfigFsm(ctx, aniEvStart, aProcessingStep, aUniID, aTpID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000549}
550
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000551// DeleteTpResource removes Resources from the ONU's specified Uni
mpagenko73143992021-04-09 15:17:10 +0000552// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000553func (onuTP *OnuUniTechProf) DeleteTpResource(ctx context.Context,
554 aUniID uint8, aTpID uint8, aPathString string, aResource ResourceEntry, aEntryID uint32,
mpagenko8b07c1b2020-11-26 10:36:31 +0000555 wg *sync.WaitGroup) {
556 defer wg.Done()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000557 logger.Debugw(ctx, "will remove TP resources from ONU's UNI", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000558 "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString, "Resource": aResource})
559 uniTPKey := uniTP{uniID: aUniID, tpID: aTpID}
560
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000561 if CResourceGemPort == aResource {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000562 logger.Debugw(ctx, "remove GemPort from the list of existing ones of the TP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000563 "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString, "GemPort": aEntryID})
564
mpagenko73143992021-04-09 15:17:10 +0000565 //ensure read protection for access to mapPonAniConfig
566 onuTP.mutexTPState.RLock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000567 // check if the requested GemPort exists in the DB, indicate it to the FSM
568 // store locally to remove it from DB later on success
569 pLocAniConfigOnUni := onuTP.mapPonAniConfig[uniTPKey]
570 if pLocAniConfigOnUni == nil {
mpagenko73143992021-04-09 15:17:10 +0000571 onuTP.mutexTPState.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000572 // No relevant entry exists anymore - acknowledge success
dbainbri4d3a0dc2020-12-02 00:33:42 +0000573 logger.Debugw(ctx, "AniConfig or GemEntry do not exists in DB", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000574 "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
575 return
576 }
mpagenko73143992021-04-09 15:17:10 +0000577 onuTP.mutexTPState.RUnlock()
578
Himani Chawla1c136902020-12-10 16:30:59 +0530579 for gemPortID, gemEntry := range pLocAniConfigOnUni.mapGemPortParams {
580 if gemPortID == uint16(aEntryID) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000581 //GemEntry to be deleted found
Himani Chawla1c136902020-12-10 16:30:59 +0530582 gemEntry.removeGemID = gemPortID //store the index for later removal
583 onuTP.mapRemoveGemEntry[uniTPKey] = pLocAniConfigOnUni.mapGemPortParams[gemPortID]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000584 logger.Debugw(ctx, "Remove-GemEntry stored", log.Fields{
Himani Chawla1c136902020-12-10 16:30:59 +0530585 "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID, "GemPort": aEntryID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000586 break //abort loop, always only one GemPort to remove
587 }
588 }
589 if onuTP.mapRemoveGemEntry[uniTPKey] == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000590 logger.Errorw(ctx, "GemPort removal aborted - GemPort not found",
mpagenko8b07c1b2020-11-26 10:36:31 +0000591 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID, "GemPort": aEntryID})
592 /* Do not set some error indication to the outside system interface on delete
593 assume there is nothing to be deleted internally and hope a new config request will recover the situation
594 onuTP.procResult[uniTpKey] = fmt.Errorf("GemPort removal aborted: GemPort not found %d for %d on %s",
595 aEntryID, aUniID, onuTP.deviceID)
596 */
597 return
598 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000599 if onuTP.baseDeviceHandler.IsReadyForOmciConfig() {
mpagenko8b07c1b2020-11-26 10:36:31 +0000600 // check that the TpConfigRequest was done before
601 // -> that is implicitly done using the AniConfigFsm,
602 // which must be in the according state to remove something
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000603 if onuTP.PAniConfigFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000604 logger.Errorw(ctx, "abort GemPort removal - no AniConfigFsm available",
mpagenko8b07c1b2020-11-26 10:36:31 +0000605 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
606 /* Do not set some error indication to the outside system interface on delete (see above)
607 onuTP.procResult[uniTpKey] = fmt.Errorf("GemPort removal aborted: no AniConfigFsm available %d on %s",
608 aUniID, onuTP.deviceID)
609 */
610 //if the FSM is not valid, also TP related remove data should not be valid:
611 // remove GemPort from config DB
mpagenko73143992021-04-09 15:17:10 +0000612 //ensure write protection for access to mapPonAniConfig
613 onuTP.mutexTPState.Lock()
Himani Chawla1c136902020-12-10 16:30:59 +0530614 delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeGemID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000615 // remove the removeEntry
616 delete(onuTP.mapRemoveGemEntry, uniTPKey)
mpagenko73143992021-04-09 15:17:10 +0000617 onuTP.mutexTPState.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000618 return
619 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000620 if _, ok := onuTP.PAniConfigFsm[uniTPKey]; !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000621 logger.Errorw(ctx, "abort GemPort removal - no AniConfigFsm available for this uni/tp",
mpagenko8b07c1b2020-11-26 10:36:31 +0000622 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
623 /* Do not set some error indication to the outside system interface on delete (see above)
624 onuTP.procResult[uniTpKey] = fmt.Errorf("GemPort removal aborted: no AniConfigFsm available %d on %s for tpid",
625 aUniID, onuTP.deviceID, aTpID)
626 */
627 //if the FSM is not valid, also TP related remove data should not be valid:
628 // remove GemPort from config DB
mpagenko73143992021-04-09 15:17:10 +0000629 //ensure write protection for access to mapPonAniConfig
630 onuTP.mutexTPState.Lock()
Himani Chawla1c136902020-12-10 16:30:59 +0530631 delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeGemID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000632 // remove the removeEntry
633 delete(onuTP.mapRemoveGemEntry, uniTPKey)
mpagenko73143992021-04-09 15:17:10 +0000634 onuTP.mutexTPState.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000635 return
636 }
mpagenko73143992021-04-09 15:17:10 +0000637 if onuTP.getProfileResetting(uniTPKey) {
638 logger.Debugw(ctx, "aborting GemRemoval on FSM, reset requested in parallel", log.Fields{
639 "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
640 //ensure write protection for access to mapPonAniConfig
641 onuTP.mutexTPState.Lock()
642 delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeGemID)
643 // remove the removeEntry
644 delete(onuTP.mapRemoveGemEntry, uniTPKey)
645 onuTP.mutexTPState.Unlock()
646 return
647 }
648 // initiate OMCI GemPort related removal
649 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
650 // hence we have to make sure they indicate 'success' on chTpConfigProcessingStep with aProcessingStep
dbainbri4d3a0dc2020-12-02 00:33:42 +0000651 if nil != onuTP.runAniConfigFsm(ctx, aniEvRemGemiw, processingStep, aUniID, aTpID) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000652 //even if the FSM invocation did not work we don't indicate a problem within procResult
653 //errors could exist also because there was nothing to delete - so we just accept that as 'deleted'
654 //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
655 return
656 }
657 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko73143992021-04-09 15:17:10 +0000658 //timeout or error detected (included wanted cancellation after e.g. disable device (FsmReset))
659 logger.Warnw(ctx, "GemPort removal aborted - Omci AniSideConfig failed",
mpagenko8b07c1b2020-11-26 10:36:31 +0000660 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
661 //even if the FSM delete execution did not work we don't indicate a problem within procResult
662 //we should never respond to delete with error ...
663 //this issue here means that the AniConfigFsm has not finished successfully
664 //which requires to reset it to allow for new usage, e.g. also on a different UNI
665 //(without that it would be reset on device down indication latest)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000666 if _, ok := onuTP.PAniConfigFsm[uniTPKey]; ok {
667 _ = onuTP.PAniConfigFsm[uniTPKey].PAdaptFsm.PFsm.Event(aniEvReset)
mpagenko73143992021-04-09 15:17:10 +0000668 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000669 //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
670 return
671 }
672 } else {
mpagenko7d6bb022021-03-11 15:07:55 +0000673 //if we can't do the OMCI processing we also suppress the ProcStatusUpdate
674 //this is needed as in the device-down case where all FSM's are getting reset and internal data gets cleared
675 //as a consequence a possible remove-flow does not see any dependency on the TechProfile anymore and is executed (pro forma) directly
676 //a later TechProfile removal would cause the device-reason to be updated to 'techProfile-delete-success' which is not the expected state
677 // and anyway is no real useful information at that stage
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000678 logger.Debugw(ctx, "UniPonAniConfigFsm delete Gem on OMCI skipped based on device state", log.Fields{
679 "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.GetDeviceReasonString()})
mpagenko8b07c1b2020-11-26 10:36:31 +0000680 }
681 // remove GemPort from config DB
mpagenko73143992021-04-09 15:17:10 +0000682 //ensure write protection for access to mapPonAniConfig
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000683 logger.Debugw(ctx, "UniPonAniConfigFsm removing gem from config data and clearing ani FSM", log.Fields{
Mahir Gunyel9545be22021-07-04 15:53:16 -0700684 "device-id": onuTP.deviceID, "gem-id": onuTP.mapRemoveGemEntry[uniTPKey].removeGemID, "uniTPKey": uniTPKey})
mpagenko73143992021-04-09 15:17:10 +0000685 onuTP.mutexTPState.Lock()
Himani Chawla1c136902020-12-10 16:30:59 +0530686 delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeGemID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000687 // remove the removeEntry
688 delete(onuTP.mapRemoveGemEntry, uniTPKey)
mpagenko73143992021-04-09 15:17:10 +0000689 onuTP.mutexTPState.Unlock()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000690 } else { //if CResourceTcont == aResource {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000691 logger.Debugw(ctx, "reset TCont with AllocId", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000692 "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString, "allocId": aEntryID})
693
mpagenko73143992021-04-09 15:17:10 +0000694 //ensure read protection for access to mapPonAniConfig
695 onuTP.mutexTPState.RLock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000696 // check if the TCont with the indicated AllocId exists in the DB, indicate its EntityId to the FSM
697 pLocAniConfigOnUni := onuTP.mapPonAniConfig[uniTPKey]
698 if pLocAniConfigOnUni == nil {
699 // No relevant entry exists anymore - acknowledge success
mpagenko73143992021-04-09 15:17:10 +0000700 onuTP.mutexTPState.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000701 logger.Debugw(ctx, "AniConfig or TCont entry do not exists in DB", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000702 "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
703 return
704 }
mpagenko73143992021-04-09 15:17:10 +0000705 onuTP.mutexTPState.RUnlock()
706
mpagenko8b07c1b2020-11-26 10:36:31 +0000707 if pLocAniConfigOnUni.tcontParams.allocID != uint16(aEntryID) {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000708 logger.Errorw(ctx, "TCont removal aborted - indicated AllocId not found",
mpagenko8b07c1b2020-11-26 10:36:31 +0000709 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID, "AllocId": aEntryID})
710 /* Do not set some error indication to the outside system interface on delete
711 assume there is nothing to be deleted internally and hope a new config request will recover the situation
712 onuTP.procResult[uniTpKey] = fmt.Errorf("TCont removal aborted: AllocId not found %d for %d on %s",
713 aEntryID, aUniID, onuTP.deviceID)
714 */
715 return
716 }
717 //T-Cont to be reset found
dbainbri4d3a0dc2020-12-02 00:33:42 +0000718 logger.Debugw(ctx, "Reset-T-Cont AllocId found - valid", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000719 "device-id": onuTP.deviceID, "uni-id": aUniID, "AllocId": aEntryID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000720 if onuTP.PAniConfigFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000721 logger.Errorw(ctx, "no TCont removal on OMCI - no AniConfigFsm available",
mpagenko8b07c1b2020-11-26 10:36:31 +0000722 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
723 /* Do not set some error indication to the outside system interface on delete (see above)
724 onuTP.procResult[uniTpKey] = fmt.Errorf("TCont cleanup aborted: no AniConfigFsm available %d on %s",
725 aUniID, onuTP.deviceID)
726 */
mpagenko8b07c1b2020-11-26 10:36:31 +0000727 return
728 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000729 if _, ok := onuTP.PAniConfigFsm[uniTPKey]; !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000730 logger.Errorw(ctx, "no TCont removal on OMCI - no AniConfigFsm available for this uni/tp",
mpagenko8b07c1b2020-11-26 10:36:31 +0000731 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
732 //even if the FSM invocation did not work we don't indicate a problem within procResult
733 //errors could exist also because there was nothing to delete - so we just accept that as 'deleted'
734 //if the FSM is not valid, also TP related data should not be valid - clear the internal store profile data
mpagenko8b07c1b2020-11-26 10:36:31 +0000735 return
736 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000737 if onuTP.baseDeviceHandler.IsReadyForOmciConfig() {
mpagenko8b07c1b2020-11-26 10:36:31 +0000738 // check that the TpConfigRequest was done before
739 // -> that is implicitly done using the AniConfigFsm,
740 // which must be in the according state to remove something
mpagenko73143992021-04-09 15:17:10 +0000741 if onuTP.getProfileResetting(uniTPKey) {
742 logger.Debugw(ctx, "aborting TCont removal on FSM, reset requested in parallel", log.Fields{
743 "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
744 return
745 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000746 // initiate OMCI TCont related cleanup
747 var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
748 // hence we have to make sure they indicate 'success' on chTpConfigProcessingStep with aProcessingStep
dbainbri4d3a0dc2020-12-02 00:33:42 +0000749 if nil != onuTP.runAniConfigFsm(ctx, aniEvRemTcontPath, processingStep, aUniID, aTpID) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000750 //even if the FSM invocation did not work we don't indicate a problem within procResult
751 //errors could exist also because there was nothing to delete - so we just accept that as 'deleted'
752 //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
753 return
754 }
755 if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
mpagenko73143992021-04-09 15:17:10 +0000756 //timeout or error detected (included wanted cancellation after e.g. disable device (FsmReset))
757 logger.Warnw(ctx, "TCont cleanup aborted - Omci AniSideConfig failed",
mpagenko8b07c1b2020-11-26 10:36:31 +0000758 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
759 //even if the FSM delete execution did not work we don't indicate a problem within procResult
760 //we should never respond to delete with error ...
761 //this issue here means that the AniConfigFsm has not finished successfully
762 //which requires to reset it to allow for new usage, e.g. also on a different UNI
763 //(without that it would be reset on device down indication latest)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000764 if _, ok := onuTP.PAniConfigFsm[uniTPKey]; ok {
765 _ = onuTP.PAniConfigFsm[uniTPKey].PAdaptFsm.PFsm.Event(aniEvReset)
mpagenko73143992021-04-09 15:17:10 +0000766 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000767 //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
768 return
769 }
770 } else {
mpagenko7d6bb022021-03-11 15:07:55 +0000771 //see gemPort comments
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000772 logger.Debugw(ctx, "UniPonAniConfigFsm TCont cleanup on OMCI skipped based on device state", log.Fields{
773 "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.GetDeviceReasonString()})
mpagenko8b07c1b2020-11-26 10:36:31 +0000774 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000775 }
Mahir Gunyel9545be22021-07-04 15:53:16 -0700776
777}
778
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000779// IsTechProfileConfigCleared - TODO: add comment
780func (onuTP *OnuUniTechProf) IsTechProfileConfigCleared(ctx context.Context, uniID uint8, tpID uint8) bool {
Mahir Gunyel9545be22021-07-04 15:53:16 -0700781 uniTPKey := uniTP{uniID: uniID, tpID: tpID}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000782 logger.Debugw(ctx, "IsTechProfileConfigCleared", log.Fields{"device-id": onuTP.deviceID})
Mahir Gunyel9545be22021-07-04 15:53:16 -0700783 if onuTP.mapPonAniConfig[uniTPKey] != nil {
784 mapGemPortParams := onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams
785 unicastGemCount := 0
786 for _, gemEntry := range mapGemPortParams {
787 if !gemEntry.isMulticast {
788 unicastGemCount++
789 }
790 }
791 if unicastGemCount == 0 || onuTP.mapPonAniConfig[uniTPKey].tcontParams.allocID == 0 {
792 logger.Debugw(ctx, "clearing-ani-side-config", log.Fields{
793 "device-id": onuTP.deviceID, "uniTpKey": uniTPKey})
794 onuTP.clearAniSideConfig(ctx, uniID, tpID)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000795 if _, ok := onuTP.PAniConfigFsm[uniTPKey]; ok {
796 _ = onuTP.PAniConfigFsm[uniTPKey].PAdaptFsm.PFsm.Event(aniEvReset)
Mahir Gunyel9545be22021-07-04 15:53:16 -0700797 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000798 go onuTP.baseDeviceHandler.DeviceProcStatusUpdate(ctx, cmn.OmciAniResourceRemoved)
Mahir Gunyel9545be22021-07-04 15:53:16 -0700799 return true
800 }
mpagenko7d6bb022021-03-11 15:07:55 +0000801 }
Mahir Gunyel9545be22021-07-04 15:53:16 -0700802 return false
mpagenko3dbcdd22020-07-22 07:38:45 +0000803}
804
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000805func (onuTP *OnuUniTechProf) waitForTimeoutOrCompletion(
mpagenkodff5dda2020-08-28 11:52:01 +0000806 ctx context.Context, aChTpProcessingStep <-chan uint8, aProcessingStep uint8) bool {
mpagenko3dbcdd22020-07-22 07:38:45 +0000807 select {
808 case <-ctx.Done():
dbainbri4d3a0dc2020-12-02 00:33:42 +0000809 logger.Warnw(ctx, "processing not completed in-time: force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000810 log.Fields{"device-id": onuTP.deviceID, "error": ctx.Err()})
mpagenko3dbcdd22020-07-22 07:38:45 +0000811 return false
mpagenkodff5dda2020-08-28 11:52:01 +0000812 case rxStep := <-aChTpProcessingStep:
mpagenko3dbcdd22020-07-22 07:38:45 +0000813 if rxStep == aProcessingStep {
814 return true
815 }
816 //all other values are not accepted - including 0 for error indication
dbainbri4d3a0dc2020-12-02 00:33:42 +0000817 logger.Warnw(ctx, "Invalid processing step received: abort and force release of TpProcMutex!",
divyadesai4d299552020-08-18 07:13:49 +0000818 log.Fields{"device-id": onuTP.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000819 "wantedStep": aProcessingStep, "haveStep": rxStep})
820 return false
821 }
822}
823
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000824// createAniConfigFsm initializes and runs the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000825func (onuTP *OnuUniTechProf) createAniConfigFsm(ctx context.Context, aUniID uint8, aTpID uint8,
826 apCurrentUniPort *cmn.OnuUniPort, devEvent cmn.OnuDeviceEvent, aProcessingStep uint8) error {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000827 logger.Debugw(ctx, "createAniConfigFsm", log.Fields{"device-id": onuTP.deviceID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000828 chAniConfigFsm := make(chan cmn.Message, 2048)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800829 uniTPKey := uniTP{uniID: aUniID, tpID: aTpID}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000830 if onuTP.onuDevice == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000831 logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": onuTP.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000832 return fmt.Errorf("no valid OnuDevice: %s", onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000833 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000834 pAniCfgFsm := NewUniPonAniConfigFsm(ctx, onuTP.onuDevice.GetDevOmciCC(), apCurrentUniPort, onuTP,
835 onuTP.onuDevice.GetOnuDB(), aTpID, devEvent,
836 "AniConfigFsm", onuTP.baseDeviceHandler, onuTP.onuDevice, chAniConfigFsm)
mpagenko8b07c1b2020-11-26 10:36:31 +0000837 if pAniCfgFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000838 logger.Errorw(ctx, "AniConfigFSM could not be created - abort!!", log.Fields{"device-id": onuTP.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000839 return fmt.Errorf("could not create AniConfigFSM: %s", onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000840 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000841 if onuTP.PAniConfigFsm == nil {
842 onuTP.PAniConfigFsm = make(map[uniTP]*UniPonAniConfigFsm)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800843 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000844 onuTP.PAniConfigFsm[uniTPKey] = pAniCfgFsm
dbainbri4d3a0dc2020-12-02 00:33:42 +0000845 return onuTP.runAniConfigFsm(ctx, aniEvStart, aProcessingStep, aUniID, aTpID)
mpagenkofc4f56e2020-11-04 17:17:49 +0000846}
847
mpagenko3dbcdd22020-07-22 07:38:45 +0000848// runAniConfigFsm starts the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000849func (onuTP *OnuUniTechProf) runAniConfigFsm(ctx context.Context, aEvent string, aProcessingStep uint8, aUniID uint8, aTpID uint8) error {
mpagenko3dbcdd22020-07-22 07:38:45 +0000850 /* Uni related ANI config procedure -
851 ***** should run via 'aniConfigDone' state and generate the argument requested event *****
852 */
Girish Gowdra041dcb32020-11-16 16:54:30 -0800853 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
854
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000855 pACStatemachine := onuTP.PAniConfigFsm[uniTpKey].PAdaptFsm.PFsm
mpagenko3dbcdd22020-07-22 07:38:45 +0000856 if pACStatemachine != nil {
mpagenko8b07c1b2020-11-26 10:36:31 +0000857 if aEvent == aniEvStart {
858 if !pACStatemachine.Is(aniStDisabled) {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000859 logger.Errorw(ctx, "wrong state of AniConfigFSM to start - want: Disabled", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000860 "have": pACStatemachine.Current(), "device-id": onuTP.deviceID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000861 // maybe try a FSM reset and then again ... - TODO: add comment!!!
mpagenko8b07c1b2020-11-26 10:36:31 +0000862 return fmt.Errorf("wrong state of AniConfigFSM to start: %s", onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000863 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000864 } else if !pACStatemachine.Is(aniStConfigDone) {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000865 logger.Errorw(ctx, "wrong state of AniConfigFSM to remove - want: ConfigDone", log.Fields{
divyadesai4d299552020-08-18 07:13:49 +0000866 "have": pACStatemachine.Current(), "device-id": onuTP.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000867 return fmt.Errorf("wrong state of AniConfigFSM to remove: %s", onuTP.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000868 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000869 //FSM init requirement to get informed about FSM completion! (otherwise timeout of the TechProf config)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000870 onuTP.PAniConfigFsm[uniTpKey].setFsmCompleteChannel(onuTP.chTpConfigProcessingStep, aProcessingStep)
mpagenko8b07c1b2020-11-26 10:36:31 +0000871 if err := pACStatemachine.Event(aEvent); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000872 logger.Errorw(ctx, "AniConfigFSM: can't trigger event", log.Fields{"err": err})
mpagenko8b07c1b2020-11-26 10:36:31 +0000873 return fmt.Errorf("can't trigger event in AniConfigFSM: %s", onuTP.deviceID)
874 }
875 /***** AniConfigFSM event notified */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000876 logger.Debugw(ctx, "AniConfigFSM event notified", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000877 "state": pACStatemachine.Current(), "device-id": onuTP.deviceID, "event": aEvent})
878 return nil
mpagenko3dbcdd22020-07-22 07:38:45 +0000879 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000880 logger.Errorw(ctx, "AniConfigFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": onuTP.deviceID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000881 // maybe try a FSM reset and then again ... - TODO: add comment!!!
mpagenko8b07c1b2020-11-26 10:36:31 +0000882 return fmt.Errorf("stateMachine AniConfigFSM invalid: %s", onuTP.deviceID)
mpagenkoaf801632020-07-03 10:00:42 +0000883}
mpagenkodff5dda2020-08-28 11:52:01 +0000884
Girish Gowdra041dcb32020-11-16 16:54:30 -0800885// clearAniSideConfig deletes internal TechProfile related data connected to the requested UniPort and TpID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000886func (onuTP *OnuUniTechProf) clearAniSideConfig(ctx context.Context, aUniID uint8, aTpID uint8) {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000887 logger.Debugw(ctx, "removing TpIndication and PonAniConfig data", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000888 "device-id": onuTP.deviceID, "uni-id": aUniID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800889 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
890
891 onuTP.mutexTPState.Lock()
892 defer onuTP.mutexTPState.Unlock()
mpagenko73143992021-04-09 15:17:10 +0000893 //deleting a map entry should be safe, even if not existing
Girish Gowdra041dcb32020-11-16 16:54:30 -0800894 delete(onuTP.mapUniTpIndication, uniTpKey)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800895 delete(onuTP.mapPonAniConfig, uniTpKey)
mpagenko73143992021-04-09 15:17:10 +0000896 delete(onuTP.procResult, uniTpKey)
897 delete(onuTP.tpProfileExists, uniTpKey)
898 delete(onuTP.tpProfileResetting, uniTpKey)
mpagenko01e726e2020-10-23 09:45:29 +0000899}
900
mpagenkodff5dda2020-08-28 11:52:01 +0000901// setConfigDone sets the requested techProfile config state (if possible)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000902func (onuTP *OnuUniTechProf) setConfigDone(aUniID uint8, aTpID uint8, aState bool) {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800903 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
904 onuTP.mutexTPState.Lock()
905 defer onuTP.mutexTPState.Unlock()
906 if _, existTP := onuTP.mapUniTpIndication[uniTpKey]; existTP {
907 onuTP.mapUniTpIndication[uniTpKey].techProfileConfigDone = aState
mpagenkodff5dda2020-08-28 11:52:01 +0000908 } //else: the state is just ignored (does not exist)
909}
910
911// getTechProfileDone checks if the Techprofile processing with the requested TechProfile ID was done
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000912func (onuTP *OnuUniTechProf) getTechProfileDone(ctx context.Context, aUniID uint8, aTpID uint8) bool {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800913 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
mpagenko73143992021-04-09 15:17:10 +0000914 onuTP.mutexTPState.RLock()
915 defer onuTP.mutexTPState.RUnlock()
Girish Gowdra041dcb32020-11-16 16:54:30 -0800916 if _, existTP := onuTP.mapUniTpIndication[uniTpKey]; existTP {
917 if onuTP.mapUniTpIndication[uniTpKey].techProfileID == aTpID {
918 if onuTP.mapUniTpIndication[uniTpKey].techProfileToDelete {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000919 logger.Debugw(ctx, "TechProfile not relevant for requested flow config - waiting on delete",
mpagenko2418ab02020-11-12 12:58:06 +0000920 log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
921 return false //still waiting for removal of this techProfile first
922 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800923 return onuTP.mapUniTpIndication[uniTpKey].techProfileConfigDone
mpagenkodff5dda2020-08-28 11:52:01 +0000924 }
925 }
926 //for all other constellations indicate false = Config not done
927 return false
928}
mpagenko2418ab02020-11-12 12:58:06 +0000929
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000930// SetProfileToDelete sets the requested techProfile toDelete state (if possible)
931func (onuTP *OnuUniTechProf) SetProfileToDelete(aUniID uint8, aTpID uint8, aState bool) {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800932 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
933 onuTP.mutexTPState.Lock()
934 defer onuTP.mutexTPState.Unlock()
935 if _, existTP := onuTP.mapUniTpIndication[uniTpKey]; existTP {
936 onuTP.mapUniTpIndication[uniTpKey].techProfileToDelete = aState
mpagenko2418ab02020-11-12 12:58:06 +0000937 } //else: the state is just ignored (does not exist)
938}
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300939
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000940func (onuTP *OnuUniTechProf) getMulticastGemPorts(ctx context.Context, aUniID uint8, aTpID uint8) []uint16 {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300941 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
mpagenko73143992021-04-09 15:17:10 +0000942 onuTP.mutexTPState.RLock()
943 defer onuTP.mutexTPState.RUnlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300944 gemPortIds := make([]uint16, 0)
945 if techProfile, existTP := onuTP.mapPonAniConfig[uniTpKey]; existTP {
946 for _, gemPortParam := range techProfile.mapGemPortParams {
947 if gemPortParam.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000948 logger.Debugw(ctx, "Detected multicast gemPort", log.Fields{"device-id": onuTP.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300949 "aUniID": aUniID, "aTPID": aTpID, "uniTPKey": uniTpKey,
950 "mcastGemId": gemPortParam.multicastGemPortID})
951 gemPortIds = append(gemPortIds, gemPortParam.multicastGemPortID)
952 }
953 }
954 } //else: the state is just ignored (does not exist)
955 return gemPortIds
956}
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800957
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000958func (onuTP *OnuUniTechProf) getBidirectionalGemPortIDsForTP(ctx context.Context, aUniID uint8, aTpID uint8) []uint16 {
ozgecanetsia82b91a62021-05-21 18:54:49 +0300959 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
960 onuTP.mutexTPState.RLock()
961 defer onuTP.mutexTPState.RUnlock()
962 gemPortIds := make([]uint16, 0)
963 if techProfile, existTP := onuTP.mapPonAniConfig[uniTpKey]; existTP {
964 logger.Debugw(ctx, "TechProfile exist", log.Fields{"device-id": onuTP.deviceID})
965 for _, gemPortParam := range techProfile.mapGemPortParams {
966 if !gemPortParam.isMulticast {
967 logger.Debugw(ctx, "Detected unicast gemPort", log.Fields{"device-id": onuTP.deviceID,
968 "aUniID": aUniID, "aTPID": aTpID, "uniTPKey": uniTpKey,
969 "GemId": gemPortParam.multicastGemPortID})
970 gemPortIds = append(gemPortIds, gemPortParam.gemPortID)
971 }
972 }
973 } else {
974 logger.Debugw(ctx, "TechProfile doesn't exist", log.Fields{"device-id": onuTP.deviceID})
975 } //else: the state is just ignored (does not exist)
976 logger.Debugw(ctx, "Gem PortID list", log.Fields{"device-id": onuTP.deviceID, "gemportList": gemPortIds})
977 return gemPortIds
978}
979
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000980// GetAllBidirectionalGemPortIDsForOnu - TODO: add comment
981func (onuTP *OnuUniTechProf) GetAllBidirectionalGemPortIDsForOnu() []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800982 var gemPortInstIDs []uint16
983 onuTP.mutexTPState.RLock()
984 defer onuTP.mutexTPState.RUnlock()
985 for _, tcontGemList := range onuTP.mapPonAniConfig {
986 for gemPortID, gemPortData := range tcontGemList.mapGemPortParams {
987 if gemPortData != nil && !gemPortData.isMulticast { // only if not multicast gem port
988 gemPortInstIDs = append(gemPortInstIDs, gemPortID)
989 }
990 }
991 }
992 return gemPortInstIDs
993}
mpagenko73143992021-04-09 15:17:10 +0000994
995// setProfileResetting sets/resets the indication, that a reset of the TechProfileConfig/Removal is ongoing
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000996func (onuTP *OnuUniTechProf) setProfileResetting(ctx context.Context, aUniID uint8, aTpID uint8, aState bool) {
mpagenko73143992021-04-09 15:17:10 +0000997 uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
998 onuTP.mutexTPState.Lock()
999 defer onuTP.mutexTPState.Unlock()
1000 onuTP.tpProfileResetting[uniTpKey] = aState
1001}
1002
1003// getProfileResetting returns true, if the the according indication for started reset procedure is set
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001004func (onuTP *OnuUniTechProf) getProfileResetting(aUniTpKey uniTP) bool {
mpagenko73143992021-04-09 15:17:10 +00001005 onuTP.mutexTPState.RLock()
1006 defer onuTP.mutexTPState.RUnlock()
1007 if isResetting, exist := onuTP.tpProfileResetting[aUniTpKey]; exist {
1008 return isResetting
1009 }
1010 return false
1011}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00001012
1013// PrepareForGarbageCollection - remove references to prepare for garbage collection
1014func (onuTP *OnuUniTechProf) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
1015 logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})
1016 onuTP.baseDeviceHandler = nil
1017 onuTP.onuDevice = nil
1018 for k, v := range onuTP.PAniConfigFsm {
1019 v.PrepareForGarbageCollection(ctx, aDeviceID)
1020 delete(onuTP.PAniConfigFsm, k)
1021 }
1022}