Add/Remove interface, Addressed patch set 2

Change-Id: Ibee195f20cb8ebea7da89ce7324d1617e78c36b2

Add/Remove interface, Addressed patch set 1

Change-Id: If98c4cbf74d1ca5eeb2e51154308c8eb2af8c195

Add/Remove interface, Addressed patch set 1

Change-Id: If98c4cbf74d1ca5eeb2e51154308c8eb2af8c195
diff --git a/apps/routing/src/main/java/org/onosproject/routing/impl/ControlPlaneRedirectManager.java b/apps/routing/src/main/java/org/onosproject/routing/impl/ControlPlaneRedirectManager.java
index b85f79f..a82d4ff 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/impl/ControlPlaneRedirectManager.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/impl/ControlPlaneRedirectManager.java
@@ -16,8 +16,16 @@
 
 package org.onosproject.routing.impl;
 
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Maps;
+import static com.google.common.base.Preconditions.checkState;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -30,6 +38,8 @@
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceEvent;
+import org.onosproject.incubator.net.intf.InterfaceListener;
 import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.ConnectPoint;
@@ -59,15 +69,8 @@
 import org.onosproject.routing.config.RouterConfig;
 import org.slf4j.Logger;
 
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-import static org.slf4j.LoggerFactory.getLogger;
-import static com.google.common.base.Preconditions.checkState;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Maps;
 
 /**
  * Manages connectivity between peers redirecting control traffic to a routing
@@ -115,6 +118,7 @@
     private final InternalNetworkConfigListener networkConfigListener =
             new InternalNetworkConfigListener();
     private final InternalHostListener hostListener = new InternalHostListener();
+    private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
 
     @Activate
     public void activate() {
@@ -123,6 +127,7 @@
         deviceService.addListener(deviceListener);
         networkConfigService.addListener(networkConfigListener);
         hostService.addListener(hostListener);
+        interfaceService.addListener(interfaceListener);
 
         updateConfig();
     }
@@ -132,6 +137,7 @@
         deviceService.removeListener(deviceListener);
         networkConfigService.removeListener(networkConfigListener);
         hostService.removeListener(hostListener);
+        interfaceService.removeListener(interfaceListener);
     }
 
     private void updateConfig() {
@@ -167,33 +173,44 @@
         }
     }
 
-    private void provisionInterface(Interface intf) {
-        addBasicInterfaceForwarding(intf);
-        updateOspfForwarding(intf);
+    private void removeInterface(Interface intf) {
+        modifyBasicInterfaceForwarding(intf, false);
+        updateOspfForwarding(intf, false);
     }
 
-    private void addBasicInterfaceForwarding(Interface intf) {
+    private void provisionInterface(Interface intf) {
+        modifyBasicInterfaceForwarding(intf, true);
+        updateOspfForwarding(intf, true);
+    }
+    /**
+     * Install or removes the basic forwarding flows for each interface
+     * based on the flag used.
+     *
+     * @param intf the Interface on which event is received
+     * @param install true to create an add objective, false to create a remove
+     *            objective
+     **/
+    private void modifyBasicInterfaceForwarding(Interface intf, boolean install) {
         log.debug("Adding interface objectives for {}", intf);
 
         DeviceId deviceId = controlPlaneConnectPoint.deviceId();
         PortNumber controlPlanePort = controlPlaneConnectPoint.port();
-
         for (InterfaceIpAddress ip : intf.ipAddresses()) {
             // create nextObjectives for forwarding to this interface and the
             // controlPlaneConnectPoint
             int cpNextId, intfNextId;
             if (intf.vlan() == VlanId.NONE) {
-                cpNextId = createNextObjective(deviceId, controlPlanePort,
+                cpNextId = modifyNextObjective(deviceId, controlPlanePort,
                                VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN),
-                               true);
-                intfNextId = createNextObjective(deviceId, intf.connectPoint().port(),
+                               true, install);
+                intfNextId = modifyNextObjective(deviceId, intf.connectPoint().port(),
                                VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN),
-                               true);
+                               true, install);
             } else {
-                cpNextId = createNextObjective(deviceId, controlPlanePort,
-                                               intf.vlan(), false);
-                intfNextId = createNextObjective(deviceId, intf.connectPoint().port(),
-                                                 intf.vlan(), false);
+                cpNextId = modifyNextObjective(deviceId, controlPlanePort,
+                                               intf.vlan(), false, install);
+                intfNextId = modifyNextObjective(deviceId, intf.connectPoint().port(),
+                                                 intf.vlan(), false, install);
             }
 
             // IPv4 to router
@@ -206,7 +223,7 @@
                     .build();
 
             flowObjectiveService.forward(deviceId,
-                    buildForwardingObjective(toSelector, null, cpNextId, true));
+                    buildForwardingObjective(toSelector, null, cpNextId, install));
 
             // IPv4 from router
             TrafficSelector fromSelector = DefaultTrafficSelector.builder()
@@ -218,7 +235,7 @@
                     .build();
 
             flowObjectiveService.forward(deviceId,
-                    buildForwardingObjective(fromSelector, null, intfNextId, true));
+                    buildForwardingObjective(fromSelector, null, intfNextId, install));
 
             // ARP to router
             toSelector = DefaultTrafficSelector.builder()
