[VOL-5536] - VGC recent fixes

Change-Id: Id6f0e647b37baac827230afbb45d132df8a62b68
Signed-off-by: Sridhar Ravindra <sridhar.ravindra@radisys.com>
diff --git a/internal/pkg/controller/device.go b/internal/pkg/controller/device.go
index 0748fa7..93fae14 100644
--- a/internal/pkg/controller/device.go
+++ b/internal/pkg/controller/device.go
@@ -242,7 +242,6 @@
 		}
 	}
 	d.flows[flow.Cookie] = flow
-	d.AddFlowToDb(cntx, flow)
 	return nil
 }
 
@@ -504,7 +503,6 @@
 	p := NewDevicePort(mp)
 	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})
@@ -563,7 +561,6 @@
 	delete(d.PortsByID, p.ID)
 	p.ID = port
 	d.PortsByID[port] = p
-	d.WritePortToDb(cntx, p)
 	GetController().PortUpdateInd(d.ID, p.Name, p.ID)
 	logger.Infow(ctx, "Updated Port", log.Fields{"Device": d.ID, "Port": p.ID, "PortName": name})
 }
@@ -698,6 +695,12 @@
 
 	logger.Debugw(ctx, "Device State change Ind: UP, trigger Audit Tasks", log.Fields{"Device": d.ID})
 	t := NewAuditDevice(d, AuditEventDeviceDisc)
+	// During VGC restart or when a device is added. skip pushing flows to voltha during audit device task
+	// When device is added, if required the flows will get pushed during the next audit table task called soon after this audit device task
+	if discType == intf.DeviceDisc {
+		t.skipFlowOnRestart = true
+	}
+
 	d.Tasks.AddTask(t)
 
 	t1 := NewAuditTablesTask(d)
@@ -788,7 +791,6 @@
 			logger.Debugw(ctx, "Resetting Port State to DOWN", log.Fields{"Device": d.ID, "Port": port})
 			GetController().PortDownInd(cntx, d.ID, port.Name)
 			port.State = PortStateDown
-			d.WritePortToDb(cntx, port)
 		}
 	}
 }
@@ -818,7 +820,7 @@
 			return
 			//Do not process port update received from change event, as we will only handle port updates during polling
 		}
-		d.ProcessPortState(cntx, port, state, portName)
+		d.ProcessPortState(cntx, port, state, portName, false)
 	}
 }
 
@@ -838,7 +840,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, portName string) {
+func (d *Device) ProcessPortState(cntx context.Context, port uint32, state uint32, portName string, skipFlowPushToVoltha bool) {
 	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
@@ -857,7 +859,7 @@
 		if state == uint32(ofp.OfpPortState_OFPPS_LIVE) && p.State == PortStateDown {
 			// Transition from DOWN to UP
 			logger.Debugw(ctx, "Port State Change to UP", log.Fields{"Device": d.ID, "Port": port})
-			GetController().PortUpInd(cntx, d.ID, p.Name)
+			GetController().PortUpInd(cntx, d.ID, p.Name, skipFlowPushToVoltha)
 			p.State = PortStateUp
 			d.WritePortToDb(cntx, p)
 		} else if (state != uint32(ofp.OfpPortState_OFPPS_LIVE)) && (p.State != PortStateDown) {
@@ -865,7 +867,6 @@
 			logger.Debugw(ctx, "Port State Change to Down", log.Fields{"Device": d.ID, "Port": port})
 			GetController().PortDownInd(cntx, d.ID, p.Name)
 			p.State = PortStateDown
-			d.WritePortToDb(cntx, p)
 		} else {
 			logger.Warnw(ctx, "Dropping Port Ind: No Change in Port State", log.Fields{"PortName": p.Name, "ID": port, "Device": d.ID, "PortState": p.State, "IncomingState": state})
 		}
@@ -884,7 +885,7 @@
 		switch p.State {
 		case PortStateUp:
 			logger.Debugw(ctx, "Port State: UP", log.Fields{"Device": d.ID, "Port": port})
-			GetController().PortUpInd(cntx, d.ID, p.Name)
+			GetController().PortUpInd(cntx, d.ID, p.Name, false)
 		case PortStateDown:
 			logger.Debugw(ctx, "Port State: Down", log.Fields{"Device": d.ID, "Port": port})
 			GetController().PortDownInd(cntx, d.ID, p.Name)
@@ -1084,6 +1085,44 @@
 	return flowCount >= uint32(GetController().GetMaxFlowRetryAttempt())
 }
 
+// IsUSTable0Flow - check if the flow is for US Table 0
+func (d *Device) IsUSTable0Flow(cntx context.Context, flow *of.VoltSubFlow) bool {
+	if flow.TableID == 0 && !util.IsNniPort(flow.Match.InPort) {
+		return true
+	}
+	return false
+}
+
+// IsDSTable0Flow - check if the flow is for DS Table 0
+func (d *Device) IsDSTable0Flow(cntx context.Context, flow *of.VoltSubFlow) bool {
+	if flow.TableID == 0 && util.IsNniPort(flow.Match.InPort) {
+		return true
+	}
+	return false
+}
+
+// GetDeviceFlow - get the DS or US Table 1 flow based on isDsFlow flag
+func (d *Device) GetDeviceFlow(cntx context.Context, flow *of.VoltSubFlow, deviceSerialNum string, devID string, isDsFlow bool) *of.VoltSubFlow {
+	cookies := GetController().GetAllFlowsForSvc(cntx, flow, devID, deviceSerialNum)
+	for _, cookie := range cookies {
+		if dbFlow, ok := d.flows[cookie]; ok {
+			logger.Debugw(ctx, "Found flow in device", log.Fields{"Cookie": cookie, "Flow": dbFlow})
+			if isDsFlow {
+				// return DS Table1 flow
+				if dbFlow.TableID == 1 && util.IsNniPort(dbFlow.Match.InPort) {
+					return dbFlow
+				}
+			} else {
+				// return US Table1 flow
+				if dbFlow.TableID == 1 && !util.IsNniPort(dbFlow.Match.InPort) {
+					return dbFlow
+				}
+			}
+		}
+	}
+	return nil
+}
+
 // 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})
@@ -1093,7 +1132,6 @@
 func (d *Device) UpdateFlowCount(cntx context.Context, cookie uint64) {
 	if dbFlow, ok := d.flows[cookie]; ok {
 		dbFlow.FlowCount++
-		d.AddFlowToDb(cntx, dbFlow)
 	}
 }
 
@@ -1116,10 +1154,6 @@
 		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)
 		}
 	}