[VOL-4010] openonuAdapterGo - investigate and resolve data race conditions

Change-Id: I8e957d8bd59b91db27ee4f303a5a222a8f83e8c4
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)