[VOL-3800] : Random ping failures seen on alpha and iskratel ONUs during sanity test
- Process gem port deletes after any active flow deletes are completed.
  On certain models of ONUs it is seen that if flow deletes and gem port
  deletes are interleaved with each other and it leaves some stale configuration
  on the ONUs. As a result any further datapath related flow configuration
  will not work predictabily - there are some invalid packet taggings.

  Since during tech profile add, we setup the gemport, tcont before
  adding the flows, it is reasonable to remove flows before deleting
  the tech profile.

Change-Id: I62dbbf046f2ea5f9df5416f99060093b930bd448
diff --git a/internal/pkg/onuadaptercore/omci_vlan_config.go b/internal/pkg/onuadaptercore/omci_vlan_config.go
index 21cdbda..42a35f5 100644
--- a/internal/pkg/onuadaptercore/omci_vlan_config.go
+++ b/internal/pkg/onuadaptercore/omci_vlan_config.go
@@ -1061,12 +1061,20 @@
 			"device-id": oFsm.deviceID})
 		// Can't call FSM Event directly, decoupling it
 		go func(a_pBaseFsm *fsm.FSM) {
-			_ = a_pBaseFsm.Event(vlanEvRemFlowDone)
+			_ = a_pBaseFsm.Event(vlanEvRemFlowDone, loRuleParams.TpID)
 		}(pConfigVlanStateBaseFsm)
 	}
 }
 
 func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(ctx context.Context, e *fsm.Event) {
+	var tpID uint8
+	// Extract the tpID
+	if len(e.Args) > 0 {
+		tpID = e.Args[0].(uint8)
+		logger.Debugw(ctx, "UniVlanConfigFsm - flow removed for tp id", log.Fields{"device-id": oFsm.deviceID, "tpID": e.Args[0].(uint8)})
+	} else {
+		logger.Warnw(ctx, "UniVlanConfigFsm - tp id not available", log.Fields{"device-id": oFsm.deviceID})
+	}
 	logger.Debugw(ctx, "UniVlanConfigFsm - removing the removal data", log.Fields{
 		"in state": e.FSM.Current(), "device-id": oFsm.deviceID})
 
@@ -1096,6 +1104,16 @@
 			}
 		}(pConfigVlanStateAFsm)
 	}
+
+	oFsm.mutexFlowParams.RLock()
+	noOfFlowRem := len(oFsm.uniRemoveFlowsSlice)
+	oFsm.mutexFlowParams.RUnlock()
+	// If all pending flow removes are completed and TP ID is valid, processing any pending TP delete
+	if noOfFlowRem == 0 && tpID > 0 {
+		logger.Debugw(ctx, "processing pending tp delete", log.Fields{"device-id": oFsm.deviceID, "tpID": tpID})
+		// If we are here then all flows are removed.
+		oFsm.pDeviceHandler.ProcessPendingTpDelete(ctx, oFsm.pOnuUniPort, tpID)
+	}
 }
 
 func (oFsm *UniVlanConfigFsm) enterResetting(ctx context.Context, e *fsm.Event) {
@@ -1835,7 +1853,7 @@
 
 	// if Config has been done for all EVTOCD entries let the FSM proceed
 	logger.Debugw(ctx, "EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
-	_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone)
+	_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone, aRuleParams.TpID)
 }
 
 func (oFsm *UniVlanConfigFsm) waitforOmciResponse(ctx context.Context) error {
@@ -2055,3 +2073,10 @@
 	}
 	return nil
 }
+
+// IsFlowRemovePending returns true if there are pending flows to remove, else false.
+func (oFsm *UniVlanConfigFsm) IsFlowRemovePending() bool {
+	oFsm.mutexFlowParams.RLock()
+	defer oFsm.mutexFlowParams.RUnlock()
+	return len(oFsm.uniRemoveFlowsSlice) > 0
+}