[VOL-3380] Functional area specific logging

Change-Id: I67414da013d8fc82827fcdb69d4f8a34040625d3
diff --git a/internal/pkg/mib/common.go b/internal/pkg/mib/common.go
new file mode 100755
index 0000000..e9d39c3
--- /dev/null
+++ b/internal/pkg/mib/common.go
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+	"github.com/opencord/voltha-lib-go/v7/pkg/log"
+)
+
+var logger log.CLogger
+
+func init() {
+	// Setup this package so that it's log level can be modified at run time
+	var err error
+	logger, err = log.RegisterPackage(log.JSON, log.ErrorLevel, log.Fields{"pkg": "mib"})
+	if err != nil {
+		panic(err)
+	}
+}
diff --git a/internal/pkg/mib/mib_download.go b/internal/pkg/mib/mib_download.go
new file mode 100755
index 0000000..9c49f9b
--- /dev/null
+++ b/internal/pkg/mib/mib_download.go
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+	"context"
+	"fmt"
+	"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/v7/pkg/log"
+	//ic "github.com/opencord/voltha-protos/v5/go/inter_container"
+	//"github.com/opencord/voltha-protos/v5/go/openflow_13"
+	//"github.com/opencord/voltha-protos/v5/go/voltha"
+	cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
+)
+
+func (onuDeviceEntry *OnuDeviceEntry) enterDLStartingState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibDownload FSM", log.Fields{"Start downloading OMCI MIB in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+	// in case the used channel is not yet defined (can be re-used after restarts)
+	if onuDeviceEntry.omciMessageReceived == nil {
+		onuDeviceEntry.omciMessageReceived = make(chan bool)
+		logger.Debug(ctx, "MibDownload FSM - defining the BridgeInit RxChannel")
+	}
+	// start go routine for processing of MibDownload messages
+	go onuDeviceEntry.processMibDownloadMessages(ctx)
+}
+
+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.mutexPLastTxMeInstance.Lock()
+	meInstance, err := onuDeviceEntry.PDevOmciCC.SendCreateGalEthernetProfile(log.WithSpanFromContext(context.TODO(), ctx),
+		onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+	//accept also nil as (error) return value for writing to LastTx
+	//  - this avoids misinterpretation of new received OMCI messages
+	if err != nil {
+		onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+		logger.Errorw(ctx, "GalEthernetProfile create failed, aborting MibDownload FSM!",
+			log.Fields{"device-id": onuDeviceEntry.deviceID})
+		pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+		if pMibDlFsm != nil {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = a_pAFsm.PFsm.Event(DlEvReset)
+			}(pMibDlFsm)
+		}
+		return
+	}
+	onuDeviceEntry.pLastTxMeInstance = meInstance
+	onuDeviceEntry.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.mutexPLastTxMeInstance.Lock()
+	meInstance, err := onuDeviceEntry.PDevOmciCC.SendSetOnu2g(log.WithSpanFromContext(context.TODO(), ctx),
+		onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+	//accept also nil as (error) return value for writing to LastTx
+	//  - this avoids misinterpretation of new received OMCI messages
+	if err != nil {
+		onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+		logger.Errorw(ctx, "ONU2-G set failed, aborting MibDownload FSM!",
+			log.Fields{"device-id": onuDeviceEntry.deviceID})
+		pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+		if pMibDlFsm != nil {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = a_pAFsm.PFsm.Event(DlEvReset)
+			}(pMibDlFsm)
+		}
+		return
+	}
+	onuDeviceEntry.pLastTxMeInstance = meInstance
+	onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterBridgeInitState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibDownload FSM - starting bridge config port loop", log.Fields{
+		"in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+	go onuDeviceEntry.performInitialBridgeSetup(ctx)
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterDownloadedState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibDownload FSM", log.Fields{"send notification to core in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+	onuDeviceEntry.transferSystemEvent(ctx, cmn.MibDownloadDone)
+	//let's reset the state machine in order to release all resources now
+	pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+	if pMibDlFsm != nil {
+		// obviously calling some FSM event here directly does not work - so trying to decouple it ...
+		go func(a_pAFsm *cmn.AdapterFsm) {
+			if a_pAFsm != nil && a_pAFsm.PFsm != nil {
+				_ = a_pAFsm.PFsm.Event(DlEvReset)
+			}
+		}(pMibDlFsm)
+	}
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterResettingState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibDownload FSM resetting", log.Fields{"device-id": onuDeviceEntry.deviceID})
+	pMibDlFsm := onuDeviceEntry.PMibDownloadFsm
+	if pMibDlFsm != nil {
+		// abort running message processing
+		fsmAbortMsg := cmn.Message{
+			Type: cmn.TestMsg,
+			Data: cmn.TestMessage{
+				TestMessageVal: cmn.AbortMessageProcessing,
+			},
+		}
+		pMibDlFsm.CommChan <- fsmAbortMsg
+
+		//try to restart the FSM to 'disabled'
+		// see DownloadedState: decouple event transfer
+		go func(a_pAFsm *cmn.AdapterFsm) {
+			if a_pAFsm != nil && a_pAFsm.PFsm != nil {
+				_ = a_pAFsm.PFsm.Event(DlEvRestart)
+			}
+		}(pMibDlFsm)
+	}
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) processMibDownloadMessages(ctx context.Context) {
+	logger.Debugw(ctx, "Start MibDownload Msg processing", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+loop:
+	for {
+		// case <-ctx.Done():
+		// 	logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": onuDeviceEntry.deviceID})
+		// 	break loop
+		// unless multiple channels are not involved, we should not use select
+		message, ok := <-onuDeviceEntry.PMibDownloadFsm.CommChan
+		if !ok {
+			logger.Info(ctx, "MibDownload Rx Msg", log.Fields{"Message couldn't be read from channel for device-id": onuDeviceEntry.deviceID})
+			// but then we have to ensure a restart of the FSM as well - as exceptional procedure
+			_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvRestart)
+			break loop
+		}
+		logger.Debugw(ctx, "MibDownload Rx Msg", log.Fields{"Received message for device-id": onuDeviceEntry.deviceID})
+
+		switch message.Type {
+		case cmn.TestMsg:
+			msg, _ := message.Data.(cmn.TestMessage)
+			if msg.TestMessageVal == cmn.AbortMessageProcessing {
+				logger.Debugw(ctx, "MibDownload abort ProcessMsg", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+				break loop
+			}
+			logger.Warnw(ctx, "MibDownload unknown TestMessage", log.Fields{"device-id": onuDeviceEntry.deviceID, "MessageVal": msg.TestMessageVal})
+		case cmn.OMCI:
+			msg, _ := message.Data.(cmn.OmciMessage)
+			onuDeviceEntry.handleOmciMibDownloadMessage(ctx, msg)
+		default:
+			logger.Warn(ctx, "MibDownload Rx Msg", log.Fields{"Unknown message type received for device-id": onuDeviceEntry.deviceID,
+				"message.Type": message.Type})
+		}
+
+	}
+	logger.Debugw(ctx, "End MibDownload Msg processing", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) handleOmciMibDownloadCreateResponseMessage(ctx context.Context, msg cmn.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.mutexPLastTxMeInstance.RLock()
+	if onuDeviceEntry.pLastTxMeInstance != nil {
+		if msgObj.EntityClass == onuDeviceEntry.pLastTxMeInstance.GetClassID() &&
+			msgObj.EntityInstance == onuDeviceEntry.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.pLastTxMeInstance.GetName() {
+			case "GalEthernetProfile":
+				{ // let the FSM proceed ...
+					onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+					_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvRxGalResp)
+				}
+			case "MacBridgeServiceProfile",
+				"MacBridgePortConfigurationData",
+				"ExtendedVlanTaggingOperationConfigurationData":
+				{ // let bridge init proceed by stopping the wait function
+					onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+					onuDeviceEntry.omciMessageReceived <- true
+				}
+			default:
+				{
+					logger.Warnw(ctx, "Unsupported ME name received!",
+						log.Fields{"ME name": onuDeviceEntry.pLastTxMeInstance.GetName(), "device-id": onuDeviceEntry.deviceID})
+					onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+				}
+			}
+		} else {
+			onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+		}
+	} else {
+		onuDeviceEntry.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 cmn.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.mutexPLastTxMeInstance.RLock()
+	if onuDeviceEntry.pLastTxMeInstance != nil {
+		if msgObj.EntityClass == onuDeviceEntry.pLastTxMeInstance.GetClassID() &&
+			msgObj.EntityInstance == onuDeviceEntry.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.pLastTxMeInstance.GetName() {
+			case "Onu2G":
+				{ // let the FSM proceed ...
+					onuDeviceEntry.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.pLastTxMeInstance.GetName(), "device-id": onuDeviceEntry.deviceID})
+					onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+				}
+
+			}
+		} else {
+			onuDeviceEntry.mutexPLastTxMeInstance.RUnlock()
+		}
+	} else {
+		onuDeviceEntry.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 cmn.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:
+		onuDeviceEntry.handleOmciMibDownloadCreateResponseMessage(ctx, msg)
+	//TODO
+	//	onuDeviceEntry.PMibDownloadFsm.PFsm.Event("rx_evtocd_resp")
+	case omci.SetResponseType:
+		onuDeviceEntry.handleOmciMibDownloadSetResponseMessage(ctx, msg)
+	default:
+		{
+			logger.Errorw(ctx, "Rx OMCI MibDownload unhandled MsgType", log.Fields{"device-id": onuDeviceEntry.deviceID,
+				"omciMsgType": msg.OmciMsg.MessageType})
+			return
+		}
+	} // switch msg.OmciMsg.MessageType
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) performInitialBridgeSetup(ctx context.Context) {
+	for uniNo, uniPort := range *onuDeviceEntry.baseDeviceHandler.GetUniEntityMap() {
+		logger.Debugw(ctx, "Starting IntialBridgeSetup", log.Fields{
+			"device-id": onuDeviceEntry.deviceID, "for PortNo": uniNo})
+
+		//create MBSP
+		onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+		meInstance, err := onuDeviceEntry.PDevOmciCC.SendCreateMBServiceProfile(
+			log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+		if err != nil {
+			onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+			logger.Errorw(ctx, "MBServiceProfile create failed, aborting MibDownload FSM!", log.Fields{"device-id": onuDeviceEntry.deviceID})
+			_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+			return
+		}
+		onuDeviceEntry.pLastTxMeInstance = meInstance
+		onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+		//verify response
+		err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
+		if err != nil {
+			logger.Errorw(ctx, "InitialBridgeSetup failed at MBSP, aborting MIB Download!",
+				log.Fields{"device-id": onuDeviceEntry.deviceID})
+			_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+			return
+		}
+
+		//create MBPCD
+		onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+		meInstance, err = onuDeviceEntry.PDevOmciCC.SendCreateMBPConfigDataUniSide(
+			log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+		if err != nil {
+			onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+			logger.Errorw(ctx, "MBPConfigData create failed, aborting MibDownload FSM!",
+				log.Fields{"device-id": onuDeviceEntry.deviceID})
+			_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+			return
+		}
+		onuDeviceEntry.pLastTxMeInstance = meInstance
+		onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+		//verify response
+		err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
+		if err != nil {
+			logger.Errorw(ctx, "InitialBridgeSetup failed at MBPCD, aborting MIB Download!",
+				log.Fields{"device-id": onuDeviceEntry.deviceID})
+			_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+			return
+		}
+
+		//create EVTOCD
+		onuDeviceEntry.mutexPLastTxMeInstance.Lock()
+		meInstance, err = onuDeviceEntry.PDevOmciCC.SendCreateEVTOConfigData(
+			log.WithSpanFromContext(context.TODO(), ctx), uniPort, onuDeviceEntry.baseDeviceHandler.GetOmciTimeout(), true)
+		if err != nil {
+			onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+			logger.Errorw(ctx, "EVTOConfigData create failed, aborting MibDownload FSM!",
+				log.Fields{"device-id": onuDeviceEntry.deviceID})
+			_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+			return
+		}
+		onuDeviceEntry.pLastTxMeInstance = meInstance
+		onuDeviceEntry.mutexPLastTxMeInstance.Unlock()
+		//verify response
+		err = onuDeviceEntry.waitforOmciResponse(ctx, meInstance)
+		if err != nil {
+			logger.Errorw(ctx, "InitialBridgeSetup failed at EVTOCD, aborting MIB Download!",
+				log.Fields{"device-id": onuDeviceEntry.deviceID})
+			_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvReset)
+			return
+		}
+	}
+	// if Config has been done for all UNI related instances let the FSM proceed
+	// while we did not check here, if there is some port at all - !?
+	logger.Infow(ctx, "IntialBridgeSetup finished", log.Fields{"device-id": onuDeviceEntry.deviceID})
+	_ = onuDeviceEntry.PMibDownloadFsm.PFsm.Event(DlEvRxBridgeResp)
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) waitforOmciResponse(ctx context.Context, apMeInstance *me.ManagedEntity) error {
+	select {
+	// maybe be also some outside cancel (but no context modeled for the moment ...)
+	// case <-ctx.Done():
+	// 		logger.Info("MibDownload-bridge-init message reception canceled", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+	case <-time.After(onuDeviceEntry.PDevOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
+		logger.Warnw(ctx, "MibDownload-bridge-init timeout", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+		return fmt.Errorf("mibDownloadBridgeInit timeout %s", onuDeviceEntry.deviceID)
+	case success := <-onuDeviceEntry.omciMessageReceived:
+		if success {
+			logger.Debug(ctx, "MibDownload-bridge-init response received")
+			return nil
+		}
+		// should not happen so far
+		logger.Warnw(ctx, "MibDownload-bridge-init response error", log.Fields{"for device-id": onuDeviceEntry.deviceID})
+		return fmt.Errorf("mibDownloadBridgeInit responseError %s", onuDeviceEntry.deviceID)
+	}
+}
diff --git a/internal/pkg/mib/mib_sync.go b/internal/pkg/mib/mib_sync.go
new file mode 100755
index 0000000..871b6de
--- /dev/null
+++ b/internal/pkg/mib/mib_sync.go
@@ -0,0 +1,1103 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+	"context"
+	"encoding/hex"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"strconv"
+	"strings"
+
+	"github.com/looplab/fsm"
+
+	"time"
+
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
+	"github.com/opencord/voltha-lib-go/v7/pkg/log"
+	cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
+	devdb "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/devdb"
+)
+
+type sLastTxMeParameter struct {
+	lastTxMessageType omci.MessageType
+	pLastTxMeInstance *me.ManagedEntity
+	repeatCount       uint8
+}
+
+var supportedClassIds = []me.ClassID{
+	me.CardholderClassID,                              // 5
+	me.CircuitPackClassID,                             // 6
+	me.SoftwareImageClassID,                           // 7
+	me.PhysicalPathTerminationPointEthernetUniClassID, // 11
+	me.PhysicalPathTerminationPointPotsUniClassID,     // 53
+	me.OltGClassID,                                    // 131
+	me.OnuPowerSheddingClassID,                        // 133
+	me.IpHostConfigDataClassID,                        // 134
+	me.OnuGClassID,                                    // 256
+	me.Onu2GClassID,                                   // 257
+	me.TContClassID,                                   // 262
+	me.AniGClassID,                                    // 263
+	me.UniGClassID,                                    // 264
+	me.PriorityQueueClassID,                           // 277
+	me.TrafficSchedulerClassID,                        // 278
+	me.VirtualEthernetInterfacePointClassID,           // 329
+	me.EnhancedSecurityControlClassID,                 // 332
+	me.OnuDynamicPowerManagementControlClassID,        // 336
+	// 347 // definitions for ME "IPv6 host config data" are currently missing in omci-lib-go!
+}
+
+var fsmMsg cmn.TestMessageType
+
+func (oo *OnuDeviceEntry) enterStartingState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start processing MibSync-msgs in State": e.FSM.Current(), "device-id": oo.deviceID})
+	oo.pOnuDB = devdb.NewOnuDeviceDB(log.WithSpanFromContext(context.TODO(), ctx), oo.deviceID)
+	go oo.processMibSyncMessages(ctx)
+}
+
+func (oo *OnuDeviceEntry) enterResettingMibState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibTemplate processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+
+	if (!oo.IsNewOnu() && !oo.baseDeviceHandler.IsReconciling()) || //use case: re-auditing failed
+		oo.baseDeviceHandler.IsSkipOnuConfigReconciling() { //use case: reconciling without omci-config failed
+		oo.baseDeviceHandler.PrepareReconcilingWithActiveAdapter(ctx)
+		oo.devState = cmn.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.baseDeviceHandler.GetOmciTimeout(), 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, cmn.OnugMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), 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 {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+			}(pMibUlFsm)
+		}
+		return
+	}
+	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, cmn.Onu2gMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), 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 {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+			}(pMibUlFsm)
+		}
+		return
+	}
+	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, cmn.FirstSwImageMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), 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 {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+			}(pMibUlFsm)
+		}
+		return
+	}
+	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, cmn.SecondSwImageMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), 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 {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+			}(pMibUlFsm)
+		}
+		return
+	}
+	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, cmn.IPHostConfigDataMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), 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 {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+			}(pMibUlFsm)
+		}
+		return
+	}
+	oo.lastTxParamStruct.lastTxMessageType = omci.GetRequestType
+	oo.lastTxParamStruct.pLastTxMeInstance = meInstance
+	oo.mutexLastTxParamStruct.Unlock()
+}
+
+func (oo *OnuDeviceEntry) enterGettingMibTemplateState(ctx context.Context, e *fsm.Event) {
+
+	oo.mutexOnuSwImageIndications.RLock()
+	if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+		oo.MutexPersOnuConfig.Lock()
+		oo.SOnuPersistentData.PersActiveSwVersion = oo.onuSwImageIndications.ActiveEntityEntry.Version
+		oo.MutexPersOnuConfig.Unlock()
+		oo.mutexOnuSwImageIndications.RUnlock()
+	} else {
+		oo.mutexOnuSwImageIndications.RUnlock()
+		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})
+	}
+	if oo.getMibFromTemplate(ctx) {
+		logger.Debug(ctx, "MibSync FSM - valid MEs stored from template")
+		oo.pOnuDB.LogMeDb(ctx)
+		fsmMsg = cmn.LoadMibTemplateOk
+	} else {
+		logger.Debug(ctx, "MibSync FSM - no valid MEs stored from template - perform MIB-upload!")
+		fsmMsg = cmn.LoadMibTemplateFailed
+
+		oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+		if mibTemplateIsGenerated, exist := oo.pOpenOnuAc.GetMibTemplatesGenerated(oo.mibTemplatePath); exist {
+			if mibTemplateIsGenerated {
+				logger.Debugw(ctx,
+					"MibSync FSM - template was successfully generated before, but doesn't exist or isn't usable anymore - reset flag in map",
+					log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+				oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, false)
+			}
+		}
+		oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+	}
+	mibSyncMsg := cmn.Message{
+		Type: cmn.TestMsg,
+		Data: cmn.TestMessage{
+			TestMessageVal: fsmMsg,
+		},
+	}
+	oo.PMibUploadFsm.CommChan <- mibSyncMsg
+}
+
+func (oo *OnuDeviceEntry) enterUploadingState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"send MibUpload in State": e.FSM.Current(), "device-id": oo.deviceID})
+	_ = oo.PDevOmciCC.SendMibUpload(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), 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) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"send notification to core in State": e.FSM.Current(), "device-id": oo.deviceID})
+	oo.transferSystemEvent(ctx, cmn.MibDatabaseSync)
+	go func() {
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+	}()
+}
+
+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() {
+			time.Sleep(oo.mibAuditInterval)
+			if err := oo.PMibUploadFsm.PFsm.Event(UlEvAuditMib); err != nil {
+				logger.Debugw(ctx, "MibSyncFsm: Can't go to state auditing", log.Fields{"device-id": oo.deviceID, "err": err})
+			}
+		}()
+	}
+}
+
+func (oo *OnuDeviceEntry) enterExaminingMdsState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start GetMds processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+	oo.requestMdsValue(ctx)
+}
+
+func (oo *OnuDeviceEntry) enterResynchronizingState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibResync processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+	logger.Debug(ctx, "function not implemented yet")
+	// TODOs:
+	// VOL-3805 - Provide exclusive OMCI channel for one FSM
+	// VOL-3785 - New event notifications and corresponding performance counters for openonu-adapter-go
+	// VOL-3792 - Support periodical audit via mib resync
+	// VOL-3793 - ONU-reconcile handling after adapter restart based on mib resync
+}
+
+func (oo *OnuDeviceEntry) enterExaminingMdsSuccessState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM",
+		log.Fields{"Start processing on examining MDS success in State": e.FSM.Current(), "device-id": oo.deviceID})
+
+	if oo.getMibFromTemplate(ctx) {
+		oo.baseDeviceHandler.StartReconciling(ctx, true)
+		oo.baseDeviceHandler.AddAllUniPorts(ctx)
+		oo.baseDeviceHandler.SetDeviceReason(cmn.DrInitialMibDownloaded)
+		oo.baseDeviceHandler.SetReadyForOmciConfig(true)
+
+		if !oo.baseDeviceHandler.GetCollectorIsRunning() {
+			// Start PM collector routine
+			go oo.baseDeviceHandler.StartCollector(ctx)
+		}
+		if !oo.baseDeviceHandler.GetAlarmManagerIsRunning(ctx) {
+			go oo.baseDeviceHandler.StartAlarmManager(ctx)
+		}
+		// no need to reconcile additional data for MibDownloadFsm, LockStateFsm, or UnlockStateFsm
+		oo.baseDeviceHandler.ReconcileDeviceTechProf(ctx)
+
+		// start go routine with select() on reconciling flow channel before
+		// starting flow reconciling process to prevent loss of any signal
+		go func() {
+			// In multi-ONU/multi-flow environment stopping reconcilement has to be delayed until
+			// we get a signal that the processing of the last step to rebuild the adapter internal
+			// flow data is finished.
+			select {
+			case success := <-oo.chReconcilingFlowsFinished:
+				if success {
+					logger.Debugw(ctx, "reconciling flows has been finished in time",
+						log.Fields{"device-id": oo.deviceID})
+					oo.baseDeviceHandler.StopReconciling(ctx, true)
+					_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+
+				} else {
+					logger.Debugw(ctx, "wait for reconciling flows aborted",
+						log.Fields{"device-id": oo.deviceID})
+					oo.SetReconcilingFlows(false)
+				}
+			case <-time.After(500 * time.Millisecond):
+				logger.Errorw(ctx, "timeout waiting for reconciling flows to be finished!",
+					log.Fields{"device-id": oo.deviceID})
+				oo.SetReconcilingFlows(false)
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+			}
+		}()
+		oo.baseDeviceHandler.ReconcileDeviceFlowConfig(ctx)
+
+		oo.MutexPersOnuConfig.RLock()
+		if oo.SOnuPersistentData.PersUniDisableDone {
+			oo.MutexPersOnuConfig.RUnlock()
+			oo.baseDeviceHandler.DisableUniPortStateUpdate(ctx)
+			oo.baseDeviceHandler.SetDeviceReason(cmn.DrOmciAdminLock)
+		} else {
+			oo.MutexPersOnuConfig.RUnlock()
+			oo.baseDeviceHandler.EnableUniPortStateUpdate(ctx)
+		}
+	} else {
+		logger.Debugw(ctx, "MibSync FSM",
+			log.Fields{"Getting MIB from template not successful": e.FSM.Current(), "device-id": oo.deviceID})
+		go func() {
+			//switch to reconciling with OMCI config
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+		}()
+	}
+}
+
+func (oo *OnuDeviceEntry) enterAuditingState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibAudit processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+	if oo.baseDeviceHandler.CheckAuditStartCondition(ctx, cmn.CUploadFsm) {
+		oo.requestMdsValue(ctx)
+	} else {
+		logger.Debugw(ctx, "MibSync FSM", log.Fields{"Configuration is ongoing or missing - skip auditing!": e.FSM.Current(), "device-id": oo.deviceID})
+		go func() {
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+		}()
+	}
+}
+
+func (oo *OnuDeviceEntry) enterReAuditingState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start retest MdsValue processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+	if oo.baseDeviceHandler.CheckAuditStartCondition(ctx, cmn.CUploadFsm) {
+		oo.requestMdsValue(ctx)
+	} else {
+		logger.Debugw(ctx, "MibSync FSM", log.Fields{"Configuration is ongoing or missing - skip re-auditing!": e.FSM.Current(), "device-id": oo.deviceID})
+		go func() {
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+		}()
+	}
+}
+
+func (oo *OnuDeviceEntry) enterOutOfSyncState(ctx context.Context, e *fsm.Event) {
+	logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start  MibReconcile processing in State": e.FSM.Current(), "device-id": oo.deviceID})
+	logger.Debug(ctx, "function not implemented yet")
+}
+
+func (oo *OnuDeviceEntry) processMibSyncMessages(ctx context.Context) {
+	logger.Debugw(ctx, "MibSync Msg", log.Fields{"Start routine to process OMCI-messages for device-id": oo.deviceID})
+loop:
+	for {
+		// case <-ctx.Done():
+		// 	logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": onuDeviceEntry.deviceID})
+		// 	break loop
+		message, ok := <-oo.PMibUploadFsm.CommChan
+		if !ok {
+			logger.Info(ctx, "MibSync Msg", log.Fields{"Message couldn't be read from channel for device-id": oo.deviceID})
+			break loop
+		}
+		logger.Debugw(ctx, "MibSync Msg", log.Fields{"Received message on ONU MibSyncChan for device-id": oo.deviceID})
+
+		switch message.Type {
+		case cmn.TestMsg:
+			msg, _ := message.Data.(cmn.TestMessage)
+			oo.handleTestMsg(ctx, msg)
+		case cmn.OMCI:
+			msg, _ := message.Data.(cmn.OmciMessage)
+			oo.handleOmciMessage(ctx, msg)
+		default:
+			logger.Warn(ctx, "MibSync Msg", log.Fields{"Unknown message type received for device-id": oo.deviceID, "message.Type": message.Type})
+		}
+	}
+	logger.Info(ctx, "MibSync Msg", log.Fields{"Stopped handling of MibSyncChan for device-id": oo.deviceID})
+	// TODO: only this action?
+	_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+}
+
+func (oo *OnuDeviceEntry) handleTestMsg(ctx context.Context, msg cmn.TestMessage) {
+
+	logger.Debugw(ctx, "MibSync Msg", log.Fields{"TestMessage received for device-id": oo.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
+
+	switch msg.TestMessageVal {
+	case cmn.LoadMibTemplateFailed:
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvUploadMib)
+		logger.Debugw(ctx, "MibSync Msg", log.Fields{"state": string(oo.PMibUploadFsm.PFsm.Current())})
+	case cmn.LoadMibTemplateOk:
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+		logger.Debugw(ctx, "MibSync Msg", log.Fields{"state": string(oo.PMibUploadFsm.PFsm.Current())})
+	default:
+		logger.Warn(ctx, "MibSync Msg", log.Fields{"Unknown message type received for device-id": oo.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
+	}
+}
+
+func (oo *OnuDeviceEntry) handleOmciMibResetResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+	if oo.PMibUploadFsm.PFsm.Is(UlStResettingMib) {
+		msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibResetResponse)
+		if msgLayer != nil {
+			msgObj, msgOk := msgLayer.(*omci.MibResetResponse)
+			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
+				}
+				logger.Errorw(ctx, "Omci MibResetResponse Error", log.Fields{"device-id": oo.deviceID, "Error": msgObj.Result})
+			} else {
+				logger.Errorw(ctx, "Omci Msg layer could not be assigned", log.Fields{"device-id": oo.deviceID})
+			}
+		} else {
+			logger.Errorw(ctx, "Omci Msg layer could not be detected", log.Fields{"device-id": oo.deviceID})
+		}
+	} else {
+		//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, cmn.OnuDataMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), 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
+	}
+	logger.Info(ctx, "MibSync Msg", log.Fields{"Stopped handling of MibSyncChan for device-id": oo.deviceID})
+	_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+}
+
+func (oo *OnuDeviceEntry) handleOmciMibUploadResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+	msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibUploadResponse)
+	if msgLayer == nil {
+		logger.Errorw(ctx, "Omci Msg layer could not be detected", log.Fields{"device-id": oo.deviceID})
+		return
+	}
+	msgObj, msgOk := msgLayer.(*omci.MibUploadResponse)
+	if !msgOk {
+		logger.Errorw(ctx, "Omci Msg layer could not be assigned", log.Fields{"device-id": oo.deviceID})
+		return
+	}
+	logger.Debugw(ctx, "MibUploadResponse Data for:", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
+	/* to be verified / reworked !!! */
+	oo.PDevOmciCC.UploadNoOfCmds = msgObj.NumberOfCommands
+	if oo.PDevOmciCC.UploadSequNo < oo.PDevOmciCC.UploadNoOfCmds {
+		_ = oo.PDevOmciCC.SendMibUploadNext(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), 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?
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvTimeout)
+	}
+}
+
+func (oo *OnuDeviceEntry) handleOmciMibUploadNextResponseMessage(ctx context.Context, msg cmn.OmciMessage) {
+	msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibUploadNextResponse)
+
+	if msgLayer == nil {
+		logger.Errorw(ctx, "Omci Msg layer could not be detected", log.Fields{"device-id": oo.deviceID})
+		return
+	}
+	msgObj, msgOk := msgLayer.(*omci.MibUploadNextResponse)
+	if !msgOk {
+		logger.Errorw(ctx, "Omci Msg layer could not be assigned", log.Fields{"device-id": oo.deviceID})
+		return
+	}
+	meName := msgObj.ReportedME.GetName()
+	if meName == "UnknownItuG988ManagedEntity" || meName == "UnknownVendorSpecificManagedEntity" {
+		logger.Debugw(ctx, "MibUploadNextResponse Data for unknown ME received - temporary workaround is to ignore it!",
+			log.Fields{"device-id": oo.deviceID, "data-fields": msgObj, "meName": meName})
+	} else {
+		logger.Debugw(ctx, "MibUploadNextResponse Data for:",
+			log.Fields{"device-id": oo.deviceID, "meName": meName, "data-fields": msgObj})
+		meClassID := msgObj.ReportedME.GetClassID()
+		meEntityID := msgObj.ReportedME.GetEntityID()
+		meAttributes := msgObj.ReportedME.GetAttributeValueMap()
+		oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, meAttributes)
+	}
+	if oo.PDevOmciCC.UploadSequNo < oo.PDevOmciCC.UploadNoOfCmds {
+		_ = oo.PDevOmciCC.SendMibUploadNext(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), 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)
+		if err != nil {
+			logger.Errorw(ctx, "MibSync - MibTemplate - Failed to create and persist the mib template", log.Fields{"error": err, "device-id": oo.deviceID})
+		}
+
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+	}
+}
+
+func (oo *OnuDeviceEntry) handleOmciGetResponseMessage(ctx context.Context, msg cmn.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
+		//  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 MIB reset with a new message that uses an increased Sequence number
+		if oo.lastTxParamStruct.lastTxMessageType == omci.MibResetRequestType && oo.lastTxParamStruct.repeatCount == 0 {
+			logger.Debugw(ctx, "MibSync FSM - repeat mibReset (updated SequenceNumber)", log.Fields{"device-id": oo.deviceID})
+			_ = oo.PDevOmciCC.SendMibReset(log.WithSpanFromContext(context.TODO(), ctx), oo.baseDeviceHandler.GetOmciTimeout(), 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})
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+		return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling of MibSyncChan stopped: %s", oo.deviceID)
+	}
+	msgObj, msgOk := msgLayer.(*omci.GetResponse)
+	if !msgOk {
+		logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling of MibSyncChan stopped", log.Fields{"device-id": oo.deviceID})
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+		return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling of MibSyncChan stopped: %s", oo.deviceID)
+	}
+	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
+			meInstance := oo.lastTxParamStruct.pLastTxMeInstance.GetName()
+			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 = cmn.TrimStringFromMeOctet(meAttributes["VendorId"])
+				snBytes, _ := me.InterfaceToOctets(meAttributes["SerialNumber"])
+				if cmn.OnugSerialNumberLen == len(snBytes) {
+					snVendorPart := fmt.Sprintf("%s", snBytes[:4])
+					snNumberPart := hex.EncodeToString(snBytes[4:])
+					oo.SOnuPersistentData.PersSerialNumber = snVendorPart + snNumberPart
+					logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu-G - VendorId/SerialNumber", log.Fields{"device-id": oo.deviceID,
+						"onuDeviceEntry.vendorID": oo.SOnuPersistentData.PersVendorID, "onuDeviceEntry.serialNumber": oo.SOnuPersistentData.PersSerialNumber})
+				} else {
+					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 = cmn.TrimStringFromMeOctet(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 > cmn.SecondSwImageMeID {
+					logger.Errorw(ctx, "mibSync FSM - Failed to GetResponse Data for SoftwareImage with expected EntityId",
+						log.Fields{"device-id": oo.deviceID, "entity-ID": entityID})
+					return fmt.Errorf("mibSync FSM - SwResponse Data with unexpected EntityId: %s %x",
+						oo.deviceID, entityID)
+				}
+				// need to use function for go lint complexity
+				oo.handleSwImageIndications(ctx, entityID, meAttributes)
+				return nil
+			case "IpHostConfigData":
+				oo.mutexLastTxParamStruct.RUnlock()
+				macBytes, _ := me.InterfaceToOctets(meAttributes["MacAddress"])
+				oo.MutexPersOnuConfig.Lock()
+				if cmn.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,
+						"macAddress": oo.SOnuPersistentData.PersMacAddress})
+				} else {
+					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 {
+			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 {
+			return nil
+		}
+	}
+	logger.Info(ctx, "MibSync Msg", log.Fields{"Stopped handling of MibSyncChan for device-id": oo.deviceID})
+	_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+	return err
+}
+
+func (oo *OnuDeviceEntry) handleSwImageIndications(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap) {
+	imageIsCommitted := meAttributes["IsCommitted"].(uint8)
+	imageIsActive := meAttributes["IsActive"].(uint8)
+	imageVersion := cmn.TrimStringFromMeOctet(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 cmn.FirstSwImageMeID == entityID {
+		//always accept the state of the first image (2nd image info should not yet be available)
+		oo.mutexOnuSwImageIndications.Lock()
+		if imageIsActive == cmn.SwIsActive {
+			oo.onuSwImageIndications.ActiveEntityEntry.EntityID = entityID
+			oo.onuSwImageIndications.ActiveEntityEntry.Valid = true
+			oo.onuSwImageIndications.ActiveEntityEntry.Version = imageVersion
+			oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = imageIsCommitted
+			//as the SW version indication may stem from some ONU Down/up event
+			//the complementary image state is to be invalidated
+			//  (state of the second image is always expected afterwards or just invalid)
+			oo.onuSwImageIndications.InActiveEntityEntry.Valid = false
+		} else {
+			oo.onuSwImageIndications.InActiveEntityEntry.EntityID = entityID
+			oo.onuSwImageIndications.InActiveEntityEntry.Valid = true
+			oo.onuSwImageIndications.InActiveEntityEntry.Version = imageVersion
+			oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted = imageIsCommitted
+			//as the SW version indication may stem form some ONU Down/up event
+			//the complementary image state is to be invalidated
+			//  (state of the second image is always expected afterwards or just invalid)
+			oo.onuSwImageIndications.ActiveEntityEntry.Valid = false
+		}
+		oo.mutexOnuSwImageIndications.Unlock()
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvGetSecondSwVersion)
+		return
+	} else if cmn.SecondSwImageMeID == entityID {
+		//2nd image info might conflict with first image info, in which case we priorize first image info!
+		oo.mutexOnuSwImageIndications.Lock()
+		if imageIsActive == cmn.SwIsActive { //2nd image reported to be active
+			if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+				//conflict exists - state of first image is left active
+				logger.Warnw(ctx, "mibSync FSM - both ONU images are reported as active - assuming 2nd to be inactive",
+					log.Fields{"device-id": oo.deviceID})
+				oo.onuSwImageIndications.InActiveEntityEntry.EntityID = entityID
+				oo.onuSwImageIndications.InActiveEntityEntry.Valid = true ////to indicate that at least something has been reported
+				oo.onuSwImageIndications.InActiveEntityEntry.Version = imageVersion
+				oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted = imageIsCommitted
+			} else { //first image inactive, this one active
+				oo.onuSwImageIndications.ActiveEntityEntry.EntityID = entityID
+				oo.onuSwImageIndications.ActiveEntityEntry.Valid = true
+				oo.onuSwImageIndications.ActiveEntityEntry.Version = imageVersion
+				oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = imageIsCommitted
+			}
+		} else { //2nd image reported to be inactive
+			if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
+				//conflict exists - both images inactive - regard it as ONU failure and assume first image to be active
+				logger.Warnw(ctx, "mibSync FSM - both ONU images are reported as inactive, defining first to be active",
+					log.Fields{"device-id": oo.deviceID})
+				oo.onuSwImageIndications.ActiveEntityEntry.EntityID = cmn.FirstSwImageMeID
+				oo.onuSwImageIndications.ActiveEntityEntry.Valid = true //to indicate that at least something has been reported
+				//copy active commit/version from the previously stored inactive position
+				oo.onuSwImageIndications.ActiveEntityEntry.Version = oo.onuSwImageIndications.InActiveEntityEntry.Version
+				oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted
+			}
+			//in any case we indicate (and possibly overwrite) the second image indications as inactive
+			oo.onuSwImageIndications.InActiveEntityEntry.EntityID = entityID
+			oo.onuSwImageIndications.InActiveEntityEntry.Valid = true
+			oo.onuSwImageIndications.InActiveEntityEntry.Version = imageVersion
+			oo.onuSwImageIndications.InActiveEntityEntry.IsCommitted = imageIsCommitted
+		}
+		oo.mutexOnuSwImageIndications.Unlock()
+		_ = oo.PMibUploadFsm.PFsm.Event(UlEvGetMacAddress)
+		return
+	}
+}
+
+func (oo *OnuDeviceEntry) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
+	logger.Debugw(ctx, "MibSync Msg", log.Fields{"OmciMessage received for device-id": oo.deviceID,
+		"msgType": msg.OmciMsg.MessageType, "msg": msg})
+	//further analysis could be done here based on msg.OmciMsg.Payload, e.g. verification of error code ...
+	switch msg.OmciMsg.MessageType {
+	case omci.MibResetResponseType:
+		oo.handleOmciMibResetResponseMessage(ctx, msg)
+
+	case omci.MibUploadResponseType:
+		oo.handleOmciMibUploadResponseMessage(ctx, msg)
+
+	case omci.MibUploadNextResponseType:
+		oo.handleOmciMibUploadNextResponseMessage(ctx, msg)
+
+	case omci.GetResponseType:
+		//TODO: error handling
+		_ = oo.handleOmciGetResponseMessage(ctx, msg)
+
+	default:
+		logger.Warnw(ctx, "Unknown Message Type", log.Fields{"msgType": msg.OmciMsg.MessageType})
+
+	}
+}
+
+func (oo *OnuDeviceEntry) handleOmciGetResponseErrors(ctx context.Context, msgObj *omci.GetResponse) error {
+	var err error = nil
+	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 {
+		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)
+		err = fmt.Errorf("erroneous result in GetResponse Data: %s - %s", msgObj.Result, oo.deviceID)
+	}
+	return err
+}
+
+// IsNewOnu - TODO: add comment
+func (oo *OnuDeviceEntry) IsNewOnu() bool {
+	oo.MutexPersOnuConfig.RLock()
+	defer oo.MutexPersOnuConfig.RUnlock()
+	return oo.SOnuPersistentData.PersMibLastDbSync == 0
+}
+
+func isSupportedClassID(meClassID me.ClassID) bool {
+	for _, v := range supportedClassIds {
+		if v == meClassID {
+			return true
+		}
+	}
+	return false
+}
+
+func (oo *OnuDeviceEntry) mibDbVolatileDict(ctx context.Context) error {
+	logger.Debug(ctx, "MibVolatileDict- running from default Entry code")
+	return errors.New("not_implemented")
+}
+
+// createAndPersistMibTemplate method creates a mib template for the device id when operator enables the ONU device for the first time.
+// We are creating a placeholder for "SerialNumber" for ME Class ID 6 and 256 and "MacAddress" for ME Class ID 134 in the template
+// and then storing the template into etcd "service/voltha/omci_mibs/go_templates/verdor_id/equipment_id/software_version" path.
+func (oo *OnuDeviceEntry) createAndPersistMibTemplate(ctx context.Context) error {
+	logger.Debugw(ctx, "MibSync - MibTemplate - path name", log.Fields{"path": oo.mibTemplatePath,
+		"device-id": oo.deviceID})
+
+	oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+	if mibTemplateIsGenerated, exist := oo.pOpenOnuAc.GetMibTemplatesGenerated(oo.mibTemplatePath); exist {
+		if mibTemplateIsGenerated {
+			logger.Debugw(ctx, "MibSync - MibTemplate - another thread has already started to generate it - skip",
+				log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+			oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+			return nil
+		}
+		logger.Debugw(ctx, "MibSync - MibTemplate - previous generation attempt seems to be failed - try again",
+			log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+	} else {
+		logger.Debugw(ctx, "MibSync - MibTemplate - first ONU-instance of this kind - start generation",
+			log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+	}
+	oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, true)
+	oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+
+	currentTime := time.Now()
+	templateMap := make(map[string]interface{})
+	templateMap["TemplateName"] = oo.mibTemplatePath
+	templateMap["TemplateCreated"] = currentTime.Format("2006-01-02 15:04:05.000000")
+
+	firstLevelMap := oo.pOnuDB.MeDb
+	for firstLevelKey, firstLevelValue := range firstLevelMap {
+		logger.Debugw(ctx, "MibSync - MibTemplate - firstLevelKey", log.Fields{"firstLevelKey": firstLevelKey})
+		classID := strconv.Itoa(int(firstLevelKey))
+
+		secondLevelMap := make(map[string]interface{})
+		for secondLevelKey, secondLevelValue := range firstLevelValue {
+			thirdLevelMap := make(map[string]interface{})
+			entityID := strconv.Itoa(int(secondLevelKey))
+			thirdLevelMap["Attributes"] = secondLevelValue
+			thirdLevelMap["InstanceId"] = entityID
+			secondLevelMap[entityID] = thirdLevelMap
+			if classID == "6" || classID == "256" {
+				forthLevelMap := map[string]interface{}(thirdLevelMap["Attributes"].(me.AttributeValueMap))
+				delete(forthLevelMap, "SerialNumber")
+				forthLevelMap["SerialNumber"] = "%SERIAL_NUMBER%"
+
+			}
+			if classID == "134" {
+				forthLevelMap := map[string]interface{}(thirdLevelMap["Attributes"].(me.AttributeValueMap))
+				delete(forthLevelMap, "MacAddress")
+				forthLevelMap["MacAddress"] = "%MAC_ADDRESS%"
+			}
+		}
+		secondLevelMap["ClassId"] = classID
+		templateMap[classID] = secondLevelMap
+	}
+	mibTemplate, err := json.Marshal(&templateMap)
+	if err != nil {
+		logger.Errorw(ctx, "MibSync - MibTemplate - Failed to marshal mibTemplate", log.Fields{"error": err, "device-id": oo.deviceID})
+		oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+		oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, false)
+		oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+		return err
+	}
+	err = oo.mibTemplateKVStore.Put(log.WithSpanFromContext(context.TODO(), ctx), oo.mibTemplatePath, string(mibTemplate))
+	if err != nil {
+		logger.Errorw(ctx, "MibSync - MibTemplate - Failed to store template in etcd", log.Fields{"error": err, "device-id": oo.deviceID})
+		oo.pOpenOnuAc.LockMutexMibTemplateGenerated()
+		oo.pOpenOnuAc.SetMibTemplatesGenerated(oo.mibTemplatePath, false)
+		oo.pOpenOnuAc.UnlockMutexMibTemplateGenerated()
+		return err
+	}
+	logger.Debugw(ctx, "MibSync - MibTemplate - Stored the template to etcd", log.Fields{"device-id": oo.deviceID})
+	return nil
+}
+
+func (oo *OnuDeviceEntry) requestMdsValue(ctx context.Context) {
+	logger.Debugw(ctx, "Request MDS value", log.Fields{"device-id": oo.deviceID})
+	requestedAttributes := me.AttributeValueMap{"MibDataSync": ""}
+	meInstance, err := oo.PDevOmciCC.SendGetMe(log.WithSpanFromContext(context.TODO(), ctx),
+		me.OnuDataClassID, cmn.OnuDataMeID, requestedAttributes, oo.baseDeviceHandler.GetOmciTimeout(), 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 {
+		logger.Errorw(ctx, "ONUData get failed, aborting MibSync FSM!", log.Fields{"device-id": oo.deviceID})
+		pMibUlFsm := oo.PMibUploadFsm
+		if pMibUlFsm != nil {
+			go func(a_pAFsm *cmn.AdapterFsm) {
+				_ = oo.PMibUploadFsm.PFsm.Event(UlEvStop)
+			}(pMibUlFsm)
+		}
+		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})
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+		} else {
+			logger.Warnw(ctx, "MibSync FSM - mib audit - MDS check failed for the first time!", log.Fields{"device-id": oo.deviceID})
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+		}
+	} else if oo.PMibUploadFsm.PFsm.Is(UlStReAuditing) {
+		if mdsValuesAreEqual {
+			logger.Debugw(ctx, "MibSync FSM - mib reaudit - MDS check ok", log.Fields{"device-id": oo.deviceID})
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+		} else {
+			logger.Errorw(ctx, "MibSync FSM - mib audit - MDS check failed for the second time!", log.Fields{"device-id": oo.deviceID})
+			//TODO: send new event notification "MDS counter mismatch" to the core
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+		}
+	} else if oo.PMibUploadFsm.PFsm.Is(UlStExaminingMds) {
+		if mdsValuesAreEqual && mibDataSyncOnu != 0 {
+			logger.Debugw(ctx, "MibSync FSM - MDS examination ok", log.Fields{"device-id": oo.deviceID})
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvSuccess)
+		} else {
+			logger.Debugw(ctx, "MibSync FSM - MDS examination failed - new provisioning", log.Fields{"device-id": oo.deviceID})
+			_ = oo.PMibUploadFsm.PFsm.Event(UlEvMismatch)
+		}
+	} else {
+		logger.Warnw(ctx, "wrong state for MDS evaluation!", log.Fields{"state": oo.PMibUploadFsm.PFsm.Current(), "device-id": oo.deviceID})
+	}
+}
+
+//GetActiveImageMeID returns the Omci MeId of the active ONU image together with error code for validity
+func (oo *OnuDeviceEntry) GetActiveImageMeID(ctx context.Context) (uint16, error) {
+	oo.mutexOnuSwImageIndications.RLock()
+	if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+		value := oo.onuSwImageIndications.ActiveEntityEntry.EntityID
+		oo.mutexOnuSwImageIndications.RUnlock()
+		return value, nil
+	}
+	oo.mutexOnuSwImageIndications.RUnlock()
+	return 0xFFFF, fmt.Errorf("no valid active image found: %s", oo.deviceID)
+}
+
+//GetInactiveImageMeID returns the Omci MeId of the inactive ONU image together with error code for validity
+func (oo *OnuDeviceEntry) GetInactiveImageMeID(ctx context.Context) (uint16, error) {
+	oo.mutexOnuSwImageIndications.RLock()
+	if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
+		value := oo.onuSwImageIndications.InActiveEntityEntry.EntityID
+		oo.mutexOnuSwImageIndications.RUnlock()
+		return value, nil
+	}
+	oo.mutexOnuSwImageIndications.RUnlock()
+	return 0xFFFF, fmt.Errorf("no valid inactive image found: %s", oo.deviceID)
+}
+
+//IsImageToBeCommitted returns true if the active image is still uncommitted
+func (oo *OnuDeviceEntry) IsImageToBeCommitted(ctx context.Context, aImageID uint16) bool {
+	oo.mutexOnuSwImageIndications.RLock()
+	if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+		if oo.onuSwImageIndications.ActiveEntityEntry.EntityID == aImageID {
+			if oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted == cmn.SwIsUncommitted {
+				oo.mutexOnuSwImageIndications.RUnlock()
+				return true
+			}
+		}
+	}
+	oo.mutexOnuSwImageIndications.RUnlock()
+	return false //all other case are treated as 'nothing to commit
+}
+func (oo *OnuDeviceEntry) getMibFromTemplate(ctx context.Context) bool {
+
+	oo.mibTemplatePath = oo.buildMibTemplatePath()
+	logger.Debugw(ctx, "MibSync FSM - get Mib from template", log.Fields{"path": fmt.Sprintf("%s/%s", cBasePathMibTemplateKvStore, oo.mibTemplatePath),
+		"device-id": oo.deviceID})
+
+	restoredFromMibTemplate := false
+	Value, err := oo.mibTemplateKVStore.Get(log.WithSpanFromContext(context.TODO(), ctx), oo.mibTemplatePath)
+	if err == nil {
+		if Value != nil {
+			logger.Debugf(ctx, "MibSync FSM - Mib template read: Key: %s, Value: %s  %s", Value.Key, Value.Value)
+
+			// 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)
+
+			var firstLevelMap map[string]interface{}
+			if err = json.Unmarshal(mibTmpBytes, &firstLevelMap); err != nil {
+				logger.Errorw(ctx, "MibSync FSM - Failed to unmarshal template", log.Fields{"error": err, "device-id": oo.deviceID})
+			} else {
+				for firstLevelKey, firstLevelValue := range firstLevelMap {
+					//logger.Debugw(ctx, "MibSync FSM - firstLevelKey", log.Fields{"firstLevelKey": firstLevelKey})
+					if uint16ValidNumber, err := strconv.ParseUint(firstLevelKey, 10, 16); err == nil {
+						meClassID := me.ClassID(uint16ValidNumber)
+						//logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a number in uint16-range", log.Fields{"uint16ValidNumber": uint16ValidNumber})
+						if isSupportedClassID(meClassID) {
+							//logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a supported classID", log.Fields{"meClassID": meClassID})
+							secondLevelMap := firstLevelValue.(map[string]interface{})
+							for secondLevelKey, secondLevelValue := range secondLevelMap {
+								//logger.Debugw(ctx, "MibSync FSM - secondLevelKey", log.Fields{"secondLevelKey": secondLevelKey})
+								if uint16ValidNumber, err := strconv.ParseUint(secondLevelKey, 10, 16); err == nil {
+									meEntityID := uint16(uint16ValidNumber)
+									//logger.Debugw(ctx, "MibSync FSM - secondLevelKey is a number and a valid EntityId", log.Fields{"meEntityID": meEntityID})
+									thirdLevelMap := secondLevelValue.(map[string]interface{})
+									for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
+										if thirdLevelKey == "Attributes" {
+											//logger.Debugw(ctx, "MibSync FSM - thirdLevelKey refers to attributes", log.Fields{"thirdLevelKey": thirdLevelKey})
+											attributesMap := thirdLevelValue.(map[string]interface{})
+											//logger.Debugw(ctx, "MibSync FSM - attributesMap", log.Fields{"attributesMap": attributesMap})
+											oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, attributesMap)
+											restoredFromMibTemplate = true
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		} else {
+			logger.Debugw(ctx, "No MIB template found", log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+		}
+	} else {
+		logger.Errorf(ctx, "Get from kvstore operation failed for path",
+			log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+	}
+	return restoredFromMibTemplate
+}
+
+//CancelProcessing terminates potentially running reconciling processes and stops the FSM
+func (oo *OnuDeviceEntry) CancelProcessing(ctx context.Context) {
+
+	if oo.IsReconcilingFlows() {
+		oo.chReconcilingFlowsFinished <- false
+	}
+	if oo.baseDeviceHandler.IsReconciling() {
+		oo.baseDeviceHandler.StopReconciling(ctx, false)
+	}
+	//the MibSync FSM might be active all the ONU-active time,
+	// hence it must be stopped unconditionally
+	pMibUlFsm := oo.PMibUploadFsm.PFsm
+	if pMibUlFsm != nil {
+		_ = pMibUlFsm.Event(UlEvStop)
+	}
+}
diff --git a/internal/pkg/mib/onu_device_entry.go b/internal/pkg/mib/onu_device_entry.go
new file mode 100755
index 0000000..ebf8de8
--- /dev/null
+++ b/internal/pkg/mib/onu_device_entry.go
@@ -0,0 +1,992 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Package mib provides the utilities for managing the onu mib
+package mib
+
+import (
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"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/v7/pkg/db"
+	"github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
+	vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
+
+	"github.com/opencord/voltha-lib-go/v7/pkg/log"
+
+	cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
+	devdb "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/devdb"
+	"github.com/opencord/voltha-openonu-adapter-go/internal/pkg/swupg"
+)
+
+// events of MibUpload FSM
+const (
+	UlEvStart              = "UlEvStart"
+	UlEvResetMib           = "UlEvResetMib"
+	UlEvGetVendorAndSerial = "UlEvGetVendorAndSerial"
+	UlEvGetEquipmentID     = "UlEvGetEquipmentId"
+	UlEvGetFirstSwVersion  = "UlEvGetFirstSwVersion"
+	UlEvGetSecondSwVersion = "UlEvGetSecondSwVersion"
+	UlEvGetMacAddress      = "UlEvGetMacAddress"
+	UlEvGetMibTemplate     = "UlEvGetMibTemplate"
+	UlEvUploadMib          = "UlEvUploadMib"
+	UlEvExamineMds         = "UlEvExamineMds"
+	UlEvSuccess            = "UlEvSuccess"
+	UlEvMismatch           = "UlEvMismatch"
+	UlEvAuditMib           = "UlEvAuditMib"
+	UlEvForceResync        = "UlEvForceResync"
+	UlEvDiffsFound         = "UlEvDiffsFound"
+	UlEvTimeout            = "UlEvTimeout"
+	UlEvStop               = "UlEvStop"
+)
+
+// states of MibUpload FSM
+const (
+	UlStDisabled               = "UlStDisabled"
+	UlStStarting               = "UlStStarting"
+	UlStResettingMib           = "UlStResettingMib"
+	UlStGettingVendorAndSerial = "UlStGettingVendorAndSerial"
+	UlStGettingEquipmentID     = "UlStGettingEquipmentID"
+	UlStGettingFirstSwVersion  = "UlStGettingFirstSwVersion"
+	UlStGettingSecondSwVersion = "UlStGettingSecondSwVersion"
+	UlStGettingMacAddress      = "UlStGettingMacAddress"
+	UlStGettingMibTemplate     = "UlStGettingMibTemplate"
+	UlStUploading              = "UlStUploading"
+	UlStUploadDone             = "UlStUploadDone"
+	UlStInSync                 = "UlStInSync"
+	UlStExaminingMds           = "UlStExaminingMds"
+	UlStResynchronizing        = "UlStResynchronizing"
+	UlStExaminingMdsSuccess    = "UlStExaminingMdsSuccess"
+	UlStAuditing               = "UlStAuditing"
+	UlStReAuditing             = "UlStReAuditing"
+	UlStOutOfSync              = "UlStOutOfSync"
+)
+
+// CMibUlFsmIdleState - TODO: add comment
+const CMibUlFsmIdleState = UlStInSync
+
+// events of MibDownload FSM
+const (
+	DlEvStart         = "DlEvStart"
+	DlEvCreateGal     = "DlEvCreateGal"
+	DlEvRxGalResp     = "DlEvRxGalResp"
+	DlEvRxOnu2gResp   = "DlEvRxOnu2gResp"
+	DlEvRxBridgeResp  = "DlEvRxBridgeResp"
+	DlEvTimeoutSimple = "DlEvTimeoutSimple"
+	DlEvTimeoutBridge = "DlEvTimeoutBridge"
+	DlEvReset         = "DlEvReset"
+	DlEvRestart       = "DlEvRestart"
+)
+
+// states of MibDownload FSM
+const (
+	DlStDisabled     = "DlStDisabled"
+	DlStStarting     = "DlStStarting"
+	DlStCreatingGal  = "DlStCreatingGal"
+	DlStSettingOnu2g = "DlStSettingOnu2g"
+	DlStBridgeInit   = "DlStBridgeInit"
+	DlStDownloaded   = "DlStDownloaded"
+	DlStResetting    = "DlStResetting"
+)
+
+// CMibDlFsmIdleState - TODO: add comment
+const CMibDlFsmIdleState = DlStDisabled
+
+const (
+	// NOTE that this hardcoded to service/voltha as the MIB template is shared across stacks
+	cBasePathMibTemplateKvStore = "service/voltha/omci_mibs/go_templates"
+	cSuffixMibTemplateKvStore   = "%s/%s/%s"
+	cBasePathOnuKVStore         = "%s/openonu"
+)
+
+const cEmptyMacAddrString = "000000000000"
+const cEmptySerialNumberString = "0000000000000000"
+
+type uniPersConfig struct {
+	PersUniID      uint8                   `json:"uni_id"`
+	PersTpPathMap  map[uint8]string        `json:"PersTpPathMap"` // tp-id to tp-path map
+	PersFlowParams []cmn.UniVlanFlowParams `json:"flow_params"`   //as defined in omci_ani_config.go
+}
+
+type onuPersistentData struct {
+	PersOnuID              uint32            `json:"onu_id"`
+	PersIntfID             uint32            `json:"intf_id"`
+	PersSerialNumber       string            `json:"serial_number"`
+	PersMacAddress         string            `json:"mac_address"`
+	PersVendorID           string            `json:"vendor_id"`
+	PersEquipmentID        string            `json:"equipment_id"`
+	PersActiveSwVersion    string            `json:"active_sw_version"`
+	PersAdminState         string            `json:"admin_state"`
+	PersOperState          string            `json:"oper_state"`
+	PersUniUnlockDone      bool              `json:"uni_unlock_done"`
+	PersUniDisableDone     bool              `json:"uni_disable_done"`
+	PersMibAuditInterval   time.Duration     `json:"mib_audit_interval"`
+	PersMibLastDbSync      uint32            `json:"mib_last_db_sync"`
+	PersMibDataSyncAdpt    uint8             `json:"mib_data_sync_adpt"`
+	PersUniConfig          []uniPersConfig   `json:"uni_config"`
+	PersAlarmAuditInterval time.Duration     `json:"alarm_audit_interval"`
+	PersTcontMap           map[uint16]uint16 `json:"tcont_map"` //alloc-id to me-instance-id map
+}
+
+// OnuDeviceEntry - ONU device info and FSM events.
+type OnuDeviceEntry struct {
+	deviceID                   string
+	baseDeviceHandler          cmn.IdeviceHandler
+	pOpenOnuAc                 cmn.IopenONUAC
+	pOnuTP                     cmn.IonuUniTechProf
+	coreClient                 *vgrpc.Client
+	PDevOmciCC                 *cmn.OmciCC
+	pOnuDB                     *devdb.OnuDeviceDB
+	mibTemplateKVStore         *db.Backend
+	MutexPersOnuConfig         sync.RWMutex
+	SOnuPersistentData         onuPersistentData
+	reconcilingFlows           bool
+	mutexReconcilingFlowsFlag  sync.RWMutex
+	chReconcilingFlowsFinished chan bool //channel to indicate that reconciling of flows has been finished
+	mibTemplatePath            string
+	mutexOnuKVStore            sync.RWMutex
+	onuKVStore                 *db.Backend
+	onuKVStorePath             string
+	mutexOnuKVStoreProcResult  sync.RWMutex
+	onuKVStoreProcResult       error //error indication of processing
+	chOnuKvProcessingStep      chan uint8
+	mutexOnuSwImageIndications sync.RWMutex
+	onuSwImageIndications      cmn.SswImageIndications
+	MutexOnuImageStatus        sync.RWMutex
+	POnuImageStatus            *swupg.OnuImageStatus
+	//lockDeviceEntries           sync.RWMutex
+	mibDbClass    func(context.Context) error
+	supportedFsms cmn.OmciDeviceFsms
+	devState      cmn.OnuDeviceEvent
+	// Audit and MDS
+	mibAuditInterval   time.Duration
+	alarmAuditInterval time.Duration
+	// TODO: periodical mib resync will be implemented with story VOL-3792
+	//mibNextDbResync uint32
+
+	// for mibUpload
+	PMibUploadFsm          *cmn.AdapterFsm //could be handled dynamically and more general as pcmn.AdapterFsm - perhaps later
+	mutexLastTxParamStruct sync.RWMutex
+	lastTxParamStruct      sLastTxMeParameter
+	// for mibDownload
+	PMibDownloadFsm *cmn.AdapterFsm //could be handled dynamically and more general as pcmn.AdapterFsm - perhaps later
+	//remark: general usage of pAdapterFsm would require generalization of CommChan  usage and internal event setting
+	//  within the FSM event procedures
+	mutexPLastTxMeInstance           sync.RWMutex
+	pLastTxMeInstance                *me.ManagedEntity
+	omciMessageReceived              chan bool        //seperate channel needed by DownloadFsm
+	omciRebootMessageReceivedChannel chan cmn.Message // channel needed by reboot request
+
+	mutexTcontMap sync.RWMutex
+}
+
+//NewOnuDeviceEntry returns a new instance of a OnuDeviceEntry
+//mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
+func NewOnuDeviceEntry(ctx context.Context, cc *vgrpc.Client, dh cmn.IdeviceHandler,
+	openonu cmn.IopenONUAC) *OnuDeviceEntry {
+	var onuDeviceEntry OnuDeviceEntry
+	onuDeviceEntry.deviceID = dh.GetDeviceID()
+	logger.Debugw(ctx, "init-onuDeviceEntry", log.Fields{"device-id": onuDeviceEntry.deviceID})
+	onuDeviceEntry.baseDeviceHandler = dh
+	onuDeviceEntry.pOpenOnuAc = openonu
+	onuDeviceEntry.coreClient = cc
+	onuDeviceEntry.devState = cmn.DeviceStatusInit
+	onuDeviceEntry.SOnuPersistentData.PersUniConfig = make([]uniPersConfig, 0)
+	onuDeviceEntry.SOnuPersistentData.PersTcontMap = make(map[uint16]uint16)
+	onuDeviceEntry.chReconcilingFlowsFinished = make(chan bool)
+	onuDeviceEntry.reconcilingFlows = false
+	onuDeviceEntry.chOnuKvProcessingStep = make(chan uint8)
+	onuDeviceEntry.omciRebootMessageReceivedChannel = make(chan cmn.Message, 2048)
+	//openomciagent.lockDeviceHandlersMap = sync.RWMutex{}
+	//OMCI related databases are on a per-agent basis. State machines and tasks
+	//are per ONU Vendor
+	//
+	// MIB Synchronization Database - possible overloading from arguments
+	supportedFsms := onuDeviceEntry.pOpenOnuAc.GetSupportedFsms()
+	if supportedFsms != nil {
+		onuDeviceEntry.supportedFsms = *supportedFsms
+	} else {
+		// This branch is currently not used and is for potential future usage of alternative MIB Sync FSMs only!
+		//var mibSyncFsm = NewMibSynchronizer()
+		// use some internal defaults, if not defined from outside
+		onuDeviceEntry.supportedFsms = cmn.OmciDeviceFsms{
+			"mib-synchronizer": {
+				//mibSyncFsm,        // Implements the MIB synchronization state machine
+				DatabaseClass: onuDeviceEntry.mibDbVolatileDict, // Implements volatile ME MIB database
+				//true,                             // Advertise events on OpenOMCI event bus
+				AuditInterval: dh.GetAlarmAuditInterval(), // Time to wait between MIB audits.  0 to disable audits.
+				// map[string]func() error{
+				// 	"mib-upload":    onuDeviceEntry.MibUploadTask,
+				// 	"mib-template":  onuDeviceEntry.MibTemplateTask,
+				// 	"get-mds":       onuDeviceEntry.GetMdsTask,
+				// 	"mib-audit":     onuDeviceEntry.GetMdsTask,
+				// 	"mib-resync":    onuDeviceEntry.MibResyncTask,
+				// 	"mib-reconcile": onuDeviceEntry.MibReconcileTask,
+				// },
+			},
+		}
+	}
+	onuDeviceEntry.mibDbClass = onuDeviceEntry.supportedFsms["mib-synchronizer"].DatabaseClass
+	logger.Debug(ctx, "access2mibDbClass")
+	go onuDeviceEntry.mibDbClass(ctx)
+	if !dh.IsReconciling() {
+		onuDeviceEntry.mibAuditInterval = onuDeviceEntry.supportedFsms["mib-synchronizer"].AuditInterval
+		onuDeviceEntry.SOnuPersistentData.PersMibAuditInterval = onuDeviceEntry.mibAuditInterval
+		onuDeviceEntry.alarmAuditInterval = dh.GetAlarmAuditInterval()
+		onuDeviceEntry.SOnuPersistentData.PersAlarmAuditInterval = onuDeviceEntry.alarmAuditInterval
+	} else {
+		logger.Debugw(ctx, "reconciling - take audit interval from persistent data", log.Fields{"device-id": onuDeviceEntry.deviceID})
+		// TODO: This is a preparation for VOL-VOL-3811 to preserve config history in case of
+		// vendor- or deviceID-specific configurations via voltctl-commands
+		onuDeviceEntry.mibAuditInterval = onuDeviceEntry.SOnuPersistentData.PersMibAuditInterval
+		onuDeviceEntry.alarmAuditInterval = onuDeviceEntry.SOnuPersistentData.PersAlarmAuditInterval
+	}
+	logger.Debugw(ctx, "MibAuditInterval and AlarmAuditInterval is set to", log.Fields{"mib-audit-interval": onuDeviceEntry.mibAuditInterval,
+		"alarm-audit-interval": onuDeviceEntry.alarmAuditInterval})
+	// TODO: periodical mib resync will be implemented with story VOL-3792
+	//onuDeviceEntry.mibNextDbResync = 0
+
+	// Omci related Mib upload sync state machine
+	mibUploadChan := make(chan cmn.Message, 2048)
+	onuDeviceEntry.PMibUploadFsm = cmn.NewAdapterFsm("MibUpload", onuDeviceEntry.deviceID, mibUploadChan)
+	onuDeviceEntry.PMibUploadFsm.PFsm = fsm.NewFSM(
+		UlStDisabled,
+		fsm.Events{
+
+			{Name: UlEvStart, Src: []string{UlStDisabled}, Dst: UlStStarting},
+
+			{Name: UlEvResetMib, Src: []string{UlStStarting}, Dst: UlStResettingMib},
+			{Name: UlEvGetVendorAndSerial, Src: []string{UlStResettingMib}, Dst: UlStGettingVendorAndSerial},
+			{Name: UlEvGetEquipmentID, Src: []string{UlStGettingVendorAndSerial}, Dst: UlStGettingEquipmentID},
+			{Name: UlEvGetFirstSwVersion, Src: []string{UlStGettingEquipmentID}, Dst: UlStGettingFirstSwVersion},
+			{Name: UlEvGetSecondSwVersion, Src: []string{UlStGettingFirstSwVersion}, Dst: UlStGettingSecondSwVersion},
+			{Name: UlEvGetMacAddress, Src: []string{UlStGettingSecondSwVersion}, Dst: UlStGettingMacAddress},
+			{Name: UlEvGetMibTemplate, Src: []string{UlStGettingMacAddress}, Dst: UlStGettingMibTemplate},
+
+			{Name: UlEvUploadMib, Src: []string{UlStGettingMibTemplate}, Dst: UlStUploading},
+			{Name: UlEvExamineMds, Src: []string{UlStStarting}, Dst: UlStExaminingMds},
+
+			{Name: UlEvSuccess, Src: []string{UlStGettingMibTemplate}, Dst: UlStUploadDone},
+			{Name: UlEvSuccess, Src: []string{UlStUploading}, Dst: UlStUploadDone},
+
+			{Name: UlEvSuccess, Src: []string{UlStUploadDone}, Dst: UlStInSync},
+			//{Name: UlEvSuccess, Src: []string{UlStExaminingMds}, Dst: UlStInSync},
+			{Name: UlEvSuccess, Src: []string{UlStExaminingMds}, Dst: UlStExaminingMdsSuccess},
+			// TODO: As long as mib-resynchronizing is not implemented, failed MDS-examination triggers
+			// mib-reset and new provisioning at this point
+			//{Name: UlEvMismatch, Src: []string{UlStExaminingMds}, Dst: UlStResynchronizing},
+			{Name: UlEvMismatch, Src: []string{UlStExaminingMds}, Dst: UlStResettingMib},
+
+			{Name: UlEvSuccess, Src: []string{UlStExaminingMdsSuccess}, Dst: UlStInSync},
+			{Name: UlEvMismatch, Src: []string{UlStExaminingMdsSuccess}, Dst: UlStResettingMib},
+
+			{Name: UlEvAuditMib, Src: []string{UlStInSync}, Dst: UlStAuditing},
+
+			{Name: UlEvSuccess, Src: []string{UlStOutOfSync}, Dst: UlStInSync},
+			{Name: UlEvAuditMib, Src: []string{UlStOutOfSync}, Dst: UlStAuditing},
+
+			{Name: UlEvSuccess, Src: []string{UlStAuditing}, Dst: UlStInSync},
+			{Name: UlEvMismatch, Src: []string{UlStAuditing}, Dst: UlStReAuditing},
+			{Name: UlEvForceResync, Src: []string{UlStAuditing}, Dst: UlStResynchronizing},
+
+			{Name: UlEvSuccess, Src: []string{UlStReAuditing}, Dst: UlStInSync},
+			{Name: UlEvMismatch, Src: []string{UlStReAuditing}, Dst: UlStResettingMib},
+
+			{Name: UlEvSuccess, Src: []string{UlStResynchronizing}, Dst: UlStInSync},
+			{Name: UlEvDiffsFound, Src: []string{UlStResynchronizing}, Dst: UlStOutOfSync},
+
+			{Name: UlEvTimeout, Src: []string{UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipmentID, UlStGettingFirstSwVersion,
+				UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing, UlStExaminingMds,
+				UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStStarting},
+
+			{Name: UlEvStop, Src: []string{UlStStarting, UlStResettingMib, UlStGettingVendorAndSerial, UlStGettingEquipmentID, UlStGettingFirstSwVersion,
+				UlStGettingSecondSwVersion, UlStGettingMacAddress, UlStGettingMibTemplate, UlStUploading, UlStResynchronizing, UlStExaminingMds,
+				UlStUploadDone, UlStInSync, UlStOutOfSync, UlStAuditing, UlStReAuditing}, Dst: UlStDisabled},
+		},
+
+		fsm.Callbacks{
+			"enter_state":                         func(e *fsm.Event) { onuDeviceEntry.PMibUploadFsm.LogFsmStateChange(ctx, e) },
+			"enter_" + UlStStarting:               func(e *fsm.Event) { onuDeviceEntry.enterStartingState(ctx, e) },
+			"enter_" + UlStResettingMib:           func(e *fsm.Event) { onuDeviceEntry.enterResettingMibState(ctx, e) },
+			"enter_" + UlStGettingVendorAndSerial: func(e *fsm.Event) { onuDeviceEntry.enterGettingVendorAndSerialState(ctx, e) },
+			"enter_" + UlStGettingEquipmentID:     func(e *fsm.Event) { onuDeviceEntry.enterGettingEquipmentIDState(ctx, e) },
+			"enter_" + UlStGettingFirstSwVersion:  func(e *fsm.Event) { onuDeviceEntry.enterGettingFirstSwVersionState(ctx, e) },
+			"enter_" + UlStGettingSecondSwVersion: func(e *fsm.Event) { onuDeviceEntry.enterGettingSecondSwVersionState(ctx, e) },
+			"enter_" + UlStGettingMacAddress:      func(e *fsm.Event) { onuDeviceEntry.enterGettingMacAddressState(ctx, e) },
+			"enter_" + UlStGettingMibTemplate:     func(e *fsm.Event) { onuDeviceEntry.enterGettingMibTemplateState(ctx, e) },
+			"enter_" + UlStUploading:              func(e *fsm.Event) { onuDeviceEntry.enterUploadingState(ctx, e) },
+			"enter_" + UlStUploadDone:             func(e *fsm.Event) { onuDeviceEntry.enterUploadDoneState(ctx, e) },
+			"enter_" + UlStExaminingMds:           func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsState(ctx, e) },
+			"enter_" + UlStResynchronizing:        func(e *fsm.Event) { onuDeviceEntry.enterResynchronizingState(ctx, e) },
+			"enter_" + UlStExaminingMdsSuccess:    func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsSuccessState(ctx, e) },
+			"enter_" + UlStAuditing:               func(e *fsm.Event) { onuDeviceEntry.enterAuditingState(ctx, e) },
+			"enter_" + UlStReAuditing:             func(e *fsm.Event) { onuDeviceEntry.enterReAuditingState(ctx, e) },
+			"enter_" + UlStOutOfSync:              func(e *fsm.Event) { onuDeviceEntry.enterOutOfSyncState(ctx, e) },
+			"enter_" + UlStInSync:                 func(e *fsm.Event) { onuDeviceEntry.enterInSyncState(ctx, e) },
+		},
+	)
+	// Omci related Mib download state machine
+	mibDownloadChan := make(chan cmn.Message, 2048)
+	onuDeviceEntry.PMibDownloadFsm = cmn.NewAdapterFsm("MibDownload", onuDeviceEntry.deviceID, mibDownloadChan)
+	onuDeviceEntry.PMibDownloadFsm.PFsm = fsm.NewFSM(
+		DlStDisabled,
+		fsm.Events{
+
+			{Name: DlEvStart, Src: []string{DlStDisabled}, Dst: DlStStarting},
+
+			{Name: DlEvCreateGal, Src: []string{DlStStarting}, Dst: DlStCreatingGal},
+			{Name: DlEvRxGalResp, Src: []string{DlStCreatingGal}, Dst: DlStSettingOnu2g},
+			{Name: DlEvRxOnu2gResp, Src: []string{DlStSettingOnu2g}, Dst: DlStBridgeInit},
+			// the bridge state is used for multi ME config for alle UNI related ports
+			// maybe such could be reflected in the state machine as well (port number parametrized)
+			// but that looks not straightforward here - so we keep it simple here for the beginning(?)
+			{Name: DlEvRxBridgeResp, Src: []string{DlStBridgeInit}, Dst: DlStDownloaded},
+
+			{Name: DlEvTimeoutSimple, Src: []string{DlStCreatingGal, DlStSettingOnu2g}, Dst: DlStStarting},
+			{Name: DlEvTimeoutBridge, Src: []string{DlStBridgeInit}, Dst: DlStStarting},
+
+			{Name: DlEvReset, Src: []string{DlStStarting, DlStCreatingGal, DlStSettingOnu2g,
+				DlStBridgeInit, DlStDownloaded}, Dst: DlStResetting},
+			// exceptional treatment for all states except DlStResetting
+			{Name: DlEvRestart, Src: []string{DlStStarting, DlStCreatingGal, DlStSettingOnu2g,
+				DlStBridgeInit, DlStDownloaded, DlStResetting}, Dst: DlStDisabled},
+		},
+
+		fsm.Callbacks{
+			"enter_state":               func(e *fsm.Event) { onuDeviceEntry.PMibDownloadFsm.LogFsmStateChange(ctx, e) },
+			"enter_" + DlStStarting:     func(e *fsm.Event) { onuDeviceEntry.enterDLStartingState(ctx, e) },
+			"enter_" + DlStCreatingGal:  func(e *fsm.Event) { onuDeviceEntry.enterCreatingGalState(ctx, e) },
+			"enter_" + DlStSettingOnu2g: func(e *fsm.Event) { onuDeviceEntry.enterSettingOnu2gState(ctx, e) },
+			"enter_" + DlStBridgeInit:   func(e *fsm.Event) { onuDeviceEntry.enterBridgeInitState(ctx, e) },
+			"enter_" + DlStDownloaded:   func(e *fsm.Event) { onuDeviceEntry.enterDownloadedState(ctx, e) },
+			"enter_" + DlStResetting:    func(e *fsm.Event) { onuDeviceEntry.enterResettingState(ctx, e) },
+		},
+	)
+	if onuDeviceEntry.PMibDownloadFsm == nil || onuDeviceEntry.PMibDownloadFsm.PFsm == nil {
+		logger.Errorw(ctx, "MibDownloadFsm could not be instantiated", log.Fields{"device-id": onuDeviceEntry.deviceID})
+		// TODO some specific error treatment - or waiting for crash ?
+	}
+
+	onuDeviceEntry.mibTemplateKVStore = onuDeviceEntry.baseDeviceHandler.SetBackend(ctx, cBasePathMibTemplateKvStore)
+	if onuDeviceEntry.mibTemplateKVStore == nil {
+		logger.Errorw(ctx, "Can't access mibTemplateKVStore - no backend connection to service",
+			log.Fields{"device-id": onuDeviceEntry.deviceID, "service": cBasePathMibTemplateKvStore})
+	}
+
+	onuDeviceEntry.onuKVStorePath = onuDeviceEntry.deviceID
+	baseKvStorePath := fmt.Sprintf(cBasePathOnuKVStore, dh.GetBackendPathPrefix())
+	onuDeviceEntry.onuKVStore = onuDeviceEntry.baseDeviceHandler.SetBackend(ctx, baseKvStorePath)
+	if onuDeviceEntry.onuKVStore == nil {
+		logger.Errorw(ctx, "Can't access onuKVStore - no backend connection to service",
+			log.Fields{"device-id": onuDeviceEntry.deviceID, "service": baseKvStorePath})
+	}
+
+	// Alarm Synchronization Database
+
+	//self._alarm_db = None
+	//self._alarm_database_cls = support_classes['alarm-synchronizer']['database']
+	return &onuDeviceEntry
+}
+
+//Start starts (logs) the omci agent
+func (oo *OnuDeviceEntry) Start(ctx context.Context) error {
+	logger.Debugw(ctx, "OnuDeviceEntry-starting", log.Fields{"for device-id": oo.deviceID})
+	if oo.PDevOmciCC == nil {
+		oo.PDevOmciCC = cmn.NewOmciCC(ctx, oo.deviceID, oo.baseDeviceHandler, oo, oo.baseDeviceHandler.GetOnuAlarmManager(), oo.coreClient)
+		if oo.PDevOmciCC == nil {
+			logger.Errorw(ctx, "Could not create devOmciCc - abort", log.Fields{"for device-id": oo.deviceID})
+			return fmt.Errorf("could not create devOmciCc %s", oo.deviceID)
+		}
+	}
+	return nil
+}
+
+//Stop stops/resets the omciCC
+func (oo *OnuDeviceEntry) Stop(ctx context.Context, abResetOmciCC bool) error {
+	logger.Debugw(ctx, "OnuDeviceEntry-stopping", log.Fields{"for device-id": oo.deviceID})
+	if abResetOmciCC && (oo.PDevOmciCC != nil) {
+		_ = oo.PDevOmciCC.Stop(ctx)
+	}
+	//to allow for all event notifications again when re-using the device and omciCC
+	oo.devState = cmn.DeviceStatusInit
+	return nil
+}
+
+// Reboot - TODO: add comment
+func (oo *OnuDeviceEntry) Reboot(ctx context.Context) error {
+	logger.Debugw(ctx, "OnuDeviceEntry-rebooting", log.Fields{"for device-id": oo.deviceID})
+	if oo.PDevOmciCC != nil {
+		if err := oo.PDevOmciCC.SendReboot(ctx, oo.baseDeviceHandler.GetOmciTimeout(), true, oo.omciRebootMessageReceivedChannel); err != nil {
+			logger.Errorw(ctx, "onu didn't reboot", log.Fields{"for device-id": oo.deviceID})
+			return err
+		}
+	}
+	return nil
+}
+
+// WaitForRebootResponse - TODO: add comment
+func (oo *OnuDeviceEntry) WaitForRebootResponse(ctx context.Context, responseChannel chan cmn.Message) error {
+	select {
+	case <-time.After(oo.PDevOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
+		logger.Warnw(ctx, "reboot timeout", log.Fields{"for device-id": oo.deviceID})
+		return fmt.Errorf("rebootTimeout")
+	case data := <-responseChannel:
+		switch data.Data.(cmn.OmciMessage).OmciMsg.MessageType {
+		case omci.RebootResponseType:
+			{
+				msgLayer := (*data.Data.(cmn.OmciMessage).OmciPacket).Layer(omci.LayerTypeRebootResponse)
+				if msgLayer == nil {
+					return fmt.Errorf("omci Msg layer could not be detected for RebootResponseType")
+				}
+				msgObj, msgOk := msgLayer.(*omci.RebootResponse)
+				if !msgOk {
+					return fmt.Errorf("omci Msg layer could not be assigned for RebootResponseType %s", oo.deviceID)
+				}
+				logger.Debugw(ctx, "RebootResponse data", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
+				if msgObj.Result != me.Success {
+					logger.Errorw(ctx, "Omci RebootResponse result error", log.Fields{"device-id": oo.deviceID, "Error": msgObj.Result})
+					// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+					return fmt.Errorf("omci RebootResponse result error indication %s for device %s",
+						msgObj.Result, oo.deviceID)
+				}
+				return nil
+			}
+		}
+		logger.Warnw(ctx, "Reboot response message type error", log.Fields{"for device-id": oo.deviceID})
+		return fmt.Errorf("unexpected OmciResponse type received %s", oo.deviceID)
+	}
+}
+
+//Relay the InSync message via Handler to Rw core - Status update
+func (oo *OnuDeviceEntry) transferSystemEvent(ctx context.Context, devEvent cmn.OnuDeviceEvent) {
+	logger.Debugw(ctx, "relaying system-event", log.Fields{"Event": devEvent})
+	// decouple the handler transfer from further processing here
+	// TODO!!! check if really no synch is required within the system e.g. to ensure following steps ..
+	if devEvent == cmn.MibDatabaseSync {
+		if oo.devState < cmn.MibDatabaseSync { //devState has not been synced yet
+			oo.devState = cmn.MibDatabaseSync
+			go oo.baseDeviceHandler.DeviceProcStatusUpdate(ctx, devEvent)
+			//TODO!!! device control: next step: start MIB capability verification from here ?!!!
+		} else {
+			logger.Debugw(ctx, "mibinsync-event in some already synced state - ignored", log.Fields{"state": oo.devState})
+		}
+	} else if devEvent == cmn.MibDownloadDone {
+		if oo.devState < cmn.MibDownloadDone { //devState has not been synced yet
+			oo.devState = cmn.MibDownloadDone
+			go oo.baseDeviceHandler.DeviceProcStatusUpdate(ctx, devEvent)
+		} else {
+			logger.Debugw(ctx, "mibdownloaddone-event was already seen - ignored", log.Fields{"state": oo.devState})
+		}
+	} else {
+		logger.Warnw(ctx, "device-event not yet handled", log.Fields{"state": devEvent})
+	}
+}
+
+// RestoreDataFromOnuKvStore - TODO: add comment
+func (oo *OnuDeviceEntry) RestoreDataFromOnuKvStore(ctx context.Context) error {
+	if oo.onuKVStore == nil {
+		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.MutexPersOnuConfig.Lock()
+	defer oo.MutexPersOnuConfig.Unlock()
+	oo.SOnuPersistentData =
+		onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
+	oo.mutexOnuKVStore.RLock()
+	Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
+	oo.mutexOnuKVStore.RUnlock()
+	if err == nil {
+		if Value != nil {
+			logger.Debugw(ctx, "ONU-data read",
+				log.Fields{"Key": Value.Key, "device-id": oo.deviceID})
+			tmpBytes, _ := kvstore.ToByte(Value.Value)
+
+			if err = json.Unmarshal(tmpBytes, &oo.SOnuPersistentData); err != nil {
+				logger.Errorw(ctx, "unable to unmarshal ONU-data", log.Fields{"error": err, "device-id": oo.deviceID})
+				return fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-ONU-data-%s", oo.deviceID))
+			}
+			logger.Debugw(ctx, "ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
+				"device-id": oo.deviceID})
+		} else {
+			logger.Debugw(ctx, "no ONU-data found", log.Fields{"path": oo.onuKVStorePath, "device-id": oo.deviceID})
+			return fmt.Errorf("no-ONU-data-found")
+		}
+	} else {
+		logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": oo.deviceID})
+		return fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s", oo.deviceID))
+	}
+	return nil
+}
+
+// DeleteDataFromOnuKvStore - TODO: add comment
+func (oo *OnuDeviceEntry) DeleteDataFromOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
+	defer wg.Done()
+
+	if oo.onuKVStore == nil {
+		logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
+		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
+	go oo.deletePersistentData(ctx, processingStep)
+	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.setKvProcessingErrorIndication(errors.New("onu-data delete aborted: during kv-access"))
+		return
+	}
+}
+
+func (oo *OnuDeviceEntry) deletePersistentData(ctx context.Context, aProcessingStep uint8) {
+
+	logger.Debugw(ctx, "delete and clear internal persistency data", log.Fields{"device-id": oo.deviceID})
+
+	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, make(map[uint16]uint16)}
+	logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
+	oo.mutexOnuKVStore.Lock()
+	err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)
+	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
+		return
+	}
+	oo.chOnuKvProcessingStep <- aProcessingStep //done
+}
+
+// UpdateOnuKvStore - TODO: add comment
+func (oo *OnuDeviceEntry) UpdateOnuKvStore(ctx context.Context, wg *sync.WaitGroup) {
+	defer wg.Done()
+
+	if oo.onuKVStore == nil {
+		logger.Debugw(ctx, "onuKVStore not set - abort", log.Fields{"device-id": oo.deviceID})
+		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
+	go oo.storeDataInOnuKvStore(ctx, processingStep)
+	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.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
+	onuIndication := oo.baseDeviceHandler.GetOnuIndication()
+	oo.SOnuPersistentData.PersOnuID = onuIndication.OnuId
+	oo.SOnuPersistentData.PersIntfID = onuIndication.IntfId
+	//TODO: verify usage of these values during restart UC
+	oo.SOnuPersistentData.PersAdminState = onuIndication.AdminState
+	oo.SOnuPersistentData.PersOperState = onuIndication.OperState
+
+	logger.Debugw(ctx, "Update ONU-data in KVStore", log.Fields{"device-id": oo.deviceID, "SOnuPersistentData": oo.SOnuPersistentData})
+
+	Value, err := json.Marshal(oo.SOnuPersistentData)
+	if err != nil {
+		logger.Errorw(ctx, "unable to marshal ONU-data", log.Fields{"SOnuPersistentData": oo.SOnuPersistentData,
+			"device-id": oo.deviceID, "err": err})
+		oo.chOnuKvProcessingStep <- 0 //error indication
+		return
+	}
+	oo.pOpenOnuAc.RLockMutexDeviceHandlersMap()
+	if _, exist := oo.pOpenOnuAc.GetDeviceHandler(oo.deviceID); !exist {
+		logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
+		oo.chOnuKvProcessingStep <- aProcessingStep
+		oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
+		return
+	}
+	oo.baseDeviceHandler.RLockMutexDeletionInProgressFlag()
+	if oo.baseDeviceHandler.GetDeletionInProgress() {
+		logger.Debugw(ctx, "delete_device in progress - skip write request", log.Fields{"device-id": oo.deviceID})
+		oo.chOnuKvProcessingStep <- aProcessingStep
+		oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
+		oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
+		return
+	}
+	oo.pOpenOnuAc.RUnlockMutexDeviceHandlersMap()
+	oo.baseDeviceHandler.RUnlockMutexDeletionInProgressFlag()
+
+	oo.mutexOnuKVStore.Lock()
+	err = oo.onuKVStore.Put(ctx, oo.onuKVStorePath, Value)
+	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
+		return
+	}
+	oo.chOnuKvProcessingStep <- aProcessingStep //done
+}
+
+// UpdateOnuUniTpPath - TODO: add comment
+func (oo *OnuDeviceEntry) UpdateOnuUniTpPath(ctx context.Context, aUniID uint8, aTpID uint8, aPathString string) bool {
+	/* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
+	   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.MutexPersOnuConfig.Lock()
+	defer oo.MutexPersOnuConfig.Unlock()
+
+	for k, v := range oo.SOnuPersistentData.PersUniConfig {
+		if v.PersUniID == aUniID {
+			existingPath, ok := oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID]
+			logger.Debugw(ctx, "PersUniConfig-entry exists", log.Fields{"device-id": oo.deviceID, "uniID": aUniID,
+				"tpID": aTpID, "path": aPathString, "existingPath": existingPath, "ok": ok})
+			if !ok {
+				logger.Debugw(ctx, "tp-does-not-exist", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "tpID": aTpID, "path": aPathString})
+			}
+			if existingPath != aPathString {
+				if aPathString == "" {
+					//existing entry to be deleted
+					logger.Debugw(ctx, "UniTp delete path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+					oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = ""
+				} else {
+					//existing entry to be modified
+					logger.Debugw(ctx, "UniTp modify path value", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+					oo.SOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID] = aPathString
+				}
+				return true
+			}
+			//entry already exists
+			if aPathString == "" {
+				//no active TechProfile
+				logger.Debugw(ctx, "UniTp path has already been removed - no AniSide config to be removed", log.Fields{
+					"device-id": oo.deviceID, "uniID": aUniID})
+			} else {
+				//the given TechProfile already exists and is assumed to be active - update devReason as if the config has been done here
+				//was needed e.g. in voltha POD Tests:Validate authentication on a disabled ONU
+				//  (as here the TechProfile has not been removed with the disable-device before the new enable-device)
+				logger.Debugw(ctx, "UniTp path already exists - TechProfile supposed to be active", log.Fields{
+					"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+				//no deviceReason update (DeviceProcStatusUpdate) here to ensure 'omci_flows_pushed' state within disable/enable procedure of ATT scenario
+				//  (during which the flows are removed/re-assigned but the techProf is left active)
+				//and as the TechProfile is regarded as active we have to verify, if some flow configuration still waits on it
+				//  (should not be the case, but should not harm or be more robust ...)
+				// and to be sure, that for some reason the corresponding TpDelete was lost somewhere in history
+				//  we also reset a possibly outstanding delete request - repeated TpConfig is regarded as valid for waiting flow config
+				if oo.pOnuTP != nil {
+					oo.pOnuTP.SetProfileToDelete(aUniID, aTpID, false)
+				}
+				go oo.baseDeviceHandler.VerifyVlanConfigRequest(ctx, aUniID, aTpID)
+			}
+			return false //indicate 'no change' - nothing more to do, TechProf inter-adapter message is return with success anyway here
+		}
+	}
+	//no entry exists for uniId
+
+	if aPathString == "" {
+		//delete request in non-existing state , accept as no change
+		logger.Debugw(ctx, "UniTp path already removed", log.Fields{"device-id": oo.deviceID, "uniID": aUniID})
+		return false
+	}
+	//new entry to be created
+	logger.Debugw(ctx, "New UniTp path set", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+	perSubTpPathMap := make(map[uint8]string)
+	perSubTpPathMap[aTpID] = aPathString
+	oo.SOnuPersistentData.PersUniConfig =
+		append(oo.SOnuPersistentData.PersUniConfig, uniPersConfig{PersUniID: aUniID, PersTpPathMap: perSubTpPathMap, PersFlowParams: make([]cmn.UniVlanFlowParams, 0)})
+	return true
+}
+
+// UpdateOnuUniFlowConfig - TODO: add comment
+func (oo *OnuDeviceEntry) UpdateOnuUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]cmn.UniVlanFlowParams) {
+
+	oo.MutexPersOnuConfig.Lock()
+	defer oo.MutexPersOnuConfig.Unlock()
+
+	for k, v := range oo.SOnuPersistentData.PersUniConfig {
+		if v.PersUniID == aUniID {
+			oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams = make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))
+			copy(oo.SOnuPersistentData.PersUniConfig[k].PersFlowParams, *aUniVlanFlowParams)
+			return
+		}
+	}
+	//flow update was faster than tp-config - create PersUniConfig-entry
+	//TODO!!: following activity to 'add' some new uni entry might not be quite correct if this function is called to clear the data
+	//  (e.g after flow removal from RemoveUniFlowParams()).
+	//  This has the effect of misleading indication that there is still some active UNI entry, even though there might be only some nil flow entry
+	//  The effect of this flaw is that at TechProfile removal there is an additional attempt to remove the entry even though no techProfile exists anymore
+	//  The code is not changed here because of the current release lane, changes might have unexpected secondary effects, perhaps later with more elaborate tests
+	tmpConfig := uniPersConfig{PersUniID: aUniID, PersTpPathMap: make(map[uint8]string), PersFlowParams: make([]cmn.UniVlanFlowParams, len(*aUniVlanFlowParams))}
+	copy(tmpConfig.PersFlowParams, *aUniVlanFlowParams)
+	oo.SOnuPersistentData.PersUniConfig = append(oo.SOnuPersistentData.PersUniConfig, tmpConfig)
+}
+
+func (oo *OnuDeviceEntry) waitForTimeoutOrCompletion(
+	ctx context.Context, aChOnuProcessingStep <-chan uint8, aProcessingStep uint8) bool {
+	select {
+	case <-ctx.Done():
+		logger.Warnw(ctx, "processing not completed in-time!",
+			log.Fields{"device-id": oo.deviceID, "error": ctx.Err()})
+		return false
+	case rxStep := <-aChOnuProcessingStep:
+		if rxStep == aProcessingStep {
+			return true
+		}
+		//all other values are not accepted - including 0 for error indication
+		logger.Warnw(ctx, "Invalid processing step received: abort!",
+			log.Fields{"device-id": oo.deviceID,
+				"wantedStep": aProcessingStep, "haveStep": rxStep})
+		return false
+	}
+}
+
+// ResetKvProcessingErrorIndication - TODO: add comment
+func (oo *OnuDeviceEntry) ResetKvProcessingErrorIndication() {
+	oo.mutexOnuKVStoreProcResult.Lock()
+	oo.onuKVStoreProcResult = nil
+	oo.mutexOnuKVStoreProcResult.Unlock()
+}
+
+// GetKvProcessingErrorIndication - TODO: add comment
+func (oo *OnuDeviceEntry) GetKvProcessingErrorIndication() error {
+	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()
+}
+
+// IncrementMibDataSync - TODO: add comment
+func (oo *OnuDeviceEntry) IncrementMibDataSync(ctx context.Context) {
+	oo.MutexPersOnuConfig.Lock()
+	defer oo.MutexPersOnuConfig.Unlock()
+	if oo.SOnuPersistentData.PersMibDataSyncAdpt < 255 {
+		oo.SOnuPersistentData.PersMibDataSyncAdpt++
+	} else {
+		// per G.984 and G.988 overflow starts over at 1 given 0 is reserved for reset
+		oo.SOnuPersistentData.PersMibDataSyncAdpt = 1
+	}
+	logger.Debugf(ctx, "mibDataSync updated - mds: %d - device-id: %s", oo.SOnuPersistentData.PersMibDataSyncAdpt, oo.deviceID)
+}
+
+// ModifySwImageInactiveVersion - updates the inactive SW image version stored
+func (oo *OnuDeviceEntry) ModifySwImageInactiveVersion(ctx context.Context, aImageVersion string) {
+	oo.mutexOnuSwImageIndications.Lock()
+	defer oo.mutexOnuSwImageIndications.Unlock()
+	logger.Debugw(ctx, "software-image set inactive version", log.Fields{
+		"device-id": oo.deviceID, "version": aImageVersion})
+	oo.onuSwImageIndications.InActiveEntityEntry.Version = aImageVersion
+	//inactive SW version is not part of persistency data (yet) - no need to update that
+}
+
+// ModifySwImageActiveCommit - updates the active SW commit flag stored
+func (oo *OnuDeviceEntry) ModifySwImageActiveCommit(ctx context.Context, aCommitted uint8) {
+	oo.mutexOnuSwImageIndications.Lock()
+	defer oo.mutexOnuSwImageIndications.Unlock()
+	logger.Debugw(ctx, "software-image set active entity commit flag", log.Fields{
+		"device-id": oo.deviceID, "committed": aCommitted})
+	oo.onuSwImageIndications.ActiveEntityEntry.IsCommitted = aCommitted
+	//commit flag is not part of persistency data (yet) - no need to update that
+}
+
+// GetActiveImageVersion - returns the active SW image version stored
+func (oo *OnuDeviceEntry) GetActiveImageVersion(ctx context.Context) string {
+	oo.mutexOnuSwImageIndications.RLock()
+	if oo.onuSwImageIndications.ActiveEntityEntry.Valid {
+		value := oo.onuSwImageIndications.ActiveEntityEntry.Version
+		oo.mutexOnuSwImageIndications.RUnlock()
+		return value
+	}
+	oo.mutexOnuSwImageIndications.RUnlock()
+	logger.Debugw(ctx, "Active Image is not valid", log.Fields{"device-id": oo.deviceID})
+	return ""
+}
+
+// GetInactiveImageVersion - TODO: add comment
+func (oo *OnuDeviceEntry) GetInactiveImageVersion(ctx context.Context) string {
+	oo.mutexOnuSwImageIndications.RLock()
+	if oo.onuSwImageIndications.InActiveEntityEntry.Valid {
+		value := oo.onuSwImageIndications.InActiveEntityEntry.Version
+		oo.mutexOnuSwImageIndications.RUnlock()
+		return value
+	}
+	oo.mutexOnuSwImageIndications.RUnlock()
+	logger.Debugw(ctx, "Inactive Image is not valid", log.Fields{"device-id": oo.deviceID})
+	return ""
+}
+
+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)
+}
+
+// AllocateFreeTcont - TODO: add comment
+func (oo *OnuDeviceEntry) AllocateFreeTcont(ctx context.Context, allocID uint16) (uint16, bool, error) {
+	logger.Debugw(ctx, "allocate-free-tcont", log.Fields{"device-id": oo.deviceID, "allocID": allocID,
+		"allocated-instances": oo.SOnuPersistentData.PersTcontMap})
+
+	oo.mutexTcontMap.Lock()
+	defer oo.mutexTcontMap.Unlock()
+	if entityID, ok := oo.SOnuPersistentData.PersTcontMap[allocID]; ok {
+		//tcont already allocated before, return the used instance-id
+		return entityID, true, nil
+	}
+	//First allocation of tcont. Find a free instance
+	if tcontInstKeys := oo.pOnuDB.GetSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
+		logger.Debugw(ctx, "allocate-free-tcont-db-keys", log.Fields{"device-id": oo.deviceID, "keys": tcontInstKeys})
+		for _, instID := range tcontInstKeys {
+			instExist := false
+			//If this instance exist in map, it means it is not  empty. It is allocated before
+			for _, v := range oo.SOnuPersistentData.PersTcontMap {
+				if v == instID {
+					instExist = true
+					break
+				}
+			}
+			if !instExist {
+				oo.SOnuPersistentData.PersTcontMap[allocID] = instID
+				return instID, false, nil
+			}
+		}
+	}
+	return 0, false, fmt.Errorf(fmt.Sprintf("no-free-tcont-left-for-device-%s", oo.deviceID))
+
+}
+
+// FreeTcont - TODO: add comment
+func (oo *OnuDeviceEntry) FreeTcont(ctx context.Context, allocID uint16) {
+	logger.Debugw(ctx, "free-tcont", log.Fields{"device-id": oo.deviceID, "alloc": allocID})
+	oo.mutexTcontMap.Lock()
+	defer oo.mutexTcontMap.Unlock()
+	delete(oo.SOnuPersistentData.PersTcontMap, allocID)
+}
+
+// GetDevOmciCC - TODO: add comment
+func (oo *OnuDeviceEntry) GetDevOmciCC() *cmn.OmciCC {
+	return oo.PDevOmciCC
+}
+
+// GetOnuDB - TODO: add comment
+func (oo *OnuDeviceEntry) GetOnuDB() *devdb.OnuDeviceDB {
+	return oo.pOnuDB
+}
+
+// GetPersSerialNumber - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersSerialNumber() string {
+	value := oo.SOnuPersistentData.PersSerialNumber
+	return value
+}
+
+// GetPersVendorID - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersVendorID() string {
+	value := oo.SOnuPersistentData.PersVendorID
+	return value
+}
+
+// GetPersEquipmentID - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersEquipmentID() string {
+	value := oo.SOnuPersistentData.PersEquipmentID
+	return value
+}
+
+// GetMibUploadFsmCommChan - TODO: add comment
+func (oo *OnuDeviceEntry) GetMibUploadFsmCommChan() chan cmn.Message {
+	return oo.PMibUploadFsm.CommChan
+}
+
+// GetMibDownloadFsmCommChan - TODO: add comment
+func (oo *OnuDeviceEntry) GetMibDownloadFsmCommChan() chan cmn.Message {
+	return oo.PMibDownloadFsm.CommChan
+}
+
+// GetOmciRebootMsgRevChan - TODO: add comment
+func (oo *OnuDeviceEntry) GetOmciRebootMsgRevChan() chan cmn.Message {
+	return oo.omciRebootMessageReceivedChannel
+}
+
+// LockMutexOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) LockMutexOnuSwImageIndications() {
+	oo.mutexOnuSwImageIndications.Lock()
+}
+
+// UnlockMutexOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) UnlockMutexOnuSwImageIndications() {
+	oo.mutexOnuSwImageIndications.Unlock()
+}
+
+// GetOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) GetOnuSwImageIndications() cmn.SswImageIndications {
+	return oo.onuSwImageIndications
+}
+
+// SetOnuSwImageIndications - TODO: add comment
+func (oo *OnuDeviceEntry) SetOnuSwImageIndications(value cmn.SswImageIndications) {
+	oo.onuSwImageIndications = value
+}
+
+// LockMutexPersOnuConfig - TODO: add comment
+func (oo *OnuDeviceEntry) LockMutexPersOnuConfig() {
+	oo.MutexPersOnuConfig.Lock()
+}
+
+// UnlockMutexPersOnuConfig - TODO: add comment
+func (oo *OnuDeviceEntry) UnlockMutexPersOnuConfig() {
+	oo.MutexPersOnuConfig.Unlock()
+}
+
+// GetPersActiveSwVersion - TODO: add comment
+func (oo *OnuDeviceEntry) GetPersActiveSwVersion() string {
+	return oo.SOnuPersistentData.PersActiveSwVersion
+}
+
+// SetPersActiveSwVersion - TODO: add comment
+func (oo *OnuDeviceEntry) SetPersActiveSwVersion(value string) {
+	oo.SOnuPersistentData.PersActiveSwVersion = value
+}
+
+// SetReconcilingFlows - TODO: add comment
+func (oo *OnuDeviceEntry) SetReconcilingFlows(value bool) {
+	oo.mutexReconcilingFlowsFlag.Lock()
+	oo.reconcilingFlows = value
+	oo.mutexReconcilingFlowsFlag.Unlock()
+}
+
+// SetChReconcilingFlowsFinished - TODO: add comment
+func (oo *OnuDeviceEntry) SetChReconcilingFlowsFinished(value bool) {
+	oo.chReconcilingFlowsFinished <- value
+}
+
+// IsReconcilingFlows - TODO: add comment
+func (oo *OnuDeviceEntry) IsReconcilingFlows() bool {
+	oo.mutexReconcilingFlowsFlag.RLock()
+	value := oo.reconcilingFlows
+	oo.mutexReconcilingFlowsFlag.RUnlock()
+	return value
+}