[ONOS-3726] Update L3's bug about deleting router interface and unbind
floating ip.

Change-Id: I8629d12e410b9312f4e7f2aadf84f08d19af18c1
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
index 023bd05..aaefb07 100644
--- a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
@@ -749,9 +749,9 @@
             } else
                 if (VtnRscEvent.Type.ROUTER_INTERFACE_DELETE == event.type()) {
                 onRouterInterfaceVanished(l3Feedback);
-            } else if (VtnRscEvent.Type.FLOATINGIP_PUT == event.type()) {
+            } else if (VtnRscEvent.Type.FLOATINGIP_BIND == event.type()) {
                 onFloatingIpDetected(l3Feedback);
-            } else if (VtnRscEvent.Type.FLOATINGIP_DELETE == event.type()) {
+            } else if (VtnRscEvent.Type.FLOATINGIP_UNBIND == event.type()) {
                 onFloatingIpVanished(l3Feedback);
             }
         }
@@ -762,6 +762,8 @@
     public void onRouterInterfaceDetected(VtnRscEventFeedback l3Feedback) {
         Objective.Operation operation = Objective.Operation.ADD;
         RouterInterface routerInf = l3Feedback.routerInterface();
+        VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
+        vPortStore.put(gwPort.portId(), gwPort);
         Iterable<RouterInterface> interfaces = routerInterfaceService
                 .getRouterInterfaces();
         Set<RouterInterface> interfacesSet = Sets.newHashSet(interfaces)
@@ -794,16 +796,21 @@
                 });
             }
         }
