Merge "Support for expiring Database entries"
diff --git a/apps/demo/src/main/java/org/onlab/onos/demo/DemoInstaller.java b/apps/demo/src/main/java/org/onlab/onos/demo/DemoInstaller.java
index ca2d6db..758f628 100644
--- a/apps/demo/src/main/java/org/onlab/onos/demo/DemoInstaller.java
+++ b/apps/demo/src/main/java/org/onlab/onos/demo/DemoInstaller.java
@@ -31,6 +31,7 @@
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 import org.onlab.onos.net.host.HostService;
+import org.onlab.onos.net.intent.Constraint;
 import org.onlab.onos.net.intent.HostToHostIntent;
 import org.onlab.onos.net.intent.Intent;
 import org.onlab.onos.net.intent.IntentService;
@@ -113,14 +114,14 @@
         public void run() {
             TrafficSelector selector = DefaultTrafficSelector.builder().build();
             TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
-
+            List<Constraint> constraint = Lists.newArrayList();
             List<Host> hosts = Lists.newArrayList(hostService.getHosts());
             while (!hosts.isEmpty()) {
                 Host src = hosts.remove(0);
                 for (Host dst : hosts) {
                     HostToHostIntent intent = new HostToHostIntent(appId, src.id(), dst.id(),
                                                                    selector, treatment,
-                                                                   null);
+                                                                   constraint);
                     existingIntents.add(intent);
                     intentService.submit(intent);
                 }
diff --git a/core/api/src/main/java/org/onlab/onos/event/AbstractEvent.java b/core/api/src/main/java/org/onlab/onos/event/AbstractEvent.java
index 0fc8eaa..49fb268 100644
--- a/core/api/src/main/java/org/onlab/onos/event/AbstractEvent.java
+++ b/core/api/src/main/java/org/onlab/onos/event/AbstractEvent.java
@@ -26,7 +26,7 @@
 
     private final long time;
     private final T type;
-    private S subject;
+    private final S subject;
 
     /**
      * Creates an event of a given type and for the specified subject and the
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/TrafficSelector.java b/core/api/src/main/java/org/onlab/onos/net/flow/TrafficSelector.java
index e0c8c78..ac75147 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/TrafficSelector.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/TrafficSelector.java
@@ -60,6 +60,7 @@
 
         /**
          * Matches an inport.
+         *
          * @param port the inport
          * @return a selection builder
          */
@@ -67,6 +68,7 @@
 
         /**
          * Matches a l2 src address.
+         *
          * @param addr a l2 address
          * @return a selection builder
          */
@@ -74,6 +76,7 @@
 
         /**
          * Matches a l2 dst address.
+         *
          * @param addr a l2 address
          * @return a selection builder
          */
@@ -81,6 +84,7 @@
 
         /**
          * Matches the ethernet type.
+         *
          * @param ethType an ethernet type
          * @return a selection builder
          */
@@ -88,6 +92,7 @@
 
         /**
          * Matches the vlan id.
+         *
          * @param vlanId a vlan id
          * @return a selection builder
          */
@@ -95,6 +100,7 @@
 
         /**
          * Matches a vlan priority.
+         *
          * @param vlanPcp a vlan priority
          * @return a selection builder
          */
@@ -102,6 +108,7 @@
 
         /**
          * Matches the l3 protocol.
+         *
          * @param proto a l3 protocol
          * @return a selection builder
          */
@@ -109,6 +116,7 @@
 
         /**
          * Matches a l3 address.
+         *
          * @param ip a l3 address
          * @return a selection builder
          */
@@ -116,6 +124,7 @@
 
         /**
          * Matches a l3 address.
+         *
          * @param ip a l3 address
          * @return a selection builder
          */
@@ -123,6 +132,7 @@
 
         /**
          * Matches a TCP source port number.
+         *
          * @param tcpPort a TCP source port number
          * @return a selection builder
          */
@@ -130,6 +140,7 @@
 
         /**
          * Matches a TCP destination port number.
+         *
          * @param tcpPort a TCP destination port number
          * @return a selection builder
          */
@@ -137,6 +148,7 @@
 
         /**
          * Matches an optical signal ID or lambda.
+         *
          * @param lambda lamda
          * @return a selection builder
          */
@@ -144,6 +156,7 @@
 
         /**
          * Matches an optical Signal Type.
+         *
          * @param signalType signalType
          * @return a selection builder
          */
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/TrafficTreatment.java b/core/api/src/main/java/org/onlab/onos/net/flow/TrafficTreatment.java
index 20447ed..bbecae0 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/TrafficTreatment.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/TrafficTreatment.java
@@ -42,6 +42,7 @@
 
         /**
          * Adds an instruction to the builder.
+         *
          * @param instruction an instruction
          * @return a treatment builder
          */
@@ -54,6 +55,7 @@
 
         /**
          * Set the output port.
+         *
          * @param number the out port
          * @return a treatment builder
          */
@@ -61,6 +63,7 @@
 
         /**
          * Sets the src l2 address.
+         *
          * @param addr a macaddress
          * @return a treatment builder
          */
@@ -68,6 +71,7 @@
 
         /**
          * Sets the dst l2 address.
+         *
          * @param addr a macaddress
          * @return a treatment builder
          */
@@ -75,6 +79,7 @@
 
         /**
          * Sets the vlan id.
+         *
          * @param id a vlanid
          * @return a treatment builder
          */
@@ -82,6 +87,7 @@
 
         /**
          * Sets the vlan priority.
+         *
          * @param pcp a vlan priority
          * @return a treatment builder
          */
@@ -89,6 +95,7 @@
 
         /**
          * Sets the src l3 address.
+         *
          * @param addr an ip
          * @return a treatment builder
          */
@@ -96,6 +103,7 @@
 
         /**
          * Sets the dst l3 address.
+         *
          * @param addr an ip
          * @return a treatment builder
          */
@@ -103,6 +111,7 @@
 
         /**
          * Sets the optical channel ID or lambda.
+         *
          * @param lambda optical channel ID
          * @return a treatment builder
          */
diff --git a/core/api/src/test/java/org/onlab/onos/net/flow/FlowIdTest.java b/core/api/src/test/java/org/onlab/onos/net/flow/FlowIdTest.java
new file mode 100644
index 0000000..92c3bd0
--- /dev/null
+++ b/core/api/src/test/java/org/onlab/onos/net/flow/FlowIdTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onlab.onos.net.flow;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for flow id class.
+ */
+public class FlowIdTest {
+
+    final FlowId flowId1 = FlowId.valueOf(1);
+    final FlowId sameAsFlowId1 = FlowId.valueOf(1);
+    final FlowId flowId2 = FlowId.valueOf(2);
+
+    /**
+     * Checks that the DefaultFlowRule class is immutable.
+     */
+    @Test
+    public void testImmutability() {
+        assertThatClassIsImmutable(FlowId.class);
+    }
+
+    /**
+     * Checks the operation of equals(), hashCode and toString() methods.
+     */
+    @Test
+    public void testEquals() {
+        new EqualsTester()
+                .addEqualityGroup(flowId1, sameAsFlowId1)
+                .addEqualityGroup(flowId2)
+                .testEquals();
+    }
+
+    /**
+     * Checks the construction of a FlowId object.
+     */
+    @Test
+    public void testConstruction() {
+        final long flowIdValue = 7777L;
+        final FlowId flowId = FlowId.valueOf(flowIdValue);
+        assertThat(flowId, is(notNullValue()));
+        assertThat(flowId.value(), is(flowIdValue));
+    }
+}
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
index 9c196a2..2505be5 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
@@ -138,9 +138,6 @@
      * @return allocated resources if any are required, null otherwise
      */
     private LinkResourceAllocations allocateResources(PathIntent intent) {
-        if (intent.constraints() == null) {
-            return null;
-        }
         LinkResourceRequest.Builder builder =
                 DefaultLinkResourceRequest.builder(intent.id(), intent.path().links());
         for (Constraint constraint : intent.constraints()) {
diff --git a/tools/test/bin/old.json b/tools/test/bin/old.json
new file mode 100644
index 0000000..713efbf
--- /dev/null
+++ b/tools/test/bin/old.json
@@ -0,0 +1,387 @@
+{
+    "linkConfig": [
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:02",
+            "params": {
+                "nodeName1": "SFO-W10",
+                "nodeName2": "SJC-W10",
+                "numWaves": 80,
+                "port1": 50,
+                "port2": 30
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:03",
+            "params": {
+                "nodeName1": "SJC-W10",
+                "nodeName2": "LAX-W10",
+                "numWaves": 80,
+                "port1": 50,
+                "port2": 30
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:04",
+            "params": {
+                "nodeName1": "LAX-W10",
+                "nodeName2": "SDG-W10",
+                "numWaves": 80,
+                "port1": 50,
+                "port2": 50
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:05",
+            "params": {
+                "nodeName1": "SFO-W10",
+                "nodeName2": "MSP-M10",
+                "numWaves": 80,
+                "port1": 20,
+                "port2": 50
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:05",
+            "params": {
+                "nodeName1": "SJC-W10",
+                "nodeName2": "MSP-M10",
+                "numWaves": 80,
+                "port1": 20,
+                "port2": 20
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+            "params": {
+                "nodeName1": "LAX-W10",
+                "nodeName2": "DFW-M10",
+                "numWaves": 80,
+                "port1": 20,
+                "port2": 50
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:04",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+            "params": {
+                "nodeName1": "SDG-W10",
+                "nodeName2": "DFW-M10",
+                "numWaves": 80,
+                "port1": 20,
+                "port2": 20
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:05",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+            "params": {
+                "nodeName1": "MSP-M10",
+                "nodeName2": "DFW-M10",
+                "numWaves": 80,
+                "port1": 30,
+                "port2": 40
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:05",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:07",
+            "params": {
+                "nodeName1": "MSP-M10",
+                "nodeName2": "CHG-N10",
+                "numWaves": 80,
+                "port1": 40,
+                "port2": 50
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:06",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:08",
+            "params": {
+                "nodeName1": "DFW-M10",
+                "nodeName2": "IAD-M10",
+                "numWaves": 80,
+                "port1": 30,
+                "port2": 50
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:07",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:08",
+            "params": {
+                "nodeName1": "CHG-N10",
+                "nodeName2": "IAD-M10",
+                "numWaves": 80,
+                "port1": 20,
+                "port2": 30
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:07",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:09",
+            "params": {
+                "nodeName1": "CHG-N10",
+                "nodeName2": "JFK-M10",
+                "numWaves": 80,
+                "port1": 30,
+                "port2": 50
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:08",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
+            "params": {
+                "nodeName1": "IAD-M10",
+                "nodeName2": "ATL-S10",
+                "numWaves": 80,
+                "port1": 20,
+                "port2": 50
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:ff:09",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
+            "params": {
+                "nodeName1": "JFK-M10",
+                "nodeName2": "ATL-S10",
+                "numWaves": 80,
+                "port1": 20,
+                "port2": 20
+            },
+            "type": "wdmLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:00:01",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:01",
+            "params": {
+                "bandwidth": 100000,
+                "nodeName1": "SFO-R10",
+                "nodeName2": "SFO-W10",
+                "port1": 2,
+                "port2": 10
+            },
+            "type": "pktOptLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:00:02",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:04",
+            "params": {
+                "bandwidth": 100000,
+                "nodeName1": null,
+                "nodeName2": "SDG-W10",
+                "port1": 2,
+                "port2": 10
+            },
+            "type": "pktOptLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:00:03",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
+            "params": {
+                "bandwidth": 100000,
+                "nodeName1": "LAX-R10",
+                "nodeName2": "DFW-M10",
+                "port1": 2,
+                "port2": 10
+            },
+            "type": "pktOptLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:00:04",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:07",
+            "params": {
+                "bandwidth": 100000,
+                "nodeName1": "SDG-R10",
+                "nodeName2": "CHG-N10",
+                "port1": 2,
+                "port2": 10
+            },
+            "type": "pktOptLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:00:05",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:09",
+            "params": {
+                "bandwidth": 100000,
+                "nodeName1": null,
+                "nodeName2": "JFK-M10",
+                "port1": 2,
+                "port2": 10
+            },
+            "type": "pktOptLink"
+        },
+        {
+            "allowed": true,
+            "nodeDpid1": "00:00:ff:ff:ff:ff:00:06",
+            "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
+            "params": {
+                "bandwidth": 100000,
+                "nodeName1": null,
+                "nodeName2": "ATL-S10",
+                "port1": 2,
+                "port2": 10
+            },
+            "type": "pktOptLink"
+        }
+    ],
+    "switchConfig": [
+        {
+            "allowed": true,
+            "latitude": 37.6,
+            "longitude": 122.3,
+            "name": "SFO-W10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:01",
+            "params": {
+                "numRegen": 0
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 37.3,
+            "longitude": 121.9,
+            "name": "SJC-W10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:02",
+            "params": {
+                "numRegen": 0
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 33.9,
+            "longitude": 118.4,
+            "name": "LAX-W10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:03",
+            "params": {
+                "numRegen": 0
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 32.8,
+            "longitude": 117.1,
+            "name": "SDG-W10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:04",
+            "params": {
+                "numRegen": 3
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 44.8,
+            "longitude": 93.1,
+            "name": "MSP-M10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:05",
+            "params": {
+                "numRegen": 3
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 32.8,
+            "longitude": 97.1,
+            "name": "DFW-M10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:06",
+            "params": {
+                "numRegen": 3
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 41.8,
+            "longitude": 120.1,
+            "name": "CHG-N10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:07",
+            "params": {
+                "numRegen": 3
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 38.8,
+            "longitude": 77.1,
+            "name": "IAD-M10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:08",
+            "params": {
+                "numRegen": 3
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 40.8,
+            "longitude": 73.1,
+            "name": "JFK-M10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:09",
+            "params": {
+                "numRegen": 0
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 33.8,
+            "longitude": 84.1,
+            "name": "ATL-S10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:0A",
+            "params": {
+                "numRegen": 0
+            },
+            "type": "Roadm"
+        },
+        {
+            "allowed": true,
+            "latitude": 32.8,
+            "longitude": 97.1,
+            "name": "DFW-M10",
+            "nodeDpid": "00:00:ff:ff:ff:ff:ff:06",
+            "params": {
+                "numRegen": 3
+            },
+            "type": "Roadm"
+        }
+    ]
+}
diff --git a/tools/test/topos/oe-nonlinear-10.json b/tools/test/topos/oe-nonlinear-10.json
index 59c5b89..29086bb 100644
--- a/tools/test/topos/oe-nonlinear-10.json
+++ b/tools/test/topos/oe-nonlinear-10.json
@@ -4,61 +4,85 @@
             "uri": "of:0000ffffffffff01", "mac": "ffffffffffff01", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "SFO-W10",
             "annotations": { "latitude": 37.6, "longitude": 122.3, "optical.regens": 0 },
-            "ports": [ { "port": 10, "speed": 100000, "type": "FIBER" }, { "port": 20, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 10, "speed": 100000, "type": "FIBER" },
+            { "port": 20, "speed": 0, "type": "FIBER" },
+            { "port": 50, "speed":100000, "type": "FIBER" } ]
         },
         {
             "uri": "of:0000ffffffffff02", "mac": "ffffffffffff02", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "SJC-W10",
             "annotations": { "latitude": 37.3, "longitude": 121.9, "optical.regens": 0 },
-            "ports": [ { "port": 11, "speed": 100000, "type": "FIBER" }, { "port": 21, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 20, "speed": 100000, "type": "FIBER" },
+            { "port": 30, "speed": 0, "type": "FIBER" },
+            { "port": 50, "speed": 0, "type": "FIBER" } ]
         },
         {
             "uri": "of:0000ffffffffff03", "mac": "ffffffffffff03", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "LAX-W10",
             "annotations": { "latitude": 33.9, "longitude": 118.4, "optical.regens": 0 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" },
+            { "port": 50, "speed": 0, "type": "FIBER" },
+            { "port": 20, "speed": 0, "type": "FIBER" } ]
         },
         {
             "uri": "of:0000ffffffffff04", "mac": "ffffffffffff04", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "SDG-W10",
             "annotations": { "latitude": 32.8, "longitude": 117.1, "optical.regens": 3 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" },
+            { "port":50, "speed": 0, "type": "FIBER" },
+             { "port":20, "speed": 0, "type": "FIBER" }]
         },
         {
             "uri": "of:0000ffffffffff05", "mac": "ffffffffffff05", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "MSP-M10",
             "annotations": { "latitude": 44.8, "longitude": 93.1, "optical.regens": 3 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 20, "speed": 0, "type": "FIBER" },
+             { "port": 30, "speed": 0, "type": "FIBER" },
+             { "port": 40, "speed": 0, "type": "FIBER" },
+             { "port": 50, "speed": 0, "type": "FIBER" }]
         },
         {
             "uri": "of:0000ffffffffff06", "mac": "ffffffffffff06", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "DFW-M10",
             "annotations": { "latitude": 32.8, "longitude": 97.1, "optical.regens": 3 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+            { "port": 20, "speed": 0, "type": "FIBER" },
+             { "port": 30, "speed": 0, "type": "FIBER" },
+             { "port": 40, "speed": 0, "type": "FIBER" },
+             { "port": 50, "speed": 0, "type": "FIBER" }]
         },
         {
             "uri": "of:0000ffffffffff07", "mac": "ffffffffffff07", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "CHG-N10",
             "annotations": { "latitude": 41.8, "longitude": 120.1, "optical.regens": 3 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+            { "port": 20, "speed": 0, "type": "FIBER" },
+             { "port": 30, "speed": 0, "type": "FIBER" },
+             { "port": 50, "speed": 0, "type": "FIBER" }]
         },
         {
             "uri": "of:0000ffffffffff08", "mac": "ffffffffffff08", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "IAD-M10",
             "annotations": { "latitude": 38.8, "longitude": 77.1, "optical.regens": 3 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 20, "speed": 0, "type": "FIBER" },
+             { "port": 30, "speed": 0, "type": "FIBER" },
+             { "port": 50, "speed": 0, "type": "FIBER" }]
         },
         {
             "uri": "of:0000ffffffffff09", "mac": "ffffffffffff09", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "JFK-M10",
             "annotations": { "latitude": 40.8, "longitude": 73.1, "optical.regens": 0 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+            { "port": 20, "speed": 0, "type": "FIBER" },
+            { "port": 50, "speed": 0, "type": "FIBER" }]
         },
         {
             "uri": "of:0000ffffffffff0A", "mac": "ffffffffffff0A", "type": "ROADM",
             "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "ATL-S10",
             "annotations": { "latitude": 33.8, "longitude": 84.1, "optical.regens": 0 },
-            "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ]
+            "ports": [ { "port": 10, "speed": 0, "type": "FIBER" },
+            { "port": 20, "speed": 0, "type": "FIBER" },
+            { "port": 50, "speed": 0, "type": "FIBER" }]
         },
         {
             "uri": "of:0000ffffffff0001", "mac": "ffffffffff0001", "type": "SWITCH",
@@ -67,31 +91,31 @@
             "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
         },
         {
-            "uri": "of:0000ffffffff0003", "mac": "ffffffffff0003", "type": "SWITCH",
+            "uri": "of:0000ffffffff0002", "mac": "ffffffffff0003", "type": "SWITCH",
             "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "LAX-R10",
             "annotations": { "latitude": 33.9, "longitude": 118.4 },
             "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
         },
         {
-            "uri": "of:0000ffffffff0004", "mac": "ffffffffff0004", "type": "SWITCH",
+            "uri": "of:0000ffffffff0003", "mac": "ffffffffff0004", "type": "SWITCH",
             "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "SDG-R10",
             "annotations": { "latitude": 32.8, "longitude": 117.1 },
             "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
         },
         {
-            "uri": "of:0000ffffffff0007", "mac": "ffffffffff0007", "type": "SWITCH",
+            "uri": "of:0000ffffffff0004", "mac": "ffffffffff0007", "type": "SWITCH",
             "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "CHG-R10",
             "annotations": { "latitude": 41.8, "longitude": 120.1 },
             "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
         },
         {
-            "uri": "of:0000ffffffff0009", "mac": "ffffffffff0009", "type": "SWITCH",
+            "uri": "of:0000ffffffff0005", "mac": "ffffffffff0009", "type": "SWITCH",
             "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "JFK-R10",
             "annotations": { "latitude": 40.8, "longitude": 73.1 },
             "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
         },
         {
-            "uri": "of:0000ffffffff000A", "mac": "ffffffffff000A", "type": "SWITCH",
+            "uri": "of:0000ffffffff0006", "mac": "ffffffffff000A", "type": "SWITCH",
             "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "ATL-R10",
             "annotations": { "latitude": 33.8, "longitude": 84.1 },
             "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ]
diff --git a/tools/test/topos/onos.py b/tools/test/topos/onos.py
index 80a8005..6dca835 100755
--- a/tools/test/topos/onos.py
+++ b/tools/test/topos/onos.py
@@ -42,6 +42,7 @@
         # add default modules
         # TODO: consider an ordered set
         self.features = Set([ 'webconsole',
+                              'onos-rest',
                               'onos-api',
                               'onos-cli',
                               'onos-openflow' ])
@@ -63,6 +64,8 @@
         if self.inNamespace:
             instanceOpts = ( '-furl mvn:org.onlab.onos/onos-features/1.0.0-SNAPSHOT/xml/features '
                              '-s 8101' )
+            if self.ip is not None:
+                instanceOpts += (' -a %s' % self.IP() )
             self.userCmd( self.karafDir + 'bin/instance create %s %s' % ( instanceOpts, self.name ) )
             self.instanceDir = self.karafDir + 'instances/%s/' % self.name
         else:
diff --git a/tools/test/topos/optical-2.py b/tools/test/topos/optical-2.py
new file mode 100755
index 0000000..245d449
--- /dev/null
+++ b/tools/test/topos/optical-2.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+
+''' file: custom/optical.py '''
+from mininet.node import RemoteController
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.log import setLogLevel, info
+from mininet.util import irange
+
+switches = []
+
+class OpticalTopo( Topo ):
+
+    def build( self, n=6, tapStart=29 ):
+	global switches
+        # Add hosts and switches
+        hosts = []
+        switches = []
+        for i in irange( 1, n ):
+            h = self.addHost( 'h%d' % i )
+            s = self.addSwitch( 's%d' % i, dpid='0000ffffffff%04d' % i )
+            self.addLink( h, s )
+            hosts.append( h )
+            switches.append( s )
+
+        # Add optical tap interfaces
+        tapNum = tapStart
+        #for sw in switches:
+        #    self.addLink( sw, sw, intfName1='%s-eth0' % sw, intfName2='tap%d' % tapNum )
+	    #Add tap interface  up
+            #sudo ip link set dev tap25 up
+       #     tapNum += 1
+
+# if you use, sudo mn --custom custom/optical.py, then register the topo:
+#sudo mn --custom ~/mininet/custom/optical-2.py --topo optical,6 --controller=remote
+#sudo ./mininet/custom/optical-2.py
+topos = { 'optical': OpticalTopo }
+
+def installStaticFlows( net ):
+    for swName in [ 's1', 's2', 's3', 's4', 's5', 's6' ]:
+      info( 'Adding flows to %s...' % swName )
+      sw = net[ swName ]
+      sw.dpctl( 'add-flow', 'in_port=1,actions=output=2' )
+      sw.dpctl( 'add-flow', 'in_port=2,actions=output=1' )
+      info( sw.dpctl( 'dump-flows' ) )
+
+def run():
+    net = Mininet( topo=OpticalTopo(), controller=RemoteController )
+    net.start()
+    #installStaticFlows( net )
+    tapStart = 29
+    for sw in switches:
+        net.get(sw).attach( 'tap%d' %tapStart )
+        tapStart += 1
+    CLI( net )
+    net.stop()
+
+# if the script is run directly (sudo custom/optical.py):
+if __name__ == '__main__':
+    setLogLevel( 'info' )
+    run()
diff --git a/tools/test/topos/optical2.py b/tools/test/topos/optical2.py
new file mode 100644
index 0000000..8d171d6
--- /dev/null
+++ b/tools/test/topos/optical2.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+
+''' file: custom/optical.py '''
+
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.log import setLogLevel, info
+from mininet.link import Intf, Link
+from mininet.node import RemoteController
+
+class NullIntf( Intf ):
+    "A dummy interface with a blank name that doesn't do any configuration"
+    def __init__( self, name, **params ):
+        self.name = ''
+
+class NullLink( Link ):
+    "A dummy link that doesn't touch either interface"
+    def makeIntfPair( cls, intf1, intf2 ):
+        pass
+    def delete( self ):
+        pass
+
+class OpticalTopo(Topo):
+    def addIntf( self, switch, intfName ):
+        "Add intf intfName to switch"
+        self.addLink( switch, switch, cls=NullLink,
+                      intfName1=intfName, cls2=NullIntf )
+    def __init__(self):
+
+        # Initialize topology
+        Topo.__init__(self)
+
+        # Add hosts and switches
+        h1 = self.addHost('h1')
+        h2 = self.addHost('h2')
+        h3 = self.addHost('h3')
+        h4 = self.addHost('h4')
+        h5 = self.addHost('h5')
+        h6 = self.addHost('h6')
+
+        s1 = self.addSwitch('s1',dpid="0000ffffffff0001")
+        s2 = self.addSwitch('s2',dpid="0000ffffffff0002")
+        s3 = self.addSwitch('s3',dpid="0000ffffffff0003")
+        s4 = self.addSwitch('s4',dpid="0000ffffffff0004")
+        s5 = self.addSwitch('s5',dpid="0000ffffffff0005")
+        s6 = self.addSwitch('s6',dpid="0000ffffffff0006")
+
+
+        # Add links from hosts to OVS
+        self.addLink(s1, h1)
+        self.addLink(s2, h2)
+        self.addLink(s3, h3)
+        self.addLink(s4, h4)
+        self.addLink(s5, h5)
+        self.addLink(s6, h6)
+
+        # temporary packet link from s1 to s2 for testing
+        # self.addLink( s1, s2 )
+
+        # add links from ovs to linc-oe
+        # sorry about the syntax :(
+        self.addLink(s1, s1, intfName1='s1-eth0', intfName2='tap29')
+        self.addLink(s2, s2, intfName1='s2-eth0', intfName2='tap30')
+        self.addLink(s3, s3, intfName1='s3-eth0', intfName2='tap31')
+        self.addLink(s4, s4, intfName1='s4-eth0', intfName2='tap32')
+        self.addLink(s5, s5, intfName1='s5-eth0', intfName2='tap33')
+        self.addLink(s6, s6, intfName1='s6-eth0', intfName2='tap34')
+
+        #self.addLink(s1, s2, s3, s4, s5, s6)
+        #intfName1 = 'tap3', intfName\2 = 'tap4', intfName2 = 'tap5',
+        # intfName2 = 'tap6', intfName2 = 'tap7', intfName2 = 'tap8'
+
+    # if you use, sudo mn --custom custom/optical.py, then register the topo:
+topos = {'optical': ( lambda: OpticalTopo() )}
+
+def installStaticFlows(net):
+    for swName in ['s1', 's2', 's3', 's4', 's5', 's6']:
+        info('Adding flows to %s...' % swName)
+        sw = net[swName]
+        sw.dpctl('add-flow', 'in_port=1,actions=output=2')
+        sw.dpctl('add-flow', 'in_port=2,actions=output=1')
+        info(sw.dpctl('dump-flows'))
+
+
+def run():
+    c = RemoteController('c','10.1.8.147',6633)
+    net = Mininet( topo=OpticalTopo(),controller=None)
+    net.addController(c)
+    net.start()
+
+    # intf1 = Intf( 'tap3', node=net.nameToNode['s1'] )
+    # intf2 = Intf( 'tap4', node=net.nameToNode['s2'] )
+    # net.nameToNode['s1'].attach( intf1 )
+    # net.nameToNode['s2'].attach( intf2 )
+
+    #installStaticFlows( net )
+    CLI( net )
+    net.stop()
+
+# if the script is run directly (sudo custom/optical.py):
+if __name__ == '__main__':
+    setLogLevel('info')
+    run()
diff --git a/tools/test/topos/sys.config b/tools/test/topos/sys.config
new file mode 100644
index 0000000..2b999d3
--- /dev/null
+++ b/tools/test/topos/sys.config
@@ -0,0 +1,183 @@
+[{linc,
+     [{of_config,disabled},
+      {software_desc,<<"LINC-OE OpenFlow Software Switch 1.1">>},
+      {capable_switch_ports,
+          [{port,1,[{interface,"dummy"},{type,optical}]},
+           {port,2,[{interface,"dummy"},{type,optical}]},
+           {port,3,[{interface,"dummy"},{type,optical}]},
+           {port,4,[{interface,"dummy"},{type,optical}]},
+           {port,5,[{interface,"dummy"},{type,optical}]},
+           {port,6,[{interface,"dummy"},{type,optical}]},
+           {port,7,[{interface,"dummy"},{type,optical}]},
+           {port,8,[{interface,"dummy"},{type,optical}]},
+           {port,9,[{interface,"dummy"},{type,optical}]},
+           {port,10,[{interface,"dummy"},{type,optical}]},
+           {port,11,[{interface,"dummy"},{type,optical}]},
+           {port,12,[{interface,"dummy"},{type,optical}]},
+           {port,13,[{interface,"dummy"},{type,optical}]},
+           {port,14,[{interface,"dummy"},{type,optical}]},
+           {port,15,[{interface,"dummy"},{type,optical}]},
+           {port,16,[{interface,"dummy"},{type,optical}]},
+           {port,17,[{interface,"dummy"},{type,optical}]},
+           {port,18,[{interface,"dummy"},{type,optical}]},
+           {port,19,[{interface,"dummy"},{type,optical}]},
+           {port,20,[{interface,"dummy"},{type,optical}]},
+           {port,21,[{interface,"dummy"},{type,optical}]},
+           {port,22,[{interface,"dummy"},{type,optical}]},
+           {port,23,[{interface,"dummy"},{type,optical}]},
+           {port,24,[{interface,"dummy"},{type,optical}]},
+           {port,25,[{interface,"dummy"},{type,optical}]},
+           {port,26,[{interface,"dummy"},{type,optical}]},
+           {port,27,[{interface,"dummy"},{type,optical}]},
+           {port,28,[{interface,"dummy"},{type,optical}]},
+           {port,29,[{interface,"tap29"}]},
+           {port,30,[{interface,"tap30"}]},
+           {port,31,[{interface,"tap31"}]},
+           {port,32,[{interface,"tap32"}]},
+           {port,33,[{interface,"tap33"}]},
+           {port,34,[{interface,"tap34"}]}]},
+      {capable_switch_queues,[]},
+      {optical_links,
+          [{{1,50},{2,30}},
+           {{2,50},{3,30}},
+           {{3,50},{4,50}},
+           {{1,20},{5,50}},
+           {{2,20},{5,20}},
+           {{3,20},{6,50}},
+           {{4,20},{6,20}},
+           {{5,30},{6,40}},
+           {{5,40},{7,50}},
+           {{6,30},{8,50}},
+           {{7,20},{8,30}},
+           {{7,30},{9,50}},
+           {{8,20},{10,50}},
+           {{9,20},{10,20}}]},
+      {logical_switches,
+          [{switch,1,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:01"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,1,[{queues,[]},{port_no,50}]},
+                     {port,7,[{queues,[]},{port_no,20}]},
+                     {port,29,[{queues,[]},{port_no,10}]}]}]},
+           {switch,2,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:02"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,2,[{queues,[]},{port_no,30}]},
+                     {port,3,[{queues,[]},{port_no,50}]},
+                     {port,9,[{queues,[]},{port_no,20}]}]}]},
+           {switch,3,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:03"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,4,[{queues,[]},{port_no,30}]},
+                     {port,5,[{queues,[]},{port_no,50}]},
+                     {port,11,[{queues,[]},{port_no,20}]}]}]},
+           {switch,4,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:04"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,6,[{queues,[]},{port_no,50}]},
+                     {port,13,[{queues,[]},{port_no,20}]},
+                     {port,30,[{queues,[]},{port_no,10}]}]}]},
+           {switch,5,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:05"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,8,[{queues,[]},{port_no,50}]},
+                     {port,10,[{queues,[]},{port_no,20}]},
+                     {port,15,[{queues,[]},{port_no,30}]},
+                     {port,17,[{queues,[]},{port_no,40}]}]}]},
+           {switch,7,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:07"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,18,[{queues,[]},{port_no,50}]},
+                     {port,21,[{queues,[]},{port_no,20}]},
+                     {port,23,[{queues,[]},{port_no,30}]},
+                     {port,32,[{queues,[]},{port_no,10}]}]}]},
+           {switch,8,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:08"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,20,[{queues,[]},{port_no,50}]},
+                     {port,22,[{queues,[]},{port_no,30}]},
+                     {port,25,[{queues,[]},{port_no,20}]}]}]},
+           {switch,9,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:09"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,24,[{queues,[]},{port_no,50}]},
+                     {port,27,[{queues,[]},{port_no,20}]},
+                     {port,33,[{queues,[]},{port_no,10}]}]}]},
+           {switch,10,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:0A"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,26,[{queues,[]},{port_no,50}]},
+                     {port,28,[{queues,[]},{port_no,20}]},
+                     {port,34,[{queues,[]},{port_no,10}]}]}]},
+           {switch,6,
+               [{backend,linc_us4_oe},
+                {datapath_id,"00:00:ff:ff:ff:ff:ff:06"},
+                {controllers,[{"Switch0-Controller","10.1.8.147",6633,tcp}]},
+                {controllers_listener,disabled},
+                {queues_status,disabled},
+                {ports,
+                    [{port,12,[{queues,[]},{port_no,50}]},
+                     {port,14,[{queues,[]},{port_no,20}]},
+                     {port,16,[{queues,[]},{port_no,40}]},
+                     {port,19,[{queues,[]},{port_no,30}]},
+                     {port,31,[{queues,[]},{port_no,10}]}]}]}]}]},
+ {epcap,[{verbose,false},{stats_interval,10}]},
+ {enetconf,
+     [{capabilities,
+          [{base,{1,0}},
+           {base,{1,1}},
+           {startup,{1,0}},
+           {'writable-running',{1,0}}]},
+      {callback_module,linc_ofconfig},
+      {sshd_ip,any},
+      {sshd_port,1830},
+      {sshd_user_passwords,[{"linc","linc"}]}]},
+ {lager,
+     [{handlers,
+          [{lager_console_backend,info},
+           {lager_file_backend,
+               [{"log/error.log",error,10485760,"$D0",5},
+                {"log/console.log",info,10485760,"$D0",5}]}]}]},
+ {sasl,
+     [{sasl_error_logger,{file,"log/sasl-error.log"}},
+      {errlog_type,error},
+      {error_logger_mf_dir,"log/sasl"},
+      {error_logger_mf_maxbytes,10485760},
+      {error_logger_mf_maxfiles,5}]},
+ {sync,[{excluded_modules,[procket]}]}].
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/showPath_ex2.json b/web/gui/src/main/webapp/json/ev/_capture/rx/showPath_ex2.json
new file mode 100644
index 0000000..2a05249
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/showPath_ex2.json
@@ -0,0 +1,11 @@
+{
+  "event": "showPath",
+  "sid": 3,
+  "payload": {
+    "ids": [
+      "of:0000000000000007"
+    ],
+    "traffic": true
+  }
+}
+// what is the client supposed to do with this?
diff --git a/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex1_devs.json b/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex1_devs.json
new file mode 100644
index 0000000..725c15f
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex1_devs.json
@@ -0,0 +1,11 @@
+{
+  "event": "requestTraffic",
+  "sid": 6,
+  "payload": {
+    "ids": [
+      "of:0000000000000007",
+      "of:000000000000000c",
+      "of:000000000000000a"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex2_hosts.json b/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex2_hosts.json
new file mode 100644
index 0000000..84f17df
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex2_hosts.json
@@ -0,0 +1,12 @@
+{
+  "event": "requestTraffic",
+  "sid": 12,
+  "payload": {
+    "ids": [
+      "86:C3:7B:90:79:CD/-1",
+      "22:BA:28:81:FD:45/-1",
+      "BA:91:F6:8E:B6:B6/-1",
+      "06:E2:E6:F7:03:12/-1"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex3_devs_hosts.json b/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex3_devs_hosts.json
new file mode 100644
index 0000000..3f915df
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/tx/requestTraffic_ex3_devs_hosts.json
@@ -0,0 +1,12 @@
+{
+  "event": "requestTraffic",
+  "sid": 18,
+  "payload": {
+    "ids": [
+      "of:0000000000000001",
+      "86:C3:7B:90:79:CD/-1",
+      "7E:D2:EE:0F:12:4A/-1",
+      "of:000000000000000c"
+    ]
+  }
+}
diff --git a/web/gui/src/main/webapp/onos2.js b/web/gui/src/main/webapp/onos2.js
index 0644c32..7632148 100644
--- a/web/gui/src/main/webapp/onos2.js
+++ b/web/gui/src/main/webapp/onos2.js
@@ -115,7 +115,6 @@
         }
 
         function doError(msg) {
-            errorCount++;
             console.error(msg);
             doAlert(msg);
         }
diff --git a/web/gui/src/main/webapp/topo2.css b/web/gui/src/main/webapp/topo2.css
index 0dfa466..a8c67a1 100644
--- a/web/gui/src/main/webapp/topo2.css
+++ b/web/gui/src/main/webapp/topo2.css
@@ -139,6 +139,8 @@
 #topo-detail td.value {
 }
 
+
+
 #topo-detail hr {
     height: 1px;
     color: #ccc;
diff --git a/web/gui/src/main/webapp/topo2.js b/web/gui/src/main/webapp/topo2.js
index 48e4851..4c09b4d 100644
--- a/web/gui/src/main/webapp/topo2.js
+++ b/web/gui/src/main/webapp/topo2.js
@@ -127,7 +127,8 @@
         P: togglePorts,
         U: unpin,
 
-        Z: requestPath,
+        W: requestTraffic,  // bag of selections
+        Z: requestPath,     // host-to-host intent (and monitor)
         X: cancelMonitor
     };
 
@@ -199,7 +200,7 @@
 
     function abortIfLive() {
         if (config.useLiveData) {
-            scenario.view.alert("Sorry, currently using live data..");
+            network.view.alert("Sorry, currently using live data..");
             return true;
         }
         return false;
@@ -342,14 +343,18 @@
         addDevice: addDevice,
         addLink: addLink,
         addHost: addHost,
+
         updateDevice: updateDevice,
         updateLink: updateLink,
         updateHost: updateHost,
+
         removeDevice: stillToImplement,
         removeLink: removeLink,
         removeHost: removeHost,
+
         showDetails: showDetails,
-        showPath: showPath
+        showPath: showPath,
+        showTraffic: showTraffic
     };
 
     function addDevice(data) {
@@ -462,6 +467,7 @@
     function showDetails(data) {
         fnTrace('showDetails', data.payload.id);
         populateDetails(data.payload);
+        // TODO: Add single-select actions ...
         detailPane.show();
     }
 
@@ -484,6 +490,10 @@
         // TODO: add selection-highlite lines to links
     }
 
+    function showTraffic(data) {
+        network.view.alert("showTraffic() -- TODO")
+    }
+
     // ...............................
 
     function stillToImplement(data) {
@@ -504,24 +514,58 @@
     // ==============================
     // Out-going messages...
 
+    function userFeedback(msg) {
+        // for now, use the alert pane as is. Maybe different alert style in
+        // the future (centered on view; dismiss button?)
+        network.view.alert(msg);
+    }
+
+    function nSel() {
+        return selectOrder.length;
+    }
     function getSel(idx) {
         return selections[selectOrder[idx]];
     }
+    function getSelId(idx) {
+        return getSel(idx).obj.id;
+    }
+    function allSelectionsClass(cls) {
+        for (var i=0, n=nSel(); i<n; i++) {
+            if (getSel(i).obj.class !== cls) {
+                return false;
+            }
+        }
+        return true;
+    }
 
-    // for now, just a host-to-host intent, (and implicit start-monitoring)
+    function requestTraffic() {
+        if (nSel() > 0) {
+            sendMessage('requestTraffic', {
+                ids: selectOrder
+            });
+        } else {
+            userFeedback('Request-Traffic requires one or\n' +
+                         'more items to be selected.');
+        }
+    }
+
     function requestPath() {
-        var payload = {
-                one: getSel(0).obj.id,
-                two: getSel(1).obj.id
-            };
-        sendMessage('requestPath', payload);
+        if (nSel() === 2 && allSelectionsClass('host')) {
+            sendMessage('requestPath', {
+                one: getSelId(0),
+                two: getSelId(1)
+            });
+        } else {
+            userFeedback('Request-Path requires two\n' +
+                'hosts to be selected.');
+        }
     }
 
     function cancelMonitor() {
-        var payload = {
-                id: "need_the_intent_id"  // FIXME: where are we storing this?
-            };
-        sendMessage('cancelMonitor', payload);
+        // FIXME: from where do we get the intent id(s) to send to the server?
+        sendMessage('cancelMonitor', {
+            ids: ["need_the_intent_id"]
+        });
     }
 
     // request details for the selected element
@@ -1200,12 +1244,43 @@
 
     function singleSelect() {
         requestDetails();
-        // NOTE: detail pane will be shown from showDetails event.
+        // NOTE: detail pane will be shown from showDetails event callback
     }
 
     function multiSelect() {
-        // TODO: use detail pane for multi-select view.
-        //detailPane.show();
+        populateMultiSelect();
+        // TODO: Add multi-select actions ...
+    }
+
+    function addSep(tbody) {
+        var tr = tbody.append('tr');
+        $('<hr>').appendTo(tr.append('td').attr('colspan', 2));
+    }
+
+    function addProp(tbody, label, value) {
+        var tr = tbody.append('tr');
+
+        tr.append('td')
+            .attr('class', 'label')
+            .text(label + ' :');
+
+        tr.append('td')
+            .attr('class', 'value')
+            .text(value);
+    }
+
+    function populateMultiSelect() {
+        detailPane.empty();
+
+        var title = detailPane.append("h2"),
+            table = detailPane.append("table"),
+            tbody = table.append("tbody");
+
+        title.text('Multi-Select...');
+
+        selectOrder.forEach(function (d, i) {
+            addProp(tbody, i+1, d);
+        });
     }
 
     function populateDetails(data) {
@@ -1225,23 +1300,6 @@
                 addProp(tbody, p, data.props[p]);
             }
         });
-
-        function addSep(tbody) {
-            var tr = tbody.append('tr');
-            $('<hr>').appendTo(tr.append('td').attr('colspan', 2));
-        }
-
-        function addProp(tbody, label, value) {
-            var tr = tbody.append('tr');
-
-            tr.append('td')
-                .attr('class', 'label')
-                .text(label + ' :');
-
-            tr.append('td')
-                .attr('class', 'value')
-                .text(value);
-        }
     }
 
     // ==============================
@@ -1290,8 +1348,6 @@
     function preload(view, ctx, flags) {
         var w = view.width(),
             h = view.height(),
-            idBg = view.uid('bg'),
-            showBg = config.options.showBackground ? 'visible' : 'hidden',
             fcfg = config.force,
             fpad = fcfg.pad,
             forceDim = [w - 2*fpad, h - 2*fpad];
@@ -1306,20 +1362,9 @@
         // add blue glow filter to svg layer
         d3u.appendGlow(svg);
 
-        // load the background image
-        bgImg = svg.append('svg:image')
-            .attr({
-                id: idBg,
-                width: w,
-                height: h,
-                'xlink:href': config.backgroundUrl
-            })
-            .style({
-                visibility: showBg
-            });
-
         // group for the topology
         topoG = svg.append('g')
+            .attr('id', 'topo-G')
             .attr('transform', fcfg.translate());
 
         // subgroups for links and nodes
@@ -1402,14 +1447,78 @@
         view.setRadio(btnSet);
         view.setKeys(keyDispatch);
 
-        if (config.useLiveData) {
-            webSock.connect();
+        // Load map data asynchronously; complete startup after that..
+        loadGeoJsonData();
+    }
+
+    // TODO: move these to config/state portion of script
+    var geoJsonUrl = 'geoUsa.json',     // TODO: Paul
+        geoJson;
+
+    function loadGeoJsonData() {
+        d3.json(geoJsonUrl, function (err, data) {
+            if (err) {
+                // fall back to USA map background
+                loadStaticMap();
+            } else {
+                geoJson = data;
+                loadGeoMap();
+            }
+
+            // finally, connect to the server...
+            if (config.useLiveData) {
+                webSock.connect();
+            }
+        });
+    }
+
+    function showBg() {
+        return config.options.showBackground ? 'visible' : 'hidden';
+    }
+
+    function loadStaticMap() {
+        fnTrace('loadStaticMap', config.backgroundUrl);
+        var w = network.view.width(),
+            h = network.view.height();
+
+        // load the background image
+        bgImg = svg.insert('svg:image', '#topo-G')
+            .attr({
+                id: 'topo-bg',
+                width: w,
+                height: h,
+                'xlink:href': config.backgroundUrl
+            })
+            .style({
+                visibility: showBg()
+            });
+    }
+
+    function loadGeoMap() {
+        fnTrace('loadGeoMap', geoJsonUrl);
+        var w = network.view.width(),
+            h = network.view.height();
+
+        // TODO: load map layer from GeoJSON stored in 'geoJson' var...
+        // bgImg = svg.insert('<svg-element-type>', '#topo-G') ...
+
+        // TODO: Paul
+    }
+
+    function resizeBg(view) {
+        if (geoJson) {
+            // TODO : resize GeoJSON map
+
+            // TODO: Paul
+
+        } else if (bgImg) {
+            setSize(bgImg, view);
         }
     }
 
     function resize(view, ctx, flags) {
         setSize(svg, view);
-        setSize(bgImg, view);
+        resizeBg(view);
 
         // TODO: hook to recompute layout, perhaps? work with zoom/pan code
         // adjust force layout size