[VOL-4018] openonuAdapterGo - adapter crashes during AniG-OMCI-processing
Change-Id: If7702253d6ef24e0b79f8fb15a6b4a64fc27cfb2
diff --git a/VERSION b/VERSION
index 52d1ae8..1f6cc1f 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.0-dev193
+1.3.0-dev194
diff --git a/internal/pkg/onuadaptercore/omci_ani_config.go b/internal/pkg/onuadaptercore/omci_ani_config.go
index c7433c8..423db39 100644
--- a/internal/pkg/onuadaptercore/omci_ani_config.go
+++ b/internal/pkg/onuadaptercore/omci_ani_config.go
@@ -125,6 +125,7 @@
tcont0ID uint16
alloc0ID uint16
gemPortAttribsSlice []ponAniGemPortAttribs
+ mutexPLastTxMeInstance sync.RWMutex
pLastTxMeInstance *me.ManagedEntity
requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
isWaitingForFlowDelete bool
@@ -483,6 +484,8 @@
"EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
oFsm.requestEventOffset = 0 //0 offset for last config request activity
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
@@ -505,6 +508,8 @@
"TpPointer": oFsm.mapperSP0ID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
//accept also nil as (error) return value for writing to LastTx
@@ -523,6 +528,8 @@
"AllocId": oFsm.alloc0ID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
//accept also nil as (error) return value for writing to LastTx
@@ -647,6 +654,8 @@
}(pConfigAniStateAFsm)
}
} else {
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
//accept also nil as (error) return value for writing to LastTx
@@ -715,6 +724,8 @@
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)
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, loGemPortID)
oFsm.pLastTxMeInstance = meInstance
@@ -798,9 +809,11 @@
"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)
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, loGemPortID)
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
// Mark the gem port to be removed for Performance History monitoring
if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(loGemPortID)
@@ -819,6 +832,8 @@
"AllocId": unusedTcontAllocID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
oFsm.pLastTxMeInstance = meInstance
@@ -828,6 +843,8 @@
logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
oFsm.pLastTxMeInstance = meInstance
@@ -837,6 +854,8 @@
logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
oFsm.pLastTxMeInstance = meInstance
@@ -894,6 +913,8 @@
func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+ oFsm.mutexPLastTxMeInstance.Lock()
+ defer oFsm.mutexPLastTxMeInstance.Unlock()
oFsm.pLastTxMeInstance = nil
}
@@ -949,27 +970,45 @@
logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
//if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
- if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
- msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
- // maybe we can use just the same eventName for different state transitions like "forward"
- // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
- switch oFsm.pLastTxMeInstance.GetName() {
- case "Ieee8021PMapperServiceProfile":
- { // let the FSM proceed ...
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
+ oFsm.mutexPLastTxMeInstance.RLock()
+ if oFsm.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ // maybe we can use just the same eventName for different state transitions like "forward"
+ // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "Ieee8021PMapperServiceProfile":
+ { // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
+ }
+ case "MacBridgePortConfigurationData":
+ { // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
+ }
+ case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
+ { // let aniConfig Multi-Id processing proceed by stopping the wait function
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ oFsm.omciMIdsResponseReceived <- true
+ }
+ default:
+ {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
+ }
}
- case "MacBridgePortConfigurationData":
- { // let the FSM proceed ...
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
- }
- case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
- { // let aniConfig Multi-Id processing proceed by stopping the wait function
- oFsm.omciMIdsResponseReceived <- true
- }
+ } else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
}
+ } else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
}
} else {
- logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
+ logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
+ log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
return
}
@@ -995,30 +1034,47 @@
// 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() {
- //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
- // if, then something like:
- //oFsm.pOnuDB.StoreMe(msgObj)
+ oFsm.mutexPLastTxMeInstance.RLock()
+ if oFsm.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
+ // if, then something like:
+ //oFsm.pOnuDB.StoreMe(msgObj)
- switch oFsm.pLastTxMeInstance.GetName() {
- case "TCont":
- { // let the FSM proceed ...
- if oFsm.requestEventOffset == 0 { //from TCont config request
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
- } else { // from T-Cont reset request
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "TCont":
+ { // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ 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", "MulticastGemInterworkingTerminationPoint":
+ { // let the PrioQueue init proceed by stopping the wait function
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ oFsm.omciMIdsResponseReceived <- true
+ }
+ case "Ieee8021PMapperServiceProfile":
+ { // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
+ }
+ default:
+ {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
}
}
- case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
- { // let the PrioQueue init proceed by stopping the wait function
- oFsm.omciMIdsResponseReceived <- true
- }
- case "Ieee8021PMapperServiceProfile":
- { // let the FSM proceed ...
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
- }
+ } else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
}
+ } else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
}
}
@@ -1043,29 +1099,47 @@
// 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)
+ oFsm.mutexPLastTxMeInstance.RLock()
+ if oFsm.pLastTxMeInstance != nil {
+ 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)
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "GemInterworkingTerminationPoint":
+ { // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
+ }
+ case "GemPortNetworkCtp":
+ { // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
+ }
+ case "Ieee8021PMapperServiceProfile":
+ { // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
+ }
+ case "MacBridgePortConfigurationData":
+ { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
+ }
+ default:
+ {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
+ }
}
- 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)
- }
+ } else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
}
+ } else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
}
}
@@ -1117,11 +1191,13 @@
"PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
//verify response
err := oFsm.waitforOmciResponse(ctx)
@@ -1162,9 +1238,11 @@
"GalProfilePointer": galEthernetEID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
true, oFsm.pAdaptFsm.commChan, meParams)
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
//verify response
err := oFsm.waitforOmciResponse(ctx)
if err != nil {
@@ -1189,9 +1267,11 @@
"Ipv4MulticastAddressTable": ipv4MulticastTable,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
oFsm.pLastTxMeInstance = meIPV4MCTableInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
} else {
meParams := me.ParamData{
@@ -1204,11 +1284,13 @@
"GalProfilePointer": galEthernetEID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
}
//verify response
err := oFsm.waitforOmciResponse(ctx)
@@ -1278,11 +1360,13 @@
meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
//verify response
err := oFsm.waitforOmciResponse(ctx)