@@ -232,7 +249,7 @@
                     .build();
 
             flowObjectiveService.forward(deviceId,
-                    buildForwardingObjective(toSelector, puntTreatment, cpNextId, true));
+                    buildForwardingObjective(toSelector, puntTreatment, cpNextId, install));
 
             // ARP from router
             fromSelector = DefaultTrafficSelector.builder()
@@ -244,11 +261,18 @@
                     .build();
 
             flowObjectiveService.forward(deviceId,
-            buildForwardingObjective(fromSelector, puntTreatment, intfNextId, true));
+            buildForwardingObjective(fromSelector, puntTreatment, intfNextId, install));
         }
     }
 
-    private void updateOspfForwarding(Interface intf) {
+    /**
+     * Install or removes ospf forwarding rules.
+     *
+     * @param intf the Interface on which event is received
+     * @param install true to create an add objective, false to create a remove
+     *            objective
+     **/
+    private void updateOspfForwarding(Interface intf, boolean install) {
         // OSPF to router
         TrafficSelector toSelector = DefaultTrafficSelector.builder()
                 .matchInPort(intf.connectPoint().port())
@@ -262,16 +286,16 @@
         PortNumber controlPlanePort = controlPlaneConnectPoint.port();
         int cpNextId;
         if (intf.vlan() == VlanId.NONE) {
-            cpNextId = createNextObjective(deviceId, controlPlanePort,
+            cpNextId = modifyNextObjective(deviceId, controlPlanePort,
                            VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN),
-                           true);
+                           true, install);
         } else {
-            cpNextId = createNextObjective(deviceId, controlPlanePort,
-                                           intf.vlan(), false);
+            cpNextId = modifyNextObjective(deviceId, controlPlanePort,
+                                           intf.vlan(), false, install);
         }
         log.debug("ospf flows intf:{} nextid:{}", intf, cpNextId);
         flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(),
-                buildForwardingObjective(toSelector, null, cpNextId, ospfEnabled));
+                buildForwardingObjective(toSelector, null, cpNextId, install ? ospfEnabled : install));
     }
 
     /**
@@ -282,10 +306,12 @@
      * @param portNumber the egress port
      * @param vlanId vlan information for egress port
      * @param popVlan if vlan tag should be popped or not
+     * @param install true to create an add next objective, false to create a remove
+     *            next objective
      * @return nextId of the next objective created
      */
-    private int createNextObjective(DeviceId deviceId, PortNumber portNumber,
-                                    VlanId vlanId, boolean popVlan) {
+    private int modifyNextObjective(DeviceId deviceId, PortNumber portNumber,
+                                    VlanId vlanId, boolean popVlan, boolean install) {
         int nextId = flowObjectiveService.allocateNextId();
         NextObjective.Builder nextObjBuilder = DefaultNextObjective
                 .builder().withId(nextId)
@@ -307,10 +333,13 @@
         nextObjBuilder.addTreatment(ttBuilder.build());
         log.debug("Submited next objective {} in device {} for port/vlan {}/{}",
                 nextId, deviceId, portNumber, vlanId);
-        flowObjectiveService.next(deviceId, nextObjBuilder.add());
+        if (install) {
+             flowObjectiveService.next(deviceId, nextObjBuilder.add());
+        } else {
+             flowObjectiveService.next(deviceId, nextObjBuilder.remove());
+        }
         return nextId;
     }
-
     /**
      * Builds a forwarding objective from the given selector, treatment and nextId.
      *
@@ -344,6 +373,7 @@
      * Listener for device events.
      */
     private class InternalDeviceListener implements DeviceListener {
+
         @Override
         public void event(DeviceEvent event) {
             if (controlPlaneConnectPoint != null &&
@@ -374,6 +404,7 @@
      * Listener for network config events.
      */
     private class InternalNetworkConfigListener implements NetworkConfigListener {
+
         @Override
         public void event(NetworkConfigEvent event) {
             if (event.configClass().equals(RoutingService.ROUTER_CONFIG_CLASS)) {
@@ -396,6 +427,7 @@
      * Listener for host events.
      */
     private class InternalHostListener implements HostListener {
+
         private void peerAdded(HostEvent event) {
             Host peer = event.subject();
             Optional<Interface> peerIntf =
@@ -536,4 +568,27 @@
                 2000 * prefix.prefixLength() + MIN_IP_PRIORITY :
                 500 * prefix.prefixLength() + MIN_IP_PRIORITY;
     }
+    private class InternalInterfaceListener implements InterfaceListener {
+
+        @Override
+        public void event(InterfaceEvent event) {
+             Interface intf = event.subject();
+                switch (event.type()) {
+                case INTERFACE_ADDED:
+                    if (intf != null && !intf.connectPoint().equals(controlPlaneConnectPoint)) {
+                        provisionInterface(intf);
+                    }
+                    break;
+                case INTERFACE_UPDATED:
+                    break;
+                case INTERFACE_REMOVED:
+                    if (intf != null && !intf.connectPoint().equals(controlPlaneConnectPoint)) {
+                        removeInterface(intf);
+                    }
+                    break;
+                default:
+                    break;
+                }
+        }
+    }
 }