+        VirtualPort gwPort = virtualPortService.getPort(routerInf.portId());
+        if (gwPort == null) {
+            gwPort = VtnData.getPort(vPortStore, routerInf.portId());
+        }
+        vPortStore.remove(gwPort.portId());
     }
 
     @Override
     public void onFloatingIpDetected(VtnRscEventFeedback l3Feedback) {
-        programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_PUT);
+        programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_BIND);
     }
 
     @Override
     public void onFloatingIpVanished(VtnRscEventFeedback l3Feedback) {
-        programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_DELETE);
+        programFloatingIpEvent(l3Feedback, VtnRscEvent.Type.FLOATINGIP_UNBIND);
     }
 
     private void programInterfacesSet(Set<RouterInterface> interfacesSet,
@@ -925,11 +932,11 @@
                 SegmentationId l3vni = vtnRscService
                         .getL3vni(vmPort.tenantId());
                 // Floating ip BIND
-                if (type == VtnRscEvent.Type.FLOATINGIP_PUT) {
+                if (type == VtnRscEvent.Type.FLOATINGIP_BIND) {
                     applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort,
                                            floaingIp, l3vni, exPort,
                                            Objective.Operation.ADD);
-                } else if (type == VtnRscEvent.Type.FLOATINGIP_DELETE) {
+                } else if (type == VtnRscEvent.Type.FLOATINGIP_UNBIND) {
                     // Floating ip UNBIND
                     applyNorthSouthL3Flows(deviceId, host, vmPort, fipPort,
                                            floaingIp, l3vni, exPort,
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java
index ce3faae..ede90fb 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java
@@ -37,6 +37,14 @@
          */
         FLOATINGIP_DELETE,
         /**
+         * Signifies that Floating IP has been bound.
+         */
+        FLOATINGIP_BIND,
+        /**
+         * Signifies that Floating IP has been unbound.
+         */
+        FLOATINGIP_UNBIND,
+        /**
          * Signifies that router has create.
          */
         ROUTER_PUT,
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java
index f76007f..7ac6805 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java
@@ -34,7 +34,15 @@
         /**
          * Signifies that Floating IP has been deleted.
          */
-        FLOATINGIP_DELETE
+        FLOATINGIP_DELETE,
+        /**
+         * Signifies that Floating IP has been bound.
+         */
+        FLOATINGIP_BIND,
+        /**
+         * Signifies that Floating IP has been unbound.
+         */
+        FLOATINGIP_UNBIND
     }
 
     /**
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java
index 91e149a..3902593 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java
@@ -63,7 +63,8 @@
 public class FloatingIpManager implements FloatingIpService {
     private static final String FLOATINGIP_ID_NOT_NULL = "Floatingip ID cannot be null";
     private static final String FLOATINGIP_NOT_NULL = "Floatingip cannot be null";
-    private static final String FLOATINGIP = "vtn-floatingip-store";
+    private static final String FLOATINGIPSTORE = "vtn-floatingip-store";
+    private static final String FLOATINGIPBINDSTORE = "vtn-floatingip-bind-store";
     private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
     private static final String LISTENER_NOT_NULL = "Listener cannot be null";
     private static final String EVENT_NOT_NULL = "event cannot be null";
@@ -74,6 +75,7 @@
     private EventuallyConsistentMapListener<FloatingIpId, FloatingIp> floatingIpListener =
             new InnerFloatingIpStoreListener();
     protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpStore;
+    protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpBindStore;
     protected ApplicationId appId;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -103,7 +105,12 @@
                           VirtualPortId.class, DefaultFloatingIp.class);
         floatingIpStore = storageService
                 .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
-                .withName(FLOATINGIP).withSerializer(serializer)
+                .withName(FLOATINGIPSTORE).withSerializer(serializer)
+                .withTimestampProvider((k, v) -> new WallClockTimestamp())
+                .build();
+        floatingIpBindStore = storageService
+                .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
+                .withName(FLOATINGIPBINDSTORE).withSerializer(serializer)
                 .withTimestampProvider((k, v) -> new WallClockTimestamp())
                 .build();
         floatingIpStore.addListener(floatingIpListener);
@@ -114,6 +121,7 @@
     public void deactivate() {
         floatingIpStore.removeListener(floatingIpListener);
         floatingIpStore.destroy();
+        floatingIpBindStore.destroy();
         listeners.clear();
         log.info("Stopped");
     }
@@ -192,6 +200,8 @@
         boolean result = true;
         for (FloatingIp floatingIp : floatingIps) {
             verifyFloatingIpData(floatingIp);
+            FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
+            floatingIpBindStore.put(floatingIp.id(), oldFloatingIp);
             floatingIpStore.put(floatingIp.id(), floatingIp);
             if (!floatingIpStore.containsKey(floatingIp.id())) {
                 log.debug("The floating Ip is updated failed whose identifier is {}",
@@ -220,6 +230,7 @@
                 return false;
             }
             floatingIpStore.remove(floatingIpId, floatingIp);
+            floatingIpBindStore.remove(floatingIpId);
             if (floatingIpStore.containsKey(floatingIpId)) {
                 log.debug("The floating Ip is deleted failed whose identifier is {}",
                           floatingIpId.toString());
@@ -303,6 +314,18 @@
                 notifyListeners(new FloatingIpEvent(
                                                     FloatingIpEvent.Type.FLOATINGIP_PUT,
                                                     floatingIp));
+                if (floatingIp.portId() != null) {
+                    notifyListeners(new FloatingIpEvent(
+                                                        FloatingIpEvent.Type.FLOATINGIP_BIND,
+                                                        floatingIp));
+                } else {
+                    FloatingIp oldFloatingIp = floatingIpBindStore.get(floatingIp.id());
+                    if (oldFloatingIp != null) {
+                        notifyListeners(new FloatingIpEvent(
+                                                            FloatingIpEvent.Type.FLOATINGIP_UNBIND,
+                                                            oldFloatingIp));
+                    }
+                }
             }
             if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
                 notifyListeners(new FloatingIpEvent(
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java
index e2d1904..417881c 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java
@@ -233,6 +233,18 @@
                                                 new VtnRscEventFeedback(
                                                                         floatingIp)));
             }
+            if (FloatingIpEvent.Type.FLOATINGIP_BIND == event.type()) {
+                notifyListeners(new VtnRscEvent(
+                                                VtnRscEvent.Type.FLOATINGIP_BIND,
+                                                new VtnRscEventFeedback(
+                                                                        floatingIp)));
+            }
+            if (FloatingIpEvent.Type.FLOATINGIP_UNBIND == event.type()) {
+                notifyListeners(new VtnRscEvent(
+                                                VtnRscEvent.Type.FLOATINGIP_UNBIND,
+                                                new VtnRscEventFeedback(
+                                                                        floatingIp)));
+            }
         }
     }