[VOL-3437] Implement (incremental) flow config removal with according OMCI VLAN configuration and some further code corrections and smaller functional extensions -> version 0.1.13-dev135, now merged with [VOL-3586] und included correction for missing Techprofile configuration at disable/enable procedure
Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I438a72867d5da83c505a30169d7d5aba8f8ee8c2
diff --git a/internal/pkg/onuadaptercore/onu_uni_tp.go b/internal/pkg/onuadaptercore/onu_uni_tp.go
index d9578fe..e052684 100644
--- a/internal/pkg/onuadaptercore/onu_uni_tp.go
+++ b/internal/pkg/onuadaptercore/onu_uni_tp.go
@@ -85,8 +85,8 @@
//onuUniTechProf structure holds information about the TechProfiles attached to Uni Ports of the ONU
type onuUniTechProf struct {
- deviceID string
baseDeviceHandler *deviceHandler
+ deviceID string
tpProcMutex sync.RWMutex
techProfileKVStore *db.Backend
chTpConfigProcessingStep chan uint8
@@ -95,15 +95,16 @@
pAniConfigFsm *uniPonAniConfigFsm
procResult error //error indication of processing
mutexTPState sync.Mutex
+ tpProfileExists bool
}
//newOnuUniTechProf returns the instance of a OnuUniTechProf
//(one instance per ONU/deviceHandler for all possible UNI's)
-func newOnuUniTechProf(ctx context.Context, aDeviceID string, aDeviceHandler *deviceHandler) *onuUniTechProf {
- logger.Infow("init-OnuUniTechProf", log.Fields{"device-id": aDeviceID})
+func newOnuUniTechProf(ctx context.Context, aDeviceHandler *deviceHandler) *onuUniTechProf {
+ logger.Infow("init-OnuUniTechProf", log.Fields{"device-id": aDeviceHandler.deviceID})
var onuTP onuUniTechProf
- onuTP.deviceID = aDeviceID
onuTP.baseDeviceHandler = aDeviceHandler
+ onuTP.deviceID = aDeviceHandler.deviceID
onuTP.tpProcMutex = sync.RWMutex{}
onuTP.chTpConfigProcessingStep = make(chan uint8)
onuTP.mapUniTpIndication = make(map[uint8]*tTechProfileIndication)
@@ -113,7 +114,7 @@
onuTP.techProfileKVStore = aDeviceHandler.setBackend(cBasePathTechProfileKVStore)
if onuTP.techProfileKVStore == nil {
logger.Errorw("Can't access techProfileKVStore - no backend connection to service",
- log.Fields{"device-id": aDeviceID, "service": cBasePathTechProfileKVStore})
+ log.Fields{"device-id": aDeviceHandler.deviceID, "service": cBasePathTechProfileKVStore})
}
return &onuTP
@@ -147,7 +148,7 @@
aUniID uint8, aPathString string, wg *sync.WaitGroup) {
defer wg.Done() //always decrement the waitGroup on return
logger.Debugw("configure the Uni according to TpPath", log.Fields{
- "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString})
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString})
if onuTP.techProfileKVStore == nil {
logger.Debug("techProfileKVStore not set - abort")
@@ -166,7 +167,7 @@
}
if pCurrentUniPort == nil {
logger.Errorw("TechProfile configuration aborted: requested uniID not found in PortDB",
- log.Fields{"device-id": onuTP.deviceID, "uniID": aUniID})
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult = fmt.Errorf("techProfile config aborted: requested uniID not found %d on %s",
aUniID, onuTP.deviceID)
return
@@ -195,8 +196,13 @@
go onuTP.readAniSideConfigFromTechProfile(ctx, aUniID, aPathString, processingStep)
if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
//timeout or error detected
+ if onuTP.tpProfileExists {
+ //ignore the internal error in case the new profile is already configured
+ // and abort the processing here
+ return
+ }
logger.Debugw("tech-profile related configuration aborted on read",
- log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult = fmt.Errorf("techProfile config aborted: tech-profile read issue for %d on %s",
aUniID, onuTP.deviceID)
return
@@ -210,7 +216,7 @@
if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
//timeout or error detected
logger.Debugw("tech-profile related configuration aborted on set",
- log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID})
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult = fmt.Errorf("techProfile config aborted: Omci AniSideConfig failed %d on %s",
aUniID, onuTP.deviceID)
//this issue here means that the AniConfigFsm has not finished successfully
@@ -222,14 +228,14 @@
} else {
// strange: UNI entry exists, but no ANI data, maybe such situation should be cleared up (if observed)
logger.Debugw("no Tcont/Gem data for this UNI found - abort", log.Fields{
- "device-id": onuTP.deviceID, "uniID": aUniID})
+ "device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult = fmt.Errorf("techProfile config aborted: no Tcont/Gem data found for this UNI %d on %s",
aUniID, onuTP.deviceID)
return
}
} else {
logger.Debugw("no PonAni data for this UNI found - abort", log.Fields{
- "device-id": onuTP.deviceID, "uniID": aUniID})
+ "device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult = fmt.Errorf("techProfile config aborted: no AniSide data found for this UNI %d on %s",
aUniID, onuTP.deviceID)
return
@@ -242,6 +248,7 @@
ctx context.Context, aUniID uint8, aPathString string, aProcessingStep uint8) {
var tpInst tp.TechProfile
+ onuTP.tpProfileExists = false
//store profile type and identifier for later usage within the OMCI identifier and possibly ME setup
//pathstring is defined to be in the form of <ProfType>/<profID>/<Interface/../Identifier>
subStringSlice := strings.Split(aPathString, "/")
@@ -251,18 +258,33 @@
onuTP.chTpConfigProcessingStep <- 0 //error indication
return
}
+ profID, err := strconv.ParseUint(subStringSlice[1], 10, 32)
+ if err != nil {
+ logger.Errorw("invalid ProfileId from path",
+ log.Fields{"ParseErr": err})
+ onuTP.chTpConfigProcessingStep <- 0 //error indication
+ return
+ }
- //just some logical check to avoid unexpected behavior
//at this point it is assumed that a new TechProfile is assigned to the UNI
- //expectation is that no TPIndication entry exists here, if yes,
- // then we throw a warning and remove it (and the possible ANIConfig) simply
- // note that the ONU config state may be ambivalent in such a case
- // also note, that the PonAniConfig map is not checked additionally
- // consistency to TPIndication is assumed
+ //expectation is that no TPIndication entry exists here, if exists and with the same TPId
+ // then we throw a warning, set an internal error and abort with error,
+ // which is later re-defined to success response to OLT adapter
+ // if TPId has changed, current data is removed (note that the ONU config state may be
+ // ambivalent in such a case)
if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {
logger.Warnw("Some active profile entry at reading new TechProfile",
log.Fields{"path": aPathString, "device-id": onuTP.deviceID,
- "UniId": aUniID, "wrongProfile": onuTP.mapUniTpIndication[aUniID].techProfileID})
+ "uni-id": aUniID, "wrongProfile": onuTP.mapUniTpIndication[aUniID].techProfileID})
+ if uint16(profID) == onuTP.mapUniTpIndication[aUniID].techProfileID {
+ // ProfId not changed - assume profile to be still the same
+ // anyway this should not appear after full support of profile (Gem/TCont) removal
+ logger.Warnw("New TechProfile already exists - aborting configuration",
+ log.Fields{"device-id": onuTP.deviceID})
+ onuTP.tpProfileExists = true
+ onuTP.chTpConfigProcessingStep <- 0 //error indication
+ return
+ }
//delete on the mapUniTpIndication map not needed, just overwritten later
//delete on the PonAniConfig map should be safe, even if not existing
delete(onuTP.mapPonAniConfig, aUniID)
@@ -272,18 +294,11 @@
}
onuTP.mapUniTpIndication[aUniID].techProfileType = subStringSlice[0]
- profID, err := strconv.ParseUint(subStringSlice[1], 10, 32)
- if err != nil {
- logger.Errorw("invalid ProfileId from path",
- log.Fields{"ParseErr": err})
- onuTP.chTpConfigProcessingStep <- 0 //error indication
- return
- }
-
//note the limitation on ID range (probably even more limited) - based on usage within OMCI EntityID
onuTP.mapUniTpIndication[aUniID].techProfileID = uint16(profID)
+ onuTP.mapUniTpIndication[aUniID].techProfileConfigDone = false
logger.Debugw("tech-profile path indications",
- log.Fields{"device-id": onuTP.deviceID, "UniId": aUniID,
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID,
"profType": onuTP.mapUniTpIndication[aUniID].techProfileType,
"profID": onuTP.mapUniTpIndication[aUniID].techProfileID})
@@ -318,7 +333,7 @@
return
}
- //default start with 1Tcont1Gem profile, later extend for multi GemPerTcont and perhaps even MultiTcontMultiGem
+ //default start with 1Tcont profile, later perhaps extend to MultiTcontMultiGem
localMapGemPortParams := make(map[uint16]*gemPortParamStruct)
localMapGemPortParams[0] = &gemPortParamStruct{}
localMapPonAniConfig := make(map[uint16]*tcontGemList)
@@ -450,7 +465,7 @@
}
pAniCfgFsm := newUniPonAniConfigFsm(pDevEntry.PDevOmciCC, apCurrentUniPort, onuTP,
pDevEntry.pOnuDB, onuTP.mapUniTpIndication[aUniID].techProfileID, devEvent,
- "AniConfigFsm", onuTP.deviceID, chAniConfigFsm)
+ "AniConfigFsm", onuTP.baseDeviceHandler, chAniConfigFsm)
if pAniCfgFsm != nil {
onuTP.pAniConfigFsm = pAniCfgFsm
onuTP.runAniConfigFsm(aProcessingStep)
@@ -488,6 +503,18 @@
}
}
+// clearAniSideConfig deletes all internal TechProfile related data connected to the requested UniPort
+func (onuTP *onuUniTechProf) clearAniSideConfig(aUniID uint8) {
+ logger.Debugw("removing TpIndication and PonAniConfig data", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID})
+ //a mutex protection on the concerned data should not be needed here, as the config/write action should not
+ // interfere with any read action or the initial write/config activity at start
+ //remove the TechProfile indications of this UNI, should be safe even if not existing
+ delete(onuTP.mapUniTpIndication, aUniID)
+ //delete on the PonAniConfig map of this UNI should be safe, even if not existing
+ delete(onuTP.mapPonAniConfig, aUniID)
+}
+
// setConfigDone sets the requested techProfile config state (if possible)
func (onuTP *onuUniTechProf) setConfigDone(aUniID uint8, aState bool) {
if _, existTP := onuTP.mapUniTpIndication[aUniID]; existTP {