[VOL-5402]-VGC all fixes till date from jan 2024

Change-Id: I2857e0ef9b1829a28c6e3ad04da96b826cb900b6
Signed-off-by: Akash Soni <akash.soni@radisys.com>
diff --git a/internal/pkg/controller/addflows.go b/internal/pkg/controller/addflows.go
index b7d42cd..a4f8a8d 100644
--- a/internal/pkg/controller/addflows.go
+++ b/internal/pkg/controller/addflows.go
@@ -93,7 +93,7 @@
 				if err.Error() == ErrDuplicateFlow {
 					dbFlow, _ := aft.device.GetFlow(flow.Cookie)
 					if dbFlow.State == of.FlowAddSuccess {
-						aft.device.triggerFlowNotification(ctx, flow.Cookie, aft.flow.Command, of.BwAvailDetails{}, nil, true)
+						aft.device.triggerFlowNotification(ctx, flow.Cookie, aft.flow.Command, of.BwAvailDetails{}, nil)
 						flowsPresent++
 						continue
 					}
@@ -109,7 +109,8 @@
 				// aft.device.AddFlowToDb(dbFlow)
 				flowsToProcess[flow.Cookie] = dbFlow
 			}
-			aft.device.triggerFlowNotification(ctx, flow.Cookie, aft.flow.Command, of.BwAvailDetails{}, nil, false)
+			// Below call will delete flow from DB and will not allow to maintain flow count and state. Hence commenting the below call.
+			//aft.device.triggerFlowNotification(ctx, flow.Cookie, aft.flow.Command, of.BwAvailDetails{}, nil, false)
 		}
 	}
 
@@ -126,7 +127,7 @@
 			for _, flow := range aft.flow.SubFlows {
 				logger.Warnw(ctx, "Skip Flow Update", log.Fields{"Reason": "Port Deleted", "PortName": aft.flow.PortName, "PortNo": aft.flow.PortID, "Cookie": flow.Cookie, "Operation": aft.flow.Command})
 				if aft.flow.Command == of.CommandDel {
-					aft.device.triggerFlowNotification(ctx, flow.Cookie, aft.flow.Command, of.BwAvailDetails{}, nil, true)
+					aft.device.triggerFlowNotification(ctx, flow.Cookie, aft.flow.Command, of.BwAvailDetails{}, nil)
 				}
 			}
 			return nil
@@ -162,7 +163,7 @@
 				}
 				break
 			}
-			aft.device.triggerFlowNotification(ctx, flow.FlowMod.Cookie, aft.flow.Command, of.BwAvailDetails{}, err, true)
+			aft.device.triggerFlowNotification(ctx, flow.FlowMod.Cookie, aft.flow.Command, of.BwAvailDetails{}, err)
 		} else {
 			logger.Errorw(ctx, "Update Flow Table Failed: Voltha Client Unavailable", log.Fields{"Flow": flow})
 		}
diff --git a/internal/pkg/controller/auditdevice.go b/internal/pkg/controller/auditdevice.go
index 461f54a..ecee452 100644
--- a/internal/pkg/controller/auditdevice.go
+++ b/internal/pkg/controller/auditdevice.go
@@ -121,7 +121,7 @@
 				// This port exists in the received list and the map at
 				// VGC. This is common so delete it
 				logger.Infow(ctx, "Port State Mismatch", log.Fields{"Port": vgcPort.ID, "OfpPort": ofpPort.PortNo, "ReceivedState": ofpPort.State, "CurrentState": vgcPort.State})
-				ad.device.ProcessPortState(ctx, ofpPort.PortNo, ofpPort.State)
+				ad.device.ProcessPortState(ctx, ofpPort.PortNo, ofpPort.State, ofpPort.Name)
 			} else {
 				//To ensure the flows are in sync with port status and no mismatch due to reboot,
 				// repush/delete flows based on current port status
@@ -179,7 +179,7 @@
 			logger.Warnw(ctx, "AddPort Failed", log.Fields{"Port No": mp.PortNo, "Port Name": mp.Name, "Reason": err})
 		}
 		if mp.State == uint32(ofp.OfpPortState_OFPPS_LIVE) {
-			ad.device.ProcessPortState(cntx, mp.PortNo, mp.State)
+			ad.device.ProcessPortState(cntx, mp.PortNo, mp.State, mp.Name)
 		}
 		logger.Debugw(ctx, "Processed Port Add Ind", log.Fields{"Port No": mp.PortNo, "Port Name": mp.Name})
 	}
