[VOL-4499] flow resource cleanup after childDeviceLost

Change-Id: I2e89f1142e38d63229de63d11cbd8887cc166529
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index bfdd3ee..2d3c7c5 100644
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -2525,16 +2525,42 @@
 			"err":       err})
 	} else {
 		logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
+		// Delete flows from device before schedulers and queue
+		// Clear flowids for gem cache.
+		removedFlows := []uint64{}
+		for _, gem := range onuGem.GemPorts {
+			if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
+				for _, flowID := range flowIDs {
+					//multiple gem port can have the same flow id
+					//it is better to send only one flowRemove request to the agent
+					var alreadyRemoved bool
+					for _, removedFlowID := range removedFlows {
+						if removedFlowID == flowID {
+							logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
+							alreadyRemoved = true
+							break
+						}
+					}
+					if !alreadyRemoved {
+						flow := &oop.Flow{FlowId: flowID}
+						if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
+							logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
+								"device-id":  dh.device.Id,
+								"onu-device": onu,
+								"err":        err})
+						}
+						removedFlows = appendUnique64bit(removedFlows, flowID)
+					}
+				}
+			}
+			_ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
+		}
 		if err := dh.clearUNIData(ctx, onuGem); err != nil {
 			logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
 				"device-id":  dh.device.Id,
 				"onu-device": onu,
 				"err":        err})
 		}
-		// Clear flowids for gem cache.
-		for _, gem := range onuGem.GemPorts {
-			_ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
-		}
 		if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
 			logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
 				"intf-id":    intfID,
diff --git a/internal/pkg/core/openolt_flowmgr.go b/internal/pkg/core/openolt_flowmgr.go
index 846ed57..9606217 100644
--- a/internal/pkg/core/openolt_flowmgr.go
+++ b/internal/pkg/core/openolt_flowmgr.go
@@ -3198,6 +3198,15 @@
 	return append(slice, item)
 }
 
+func appendUnique64bit(slice []uint64, item uint64) []uint64 {
+	for _, sliceElement := range slice {
+		if sliceElement == item {
+			return slice
+		}
+	}
+	return append(slice, item)
+}
+
 // getNniIntfID gets nni intf id from the flow classifier/action
 func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {