Add support for reconfiguring interfaces in SDN-IP.

Change-Id: I2ea85d85432e661c3cbdca5e5a8b16678a242369
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
index 48f097e..54cb16b 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
@@ -17,7 +17,6 @@
 
 import com.google.common.collect.Sets;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.onlab.junit.TestUtils.TestUtilsException;
 import org.onlab.packet.Ethernet;
@@ -30,6 +29,7 @@
 import org.onosproject.TestApplicationId;
 import org.onosproject.core.ApplicationId;
 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;
@@ -48,14 +48,10 @@
 import org.onosproject.routing.IntentSynchronizationService;
 import org.onosproject.routing.config.BgpConfig;
 import org.onosproject.routing.config.BgpPeer;
-import org.onosproject.routing.config.BgpSpeaker;
-import org.onosproject.routing.config.InterfaceAddress;
-import org.onosproject.routing.config.RoutingConfigurationService;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -81,7 +77,6 @@
 
     private PeerConnectivityManager peerConnectivityManager;
     private IntentSynchronizationService intentSynchronizer;
-    private RoutingConfigurationService routingConfig;
     private InterfaceService interfaceService;
     private NetworkConfigService networkConfigService;
 
@@ -104,8 +99,6 @@
     // Interfaces connected to BGP speakers
     private final ConnectPoint s1Eth100 =
             new ConnectPoint(deviceId1, PortNumber.portNumber(100));
-    private final ConnectPoint s2Eth100 =
-            new ConnectPoint(deviceId2, PortNumber.portNumber(100));
 
     // Interfaces connected to BGP peers
     private final ConnectPoint s1Eth1 =
@@ -119,8 +112,10 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        routingConfig = createMock(RoutingConfigurationService.class);
+
         interfaceService = createMock(InterfaceService.class);
+        interfaceService.addListener(anyObject(InterfaceListener.class));
+        expectLastCall().anyTimes();
         networkConfigService = createMock(NetworkConfigService.class);
         networkConfigService.addListener(anyObject(NetworkConfigListener.class));
         expectLastCall().anyTimes();
@@ -172,7 +167,7 @@
         InterfaceIpAddress ia1 =
             new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
                                    IpPrefix.valueOf("192.168.10.0/24"));
-        Interface intfsw1eth1 = new Interface(s1Eth1,
+        Interface intfsw1eth1 = new Interface(interfaceSw1Eth1, s1Eth1,
                 Collections.singletonList(ia1),
                 MacAddress.valueOf("00:00:00:00:00:01"),
                 VlanId.NONE);
@@ -182,7 +177,7 @@
         InterfaceIpAddress ia2 =
             new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
                                    IpPrefix.valueOf("192.168.20.0/24"));
-        Interface intfsw2eth1 = new Interface(s2Eth1,
+        Interface intfsw2eth1 = new Interface(interfaceSw2Eth1, s2Eth1,
                 Collections.singletonList(ia2),
                 MacAddress.valueOf("00:00:00:00:00:02"),
                 VlanId.NONE);
@@ -192,7 +187,7 @@
         InterfaceIpAddress ia3 =
                 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
                         IpPrefix.valueOf("192.168.30.0/24"));
