changes for cord-488 and addressed comments

Change-Id: Ic51923f7d5860d9120acadc5ca3716cf5f143dcc
diff --git a/apps/routing/pom.xml b/apps/routing/pom.xml
index 8b791a0..1c7d1b5 100644
--- a/apps/routing/pom.xml
+++ b/apps/routing/pom.xml
@@ -47,6 +47,14 @@
 
         <dependency>
             <groupId>org.onosproject</groupId>
+            <artifactId>onos-incubator-api</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+            <classifier>tests</classifier>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
             <artifactId>onos-cli</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
index ccf93d1..b548492 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
@@ -37,6 +37,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.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
@@ -139,6 +141,8 @@
     // Stores FIB updates that are waiting for groups to be set up
     private final Multimap<NextHopGroupKey, FibEntry> pendingUpdates = HashMultimap.create();
 
+    //interface object for event
+    private InternalInterfaceListener internalInterfaceList = new InternalInterfaceListener();
 
     @Activate
     protected void activate(ComponentContext context) {
@@ -150,6 +154,8 @@
         deviceListener = new InternalDeviceListener();
         deviceService.addListener(deviceListener);
 
+        interfaceService.addListener(internalInterfaceList);
+
         routingService.addFibListener(new InternalFibListener());
         routingService.start();
 
@@ -164,6 +170,8 @@
 
         deviceService.removeListener(deviceListener);
 
+        interfaceService.removeListener(internalInterfaceList);
+
         //processIntfFilters(false, configService.getInterfaces()); //TODO necessary?
 
         componentConfigService.unregisterProperties(getClass(), false);
@@ -393,47 +401,84 @@
                 continue;
             }
 
-            FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
-            // first add filter for the interface
-            fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
-                .addCondition(Criteria.matchEthDst(intf.mac()))
-                .addCondition(Criteria.matchVlanId(intf.vlan()));
-            fob.withPriority(PRIORITY_OFFSET);
-            if (intf.vlan() == VlanId.NONE) {
-                TrafficTreatment tt = DefaultTrafficTreatment.builder()
-                        .pushVlan().setVlanId(VlanId.vlanId(ASSIGNED_VLAN)).build();
-                fob.withMeta(tt);
-            }
+            createFilteringObjective(install, intf);
+        }
+    }
 
-            fob.permit().fromApp(routerAppId);
+    //process filtering objective for interface add/remove.
+    private void processIntfFilter(boolean install, Interface intf) {
+
+        if (!intf.connectPoint().deviceId().equals(deviceId)) {
+            // Ignore interfaces if they are not on the router switch
+            return;
+        }
+
+        createFilteringObjective(install, intf);
+    }
+
+    //create filtering objective for interface
+    private void createFilteringObjective(boolean install, Interface intf) {
+
+        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
+        // first add filter for the interface
+        fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
+            .addCondition(Criteria.matchEthDst(intf.mac()))
+            .addCondition(Criteria.matchVlanId(intf.vlan()));
+        fob.withPriority(PRIORITY_OFFSET);
+        if (intf.vlan() == VlanId.NONE) {
+            TrafficTreatment tt = DefaultTrafficTreatment.builder()
+                    .pushVlan().setVlanId(VlanId.vlanId(ASSIGNED_VLAN)).build();
+            fob.withMeta(tt);
+        }
+
+        fob.permit().fromApp(routerAppId);
+        sendFilteringObjective(install, fob, intf);
+        if (controlPlaneConnectPoint != null) {
+            // then add the same mac/vlan filters for control-plane connect point
+            fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port()));
             sendFilteringObjective(install, fob, intf);
