Updated SDN-IP to use the Intent framework batch-based intents.

Also, created a local cache of IPv4-to-MAC address mapping,
to avoid relatively costly hostService.getHostsByIp() calls
per added route.

Change-Id: I8abed378985708e883fd99e85c54b01f38756515
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/IntentSyncTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/IntentSyncTest.java
index 2cb74f5..d0c0aeb 100644
--- a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/IntentSyncTest.java
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/IntentSyncTest.java
@@ -325,13 +325,13 @@
                 .andReturn(IntentState.WITHDRAWING).anyTimes();
         expect(intentService.getIntents()).andReturn(intents).anyTimes();
 
-        IntentOperations.Builder builder = IntentOperations.builder(null); //FIXME null
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
         builder.addWithdrawOperation(intent2.id());
         builder.addWithdrawOperation(intent4.id());
         intentService.execute(TestIntentServiceHelper.eqExceptId(
                                 builder.build()));
 
-        builder = IntentOperations.builder(null); //FIXME null
+        builder = IntentOperations.builder(APPID);
         builder.addSubmitOperation(intent3);
         builder.addSubmitOperation(intent4Update);
         builder.addSubmitOperation(intent6);
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/PeerConnectivityManagerTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/PeerConnectivityManagerTest.java
index 0c39582..46824ca 100644
--- a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/PeerConnectivityManagerTest.java
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/PeerConnectivityManagerTest.java
@@ -566,7 +566,7 @@
         reset(intentService);
 
         // Setup the expected intents
-        IntentOperations.Builder builder = IntentOperations.builder(null); //FIXME null
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
         for (Intent intent : intentList) {
             builder.addSubmitOperation(intent);
         }
@@ -601,9 +601,8 @@
         replay(configInfoService);
 
         reset(intentService);
-        IntentOperations.Builder builder = IntentOperations.builder(null); //FIXME null
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                builder.build()));
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        intentService.execute(builder.build());
         replay(intentService);
         peerConnectivityManager.start();
         verify(intentService);
@@ -627,9 +626,8 @@
         replay(configInfoService);
 
         reset(intentService);
-        IntentOperations.Builder builder = IntentOperations.builder(null); //FIXME null
-        intentService.execute(TestIntentServiceHelper.eqExceptId(
-                builder.build()));
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        intentService.execute(builder.build());
         replay(intentService);
         peerConnectivityManager.start();
         verify(intentService);
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTest.java
index f15d50f..e877f34 100644
--- a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTest.java
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTest.java
@@ -25,6 +25,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -50,6 +51,7 @@
 import org.onlab.onos.net.host.HostService;
 import org.onlab.onos.net.host.InterfaceIpAddress;
 import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentOperations;
 import org.onlab.onos.net.intent.IntentService;
 import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
 import org.onlab.onos.net.intent.AbstractIntentTest;
@@ -234,7 +236,7 @@
      * This method tests adding a route entry.
      */
     @Test
