VOL-3434 Added SCA Fixes

Change-Id: I405780cef6de3e2d287dbafa6ddd968caaa72dac
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index 91b794c..ae7a593 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -218,6 +218,184 @@
 
 }
 
+func (dh *DeviceHandler) processInterAdapterOMCIReqMessage(msg *ic.InterAdapterMessage) error {
+	msgBody := msg.GetBody()
+	omciMsg := &ic.InterAdapterOmciMessage{}
+	if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
+		logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
+			"device-id": dh.deviceID, "error": err})
+		return err
+	}
+
+	//assuming omci message content is hex coded!
+	// with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
+	logger.Debugw("inter-adapter-recv-omci", log.Fields{
+		"device-id": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
+	//receive_message(omci_msg.message)
+	pDevEntry := dh.GetOnuDeviceEntry(true)
+	if pDevEntry != nil {
+		return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
+	}
+	logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
+	return errors.New("no valid OnuDevice")
+}
+
+func (dh *DeviceHandler) processInterAdapterONUIndReqMessage(msg *ic.InterAdapterMessage) error {
+	msgBody := msg.GetBody()
+	onuIndication := &oop.OnuIndication{}
+	if err := ptypes.UnmarshalAny(msgBody, onuIndication); err != nil {
+		logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
+			"device-id": dh.deviceID, "error": err})
+		return err
+	}
+
+	onuOperstate := onuIndication.GetOperState()
+	logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onuIndication.GetOnuId(),
+		"AdminState": onuIndication.GetAdminState(), "OperState": onuOperstate,
+		"SNR": onuIndication.GetSerialNumber()})
+
+	//interface related functions might be error checked ....
+	if onuOperstate == "up" {
+		_ = dh.createInterface(onuIndication)
+	} else if (onuOperstate == "down") || (onuOperstate == "unreachable") {
+		_ = dh.updateInterface(onuIndication)
+	} else {
+		logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onuIndication.GetOnuId()})
+		return errors.New("invalidOperState")
+	}
+	return nil
+}
+
+func (dh *DeviceHandler) processInterAdapterTechProfileDownloadReqMessage(
+	msg *ic.InterAdapterMessage) error {
+	if dh.pOnuTP == nil {
+		//should normally not happen ...
+		logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
+			log.Fields{"device-id": dh.deviceID})
+		return errors.New("techProfile DLMsg request while onuTechProf instance not setup")
+	}
+	if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
+		// I've seen cases for this request, where the device was already stopped
+		logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
+		return errors.New("device-unreachable")
+	}
+
+	msgBody := msg.GetBody()
+	techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
+	if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
+		logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
+			"device-id": dh.deviceID, "error": err})
+		return err
+	}
+
+	// we have to lock access to TechProfile processing based on different messageType calls or
+	// even to fast subsequent calls of the same messageType
+	dh.pOnuTP.lockTpProcMutex()
+	// lock hangs as long as below decoupled or other related TechProfile processing is active
+	if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify {
+		//	if there has been some change for some uni TechProfilePath
+		//in order to allow concurrent calls to other dh instances we do not wait for execution here
+		//but doing so we can not indicate problems to the caller (who does what with that then?)
+		//by now we just assume straightforward successful execution
+		//TODO!!! Generally: In this scheme it would be good to have some means to indicate
+		//  possible problems to the caller later autonomously
+
+		// deadline context to ensure completion of background routines waited for
+		//20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
+		deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
+		dctx, cancel := context.WithDeadline(context.Background(), deadline)
+
+		dh.pOnuTP.resetProcessingErrorIndication()
+		var wg sync.WaitGroup
+		wg.Add(2) // for the 2 go routines to finish
+		// attention: deadline completion check and wg.Done is to be done in both routines
+		go dh.pOnuTP.configureUniTp(dctx, uint8(techProfMsg.UniId), techProfMsg.Path, &wg)
+		go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
+		//the wait.. function is responsible for tpProcMutex.Unlock()
+		err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
+		return err
+	}
+	// no change, nothing really to do
+	dh.pOnuTP.unlockTpProcMutex()
+	//return success
+	return nil
+}
+
+func (dh *DeviceHandler) processInterAdapterDeleteGemPortReqMessage(
+	msg *ic.InterAdapterMessage) error {
+
+	if dh.pOnuTP == nil {
+		//should normally not happen ...
+		logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
+			log.Fields{"device-id": dh.deviceID})
+		return errors.New("techProfile DelGem request while onuTechProf instance not setup")
+	}
+
+	msgBody := msg.GetBody()
+	delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
+	if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
+		logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
+			"device-id": dh.deviceID, "error": err})
+		return err
+	}
+
+	//compare TECH_PROFILE_DOWNLOAD_REQUEST
+	dh.pOnuTP.lockTpProcMutex()
+
+	// deadline context to ensure completion of background routines waited for
+	deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
+	dctx, cancel := context.WithDeadline(context.Background(), deadline)
+
+	dh.pOnuTP.resetProcessingErrorIndication()
+	var wg sync.WaitGroup
+	wg.Add(1) // for the 1 go routine to finish
+	go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
+		cResourceGemPort, delGemPortMsg.GemPortId, &wg)
+	//the wait.. function is responsible for tpProcMutex.Unlock()
+	err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
+	return err
+}
+
+func (dh *DeviceHandler) processInterAdapterDeleteTcontReqMessage(
+	msg *ic.InterAdapterMessage) error {
+	if dh.pOnuTP == nil {
+		//should normally not happen ...
+		logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
+			log.Fields{"device-id": dh.deviceID})
+		return errors.New("techProfile DelTcont request while onuTechProf instance not setup")
+	}
+
+	msgBody := msg.GetBody()
+	delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
+	if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
+		logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
+			"device-id": dh.deviceID, "error": err})
+		return err
+	}
+
+	//compare TECH_PROFILE_DOWNLOAD_REQUEST
+	dh.pOnuTP.lockTpProcMutex()
+	if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify {
+		// deadline context to ensure completion of background routines waited for
+		deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
+		dctx, cancel := context.WithDeadline(context.Background(), deadline)
+
+		dh.pOnuTP.resetProcessingErrorIndication()
+		var wg sync.WaitGroup
+		wg.Add(2) // for the 2 go routines to finish
+		go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
+			cResourceTcont, delTcontMsg.AllocId, &wg)
+		// Removal of the tcont/alloc id mapping represents the removal of the tech profile
+		go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
+		//the wait.. function is responsible for tpProcMutex.Unlock()
+		err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
+		return err
+	}
+	dh.pOnuTP.unlockTpProcMutex()
+	//return success
+	return nil
+}
+
 //ProcessInterAdapterMessage sends the proxied messages to the target device
 // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
 // is meant, and then send the unmarshalled omci message to this onu
