[VOL-4429] openonuAdapterGo - omci config error and crash during flow removal after adapter restart

Change-Id: Ifa3c62071fe59e270dd070ed8ccbae9018d582f5
diff --git a/VERSION b/VERSION
index 13097ab..4e7057f 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.0.3-dev240
+2.0.3-dev241
diff --git a/internal/pkg/avcfg/omci_ani_config.go b/internal/pkg/avcfg/omci_ani_config.go
index 6ade746..d4c8082 100755
--- a/internal/pkg/avcfg/omci_ani_config.go
+++ b/internal/pkg/avcfg/omci_ani_config.go
@@ -784,7 +784,7 @@
 	uniVlanConfigFsm := oFsm.pDeviceHandler.GetUniVlanConfigFsm(oFsm.pOnuUniPort.UniID)
 	if uniVlanConfigFsm != nil {
 		// ensure mutexTPState not locked before calling some VlanConfigFsm activity (that might already be pending on it)
-		if uniVlanConfigFsm.IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
+		if uniVlanConfigFsm.IsFlowRemovePending(ctx, oFsm.waitFlowDeleteChannel) {
 			logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
 				log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.UniID, "techProfile-id": oFsm.techProfileID})
 			// if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
diff --git a/internal/pkg/avcfg/omci_vlan_config.go b/internal/pkg/avcfg/omci_vlan_config.go
index 03cacf9..7d6dcfe 100755
--- a/internal/pkg/avcfg/omci_vlan_config.go
+++ b/internal/pkg/avcfg/omci_vlan_config.go
@@ -213,7 +213,7 @@
 		logger.Errorw(ctx, "UniVlanConfigFsm's cmn.AdapterFsm could not be instantiated!!", log.Fields{
 			"device-id": instFsm.deviceID})
 		// Push response on the response channel
-		instFsm.PushReponseOnFlowResponseChannel(ctx, respChan, fmt.Errorf("adapter-fsm-could-not-be-instantiated"))
+		instFsm.pushReponseOnFlowResponseChannel(ctx, respChan, fmt.Errorf("adapter-fsm-could-not-be-instantiated"))
 		return nil
 	}
 	instFsm.PAdaptFsm.PFsm = fsm.NewFSM(
@@ -271,7 +271,7 @@
 		logger.Errorw(ctx, "UniVlanConfigFsm's Base FSM could not be instantiated!!", log.Fields{
 			"device-id": instFsm.deviceID})
 		// Push response on the response channel
-		instFsm.PushReponseOnFlowResponseChannel(ctx, respChan, fmt.Errorf("adapter-base-fsm-could-not-be-instantiated"))
+		instFsm.pushReponseOnFlowResponseChannel(ctx, respChan, fmt.Errorf("adapter-base-fsm-could-not-be-instantiated"))
 		return nil
 	}
 
@@ -339,6 +339,8 @@
 	if oFsm.pDeviceHandler.IsSkipOnuConfigReconciling() {
 		oFsm.reconcileVlanFilterList(ctx, uint16(loRuleParams.SetVid))
 	}
+	//cmp also usage in EVTOCDE create in omci_cc
+	oFsm.evtocdID = cmn.MacBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.MacBpNo)
 	oFsm.NumUniFlows = 1
 	oFsm.uniRemoveFlowsSlice = make([]uniRemoveVlanFlowParams, 0) //initially nothing to remove
 
@@ -354,6 +356,10 @@
 
 //CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
 func (oFsm *UniVlanConfigFsm) CancelProcessing(ctx context.Context) {
+	if oFsm == nil {
+		logger.Error(ctx, "no valid UniVlanConfigFsm!")
+		return
+	}
 	//mutex protection is required for possible concurrent access to FSM members
 	oFsm.mutexIsAwaitingResponse.Lock()
 	oFsm.isCanceled = true
@@ -378,7 +384,11 @@
 }
 
 //GetWaitingTpID returns the TpId that the FSM might be waiting for continuation (0 if none)