-    public void testProcessRouteAdd() throws TestUtilsException {
+    public void testRouteAdd() throws TestUtilsException {
         // Construct a route entry
         RouteEntry routeEntry = new RouteEntry(
                 Ip4Prefix.valueOf("1.1.1.0/24"),
@@ -261,13 +263,19 @@
 
         // Set up test expectation
         reset(intentService);
-        intentService.submit(TestIntentServiceHelper.eqExceptId(intent));
+        // Setup the expected intents
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addSubmitOperation(intent);
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
         replay(intentService);
 
-        // Call the processRouteAdd() method in Router class
+        // Call the processRouteUpdates() method in Router class
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        router.processRouteAdd(routeEntry);
+        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
+                                                  routeEntry);
+        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
 
         // Verify
         assertEquals(router.getRoutes().size(), 1);
@@ -289,32 +297,16 @@
     @Test
     public void testRouteUpdate() throws TestUtilsException {
         // Firstly add a route
-        testProcessRouteAdd();
+        testRouteAdd();
+
+        Intent addedIntent =
+            intentSynchronizer.getRouteIntents().iterator().next();
 
         // Construct the existing route entry
         RouteEntry routeEntry = new RouteEntry(
                 Ip4Prefix.valueOf("1.1.1.0/24"),
                 Ip4Address.valueOf("192.168.10.1"));
 
-        // Construct the existing MultiPointToSinglePointIntent intent
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
-                routeEntry.prefix());
-
-        TrafficTreatment.Builder treatmentBuilder =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
-
-        Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
-        ingressPoints.add(SW2_ETH1);
-        ingressPoints.add(SW3_ETH1);
-
-        MultiPointToSinglePointIntent intent =
-                new MultiPointToSinglePointIntent(APPID,
-                        selectorBuilder.build(), treatmentBuilder.build(),
-                        ingressPoints, SW1_ETH1);
-
         // Start to construct a new route entry and new intent
         RouteEntry routeEntryUpdate = new RouteEntry(
                 Ip4Prefix.valueOf("1.1.1.0/24"),
@@ -343,14 +335,23 @@
 
         // Set up test expectation
         reset(intentService);
-        intentService.withdraw(TestIntentServiceHelper.eqExceptId(intent));
-        intentService.submit(TestIntentServiceHelper.eqExceptId(intentNew));
+        // Setup the expected intents
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addWithdrawOperation(addedIntent.id());
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
+        builder = IntentOperations.builder(APPID);
+        builder.addSubmitOperation(intentNew);
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
         replay(intentService);
 
-        // Call the processRouteAdd() method in Router class
+        // Call the processRouteUpdates() method in Router class
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        router.processRouteAdd(routeEntryUpdate);
+        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
+                                                  routeEntryUpdate);
+        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
 
         // Verify
         assertEquals(router.getRoutes().size(), 1);
@@ -368,43 +369,33 @@
      * This method tests deleting a route entry.
      */
     @Test
-    public void testProcessRouteDelete() throws TestUtilsException {
+    public void testRouteDelete() throws TestUtilsException {
         // Firstly add a route
-        testProcessRouteAdd();
+        testRouteAdd();
+
+        Intent addedIntent =
+            intentSynchronizer.getRouteIntents().iterator().next();
 
         // Construct the existing route entry
         RouteEntry routeEntry = new RouteEntry(
                 Ip4Prefix.valueOf("1.1.1.0/24"),
                 Ip4Address.valueOf("192.168.10.1"));
 
-        // Construct the existing MultiPointToSinglePointIntent intent
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
-                routeEntry.prefix());
-
-        TrafficTreatment.Builder treatmentBuilder =
-                DefaultTrafficTreatment.builder();
-        treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
-
-        Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
-        ingressPoints.add(SW2_ETH1);
-        ingressPoints.add(SW3_ETH1);
-
-        MultiPointToSinglePointIntent intent =
-                new MultiPointToSinglePointIntent(APPID,
-                        selectorBuilder.build(), treatmentBuilder.build(),
-                        ingressPoints, SW1_ETH1);
-
         // Set up expectation
         reset(intentService);
-        intentService.withdraw(TestIntentServiceHelper.eqExceptId(intent));
+        // Setup the expected intents
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addWithdrawOperation(addedIntent.id());
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
         replay(intentService);
 
-        // Call route deleting method in Router class
+        // Call the processRouteUpdates() method in Router class
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        router.processRouteDelete(routeEntry);
+        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
+                                                  routeEntry);
+        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
 
         // Verify
         assertEquals(router.getRoutes().size(), 0);
@@ -428,10 +419,12 @@
         reset(intentService);
         replay(intentService);
 
-        // Call the processRouteAdd() method in Router class
+        // Call the processRouteUpdates() method in Router class
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        router.processRouteAdd(routeEntry);
+        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
+                                                  routeEntry);
+        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
 
         // Verify
         assertEquals(router.getRoutes().size(), 1);
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTestWithAsyncArp.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTestWithAsyncArp.java
index 0e1226e..46bcdd3 100644
--- a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTestWithAsyncArp.java
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/RouterTestWithAsyncArp.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -50,6 +51,7 @@
 import org.onlab.onos.net.host.HostService;
 import org.onlab.onos.net.host.InterfaceIpAddress;
 import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentOperations;
 import org.onlab.onos.net.intent.IntentService;
 import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
 import org.onlab.onos.net.intent.AbstractIntentTest;
@@ -196,7 +198,7 @@
      * This method tests adding a route entry.
      */
     @Test
-    public void testProcessRouteAdd() throws TestUtilsException {
+    public void testRouteAdd() throws TestUtilsException {
 
         // Construct a route entry
         RouteEntry routeEntry = new RouteEntry(
@@ -214,13 +216,18 @@
         replay(hostService);
 
         reset(intentService);
-        intentService.submit(TestIntentServiceHelper.eqExceptId(intent));
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addSubmitOperation(intent);
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
         replay(intentService);
 
-        // Call the processRouteAdd() method in Router class
+        // Call the processRouteUpdates() method in Router class
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        router.processRouteAdd(routeEntry);
+        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
+                                                  routeEntry);
+        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
 
         Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
                 MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
@@ -299,14 +306,22 @@
         replay(hostService);
 
         reset(intentService);
-        intentService.withdraw(TestIntentServiceHelper.eqExceptId(intent));
-        intentService.submit(TestIntentServiceHelper.eqExceptId(intentNew));
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addWithdrawOperation(intent.id());
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
+        builder = IntentOperations.builder(APPID);
+        builder.addSubmitOperation(intentNew);
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
         replay(intentService);
 
-        // Call the processRouteAdd() method in Router class
+        // Call the processRouteUpdates() method in Router class
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        router.processRouteAdd(routeEntryUpdate);
+        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
+                                                  routeEntryUpdate);
+        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
 
         Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
                 MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
@@ -334,7 +349,7 @@
      * This method tests deleting a route entry.
      */
     @Test
-    public void testProcessRouteDelete() throws TestUtilsException {
+    public void testRouteDelete() throws TestUtilsException {
 
         // Construct the existing route entry
         RouteEntry routeEntry = new RouteEntry(
@@ -351,13 +366,18 @@
 
         // Set up expectation
         reset(intentService);
-        intentService.withdraw(TestIntentServiceHelper.eqExceptId(intent));
+        IntentOperations.Builder builder = IntentOperations.builder(APPID);
+        builder.addWithdrawOperation(intent.id());
+        intentService.execute(TestIntentServiceHelper.eqExceptId(
+                                builder.build()));
         replay(intentService);
 
-        // Call route deleting method in Router class
+        // Call the processRouteUpdates() method in Router class
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
-        router.processRouteDelete(routeEntry);
+        RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
+                                                  routeEntry);
+        router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
 
         // Verify
         assertEquals(router.getRoutes().size(), 0);
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/SdnIpTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/SdnIpTest.java
index ab26766..4dfe3cc 100644
--- a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/SdnIpTest.java
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/SdnIpTest.java
@@ -236,9 +236,7 @@
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
 
         // Add route updates
-        for (RouteUpdate update : routeUpdates) {
-            router.processRouteAdd(update.routeEntry());
-        }
+        router.processRouteUpdates(routeUpdates);
 
         latch.await(5000, TimeUnit.MILLISECONDS);
 
@@ -304,17 +302,19 @@
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
 
         // Send the add updates first
-        for (RouteUpdate update : routeUpdates) {
-            router.processRouteAdd(update.routeEntry());
-        }
+        router.processRouteUpdates(routeUpdates);
 
         // Give some time to let the intents be submitted
         installCount.await(5000, TimeUnit.MILLISECONDS);
 
         // Send the DELETE updates
+        List<RouteUpdate> deleteRouteUpdates = new ArrayList<>();
         for (RouteUpdate update : routeUpdates) {
-            router.processRouteDelete(update.routeEntry());
+            RouteUpdate deleteUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
+                                                       update.routeEntry());
+            deleteRouteUpdates.add(deleteUpdate);
         }
+        router.processRouteUpdates(deleteRouteUpdates);
 
         deleteCount.await(5000, TimeUnit.MILLISECONDS);
 
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpSessionManagerTest.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpSessionManagerTest.java
index 5f8c075..8905289 100644
--- a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpSessionManagerTest.java
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/bgp/BgpSessionManagerTest.java
@@ -82,7 +82,7 @@
      */
     private class DummyRouteListener implements RouteListener {
         @Override
-        public void update(RouteUpdate routeUpdate) {
+        public void update(Collection<RouteUpdate> routeUpdate) {
             // Nothing to do
         }
     }