@@ -234,176 +412,24 @@
 	switch msgType {
 	case ic.InterAdapterMessageType_OMCI_REQUEST:
 		{
-			msgBody := msg.GetBody()
-			omciMsg := &ic.InterAdapterOmciMessage{}
-			if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
-				logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
-					"device-id": dh.deviceID, "error": err})
-				return err
-			}
-
-			//assuming omci message content is hex coded!
-			// with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
-			logger.Debugw("inter-adapter-recv-omci", log.Fields{
-				"device-id": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
-			//receive_message(omci_msg.message)
-			pDevEntry := dh.GetOnuDeviceEntry(true)
-			if pDevEntry != nil {
-				return pDevEntry.PDevOmciCC.ReceiveMessage(context.TODO(), omciMsg.Message)
-			}
-			logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
-			return errors.New("no valid OnuDevice")
+			return dh.processInterAdapterOMCIReqMessage(msg)
 		}
 	case ic.InterAdapterMessageType_ONU_IND_REQUEST:
 		{
-			msgBody := msg.GetBody()
-			onuIndication := &oop.OnuIndication{}
-			if err := ptypes.UnmarshalAny(msgBody, onuIndication); err != nil {
-				logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
-					"device-id": dh.deviceID, "error": err})
-				return err
-			}
-
-			onuOperstate := onuIndication.GetOperState()
-			logger.Debugw("inter-adapter-recv-onu-ind", log.Fields{"OnuId": onuIndication.GetOnuId(),
-				"AdminState": onuIndication.GetAdminState(), "OperState": onuOperstate,
-				"SNR": onuIndication.GetSerialNumber()})
-
-			//interface related functions might be error checked ....
-			if onuOperstate == "up" {
-				_ = dh.createInterface(onuIndication)
-			} else if (onuOperstate == "down") || (onuOperstate == "unreachable") {
-				_ = dh.updateInterface(onuIndication)
-			} else {
-				logger.Errorw("unknown-onu-indication operState", log.Fields{"OnuId": onuIndication.GetOnuId()})
-				return errors.New("invalidOperState")
-			}
+			return dh.processInterAdapterONUIndReqMessage(msg)
 		}
 	case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
 		{
-			if dh.pOnuTP == nil {
-				//should normally not happen ...
-				logger.Warnw("onuTechProf instance not set up for DLMsg request - ignoring request",
-					log.Fields{"device-id": dh.deviceID})
-				return errors.New("techProfile DLMsg request while onuTechProf instance not setup")
-			}
-			if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
-				// I've seen cases for this request, where the device was already stopped
-				logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
-				return errors.New("device-unreachable")
-			}
-
-			msgBody := msg.GetBody()
-			techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
-			if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
-				logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
-					"device-id": dh.deviceID, "error": err})
-				return err
-			}
-
-			// we have to lock access to TechProfile processing based on different messageType calls or
-			// even to fast subsequent calls of the same messageType
-			dh.pOnuTP.lockTpProcMutex()
-			// lock hangs as long as below decoupled or other related TechProfile processing is active
-			if bTpModify := dh.pOnuTP.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify {
-				//	if there has been some change for some uni TechProfilePath
-				//in order to allow concurrent calls to other dh instances we do not wait for execution here
-				//but doing so we can not indicate problems to the caller (who does what with that then?)
-				//by now we just assume straightforward successful execution
-				//TODO!!! Generally: In this scheme it would be good to have some means to indicate
-				//  possible problems to the caller later autonomously
-
-				// deadline context to ensure completion of background routines waited for
-				//20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
-				deadline := time.Now().Add(30 * time.Second) //allowed run time to finish before execution
-				dctx, cancel := context.WithDeadline(context.Background(), deadline)
-
-				dh.pOnuTP.resetProcessingErrorIndication()
-				var wg sync.WaitGroup
-				wg.Add(2) // for the 2 go routines to finish
-				// attention: deadline completion check and wg.Done is to be done in both routines
-				go dh.pOnuTP.configureUniTp(dctx, uint8(techProfMsg.UniId), techProfMsg.Path, &wg)
-				go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
-				//the wait.. function is responsible for tpProcMutex.Unlock()
-				err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
-				return err
-			}
-			// no change, nothing really to do
-			dh.pOnuTP.unlockTpProcMutex()
-			//return success
-			return nil
+			return dh.processInterAdapterTechProfileDownloadReqMessage(msg)
 		}
 	case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
 		{
-			if dh.pOnuTP == nil {
-				//should normally not happen ...
-				logger.Warnw("onuTechProf instance not set up for DelGem request - ignoring request",
-					log.Fields{"device-id": dh.deviceID})
-				return errors.New("techProfile DelGem request while onuTechProf instance not setup")
-			}
+			return dh.processInterAdapterDeleteGemPortReqMessage(msg)
 
-			msgBody := msg.GetBody()
-			delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
-			if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
-				logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
-					"device-id": dh.deviceID, "error": err})
-				return err
-			}
-
-			//compare TECH_PROFILE_DOWNLOAD_REQUEST
-			dh.pOnuTP.lockTpProcMutex()
-
-			// deadline context to ensure completion of background routines waited for
-			deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
-			dctx, cancel := context.WithDeadline(context.Background(), deadline)
-
-			dh.pOnuTP.resetProcessingErrorIndication()
-			var wg sync.WaitGroup
-			wg.Add(1) // for the 1 go routine to finish
-			go dh.pOnuTP.deleteTpResource(dctx, delGemPortMsg.UniId, delGemPortMsg.TpPath,
-				cResourceGemPort, delGemPortMsg.GemPortId, &wg)
-			//the wait.. function is responsible for tpProcMutex.Unlock()
-			err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
-			return err
 		}
 	case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
 		{
-			if dh.pOnuTP == nil {
-				//should normally not happen ...
-				logger.Warnw("onuTechProf instance not set up for DelTcont request - ignoring request",
-					log.Fields{"device-id": dh.deviceID})
-				return errors.New("techProfile DelTcont request while onuTechProf instance not setup")
-			}
-
-			msgBody := msg.GetBody()
-			delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
-			if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
-				logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
-					"device-id": dh.deviceID, "error": err})
-				return err
-			}
-
-			//compare TECH_PROFILE_DOWNLOAD_REQUEST
-			dh.pOnuTP.lockTpProcMutex()
-			if bTpModify := dh.pOnuTP.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify {
-				// deadline context to ensure completion of background routines waited for
-				deadline := time.Now().Add(10 * time.Second) //allowed run time to finish before execution
-				dctx, cancel := context.WithDeadline(context.Background(), deadline)
-
-				dh.pOnuTP.resetProcessingErrorIndication()
-				var wg sync.WaitGroup
-				wg.Add(2) // for the 2 go routines to finish
-				go dh.pOnuTP.deleteTpResource(dctx, delTcontMsg.UniId, delTcontMsg.TpPath,
-					cResourceTcont, delTcontMsg.AllocId, &wg)
-				// Removal of the tcont/alloc id mapping represents the removal of the tech profile
-				go dh.pOnuTP.updateOnuTpPathKvStore(dctx, &wg)
-				//the wait.. function is responsible for tpProcMutex.Unlock()
-				err := dh.pOnuTP.waitForTpCompletion(cancel, &wg) //let that also run off-line to let the IA messaging return!
-				return err
-			}
-			dh.pOnuTP.unlockTpProcMutex()
-			//return success
-			return nil
+			return dh.processInterAdapterDeleteTcontReqMessage(msg)
 		}
 	default:
 		{
@@ -412,7 +438,6 @@
 			return errors.New("unimplemented")
 		}
 	}
