[VOL-3330] removal of tech profile OMCI related configuration on tech profile deletion - version 0.1.15-dev144
Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: Ife9ddc140e725af1375d4a786e2b5079edbb8f33
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index fbb324e..e2b847d 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -394,7 +394,7 @@
var wg sync.WaitGroup
wg.Add(1) // for the 1 go routine to finish
- go dh.pOnuTP.deleteTpResource(dctx, uniID, delGemPortMsg.TpPath,
+ go dh.pOnuTP.deleteTpResource(dctx, uniID, tpID, delGemPortMsg.TpPath,
cResourceGemPort, delGemPortMsg.GemPortId, &wg)
dh.waitForCompletion(cancel, &wg, "GemDelete") //wait for background process to finish
@@ -454,7 +454,7 @@
var wg sync.WaitGroup
wg.Add(2) // for the 2 go routines to finish
- go dh.pOnuTP.deleteTpResource(dctx, uniID, delTcontMsg.TpPath,
+ go dh.pOnuTP.deleteTpResource(dctx, uniID, tpID, delTcontMsg.TpPath,
cResourceTcont, delTcontMsg.AllocId, &wg)
// Removal of the tcont/alloc id mapping represents the removal of the tech profile
go pDevEntry.updateOnuKvStore(dctx, &wg)
@@ -845,6 +845,10 @@
return err
}
dh.ReadyForSpecificOmciConfig = false
+ //no specific activity to synchronize any internal FSM to the 'rebooted' state is explicitly done here
+ // the expectation ids for a real device, that it will be synced with the expected following 'down' indication
+ // as BBSIM does not support this testing requires explicite disable/enable device calls in which sequence also
+ // all other FSM's should be synchronized again
return nil
}
diff --git a/internal/pkg/onuadaptercore/omci_ani_config.go b/internal/pkg/onuadaptercore/omci_ani_config.go
index 7341ff6..0f44d84 100644
--- a/internal/pkg/onuadaptercore/omci_ani_config.go
+++ b/internal/pkg/onuadaptercore/omci_ani_config.go
@@ -35,19 +35,26 @@
const (
// events of config PON ANI port FSM
- aniEvStart = "uniEvStart"
- aniEvStartConfig = "aniEvStartConfig"
- aniEvRxDot1pmapCResp = "aniEvRxDot1pmapCResp"
- aniEvRxMbpcdResp = "aniEvRxMbpcdResp"
- aniEvRxTcontsResp = "aniEvRxTcontsResp"
- aniEvRxGemntcpsResp = "aniEvRxGemntcpsResp"
- aniEvRxGemiwsResp = "aniEvRxGemiwsResp"
- aniEvRxPrioqsResp = "aniEvRxPrioqsResp"
- aniEvRxDot1pmapSResp = "aniEvRxDot1pmapSResp"
- aniEvTimeoutSimple = "aniEvTimeoutSimple"
- aniEvTimeoutMids = "aniEvTimeoutMids"
- aniEvReset = "aniEvReset"
- aniEvRestart = "aniEvRestart"
+ aniEvStart = "aniEvStart"
+ aniEvStartConfig = "aniEvStartConfig"
+ aniEvRxDot1pmapCResp = "aniEvRxDot1pmapCResp"
+ aniEvRxMbpcdResp = "aniEvRxMbpcdResp"
+ aniEvRxTcontsResp = "aniEvRxTcontsResp"
+ aniEvRxGemntcpsResp = "aniEvRxGemntcpsResp"
+ aniEvRxGemiwsResp = "aniEvRxGemiwsResp"
+ aniEvRxPrioqsResp = "aniEvRxPrioqsResp"
+ aniEvRxDot1pmapSResp = "aniEvRxDot1pmapSResp"
+ aniEvRemGemiw = "aniEvRemGemiw"
+ aniEvRxRemGemiwResp = "aniEvRxRemGemiwResp"
+ aniEvRxRemGemntpResp = "aniEvRxRemGemntpResp"
+ aniEvRemTcontPath = "aniEvRemTcontPath"
+ aniEvRxResetTcontResp = "aniEvRxResetTcontResp"
+ aniEvRxRem1pMapperResp = "aniEvRxRem1pMapperResp"
+ aniEvRxRemAniBPCDResp = "aniEvRxRemAniBPCDResp"
+ aniEvTimeoutSimple = "aniEvTimeoutSimple"
+ aniEvTimeoutMids = "aniEvTimeoutMids"
+ aniEvReset = "aniEvReset"
+ aniEvRestart = "aniEvRestart"
)
const (
// states of config PON ANI port FSM
@@ -61,6 +68,12 @@
aniStSettingPQs = "aniStSettingPQs"
aniStSettingDot1PMapper = "aniStSettingDot1PMapper"
aniStConfigDone = "aniStConfigDone"
+ aniStRemovingGemIW = "aniStRemovingGemIW"
+ aniStRemovingGemNCTP = "aniStRemovingGemNCTP"
+ aniStResetTcont = "aniStResetTcont"
+ aniStRemDot1PMapper = "aniStRemDot1PMapper"
+ aniStRemAniBPCD = "aniStRemAniBPCD"
+ aniStRemoveDone = "aniStRemoveDone"
aniStResetting = "aniStResetting"
)
@@ -87,6 +100,7 @@
pUniTechProf *onuUniTechProf
pOnuDB *onuDeviceDB
techProfileID uint8
+ uniTpKey uniTP
requestEvent OnuDeviceEvent
omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
pAdaptFsm *AdapterFsm
@@ -99,6 +113,7 @@
alloc0ID uint16
gemPortAttribsSlice []ponAniGemPortAttribs
pLastTxMeInstance *me.ManagedEntity
+ requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
}
//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
@@ -116,6 +131,8 @@
requestEvent: aRequestEvent,
chanSet: false,
}
+ instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
+
instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
if instFsm.pAdaptFsm == nil {
logger.Errorw("uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
@@ -142,15 +159,28 @@
{Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
{Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
- {Name: aniEvTimeoutSimple, Src: []string{
- aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper}, Dst: aniStStarting},
+ //for removing Gem related resources
+ {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
+ {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
+ {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
+
+ //for removing TCONT related resources
+ {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
+ {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
+ {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
+ {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
+
+ {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
+ aniStRemovingGemIW, aniStRemovingGemNCTP,
+ aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
{Name: aniEvTimeoutMids, Src: []string{
aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
// exceptional treatment for all states except aniStResetting
{Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
- aniStConfigDone}, Dst: aniStResetting},
+ aniStConfigDone, aniStRemovingGemIW, aniStRemovingGemNCTP,
+ aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
// the only way to get to resource-cleared disabled state again is via "resseting"
{Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
},
@@ -166,6 +196,12 @@
("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(e) },
("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(e) },
("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(e) },
+ ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(e) },
+ ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(e) },
+ ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(e) },
+ ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(e) },
+ ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(e) },
+ ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(e) },
("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(e) },
("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(e) },
},
@@ -189,7 +225,6 @@
func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(aPAFsm *AdapterFsm) {
if aPAFsm != nil && aPAFsm.pFsm != nil {
- uniTpKey := uniTP{uniID: oFsm.pOnuUniPort.uniID, tpID: oFsm.techProfileID}
//stick to pythonAdapter numbering scheme
//index 0 in naming refers to possible usage of multiple instances (later)
oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
@@ -262,8 +297,8 @@
// Access critical state with lock
oFsm.pUniTechProf.mutexTPState.Lock()
- oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[uniTpKey].tcontParams.allocID
- mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[uniTpKey].mapGemPortParams
+ oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
+ mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
oFsm.pUniTechProf.mutexTPState.Unlock()
loGemPortAttribs := ponAniGemPortAttribs{}
@@ -342,8 +377,8 @@
}
func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(e *fsm.Event) {
- logger.Debugw("UniPonAniConfigFsm start", log.Fields{"in state": e.FSM.Current(),
- "device-id": oFsm.deviceID})
+ logger.Debugw("UniPonAniConfigFsm start", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
// in case the used channel is not yet defined (can be re-used after restarts)
if oFsm.omciMIdsResponseReceived == nil {
oFsm.omciMIdsResponseReceived = make(chan bool)
@@ -374,7 +409,8 @@
func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(e *fsm.Event) {
logger.Debugw("uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
"EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
- "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+ oFsm.requestEventOffset = 0 //0 offset for last config request activity
meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
@@ -386,7 +422,7 @@
logger.Debugw("uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
"EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
"TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
- "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
meParams := me.ParamData{
EntityID: oFsm.macBPCD0ID,
@@ -402,14 +438,13 @@
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
oFsm.pLastTxMeInstance = meInstance
-
}
func (oFsm *uniPonAniConfigFsm) enterSettingTconts(e *fsm.Event) {
logger.Debugw("uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
"EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
"AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
- "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
meParams := me.ParamData{
EntityID: oFsm.tcont0ID,
Attributes: me.AttributeValueMap{
@@ -425,13 +460,13 @@
func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(e *fsm.Event) {
logger.Debugw("uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
- "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
go oFsm.performCreatingGemNCTPs()
}
func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(e *fsm.Event) {
logger.Debugw("uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
- "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
go oFsm.performCreatingGemIWs()
}
@@ -443,7 +478,8 @@
func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(e *fsm.Event) {
logger.Debugw("uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
- "toGemIw": 1024 /* cmp above */, "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ "toGemIw": 1024, /* cmp above */
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
logger.Debugw("uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
"EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
@@ -513,14 +549,17 @@
}
func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(e *fsm.Event) {
- logger.Debugw("uniPonAniConfigFsm send dh event notification recheck pending flow config", log.Fields{
- "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
+ logger.Debugw("uniPonAniConfigFsm ani config done", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
//use DeviceHandler event notification directly
- oFsm.pDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
+ oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
//store that the UNI related techProfile processing is done for the given Profile and Uni
oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
//if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
- go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(oFsm.pOnuUniPort)
+ // but only in case the techProfile was configured (not deleted)
+ if oFsm.requestEventOffset == 0 {
+ go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(oFsm.pOnuUniPort)
+ }
if oFsm.chanSet {
// indicate processing done to the caller
@@ -533,8 +572,98 @@
//the FSM is left active in this state as long as no specific reset or remove is requested from outside
}
+func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(e *fsm.Event) {
+ // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
+ oFsm.pUniTechProf.mutexTPState.Lock()
+ loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
+ oFsm.pUniTechProf.mutexTPState.Unlock()
+ logger.Debugw("uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
+ "GemIwTp-entity-id": loGemPortID})
+ oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
+
+ // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
+ meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, loGemPortID)
+ oFsm.pLastTxMeInstance = meInstance
+}
+
+func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(e *fsm.Event) {
+ oFsm.pUniTechProf.mutexTPState.Lock()
+ loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
+ oFsm.pUniTechProf.mutexTPState.Unlock()
+ logger.Debugw("uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
+ "GemNCTP-entity-id": loGemPortID})
+ // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
+ meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, loGemPortID)
+ oFsm.pLastTxMeInstance = meInstance
+}
+
+func (oFsm *uniPonAniConfigFsm) enterResettingTcont(e *fsm.Event) {
+ logger.Debugw("uniPonAniConfigFsm - start resetting the TCont", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+
+ oFsm.requestEventOffset = 1 //offset 1 for last remove activity
+ // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
+ meParams := me.ParamData{
+ EntityID: oFsm.tcont0ID,
+ Attributes: me.AttributeValueMap{
+ "AllocId": unusedTcontAllocID,
+ },
+ }
+ meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, meParams)
+ oFsm.pLastTxMeInstance = meInstance
+}
+
+func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(e *fsm.Event) {
+ logger.Debugw("uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+
+ meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
+ oFsm.pLastTxMeInstance = meInstance
+}
+
+func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(e *fsm.Event) {
+ logger.Debugw("uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+
+ meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
+ oFsm.pLastTxMeInstance = meInstance
+}
+
+func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(e *fsm.Event) {
+ logger.Debugw("uniPonAniConfigFsm ani removal done", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+ //use DeviceHandler event notification directly
+ oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
+ if oFsm.chanSet {
+ // indicate processing done to the caller
+ logger.Debugw("uniPonAniConfigFsm processingDone on channel", log.Fields{
+ "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
+ oFsm.chSuccess <- oFsm.procStep
+ oFsm.chanSet = false //reset the internal channel state
+ }
+
+ //let's reset the state machine in order to release all resources now
+ pConfigAniStateAFsm := oFsm.pAdaptFsm
+ if pConfigAniStateAFsm != nil {
+ // obviously calling some FSM event here directly does not work - so trying to decouple it ...
+ go func(aPAFsm *AdapterFsm) {
+ if aPAFsm != nil && aPAFsm.pFsm != nil {
+ _ = aPAFsm.pFsm.Event(aniEvReset)
+ }
+ }(pConfigAniStateAFsm)
+ }
+}
+
func (oFsm *uniPonAniConfigFsm) enterResettingState(e *fsm.Event) {
- logger.Debugw("uniPonAniConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
+ logger.Debugw("uniPonAniConfigFsm resetting", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
pConfigAniStateAFsm := oFsm.pAdaptFsm
if pConfigAniStateAFsm != nil {
@@ -557,7 +686,8 @@
}
func (oFsm *uniPonAniConfigFsm) enterDisabledState(e *fsm.Event) {
- logger.Debugw("uniPonAniConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
+ logger.Debugw("uniPonAniConfigFsm enters disabled state", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
oFsm.pLastTxMeInstance = nil
//remove all TechProf related internal data to allow for new configuration (e.g. with disable/enable procedure)
@@ -671,7 +801,11 @@
switch oFsm.pLastTxMeInstance.GetName() {
case "TCont":
{ // let the FSM proceed ...
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
+ if oFsm.requestEventOffset == 0 { //from TCont config request
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
+ } else { // from T-Cont reset request
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
+ }
}
case "PriorityQueue":
{ // let the PrioQueue init proceed by stopping the wait function
@@ -685,6 +819,53 @@
}
}
+func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(msg OmciMessage) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
+ if msgLayer == nil {
+ logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
+ log.Fields{"device-id": oFsm.deviceID})
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
+ if !msgOk {
+ logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
+ log.Fields{"device-id": oFsm.deviceID})
+ return
+ }
+ logger.Debugw("UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success {
+ logger.Errorw("UniPonAniConfigFsm - Omci DeleteResponse Error",
+ log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
+ //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
+ // store error for mgmt display?
+ return
+ }
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
+ // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
+
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "GemInterworkingTerminationPoint":
+ { // let the FSM proceed ...
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
+ }
+ case "GemPortNetworkCtp":
+ { // let the FSM proceed ...
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
+ }
+ case "Ieee8021PMapperServiceProfile":
+ { // let the FSM proceed ...
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
+ }
+ case "MacBridgePortConfigurationData":
+ { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
+ }
+ }
+ }
+}
+
func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(msg OmciMessage) {
logger.Debugw("Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
"msgType": msg.OmciMsg.MessageType})
@@ -700,6 +881,11 @@
oFsm.handleOmciAniConfigSetResponseMessage(msg)
} //SetResponseType
+ case omci.DeleteResponseType:
+ {
+ oFsm.handleOmciAniConfigDeleteResponseMessage(msg)
+
+ } //SetResponseType
default:
{
logger.Errorw("uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 32d729e..17e674d 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -59,6 +59,8 @@
const ieeeMapperServiceProfileEID = uint16(0x8001)
const macBridgePortAniEID = uint16(0x2102)
+const unusedTcontAllocID = uint16(0xFFFF) //common unused AllocId for G.984 and G.987 systems
+
// ### OMCI related definitions - end
//callbackPairEntry to be used for OMCI send/receive correlation
@@ -142,7 +144,7 @@
//stop stops/resets the omciCC
func (oo *omciCC) stop(ctx context.Context) error {
- logger.Debugw("omciCC-stopping", log.Fields{"for device-id": oo.deviceID})
+ logger.Debugw("omciCC-stopping", log.Fields{"device-id": oo.deviceID})
//reseting all internal data, which might also be helpful for discarding any lingering tx/rx requests
oo.mutexTxQueue.Lock()
oo.txQueue.Init() // clear the tx queue
@@ -242,17 +244,17 @@
packet := gopacket.NewPacket(rxMsg, omci.LayerTypeOMCI, gopacket.NoCopy)
if packet == nil {
- logger.Errorw("omci-message could not be decoded", log.Fields{"deviceID": oo.deviceID})
+ logger.Errorw("omci-message could not be decoded", log.Fields{"device-id": oo.deviceID})
return fmt.Errorf("could not decode rxMsg as OMCI %s", oo.deviceID)
}
omciLayer := packet.Layer(omci.LayerTypeOMCI)
if omciLayer == nil {
- logger.Errorw("omci-message could not decode omci layer", log.Fields{"deviceID": oo.deviceID})
+ logger.Errorw("omci-message could not decode omci layer", log.Fields{"device-id": oo.deviceID})
return fmt.Errorf("could not decode omci layer %s", oo.deviceID)
}
omciMsg, ok := omciLayer.(*omci.OMCI)
if !ok {
- logger.Errorw("omci-message could not assign omci layer", log.Fields{"deviceID": oo.deviceID})
+ logger.Errorw("omci-message could not assign omci layer", log.Fields{"device-id": oo.deviceID})
return fmt.Errorf("could not assign omci layer %s", oo.deviceID)
}
logger.Debugw("omci-message-decoded:", log.Fields{"omciMsgType": omciMsg.MessageType,
@@ -265,7 +267,7 @@
}
logger.Errorw("Unexpected TransCorrId != 0 not accepted for autonomous messages",
log.Fields{"msgType": omciMsg.MessageType, "payload": hex.EncodeToString(omciMsg.Payload),
- "deviceID": oo.deviceID})
+ "device-id": oo.deviceID})
return fmt.Errorf("autonomous Omci Message with TranSCorrId != 0 not acccepted %s", oo.deviceID)
}
@@ -281,7 +283,7 @@
oo.mutexRxSchedMap.Unlock()
} else {
oo.mutexRxSchedMap.Unlock()
- logger.Errorw("omci-message-response for not registered transCorrId", log.Fields{"deviceID": oo.deviceID})
+ logger.Errorw("omci-message-response for not registered transCorrId", log.Fields{"device-id": oo.deviceID})
return fmt.Errorf("could not find registered response handler tor transCorrId %s", oo.deviceID)
}
@@ -496,11 +498,11 @@
return fmt.Errorf("failed to fetch device %s", oo.deviceID)
}
- logger.Debugw("omci-message-sending", log.Fields{"fromDeviceType": oo.pBaseDeviceHandler.DeviceType,
- "toDeviceType": oo.pBaseDeviceHandler.ProxyAddressType,
- "onuDeviceID": oo.deviceID, "proxyDeviceID": oo.pBaseDeviceHandler.ProxyAddressID})
- logger.Debugw("omci-message-to-send:",
- log.Fields{"TxOmciMessage": hex.EncodeToString(omciTxRequest.txFrame)})
+ logger.Debugw("omci-message-to-send:", log.Fields{
+ "TxOmciMessage": hex.EncodeToString(omciTxRequest.txFrame),
+ "device-id": oo.deviceID,
+ "toDeviceType": oo.pBaseDeviceHandler.ProxyAddressType,
+ "proxyDeviceID": oo.pBaseDeviceHandler.ProxyAddressID})
omciMsg := &ic.InterAdapterOmciMessage{Message: omciTxRequest.txFrame}
if sendErr := oo.adapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
@@ -1656,6 +1658,190 @@
return nil
}
+func (oo *omciCC) sendDeleteGemIWTP(ctx context.Context, timeout int, highPrio bool,
+ rxChan chan Message, aInstID uint16) *me.ManagedEntity {
+ tid := oo.getNextTid(highPrio)
+ logger.Debugw("send GemIwTp-Delete-msg:", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aInstID), 16)})
+
+ meParams := me.ParamData{EntityID: aInstID}
+ meInstance, omciErr := me.NewGemInterworkingTerminationPoint(meParams)
+ if omciErr.GetError() == nil {
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.DeleteRequestType,
+ omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorw("Cannot encode GemIwTp for delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
+ // return (dual format) error code that can be used at caller for immediate error treatment
+ // (relevant to all used sendXX() methods and their error conditions)
+ return nil
+ }
+
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize GemIwTp delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+
+ omciRxCallbackPair := callbackPair{
+ cbKey: tid,
+ cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+ }
+ err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send GemIwTp delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+ logger.Debug("send GemIwTp-Delete-msg done")
+ return meInstance
+ }
+ logger.Errorw("Cannot generate GemIwTp Instance for delete", log.Fields{
+ "Err": omciErr.GetError(), "device-id": oo.deviceID})
+ return nil
+}
+
+func (oo *omciCC) sendDeleteGemNCTP(ctx context.Context, timeout int, highPrio bool,
+ rxChan chan Message, aInstID uint16) *me.ManagedEntity {
+ tid := oo.getNextTid(highPrio)
+ logger.Debugw("send GemNCtp-Delete-msg:", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aInstID), 16)})
+
+ meParams := me.ParamData{EntityID: aInstID}
+ meInstance, omciErr := me.NewGemPortNetworkCtp(meParams)
+ if omciErr.GetError() == nil {
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.DeleteRequestType,
+ omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorw("Cannot encode GemNCtp for delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
+ // return (dual format) error code that can be used at caller for immediate error treatment
+ // (relevant to all used sendXX() methods and their error conditions)
+ return nil
+ }
+
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize GemNCtp delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+
+ omciRxCallbackPair := callbackPair{
+ cbKey: tid,
+ cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+ }
+ err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send GemNCtp delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+ logger.Debug("send GemNCtp-Delete-msg done")
+ return meInstance
+ }
+ logger.Errorw("Cannot generate GemNCtp Instance for delete", log.Fields{
+ "Err": omciErr.GetError(), "device-id": oo.deviceID})
+ return nil
+}
+
+func (oo *omciCC) sendDeleteDot1PMapper(ctx context.Context, timeout int, highPrio bool,
+ rxChan chan Message, aInstID uint16) *me.ManagedEntity {
+ tid := oo.getNextTid(highPrio)
+ logger.Debugw("send .1pMapper-Delete-msg:", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aInstID), 16)})
+
+ meParams := me.ParamData{EntityID: aInstID}
+ meInstance, omciErr := me.NewIeee8021PMapperServiceProfile(meParams)
+ if omciErr.GetError() == nil {
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.DeleteRequestType,
+ omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorw("Cannot encode .1pMapper for delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
+ // return (dual format) error code that can be used at caller for immediate error treatment
+ // (relevant to all used sendXX() methods and their error conditions)
+ return nil
+ }
+
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize .1pMapper delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+
+ omciRxCallbackPair := callbackPair{
+ cbKey: tid,
+ cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+ }
+ err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send .1pMapper delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+ logger.Debug("send .1pMapper-Delete-msg done")
+ return meInstance
+ }
+ logger.Errorw("Cannot generate .1pMapper Instance for delete", log.Fields{
+ "Err": omciErr.GetError(), "device-id": oo.deviceID})
+ return nil
+}
+
+func (oo *omciCC) sendDeleteMBPConfigData(ctx context.Context, timeout int, highPrio bool,
+ rxChan chan Message, aInstID uint16) *me.ManagedEntity {
+ tid := oo.getNextTid(highPrio)
+ logger.Debugw("send MBPCD-Delete-msg:", log.Fields{"device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16),
+ "InstId": strconv.FormatInt(int64(aInstID), 16)})
+
+ meParams := me.ParamData{EntityID: aInstID}
+ meInstance, omciErr := me.NewMacBridgePortConfigurationData(meParams)
+ if omciErr.GetError() == nil {
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.DeleteRequestType,
+ omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorw("Cannot encode MBPCD for delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
+ // return (dual format) error code that can be used at caller for immediate error treatment
+ // (relevant to all used sendXX() methods and their error conditions)
+ return nil
+ }
+
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize MBPCD delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+
+ omciRxCallbackPair := callbackPair{
+ cbKey: tid,
+ cbEntry: callbackPairEntry{rxChan, oo.receiveOmciResponse},
+ }
+ err = oo.send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send MBPCD delete", log.Fields{
+ "Err": err, "device-id": oo.deviceID})
+ return nil
+ }
+ logger.Debug("send MBPCD-Delete-msg done")
+ return meInstance
+ }
+ logger.Errorw("Cannot generate MBPCD Instance for delete", log.Fields{
+ "Err": omciErr.GetError(), "device-id": oo.deviceID})
+ return nil
+}
+
// nolint: unused
func (oo *omciCC) sendCreateMulticastGemIWTPVar(ctx context.Context, timeout int, highPrio bool,
rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
diff --git a/internal/pkg/onuadaptercore/omci_vlan_config.go b/internal/pkg/onuadaptercore/omci_vlan_config.go
index 71c1a8f..eb3b65f 100644
--- a/internal/pkg/onuadaptercore/omci_vlan_config.go
+++ b/internal/pkg/onuadaptercore/omci_vlan_config.go
@@ -608,6 +608,16 @@
func (oFsm *UniVlanConfigFsm) enterConfigVtfd(e *fsm.Event) {
//mutex protection is required for possible concurrent access to FSM members
oFsm.mutexFlowParams.Lock()
+ if len(oFsm.uniVlanFlowParamsSlice) == 0 {
+ //possibly the entry is not valid anymore based on intermediate delete requests
+ //just a basic protection ...
+ oFsm.mutexFlowParams.Unlock()
+ pConfigVlanStateAFsm := oFsm.pAdaptFsm
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ }(pConfigVlanStateAFsm)
+ return
+ }
if oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
// meaning transparent setup - no specific VTFD setting required
oFsm.mutexFlowParams.Unlock()
@@ -705,7 +715,16 @@
}(pConfigVlanStateBaseFsm)
return
}
-
+ if uint8(len(oFsm.uniVlanFlowParamsSlice)) < oFsm.configuredUniFlow {
+ //possibly the entry is not valid anymore based on intermediate delete requests
+ //just a basic protection ...
+ oFsm.mutexFlowParams.Unlock()
+ pConfigVlanStateAFsm := oFsm.pAdaptFsm
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ }(pConfigVlanStateAFsm)
+ return
+ }
if oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
// meaning transparent setup - no specific VTFD setting required
oFsm.mutexFlowParams.Unlock()
@@ -1198,6 +1217,17 @@
} //first flow element
oFsm.mutexFlowParams.Lock()
+ if uint8(len(oFsm.uniVlanFlowParamsSlice)) < aFlowEntryNo {
+ //possibly the entry is not valid anymore based on intermediate delete requests
+ //just a basic protection ...
+ oFsm.mutexFlowParams.Unlock()
+ pConfigVlanStateAFsm := oFsm.pAdaptFsm
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(vlanEvReset)
+ }(pConfigVlanStateAFsm)
+ return
+ }
+
if oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
//transparent transmission required
oFsm.mutexFlowParams.Unlock()
diff --git a/internal/pkg/onuadaptercore/onu_uni_tp.go b/internal/pkg/onuadaptercore/onu_uni_tp.go
index ee52b13..102f32d 100644
--- a/internal/pkg/onuadaptercore/onu_uni_tp.go
+++ b/internal/pkg/onuadaptercore/onu_uni_tp.go
@@ -72,6 +72,7 @@
//maxQueueSize uint16
queueSchedPolicy string
queueWeight uint8
+ removeIndex uint16
}
//refers to one tcont and its properties and all assigned GemPorts and their properties
@@ -99,6 +100,7 @@
procResult map[uniTP]error //error indication of processing
mutexTPState sync.Mutex
tpProfileExists map[uniTP]bool
+ mapRemoveGemEntry map[uniTP]*gemPortParamStruct //per UNI: pointer to GemEntry to be removed
}
//newOnuUniTechProf returns the instance of a OnuUniTechProf
@@ -114,6 +116,7 @@
onuTP.mapPonAniConfig = make(map[uniTP]*tcontGemList)
onuTP.procResult = make(map[uniTP]error)
onuTP.tpProfileExists = make(map[uniTP]bool)
+ onuTP.mapRemoveGemEntry = make(map[uniTP]*gemPortParamStruct)
baseKvStorePath := fmt.Sprintf(cBasePathTechProfileKVStore, aDeviceHandler.pOpenOnuAc.cm.Backend.PathPrefix)
onuTP.techProfileKVStore = aDeviceHandler.setBackend(baseKvStorePath)
if onuTP.techProfileKVStore == nil {
@@ -144,7 +147,7 @@
return onuTP.procResult[uniTP{uniID: aUniID, tpID: aTpID}]
}
-// configureUniTp checks existing tp resources to delete and starts the corresponding OMCI configuation of the UNI port
+// configureUniTp checks existing tp resources to configure and starts the corresponding OMCI configuation of the UNI port
// all possibly blocking processing must be run in background to allow for deadline supervision!
// but take care on sequential background processing when needed (logical dependencies)
// use waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) for internal synchronization
@@ -160,7 +163,8 @@
return
}
if onuTP.techProfileKVStore == nil {
- logger.Debug("techProfileKVStore not set - abort")
+ logger.Errorw("techProfileKVStore not set - abort",
+ log.Fields{"device-id": onuTP.deviceID})
onuTP.procResult[uniTpKey] = errors.New("techProfile config aborted: techProfileKVStore not set")
return
}
@@ -210,7 +214,7 @@
// and abort the processing here
return
}
- logger.Debugw("tech-profile related configuration aborted on read",
+ logger.Errorw("tech-profile related configuration aborted on read",
log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: tech-profile read issue for %d on %s",
aUniID, onuTP.deviceID)
@@ -224,10 +228,15 @@
if existPA {
if valuePA != nil {
//Config data for this uni and and at least TCont Index 0 exist
- go onuTP.setAniSideConfigFromTechProfile(ctx, aUniID, tpID, pCurrentUniPort, processingStep)
+ if err := onuTP.setAniSideConfigFromTechProfile(ctx, aUniID, tpID, pCurrentUniPort, processingStep); err != nil {
+ logger.Errorw("tech-profile related FSM could not be started",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
+ onuTP.procResult[uniTpKey] = err
+ return
+ }
if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
//timeout or error detected
- logger.Debugw("tech-profile related configuration aborted on set",
+ logger.Errorw("tech-profile related configuration aborted on set",
log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: Omci AniSideConfig failed %d on %s",
@@ -240,7 +249,7 @@
}
} 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{
+ logger.Errorw("no Tcont/Gem data for this UNI found - abort", log.Fields{
"device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: no Tcont/Gem data found for this UNI %d on %s",
@@ -248,7 +257,7 @@
return
}
} else {
- logger.Debugw("no PonAni data for this UNI found - abort", log.Fields{
+ logger.Errorw("no PonAni data for this UNI found - abort", log.Fields{
"device-id": onuTP.deviceID, "uni-id": aUniID})
onuTP.procResult[uniTpKey] = fmt.Errorf("techProfile config aborted: no AniSide data found for this UNI %d on %s",
@@ -419,8 +428,8 @@
//logger does not simply output the given structures, just give some example debug values
logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
- "device-id": onuTP.deviceID,
- "AllocId": onuTP.mapPonAniConfig[uniTPKey].tcontParams.allocID})
+ "device-id": onuTP.deviceID, "uni-id": aUniID,
+ "AllocId": onuTP.mapPonAniConfig[uniTPKey].tcontParams.allocID})
for gemIndex, gemEntry := range onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams {
logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
"GemIndex": gemIndex,
@@ -432,19 +441,209 @@
}
func (onuTP *onuUniTechProf) setAniSideConfigFromTechProfile(
- ctx context.Context, aUniID uint8, aTpID uint8, apCurrentUniPort *onuUniPort, aProcessingStep uint8) {
+ ctx context.Context, aUniID uint8, aTpID uint8, apCurrentUniPort *onuUniPort, aProcessingStep uint8) error {
//OMCI transfer of ANI data acc. to mapPonAniConfig
// also the FSM's are running in background,
- // hence we have to make sure they indicate 'success' success on chTpConfigProcessingStep with aProcessingStep
+ // hence we have to make sure they indicate 'success' on chTpConfigProcessingStep with aProcessingStep
uniTPKey := uniTP{uniID: aUniID, tpID: aTpID}
if onuTP.pAniConfigFsm == nil {
- onuTP.createAniConfigFsm(aUniID, aTpID, apCurrentUniPort, OmciAniConfigDone, aProcessingStep)
+ return onuTP.createAniConfigFsm(aUniID, aTpID, apCurrentUniPort, OmciAniConfigDone, aProcessingStep)
} else if _, ok := onuTP.pAniConfigFsm[uniTPKey]; !ok {
- onuTP.createAniConfigFsm(aUniID, aTpID, apCurrentUniPort, OmciAniConfigDone, aProcessingStep)
- } else { //AniConfigFsm already init
- onuTP.runAniConfigFsm(aProcessingStep, aUniID, aTpID)
+ return onuTP.createAniConfigFsm(aUniID, aTpID, apCurrentUniPort, OmciAniConfigDone, aProcessingStep)
}
+ //AniConfigFsm already init
+ return onuTP.runAniConfigFsm(aniEvStart, aProcessingStep, aUniID, aTpID)
+}
+
+// deleteTpResource removes Resources from the ONU's specified Uni
+func (onuTP *onuUniTechProf) deleteTpResource(ctx context.Context,
+ aUniID uint8, aTpID uint8, aPathString string, aResource resourceEntry, aEntryID uint32,
+ wg *sync.WaitGroup) {
+ defer wg.Done()
+ logger.Debugw("will remove TP resources from ONU's UNI", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString, "Resource": aResource})
+ uniTPKey := uniTP{uniID: aUniID, tpID: aTpID}
+
+ if cResourceGemPort == aResource {
+ logger.Debugw("remove GemPort from the list of existing ones of the TP", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString, "GemPort": aEntryID})
+
+ // check if the requested GemPort exists in the DB, indicate it to the FSM
+ // store locally to remove it from DB later on success
+ pLocAniConfigOnUni := onuTP.mapPonAniConfig[uniTPKey]
+ if pLocAniConfigOnUni == nil {
+ // No relevant entry exists anymore - acknowledge success
+ logger.Debugw("AniConfig or GemEntry do not exists in DB", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
+ return
+ }
+ for gemIndex, gemEntry := range pLocAniConfigOnUni.mapGemPortParams {
+ if gemEntry.gemPortID == uint16(aEntryID) {
+ //GemEntry to be deleted found
+ gemEntry.removeIndex = gemIndex //store the index for later removal
+ onuTP.mapRemoveGemEntry[uniTPKey] = pLocAniConfigOnUni.mapGemPortParams[gemIndex]
+ logger.Debugw("Remove-GemEntry stored", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID, "GemIndex": gemIndex})
+ break //abort loop, always only one GemPort to remove
+ }
+ }
+ if onuTP.mapRemoveGemEntry[uniTPKey] == nil {
+ logger.Errorw("GemPort removal aborted - GemPort not found",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID, "GemPort": aEntryID})
+ /* Do not set some error indication to the outside system interface on delete
+ assume there is nothing to be deleted internally and hope a new config request will recover the situation
+ onuTP.procResult[uniTpKey] = fmt.Errorf("GemPort removal aborted: GemPort not found %d for %d on %s",
+ aEntryID, aUniID, onuTP.deviceID)
+ */
+ return
+ }
+ if onuTP.baseDeviceHandler.ReadyForSpecificOmciConfig {
+ // check that the TpConfigRequest was done before
+ // -> that is implicitly done using the AniConfigFsm,
+ // which must be in the according state to remove something
+ // initiate OMCI GemPort related removal
+ var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
+ // hence we have to make sure they indicate 'success' on chTpConfigProcessingStep with aProcessingStep
+ if onuTP.pAniConfigFsm == nil {
+ logger.Errorw("abort GemPort removal - no AniConfigFsm available",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
+ /* Do not set some error indication to the outside system interface on delete (see above)
+ onuTP.procResult[uniTpKey] = fmt.Errorf("GemPort removal aborted: no AniConfigFsm available %d on %s",
+ aUniID, onuTP.deviceID)
+ */
+ //if the FSM is not valid, also TP related remove data should not be valid:
+ // remove GemPort from config DB
+ delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeIndex)
+ // remove the removeEntry
+ delete(onuTP.mapRemoveGemEntry, uniTPKey)
+ return
+ }
+ if _, ok := onuTP.pAniConfigFsm[uniTPKey]; !ok {
+ logger.Errorw("abort GemPort removal - no AniConfigFsm available for this uni/tp",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
+ /* Do not set some error indication to the outside system interface on delete (see above)
+ onuTP.procResult[uniTpKey] = fmt.Errorf("GemPort removal aborted: no AniConfigFsm available %d on %s for tpid",
+ aUniID, onuTP.deviceID, aTpID)
+ */
+ //if the FSM is not valid, also TP related remove data should not be valid:
+ // remove GemPort from config DB
+ delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeIndex)
+ // remove the removeEntry
+ delete(onuTP.mapRemoveGemEntry, uniTPKey)
+ return
+ }
+ if nil != onuTP.runAniConfigFsm(aniEvRemGemiw, processingStep, aUniID, aTpID) {
+ //even if the FSM invocation did not work we don't indicate a problem within procResult
+ //errors could exist also because there was nothing to delete - so we just accept that as 'deleted'
+ //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
+ return
+ }
+ if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
+ //timeout or error detected
+ logger.Errorw("GemPort removal aborted - Omci AniSideConfig failed",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
+ //even if the FSM delete execution did not work we don't indicate a problem within procResult
+ //we should never respond to delete with error ...
+ //this issue here means that the AniConfigFsm has not finished successfully
+ //which requires to reset it to allow for new usage, e.g. also on a different UNI
+ //(without that it would be reset on device down indication latest)
+ _ = onuTP.pAniConfigFsm[uniTPKey].pAdaptFsm.pFsm.Event(aniEvReset)
+ //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
+ return
+ }
+ } else {
+ logger.Debugw("uniPonAniConfigFsm delete Gem on OMCI skipped based on device state", log.Fields{
+ "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.deviceReason})
+ }
+ // remove GemPort from config DB
+ delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeIndex)
+ // remove the removeEntry
+ delete(onuTP.mapRemoveGemEntry, uniTPKey)
+ // deviceHandler StatusEvent (reason update) (see end of function) is only generated in case some element really was removed
+ } else { //if cResourceTcont == aResource {
+ logger.Debugw("reset TCont with AllocId", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString, "allocId": aEntryID})
+
+ // check if the TCont with the indicated AllocId exists in the DB, indicate its EntityId to the FSM
+ pLocAniConfigOnUni := onuTP.mapPonAniConfig[uniTPKey]
+ if pLocAniConfigOnUni == nil {
+ // No relevant entry exists anymore - acknowledge success
+ logger.Debugw("AniConfig or TCont entry do not exists in DB", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
+ return
+ }
+ if pLocAniConfigOnUni.tcontParams.allocID != uint16(aEntryID) {
+ logger.Errorw("TCont removal aborted - indicated AllocId not found",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID, "AllocId": aEntryID})
+ /* Do not set some error indication to the outside system interface on delete
+ assume there is nothing to be deleted internally and hope a new config request will recover the situation
+ onuTP.procResult[uniTpKey] = fmt.Errorf("TCont removal aborted: AllocId not found %d for %d on %s",
+ aEntryID, aUniID, onuTP.deviceID)
+ */
+ return
+ }
+ //T-Cont to be reset found
+ logger.Debugw("Reset-T-Cont AllocId found - valid", log.Fields{
+ "device-id": onuTP.deviceID, "uni-id": aUniID, "AllocId": aEntryID})
+ if onuTP.pAniConfigFsm == nil {
+ logger.Errorw("no TCont removal on OMCI - no AniConfigFsm available",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
+ /* Do not set some error indication to the outside system interface on delete (see above)
+ onuTP.procResult[uniTpKey] = fmt.Errorf("TCont cleanup aborted: no AniConfigFsm available %d on %s",
+ aUniID, onuTP.deviceID)
+ */
+ //if the FSM is not valid, also TP related data should not be valid - clear the internal store profile data
+ onuTP.clearAniSideConfig(aUniID, aTpID)
+ return
+ }
+ if _, ok := onuTP.pAniConfigFsm[uniTPKey]; !ok {
+ logger.Errorw("no TCont removal on OMCI - no AniConfigFsm available for this uni/tp",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "tp-id": aTpID})
+ //even if the FSM invocation did not work we don't indicate a problem within procResult
+ //errors could exist also because there was nothing to delete - so we just accept that as 'deleted'
+ //if the FSM is not valid, also TP related data should not be valid - clear the internal store profile data
+ onuTP.clearAniSideConfig(aUniID, aTpID)
+ return
+ }
+ if onuTP.baseDeviceHandler.ReadyForSpecificOmciConfig {
+ // check that the TpConfigRequest was done before
+ // -> that is implicitly done using the AniConfigFsm,
+ // which must be in the according state to remove something
+ // initiate OMCI TCont related cleanup
+ var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
+ // hence we have to make sure they indicate 'success' on chTpConfigProcessingStep with aProcessingStep
+ if nil != onuTP.runAniConfigFsm(aniEvRemTcontPath, processingStep, aUniID, aTpID) {
+ //even if the FSM invocation did not work we don't indicate a problem within procResult
+ //errors could exist also because there was nothing to delete - so we just accept that as 'deleted'
+ //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
+ return
+ }
+ if !onuTP.waitForTimeoutOrCompletion(ctx, onuTP.chTpConfigProcessingStep, processingStep) {
+ //timeout or error detected
+ logger.Errorw("TCont cleanup aborted - Omci AniSideConfig failed",
+ log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID})
+ //even if the FSM delete execution did not work we don't indicate a problem within procResult
+ //we should never respond to delete with error ...
+ //this issue here means that the AniConfigFsm has not finished successfully
+ //which requires to reset it to allow for new usage, e.g. also on a different UNI
+ //(without that it would be reset on device down indication latest)
+ _ = onuTP.pAniConfigFsm[uniTPKey].pAdaptFsm.pFsm.Event(aniEvReset)
+ //TP related data cleared by FSM error treatment or re-used by FSM error-recovery (if implemented)
+ return
+ }
+ } else {
+ logger.Debugw("uniPonAniConfigFsm TCont cleanup on OMCI skipped based on device state", log.Fields{
+ "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.deviceReason})
+ }
+ //clear the internal store profile data
+ onuTP.clearAniSideConfig(aUniID, aTpID)
+ // reset also the FSM in order to admit a new OMCI configuration in case a new profile is created
+ // FSM stop maybe encapsulated as OnuTP method - perhaps later in context of module splitting
+ _ = onuTP.pAniConfigFsm[uniTPKey].pAdaptFsm.pFsm.Event(aniEvReset)
+ }
+ // generate deviceHandler StatusEvent in case the FSM was not invoked
+ go onuTP.baseDeviceHandler.deviceProcStatusUpdate(OmciAniResourceRemoved)
}
func (onuTP *onuUniTechProf) waitForTimeoutOrCompletion(
@@ -468,85 +667,31 @@
// createUniLockFsm initializes and runs the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
func (onuTP *onuUniTechProf) createAniConfigFsm(aUniID uint8, aTpID uint8,
- apCurrentUniPort *onuUniPort, devEvent OnuDeviceEvent, aProcessingStep uint8) {
+ apCurrentUniPort *onuUniPort, devEvent OnuDeviceEvent, aProcessingStep uint8) error {
logger.Debugw("createAniConfigFsm", log.Fields{"device-id": onuTP.deviceID})
chAniConfigFsm := make(chan Message, 2048)
uniTPKey := uniTP{uniID: aUniID, tpID: aTpID}
pDevEntry := onuTP.baseDeviceHandler.getOnuDeviceEntry(true)
if pDevEntry == nil {
logger.Errorw("No valid OnuDevice - aborting", log.Fields{"device-id": onuTP.deviceID})
- return
+ return fmt.Errorf("no valid OnuDevice: %s", onuTP.deviceID)
}
pAniCfgFsm := newUniPonAniConfigFsm(pDevEntry.PDevOmciCC, apCurrentUniPort, onuTP,
pDevEntry.pOnuDB, aTpID, devEvent,
"AniConfigFsm", onuTP.baseDeviceHandler, chAniConfigFsm)
- if pAniCfgFsm != nil {
- if onuTP.pAniConfigFsm == nil {
- onuTP.pAniConfigFsm = make(map[uniTP]*uniPonAniConfigFsm)
- }
- onuTP.pAniConfigFsm[uniTPKey] = pAniCfgFsm
- onuTP.runAniConfigFsm(aProcessingStep, aUniID, aTpID)
- } else {
+ if pAniCfgFsm == nil {
logger.Errorw("AniConfigFSM could not be created - abort!!", log.Fields{"device-id": onuTP.deviceID})
+ return fmt.Errorf("could not create AniConfigFSM: %s", onuTP.deviceID)
}
-}
-
-// deleteTpResource removes Resources from the ONU's specified Uni
-func (onuTP *onuUniTechProf) deleteTpResource(ctx context.Context,
- aUniID uint8, aPathString string, aResource resourceEntry, aEntryID uint32,
- wg *sync.WaitGroup) {
- defer wg.Done()
- logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
- "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "Resource": aResource})
- tpID, err := GetTpIDFromTpPath(aPathString)
- if err != nil {
- logger.Errorw("error-extracting-tp-id-from-tp-path", log.Fields{"device-id": onuTP.deviceID, "uni-id": aUniID, "path": aPathString})
- return
+ if onuTP.pAniConfigFsm == nil {
+ onuTP.pAniConfigFsm = make(map[uniTP]*uniPonAniConfigFsm)
}
- uniTpKey := uniTP{uniID: aUniID, tpID: tpID}
- if cResourceGemPort == aResource {
- logger.Debugw("remove GemPort from the list of existing ones of the TP", log.Fields{
- "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "entry": aEntryID})
- // check if the requested GemPort exists in the DB
- // check that the TpConfigRequest was done
- // initiate OMCI GemPort related removal
- // remove GemPort from config DB
- // dev reason update? (for the moment not yet done here!)
- } else { //if cResourceTcont == aResource {
- //the TechProfile indicated by path is considered for removal
- // by now we do not clear the OMCI related configuration (to be done later)
- // so we use this position here just to remove the internal stored profile data
- // (needed for checking the existence of the TechProfile after some profile delete)
- // at the oment we only admit 1 TechProfile (T-Cont), so by now we can just remove the only existing TechProfile
- // TODO: To be updated with multi-T-Cont implementation
- logger.Debugw("DeleteTcont clears the existing internal profile", log.Fields{
- "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "Resource": aResource})
-
- onuTP.clearAniSideConfig(aUniID, tpID)
- // reset also the FSM in order to admit a new OMCI configuration in case a new profile is created
- // FSM stop maybe encapsulated as OnuTP method - perhaps later in context of module splitting
- if onuTP.pAniConfigFsm != nil {
- _ = onuTP.pAniConfigFsm[uniTpKey].pAdaptFsm.pFsm.Event(aniEvReset)
- }
-
- //TODO!!! - the real processing could look like that (for starting the removal, where the clearAniSideConfig is done implicitly):
- //delete the given resource from ONU OMCI config and data base - as background routine
- /*
- var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
- go onuTp.deleteAniResource(ctx, processingStep)
- if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
- //timeout or error detected
- return
- }
- */
- }
- //if implemented, the called FSM would generate an adequate event if config has been done,
- // by now we just stimulate this event here as 'done' - TODO!!: to be removed after full implementation
- go onuTP.baseDeviceHandler.deviceProcStatusUpdate(OmciAniResourceRemoved)
+ onuTP.pAniConfigFsm[uniTPKey] = pAniCfgFsm
+ return onuTP.runAniConfigFsm(aniEvStart, aProcessingStep, aUniID, aTpID)
}
// runAniConfigFsm starts the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
-func (onuTP *onuUniTechProf) runAniConfigFsm(aProcessingStep uint8, aUniID uint8, aTpID uint8) {
+func (onuTP *onuUniTechProf) runAniConfigFsm(aEvent string, aProcessingStep uint8, aUniID uint8, aTpID uint8) error {
/* Uni related ANI config procedure -
***** should run via 'aniConfigDone' state and generate the argument requested event *****
*/
@@ -554,26 +699,32 @@
pACStatemachine := onuTP.pAniConfigFsm[uniTpKey].pAdaptFsm.pFsm
if pACStatemachine != nil {
- if pACStatemachine.Is(aniStDisabled) {
- //FSM init requirement to get informed abou FSM completion! (otherwise timeout of the TechProf config)
- onuTP.pAniConfigFsm[uniTpKey].setFsmCompleteChannel(onuTP.chTpConfigProcessingStep, aProcessingStep)
- if err := pACStatemachine.Event(aniEvStart); err != nil {
- logger.Warnw("AniConfigFSM: can't start", log.Fields{"err": err})
+ if aEvent == aniEvStart {
+ if !pACStatemachine.Is(aniStDisabled) {
+ logger.Errorw("wrong state of AniConfigFSM to start - want: Disabled", log.Fields{
+ "have": pACStatemachine.Current(), "device-id": onuTP.deviceID})
// maybe try a FSM reset and then again ... - TODO!!!
- } else {
- /***** AniConfigFSM started */
- logger.Debugw("AniConfigFSM started", log.Fields{
- "state": pACStatemachine.Current(), "device-id": onuTP.deviceID})
+ return fmt.Errorf("wrong state of AniConfigFSM to start: %s", onuTP.deviceID)
}
- } else {
- logger.Warnw("wrong state of AniConfigFSM - want: disabled", log.Fields{
+ } else if !pACStatemachine.Is(aniStConfigDone) {
+ logger.Errorw("wrong state of AniConfigFSM to remove - want: ConfigDone", log.Fields{
"have": pACStatemachine.Current(), "device-id": onuTP.deviceID})
- // maybe try a FSM reset and then again ... - TODO!!!
+ return fmt.Errorf("wrong state of AniConfigFSM to remove: %s", onuTP.deviceID)
}
- } else {
- logger.Errorw("AniConfigFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": onuTP.deviceID})
- // maybe try a FSM reset and then again ... - TODO!!!
+ //FSM init requirement to get informed about FSM completion! (otherwise timeout of the TechProf config)
+ onuTP.pAniConfigFsm[uniTpKey].setFsmCompleteChannel(onuTP.chTpConfigProcessingStep, aProcessingStep)
+ if err := pACStatemachine.Event(aEvent); err != nil {
+ logger.Errorw("AniConfigFSM: can't trigger event", log.Fields{"err": err})
+ return fmt.Errorf("can't trigger event in AniConfigFSM: %s", onuTP.deviceID)
+ }
+ /***** AniConfigFSM event notified */
+ logger.Debugw("AniConfigFSM event notified", log.Fields{
+ "state": pACStatemachine.Current(), "device-id": onuTP.deviceID, "event": aEvent})
+ return nil
}
+ logger.Errorw("AniConfigFSM StateMachine invalid - cannot be executed!!", log.Fields{"device-id": onuTP.deviceID})
+ // maybe try a FSM reset and then again ... - TODO!!!
+ return fmt.Errorf("stateMachine AniConfigFSM invalid: %s", onuTP.deviceID)
}
// clearAniSideConfig deletes internal TechProfile related data connected to the requested UniPort and TpID