[VOL-5606]:Southbound port indication update at db

Change-Id: I3ca152fcd84b0488b93f18ee09c58b2394570e7e
Signed-off-by: balaji.nagarajan <balaji.nagarajan@radisys.com>
diff --git a/VERSION b/VERSION
index 35c6ac5..03d7b8f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.7.14
+3.7.15
diff --git a/rw_core/core/device/agent_port.go b/rw_core/core/device/agent_port.go
index 7015240..5984f0a 100644
--- a/rw_core/core/device/agent_port.go
+++ b/rw_core/core/device/agent_port.go
@@ -22,6 +22,7 @@
 
 	"github.com/opencord/voltha-protos/v5/go/adapter_service"
 	"github.com/opencord/voltha-protos/v5/go/common"
+	ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
 
 	"github.com/opencord/voltha-go/rw_core/core/device/port"
 	coreutils "github.com/opencord/voltha-go/rw_core/utils"
@@ -113,11 +114,30 @@
 		return nil
 	}
 
-	newPort := proto.Clone(port).(*voltha.Port) // clone top-level port struct
-	newPort.OperStatus = operStatus
+	// clone top-level port struct
+	newPort := cloneDevicePortSetState(port, operStatus)
 	return portHandle.Update(ctx, newPort)
 }
 
+func cloneDevicePortSetState(oldPort *voltha.Port, state voltha.OperStatus_Types) *voltha.Port {
+	newPort := proto.Clone(oldPort).(*voltha.Port) // only clone the struct(s) that will be changed
+	if oldPort.OfpPort == nil {
+		newPort.OperStatus = state
+		return newPort
+	}
+	newOfpPort := proto.Clone(oldPort.OfpPort).(*ofp.OfpPort)
+	newPort.OfpPort = newOfpPort
+	newPort.OperStatus = state
+	if state == voltha.OperStatus_ACTIVE {
+		newOfpPort.Config &= ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
+		newOfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
+	} else {
+		newOfpPort.Config |= uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
+		newOfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
+	}
+	return newPort
+}
+
 func (agent *Agent) deleteAllPorts(ctx context.Context) error {
 	logger.Debugw(ctx, "delete-all-ports", log.Fields{"device-id": agent.deviceID})
 
@@ -181,6 +201,9 @@
 	newPort.Label = port.Label
 	newPort.OperStatus = port.OperStatus
 
+	if port.OfpPort != nil {
+		newPort.OfpPort = port.OfpPort
+	}
 	err = portHandle.Update(ctx, newPort)
 	if err != nil {
 		desc = err.Error()
diff --git a/rw_core/core/device/logical_agent_port.go b/rw_core/core/device/logical_agent_port.go
index 16d889f..c44c879 100644
--- a/rw_core/core/device/logical_agent_port.go
+++ b/rw_core/core/device/logical_agent_port.go
@@ -166,6 +166,9 @@
 
 func clonePortSetState(oldPort *voltha.LogicalPort, state voltha.OperStatus_Types) *voltha.LogicalPort {
 	newPort := proto.Clone(oldPort).(*voltha.LogicalPort) // only clone the struct(s) that will be changed
+	if oldPort.OfpPort == nil {
+		return newPort
+	}
 	newOfpPort := proto.Clone(oldPort.OfpPort).(*ofp.OfpPort)
 	newPort.OfpPort = newOfpPort
 
@@ -369,6 +372,8 @@
 		OfpPortStats: &ofp.OfpPortStats{},
 	}
 
+	// clone top-level port struct
+	uniPort = clonePortSetState(uniPort, port.OperStatus)
 	portHandle, created, err := agent.portLoader.LockOrCreate(ctx, uniPort)
 	if err != nil {
 		return err
@@ -390,10 +395,10 @@
 		if err := agent.updateRoutes(subCtx, deviceID, devicePorts, uniPort, agent.listLogicalDevicePorts(ctx)); err != nil {
 			// This is not an error as we may not have enough logical ports to set up routes or some PON ports have not been
 			// created yet.
-			logger.Infow(ctx, "routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "logical-port": uniPort.OfpPort.PortNo, "error": err})
+			logger.Infow(subCtx, "routes-not-ready", log.Fields{"logical-device-id": agent.logicalDeviceID, "logical-port": uniPort.OfpPort.PortNo, "error": err})
 		}
 		// send event, and allow any queued events to be sent as well
-		queuePosition.send(ctx, agent, agent.logicalDeviceID, ofp.OfpPortReason_OFPPR_ADD, uniPort.OfpPort)
+		queuePosition.send(subCtx, agent, agent.logicalDeviceID, ofp.OfpPortReason_OFPPR_ADD, uniPort.OfpPort)
 	}()
 	return nil
 }