-	return nil
 }
 
 //FlowUpdateIncremental removes and/or adds the flow changes on a given device
@@ -568,7 +593,7 @@
 		var wg sync.WaitGroup
 		wg.Add(1) // for the 1 go routines to finish
 		// attention: deadline completion check and wg.Done is to be done in both routines
-		go dh.pOnuTP.configureUniTp(dctx, uint8(uniData.PersUniId), uniData.PersTpPath, &wg)
+		go dh.pOnuTP.configureUniTp(dctx, uint8(uniData.PersUniID), uniData.PersTpPath, &wg)
 		//the wait.. function is responsible for tpProcMutex.Unlock()
 		_ = dh.pOnuTP.waitForTpCompletion(cancel, &wg) //wait for background process to finish and collect their result
 		return
@@ -1143,9 +1168,9 @@
 				}
 				for _, uniPort := range dh.uniEntityMap {
 					//reset the TechProfileConfig Done state for all (active) UNI's
-					dh.pOnuTP.setConfigDone(uniPort.uniId, false)
-					// reset tjhe possibly existing VlanConfigFsm
-					if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[uniPort.uniId]; exist {
+					dh.pOnuTP.setConfigDone(uniPort.uniID, false)
+					// reset the possibly existing VlanConfigFsm
+					if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[uniPort.uniID]; exist {
 						//VlanFilterFsm exists and was already started
 						pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
 						if pVlanFilterStatemachine != nil {
@@ -1199,197 +1224,221 @@
 	return nil
 }
 
+func (dh *DeviceHandler) processMibDatabaseSyncEvent(devEvent OnuDeviceEvent) {
+	logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
+	if !dh.reconciling {
+		//initiate DevStateUpdate
+		if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
+			//TODO with VOL-3045/VOL-3046: return the error and stop further processing
+			logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
+				"device-id": dh.deviceID, "error": err})
+		} else {
+			logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
+		}
+	} else {
+		logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
+			log.Fields{"device-id": dh.deviceID})
+	}
+	//set internal state anyway - as it was done
+	dh.deviceReason = "discovery-mibsync-complete"
+
+	i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
+	pDevEntry := dh.GetOnuDeviceEntry(false)
+	if unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
+		for _, mgmtEntityID := range unigInstKeys {
+			logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
+				"device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityID})
+			dh.addUniPort(mgmtEntityID, i, UniPPTP)
+			i++
+		}
+	} else {
+		logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
+	}
+	if veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
+		for _, mgmtEntityID := range veipInstKeys {
+			logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
+				"device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
+			dh.addUniPort(mgmtEntityID, i, UniVEIP)
+			i++
+		}
+	} else {
+		logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
+	}
+	if i == 0 {
+		logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
+	}
+
+	/* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
+	 *  left the code here as comment in case such processing should prove needed unexpectedly
+			// Init Uni Ports to Admin locked state
+			// maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
+			// *** should generate UniLockStateDone event *****
+			if dh.pLockStateFsm == nil {
+				dh.createUniLockFsm(true, UniLockStateDone)
+			} else { //LockStateFSM already init
+				dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
+				dh.runUniLockFsm(true)
+			}
+		}
+	case UniLockStateDone:
+		{
+			logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
+	* lockState processing commented out
+	*/
+	/*  Mib download procedure -
+	***** should run over 'downloaded' state and generate MibDownloadDone event *****
+	 */
+	pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
+	if pMibDlFsm != nil {
+		if pMibDlFsm.Is(dlStDisabled) {
+			if err := pMibDlFsm.Event(dlEvStart); err != nil {
+				logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
+				// maybe try a FSM reset and then again ... - TODO!!!
+			} else {
+				logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
+				// maybe use more specific states here for the specific download steps ...
+				if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
+					logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
+				} else {
+					logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
+					//Begin MIB data download (running autonomously)
+				}
+			}
+		} else {
+			logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
+			// maybe try a FSM reset and then again ... - TODO!!!
+		}
+		/***** Mib download started */
+	} else {
+		logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
+	}
+}
+
+func (dh *DeviceHandler) processMibDownloadDoneEvent(devEvent OnuDeviceEvent) {
+	logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
+	//initiate DevStateUpdate
+	if !dh.reconciling {
+		if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
+			voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
+			//TODO with VOL-3045/VOL-3046: return the error and stop further processing
+			logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
+		} else {
+			logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
+		}
+	} else {
+		logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
+			log.Fields{"device-id": dh.deviceID})
+	}
+	if !dh.reconciling {
+		if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
+			//TODO with VOL-3045/VOL-3046: return the error and stop further processing
+			logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
+				log.Fields{"device-id": dh.deviceID, "error": err})
+		} else {
+			logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
+		}
+	} else {
+		logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
+			log.Fields{"device-id": dh.deviceID})
+	}
+	//set internal state anyway - as it was done
+	dh.deviceReason = "initial-mib-downloaded"
+	// *** should generate UniUnlockStateDone event *****
+	if dh.pUnlockStateFsm == nil {
+		dh.createUniLockFsm(false, UniUnlockStateDone)
+	} else { //UnlockStateFSM already init
+		dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
+		dh.runUniLockFsm(false)
+	}
+}
+
+func (dh *DeviceHandler) processUniUnlockStateDoneEvent(devEvent OnuDeviceEvent) {
+	go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
+
+	if !dh.reconciling {
+		logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
+		raisedTs := time.Now().UnixNano()
+		go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
+	} else {
+		logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
+			log.Fields{"device-id": dh.deviceID})
+		go dh.ReconcileDeviceTechProf()
+		//TODO: further actions e.g. restore flows, metrics, ...
+	}
+}
+
+func (dh *DeviceHandler) processOmciAniConfigDoneEvent(devEvent OnuDeviceEvent) {
+	logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
+	// attention: the device reason update is done based on ONU-UNI-Port related activity
+	//  - which may cause some inconsistency
+	if dh.deviceReason != "tech-profile-config-download-success" {
+		// which may be the case from some previous actvity on another UNI Port of the ONU
+		if !dh.reconciling {
+			if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
+				//TODO with VOL-3045/VOL-3046: return the error and stop further processing
+				logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
+					log.Fields{"device-id": dh.deviceID, "error": err})
+			} else {
+				logger.Infow("update dev reason to 'tech-profile-config-download-success'",
+					log.Fields{"device-id": dh.deviceID})
+			}
+		} else {
+			logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
+				log.Fields{"device-id": dh.deviceID})
+		}
+		//set internal state anyway - as it was done
+		dh.deviceReason = "tech-profile-config-download-success"
+	}
+}
+
+func (dh *DeviceHandler) processOmciVlanFilterDoneEvent(devEvent OnuDeviceEvent) {
+	logger.Debugw("OmciVlanFilterDone event received",
+		log.Fields{"device-id": dh.deviceID})
+	// attention: the device reason update is done based on ONU-UNI-Port related activity
+	//  - which may cause some inconsistency
+	//			yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
+
+	if dh.deviceReason != "omci-flows-pushed" {
+		// which may be the case from some previous actvity on another UNI Port of the ONU
+		// or even some previous flow add activity on the same port
+		if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
+			logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
+				log.Fields{"device-id": dh.deviceID, "error": err})
+		} else {
+			logger.Infow("updated dev reason to ''omci-flows-pushed'",
+				log.Fields{"device-id": dh.deviceID})
+		}
+		//set internal state anyway - as it was done
+		dh.deviceReason = "omci-flows-pushed"
+	}
+}
+
 //DeviceProcStatusUpdate evaluates possible processing events and initiates according next activities
 func (dh *DeviceHandler) DeviceProcStatusUpdate(devEvent OnuDeviceEvent) {
 	switch devEvent {
 	case MibDatabaseSync:
 		{
-			logger.Debugw("MibInSync event received", log.Fields{"device-id": dh.deviceID})
-			if !dh.reconciling {
-				//initiate DevStateUpdate
-				if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
-					//TODO with VOL-3045/VOL-3046: return the error and stop further processing
-					logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
-						"device-id": dh.deviceID, "error": err})
-				} else {
-					logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
-				}
-			} else {
-				logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
-					log.Fields{"device-id": dh.deviceID})
-			}
-			//set internal state anyway - as it was done
-			dh.deviceReason = "discovery-mibsync-complete"
-
-			i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
-			pDevEntry := dh.GetOnuDeviceEntry(false)
-			if unigInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.UniGClassID); len(unigInstKeys) > 0 {
-				for _, mgmtEntityID := range unigInstKeys {
-					logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
-						"device-id": dh.deviceID, "UnigMe EntityID": mgmtEntityID})
-					dh.addUniPort(mgmtEntityID, i, UniPPTP)
-					i++
-				}
-			} else {
-				logger.Debugw("No UniG instances found", log.Fields{"device-id": dh.deviceID})
-			}
-			if veipInstKeys := pDevEntry.pOnuDB.GetSortedInstKeys(me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
-				for _, mgmtEntityID := range veipInstKeys {
-					logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
-						"device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
-					dh.addUniPort(mgmtEntityID, i, UniVEIP)
-					i++
-				}
-			} else {
-				logger.Debugw("No VEIP instances found", log.Fields{"device-id": dh.deviceID})
-			}
-			if i == 0 {
-				logger.Warnw("No PPTP instances found", log.Fields{"device-id": dh.deviceID})
-			}
-
-			/* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here
-			 *  left the code here as comment in case such processing should prove needed unexpectedly
-					// Init Uni Ports to Admin locked state
-					// maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
-					// *** should generate UniLockStateDone event *****
-					if dh.pLockStateFsm == nil {
-						dh.createUniLockFsm(true, UniLockStateDone)
-					} else { //LockStateFSM already init
-						dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
-						dh.runUniLockFsm(true)
-					}
-				}
-			case UniLockStateDone:
-				{
-					logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"device-id": dh.deviceID})
-			* lockState processing commented out
-			*/
-			/*  Mib download procedure -
-			***** should run over 'downloaded' state and generate MibDownloadDone event *****
-			 */
-			pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
-			if pMibDlFsm != nil {
-				if pMibDlFsm.Is(dlStDisabled) {
-					if err := pMibDlFsm.Event(dlEvStart); err != nil {
-						logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
-						// maybe try a FSM reset and then again ... - TODO!!!
-					} else {
-						logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
-						// maybe use more specific states here for the specific download steps ...
-						if err := pMibDlFsm.Event(dlEvCreateGal); err != nil {
-							logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
-						} else {
-							logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
-							//Begin MIB data download (running autonomously)
-						}
-					}
-				} else {
-					logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
-					// maybe try a FSM reset and then again ... - TODO!!!
-				}
-				/***** Mib download started */
-			} else {
-				logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"device-id": dh.deviceID})
-			}
+			dh.processMibDatabaseSyncEvent(devEvent)
 		}
 	case MibDownloadDone:
 		{
-			logger.Debugw("MibDownloadDone event received", log.Fields{"device-id": dh.deviceID})
-			//initiate DevStateUpdate
-			if !dh.reconciling {
-				if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
-					voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
-					//TODO with VOL-3045/VOL-3046: return the error and stop further processing
-					logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
-				} else {
-					logger.Debugw("dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
-				}
-			} else {
-				logger.Debugw("reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
-					log.Fields{"device-id": dh.deviceID})
-			}
-			if !dh.reconciling {
-				if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
-					//TODO with VOL-3045/VOL-3046: return the error and stop further processing
-					logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
-						log.Fields{"device-id": dh.deviceID, "error": err})
-				} else {
-					logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
-				}
-			} else {
-				logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
-					log.Fields{"device-id": dh.deviceID})
-			}
-			//set internal state anyway - as it was done
-			dh.deviceReason = "initial-mib-downloaded"
-			// *** should generate UniUnlockStateDone event *****
-			if dh.pUnlockStateFsm == nil {
-				dh.createUniLockFsm(false, UniUnlockStateDone)
-			} else { //UnlockStateFSM already init
-				dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
-				dh.runUniLockFsm(false)
-			}
+			dh.processMibDownloadDoneEvent(devEvent)
+
 		}
 	case UniUnlockStateDone:
 		{
-			go dh.enableUniPortStateUpdate() //cmp python yield self.enable_ports()
+			dh.processUniUnlockStateDoneEvent(devEvent)
 
-			if !dh.reconciling {
-				logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"device-id": dh.deviceID})
-				raisedTs := time.Now().UnixNano()
-				go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
-			} else {
-				logger.Debugw("reconciling - don't notify core that onu went to active but trigger tech profile config",
-					log.Fields{"device-id": dh.deviceID})
-				go dh.ReconcileDeviceTechProf()
-				//TODO: further actions e.g. restore flows, metrics, ...
-			}
 		}
 	case OmciAniConfigDone:
 		{
-			logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
-			// attention: the device reason update is done based on ONU-UNI-Port related activity
-			//  - which may cause some inconsistency
-			if dh.deviceReason != "tech-profile-config-download-success" {
-				// which may be the case from some previous actvity on another UNI Port of the ONU
-				if !dh.reconciling {
-					if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
-						//TODO with VOL-3045/VOL-3046: return the error and stop further processing
-						logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
-							log.Fields{"device-id": dh.deviceID, "error": err})
-					} else {
-						logger.Infow("update dev reason to 'tech-profile-config-download-success'",
-							log.Fields{"device-id": dh.deviceID})
-					}
-				} else {
-					logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
-						log.Fields{"device-id": dh.deviceID})
-				}
-				//set internal state anyway - as it was done
-				dh.deviceReason = "tech-profile-config-download-success"
-			}
+			dh.processOmciAniConfigDoneEvent(devEvent)
+
 		}
 	case OmciVlanFilterDone:
 		{
-			logger.Debugw("OmciVlanFilterDone event received",
-				log.Fields{"device-id": dh.deviceID})
-			// attention: the device reason update is done based on ONU-UNI-Port related activity
-			//  - which may cause some inconsistency
-			//			yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
+			dh.processOmciVlanFilterDoneEvent(devEvent)
 
-			if dh.deviceReason != "omci-flows-pushed" {
-				// which may be the case from some previous actvity on another UNI Port of the ONU
-				// or even some previous flow add activity on the same port
-				if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
-					logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
-						log.Fields{"device-id": dh.deviceID, "error": err})
-				} else {
-					logger.Infow("updated dev reason to ''omci-flows-pushed'",
-						log.Fields{"device-id": dh.deviceID})
-				}
-				//set internal state anyway - as it was done
-				dh.deviceReason = "omci-flows-pushed"
-			}
 		}
 	default:
 		{
@@ -1436,7 +1485,7 @@
 
 	for uniNo, uniPort := range dh.uniEntityMap {
 		// only if this port is validated for operState transfer
-		if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
+		if (1<<uniPort.uniID)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniID) {
 			logger.Infow("onuUniPort-forced-OperState-ACTIVE", log.Fields{"for PortNo": uniNo})
 			uniPort.SetOperState(vc.OperStatus_ACTIVE)
 			if !dh.reconciling {
@@ -1455,7 +1504,7 @@
 	//   -> use current restriction to operate only on first UNI port as inherited from actual Py code
 	for uniNo, uniPort := range dh.uniEntityMap {
 		// only if this port is validated for operState transfer
-		if (1<<uniPort.uniId)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniId) {
+		if (1<<uniPort.uniID)&ActiveUniPortStateUpdateMask == (1 << uniPort.uniID) {
 			logger.Infow("onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
 			uniPort.SetOperState(vc.OperStatus_UNKNOWN)
 			//maybe also use getter functions on uniPort - perhaps later ...
@@ -1596,30 +1645,9 @@
 
 	return kvbackend
 }
+func (dh *DeviceHandler) getFlowOfbFields(apFlowItem *ofp.OfpFlowStats, loMatchVlan *uint16,
+	loAddPcp *uint8, loIPProto *uint32) {
 
-//addFlowItemToUniPort parses the actual flow item to add it to the UniPort
-func (dh *DeviceHandler) addFlowItemToUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *OnuUniPort) error {
-	var loSetVlan uint16 = uint16(of.OfpVlanId_OFPVID_NONE)      //noValidEntry
-	var loMatchVlan uint16 = uint16(of.OfpVlanId_OFPVID_PRESENT) //reserved VLANID entry
-	var loAddPcp, loSetPcp uint8
-	/* the TechProfileId is part of the flow Metadata - compare also comment within
-	 * OLT-Adapter:openolt_flowmgr.go
-	 *     Metadata 8 bytes:
-	 *	   Most Significant 2 Bytes = Inner VLAN
-	 *	   Next 2 Bytes = Tech Profile ID(TPID)
-	 *	   Least Significant 4 Bytes = Port ID
-	 *     Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
-	 *     subscriber related flows.
-	 */
-
-	metadata := flow.GetMetadataFromWriteMetadataAction(apFlowItem)
-	if metadata == 0 {
-		logger.Debugw("FlowAdd invalid metadata - abort",
-			log.Fields{"device-id": dh.deviceID})
-		return errors.New("FlowAdd invalid metadata")
-	}
-	loTpID := flow.GetTechProfileIDFromWriteMetaData(metadata)
-	logger.Debugw("FlowAdd TechProfileId", log.Fields{"device-id": dh.deviceID, "TP-Id": loTpID})
 	for _, field := range flow.GetOfbFields(apFlowItem) {
 		switch field.Type {
 		case of.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
@@ -1629,32 +1657,32 @@
 			}
 		case of.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
 			{
-				loIPProto := field.GetIpProto()
+				*loIPProto = field.GetIpProto()
 				logger.Debugw("FlowAdd type IpProto", log.Fields{"device-id": dh.deviceID,
-					"IpProto": strconv.FormatInt(int64(loIPProto), 16)})
-				if loIPProto == 2 {
+					"IpProto": strconv.FormatInt(int64(*loIPProto), 16)})
+				if *loIPProto == 2 {
 					// some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
 					// avoids installing invalid EVTOCD rule
 					logger.Debugw("FlowAdd type IpProto 2: TT workaround: ignore flow",
 						log.Fields{"device-id": dh.deviceID,
-							"IpProto": strconv.FormatInt(int64(loIPProto), 16)})
-					return nil
+							"IpProto": strconv.FormatInt(int64(*loIPProto), 16)})
+					return
 				}
 			}
 		case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
 			{
-				loMatchVlan = uint16(field.GetVlanVid())
+				*loMatchVlan = uint16(field.GetVlanVid())
 				loMatchVlanMask := uint16(field.GetVlanVidMask())
-				if !(loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) &&
+				if !(*loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) &&
 					loMatchVlanMask == uint16(of.OfpVlanId_OFPVID_PRESENT)) {
-					loMatchVlan = loMatchVlan & 0xFFF // not transparent: copy only ID bits
+					*loMatchVlan = *loMatchVlan & 0xFFF // not transparent: copy only ID bits
 				}
 				logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
-					"VID": strconv.FormatInt(int64(loMatchVlan), 16)})
+					"VID": strconv.FormatInt(int64(*loMatchVlan), 16)})
 			}
 		case of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
 			{
-				loAddPcp = uint8(field.GetVlanPcp())
+				*loAddPcp = uint8(field.GetVlanPcp())
 				logger.Debugw("FlowAdd field type", log.Fields{"device-id": dh.deviceID,
 					"PCP": loAddPcp})
 			}