diff --git a/internal/pkg/controller/audittables.go b/internal/pkg/controller/audittables.go
index d5ce858..0be505a 100644
--- a/internal/pkg/controller/audittables.go
+++ b/internal/pkg/controller/audittables.go
@@ -257,7 +257,7 @@
 			break
 		}
 
-		logger.Debugw(ctx, "Auditing Flow", log.Fields{"Cookie": flow.Cookie})
+		logger.Debugw(ctx, "Auditing Flow", log.Fields{"Cookie": flow.Cookie, "State": flow.State})
 		if _, ok := rcvdFlows[flow.Cookie]; ok {
 			// The flow exists in the device too. Just remove it from
 			// the received flows & trigger flow success indication unless
@@ -265,13 +265,26 @@
 
 			if flow.State != of.FlowDelFailure && flow.State != of.FlowDelPending {
 				delete(rcvdFlows, flow.Cookie)
+			} else {
+				// Update flow delete count since we are retrying the flow delete due to failure
+				att.device.UpdateFlowCount(cntx, flow.Cookie)
 			}
 			defaultSuccessFlowStatus.Cookie = strconv.FormatUint(flow.Cookie, 10)
 		} else {
 			// The flow exists at the controller but not at the device
 			// Push the flow to the device
 			logger.Debugw(ctx, "Adding Flow To Missing Flows", log.Fields{"Cookie": flow.Cookie})
-			flowsToAdd.SubFlows[flow.Cookie] = flow
+			if !att.device.IsFlowAddThresholdReached(flow.FlowCount, flow.Cookie) {
+				flowsToAdd.SubFlows[flow.Cookie] = flow
+				att.device.UpdateFlowCount(cntx, flow.Cookie)
+			} else if flow.State != of.FlowDelFailure {
+				// Release the lock before deactivating service, as we acquire the same lock to delete flows
+				att.device.flowLock.Unlock()
+				// If flow add threshold has reached, deactivate the service corresponding to the UNI
+				GetController().CheckAndDeactivateService(cntx, flow, att.device.SerialNum, att.device.ID)
+				// Acquire the lock again for processing remaining flows
+				att.device.flowLock.Lock()
+			}
 		}
 	}
 	att.device.flowLock.Unlock()
