[VOL-4010] openonuAdapterGo - investigate and resolve data race conditions
Change-Id: I8e957d8bd59b91db27ee4f303a5a222a8f83e8c4
diff --git a/VERSION b/VERSION
index d9acaf8..04bd18f 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.1-dev140
+1.3.1-dev200
diff --git a/internal/pkg/onuadaptercore/alarm_manager.go b/internal/pkg/onuadaptercore/alarm_manager.go
index f2482eb..6bbceb6 100644
--- a/internal/pkg/onuadaptercore/alarm_manager.go
+++ b/internal/pkg/onuadaptercore/alarm_manager.go
@@ -21,15 +21,16 @@
"context"
"errors"
"fmt"
+ "reflect"
+ "sync"
+ "time"
+
"github.com/looplab/fsm"
"github.com/opencord/omci-lib-go"
me "github.com/opencord/omci-lib-go/generated"
"github.com/opencord/voltha-lib-go/v4/pkg/events/eventif"
"github.com/opencord/voltha-lib-go/v4/pkg/log"
"github.com/opencord/voltha-protos/v4/go/voltha"
- "reflect"
- "sync"
- "time"
)
const (
@@ -395,15 +396,17 @@
logger.Debugw(ctx, "alarm-sync-fsm-is-disabled-ignoring-response-message", log.Fields{"device-id": am.pDeviceHandler.deviceID, "data-fields": msgObj})
return
}
+ am.onuAlarmManagerLock.Lock()
am.alarmUploadNoOfCmds = msgObj.NumberOfCommands
+ am.onuAlarmManagerLock.Unlock()
failureTransition := func() {
if err := am.alarmSyncFsm.pFsm.Event(asEvFailure); err != nil {
logger.Debugw(ctx, "alarm-sync-fsm-cannot-go-to-state-failure", log.Fields{"device-id": am.pDeviceHandler.deviceID, "err": err})
}
}
+ am.onuAlarmManagerLock.Lock()
if am.alarmUploadSeqNo < am.alarmUploadNoOfCmds {
// Reset Onu Alarm Sequence
- am.onuAlarmManagerLock.Lock()
am.resetAlarmSequence()
// Get a copy of the alarm bit map db.
for alarms, bitmap := range am.alarmBitMapDB {
@@ -417,7 +420,6 @@
}
} else if am.alarmUploadNoOfCmds == 0 {
// Reset Onu Alarm Sequence
- am.onuAlarmManagerLock.Lock()
am.resetAlarmSequence()
// Get a copy of the alarm bit map db.
for alarms, bitmap := range am.alarmBitMapDB {
@@ -442,6 +444,7 @@
} else {
logger.Errorw(ctx, "invalid-number-of-commands-received", log.Fields{"device-id": am.pDeviceHandler.deviceID,
"upload-no-of-cmds": am.alarmUploadNoOfCmds, "upload-seq-no": am.alarmUploadSeqNo})
+ am.onuAlarmManagerLock.Unlock()
go failureTransition()
}
}
@@ -475,13 +478,16 @@
logger.Debugw(ctx, "alarm-sync-fsm-cannot-go-to-state-failure", log.Fields{"device-id": am.pDeviceHandler.deviceID, "err": err})
}
}
+ am.onuAlarmManagerLock.RLock()
if am.alarmUploadSeqNo < am.alarmUploadNoOfCmds {
+ am.onuAlarmManagerLock.RUnlock()
if err := am.pDeviceHandler.pOnuOmciDevice.PDevOmciCC.sendGetAllAlarmNext(
log.WithSpanFromContext(context.TODO(), ctx), am.pDeviceHandler.pOpenOnuAc.omciTimeout, true); err != nil {
// Transition to failure
go failureTransition()
} //TODO: needs to handle timeouts
} else {
+ am.onuAlarmManagerLock.RUnlock()
if am.isAlarmDBDiffPresent(ctx) {
// transition to resync state
go func() {
@@ -686,7 +692,9 @@
context := make(map[string]string)
intfID := am.getIntfIDAlarm(ctx, classID, instanceID)
onuID := am.pDeviceHandler.deviceID
+ am.pDeviceHandler.pOnuOmciDevice.mutexPersOnuConfig.RLock()
serialNo := am.pDeviceHandler.pOnuOmciDevice.sOnuPersistentData.PersSerialNumber
+ am.pDeviceHandler.pOnuOmciDevice.mutexPersOnuConfig.RUnlock()
if intfID == nil {
logger.Warn(ctx, "intf-id-for-alarm-not-found", log.Fields{"alarm-no": alarm, "class-id": classID})
return
@@ -755,3 +763,26 @@
}
return onuDeviceEvent{}, errors.New("onu Event Detail not found")
}
+
+//ResetAlarmUploadCounters resets alarm upload sequence number and number of commands
+func (am *onuAlarmManager) ResetAlarmUploadCounters() {
+ am.onuAlarmManagerLock.Lock()
+ am.alarmUploadSeqNo = 0
+ am.alarmUploadNoOfCmds = 0
+ am.onuAlarmManagerLock.Unlock()
+}
+
+//IncrementAlarmUploadSeqNo increments alarm upload sequence number
+func (am *onuAlarmManager) IncrementAlarmUploadSeqNo() {
+ am.onuAlarmManagerLock.Lock()
+ am.alarmUploadSeqNo++
+ am.onuAlarmManagerLock.Unlock()
+}
+
+//GetAlarmUploadSeqNo gets alarm upload sequence number
+func (am *onuAlarmManager) GetAlarmUploadSeqNo() uint16 {
+ am.onuAlarmManagerLock.RLock()
+ value := am.alarmUploadSeqNo
+ am.onuAlarmManagerLock.RUnlock()
+ return value
+}
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index 15d8c4e..07fa67b 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -220,7 +220,8 @@
reconcilingFlows bool
mutexReconcilingFlowsFlag sync.RWMutex
chReconcilingFlowsFinished chan bool //channel to indicate that reconciling of flows has been finished
- ReadyForSpecificOmciConfig bool
+ mutexReadyForOmciConfig sync.RWMutex
+ readyForOmciConfig bool
deletionInProgress bool
mutexDeletionInProgressFlag sync.RWMutex
}
@@ -255,7 +256,7 @@
dh.chReconcilingFinished = make(chan bool)
dh.reconcilingFlows = false
dh.chReconcilingFlowsFinished = make(chan bool)
- dh.ReadyForSpecificOmciConfig = false
+ dh.readyForOmciConfig = false
dh.deletionInProgress = false
if dh.device.PmConfigs != nil { // can happen after onu adapter restart
@@ -373,7 +374,7 @@
log.Fields{"device-id": dh.deviceID})
return fmt.Errorf("techProfile DLMsg request while onuTechProf instance not setup: %s", dh.deviceID)
}
- if !dh.ReadyForSpecificOmciConfig {
+ if !dh.isReadyForOmciConfig() {
logger.Errorw(ctx, "TechProf-set rejected: improper device state", log.Fields{"device-id": dh.deviceID,
"device-state": dh.getDeviceReasonString()})
return fmt.Errorf("improper device state %s on device %s", dh.getDeviceReasonString(), dh.deviceID)
@@ -694,7 +695,7 @@
// after the device gets active automatically (and still with its dependency to the TechProfile)
// for state checking compare also code here: processInterAdapterTechProfileDownloadReqMessage
// also abort for the other still possible flows here
- if !dh.ReadyForSpecificOmciConfig {
+ if !dh.isReadyForOmciConfig() {
logger.Errorw(ctx, "flow-add rejected: improper device state", log.Fields{"device-id": dh.deviceID,
"last device-reason": dh.getDeviceReasonString()})
return fmt.Errorf("improper device state on device %s", dh.deviceID)
@@ -736,7 +737,7 @@
//disable-device shall be just a UNi/ONU-G related admin state setting
//all other configurations/FSM's shall not be impacted and shall execute as required by the system
- if dh.ReadyForSpecificOmciConfig {
+ if dh.isReadyForOmciConfig() {
// disable UNI ports/ONU
// *** should generate UniDisableStateDone event - used to disable the port(s) on success
if dh.pLockStateFsm == nil {
@@ -773,7 +774,7 @@
// OnuIndication-Dw (or not active at all) (- disable) - enable: here already the LockFsm may run into timeout (no OmciResponse)
// but that anyway is hopefully resolved by some OnuIndication-Up event (maybe to be tested)
// one could also argue, that a device-enable should also enable attempts for specific omci configuration
- dh.ReadyForSpecificOmciConfig = true //needed to allow subsequent flow/techProf config (on BBSIM)
+ dh.setReadyForOmciConfig(true) //needed to allow subsequent flow/techProf config (on BBSIM)
// enable ONU/UNI ports
// *** should generate UniEnableStateDone event - used to disable the port(s) on success
@@ -803,10 +804,12 @@
return
}
var onuIndication oop.OnuIndication
+ pDevEntry.mutexPersOnuConfig.RLock()
onuIndication.IntfId = pDevEntry.sOnuPersistentData.PersIntfID
onuIndication.OnuId = pDevEntry.sOnuPersistentData.PersOnuID
onuIndication.OperState = pDevEntry.sOnuPersistentData.PersOperState
onuIndication.AdminState = pDevEntry.sOnuPersistentData.PersAdminState
+ pDevEntry.mutexPersOnuConfig.RUnlock()
_ = dh.createInterface(ctx, &onuIndication)
}
@@ -823,8 +826,8 @@
}
dh.pOnuTP.lockTpProcMutex()
defer dh.pOnuTP.unlockTpProcMutex()
- pDevEntry.persUniConfigMutex.RLock()
- defer pDevEntry.persUniConfigMutex.RUnlock()
+ pDevEntry.mutexPersOnuConfig.RLock()
+ defer pDevEntry.mutexPersOnuConfig.RUnlock()
if len(pDevEntry.sOnuPersistentData.PersUniConfig) == 0 {
logger.Debugw(ctx, "reconciling - no uni-configs have been stored before adapter restart - terminate reconcilement",
@@ -894,8 +897,8 @@
}
return
}
- pDevEntry.persUniConfigMutex.RLock()
- defer pDevEntry.persUniConfigMutex.RUnlock()
+ pDevEntry.mutexPersOnuConfig.RLock()
+ defer pDevEntry.mutexPersOnuConfig.RUnlock()
if len(pDevEntry.sOnuPersistentData.PersUniConfig) == 0 {
logger.Debugw(ctx, "reconciling - no uni-configs have been stored before adapter restart - terminate reconcilement",
@@ -1033,7 +1036,7 @@
if err := dh.deviceReasonUpdate(ctx, drRebooting, true); err != nil {
return
}
- dh.ReadyForSpecificOmciConfig = false
+ dh.setReadyForOmciConfig(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
@@ -1053,7 +1056,7 @@
return fmt.Errorf("start Onu SW upgrade rejected: no valid OnuDevice for device-id: %s", dh.deviceID)
}
- if dh.ReadyForSpecificOmciConfig {
+ if dh.isReadyForOmciConfig() {
var inactiveImageID uint16
if inactiveImageID, err = pDevEntry.GetInactiveImageMeID(ctx); err == nil {
dh.lockUpgradeFsm.Lock()
@@ -1434,10 +1437,14 @@
logger.Debugw(ctx, "reconciling - don't notify core about DeviceStateUpdate to ACTIVATING",
log.Fields{"device-id": dh.deviceID})
+ pDevEntry.mutexPersOnuConfig.RLock()
if !pDevEntry.sOnuPersistentData.PersUniUnlockDone {
+ pDevEntry.mutexPersOnuConfig.RUnlock()
logger.Debugw(ctx, "reconciling - uni-ports were not unlocked before adapter restart - resume with a normal start-up",
log.Fields{"device-id": dh.deviceID})
dh.stopReconciling(ctx)
+ } else {
+ pDevEntry.mutexPersOnuConfig.RUnlock()
}
}
// It does not look to me as if makes sense to work with the real core device here, (not the stored clone)?
@@ -1639,7 +1646,7 @@
dh.disableUniPortStateUpdate(ctx)
- dh.ReadyForSpecificOmciConfig = false
+ dh.setReadyForOmciConfig(false)
if err := dh.deviceReasonUpdate(ctx, drStoppingOpenomci, true); err != nil {
// abort: system behavior is just unstable ...
@@ -1849,19 +1856,22 @@
logger.Errorw(ctx, "error starting l2 pm fsm", log.Fields{"device-id": dh.device.Id, "err": err})
}
- dh.ReadyForSpecificOmciConfig = true
+ dh.setReadyForOmciConfig(true)
pDevEntry := dh.getOnuDeviceEntry(ctx, false)
if pDevEntry == nil {
logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
return
}
+ pDevEntry.mutexPersOnuConfig.RLock()
if dh.isReconciling() && pDevEntry.sOnuPersistentData.PersUniDisableDone {
+ pDevEntry.mutexPersOnuConfig.RUnlock()
logger.Debugw(ctx, "reconciling - uni-ports were disabled by admin before adapter restart - keep the ports locked",
log.Fields{"device-id": dh.deviceID})
go dh.reconcileDeviceTechProf(ctx)
// reconcilement will be continued after ani config is done
} else {
+ pDevEntry.mutexPersOnuConfig.RUnlock()
// *** should generate UniUnlockStateDone event *****
if dh.pUnlockStateFsm == nil {
dh.createUniLockFsm(ctx, false, UniUnlockStateDone)
@@ -1884,7 +1894,9 @@
logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
return
}
+ pDevEntry.mutexPersOnuConfig.Lock()
pDevEntry.sOnuPersistentData.PersUniUnlockDone = true
+ pDevEntry.mutexPersOnuConfig.Unlock()
if err := dh.storePersistentData(ctx); err != nil {
logger.Warnw(ctx, "store persistent data error - continue for now as there will be additional write attempts",
log.Fields{"device-id": dh.deviceID, "err": err})
@@ -1918,7 +1930,9 @@
logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
return
}
+ pDevEntry.mutexPersOnuConfig.Lock()
pDevEntry.sOnuPersistentData.PersUniDisableDone = true
+ pDevEntry.mutexPersOnuConfig.Unlock()
if err := dh.storePersistentData(ctx); err != nil {
logger.Warnw(ctx, "store persistent data error - continue for now as there will be additional write attempts",
log.Fields{"device-id": dh.deviceID, "err": err})
@@ -1947,7 +1961,9 @@
logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
return
}
+ pDevEntry.mutexPersOnuConfig.Lock()
pDevEntry.sOnuPersistentData.PersUniDisableDone = false
+ pDevEntry.mutexPersOnuConfig.Unlock()
if err := dh.storePersistentData(ctx); err != nil {
logger.Warnw(ctx, "store persistent data error - continue for now as there will be additional write attempts",
log.Fields{"device-id": dh.deviceID, "err": err})
@@ -3275,3 +3291,16 @@
dh.mutexReconcilingFlowsFlag.RUnlock()
return value
}
+
+func (dh *deviceHandler) setReadyForOmciConfig(flagValue bool) {
+ dh.mutexReadyForOmciConfig.Lock()
+ dh.readyForOmciConfig = flagValue
+ dh.mutexReadyForOmciConfig.Unlock()
+}
+
+func (dh *deviceHandler) isReadyForOmciConfig() bool {
+ dh.mutexReadyForOmciConfig.RLock()
+ flagValue := dh.readyForOmciConfig
+ dh.mutexReadyForOmciConfig.RUnlock()
+ return flagValue
+}
diff --git a/internal/pkg/onuadaptercore/mib_download.go b/internal/pkg/onuadaptercore/mib_download.go
index 3a729a6..148291c 100644
--- a/internal/pkg/onuadaptercore/mib_download.go
+++ b/internal/pkg/onuadaptercore/mib_download.go
@@ -45,10 +45,12 @@
func (onuDeviceEntry *OnuDeviceEntry) enterCreatingGalState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibDownload FSM", log.Fields{"Tx create::GAL Ethernet Profile in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Lock()
meInstance, err := onuDeviceEntry.PDevOmciCC.sendCreateGalEthernetProfile(log.WithSpanFromContext(context.TODO(), ctx), onuDeviceEntry.pOpenOnuAc.omciTimeout, true)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
if err != nil {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "GalEthernetProfile create failed, aborting MibDownload FSM!",
log.Fields{"device-id": onuDeviceEntry.deviceID})
pMibDlFsm := onuDeviceEntry.pMibDownloadFsm
@@ -60,15 +62,18 @@
return
}
onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
}
func (onuDeviceEntry *OnuDeviceEntry) enterSettingOnu2gState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibDownload FSM", log.Fields{"Tx Set::ONU2-G in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Lock()
meInstance, err := onuDeviceEntry.PDevOmciCC.sendSetOnu2g(log.WithSpanFromContext(context.TODO(), ctx),
onuDeviceEntry.pOpenOnuAc.omciTimeout, true)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
if err != nil {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "ONU2-G set failed, aborting MibDownload FSM!",
log.Fields{"device-id": onuDeviceEntry.deviceID})
pMibDlFsm := onuDeviceEntry.pMibDownloadFsm
@@ -80,6 +85,7 @@
return
}
onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
}
func (onuDeviceEntry *OnuDeviceEntry) enterBridgeInitState(ctx context.Context, e *fsm.Event) {
@@ -163,94 +169,131 @@
logger.Debugw(ctx, "End MibDownload Msg processing", log.Fields{"for device-id": onuDeviceEntry.deviceID})
}
+func (onuDeviceEntry *OnuDeviceEntry) handleOmciMibDownloadCreateResponseMessage(ctx context.Context, msg OmciMessage) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.CreateResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success && msgObj.Result != me.InstanceExists {
+ logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": onuDeviceEntry.deviceID, "Error": msgObj.Result})
+ // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ return
+ }
+ // maybe there is a way of pushing the specific create response type generally to the FSM
+ // and let the FSM verify, if the response was according to current state
+ // and possibly store the element to DB and progress - maybe some future option ...
+ // but as that is not straightforward to me I insert the type checkes manually here
+ // and feed the FSM with only 'pre-defined' events ...
+
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RLock()
+ if onuDeviceEntry.PDevOmciCC.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetEntityID() {
+ //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
+ // if, then something like:
+ //onuDeviceEntry.pOnuDB.StoreMe(msgObj)
+
+ // 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 onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetName() {
+ case "GalEthernetProfile":
+ { // let the FSM proceed ...
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ _ = onuDeviceEntry.pMibDownloadFsm.pFsm.Event(dlEvRxGalResp)
+ }
+ case "MacBridgeServiceProfile",
+ "MacBridgePortConfigurationData",
+ "ExtendedVlanTaggingOperationConfigurationData":
+ { // let bridge init proceed by stopping the wait function
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ onuDeviceEntry.omciMessageReceived <- true
+ }
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetName(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ }
+ }
+ } else {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ }
+ } else {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ logger.Errorw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ }
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) handleOmciMibDownloadSetResponseMessage(ctx context.Context, msg OmciMessage) {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
+ if msgLayer == nil {
+ logger.Errorw(ctx, "Omci Msg layer could not be detected for SetResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.SetResponse)
+ if !msgOk {
+ logger.Errorw(ctx, "Omci Msg layer could not be assigned for SetResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ return
+ }
+ logger.Debugw(ctx, "SetResponse Data", log.Fields{"device-id": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success {
+ logger.Errorw(ctx, "Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": onuDeviceEntry.deviceID,
+ "Error": msgObj.Result})
+ // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ return
+ }
+ // compare comments above for CreateResponse (apply also here ...)
+
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RLock()
+ if onuDeviceEntry.PDevOmciCC.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetEntityID() {
+ //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
+ // if, then something like:
+ //onuDeviceEntry.pOnuDB.StoreMe(msgObj)
+
+ switch onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetName() {
+ case "Onu2G":
+ { // let the FSM proceed ...
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ _ = onuDeviceEntry.pMibDownloadFsm.pFsm.Event(dlEvRxOnu2gResp)
+ }
+ //so far that was the only MibDownlad Set Element ...
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetName(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ }
+
+ }
+ } else {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ }
+ } else {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.RUnlock()
+ logger.Errorw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ }
+}
+
func (onuDeviceEntry *OnuDeviceEntry) handleOmciMibDownloadMessage(ctx context.Context, msg OmciMessage) {
logger.Debugw(ctx, "Rx OMCI MibDownload Msg", log.Fields{"device-id": onuDeviceEntry.deviceID,
"msgType": msg.OmciMsg.MessageType})
switch msg.OmciMsg.MessageType {
case omci.CreateResponseType:
- {
- msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
- if msgLayer == nil {
- logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
- return
- }
- msgObj, msgOk := msgLayer.(*omci.CreateResponse)
- if !msgOk {
- logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
- return
- }
- logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": onuDeviceEntry.deviceID, "data-fields": msgObj})
- if msgObj.Result != me.Success && msgObj.Result != me.InstanceExists {
- logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": onuDeviceEntry.deviceID, "Error": msgObj.Result})
- // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
- return
- }
- // maybe there is a way of pushing the specific create response type generally to the FSM
- // and let the FSM verify, if the response was according to current state
- // and possibly store the element to DB and progress - maybe some future option ...
- // but as that is not straightforward to me I insert the type checkes manually here
- // and feed the FSM with only 'pre-defined' events ...
- if msgObj.EntityClass == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetClassID() &&
- msgObj.EntityInstance == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetEntityID() {
- //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
- // if, then something like:
- //onuDeviceEntry.pOnuDB.StoreMe(msgObj)
-
- // 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 onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetName() {
- case "GalEthernetProfile":
- { // let the FSM proceed ...
- _ = onuDeviceEntry.pMibDownloadFsm.pFsm.Event(dlEvRxGalResp)
- }
- case "MacBridgeServiceProfile",
- "MacBridgePortConfigurationData",
- "ExtendedVlanTaggingOperationConfigurationData":
- { // let bridge init proceed by stopping the wait function
- onuDeviceEntry.omciMessageReceived <- true
- }
- }
- }
- } //CreateResponseType
+ onuDeviceEntry.handleOmciMibDownloadCreateResponseMessage(ctx, msg)
//TODO
// onuDeviceEntry.pMibDownloadFsm.pFsm.Event("rx_evtocd_resp")
-
case omci.SetResponseType:
- {
- msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
- if msgLayer == nil {
- logger.Errorw(ctx, "Omci Msg layer could not be detected for SetResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
- return
- }
- msgObj, msgOk := msgLayer.(*omci.SetResponse)
- if !msgOk {
- logger.Errorw(ctx, "Omci Msg layer could not be assigned for SetResponse", log.Fields{"device-id": onuDeviceEntry.deviceID})
- return
- }
- logger.Debugw(ctx, "SetResponse Data", log.Fields{"device-id": onuDeviceEntry.deviceID, "data-fields": msgObj})
- if msgObj.Result != me.Success {
- logger.Errorw(ctx, "Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": onuDeviceEntry.deviceID,
- "Error": msgObj.Result})
- // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
- return
- }
- // compare comments above for CreateResponse (apply also here ...)
- if msgObj.EntityClass == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetClassID() &&
- msgObj.EntityInstance == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetEntityID() {
- //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
- // if, then something like:
- //onuDeviceEntry.pOnuDB.StoreMe(msgObj)
-
- switch onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetName() {
- case "Onu2G":
- { // let the FSM proceed ...
- _ = onuDeviceEntry.pMibDownloadFsm.pFsm.Event(dlEvRxOnu2gResp)
- }
- //so far that was the only MibDownlad Set Element ...
- }
- }
- } //SetResponseType
+ onuDeviceEntry.handleOmciMibDownloadSetResponseMessage(ctx, msg)
default:
{
logger.Errorw(ctx, "Rx OMCI MibDownload unhandled MsgType", log.Fields{"device-id": onuDeviceEntry.deviceID,
@@ -266,14 +309,17 @@
"device-id": onuDeviceEntry.deviceID, "for PortNo": uniNo})
//create MBSP
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Lock()
meInstance, err := onuDeviceEntry.PDevOmciCC.sendCreateMBServiceProfile(
log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.pOpenOnuAc.omciTimeout, true)
if err != nil {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "MBServiceProfile create failed, aborting MibDownload FSM!", log.Fields{"device-id": onuDeviceEntry.deviceID})
_ = onuDeviceEntry.pMibDownloadFsm.pFsm.Event(dlEvReset)
return
}
onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
//verify response
err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
if err != nil {
@@ -284,15 +330,18 @@
}
//create MBPCD
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Lock()
meInstance, err = onuDeviceEntry.PDevOmciCC.sendCreateMBPConfigData(
log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.pOpenOnuAc.omciTimeout, true)
if err != nil {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "MBPConfigData create failed, aborting MibDownload FSM!",
log.Fields{"device-id": onuDeviceEntry.deviceID})
_ = onuDeviceEntry.pMibDownloadFsm.pFsm.Event(dlEvReset)
return
}
onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
//verify response
err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
if err != nil {
@@ -303,15 +352,18 @@
}
//create EVTOCD
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Lock()
meInstance, err = onuDeviceEntry.PDevOmciCC.sendCreateEVTOConfigData(
log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.pOpenOnuAc.omciTimeout, true)
if err != nil {
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "EVTOConfigData create failed, aborting MibDownload FSM!",
log.Fields{"device-id": onuDeviceEntry.deviceID})
_ = onuDeviceEntry.pMibDownloadFsm.pFsm.Event(dlEvReset)
return
}
onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+ onuDeviceEntry.PDevOmciCC.mutexPLastTxMeInstance.Unlock()
//verify response
err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
if err != nil {
diff --git a/internal/pkg/onuadaptercore/mib_sync.go b/internal/pkg/onuadaptercore/mib_sync.go
index 2aa4ec1..29e0a2a 100644
--- a/internal/pkg/onuadaptercore/mib_sync.go
+++ b/internal/pkg/onuadaptercore/mib_sync.go
@@ -86,21 +86,25 @@
oo.devState = DeviceStatusInit
}
logger.Debugw(ctx, "MibSync FSM", log.Fields{"send mibReset in State": e.FSM.Current(), "device-id": oo.deviceID})
+ oo.mutexLastTxParamStruct.Lock()
_ = oo.PDevOmciCC.sendMibReset(log.WithSpanFromContext(context.TODO(), ctx), oo.pOpenOnuAc.omciTimeout, true)
//TODO: needs to handle timeouts
//even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
// that the lastTxMessageType is correctly set to avoid misinterpreting other responses
oo.lastTxParamStruct.lastTxMessageType = omci.MibResetRequestType
oo.lastTxParamStruct.repeatCount = 0
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) enterGettingVendorAndSerialState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting VendorId and SerialNumber in State": e.FSM.Current(), "device-id": oo.deviceID})
requestedAttributes := me.AttributeValueMap{"VendorId": "", "SerialNumber": 0}
+ oo.mutexLastTxParamStruct.Lock()
meInstance, err := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.OnuGClassID, onugMeID, requestedAttributes, oo.pOpenOnuAc.omciTimeout, true, oo.pMibUploadFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
logger.Errorw(ctx, "ONU-G get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
pMibUlFsm := oo.pMibUploadFsm
if pMibUlFsm != nil {
@@ -112,15 +116,18 @@
}
oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) enterGettingEquipmentIDState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting EquipmentId in State": e.FSM.Current(), "device-id": oo.deviceID})
requestedAttributes := me.AttributeValueMap{"EquipmentId": ""}
+ oo.mutexLastTxParamStruct.Lock()
meInstance, err := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.Onu2GClassID, onu2gMeID, requestedAttributes, oo.pOpenOnuAc.omciTimeout, true, oo.pMibUploadFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
logger.Errorw(ctx, "ONU2-G get failed, aborting MibSync FSM!", log.Fields{"device-id": oo.deviceID})
pMibUlFsm := oo.pMibUploadFsm
if pMibUlFsm != nil {
@@ -132,15 +139,18 @@
}
oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) enterGettingFirstSwVersionState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting IsActive and Version of first SW-image in State": e.FSM.Current(), "device-id": oo.deviceID})
requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
+ oo.mutexLastTxParamStruct.Lock()
meInstance, err := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, firstSwImageMeID, requestedAttributes, oo.pOpenOnuAc.omciTimeout, true, oo.pMibUploadFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
logger.Errorw(ctx, "SoftwareImage get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
pMibUlFsm := oo.pMibUploadFsm
if pMibUlFsm != nil {
@@ -152,15 +162,18 @@
}
oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) enterGettingSecondSwVersionState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting IsActive and Version of second SW-image in State": e.FSM.Current(), "device-id": oo.deviceID})
requestedAttributes := me.AttributeValueMap{"IsCommitted": 0, "IsActive": 0, "Version": ""}
+ oo.mutexLastTxParamStruct.Lock()
meInstance, err := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.SoftwareImageClassID, secondSwImageMeID, requestedAttributes, oo.pOpenOnuAc.omciTimeout, true, oo.pMibUploadFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
logger.Errorw(ctx, "SoftwareImage get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
pMibUlFsm := oo.pMibUploadFsm
if pMibUlFsm != nil {
@@ -172,15 +185,18 @@
}
oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) enterGettingMacAddressState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start getting MacAddress in State": e.FSM.Current(), "device-id": oo.deviceID})
requestedAttributes := me.AttributeValueMap{"MacAddress": ""}
+ oo.mutexLastTxParamStruct.Lock()
meInstance, err := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx), me.IpHostConfigDataClassID, ipHostConfigDataMeID, requestedAttributes, oo.pOpenOnuAc.omciTimeout, true, oo.pMibUploadFsm.commChan)
//accept also nil as (error) return value for writing to LastTx
// - this avoids misinterpretation of new received OMCI messages
if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
logger.Errorw(ctx, "IpHostConfigData get failed, aborting MibSync FSM", log.Fields{"device-id": oo.deviceID})
pMibUlFsm := oo.pMibUploadFsm
if pMibUlFsm != nil {
@@ -192,12 +208,15 @@
}
oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) enterGettingMibTemplateState(ctx context.Context, e *fsm.Event) {
if oo.onuSwImageIndications.activeEntityEntry.valid {
+ oo.mutexPersOnuConfig.Lock()
oo.sOnuPersistentData.PersActiveSwVersion = oo.onuSwImageIndications.activeEntityEntry.version
+ oo.mutexPersOnuConfig.Unlock()
} else {
logger.Errorw(ctx, "get-mib-template: no active SW version found, working with empty SW version, which might be untrustworthy",
log.Fields{"device-id": oo.deviceID})
@@ -235,7 +254,9 @@
_ = oo.PDevOmciCC.sendMibUpload(log.WithSpanFromContext(context.TODO(), ctx), oo.pOpenOnuAc.omciTimeout, true)
//even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
// that the lastTxMessageType is correctly set to avoid misinterpreting other responses
+ oo.mutexLastTxParamStruct.Lock()
oo.lastTxParamStruct.lastTxMessageType = omci.MibUploadRequestType
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) enterUploadDoneState(ctx context.Context, e *fsm.Event) {
@@ -247,7 +268,9 @@
}
func (oo *OnuDeviceEntry) enterInSyncState(ctx context.Context, e *fsm.Event) {
+ oo.mutexPersOnuConfig.Lock()
oo.sOnuPersistentData.PersMibLastDbSync = uint32(time.Now().Unix())
+ oo.mutexPersOnuConfig.Unlock()
if oo.mibAuditInterval > 0 {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"trigger next Audit in State": e.FSM.Current(), "oo.mibAuditInterval": oo.mibAuditInterval, "device-id": oo.deviceID})
go func() {
@@ -282,7 +305,7 @@
oo.baseDeviceHandler.startReconciling(ctx, true)
oo.baseDeviceHandler.addAllUniPorts(ctx)
oo.baseDeviceHandler.setDeviceReason(drInitialMibDownloaded)
- oo.baseDeviceHandler.ReadyForSpecificOmciConfig = true
+ oo.baseDeviceHandler.setReadyForOmciConfig(true)
// no need to reconcile additional data for MibDownloadFsm, LockStateFsm, or UnlockStateFsm
oo.baseDeviceHandler.reconcileDeviceTechProf(ctx)
@@ -315,10 +338,13 @@
}()
oo.baseDeviceHandler.reconcileDeviceFlowConfig(ctx)
+ oo.mutexPersOnuConfig.RLock()
if oo.sOnuPersistentData.PersUniDisableDone {
+ oo.mutexPersOnuConfig.RUnlock()
oo.baseDeviceHandler.disableUniPortStateUpdate(ctx)
oo.baseDeviceHandler.setDeviceReason(drOmciAdminLock)
} else {
+ oo.mutexPersOnuConfig.RUnlock()
oo.baseDeviceHandler.enableUniPortStateUpdate(ctx)
}
} else {
@@ -414,7 +440,9 @@
if msgOk {
logger.Debugw(ctx, "MibResetResponse Data", log.Fields{"data-fields": msgObj})
if msgObj.Result == me.Success {
+ oo.mutexPersOnuConfig.Lock()
oo.sOnuPersistentData.PersMibDataSyncAdpt = 0
+ oo.mutexPersOnuConfig.Unlock()
// trigger retrieval of VendorId and SerialNumber
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetVendorAndSerial)
return
@@ -430,20 +458,24 @@
//in case the last request was MdsGetRequest this issue may appear if the ONU was online before and has received the MIB reset
// with Sequence number 0x8000 as last request before - so it may still respond to that
// then we may force the ONU to react on the MdsGetRequest with a new message that uses an increased Sequence number
+ oo.mutexLastTxParamStruct.Lock()
if oo.lastTxParamStruct.lastTxMessageType == omci.GetRequestType && oo.lastTxParamStruct.repeatCount == 0 {
logger.Debugw(ctx, "MibSync FSM - repeat MdsGetRequest (updated SequenceNumber)", log.Fields{"device-id": oo.deviceID})
requestedAttributes := me.AttributeValueMap{"MibDataSync": ""}
_, err := oo.PDevOmciCC.sendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
me.OnuDataClassID, onuDataMeID, requestedAttributes, oo.pOpenOnuAc.omciTimeout, true, oo.pMibUploadFsm.commChan)
if err != nil {
+ oo.mutexLastTxParamStruct.Unlock()
logger.Errorw(ctx, "ONUData get failed, aborting MibSync", log.Fields{"device-id": oo.deviceID})
_ = oo.pMibUploadFsm.pFsm.Event(ulEvStop)
return
}
//TODO: needs extra handling of timeouts
oo.lastTxParamStruct.repeatCount = 1
+ oo.mutexLastTxParamStruct.Unlock()
return
}
+ oo.mutexLastTxParamStruct.Unlock()
logger.Errorw(ctx, "unexpected MibResetResponse - ignoring", log.Fields{"device-id": oo.deviceID})
//perhaps some still lingering message from some prior activity, let's wait for the real response
return
@@ -470,7 +502,9 @@
_ = oo.PDevOmciCC.sendMibUploadNext(log.WithSpanFromContext(context.TODO(), ctx), oo.pOpenOnuAc.omciTimeout, true)
//even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
// that the lastTxMessageType is correctly set to avoid misinterpreting other responses
+ oo.mutexLastTxParamStruct.Lock()
oo.lastTxParamStruct.lastTxMessageType = omci.MibUploadNextRequestType
+ oo.mutexLastTxParamStruct.Unlock()
} else {
logger.Errorw(ctx, "Invalid number of commands received for:", log.Fields{"device-id": oo.deviceID, "uploadNoOfCmds": oo.PDevOmciCC.uploadNoOfCmds})
//TODO right action?
@@ -506,7 +540,9 @@
_ = oo.PDevOmciCC.sendMibUploadNext(log.WithSpanFromContext(context.TODO(), ctx), oo.pOpenOnuAc.omciTimeout, true)
//even though lastTxParameters are currently not used for checking the ResetResponse message we have to ensure
// that the lastTxMessageType is correctly set to avoid misinterpreting other responses
+ oo.mutexLastTxParamStruct.Lock()
oo.lastTxParamStruct.lastTxMessageType = omci.MibUploadNextRequestType
+ oo.mutexLastTxParamStruct.Unlock()
} else {
oo.pOnuDB.logMeDb(ctx)
err := oo.createAndPersistMibTemplate(ctx)
@@ -521,6 +557,7 @@
func (oo *OnuDeviceEntry) handleOmciGetResponseMessage(ctx context.Context, msg OmciMessage) error {
var err error = nil
+ oo.mutexLastTxParamStruct.RLock()
if oo.lastTxParamStruct.lastTxMessageType != omci.GetRequestType ||
oo.lastTxParamStruct.pLastTxMeInstance == nil {
//in case the last request was MibReset this issue may appear if the ONU was online before and has received the MDS GetRequest
@@ -531,12 +568,15 @@
_ = oo.PDevOmciCC.sendMibReset(log.WithSpanFromContext(context.TODO(), ctx), oo.pOpenOnuAc.omciTimeout, true)
//TODO: needs extra handling of timeouts
oo.lastTxParamStruct.repeatCount = 1
+ oo.mutexLastTxParamStruct.RUnlock()
return nil
}
+ oo.mutexLastTxParamStruct.RUnlock()
logger.Warnw(ctx, "unexpected GetResponse - ignoring", log.Fields{"device-id": oo.deviceID})
//perhaps some still lingering message from some prior activity, let's wait for the real response
return nil
}
+ oo.mutexLastTxParamStruct.RUnlock()
msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
if msgLayer == nil {
logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling of MibSyncChan stopped", log.Fields{"device-id": oo.deviceID})
@@ -551,6 +591,7 @@
}
logger.Debugw(ctx, "MibSync FSM - GetResponse Data", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
if msgObj.Result == me.Success {
+ oo.mutexLastTxParamStruct.RLock()
entityID := oo.lastTxParamStruct.pLastTxMeInstance.GetEntityID()
if msgObj.EntityClass == oo.lastTxParamStruct.pLastTxMeInstance.GetClassID() && msgObj.EntityInstance == entityID {
meAttributes := msgObj.Attributes
@@ -558,6 +599,8 @@
logger.Debugf(ctx, "MibSync FSM - GetResponse Data for %s", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, meInstance)
switch meInstance {
case "OnuG":
+ oo.mutexLastTxParamStruct.RUnlock()
+ oo.mutexPersOnuConfig.Lock()
oo.sOnuPersistentData.PersVendorID = trimStringFromInterface(meAttributes["VendorId"])
snBytes, _ := me.InterfaceToOctets(meAttributes["SerialNumber"])
if onugSerialNumberLen == len(snBytes) {
@@ -570,17 +613,22 @@
logger.Infow(ctx, "MibSync FSM - SerialNumber has wrong length - fill serialNumber with zeros", log.Fields{"device-id": oo.deviceID, "length": len(snBytes)})
oo.sOnuPersistentData.PersSerialNumber = cEmptySerialNumberString
}
+ oo.mutexPersOnuConfig.Unlock()
// trigger retrieval of EquipmentId
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetEquipmentID)
return nil
case "Onu2G":
+ oo.mutexLastTxParamStruct.RUnlock()
+ oo.mutexPersOnuConfig.Lock()
oo.sOnuPersistentData.PersEquipmentID = trimStringFromInterface(meAttributes["EquipmentId"])
logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu2-G - EquipmentId", log.Fields{"device-id": oo.deviceID,
"onuDeviceEntry.equipmentID": oo.sOnuPersistentData.PersEquipmentID})
+ oo.mutexPersOnuConfig.Unlock()
// trigger retrieval of 1st SW-image info
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetFirstSwVersion)
return nil
case "SoftwareImage":
+ oo.mutexLastTxParamStruct.RUnlock()
if entityID > secondSwImageMeID {
logger.Errorw(ctx, "mibSync FSM - Failed to GetResponse Data for SoftwareImage with expected EntityId",
log.Fields{"device-id": oo.deviceID, "entity-ID": entityID})
@@ -591,7 +639,9 @@
oo.handleSwImageIndications(ctx, entityID, meAttributes)
return nil
case "IpHostConfigData":
+ oo.mutexLastTxParamStruct.RUnlock()
macBytes, _ := me.InterfaceToOctets(meAttributes["MacAddress"])
+ oo.mutexPersOnuConfig.Lock()
if omciMacAddressLen == len(macBytes) {
oo.sOnuPersistentData.PersMacAddress = hex.EncodeToString(macBytes[:])
logger.Debugw(ctx, "MibSync FSM - GetResponse Data for IpHostConfigData - MacAddress", log.Fields{"device-id": oo.deviceID,
@@ -600,15 +650,24 @@
logger.Infow(ctx, "MibSync FSM - MacAddress wrong length - fill macAddress with zeros", log.Fields{"device-id": oo.deviceID, "length": len(macBytes)})
oo.sOnuPersistentData.PersMacAddress = cEmptyMacAddrString
}
+ oo.mutexPersOnuConfig.Unlock()
// trigger retrieval of mib template
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetMibTemplate)
return nil
case "OnuData":
+ oo.mutexLastTxParamStruct.RUnlock()
oo.checkMdsValue(ctx, meAttributes["MibDataSync"].(uint8))
return nil
+ default:
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": meInstance, "device-id": oo.deviceID})
+
}
} else {
- logger.Warnf(ctx, "MibSync FSM - Received GetResponse Data for %s with wrong classID or entityID ", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, msgObj.EntityClass)
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnf(ctx, "MibSync FSM - Received GetResponse Data for %s with wrong classID or entityID ",
+ log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, msgObj.EntityClass)
}
} else {
if err = oo.handleOmciGetResponseErrors(ctx, msgObj); err == nil {
@@ -624,9 +683,11 @@
imageIsCommitted := meAttributes["IsCommitted"].(uint8)
imageIsActive := meAttributes["IsActive"].(uint8)
imageVersion := trimStringFromInterface(meAttributes["Version"])
+ oo.mutexPersOnuConfig.RLock()
logger.Infow(ctx, "MibSync FSM - GetResponse Data for SoftwareImage",
log.Fields{"device-id": oo.deviceID, "entityID": entityID,
"version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted, "SNR": oo.sOnuPersistentData.PersSerialNumber})
+ oo.mutexPersOnuConfig.RUnlock()
if firstSwImageMeID == entityID {
//always accept the state of the first image (2nd image info should not yet be available)
if imageIsActive == swIsActive {
@@ -718,21 +779,33 @@
logger.Debugf(ctx, "MibSync FSM - erroneous result in GetResponse Data: %s", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, msgObj.Result)
// Up to now the following erroneous results have been seen for different ONU-types to indicate an unsupported ME
if msgObj.Result == me.UnknownInstance || msgObj.Result == me.UnknownEntity || msgObj.Result == me.ProcessingError || msgObj.Result == me.NotSupported {
- entityID := oo.lastTxParamStruct.pLastTxMeInstance.GetEntityID()
- if msgObj.EntityClass == oo.lastTxParamStruct.pLastTxMeInstance.GetClassID() && msgObj.EntityInstance == entityID {
- meInstance := oo.lastTxParamStruct.pLastTxMeInstance.GetName()
- switch meInstance {
- case "IpHostConfigData":
- logger.Debugw(ctx, "MibSync FSM - erroneous result for IpHostConfigData received - ONU doesn't support ME - fill macAddress with zeros",
- log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
- oo.sOnuPersistentData.PersMacAddress = cEmptyMacAddrString
- // trigger retrieval of mib template
- _ = oo.pMibUploadFsm.pFsm.Event(ulEvGetMibTemplate)
- return nil
- default:
- logger.Warnf(ctx, "MibSync FSM - erroneous result for %s received - no exceptional treatment defined", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, meInstance)
- err = fmt.Errorf("erroneous result for %s received - no exceptional treatment defined: %s", meInstance, oo.deviceID)
+ oo.mutexLastTxParamStruct.RLock()
+ if oo.lastTxParamStruct.pLastTxMeInstance != nil {
+ entityID := oo.lastTxParamStruct.pLastTxMeInstance.GetEntityID()
+ if msgObj.EntityClass == oo.lastTxParamStruct.pLastTxMeInstance.GetClassID() && msgObj.EntityInstance == entityID {
+ meInstance := oo.lastTxParamStruct.pLastTxMeInstance.GetName()
+ switch meInstance {
+ case "IpHostConfigData":
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Debugw(ctx, "MibSync FSM - erroneous result for IpHostConfigData received - ONU doesn't support ME - fill macAddress with zeros",
+ log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
+ oo.mutexPersOnuConfig.Lock()
+ oo.sOnuPersistentData.PersMacAddress = cEmptyMacAddrString
+ oo.mutexPersOnuConfig.Unlock()
+ // trigger retrieval of mib template
+ _ = oo.pMibUploadFsm.pFsm.Event(ulEvGetMibTemplate)
+ return nil
+ default:
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnf(ctx, "MibSync FSM - erroneous result for %s received - no exceptional treatment defined", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, meInstance)
+ err = fmt.Errorf("erroneous result for %s received - no exceptional treatment defined: %s", meInstance, oo.deviceID)
+ }
+ } else {
+ oo.mutexLastTxParamStruct.RUnlock()
}
+ } else {
+ oo.mutexLastTxParamStruct.RUnlock()
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oo.deviceID})
}
} else {
logger.Errorf(ctx, "MibSync FSM - erroneous result in GetResponse Data: %s", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, msgObj.Result)
@@ -742,6 +815,8 @@
}
func (oo *OnuDeviceEntry) isNewOnu() bool {
+ oo.mutexPersOnuConfig.RLock()
+ defer oo.mutexPersOnuConfig.RUnlock()
return oo.sOnuPersistentData.PersMibLastDbSync == 0
}
@@ -857,16 +932,20 @@
}
return
}
+ oo.mutexLastTxParamStruct.Lock()
oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
oo.lastTxParamStruct.pLastTxMeInstance = meInstance
oo.lastTxParamStruct.repeatCount = 0
+ oo.mutexLastTxParamStruct.Unlock()
}
func (oo *OnuDeviceEntry) checkMdsValue(ctx context.Context, mibDataSyncOnu uint8) {
+ oo.mutexPersOnuConfig.RLock()
logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu-Data - MibDataSync", log.Fields{"device-id": oo.deviceID,
"mibDataSyncOnu": mibDataSyncOnu, "PersMibDataSyncAdpt": oo.sOnuPersistentData.PersMibDataSyncAdpt})
mdsValuesAreEqual := oo.sOnuPersistentData.PersMibDataSyncAdpt == mibDataSyncOnu
+ oo.mutexPersOnuConfig.RUnlock()
if oo.pMibUploadFsm.pFsm.Is(ulStAuditing) {
if mdsValuesAreEqual {
logger.Debugw(ctx, "MibSync FSM - mib audit - MDS check ok", log.Fields{"device-id": oo.deviceID})
@@ -938,8 +1017,10 @@
// swap out tokens with specific data
mibTmpString, _ := kvstore.ToString(Value.Value)
+ oo.mutexPersOnuConfig.RLock()
mibTmpString2 := strings.Replace(mibTmpString, "%SERIAL_NUMBER%", oo.sOnuPersistentData.PersSerialNumber, -1)
mibTmpString = strings.Replace(mibTmpString2, "%MAC_ADDRESS%", oo.sOnuPersistentData.PersMacAddress, -1)
+ oo.mutexPersOnuConfig.RUnlock()
mibTmpBytes := []byte(mibTmpString)
logger.Debugf(ctx, "MibSync FSM - Mib template tokens swapped out: %s", mibTmpBytes)
diff --git a/internal/pkg/onuadaptercore/omci_ani_config.go b/internal/pkg/onuadaptercore/omci_ani_config.go
index 2453f85..a3df661 100644
--- a/internal/pkg/onuadaptercore/omci_ani_config.go
+++ b/internal/pkg/onuadaptercore/omci_ani_config.go
@@ -121,6 +121,7 @@
pAdaptFsm *AdapterFsm
chSuccess chan<- uint8
procStep uint8
+ mutexChanSet sync.RWMutex
chanSet bool
mapperSP0ID uint16
macBPCD0ID uint16
@@ -243,7 +244,7 @@
func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
oFsm.chSuccess = aChSuccess
oFsm.procStep = aProcStep
- oFsm.chanSet = true
+ oFsm.setChanSet(true)
}
//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
@@ -346,10 +347,10 @@
"device-id": oFsm.deviceID})
} else {
logger.Errorw(ctx, "tech profile id not in valid range", log.Fields{"device-id": oFsm.deviceID, "tp-id": oFsm.techProfileID, "num-tcont": len(tcontInstKeys)})
- if oFsm.chanSet {
+ if oFsm.isChanSet() {
// indicate processing error/abort to the caller
oFsm.chSuccess <- 0
- oFsm.chanSet = false //reset the internal channel state
+ oFsm.setChanSet(false) //reset the internal channel state
}
//reset the state machine to enable usage on subsequent requests
_ = aPAFsm.pFsm.Event(aniEvReset)
@@ -768,12 +769,12 @@
} else {
logger.Debugw(ctx, "reconciling - skip AniConfigDone processing", log.Fields{"device-id": oFsm.deviceID})
}
- if oFsm.chanSet {
+ if oFsm.isChanSet() {
// indicate processing done to the caller
logger.Debugw(ctx, "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
+ oFsm.setChanSet(false) //reset the internal channel state
}
//the FSM is left active in this state as long as no specific reset or remove is requested from outside
@@ -1041,12 +1042,12 @@
"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
//use DeviceHandler event notification directly
oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
- if oFsm.chanSet {
+ if oFsm.isChanSet() {
// indicate processing done to the caller
logger.Debugw(ctx, "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
+ oFsm.setChanSet(false) //reset the internal channel state
}
//let's reset the state machine in order to release all resources now
@@ -1635,3 +1636,16 @@
return fmt.Errorf(cErrWaitAborted)
}
}
+
+func (oFsm *uniPonAniConfigFsm) setChanSet(flagValue bool) {
+ oFsm.mutexChanSet.Lock()
+ oFsm.chanSet = flagValue
+ oFsm.mutexChanSet.Unlock()
+}
+
+func (oFsm *uniPonAniConfigFsm) isChanSet() bool {
+ oFsm.mutexChanSet.RLock()
+ flagValue := oFsm.chanSet
+ oFsm.mutexChanSet.RUnlock()
+ return flagValue
+}
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index b37230b..7a85e4a 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -119,13 +119,14 @@
uploadSequNo uint16
uploadNoOfCmds uint16
- mutexTxQueue sync.Mutex
- txQueue *list.List
- mutexRxSchedMap sync.Mutex
- rxSchedulerMap map[uint16]callbackPairEntry
- mutexMonReq sync.RWMutex
- monitoredRequests map[uint16]omciTransferStructure
- pLastTxMeInstance *me.ManagedEntity
+ mutexTxQueue sync.Mutex
+ txQueue *list.List
+ mutexRxSchedMap sync.Mutex
+ rxSchedulerMap map[uint16]callbackPairEntry
+ mutexMonReq sync.RWMutex
+ monitoredRequests map[uint16]omciTransferStructure
+ mutexPLastTxMeInstance sync.RWMutex
+ pLastTxMeInstance *me.ManagedEntity
}
var responsesWithMibDataSync = []omci.MessageType{
@@ -824,8 +825,7 @@
"Err": err, "device-id": oo.deviceID})
return err
}
- oo.pBaseDeviceHandler.pAlarmMgr.alarmUploadSeqNo = 0
- oo.pBaseDeviceHandler.pAlarmMgr.alarmUploadNoOfCmds = 0
+ oo.pBaseDeviceHandler.pAlarmMgr.ResetAlarmUploadCounters()
omciRxCallbackPair := callbackPair{
cbKey: tid,
@@ -836,7 +836,7 @@
}
func (oo *omciCC) sendGetAllAlarmNext(ctx context.Context, timeout int, highPrio bool) error {
- alarmUploadSeqNo := oo.pBaseDeviceHandler.pAlarmMgr.alarmUploadSeqNo
+ alarmUploadSeqNo := oo.pBaseDeviceHandler.pAlarmMgr.GetAlarmUploadSeqNo()
logger.Debugw(ctx, "send sendGetAllAlarmNext-msg to:", log.Fields{"device-id": oo.deviceID,
"alarmUploadSeqNo": alarmUploadSeqNo})
request := &omci.GetAllAlarmsNextRequest{
@@ -852,7 +852,7 @@
"Err": err, "device-id": oo.deviceID})
return err
}
- oo.pBaseDeviceHandler.pAlarmMgr.alarmUploadSeqNo++
+ oo.pBaseDeviceHandler.pAlarmMgr.IncrementAlarmUploadSeqNo()
omciRxCallbackPair := callbackPair{
cbKey: tid,
diff --git a/internal/pkg/onuadaptercore/omci_test_request.go b/internal/pkg/onuadaptercore/omci_test_request.go
index c08cde9..d11133e 100644
--- a/internal/pkg/onuadaptercore/omci_test_request.go
+++ b/internal/pkg/onuadaptercore/omci_test_request.go
@@ -138,12 +138,14 @@
//TODO!!! further tests on the payload should be done here ...
+ oo.pDevOmciCC.mutexMonReq.RLock()
if _, exist := oo.pDevOmciCC.monitoredRequests[omciMsg.TransactionID]; exist {
oo.pDevOmciCC.monitoredRequests[omciMsg.TransactionID].chSuccess <- true
} else {
logger.Infow(ctx, "reqMon: map entry does not exist!",
log.Fields{"tid": omciMsg.TransactionID, "device-id": oo.deviceID})
}
+ oo.pDevOmciCC.mutexMonReq.RUnlock()
oo.result = true
oo.verifyDone <- true
diff --git a/internal/pkg/onuadaptercore/omci_vlan_config.go b/internal/pkg/onuadaptercore/omci_vlan_config.go
index c0dced5..308d3af 100644
--- a/internal/pkg/onuadaptercore/omci_vlan_config.go
+++ b/internal/pkg/onuadaptercore/omci_vlan_config.go
@@ -171,6 +171,7 @@
numVlanFilterEntries uint8
vlanFilterList [cVtfdTableSize]uint16
evtocdID uint16
+ mutexPLastTxMeInstance sync.RWMutex
pLastTxMeInstance *me.ManagedEntity
requestEventOffset uint8
TpIDWaitingFor uint8
@@ -964,9 +965,11 @@
}
logger.Debugw(ctx, "UniVlanConfigFsm sendcreate VTFD", log.Fields{
"in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "VTFD create failed, aborting UniVlanConfig FSM!",
log.Fields{"device-id": oFsm.deviceID})
pConfigVlanStateAFsm := oFsm.pAdaptFsm
@@ -983,6 +986,7 @@
// send shall return (dual format) error code that can be used here for immediate error treatment
// (relevant to all used sendXX() methods in this (and other) FSM's)
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
}
}
@@ -1144,9 +1148,11 @@
"NumberOfEntries": oFsm.numVlanFilterEntries,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "VTFD create failed, aborting UniVlanConfig FSM!",
log.Fields{"device-id": oFsm.deviceID})
pConfigVlanStateAFsm := oFsm.pAdaptFsm
@@ -1163,6 +1169,7 @@
// send shall return (dual format) error code that can be used here for immediate error treatment
// (relevant to all used sendXX() methods in this (and other) FSM's)
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
} else {
// This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
// this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
@@ -1191,9 +1198,11 @@
"NumberOfEntries": oFsm.numVlanFilterEntries,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "UniVlanFsm create Vlan Tagging Filter ME result error",
log.Fields{"device-id": oFsm.deviceID, "Error": err})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -1205,6 +1214,7 @@
// send shall return (dual format) error code that can be used here for immediate error treatment
// (relevant to all used sendXX() methods in this (and other) FSM's)
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
}
oFsm.mutexFlowParams.Unlock()
//verify response
@@ -1258,7 +1268,7 @@
"device-id": oFsm.deviceID})
pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
- loAllowSpecificOmciConfig := oFsm.pDeviceHandler.ReadyForSpecificOmciConfig
+ loAllowSpecificOmciConfig := oFsm.pDeviceHandler.isReadyForOmciConfig()
loVlanEntryClear := uint8(0)
loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
//shallow copy is sufficient as no reference variables are used within struct
@@ -1284,15 +1294,18 @@
"in state": e.FSM.Current(), "device-id": oFsm.deviceID})
loVlanEntryClear = 1 //full VlanFilter clear request
if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, vtfdID)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "UniVlanFsm delete Vlan Tagging Filter ME result error",
log.Fields{"device-id": oFsm.deviceID, "Error": err})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
return
}
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
} else {
logger.Debugw(ctx, "UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
"device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.getDeviceReasonString()})
@@ -1328,15 +1341,18 @@
if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
// FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, vtfdID)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "UniVlanFsm delete Vlan Tagging Filter ME result error",
log.Fields{"device-id": oFsm.deviceID, "Error": err})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
return
}
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
} else {
logger.Debugw(ctx, "UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
"device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.getDeviceReasonString()})
@@ -1480,7 +1496,9 @@
func (oFsm *UniVlanConfigFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "UniVlanConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
+ oFsm.mutexPLastTxMeInstance.Lock()
oFsm.pLastTxMeInstance = nil
+ oFsm.mutexPLastTxMeInstance.Unlock()
if oFsm.pDeviceHandler != nil {
//TODO: to clarify with improved error treatment for VlanConfigFsm (timeout,reception) errors
// current code removes the complete FSM including all flow/rule configuration done so far
@@ -1574,15 +1592,28 @@
// 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() {
- switch oFsm.pLastTxMeInstance.GetName() {
- case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData", "MulticastOperationsProfile":
- { // let the MultiEntity config proceed by stopping the wait function
- oFsm.omciMIdsResponseReceived <- true
+ oFsm.mutexPLastTxMeInstance.RLock()
+ if oFsm.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData", "MulticastOperationsProfile":
+ { // let the MultiEntity config proceed by stopping the wait function
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ oFsm.omciMIdsResponseReceived <- true
+ return
+ }
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
+ }
}
}
+ } else {
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
}
+ oFsm.mutexPLastTxMeInstance.RUnlock()
} //SetResponseType
case omci.DeleteResponseType:
{ // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
@@ -1623,23 +1654,36 @@
return fmt.Errorf("omci CreateResponse Error for device-id %x",
oFsm.deviceID)
}
- if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
- msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
- // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
- switch oFsm.pLastTxMeInstance.GetName() {
- case "VlanTaggingFilterData", "MulticastOperationsProfile",
- "MulticastSubscriberConfigInfo", "MacBridgePortConfigurationData",
- "ExtendedVlanTaggingOperationConfigurationData":
- {
- if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
- // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
- _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
- } else { // let the MultiEntity config proceed by stopping the wait function
- oFsm.omciMIdsResponseReceived <- true
+ oFsm.mutexPLastTxMeInstance.RLock()
+ if oFsm.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "VlanTaggingFilterData", "MulticastOperationsProfile",
+ "MulticastSubscriberConfigInfo", "MacBridgePortConfigurationData",
+ "ExtendedVlanTaggingOperationConfigurationData":
+ {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
+ // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
+ _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
+ } else { // let the MultiEntity config proceed by stopping the wait function
+ oFsm.omciMIdsResponseReceived <- true
+ }
+ return nil
+ }
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
}
}
}
+ } else {
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
}
+ oFsm.mutexPLastTxMeInstance.RUnlock()
return nil
}
@@ -1666,15 +1710,28 @@
return fmt.Errorf("omci DeleteResponse Error for device-id %x",
oFsm.deviceID)
}
- if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
- msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
- switch oFsm.pLastTxMeInstance.GetName() {
- case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData":
- { // let the MultiEntity config proceed by stopping the wait function
- oFsm.omciMIdsResponseReceived <- true
+ oFsm.mutexPLastTxMeInstance.RLock()
+ if oFsm.pLastTxMeInstance != nil {
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData":
+ { // let the MultiEntity config proceed by stopping the wait function
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ oFsm.omciMIdsResponseReceived <- true
+ return nil
+ }
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
+ }
}
}
+ } else {
+ logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
}
+ oFsm.mutexPLastTxMeInstance.RUnlock()
return nil
}
@@ -1699,9 +1756,11 @@
"AssociatedMePointer": oFsm.pOnuUniPort.entityID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendCreateEvtocdVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
true, oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "CreateEvtocdVar create failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -1710,6 +1769,7 @@
//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)
@@ -1729,10 +1789,12 @@
"DownstreamMode": uint8(cDefaultDownstreamMode),
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err = oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -1741,6 +1803,7 @@
//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)
@@ -1788,10 +1851,12 @@
"ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -1800,6 +1865,7 @@
//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)
@@ -1851,10 +1917,12 @@
"ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -1863,6 +1931,7 @@
//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)
@@ -1910,10 +1979,12 @@
"ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -1922,6 +1993,7 @@
//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)
@@ -1970,10 +2042,12 @@
"ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -1982,6 +2056,7 @@
//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)
@@ -2040,10 +2115,12 @@
"ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2052,6 +2129,7 @@
//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)
@@ -2090,10 +2168,12 @@
"ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2102,6 +2182,7 @@
//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)
@@ -2129,10 +2210,12 @@
meParams := me.ParamData{
EntityID: oFsm.evtocdID,
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendDeleteEvtocd(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "DeleteEvtocdVar delete failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2141,6 +2224,7 @@
//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)
@@ -2243,10 +2327,12 @@
"ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetEvtocdVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2255,6 +2341,7 @@
//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)
@@ -2347,9 +2434,11 @@
"TpPointer": multicastGemPortID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true, oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "MBPConfigDataVar create failed, aborting AniConfig FSM!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2358,6 +2447,7 @@
//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()
err = oFsm.waitforOmciResponse(ctx)
if err != nil {
logger.Errorw(ctx, "CreateMBPConfigData failed, aborting AniConfig FSM!",
@@ -2390,15 +2480,18 @@
"NumberOfEntries": oFsm.numVlanFilterEntries,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err = oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true, oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "CreateVtfdVar create failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
return fmt.Errorf("createMcastVlanFilterData creationError %s, error %s", oFsm.deviceID, err)
}
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
err = oFsm.waitforOmciResponse(ctx)
if err != nil {
logger.Errorw(ctx, "CreateMcastVlanFilterData failed, aborting AniConfig FSM!",
@@ -2427,10 +2520,12 @@
"MulticastOperationsProfilePointer": instID,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendCreateMulticastSubConfigInfoVar(context.TODO(),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "CreateMulticastSubConfigInfoVar create failed, aborting UniVlanConfigFSM!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2440,6 +2535,7 @@
//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)
if err != nil {
@@ -2474,10 +2570,12 @@
"UnauthorizedJoinBehaviour": 0,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendCreateMulticastOperationProfileVar(context.TODO(),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "CreateMulticastOperationProfileVar create failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2486,6 +2584,7 @@
//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)
if err != nil {
@@ -2535,10 +2634,12 @@
"DynamicAccessControlListTable": dynamicAccessCL,
},
}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetMulticastOperationProfileVar(context.TODO(),
oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
oFsm.pAdaptFsm.commChan, meParams)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetMulticastOperationProfileVar set failed, aborting UniVlanConfigFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
@@ -2547,6 +2648,7 @@
//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)
if err != nil {
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index bddd3d5..9544efa 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -261,23 +261,24 @@
// OnuDeviceEntry - ONU device info and FSM events.
type OnuDeviceEntry struct {
- deviceID string
- baseDeviceHandler *deviceHandler
- pOpenOnuAc *OpenONUAC
- coreProxy adapterif.CoreProxy
- adapterProxy adapterif.AdapterProxy
- PDevOmciCC *omciCC
- pOnuDB *onuDeviceDB
- mibTemplateKVStore *db.Backend
- persUniConfigMutex sync.RWMutex
- sOnuPersistentData onuPersistentData
- mibTemplatePath string
- onuKVStoreMutex sync.RWMutex
- onuKVStore *db.Backend
- onuKVStorePath string
- onuKVStoreprocResult error //error indication of processing
- chOnuKvProcessingStep chan uint8
- onuSwImageIndications sSwImageIndications
+ deviceID string
+ baseDeviceHandler *deviceHandler
+ pOpenOnuAc *OpenONUAC
+ coreProxy adapterif.CoreProxy
+ adapterProxy adapterif.AdapterProxy
+ PDevOmciCC *omciCC
+ pOnuDB *onuDeviceDB
+ mibTemplateKVStore *db.Backend
+ mutexPersOnuConfig sync.RWMutex
+ sOnuPersistentData onuPersistentData
+ mibTemplatePath string
+ mutexOnuKVStore sync.RWMutex
+ onuKVStore *db.Backend
+ onuKVStorePath string
+ mutexOnuKVStoreProcResult sync.RWMutex
+ onuKVStoreProcResult error //error indication of processing
+ chOnuKvProcessingStep chan uint8
+ onuSwImageIndications sSwImageIndications
//lockDeviceEntries sync.RWMutex
mibDbClass func(context.Context) error
supportedFsms OmciDeviceFsms
@@ -289,8 +290,9 @@
//mibNextDbResync uint32
// for mibUpload
- pMibUploadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
- lastTxParamStruct sLastTxMeParameter
+ pMibUploadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
+ mutexLastTxParamStruct sync.RWMutex
+ lastTxParamStruct sLastTxMeParameter
// for mibDownload
pMibDownloadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
//remark: general usage of pAdapterFsm would require generalization of commChan usage and internal event setting
@@ -601,13 +603,13 @@
logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
return fmt.Errorf(fmt.Sprintf("onuKVStore-not-set-abort-%s", oo.deviceID))
}
- oo.persUniConfigMutex.Lock()
- defer oo.persUniConfigMutex.Unlock()
+ oo.mutexPersOnuConfig.Lock()
+ defer oo.mutexPersOnuConfig.Unlock()
oo.sOnuPersistentData =
onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval}
- oo.onuKVStoreMutex.RLock()
+ oo.mutexOnuKVStore.RLock()
Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
- oo.onuKVStoreMutex.RUnlock()
+ oo.mutexOnuKVStore.RUnlock()
if err == nil {
if Value != nil {
logger.Debugw(ctx, "ONU-data read",
@@ -636,7 +638,7 @@
if oo.onuKVStore == nil {
logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
- oo.onuKVStoreprocResult = errors.New("onu-data delete aborted: onuKVStore not set")
+ oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: onuKVStore not set"))
return
}
var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
@@ -644,7 +646,7 @@
if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
//timeout or error detected
logger.Debugw(ctx, "ONU-data not deleted - abort", log.Fields{"device-id": oo.deviceID})
- oo.onuKVStoreprocResult = errors.New("onu-data delete aborted: during kv-access")
+ oo.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: during kv-access"))
return
}
}
@@ -653,16 +655,16 @@
logger.Debugw(ctx, "delete and clear internal persistency data", log.Fields{"device-id": oo.deviceID})
- oo.persUniConfigMutex.Lock()
- defer oo.persUniConfigMutex.Unlock()
+ oo.mutexPersOnuConfig.Lock()
+ defer oo.mutexPersOnuConfig.Unlock()
oo.sOnuPersistentData.PersUniConfig = nil //releasing all UniConfig entries to garbage collector default entry
oo.sOnuPersistentData =
onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval}
logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
- oo.onuKVStoreMutex.Lock()
+ oo.mutexOnuKVStore.Lock()
err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)
- oo.onuKVStoreMutex.Unlock()
+ oo.mutexOnuKVStore.Unlock()
if err != nil {
logger.Errorw(ctx, "unable to delete in KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
oo.chOnuKvProcessingStep <- 0 //error indication
@@ -676,7 +678,7 @@
if oo.onuKVStore == nil {
logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
- oo.onuKVStoreprocResult = errors.New("onu-data update aborted: onuKVStore not set")
+ oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: onuKVStore not set"))
return
}
var processingStep uint8 = 1 // used to synchronize the different processing steps with chOnuKvProcessingStep
@@ -684,13 +686,15 @@
if !oo.waitForTimeoutOrCompletion(ctx, oo.chOnuKvProcessingStep, processingStep) {
//timeout or error detected
logger.Debugw(ctx, "ONU-data not written - abort", log.Fields{"device-id": oo.deviceID})
- oo.onuKVStoreprocResult = errors.New("onu-data update aborted: during writing process")
+ oo.setKvProcessingErrorIndication(errors.New("onu-data update aborted: during writing process"))
return
}
}
func (oo *OnuDeviceEntry) storeDataInOnuKvStore(ctx context.Context, aProcessingStep uint8) {
+ oo.mutexPersOnuConfig.Lock()
+ defer oo.mutexPersOnuConfig.Unlock()
//assign values which are not already present when newOnuDeviceEntry() is called
oo.sOnuPersistentData.PersOnuID = oo.baseDeviceHandler.pOnuIndication.OnuId
oo.sOnuPersistentData.PersIntfID = oo.baseDeviceHandler.pOnuIndication.IntfId
@@ -698,8 +702,6 @@
oo.sOnuPersistentData.PersAdminState = oo.baseDeviceHandler.pOnuIndication.AdminState
oo.sOnuPersistentData.PersOperState = oo.baseDeviceHandler.pOnuIndication.OperState
- oo.persUniConfigMutex.RLock()
- defer oo.persUniConfigMutex.RUnlock()
logger.Debugw(ctx, "Update ONU-data in KVStore", log.Fields{"device-id": oo.deviceID, "sOnuPersistentData": oo.sOnuPersistentData})
Value, err := json.Marshal(oo.sOnuPersistentData)
@@ -727,9 +729,9 @@
oo.pOpenOnuAc.lockDeviceHandlersMap.RUnlock()
oo.baseDeviceHandler.mutexDeletionInProgressFlag.RUnlock()
- oo.onuKVStoreMutex.Lock()
+ oo.mutexOnuKVStore.Lock()
err = oo.onuKVStore.Put(ctx, oo.onuKVStorePath, Value)
- oo.onuKVStoreMutex.Unlock()
+ oo.mutexOnuKVStore.Unlock()
if err != nil {
logger.Errorw(ctx, "unable to write ONU-data into KVstore", log.Fields{"device-id": oo.deviceID, "err": err})
oo.chOnuKvProcessingStep <- 0 //error indication
@@ -743,8 +745,8 @@
as also the complete sequence is ensured to 'run to completion' before some new request is accepted
no specific concurrency protection to sOnuPersistentData is required here
*/
- oo.persUniConfigMutex.Lock()
- defer oo.persUniConfigMutex.Unlock()
+ oo.mutexPersOnuConfig.Lock()
+ defer oo.mutexPersOnuConfig.Unlock()
for k, v := range oo.sOnuPersistentData.PersUniConfig {
if v.PersUniID == aUniID {
@@ -808,8 +810,8 @@
func (oo *OnuDeviceEntry) updateOnuUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]uniVlanFlowParams) {
- oo.persUniConfigMutex.Lock()
- defer oo.persUniConfigMutex.Unlock()
+ oo.mutexPersOnuConfig.Lock()
+ defer oo.mutexPersOnuConfig.Unlock()
for k, v := range oo.sOnuPersistentData.PersUniConfig {
if v.PersUniID == aUniID {
@@ -849,12 +851,27 @@
}
func (oo *OnuDeviceEntry) resetKvProcessingErrorIndication() {
- oo.onuKVStoreprocResult = nil
+ oo.mutexOnuKVStoreProcResult.Lock()
+ oo.onuKVStoreProcResult = nil
+ oo.mutexOnuKVStoreProcResult.Unlock()
}
+
func (oo *OnuDeviceEntry) getKvProcessingErrorIndication() error {
- return oo.onuKVStoreprocResult
+ oo.mutexOnuKVStoreProcResult.RLock()
+ value := oo.onuKVStoreProcResult
+ oo.mutexOnuKVStoreProcResult.RUnlock()
+ return value
}
+
+func (oo *OnuDeviceEntry) setKvProcessingErrorIndication(value error) {
+ oo.mutexOnuKVStoreProcResult.Lock()
+ oo.onuKVStoreProcResult = value
+ oo.mutexOnuKVStoreProcResult.Unlock()
+}
+
func (oo *OnuDeviceEntry) incrementMibDataSync(ctx context.Context) {
+ oo.mutexPersOnuConfig.Lock()
+ defer oo.mutexPersOnuConfig.Unlock()
if oo.sOnuPersistentData.PersMibDataSyncAdpt < 255 {
oo.sOnuPersistentData.PersMibDataSyncAdpt++
} else {
@@ -865,5 +882,7 @@
}
func (oo *OnuDeviceEntry) buildMibTemplatePath() string {
+ oo.mutexPersOnuConfig.RLock()
+ defer oo.mutexPersOnuConfig.RUnlock()
return fmt.Sprintf(cSuffixMibTemplateKvStore, oo.sOnuPersistentData.PersVendorID, oo.sOnuPersistentData.PersEquipmentID, oo.sOnuPersistentData.PersActiveSwVersion)
}
diff --git a/internal/pkg/onuadaptercore/onu_uni_tp.go b/internal/pkg/onuadaptercore/onu_uni_tp.go
index eecac2a..af0fdbe 100644
--- a/internal/pkg/onuadaptercore/onu_uni_tp.go
+++ b/internal/pkg/onuadaptercore/onu_uni_tp.go
@@ -630,7 +630,7 @@
*/
return
}
- if onuTP.baseDeviceHandler.ReadyForSpecificOmciConfig {
+ if onuTP.baseDeviceHandler.isReadyForOmciConfig() {
// check that the TpConfigRequest was done before
// -> that is implicitly done using the AniConfigFsm,
// which must be in the according state to remove something
@@ -771,7 +771,7 @@
onuTP.clearAniSideConfig(ctx, aUniID, aTpID)
return
}
- if onuTP.baseDeviceHandler.ReadyForSpecificOmciConfig {
+ if onuTP.baseDeviceHandler.isReadyForOmciConfig() {
// check that the TpConfigRequest was done before
// -> that is implicitly done using the AniConfigFsm,
// which must be in the according state to remove something
diff --git a/internal/pkg/onuadaptercore/uniportadmin.go b/internal/pkg/onuadaptercore/uniportadmin.go
index 0d7a117..57a1b58 100644
--- a/internal/pkg/onuadaptercore/uniportadmin.go
+++ b/internal/pkg/onuadaptercore/uniportadmin.go
@@ -20,6 +20,7 @@
import (
"context"
"fmt"
+ "sync"
"time"
"github.com/looplab/fsm"
@@ -36,10 +37,12 @@
pDeviceHandler *deviceHandler
deviceID string
pOmciCC *omciCC
+ mutexAdminState sync.RWMutex
adminState bool
requestEvent OnuDeviceEvent
omciLockResponseReceived chan bool //seperate channel needed for checking UNI port OMCi message responses
pAdaptFsm *AdapterFsm
+ mutexPLastTxMeInstance sync.RWMutex
pLastTxMeInstance *me.ManagedEntity
}
@@ -199,15 +202,19 @@
func (oFsm *lockStateFsm) enterSettingOnuGState(ctx context.Context, e *fsm.Event) {
var omciAdminState uint8 = 1 //default locked
+ oFsm.mutexAdminState.RLock()
if !oFsm.adminState {
omciAdminState = 0
}
+ oFsm.mutexAdminState.RUnlock()
logger.Debugw(ctx, "LockStateFSM Tx Set::ONU-G:admin", log.Fields{
"omciAdmin": omciAdminState, "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
requestedAttributes := me.AttributeValueMap{"AdministrativeState": omciAdminState}
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetOnuGLS(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
requestedAttributes, oFsm.pAdaptFsm.commChan)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "OnuGLS set failed, aborting LockStateFSM", log.Fields{"device-id": oFsm.deviceID})
pLockStateAFsm := oFsm.pAdaptFsm
if pLockStateAFsm != nil {
@@ -223,11 +230,13 @@
// - this avoids misinterpretation of new received OMCI messages
oFsm.pLastTxMeInstance = meInstance
if oFsm.pLastTxMeInstance == nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "could not send OMCI message from LockStateFsm", log.Fields{
"device-id": oFsm.deviceID})
//some more sophisticated approach is possible, e.g. repeating once, by now let's reset the state machine in order to release all resources now
pLockStateAFsm := oFsm.pAdaptFsm
if pLockStateAFsm != nil {
+
// obviously calling some FSM event here directly does not work - so trying to decouple it ...
go func(a_pAFsm *AdapterFsm) {
if a_pAFsm != nil && a_pAFsm.pFsm != nil {
@@ -235,12 +244,16 @@
}
}(pLockStateAFsm)
}
+ return
}
+ oFsm.mutexPLastTxMeInstance.Unlock()
}
func (oFsm *lockStateFsm) enterSettingUnisState(ctx context.Context, e *fsm.Event) {
+ oFsm.mutexAdminState.RLock()
logger.Debugw(ctx, "LockStateFSM - starting UniTP adminState loop", log.Fields{
"in state": e.FSM.Current(), "device-id": oFsm.deviceID, "LockState": oFsm.adminState})
+ oFsm.mutexAdminState.RUnlock()
go oFsm.performUniPortAdminSet(ctx)
}
@@ -281,7 +294,9 @@
_ = a_pAFsm.pFsm.Event(uniEvRestart)
}
}(pLockStateAFsm)
+ oFsm.mutexPLastTxMeInstance.Lock()
oFsm.pLastTxMeInstance = nil
+ oFsm.mutexPLastTxMeInstance.Unlock()
}
}
@@ -345,6 +360,7 @@
}
//should never appear, left here for robustness
+ oFsm.mutexPLastTxMeInstance.RLock()
if oFsm.pLastTxMeInstance != nil {
// compare comments above for CreateResponse (apply also here ...)
if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
@@ -356,18 +372,28 @@
switch oFsm.pLastTxMeInstance.GetName() {
case "OnuG":
{ // let the FSM proceed ...
+ oFsm.mutexPLastTxMeInstance.RUnlock()
_ = oFsm.pAdaptFsm.pFsm.Event(uniEvRxOnugResp)
}
case "PhysicalPathTerminationPointEthernetUni", "VirtualEthernetInterfacePoint":
{ // let the PPTP init proceed by stopping the wait function
+ oFsm.mutexPLastTxMeInstance.RUnlock()
oFsm.omciLockResponseReceived <- true
}
+ default:
+ {
+ logger.Warnw(ctx, "Unsupported ME name received!",
+ log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
+ oFsm.mutexPLastTxMeInstance.RUnlock()
+ }
}
} else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
logger.Warnf(ctx, "LockStateFsm - Received SetResponse Data for %s with wrong classID or entityID ",
log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj}, msgObj.EntityClass)
}
} else {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
logger.Errorw(ctx, "pLastTxMeInstance is nil", log.Fields{"device-id": oFsm.deviceID})
return
}
@@ -379,9 +405,11 @@
func (oFsm *lockStateFsm) performUniPortAdminSet(ctx context.Context) {
var omciAdminState uint8 = 1 //default locked
+ oFsm.mutexAdminState.RLock()
if !oFsm.adminState {
omciAdminState = 0
}
+ oFsm.mutexAdminState.RUnlock()
//set PPTPEthUni or VEIP AdminState
requestedAttributes := me.AttributeValueMap{"AdministrativeState": omciAdminState}
@@ -393,41 +421,50 @@
if uniPort.portType == uniPPTP {
logger.Debugw(ctx, "Setting PPTP admin state", log.Fields{
"device-id": oFsm.deviceID, "for PortNo": uniNo, "state (0-unlock)": omciAdminState})
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetPptpEthUniLS(log.WithSpanFromContext(context.TODO(), ctx),
uniPort.entityID, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
true, requestedAttributes, oFsm.pAdaptFsm.commChan)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetPptpEthUniLS set failed, aborting LockStateFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(uniEvReset)
return
}
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
} else if uniPort.portType == uniVEIP {
logger.Debugw(ctx, "Setting VEIP admin state", log.Fields{
"device-id": oFsm.deviceID, "for PortNo": uniNo, "state (0-unlock)": omciAdminState})
+ oFsm.mutexPLastTxMeInstance.Lock()
meInstance, err := oFsm.pOmciCC.sendSetVeipLS(log.WithSpanFromContext(context.TODO(), ctx),
uniPort.entityID, oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
true, requestedAttributes, oFsm.pAdaptFsm.commChan)
if err != nil {
+ oFsm.mutexPLastTxMeInstance.Unlock()
logger.Errorw(ctx, "SetVeipLS set failed, aborting LockStateFsm!",
log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(uniEvReset)
return
}
oFsm.pLastTxMeInstance = meInstance
+ oFsm.mutexPLastTxMeInstance.Unlock()
} else {
logger.Warnw(ctx, "Unsupported UniTP type - skip",
log.Fields{"device-id": oFsm.deviceID, "Port": uniNo})
continue
}
+ oFsm.mutexPLastTxMeInstance.RLock()
if oFsm.pLastTxMeInstance == nil {
+ oFsm.mutexPLastTxMeInstance.RUnlock()
logger.Errorw(ctx, "could not send PortAdmin OMCI message from LockStateFsm", log.Fields{
"device-id": oFsm.deviceID, "Port": uniNo})
//some more sophisticated approach is possible, e.g. repeating once, by now let's reset the state machine in order to release all resources now
_ = oFsm.pAdaptFsm.pFsm.Event(uniEvReset)
return
}
+ oFsm.mutexPLastTxMeInstance.RUnlock()
//verify response
err := oFsm.waitforOmciResponse(ctx, meInstance)