Restructured to separate stores and managers into different bundles. Reactive forwarding does not seem to work; will investigate.
diff --git a/core/api/src/main/java/org/onlab/onos/net/topology/DefaultGraphDescription.java b/core/api/src/main/java/org/onlab/onos/net/topology/DefaultGraphDescription.java
new file mode 100644
index 0000000..94a6abf
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/topology/DefaultGraphDescription.java
@@ -0,0 +1,87 @@
+package org.onlab.onos.net.topology;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.Device;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.Link;
+
+import java.util.Map;
+
+/**
+ * Default implementation of an immutable topology graph data carrier.
+ */
+public class DefaultGraphDescription implements GraphDescription {
+
+    private final long nanos;
+    private final ImmutableSet<TopologyVertex> vertexes;
+    private final ImmutableSet<TopologyEdge> edges;
+
+    private final Map<DeviceId, TopologyVertex> vertexesById = Maps.newHashMap();
+
+
+    /**
+     * Creates a minimal topology graph description to allow core to construct
+     * and process the topology graph.
+     *
+     * @param nanos   time in nanos of when the topology description was created
+     * @param devices collection of infrastructure devices
+     * @param links   collection of infrastructure links
+     */
+    public DefaultGraphDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) {
+        this.nanos = nanos;
+        this.vertexes = buildVertexes(devices);
+        this.edges = buildEdges(links);
+        vertexesById.clear();
+    }
+
+    @Override
+    public long timestamp() {
+        return nanos;
+    }
+
+    @Override
+    public ImmutableSet<TopologyVertex> vertexes() {
+        return vertexes;
+    }
+
+    @Override
+    public ImmutableSet<TopologyEdge> edges() {
+        return edges;
+    }
+
+    // Builds a set of topology vertexes from the specified list of devices
+    private ImmutableSet<TopologyVertex> buildVertexes(Iterable<Device> devices) {
+        ImmutableSet.Builder<TopologyVertex> vertexes = ImmutableSet.builder();
+        for (Device device : devices) {
+            TopologyVertex vertex = new DefaultTopologyVertex(device.id());
+            vertexes.add(vertex);
+            vertexesById.put(vertex.deviceId(), vertex);
+        }
+        return vertexes.build();
+    }
+
+    // Builds a set of topology vertexes from the specified list of links
+    private ImmutableSet<TopologyEdge> buildEdges(Iterable<Link> links) {
+        ImmutableSet.Builder<TopologyEdge> edges = ImmutableSet.builder();
+        for (Link link : links) {
+            edges.add(new DefaultTopologyEdge(vertexOf(link.src()),
+                                              vertexOf(link.dst()), link));
+        }
+        return edges.build();
+    }
+
+    // Fetches a vertex corresponding to the given connection point device.
+    private TopologyVertex vertexOf(ConnectPoint connectPoint) {
+        DeviceId id = connectPoint.deviceId();
+        TopologyVertex vertex = vertexesById.get(id);
+        if (vertex == null) {
+            // If vertex does not exist, create one and register it.
+            vertex = new DefaultTopologyVertex(id);
+            vertexesById.put(id, vertex);
+        }
+        return vertex;
+    }
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyEdge.java b/core/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyEdge.java
new file mode 100644
index 0000000..00eb3d2
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyEdge.java
@@ -0,0 +1,66 @@
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.Link;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of the topology edge backed by a link.
+ */
+public class DefaultTopologyEdge implements TopologyEdge {
+
+    private final Link link;
+    private final TopologyVertex src;
+    private final TopologyVertex dst;
+
+    /**
+     * Creates a new topology edge.
+     *
+     * @param src  source vertex
+     * @param dst  destination vertex
+     * @param link infrastructure link
+     */
+    public DefaultTopologyEdge(TopologyVertex src, TopologyVertex dst, Link link) {
+        this.src = src;
+        this.dst = dst;
+        this.link = link;
+    }
+
+    @Override
+    public Link link() {
+        return link;
+    }
+
+    @Override
+    public TopologyVertex src() {
+        return src;
+    }
+
+    @Override
+    public TopologyVertex dst() {
+        return dst;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(link);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof DefaultTopologyEdge) {
+            final DefaultTopologyEdge other = (DefaultTopologyEdge) obj;
+            return Objects.equals(this.link, other.link);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this).add("src", src).add("dst", dst).toString();
+    }
+
+}
+
diff --git a/core/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyVertex.java b/core/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyVertex.java
new file mode 100644
index 0000000..7bc231e
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/topology/DefaultTopologyVertex.java
@@ -0,0 +1,48 @@
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.DeviceId;
+
+import java.util.Objects;
+
+/**
+ * Implementation of the topology vertex backed by a device id.
+ */
+public class DefaultTopologyVertex implements TopologyVertex {
+
+    private final DeviceId deviceId;
+
+    /**
+     * Creates a new topology vertex.
+     *
+     * @param deviceId backing infrastructure device identifier
+     */
+    public DefaultTopologyVertex(DeviceId deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    @Override
+    public DeviceId deviceId() {
+        return deviceId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(deviceId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof DefaultTopologyVertex) {
+            final DefaultTopologyVertex other = (DefaultTopologyVertex) obj;
+            return Objects.equals(this.deviceId, other.deviceId);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return deviceId.toString();
+    }
+
+}
+