@@ -301,10 +314,8 @@
 		return
 	}
 	for _, flow := range ofFlows {
-		var dbFlow *of.VoltSubFlow
-		var present bool
 		if flow.FlowMod != nil {
-			if dbFlow, present = att.device.GetFlow(flow.FlowMod.Cookie); !present {
+			if _, present := att.device.GetFlow(flow.FlowMod.Cookie); !present {
 				logger.Warnw(ctx, "Flow Removed from DB. Ignoring Add Missing Flow", log.Fields{"Device": att.device.ID, "Cookie": flow.FlowMod.Cookie})
 				continue
 			}
@@ -313,7 +324,7 @@
 		if _, err = vc.UpdateLogicalDeviceFlowTable(att.ctx, flow); err != nil {
 			logger.Errorw(ctx, "Update Flow Table Failed", log.Fields{"Reason": err.Error()})
 		}
-		att.device.triggerFlowResultNotification(cntx, flow.FlowMod.Cookie, dbFlow, of.CommandAdd, bwConsumedInfo, err, true)
+		att.device.triggerFlowNotification(cntx, flow.FlowMod.Cookie, of.CommandAdd, bwConsumedInfo, err)
 	}
 }
 
@@ -329,13 +340,13 @@
 
 	// Let's cycle through the flows to delete the excess flows
 	for _, flow := range flows {
-		if _, present := att.device.GetFlow(flow.Cookie); present {
-			logger.Warnw(ctx, "Flow Present in DB. Ignoring Delete Excess Flow", log.Fields{"Device": att.device.ID, "Cookie": flow.Cookie})
-			continue
-		}
-
-		if flag := GetController().IsFlowDelThresholdReached(cntx, strconv.FormatUint(flow.Cookie, 10), att.device.ID); flag {
-			logger.Warnw(ctx, "Flow delete threshold reached, skipping flow delete", log.Fields{"Device": att.device.ID, "Cookie": flow.Cookie})
+		if dbFlow, present := att.device.GetFlow(flow.Cookie); present {
+			if dbFlow.State != of.FlowDelFailure && dbFlow.State != of.FlowDelPending {
+				logger.Warnw(ctx, "Flow Present in DB. Ignoring Delete Excess Flow", log.Fields{"Device": att.device.ID, "Cookie": flow.Cookie})
+				continue
+			}
+		} else {
+			logger.Debugw(ctx, "Flow removed from DB after delete threshold reached. Ignoring Delete Excess Flow", log.Fields{"Device": att.device.ID, "Cookie": flow.Cookie})
 			continue
 		}
 
@@ -365,7 +376,7 @@
 		if _, err = vc.UpdateLogicalDeviceFlowTable(att.ctx, flowUpdate); err != nil {
 			logger.Errorw(ctx, "Flow Audit Delete Failed", log.Fields{"Reason": err.Error()})
 		}
-		att.device.triggerFlowResultNotification(cntx, flow.Cookie, nil, of.CommandDel, of.BwAvailDetails{}, err, true)
+		att.device.triggerFlowNotification(cntx, flow.Cookie, of.CommandDel, of.BwAvailDetails{}, err)
 	}
 }
 
@@ -562,11 +573,16 @@
 		logger.Debugw(ctx, "Process Port State Ind", log.Fields{"Port No": vgcPort.ID, "Port Name": vgcPort.Name})
 
 		if ofpPort, ok := missingPorts[id]; ok {
+			if vgcPort.Name != ofpPort.Name {
+				logger.Infow(ctx, "Port Name Mismatch", log.Fields{"vgcPort": vgcPort.Name, "ofpPort": ofpPort.Name, "ID": id})
+				att.DeleteMismatchPorts(ctx, vgcPort, ofpPort.Name)
+				return
+			}
 			if ((vgcPort.State == PortStateDown) && (ofpPort.State == uint32(ofp.OfpPortState_OFPPS_LIVE))) || ((vgcPort.State == PortStateUp) && (ofpPort.State != uint32(ofp.OfpPortState_OFPPS_LIVE))) {
 				// This port exists in the received list and the map at
 				// VGC. This is common so delete it
 				logger.Infow(ctx, "Port State Mismatch", log.Fields{"Port": vgcPort.ID, "OfpPort": ofpPort.PortNo, "ReceivedState": ofpPort.State, "CurrentState": vgcPort.State})
-				att.device.ProcessPortState(ctx, ofpPort.PortNo, ofpPort.State)
+				att.device.ProcessPortState(ctx, ofpPort.PortNo, ofpPort.State, ofpPort.Name)
 			}
 			delete(missingPorts, id)
 		} else {
@@ -613,7 +629,7 @@
 			logger.Warnw(ctx, "AddPort Failed", log.Fields{"No": mp.PortNo, "Name": mp.Name, "Reason": err})
 		}
 		if mp.State == uint32(ofp.OfpPortState_OFPPS_LIVE) {
-			att.device.ProcessPortState(cntx, mp.PortNo, mp.State)
+			att.device.ProcessPortState(cntx, mp.PortNo, mp.State, mp.Name)
 		}
 		logger.Debugw(ctx, "Processed Port Add Ind", log.Fields{"Port No": mp.PortNo, "Port Name": mp.Name})
 	}
@@ -642,3 +658,12 @@
 		}
 	}
 }