-            if (controlPlaneConnectPoint != null) {
-                // then add the same mac/vlan filters for control-plane connect point
-                fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port()));
-                sendFilteringObjective(install, fob, intf);
-            }
         }
     }
 
     private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob,
                                         Interface intf) {
-        flowObjectiveService.filter(
-            deviceId,
-            fob.add(new ObjectiveContext() {
-                @Override
-                public void onSuccess(Objective objective) {
-                    log.info("Successfully installed interface based "
-                            + "filtering objectives for intf {}", intf);
-                }
+        if (install) {
+            flowObjectiveService.filter(
+                deviceId,
+                fob.add(new ObjectiveContext() {
+                    @Override
+                    public void onSuccess(Objective objective) {
+                        log.info("Successfully installed interface based "
+                                + "filtering objectives for intf {}", intf);
+                    }
 
-                @Override
-                public void onError(Objective objective,
-                                    ObjectiveError error) {
-                    log.error("Failed to install interface filters for intf {}: {}",
-                              intf, error);
-                    // TODO something more than just logging
-                }
+                    @Override
+                    public void onError(Objective objective,
+                                        ObjectiveError error) {
+                        log.error("Failed to install interface filters for intf {}: {}",
+                                  intf, error);
+                        // TODO something more than just logging
+                    }
             }));
+        } else {
+            flowObjectiveService.filter(
+                deviceId,
+                fob.remove(new ObjectiveContext() {
+                    @Override
+                    public void onSuccess(Objective objective) {
+                        log.info("Successfully removed interface based "
+                                   + "filtering objectives for intf {}", intf);
+                    }
+
+                    @Override
+                    public void onError(Objective objective,
+                                        ObjectiveError error) {
+                        log.error("Failed to install interface filters for intf {}: {}",
+                                  intf, error);
+                            // TODO something more than just logging
+                    }
+            }));
+        }
     }
 
     private class InternalFibListener implements FibListener {
@@ -497,4 +542,28 @@
             }
         }
     }
+
+    private class InternalInterfaceListener implements InterfaceListener {
+
+        @Override
+        public void event(InterfaceEvent event) {
+            Interface intf = event.subject();
+            switch (event.type()) {
+            case INTERFACE_ADDED:
+                if (intf != null) {
+                    processIntfFilter(true, intf);
+                }
+                break;
+            case INTERFACE_UPDATED:
+                break;
+            case INTERFACE_REMOVED:
+                if (intf != null) {
+                    processIntfFilter(false, intf);
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
 }
diff --git a/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java b/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
index 4e76670..29c8352 100644
--- a/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
+++ b/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
@@ -25,6 +25,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Dictionary;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -45,7 +46,9 @@
 import org.osgi.service.component.ComponentContext;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceListener;
 import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.incubator.net.intf.InterfaceServiceAdapter;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
@@ -70,7 +73,6 @@
 import org.onosproject.routing.RoutingService;
 import org.onosproject.routing.RoutingServiceAdapter;
 import org.onosproject.routing.config.RouterConfig;
-
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 
@@ -108,7 +110,8 @@
     private CoreService coreService;
     private RouterConfig routerConfig;
     private RoutingService routingService;
-    SingleSwitchFibInstaller sSfibInstaller;
+    private SingleSwitchFibInstaller sSfibInstaller;
+    private InterfaceListener interfaceListener;
 
     @Before
     public void setUp() throws Exception {
@@ -135,7 +138,8 @@
         coreService = new TestCoreService();
         routingService = new TestRoutingService();
         routerConfig = new TestRouterConfig();
-        interfaceService = createMock(InterfaceService.class);
+        //interfaceService = createMock(InterfaceService.class);
+        interfaceService = new TestInterfaceService();
         networkConfigService = createMock(NetworkConfigService.class);
         flowObjectiveService = createMock(FlowObjectiveService.class);
         deviceService = new TestDeviceService();
@@ -158,7 +162,7 @@
     private void setUpInterfaceService() {
         Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
         interfaceIpAddresses1.add(new InterfaceIpAddress(
-                IpAddress.valueOf("192.168.10.101"),
+                IpAddress.valueOf("192.168.10.1"),
                 IpPrefix.valueOf("192.168.10.0/24")));
         Interface sw1Eth1 = new Interface(SW1_ETH1.deviceId().toString(), SW1_ETH1,
                   interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
@@ -166,7 +170,7 @@
         interfaces.add(sw1Eth1);
 
         Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
-        interfaceIpAddresses2.add(new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
+        interfaceIpAddresses2.add(new InterfaceIpAddress(IpAddress.valueOf("192.168.20.1"),
            IpPrefix.valueOf("192.168.20.0/24")));
         Interface sw2Eth1 = new Interface(SW2_ETH1.deviceId().toString(), SW2_ETH1,
            interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
@@ -182,35 +186,14 @@
         interfaces.add(sw3Eth1);
 
         InterfaceIpAddress interfaceIpAddress4 =
-           new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
+           new InterfaceIpAddress(IpAddress.valueOf("192.168.40.1"),
            IpPrefix.valueOf("192.168.40.0/24"));
 
         Interface sw4Eth1 = new Interface(SW4_ETH1.deviceId().toString(), SW4_ETH1,
            Sets.newHashSet(interfaceIpAddress4),
            MacAddress.valueOf("00:00:00:00:00:04"),
            VlanId.vlanId((short) 1));
-
-        expect(interfaceService.getInterfacesByPort(SW4_ETH1)).andReturn(
-                Collections.singleton(sw4Eth1)).anyTimes();
-        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.40.1")))
-                .andReturn(sw4Eth1).anyTimes();
-
         interfaces.add(sw4Eth1);
-
-        expect(interfaceService.getInterfacesByPort(SW1_ETH1)).andReturn(
-                Collections.singleton(sw1Eth1)).anyTimes();
-        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.10.1")))
-                .andReturn(sw1Eth1).anyTimes();
-        expect(interfaceService.getInterfacesByPort(SW2_ETH1)).andReturn(
-                Collections.singleton(sw2Eth1)).anyTimes();
-        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.20.1")))
-                .andReturn(sw2Eth1).anyTimes();
-        expect(interfaceService.getInterfacesByPort(SW3_ETH1)).andReturn(
-                Collections.singleton(sw3Eth1)).anyTimes();
-        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.30.1")))
-                .andReturn(sw3Eth1).anyTimes();
-        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
-        replay(interfaceService);
     }
 
     /*
@@ -482,6 +465,47 @@
         verify(flowObjectiveService);
     }
 
+    private class TestInterfaceService extends InterfaceServiceAdapter {
+
+        @Override
+        public void addListener(InterfaceListener listener) {
+            SingleSwitchFibInstallerTest.this.interfaceListener = listener;
+        }
+
+        @Override
+        public Set<Interface> getInterfaces() {
+            return interfaces;
+        }
+
+        @Override
+        public Set<Interface> getInterfacesByPort(ConnectPoint port) {
+
+            Set<Interface> setIntf = new HashSet<Interface>();
+            for (Interface intf : interfaces) {
+                if (intf.connectPoint().equals(port)) {
+                    setIntf.add(intf);
+
+                }
+            }
+            return setIntf;
+        }
+
+        @Override
+        public Interface getMatchingInterface(IpAddress ip) {
+            Interface intff = null;
+            for (Interface intf : interfaces) {
+                for (InterfaceIpAddress address : intf.ipAddresses()) {
+                    if (address.ipAddress().equals(ip)) {
+                        intff = intf;
+                        break;
+                    }
+                }
+            }
+
+            return intff;
+        }
+    }
+
     private class TestCoreService extends CoreServiceAdapter {
 
         @Override