[VOL-1949] fix individual port state change

Change-Id: I66b94e83b6513b657af15c395a907b200735c764
diff --git a/rw_core/core/device_manager.go b/rw_core/core/device_manager.go
index beff7ae..0ae1491 100755
--- a/rw_core/core/device_manager.go
+++ b/rw_core/core/device_manager.go
@@ -830,7 +830,12 @@
 func (dMgr *DeviceManager) updatePortState(deviceId string, portType voltha.Port_PortType, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
 	log.Debugw("updatePortState", log.Fields{"deviceid": deviceId, "portType": portType, "portNo": portNo, "operStatus": operStatus})
 	if agent := dMgr.getDeviceAgent(deviceId); agent != nil {
-		return agent.updatePortState(portType, portNo, operStatus)
+		if err := agent.updatePortState(portType, portNo, operStatus); err != nil {
+			log.Errorw("updating-port-state-failed", log.Fields{"deviceid": deviceId, "portNo": portNo, "error": err})
+			return err
+		}
+		// Notify the logical device manager to change the port state
+		go dMgr.logicalDeviceMgr.updatePortState(deviceId, portNo, operStatus)
 	}
 	return status.Errorf(codes.NotFound, "%s", deviceId)
 }
diff --git a/rw_core/core/logical_device_agent.go b/rw_core/core/logical_device_agent.go
index c896b44..b5fe6d5 100644
--- a/rw_core/core/logical_device_agent.go
+++ b/rw_core/core/logical_device_agent.go
@@ -441,6 +441,38 @@
 	return err
 }
 
+// updatePortState updates the port state of the device
+func (agent *LogicalDeviceAgent) updatePortState(deviceId string, portNo uint32, operStatus voltha.OperStatus_OperStatus) error {
+	log.Infow("updatePortState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "portNo": portNo, "state": operStatus})
+	agent.lockLogicalDevice.Lock()
+	defer agent.lockLogicalDevice.Unlock()
+	// Get the latest logical device info
+	if ld, err := agent.getLogicalDeviceWithoutLock(); err != nil {
+		log.Warnw("logical-device-unknown", log.Fields{"logicalDeviceId": agent.logicalDeviceId, "error": err})
+		return err
+	} else {
+		for idx, lPort := range ld.Ports {
+			if lPort.DeviceId == deviceId && lPort.DevicePortNo == portNo {
+				cloned := (proto.Clone(ld)).(*voltha.LogicalDevice)
+				if operStatus == voltha.OperStatus_ACTIVE {
+					cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config & ^uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
+					cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LIVE)
+				} else {
+					cloned.Ports[idx].OfpPort.Config = cloned.Ports[idx].OfpPort.Config | uint32(ofp.OfpPortConfig_OFPPC_PORT_DOWN)
+					cloned.Ports[idx].OfpPort.State = uint32(ofp.OfpPortState_OFPPS_LINK_DOWN)
+				}
+				// Update the logical device
+				if err := agent.updateLogicalDeviceWithoutLock(cloned); err != nil {
+					log.Errorw("error-updating-logical-device", log.Fields{"error": err})
+					return err
+				}
+				return nil
+			}
+		}
+		return status.Errorf(codes.NotFound, "port-%d-not-exist", portNo)
+	}
+}
+
 // updatePortsState updates the ports state related to the device
 func (agent *LogicalDeviceAgent) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
 	log.Infow("updatePortsState-start", log.Fields{"logicalDeviceId": agent.logicalDeviceId})
diff --git a/rw_core/core/logical_device_manager.go b/rw_core/core/logical_device_manager.go
index b3ccd11..17c441c 100644
--- a/rw_core/core/logical_device_manager.go
+++ b/rw_core/core/logical_device_manager.go
@@ -485,6 +485,23 @@
 	}
 	return nil
 }
+func (ldMgr *LogicalDeviceManager) updatePortState(deviceId string, portNo uint32, state voltha.OperStatus_OperStatus) error {
+	log.Debugw("updatePortState", log.Fields{"deviceId": deviceId, "state": state, "portNo": portNo})
+
+	var ldId *string
+	var err error
+	//Get the logical device Id for this device
+	if ldId, err = ldMgr.getLogicalDeviceIdFromDeviceId(deviceId); err != nil {
+		log.Warnw("no-logical-device-found", log.Fields{"deviceId": deviceId, "error": err})
+		return err
+	}
+	if agent := ldMgr.getLogicalDeviceAgent(*ldId); agent != nil {
+		if err := agent.updatePortState(deviceId, portNo, state); err != nil {
+			return err
+		}
+	}
+	return nil
+}
 
 func (ldMgr *LogicalDeviceManager) updatePortsState(device *voltha.Device, state voltha.AdminState_AdminState) error {
 	log.Debugw("updatePortsState", log.Fields{"deviceId": device.Id, "state": state, "current-data": device})