@@ -1691,7 +1719,9 @@
 			*/
 		}
 	} //for all OfbFields
+}
 
+func (dh *DeviceHandler) getFlowActions(apFlowItem *ofp.OfpFlowStats, loSetPcp *uint8, loSetVlan *uint16) {
 	for _, action := range flow.GetActions(apFlowItem) {
 		switch action.Type {
 		/* not used:
@@ -1714,13 +1744,13 @@
 						"OxcmClass": pActionSetField.Field.OxmClass})
 				}
 				if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
-					loSetVlan = uint16(pActionSetField.Field.GetOfbField().GetVlanVid())
+					*loSetVlan = uint16(pActionSetField.Field.GetOfbField().GetVlanVid())
 					logger.Debugw("FlowAdd Set VLAN from SetField action", log.Fields{"device-id": dh.deviceID,
-						"SetVlan": strconv.FormatInt(int64(loSetVlan), 16)})
+						"SetVlan": strconv.FormatInt(int64(*loSetVlan), 16)})
 				} else if pActionSetField.Field.GetOfbField().Type == of.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
-					loSetPcp = uint8(pActionSetField.Field.GetOfbField().GetVlanPcp())
+					*loSetPcp = uint8(pActionSetField.Field.GetOfbField().GetVlanPcp())
 					logger.Debugw("FlowAdd Set PCP from SetField action", log.Fields{"device-id": dh.deviceID,
-						"SetPcp": loSetPcp})
+						"SetPcp": *loSetPcp})
 				} else {
 					logger.Warnw("FlowAdd action SetField invalid FieldType", log.Fields{"device-id": dh.deviceID,
 						"Type": pActionSetField.Field.GetOfbField().Type})
@@ -1734,6 +1764,43 @@
 			*/
 		}
 	} //for all Actions
+}
+
+//addFlowItemToUniPort parses the actual flow item to add it to the UniPort
+func (dh *DeviceHandler) addFlowItemToUniPort(apFlowItem *ofp.OfpFlowStats, apUniPort *OnuUniPort) error {
+	var loSetVlan uint16 = uint16(of.OfpVlanId_OFPVID_NONE)      //noValidEntry
+	var loMatchVlan uint16 = uint16(of.OfpVlanId_OFPVID_PRESENT) //reserved VLANID entry
+	var loAddPcp, loSetPcp uint8
+	var loIPProto uint32
+	/* the TechProfileId is part of the flow Metadata - compare also comment within
+	 * OLT-Adapter:openolt_flowmgr.go
+	 *     Metadata 8 bytes:
+	 *	   Most Significant 2 Bytes = Inner VLAN
+	 *	   Next 2 Bytes = Tech Profile ID(TPID)
+	 *	   Least Significant 4 Bytes = Port ID
+	 *     Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
+	 *     subscriber related flows.
+	 */
+
+	metadata := flow.GetMetadataFromWriteMetadataAction(apFlowItem)
+	if metadata == 0 {
+		logger.Debugw("FlowAdd invalid metadata - abort",
+			log.Fields{"device-id": dh.deviceID})
+		return errors.New("flowAdd invalid metadata")
+	}
+	loTpID := flow.GetTechProfileIDFromWriteMetaData(metadata)
+	logger.Debugw("FlowAdd TechProfileId", log.Fields{"device-id": dh.deviceID, "TP-Id": loTpID})
+
+	dh.getFlowOfbFields(apFlowItem, &loMatchVlan, &loAddPcp, &loIPProto)
+	if loIPProto == 2 {
+		// some workaround for TT workflow at proto == 2 (IGMP trap) -> ignore the flow
+		// avoids installing invalid EVTOCD rule
+		logger.Debugw("FlowAdd type IpProto 2: TT workaround: ignore flow",
+			log.Fields{"device-id": dh.deviceID,
+				"IpProto": strconv.FormatInt(int64(loIPProto), 16)})
+		return nil
+	}
+	dh.getFlowActions(apFlowItem, &loSetPcp, &loSetVlan)
 
 	if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
 		logger.Errorw("FlowAdd aborted - SetVlanId undefined, but MatchVid set", log.Fields{
@@ -1742,7 +1809,7 @@
 			"match_vid": strconv.FormatInt(int64(loMatchVlan), 16)})
 		//TODO!!: Use DeviceId within the error response to rwCore
 		//  likewise also in other error response cases to calling components as requested in [VOL-3458]
-		return errors.New("FlowAdd Set/Match VlanId inconsistent")
+		return errors.New("flowAdd Set/Match VlanId inconsistent")
 	}
 	if loSetVlan == uint16(of.OfpVlanId_OFPVID_NONE) && loMatchVlan == uint16(of.OfpVlanId_OFPVID_PRESENT) {
 		logger.Debugw("FlowAdd vlan-any/copy", log.Fields{"device-id": dh.deviceID})
@@ -1751,22 +1818,22 @@
 		//looks like OMCI value 4097 (copyFromOuter - for Uni double tagged) is not supported here
 		if loSetVlan != uint16(of.OfpVlanId_OFPVID_PRESENT) {
 			// not set to transparent
-			loSetVlan &= 0x0FFF //mask VID bits as prerequiste for vlanConfigFsm
+			loSetVlan &= 0x0FFF //mask VID bits as prerequisite for vlanConfigFsm
 		}
 		logger.Debugw("FlowAdd vlan-set", log.Fields{"device-id": dh.deviceID})
 	}
 	//TODO!!: further FlowAdd requests may be valid even in case the FSM is already running,
 	//  e.g. for multi-step flow configuration, error treatment must be redefined in this context as requested in [VOL-3441]