+
+func (att *AuditTablesTask) DeleteMismatchPorts(cntx context.Context, vgcPort *DevicePort, ofpPortName string) {
+	logger.Infow(ctx, "Deleting port in VGC due to mismatch with voltha", log.Fields{"vgcPortID": vgcPort.ID, "vgcPortName": vgcPort.Name})
+	_ = att.device.DelPort(cntx, vgcPort.ID, vgcPort.Name)
+	if p := att.device.GetPortByName(ofpPortName); p != nil {
+		logger.Infow(ctx, "Delete port by name in VGC due to mismatch with voltha", log.Fields{"portID": p.ID, "portName": p.Name})
+		_ = att.device.DelPort(cntx, p.ID, p.Name)
+	}
+}
diff --git a/internal/pkg/controller/changeevent.go b/internal/pkg/controller/changeevent.go
index fad74a8..c146f23 100644
--- a/internal/pkg/controller/changeevent.go
+++ b/internal/pkg/controller/changeevent.go
@@ -68,7 +68,6 @@
 func (cet *ChangeEventTask) Start(ctx context.Context, taskID uint8) error {
 	cet.taskID = taskID
 	cet.ctx = ctx
-
 	if status, ok := cet.event.Event.(*ofp.ChangeEvent_PortStatus); ok {
 		portNo := status.PortStatus.Desc.PortNo
 		portName := status.PortStatus.Desc.Name
@@ -77,12 +76,10 @@
 		if status.PortStatus.Reason == ofp.OfpPortReason_OFPPR_ADD {
 			_ = cet.device.AddPort(ctx, status.PortStatus.Desc)
 			if state == uint32(ofp.OfpPortState_OFPPS_LIVE) {
-				cet.device.ProcessPortState(ctx, portNo, state)
+				cet.device.ProcessPortState(ctx, portNo, state, portName)
 			}
 		} else if status.PortStatus.Reason == ofp.OfpPortReason_OFPPR_DELETE {
-			if err := cet.device.DelPort(ctx, portNo, portName); err != nil {
-				logger.Warnw(ctx, "DelPort Failed", log.Fields{"Port No": portNo, "Error": err})
-			}
+			cet.device.CheckAndDeletePort(ctx, portNo, portName)
 		} else if status.PortStatus.Reason == ofp.OfpPortReason_OFPPR_MODIFY {
 			cet.device.ProcessPortUpdate(ctx, portName, portNo, state)
 		}
diff --git a/internal/pkg/controller/controller.go b/internal/pkg/controller/controller.go
index 76e4558..7d974f8 100644
--- a/internal/pkg/controller/controller.go
+++ b/internal/pkg/controller/controller.go
@@ -266,9 +266,8 @@
 	v.app.ProcessFlowModResultIndication(cntx, flowStatus)
 }
 
-// IsFlowDelThresholdReached - check if the attempts for flow delete has reached threshold or not
-func (v *VoltController) IsFlowDelThresholdReached(cntx context.Context, cookie string, device string) bool {
-	return v.app.IsFlowDelThresholdReached(cntx, cookie, device)
+func (v *VoltController) CheckAndDeactivateService(ctx context.Context, flow *of.VoltSubFlow, devSerialNum string, devID string) {
+	v.app.CheckAndDeactivateService(ctx, flow, devSerialNum, devID)
 }
 
 // AddVPAgent to add the vpagent
diff --git a/internal/pkg/controller/device.go b/internal/pkg/controller/device.go
index bdac105..abf3108 100644
--- a/internal/pkg/controller/device.go
+++ b/internal/pkg/controller/device.go
@@ -199,8 +199,8 @@
 func (d *Device) GetFlow(cookie uint64) (*of.VoltSubFlow, bool) {
 	d.flowLock.RLock()
 	defer d.flowLock.RUnlock()
-	logger.Debugw(ctx, "Get Flow", log.Fields{"Cookie": cookie})
 	flow, ok := d.flows[cookie]
+	logger.Debugw(ctx, "Get Flow", log.Fields{"Cookie": cookie})
 	return flow, ok
 }
 
@@ -235,8 +235,11 @@
 	d.flowLock.Lock()
 	defer d.flowLock.Unlock()
 	logger.Debugw(ctx, "AddFlow to device", log.Fields{"Cookie": flow.Cookie})
-	if _, ok := d.flows[flow.Cookie]; ok {
-		return errors.New(ErrDuplicateFlow)
+	if dbFlow, ok := d.flows[flow.Cookie]; ok {
+		// In case of ONU reboot after flow delete failure, try to install flow in the device by checking for previous flow state
+		if dbFlow.State != of.FlowDelFailure {
+			return errors.New(ErrDuplicateFlow)
+		}
 	}
 	d.flows[flow.Cookie] = flow
 	d.AddFlowToDb(cntx, flow)
@@ -277,7 +280,7 @@
 		return false
 	} else if flow.OldCookie != 0 && flow.Cookie != flow.OldCookie {
 		if _, ok := d.flows[flow.OldCookie]; ok {
-			logger.Debugw(ctx, "Flow present with old cookie", log.Fields{"OldCookie": flow.OldCookie})
+			logger.Warnw(ctx, "Flow present with old cookie", log.Fields{"OldCookie": flow.OldCookie})
 			return true
 		}
 	}
@@ -487,13 +490,14 @@
 // Inform the application if the port is successfully added
 func (d *Device) AddPort(cntx context.Context, mp *ofp.OfpPort) error {
 	d.portLock.Lock()
-	defer d.portLock.Unlock()
 	id := mp.PortNo
 	name := mp.Name
 	if _, ok := d.PortsByID[id]; ok {
+		d.portLock.Unlock()
 		return errors.New(Duplicate_Port)
 	}
 	if _, ok := d.PortsByName[name]; ok {
+		d.portLock.Unlock()
 		return errors.New(Duplicate_Port)
 	}
 
@@ -501,6 +505,7 @@
 	d.PortsByID[id] = p
 	d.PortsByName[name] = p
 	d.WritePortToDb(cntx, p)
+	d.portLock.Unlock()
 	GetController().PortAddInd(cntx, d.ID, p.ID, p.Name)
 	logger.Infow(ctx, "Added Port", log.Fields{"Device": d.ID, "Port": id})
 	return nil
@@ -533,6 +538,19 @@
 	return nil
 }
 
+// CheckAndDeletePort deletes the port if the port name matches with VGC and one sent from voltha in OFPPR_DELETE
+func (d *Device) CheckAndDeletePort(cntx context.Context, portNo uint32, portName string) {
+	if p := d.GetPortByID(portNo); p != nil {
+		if p.Name != portName {
+			logger.Warnw(ctx, "Dropping Del Port event: Port name mismatch", log.Fields{"vgcPortName": p.Name, "ofpPortName": portName, "ID": p.ID})
+			return
+		}
+		if err := d.DelPort(cntx, portNo, portName); err != nil {
+			logger.Warnw(ctx, "DelPort Failed", log.Fields{"Port No": portNo, "Error": err})
+		}
+	}
+}
+
 // UpdatePortByName is utility to update the port by Name
 func (d *Device) UpdatePortByName(cntx context.Context, name string, port uint32) {
 	d.portLock.Lock()
@@ -796,15 +814,11 @@
 func (d *Device) ProcessPortUpdate(cntx context.Context, portName string, port uint32, state uint32) {
 	if p := d.GetPortByName(portName); p != nil {
 		if p.ID != port {
-			logger.Infow(ctx, "Port ID update indication", log.Fields{"Port": p.Name, "Old PortID": p.ID, "New Port ID": port})
-			if p.State != PortStateDown {
-				logger.Errorw(ctx, "Port ID update failed. Port State UP", log.Fields{"Port": p})
-				return
-			}
-			d.UpdatePortByName(cntx, portName, port)
-			logger.Errorw(ctx, "Port ID Updated", log.Fields{"Port": p})
+			logger.Warnw(ctx, "Port update indication received with mismatching ID", log.Fields{"Port": p.Name, "Old PortID": p.ID, "New Port ID": port})
+			return
+			//Do not process port update received from change event, as we will only handle port updates during polling
 		}
-		d.ProcessPortState(cntx, port, state)
+		d.ProcessPortState(cntx, port, state, portName)
 	}
 }
 
@@ -824,7 +838,7 @@
 
 // ProcessPortState deals with the change in port status and taking action
 // based on the new state and the old state
-func (d *Device) ProcessPortState(cntx context.Context, port uint32, state uint32) {
+func (d *Device) ProcessPortState(cntx context.Context, port uint32, state uint32, portName string) {
 	if d.State != DeviceStateUP && !util.IsNniPort(port) {
 		logger.Warnw(ctx, "Ignore Port State Processing - Device not UP", log.Fields{"Device": d.ID, "Port": port, "DeviceState": d.State})
 		return
@@ -832,6 +846,10 @@
 	if p := d.GetPortByID(port); p != nil {
 		logger.Infow(ctx, "Port State Processing", log.Fields{"Received": state, "Current": p.State})
 
+		if p.Name != portName {
+			logger.Warnw(ctx, "Dropping Port State processing: Port name does not match", log.Fields{"vgcPort": p.Name, "ofpPort": portName, "ID": port})
+			return
+		}
 		// Avoid blind initialization as the current tasks in the queue will be lost
 		// Eg: Service Del followed by Port Down - The flows will be dangling
 		// Eg: NNI Down followed by NNI UP - Mcast data flows will be dangling
@@ -1059,19 +1077,43 @@
 	return false
 }
 
-func (d *Device) triggerFlowNotification(cntx context.Context, cookie uint64, oper of.Command, bwDetails of.BwAvailDetails, err error, sendFlowNotif bool) {
-	flow, _ := d.GetFlow(cookie)
-	d.triggerFlowResultNotification(cntx, cookie, flow, oper, bwDetails, err, sendFlowNotif)
+// IsFlowDelThresholdReached - check if the attempts for flow delete has reached threshold or not
+func (d *Device) IsFlowDelThresholdReached(flowCount uint32, cookie uint64) bool {
+	logger.Debugw(ctx, "Check flow delete threshold", log.Fields{"Cookie": cookie, "FlowCount": flowCount})
+	return flowCount >= GetController().GetMaxFlowRetryAttempt()
 }
 
-func (d *Device) triggerFlowResultNotification(cntx context.Context, cookie uint64, flow *of.VoltSubFlow, oper of.Command, bwDetails of.BwAvailDetails, err error, sendFlowNotif bool) {
+// IsFlowAddThresholdReached - check if the attempts for flow add has reached threshold or not
+func (d *Device) IsFlowAddThresholdReached(flowCount uint32, cookie uint64) bool {
+	logger.Debugw(ctx, "Check flow add threshold", log.Fields{"Cookie": cookie, "FlowCount": flowCount})
+	return flowCount >= GetController().GetMaxFlowRetryAttempt()
+}
+
+func (d *Device) UpdateFlowCount(cntx context.Context, cookie uint64) {
+	if dbFlow, ok := d.flows[cookie]; ok {
+		dbFlow.FlowCount++
+		d.AddFlowToDb(cntx, dbFlow)
+	}
+}
+
+func (d *Device) triggerFlowNotification(cntx context.Context, cookie uint64, oper of.Command, bwDetails of.BwAvailDetails, err error) {
+	flow, _ := d.GetFlow(cookie)
+	d.triggerFlowResultNotification(cntx, cookie, flow, oper, bwDetails, err)
+}
+
+func (d *Device) triggerFlowResultNotification(cntx context.Context, cookie uint64, flow *of.VoltSubFlow, oper of.Command, bwDetails of.BwAvailDetails, err error) {
 	statusCode, statusMsg := infraerror.GetErrorInfo(err)
 	success := isFlowOperSuccess(statusCode, oper)
 
-	updateFlow := func(cookie uint64, state int, reason string) {
-		if dbFlow, ok := d.GetFlow(cookie); ok {
+	updateFlowStatus := func(cookie uint64, state int, reason string) {
+		d.flowLock.Lock()
+		defer d.flowLock.Unlock()
+		if dbFlow, ok := d.flows[cookie]; ok {
 			dbFlow.State = uint8(state)
 			dbFlow.ErrorReason = reason
+			if state == of.FlowAddSuccess {
+				dbFlow.FlowCount = 0
+			}
 			d.AddFlowToDb(cntx, dbFlow)
 		}
 	}
@@ -1086,15 +1128,24 @@
 			state = of.FlowAddFailure
 			reason = statusMsg
 		}
-		updateFlow(cookie, state, reason)
-		logger.Debugw(ctx, "Updated Flow to DB", log.Fields{"Cookie": cookie, "State": state})
+		updateFlowStatus(cookie, state, reason)
+		logger.Debugw(ctx, "Add flow updated to DB", log.Fields{"Cookie": cookie, "State": state})
 	} else {
 		if success && flow != nil {
+			logger.Debugw(ctx, "Deleted flow from device and DB", log.Fields{"Cookie": cookie})
 			if err := d.DelFlow(cntx, flow); err != nil {
 				logger.Warnw(ctx, "Delete Flow Error", log.Fields{"Cookie": flow.Cookie, "Reason": err.Error()})
 			}
 		} else if !success {
-			updateFlow(cookie, of.FlowDelFailure, statusMsg)
+			if d.IsFlowDelThresholdReached(flow.FlowCount, flow.Cookie) {
+				logger.Debugw(ctx, "Deleted flow from device and DB after delete threshold reached", log.Fields{"Cookie": cookie})
+				if err := d.DelFlow(cntx, flow); err != nil {
+					logger.Warnw(ctx, "Delete Flow Error", log.Fields{"Cookie": flow.Cookie, "Reason": err.Error()})
+				}
+			} else {
+				updateFlowStatus(cookie, of.FlowDelFailure, statusMsg)
+				logger.Debugw(ctx, "Delete flow updated to DB", log.Fields{"Cookie": cookie})
+			}
 		}
 	}
 
@@ -1108,8 +1159,6 @@
 		AdditionalData: bwDetails,
 	}
 
-	if sendFlowNotif {
-		logger.Debugw(ctx, "Sending Flow Notification", log.Fields{"Cookie": cookie, "Error Code": statusCode, "FlowOp": oper})
-		GetController().ProcessFlowModResultIndication(cntx, flowResult)
-	}
+	logger.Debugw(ctx, "Sending Flow Notification", log.Fields{"Cookie": cookie, "Error Code": statusCode, "FlowOp": oper})
+	GetController().ProcessFlowModResultIndication(cntx, flowResult)
 }
diff --git a/internal/pkg/controller/device_test.go b/internal/pkg/controller/device_test.go
index 7089c64..8f35aef 100644
--- a/internal/pkg/controller/device_test.go
+++ b/internal/pkg/controller/device_test.go
@@ -170,7 +170,7 @@
 			db = dbintf
 			dbintf.EXPECT().PutFlow(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(1)
 			appMock.EXPECT().ProcessFlowModResultIndication(gomock.Any(), gomock.Any()).Times(1)
-			d.triggerFlowResultNotification(tt.args.cntx, tt.args.cookie, tt.args.flow, tt.args.oper, tt.args.bwDetails, tt.args.err, false)
+			d.triggerFlowResultNotification(tt.args.cntx, tt.args.cookie, tt.args.flow, tt.args.oper, tt.args.bwDetails, tt.args.err)
 		})
 	}
 }
diff --git a/internal/pkg/controller/modmeter.go b/internal/pkg/controller/modmeter.go
index 6b677a9..0d7b0e8 100644
--- a/internal/pkg/controller/modmeter.go
+++ b/internal/pkg/controller/modmeter.go
@@ -93,7 +93,7 @@
 			// Meter already exists so we dont have to do anything here
 			return nil
 		}
-		logger.Infow(ctx, "Updated meter state to pending", log.Fields{"Meter": mmt.meter.ID})
+		logger.Debugw(ctx, "Updated meter state to pending", log.Fields{"Meter": mmt.meter.ID})
 	} else {
 		if !mmt.device.DelMeter(ctx, mmt.meter) {
 			// Meter doesn't exist so we dont have to do anything here
@@ -120,7 +120,7 @@
 				// Meter does not exist, update failed
 				logger.Error(ctx, "Update meter to DB failed")
 			}
-			logger.Infow(ctx, "Updated meter state to success", log.Fields{"Meter": mmt.meter.ID})
+			logger.Debugw(ctx, "Updated meter state to success", log.Fields{"Meter": mmt.meter.ID})
 		}
 		//triggerMeterNotification(err)
 		return err