-func (oFsm *UniVlanConfigFsm) GetWaitingTpID() uint8 {
+func (oFsm *UniVlanConfigFsm) GetWaitingTpID(ctx context.Context) uint8 {
+	if oFsm == nil {
+		logger.Error(ctx, "no valid UniVlanConfigFsm!")
+		return 0
+	}
 	//mutex protection is required for possible concurrent access to FSM members
 	oFsm.mutexFlowParams.RLock()
 	defer oFsm.mutexFlowParams.RUnlock()
@@ -386,7 +396,11 @@
 }
 
 //RequestClearPersistency sets the internal flag to not clear persistency data (false=NoClear)
-func (oFsm *UniVlanConfigFsm) RequestClearPersistency(aClear bool) {
+func (oFsm *UniVlanConfigFsm) RequestClearPersistency(ctx context.Context, aClear bool) {
+	if oFsm == nil {
+		logger.Error(ctx, "no valid UniVlanConfigFsm!")
+		return
+	}
 	//mutex protection is required for possible concurrent access to FSM members
 	oFsm.mutexFlowParams.Lock()
 	defer oFsm.mutexFlowParams.Unlock()
@@ -400,6 +414,10 @@
 // nolint: gocyclo
 func (oFsm *UniVlanConfigFsm) SetUniFlowParams(ctx context.Context, aTpID uint8, aCookieSlice []uint64,
 	aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8, lastFlowToReconcile bool, aMeter *voltha.OfpMeterConfig, respChan *chan error) error {
+	if oFsm == nil {
+		logger.Error(ctx, "no valid UniVlanConfigFsm!")
+		return fmt.Errorf("no-valid-UniVlanConfigFsm")
+	}
 	loRuleParams := cmn.UniVlanRuleParams{
 		TpID:     aTpID,
 		MatchVid: uint32(aMatchVlan),
@@ -449,7 +467,7 @@
 						"device-id": oFsm.deviceID, "slice length": len(oFsm.uniRemoveFlowsSlice)})
 					oFsm.mutexFlowParams.RUnlock()
 					err = fmt.Errorf("abort UniVlanConfigFsm flow add - inconsistent RemoveFlowsSlice %s", oFsm.deviceID)
-					oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, err)
+					oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, err)
 					return err
 
 				}
@@ -459,7 +477,7 @@
 					logger.Errorw(ctx, "UniVlanConfigFsm suspension on add aborted - abort complete add-request", log.Fields{
 						"device-id": oFsm.deviceID, "cookie": removeUniFlowParams.cookie})
 					err = fmt.Errorf("abort UniVlanConfigFsm suspension on add %s", oFsm.deviceID)
-					oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, err)
+					oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, err)
 					return err
 				}
 				oFsm.mutexFlowParams.RLock()
@@ -506,7 +524,7 @@
 							logger.Errorw(ctx, "UniVlanConfigFsm suspended add-cookie-to-rule aborted", log.Fields{
 								"device-id": oFsm.deviceID, "cookie": delayedCookie})
 							err = fmt.Errorf(" UniVlanConfigFsm suspended add-cookie-to-rule aborted %s", oFsm.deviceID)
-							oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, err)
+							oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, err)
 							return err
 						}
 						flowCookieModify, requestAppendRule = oFsm.reviseFlowConstellation(ctx, delayedCookie, loRuleParams)
@@ -532,7 +550,7 @@
 			logger.Errorw(ctx, "UniVlanConfigFsm suspended add-new-rule aborted", log.Fields{
 				"device-id": oFsm.deviceID, "cookie": delayedCookie})
 			err = fmt.Errorf(" UniVlanConfigFsm suspended add-new-rule aborted %s", oFsm.deviceID)
-			oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, err)
+			oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, err)
 			return err
 		}
 		requestAppendRule = true //default assumption here is that rule is to be appended
@@ -576,7 +594,7 @@
 						logger.Errorw(ctx, "error in FsmEvent handling UniVlanConfigFsm!",
 							log.Fields{"fsmState": oFsm.PAdaptFsm.PFsm.Current(), "error": fsmErr, "device-id": oFsm.deviceID})
 						err = fsmErr
-						oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, err)
+						oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, err)
 						return err
 					}
 				}
@@ -609,7 +627,7 @@
 								"sliceLen": len(oFsm.uniVlanFlowParamsSlice), "device-id": oFsm.deviceID})
 						oFsm.mutexFlowParams.Unlock()
 						err = fmt.Errorf("abort UniVlanConfigFsm on add due to internal counter mismatch %s", oFsm.deviceID)
-						oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, err)
+						oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, err)
 						return err
 					}
 
@@ -639,7 +657,7 @@
 					if fsmErr != nil {
 						logger.Errorw(ctx, "error in FsmEvent handling UniVlanConfigFsm!",
 							log.Fields{"fsmState": pConfigVlanStateBaseFsm.Current(), "error": fsmErr, "device-id": oFsm.deviceID})
-						oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, fsmErr)
+						oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, fsmErr)
 						return fsmErr
 					}
 				}
@@ -653,14 +671,14 @@
 				"device-id": oFsm.deviceID, "flow-number": oFsm.NumUniFlows})
 			oFsm.mutexFlowParams.Unlock()
 			err = fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
