[VOL-3342] Avoid reacting to port events on a disconnected device

Change-Id: I3831a2d02ebe4acf9ae9b38793116b135690b7e1
diff --git a/app/src/main/java/org/opencord/olt/impl/Olt.java b/app/src/main/java/org/opencord/olt/impl/Olt.java
index 1f3634b..42c53b7 100644
--- a/app/src/main/java/org/opencord/olt/impl/Olt.java
+++ b/app/src/main/java/org/opencord/olt/impl/Olt.java
@@ -1046,15 +1046,12 @@
                         && !deviceService.isAvailable(devId) && deviceService.getPorts(devId).isEmpty()) {
                     log.info("Cleaning local state for non master instance upon " +
                                      "device disconnection {}", devId);
-                    programmedDevices.remove(devId);
                     // Since no mastership of the device is present upon disconnection
                     // the method in the FlowRuleManager only empties the local copy
                     // of the DeviceFlowTable thus this method needs to get called
                     // on every instance, see how it's done in the InternalDeviceListener
                     // in FlowRuleManager: no mastership check for purgeOnDisconnection
-                    flowRuleService.purgeFlowRules(devId);
-                    oltFlowService.clearDeviceState(devId);
-                    oltMeterService.clearDeviceState(devId);
+                    handleDeviceDisconnection(dev, false, false);
                     return;
                 } else if (!isLocalLeader) {
                     log.debug("Not handling event because instance is not leader for {}", devId);
@@ -1078,6 +1075,10 @@
                     //TODO: Port handling and bookkeeping should be improved once
                     // olt firmware handles correct behaviour.
                     case PORT_ADDED:
+                        if (!deviceService.isAvailable(devId)) {
+                            log.warn("Received {} for disconnected device {}, ignoring", event, devId);
+                            return;
+                        }
                         if (isUniPort(dev, port)) {
                             post(new AccessDeviceEvent(AccessDeviceEvent.Type.UNI_ADDED, devId, port));
 
@@ -1085,7 +1086,8 @@
                                 log.info("eapol will be sent for port added {}", port);
                                 oltFlowService.processEapolFilteringObjectives(devId, port.number(), defaultBpId,
                                                                                null,
-                                                                               VlanId.vlanId(EAPOL_DEFAULT_VLAN), true);
+                                                                               VlanId.vlanId(EAPOL_DEFAULT_VLAN),
+                                                                               true);
                             }
                         } else {
                             SubscriberAndDeviceInformation deviceInfo = getOltInfo(dev);
@@ -1106,6 +1108,10 @@
                         }
                         break;
                     case PORT_UPDATED:
+                        if (!deviceService.isAvailable(devId)) {
+                            log.warn("Received {} for disconnected device {}, ignoring", event, devId);
+                            return;
+                        }
                         if (!isUniPort(dev, port)) {
                             SubscriberAndDeviceInformation deviceInfo = getOltInfo(dev);
                             if (deviceInfo != null && port.isEnabled()) {
@@ -1147,7 +1153,7 @@
                         handleDeviceConnection(dev, true);
                         break;
                     case DEVICE_REMOVED:
-                        handleDeviceDisconnection(dev, true);
+                        handleDeviceDisconnection(dev, true, true);
                         break;
                     case DEVICE_AVAILABILITY_CHANGED:
                         if (deviceService.isAvailable(devId)) {
@@ -1157,7 +1163,7 @@
                             if (deviceService.getPorts(devId).isEmpty()) {
                                 log.info("Handling controlled device disconnection .. "
                                                  + "flushing all state for dev:{}", devId);
-                                handleDeviceDisconnection(dev, false);
+                                handleDeviceDisconnection(dev, true, false);
                             } else {
                                 log.info("Disconnected device has available ports .. "
                                                  + "assuming temporary disconnection, "
@@ -1166,6 +1172,7 @@
                         }
                         break;
                     default:
+                        log.debug("Not handling event {}", event);
                         return;
                 }
             });
@@ -1178,7 +1185,7 @@
                     .forEach(p -> post(new AccessDeviceEvent(eventType, device.id(), p)));
         }
 
-        private void handleDeviceDisconnection(Device device, boolean sendUniEvent) {
+        private void handleDeviceDisconnection(Device device, boolean sendDisconnectedEvent, boolean sendUniEvent) {
             programmedDevices.remove(device.id());
             removeAllSubscribers(device.id());
             //Handle case where OLT disconnects during subscriber provisioning
@@ -1188,9 +1195,11 @@
             //Complete meter and flow purge
             flowRuleService.purgeFlowRules(device.id());
             oltMeterService.clearMeters(device.id());
-            post(new AccessDeviceEvent(
-                    AccessDeviceEvent.Type.DEVICE_DISCONNECTED, device.id(),
-                    null, null, null));
+            if (sendDisconnectedEvent) {
+                post(new AccessDeviceEvent(
+                        AccessDeviceEvent.Type.DEVICE_DISCONNECTED, device.id(),
+                        null, null, null));
+            }
             if (sendUniEvent) {
                 sendUniEvent(device, AccessDeviceEvent.Type.UNI_REMOVED);
             }