-	if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniId]; exist {
+	if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
 		logger.Errorw("FlowAdd aborted - FSM already running", log.Fields{
 			"device-id": dh.deviceID, "UniPort": apUniPort.portNo})
-		return errors.New("FlowAdd FSM already running")
+		return errors.New("flowAdd FSM already running")
 	}
 	return dh.createVlanFilterFsm(apUniPort,
 		loTpID, loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterDone)
 }
 
-// createVlanFilterFsm initialises and runs the VlanFilter FSM to transfer OMCI related VLAN config
+// createVlanFilterFsm initializes and runs the VlanFilter FSM to transfer OMCI related VLAN config
 func (dh *DeviceHandler) createVlanFilterFsm(apUniPort *OnuUniPort,
 	aTpID uint16, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8, aDevEvent OnuDeviceEvent) error {
 	chVlanFilterFsm := make(chan Message, 2048)
@@ -1774,40 +1841,39 @@
 	pDevEntry := dh.GetOnuDeviceEntry(true)
 	if pDevEntry == nil {
 		logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
-		return fmt.Errorf("No valid OnuDevice for device-id %x - aborting", dh.deviceID)
+		return fmt.Errorf("no valid OnuDevice for device-id %x - aborting", dh.deviceID)
 	}
 
 	pVlanFilterFsm := NewUniVlanConfigFsm(dh, pDevEntry.PDevOmciCC, apUniPort, dh.pOnuTP,
 		pDevEntry.pOnuDB, aTpID, aDevEvent, "UniVlanConfigFsm", dh.deviceID, chVlanFilterFsm,
 		dh.pOpenOnuAc.AcceptIncrementalEvto, aMatchVlan, aSetVlan, aSetPcp)
 	if pVlanFilterFsm != nil {
-		dh.UniVlanConfigFsmMap[apUniPort.uniId] = pVlanFilterFsm
+		dh.UniVlanConfigFsmMap[apUniPort.uniID] = pVlanFilterFsm
 		pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
 		if pVlanFilterStatemachine != nil {
 			if pVlanFilterStatemachine.Is(vlanStDisabled) {
 				if err := pVlanFilterStatemachine.Event(vlanEvStart); err != nil {
 					logger.Warnw("UniVlanConfigFsm: can't start", log.Fields{"err": err})
-					return fmt.Errorf("Can't start UniVlanConfigFsm for device-id %x", dh.deviceID)
-				} else {
-					/***** UniVlanConfigFsm started */
-					logger.Debugw("UniVlanConfigFsm started", log.Fields{
-						"state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
-						"UniPort": apUniPort.portNo})
+					return fmt.Errorf("can't start UniVlanConfigFsm for device-id %x", dh.deviceID)
 				}
+				/***** UniVlanConfigFsm started */
+				logger.Debugw("UniVlanConfigFsm started", log.Fields{
+					"state": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID,
+					"UniPort": apUniPort.portNo})
 			} else {
 				logger.Warnw("wrong state of UniVlanConfigFsm - want: disabled", log.Fields{
 					"have": pVlanFilterStatemachine.Current(), "device-id": dh.deviceID})
-				return fmt.Errorf("UniVlanConfigFsm not in expected disabled state for device-id %x", dh.deviceID)
+				return fmt.Errorf("uniVlanConfigFsm not in expected disabled state for device-id %x", dh.deviceID)
 			}
 		} else {
 			logger.Errorw("UniVlanConfigFsm StateMachine invalid - cannot be executed!!", log.Fields{
 				"device-id": dh.deviceID})
-			return fmt.Errorf("UniVlanConfigFsm invalid for device-id %x", dh.deviceID)
+			return fmt.Errorf("uniVlanConfigFsm invalid for device-id %x", dh.deviceID)
 		}
 	} else {
 		logger.Errorw("UniVlanConfigFsm could not be created - abort!!", log.Fields{
 			"device-id": dh.deviceID, "UniPort": apUniPort.portNo})
-		return fmt.Errorf("UniVlanConfigFsm could not be created for device-id %x", dh.deviceID)
+		return fmt.Errorf("uniVlanConfigFsm could not be created for device-id %x", dh.deviceID)
 	}
 	return nil
 }
@@ -1817,7 +1883,7 @@
 	//TODO!! verify and start pending flow configuration
 	//some pending config request my exist in case the UniVlanConfig FSM was already started - with internal data -
 	//but execution was set to 'on hold' as first the TechProfile config had to be applied
-	if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[apUniPort.uniId]; exist {
+	if pVlanFilterFsm, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
 		//VlanFilterFsm exists and was already started (assumed to wait for TechProfile execution here)
 		pVlanFilterStatemachine := pVlanFilterFsm.pAdaptFsm.pFsm
 		if pVlanFilterStatemachine != nil {
@@ -1848,5 +1914,5 @@
 	logger.Debugw("remove UniVlanConfigFsm StateMachine", log.Fields{
 		"device-id": dh.deviceID, "uniPort": apUniPort.portNo})
 	//save to do, even if entry dows not exist
-	delete(dh.UniVlanConfigFsmMap, apUniPort.uniId)
+	delete(dh.UniVlanConfigFsmMap, apUniPort.uniID)
 }