-        Interface intfsw2eth1intf2 = new Interface(s2Eth1,
+        Interface intfsw2eth1intf2 = new Interface(interfaceSw2Eth1intf2, s2Eth1,
                 Collections.singletonList(ia3),
                 MacAddress.valueOf("00:00:00:00:00:03"),
                 VlanId.NONE);
@@ -430,13 +425,11 @@
      * @throws TestUtilsException if exceptions when using TestUtils
      */
     private void initPeerConnectivity() throws TestUtilsException {
-        expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes();
         expect(bgpConfig.bgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
         replay(bgpConfig);
         expect(networkConfigService.getConfig(APPID, BgpConfig.class))
                 .andReturn(bgpConfig).anyTimes();
         replay(networkConfigService);
-        replay(routingConfig);
         replay(interfaceService);
 
         intentSynchronizer = createMock(IntentSynchronizationService.class);
@@ -478,6 +471,8 @@
     @Test
     public void testNullInterfaces() {
         reset(interfaceService);
+        interfaceService.addListener(anyObject(InterfaceListener.class));
+        expectLastCall().anyTimes();
 
         expect(interfaceService.getInterfaces()).andReturn(
                 Sets.newHashSet()).anyTimes();
@@ -511,13 +506,9 @@
      */
     @Test
     public void testNullBgpSpeakers() {
-        reset(routingConfig);
         reset(bgpConfig);
-
         expect(bgpConfig.bgpSpeakers()).andReturn(Collections.emptySet()).anyTimes();
         replay(bgpConfig);
-        expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes();
-        replay(routingConfig);
 
         reset(intentSynchronizer);
         replay(intentSynchronizer);
@@ -537,21 +528,4 @@
         testConnectionSetup();
     }
 
-    /**
-     * Tests a corner case, when there is no Interface configured for one BGP
-     * speaker.
-     */
-    @Ignore
-    @Test
-    public void testNoSpeakerInterface() {
-        BgpSpeaker bgpSpeaker100 = new BgpSpeaker(
-                "bgpSpeaker100",
-                "00:00:00:00:00:00:01:00", 100,
-                "00:00:00:00:01:00");
-        List<InterfaceAddress> interfaceAddresses100 = new LinkedList<>();
-        interfaceAddresses100.add(new InterfaceAddress(dpid1, 1, "192.168.10.201"));
-        interfaceAddresses100.add(new InterfaceAddress(dpid2, 1, "192.168.20.201"));
-        bgpSpeaker100.setInterfaceAddresses(interfaceAddresses100);
-        testConnectionSetup();
-    }
 }
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java
index 3fe048b..c23737c 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java
@@ -31,7 +31,10 @@
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreServiceAdapter;
 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.incubator.net.intf.InterfaceServiceAdapter;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
@@ -48,18 +51,16 @@
 import org.onosproject.routing.FibUpdate;
 import org.onosproject.routing.IntentSynchronizationService;
 import org.onosproject.routing.RoutingServiceAdapter;
-import org.onosproject.routing.config.BgpPeer;
-import org.onosproject.routing.config.RoutingConfigurationService;
 
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
+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;
@@ -70,7 +71,6 @@
  */
 public class SdnIpFibTest extends AbstractIntentTest {
 
-    private RoutingConfigurationService routingConfig;
     private InterfaceService interfaceService;
 
     private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
@@ -89,6 +89,10 @@
             DeviceId.deviceId("of:0000000000000004"),
             PortNumber.portNumber(1));
 
+    private static final ConnectPoint SW5_ETH1 = new ConnectPoint(
+            DeviceId.deviceId("of:0000000000000005"),
+            PortNumber.portNumber(1));
+
     private SdnIpFib sdnipFib;
     private IntentSynchronizationService intentSynchronizer;
     private final Set<Interface> interfaces = Sets.newHashSet();
@@ -96,19 +100,19 @@
     private static final ApplicationId APPID = TestApplicationId.create("SDNIP");
 
     private FibListener fibListener;
+    private InterfaceListener interfaceListener;
 
     @Before
     public void setUp() throws Exception {
         super.setUp();
 
-        routingConfig = createMock(RoutingConfigurationService.class);
         interfaceService = createMock(InterfaceService.class);
+        interfaceService.addListener(anyObject(InterfaceListener.class));
+        expectLastCall().andDelegateTo(new InterfaceServiceDelegate());
 
         // These will set expectations on routingConfig and interfaceService
         setUpInterfaceService();
-        setUpBgpPeers();
 
-        replay(routingConfig);
         replay(interfaceService);
 
         intentSynchronizer = createMock(IntentSynchronizationService.class);
@@ -123,33 +127,6 @@
     }
 
     /**
-     * Sets up BGP peers in external networks.
-     */
-    private void setUpBgpPeers() {
-
-        Map<IpAddress, BgpPeer> peers = new HashMap<>();
-
-        String peerSw1Eth1 = "192.168.10.1";
-        peers.put(IpAddress.valueOf(peerSw1Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
-
-        // Two BGP peers are connected to switch 2 port 1.
-        String peer1Sw2Eth1 = "192.168.20.1";
-        peers.put(IpAddress.valueOf(peer1Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
-
-        String peer2Sw2Eth1 = "192.168.20.2";
-        peers.put(IpAddress.valueOf(peer2Sw2Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
-
-        String peer1Sw4Eth1 = "192.168.40.1";
-        peers.put(IpAddress.valueOf(peer1Sw4Eth1),
-                new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
-
-        expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes();
-    }
-
-    /**
      * Sets up InterfaceService.
      */
     private void setUpInterfaceService() {
@@ -157,7 +134,7 @@
         interfaceIpAddresses1.add(new InterfaceIpAddress(
                 IpAddress.valueOf("192.168.10.101"),
                 IpPrefix.valueOf("192.168.10.0/24")));
-        Interface sw1Eth1 = new Interface(SW1_ETH1,
+        Interface sw1Eth1 = new Interface("sw1-eth1", SW1_ETH1,
                 interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
                 VlanId.NONE);
         interfaces.add(sw1Eth1);
@@ -166,7 +143,7 @@
         interfaceIpAddresses2.add(
                 new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
                         IpPrefix.valueOf("192.168.20.0/24")));
-        Interface sw2Eth1 = new Interface(SW2_ETH1,
+        Interface sw2Eth1 = new Interface("sw2-eth1", SW2_ETH1,
                 interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
                 VlanId.NONE);
         interfaces.add(sw2Eth1);
@@ -175,7 +152,7 @@
         interfaceIpAddresses3.add(
                 new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
                         IpPrefix.valueOf("192.168.30.0/24")));
-        Interface sw3Eth1 = new Interface(SW3_ETH1,
+        Interface sw3Eth1 = new Interface("sw3-eth1", SW3_ETH1,
                 interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
                 VlanId.NONE);
         interfaces.add(sw3Eth1);
@@ -183,7 +160,7 @@
         InterfaceIpAddress interfaceIpAddress4 =
                 new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
                         IpPrefix.valueOf("192.168.40.0/24"));
-        Interface sw4Eth1 = new Interface(SW4_ETH1,
+        Interface sw4Eth1 = new Interface("sw4-eth1", SW4_ETH1,
                 Lists.newArrayList(interfaceIpAddress4),
                 MacAddress.valueOf("00:00:00:00:00:04"),
                 VlanId.vlanId((short) 1));
@@ -428,6 +405,100 @@
         verify(intentSynchronizer);
     }
 
+    @Test
+    public void testAddInterface() {
+        testFibAdd();
+
+        IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
+
+        // Construct the existing MultiPointToSinglePoint intent
+        TrafficSelector.Builder selectorBuilder =
+                DefaultTrafficSelector.builder();
+        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(prefix);
+
+        TrafficTreatment.Builder treatmentBuilder =
+                DefaultTrafficTreatment.builder();
+        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
+
+        Set<ConnectPoint> ingressPoints = new HashSet<>();
+        ingressPoints.add(SW2_ETH1);
+        ingressPoints.add(SW3_ETH1);
+        ingressPoints.add(SW4_ETH1);
+        ingressPoints.add(SW5_ETH1);
+
+        MultiPointToSinglePointIntent addedIntent =
+                MultiPointToSinglePointIntent.builder()
+                        .appId(APPID)
+                        .key(Key.of(prefix.toString(), APPID))
+                        .selector(selectorBuilder.build())
+                        .treatment(treatmentBuilder.build())
+                        .ingressPoints(ingressPoints)
+                        .egressPoint(SW1_ETH1)
+                        .constraints(SdnIpFib.CONSTRAINTS)
+                        .build();
+
+        reset(intentSynchronizer);
+
+        intentSynchronizer.submit(eqExceptId(addedIntent));
+        expectLastCall().once();
+
+        replay(intentSynchronizer);
+
+        Interface intf = new Interface("newintf", SW5_ETH1,
+                Collections.singletonList(InterfaceIpAddress.valueOf("192.168.50.101/24")),
+                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE);
+        InterfaceEvent intfEvent = new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf);
+        interfaceListener.event(intfEvent);
+
+        verify(intentSynchronizer);
+    }
+
+    @Test
+    public void testRemoveInterface() {
+        testFibAdd();
+
+        IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
+
+        // Construct the existing MultiPointToSinglePoint intent
+        TrafficSelector.Builder selectorBuilder =
+                DefaultTrafficSelector.builder();
+        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(prefix);
+
+        TrafficTreatment.Builder treatmentBuilder =
+                DefaultTrafficTreatment.builder();
+        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
+
+        Set<ConnectPoint> ingressPoints = new HashSet<>();
+        ingressPoints.add(SW2_ETH1);
+        ingressPoints.add(SW3_ETH1);
+
+        MultiPointToSinglePointIntent addedIntent =
+                MultiPointToSinglePointIntent.builder()
+                        .appId(APPID)
+                        .key(Key.of(prefix.toString(), APPID))
+                        .selector(selectorBuilder.build())
+                        .treatment(treatmentBuilder.build())
+                        .ingressPoints(ingressPoints)
+                        .egressPoint(SW1_ETH1)
+                        .constraints(SdnIpFib.CONSTRAINTS)
+                        .build();
+
+        reset(intentSynchronizer);
+
+        intentSynchronizer.submit(eqExceptId(addedIntent));
+        expectLastCall().once();
+
+        replay(intentSynchronizer);
+
+        Interface intf = new Interface("newintf", SW4_ETH1,
+                Collections.singletonList(InterfaceIpAddress.valueOf("192.168.50.101/24")),
+                MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE);
+        InterfaceEvent intfEvent = new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, intf);
+        interfaceListener.event(intfEvent);
+
+        verify(intentSynchronizer);
+    }
+
     private class TestCoreService extends CoreServiceAdapter {
         @Override
         public ApplicationId getAppId(String name) {
@@ -442,4 +513,12 @@
             SdnIpFibTest.this.fibListener = fibListener;
         }
     }
+
+    private class InterfaceServiceDelegate extends InterfaceServiceAdapter {
+
+        @Override
+        public void addListener(InterfaceListener listener) {
+            SdnIpFibTest.this.interfaceListener = listener;
+        }
+    }
 }