[GEANT] Listener to interface service added.

Change-Id: I03ebf90c6bf8225367919cbb6ec63fe0846522ce
diff --git a/sdx-l3/app.xml b/sdx-l3/app.xml
index 54b83d4..9bd278f 100644
--- a/sdx-l3/app.xml
+++ b/sdx-l3/app.xml
@@ -21,6 +21,7 @@
      featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
      features="${project.artifactId}">
     <description>${project.description}</description>
+    <readme>Application controlling SDN-based L3 Internet Exchange Points.</readme>
     <artifact>mvn:${project.groupId}/onos-app-routing-api/${project.version}</artifact>
     <artifact>mvn:${project.groupId}/onos-app-routing/${project.version}</artifact>
     <artifact>mvn:${project.groupId}/${project.artifactId}/${project.version}</artifact>
diff --git a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java b/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java
index c28e894..bcef2f3 100644
--- a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java
+++ b/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3.java
@@ -72,7 +72,6 @@
     private static List<String> components = new ArrayList<>();
     static {
         components.add("org.onosproject.routing.bgp.BgpSessionManager");
-        components.add("org.onosproject.routing.impl.Router");
         components.add(org.onosproject.sdxl3.impl.SdxL3PeerManager.class.getName());
         components.add(SdxL3Fib.class.getName());
         components.add(SdxL3ArpHandler.class.getName());
@@ -82,9 +81,11 @@
     protected void activate() {
         components.forEach(name -> componentService.activate(appId, name));
         appId = coreService.registerApplication(SDX_L3_APP);
-        // TODO fix removing intents
-        applicationService.registerDeactivateHook(appId,
-                intentSynchronizerAdmin::removeIntents);
+
+        applicationService.registerDeactivateHook(appId, () -> {
+            intentSynchronizer.removeIntentsByAppId(appId);
+        });
+
         log.info("SDX-L3 started");
     }
 
diff --git a/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java b/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java
index e9105a3..2a2e617 100644
--- a/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java
+++ b/sdx-l3/src/main/java/org/onosproject/sdxl3/impl/SdxL3PeerManager.java
@@ -34,6 +34,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.config.ConfigFactory;
@@ -117,6 +119,9 @@
     private final InternalNetworkConfigListener configListener
             = new InternalNetworkConfigListener();
 
+    private final InternalInterfaceListener interfaceListener
+            = new InternalInterfaceListener();
+
     @Activate
     public void activate() {
         sdxAppId = coreService.getAppId(SdxL3.SDX_L3_APP);
@@ -125,6 +130,7 @@
         registry.registerConfigFactory(configFactory);
 
         configService.addListener(configListener);
+        interfaceService.addListener(interfaceListener);
 
         setUpConnectivity();
 
@@ -134,6 +140,7 @@
     @Deactivate
     public void deactivate() {
         configService.removeListener(configListener);
+        interfaceService.removeListener(interfaceListener);
 
         log.info("Connectivity with BGP peers stopped");
     }
@@ -434,15 +441,14 @@
     }
 
     /**
-     * Builds the required intents between the two pairs of connect points and
-     * IP addresses.
+     * Builds the required intents between a BGP speaker and an external router.
      *
-     * @param portOne the first connect point
-     * @param vlanOne the ingress VLAN
-     * @param ipOne the first IP address
-     * @param portTwo the second connect point
-     * @param vlanTwo the egress VLAN
-     * @param ipTwo the second IP address
+     * @param portOne the BGP speaker connect point
+     * @param vlanOne the BGP speaker VLAN
+     * @param ipOne the BGP speaker IP address
+     * @param portTwo the external BGP peer connect point
+     * @param vlanTwo the external BGP peer VLAN
+     * @param ipTwo the external BGP peer IP address
      * @return the intents to install
      */
     private Collection<PointToPointIntent> buildIntents(ConnectPoint portOne,
@@ -470,9 +476,13 @@
             icmpProtocol = IPv6.PROTOCOL_ICMP6;
         }
 
-        // Add treatment for VLAN for traffic going from BGP speaker to BGP peer
-        if (!vlanTwo.equals(VlanId.NONE)) {
-            treatmentToPeer.setVlanId(vlanTwo);
+        // Add VLAN treatment for traffic going from BGP speaker to BGP peer
+        if (!vlanOne.equals(vlanTwo)) {
+            if (vlanTwo.equals(VlanId.NONE)) {
+                treatmentToPeer.popVlan();
+            } else {
+                treatmentToPeer.setVlanId(vlanTwo);
+            }
         }
 
         // Path from BGP speaker to BGP peer matching destination TCP port 179
@@ -535,9 +545,13 @@
                 .priority(PRIORITY_OFFSET)
                 .build());
 
-        // Add treatment for VLAN for traffic going from BGP peer to BGP speaker
-        if (!vlanOne.equals(VlanId.NONE)) {
-            treatmentToSpeaker.setVlanId(vlanOne);
+        // Add VLAN treatment for traffic going from BGP peer to BGP speaker
+        if (!vlanTwo.equals(vlanOne)) {
+            if (vlanOne.equals(VlanId.NONE)) {
+                treatmentToSpeaker.popVlan();
+            } else {
+                treatmentToSpeaker.setVlanId(vlanOne);
+            }
         }
 
         // Path from BGP peer to BGP speaker matching destination TCP port 179
@@ -692,4 +706,19 @@
         }
     }
 