-			oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, err)
+			oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, err)
 			return err
 		}
 	} else {
 		// no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
 		kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
 		// push response on response channel as there is nothing to be done for this flow
-		oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, nil)
+		oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, nil)
 
 		oFsm.mutexFlowParams.RLock()
 		if oFsm.NumUniFlows == oFsm.ConfiguredUniFlow {
@@ -820,6 +838,10 @@
 // if found removes cookie from flow cookie list and if this is empty
 // initiates removal of the flow related configuration from the ONU (via OMCI)
 func (oFsm *UniVlanConfigFsm) RemoveUniFlowParams(ctx context.Context, aCookie uint64, respChan *chan error) error {
+	if oFsm == nil {
+		logger.Error(ctx, "no valid UniVlanConfigFsm!")
+		return fmt.Errorf("no-valid-UniVlanConfigFsm")
+	}
 	var deletedCookie uint64
 	flowCookieMatch := false
 	//mutex protection is required for possible concurrent access to FSM members
@@ -860,7 +882,7 @@
 							"device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
 					}
 					// Push response on the response channel
-					oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, nil)
+					oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, nil)
 					//permanently store the modified flow config for reconcile case and immediately write to KvStore
 					if oFsm.pDeviceHandler != nil {
 						if err := oFsm.pDeviceHandler.StorePersUniFlowConfig(ctx, oFsm.pOnuUniPort.UniID,
@@ -885,7 +907,7 @@
 			go oFsm.pDeviceHandler.DeviceProcStatusUpdate(ctx, cmn.OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetRemoveNoKvStore))
 		}
 		// Push response on the response channel
-		oFsm.PushReponseOnFlowResponseChannel(ctx, respChan, nil)
+		oFsm.pushReponseOnFlowResponseChannel(ctx, respChan, nil)
 		return nil
 	} //unknown cookie
 
@@ -1037,7 +1059,7 @@
 				if !aWasConfigured {
 					// We did not actually process this flow but was removed before that.
 					// Indicate success response for the flow to caller who is blocking on a response
-					oFsm.PushReponseOnFlowResponseChannel(ctx, storedUniFlowParams.RespChan, nil)
+					oFsm.pushReponseOnFlowResponseChannel(ctx, storedUniFlowParams.RespChan, nil)
 				}
 
 				//cut off the requested flow by slicing out this element
@@ -1145,8 +1167,6 @@
 		oFsm.actualUniFlowParam = oFsm.uniVlanFlowParamsSlice[0]
 		tpID := oFsm.actualUniFlowParam.VlanRuleParams.TpID
 		oFsm.TpIDWaitingFor = tpID
-		//cmp also usage in EVTOCDE create in omci_cc
-		oFsm.evtocdID = cmn.MacBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.MacBpNo)
 		loSetVlan := oFsm.actualUniFlowParam.VlanRuleParams.SetVid
 		//attention: take care to release the mutexFlowParams when calling the FSM directly -
 		//  synchronous FSM 'event/state' functions may rely on this mutex
@@ -1297,7 +1317,7 @@
 		"device-id":         oFsm.deviceID,
 		"overall-uni-rules": oFsm.NumUniFlows, "configured-uni-rules": oFsm.ConfiguredUniFlow})
 	if len(oFsm.uniVlanFlowParamsSlice) > 0 {
-		oFsm.PushReponseOnFlowResponseChannel(ctx, oFsm.actualUniFlowParam.RespChan, nil)
+		oFsm.pushReponseOnFlowResponseChannel(ctx, oFsm.actualUniFlowParam.RespChan, nil)
 	}
 
 	pConfigVlanStateAFsm := oFsm.PAdaptFsm
@@ -1812,7 +1832,7 @@
 	oFsm.mutexFlowParams.Unlock()
 
 	// send response on the response channel for the removed flow.
-	oFsm.PushReponseOnFlowResponseChannel(ctx, flowRespChan, nil)
+	oFsm.pushReponseOnFlowResponseChannel(ctx, flowRespChan, nil)
 }
 
 func (oFsm *UniVlanConfigFsm) enterResetting(ctx context.Context, e *fsm.Event) {
@@ -1863,7 +1883,7 @@
 				oFsm.mutexFlowParams.RLock()
 			}
 			// Send response on response channel if the caller is waiting on it.
-			oFsm.PushReponseOnFlowResponseChannel(ctx, removeUniFlowParams.respChan, fmt.Errorf("internal-error"))
+			oFsm.pushReponseOnFlowResponseChannel(ctx, removeUniFlowParams.respChan, fmt.Errorf("internal-error"))
 		}
 	}
 