+    private class InternalInterfaceListener implements InterfaceListener {
+        @Override
+        public void event(InterfaceEvent event) {
+            switch (event.type()) {
+                case INTERFACE_ADDED:
+                case INTERFACE_UPDATED:
+                case INTERFACE_REMOVED:
+                    setUpConnectivity();
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
 }
diff --git a/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerAdministrationTest.java b/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerAdministrationTest.java
index 1881aad..fc96f88 100644
--- a/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerAdministrationTest.java
+++ b/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerAdministrationTest.java
@@ -30,6 +30,7 @@
 import org.onosproject.core.CoreService;
 import org.onosproject.core.CoreServiceAdapter;
 import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceListener;
 import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
@@ -58,6 +59,7 @@
 import java.util.Set;
 
 import static junit.framework.TestCase.assertEquals;
+import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
@@ -162,6 +164,8 @@
         configService = new TestNetworkConfigService();
         registry = new NetworkConfigRegistryAdapter();
         interfaceService = createMock(InterfaceService.class);
+        interfaceService.addListener(anyObject(InterfaceListener.class));
+        expectLastCall().anyTimes();
         intentSynchronizer = createMock(IntentSynchronizationService.class);
     }
 
diff --git a/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerConnectivityTest.java b/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerConnectivityTest.java
index 1f9cbdd..0bd4aec 100644
--- a/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerConnectivityTest.java
+++ b/sdx-l3/src/test/java/org/onosproject/sdxl3/impl/SdxL3PeerConnectivityTest.java
@@ -68,6 +68,7 @@
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.reset;
 import static org.easymock.EasyMock.verify;
@@ -184,6 +185,8 @@
         configService = new TestNetworkConfigService();
         registry = new NetworkConfigRegistryAdapter();
         interfaceService = createMock(InterfaceService.class);
+        interfaceService.addListener(anyObject(InterfaceListener.class));
+        expectLastCall().anyTimes();
         intentSynchronizer = createMock(IntentSynchronizationService.class);
     }
 
@@ -686,6 +689,8 @@
     public void testNullInterfaces() {
         reset(interfaceService);
 
+        interfaceService.addListener(anyObject(InterfaceListener.class));
+        expectLastCall().anyTimes();
         expect(interfaceService.getInterfaces()).andReturn(Sets.newHashSet())
                 .anyTimes();
         expect(interfaceService.getInterfacesByPort(anyObject()))