@@ -1877,7 +1897,7 @@
 			if len(oFsm.uniVlanFlowParamsSlice) > 0 {
 				for _, vlanRule := range oFsm.uniVlanFlowParamsSlice {
 					// Send response on response channel if the caller is waiting on it.
-					oFsm.PushReponseOnFlowResponseChannel(ctx, vlanRule.RespChan, fmt.Errorf("internal-error"))
+					oFsm.pushReponseOnFlowResponseChannel(ctx, vlanRule.RespChan, fmt.Errorf("internal-error"))
 				}
 				var emptySlice = make([]cmn.UniVlanFlowParams, 0)
 				_ = oFsm.pDeviceHandler.StorePersUniFlowConfig(ctx, oFsm.pOnuUniPort.UniID, &emptySlice, true) //ignore errors
@@ -3146,7 +3166,11 @@
 }
 
 // IsFlowRemovePending returns true if there are pending flows to remove, else false.
-func (oFsm *UniVlanConfigFsm) IsFlowRemovePending(aFlowDeleteChannel chan<- bool) bool {
+func (oFsm *UniVlanConfigFsm) IsFlowRemovePending(ctx context.Context, aFlowDeleteChannel chan<- bool) bool {
+	if oFsm == nil {
+		logger.Error(ctx, "no valid UniVlanConfigFsm!")
+		return false
+	}
 	oFsm.mutexFlowParams.Lock()
 	defer oFsm.mutexFlowParams.Unlock()
 	if len(oFsm.uniRemoveFlowsSlice) > 0 {
@@ -3173,8 +3197,8 @@
 	}
 }
 
-// PushReponseOnFlowResponseChannel pushes response on the response channel if available
-func (oFsm *UniVlanConfigFsm) PushReponseOnFlowResponseChannel(ctx context.Context, respChan *chan error, err error) {
+// pushReponseOnFlowResponseChannel pushes response on the response channel if available
+func (oFsm *UniVlanConfigFsm) pushReponseOnFlowResponseChannel(ctx context.Context, respChan *chan error, err error) {
 	if respChan != nil {
 		// Do it in a non blocking fashion, so that in case the flow handler routine has shutdown for any reason, we do not block here
 		select {
diff --git a/internal/pkg/common/interfaces.go b/internal/pkg/common/interfaces.go
index ef5e004..1f7d457 100755
--- a/internal/pkg/common/interfaces.go
+++ b/internal/pkg/common/interfaces.go
@@ -178,5 +178,5 @@
 
 // IuniVlanConfigFsm interface to uniVlanConfigFsm
 type IuniVlanConfigFsm interface {
-	IsFlowRemovePending(chan<- bool) bool
+	IsFlowRemovePending(context.Context, chan<- bool) bool
 }
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 41a8771..f2cd542 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -2076,7 +2076,7 @@
 				dh.lockVlanConfig.RUnlock()
 				//reset of all Fsm is always accompanied by global persistency data removal
 				//  no need to remove specific data
-				pVlanFilterFsm.RequestClearPersistency(false)
+				pVlanFilterFsm.RequestClearPersistency(ctx, false)
 				//ensure the FSM processing is stopped in case waiting for some response
 				pVlanFilterFsm.CancelProcessing(ctx)
 			} else {
@@ -3268,7 +3268,7 @@
 		pVlanFilterStatemachine := pVlanFilterFsm.PAdaptFsm.PFsm
 		if pVlanFilterStatemachine != nil {
 			//if this was an event of the TP processing that was waited for in the VlanFilterFsm
-			if pVlanFilterFsm.GetWaitingTpID() == aTpID {
+			if pVlanFilterFsm.GetWaitingTpID(ctx) == aTpID {
 				if pVlanFilterStatemachine.Is(avcfg.VlanStWaitingTechProf) {
 					if err := pVlanFilterStatemachine.Event(avcfg.VlanEvContinueConfig); err != nil {
 						logger.Warnw(ctx, "UniVlanConfigFsm: can't continue processing", log.Fields{"err": err,
@@ -4147,7 +4147,10 @@
 
 // GetUniVlanConfigFsm - TODO: add comment
 func (dh *deviceHandler) GetUniVlanConfigFsm(uniID uint8) cmn.IuniVlanConfigFsm {
-	return dh.UniVlanConfigFsmMap[uniID]
+	dh.lockVlanConfig.RLock()
+	value := dh.UniVlanConfigFsmMap[uniID]
+	dh.lockVlanConfig.RUnlock()
+	return value
 }
 
 // GetOnuAlarmManager - TODO: add comment