tom

Refactored the topology provider.

1 +package org.onlab.onos.net.trivial.topology.provider.impl;
2 +
3 +import org.onlab.onos.net.Link;
4 +import org.onlab.onos.net.topology.TopoEdge;
5 +import org.onlab.onos.net.topology.TopoVertex;
6 +
7 +import java.util.Objects;
8 +
9 +import static com.google.common.base.MoreObjects.toStringHelper;
10 +
11 +/**
12 + * Implementation of the topology edge backed by a link.
13 + */
14 +class DefaultTopoEdge implements TopoEdge {
15 +
16 + private final Link link;
17 + private final TopoVertex src;
18 + private final TopoVertex dst;
19 +
20 + /**
21 + * Creates a new topology edge.
22 + *
23 + * @param src source vertex
24 + * @param dst destination vertex
25 + * @param link infrastructure link
26 + */
27 + DefaultTopoEdge(TopoVertex src, TopoVertex dst, Link link) {
28 + this.src = src;
29 + this.dst = dst;
30 + this.link = link;
31 + }
32 +
33 + @Override
34 + public Link link() {
35 + return link;
36 + }
37 +
38 + @Override
39 + public TopoVertex src() {
40 + return src;
41 + }
42 +
43 + @Override
44 + public TopoVertex dst() {
45 + return dst;
46 + }
47 +
48 + @Override
49 + public int hashCode() {
50 + return Objects.hash(link);
51 + }
52 +
53 + @Override
54 + public boolean equals(Object obj) {
55 + if (obj instanceof DefaultTopoEdge) {
56 + final DefaultTopoEdge other = (DefaultTopoEdge) obj;
57 + return Objects.equals(this.link, other.link);
58 + }
59 + return false;
60 + }
61 +
62 + @Override
63 + public String toString() {
64 + return toStringHelper(this).add("src", src).add("dst", dst).toString();
65 + }
66 +
67 +}
68 +
1 +package org.onlab.onos.net.trivial.topology.provider.impl;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +import org.onlab.onos.net.topology.TopoVertex;
5 +
6 +import java.util.Objects;
7 +
8 +/**
9 + * Implementation of the topology vertex backed by a device id.
10 + */
11 +class DefaultTopoVertex implements TopoVertex {
12 +
13 + private final DeviceId deviceId;
14 +
15 + /**
16 + * Creates a new topology vertex.
17 + *
18 + * @param deviceId backing infrastructure device identifier
19 + */
20 + DefaultTopoVertex(DeviceId deviceId) {
21 + this.deviceId = deviceId;
22 + }
23 +
24 + @Override
25 + public DeviceId deviceId() {
26 + return deviceId;
27 + }
28 +
29 + @Override
30 + public int hashCode() {
31 + return Objects.hash(deviceId);
32 + }
33 +
34 + @Override
35 + public boolean equals(Object obj) {
36 + if (obj instanceof DefaultTopoVertex) {
37 + final DefaultTopoVertex other = (DefaultTopoVertex) obj;
38 + return Objects.equals(this.deviceId, other.deviceId);
39 + }
40 + return false;
41 + }
42 +
43 + @Override
44 + public String toString() {
45 + return deviceId.toString();
46 + }
47 +
48 +}
49 +
1 package org.onlab.onos.net.trivial.topology.provider.impl; 1 package org.onlab.onos.net.trivial.topology.provider.impl;
2 2
3 import com.google.common.collect.ImmutableSet; 3 import com.google.common.collect.ImmutableSet;
4 +import com.google.common.collect.ImmutableSetMultimap;
4 import com.google.common.collect.Maps; 5 import com.google.common.collect.Maps;
5 -import com.google.common.collect.Multimap;
6 import com.google.common.collect.Sets; 6 import com.google.common.collect.Sets;
7 import org.onlab.graph.AdjacencyListsGraph; 7 import org.onlab.graph.AdjacencyListsGraph;
8 import org.onlab.graph.DijkstraGraphSearch; 8 import org.onlab.graph.DijkstraGraphSearch;
...@@ -21,13 +21,11 @@ import org.onlab.onos.net.topology.TopoVertex; ...@@ -21,13 +21,11 @@ import org.onlab.onos.net.topology.TopoVertex;
21 import org.onlab.onos.net.topology.TopologyCluster; 21 import org.onlab.onos.net.topology.TopologyCluster;
22 import org.onlab.onos.net.topology.TopologyDescription; 22 import org.onlab.onos.net.topology.TopologyDescription;
23 23
24 -import java.util.HashSet;
25 import java.util.List; 24 import java.util.List;
26 import java.util.Map; 25 import java.util.Map;
27 -import java.util.Objects;
28 import java.util.Set; 26 import java.util.Set;
29 27
30 -import static com.google.common.base.MoreObjects.toStringHelper; 28 +import static com.google.common.collect.ImmutableSetMultimap.Builder;
31 import static org.onlab.graph.GraphPathSearch.Result; 29 import static org.onlab.graph.GraphPathSearch.Result;
32 import static org.onlab.graph.TarjanGraphSearch.SCCResult; 30 import static org.onlab.graph.TarjanGraphSearch.SCCResult;
33 import static org.onlab.onos.net.Link.Type.INDIRECT; 31 import static org.onlab.onos.net.Link.Type.INDIRECT;
...@@ -49,16 +47,16 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -49,16 +47,16 @@ class DefaultTopologyDescription implements TopologyDescription {
49 private final Map<ClusterId, TopologyCluster> clusters; 47 private final Map<ClusterId, TopologyCluster> clusters;
50 48
51 // Secondary look-up indexes 49 // Secondary look-up indexes
52 - private Multimap<ClusterId, DeviceId> devicesByCluster; 50 + private ImmutableSetMultimap<ClusterId, DeviceId> devicesByCluster;
53 - private Multimap<ClusterId, Link> linksByCluster; 51 + private ImmutableSetMultimap<ClusterId, Link> linksByCluster;
54 - private Map<DeviceId, TopologyCluster> clustersByDevice; 52 + private Map<DeviceId, TopologyCluster> clustersByDevice = Maps.newHashMap();
55 53
56 /** 54 /**
57 * Creates a topology description to carry topology vitals to the core. 55 * Creates a topology description to carry topology vitals to the core.
58 * 56 *
59 * @param nanos time in nanos of when the topology description was created 57 * @param nanos time in nanos of when the topology description was created
60 - * @param devices collection of devices 58 + * @param devices collection of infrastructure devices
61 - * @param links 59 + * @param links collection of infrastructure links
62 */ 60 */
63 DefaultTopologyDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) { 61 DefaultTopologyDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) {
64 this.nanos = nanos; 62 this.nanos = nanos;
...@@ -67,22 +65,81 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -67,22 +65,81 @@ class DefaultTopologyDescription implements TopologyDescription {
67 this.clusters = computeClusters(); 65 this.clusters = computeClusters();
68 } 66 }
69 67
68 + @Override
69 + public long timestamp() {
70 + return nanos;
71 + }
72 +
73 + @Override
74 + public Graph<TopoVertex, TopoEdge> graph() {
75 + return graph;
76 + }
77 +
78 + @Override
79 + public Result<TopoVertex, TopoEdge> pathResults(DeviceId srcDeviceId) {
80 + return results.get(srcDeviceId);
81 + }
82 +
83 + @Override
84 + public Set<TopologyCluster> clusters() {
85 + return ImmutableSet.copyOf(clusters.values());
86 + }
87 +
88 + @Override
89 + public Set<DeviceId> clusterDevices(TopologyCluster cluster) {
90 + return devicesByCluster.get(cluster.id());
91 + }
92 +
93 + @Override
94 + public Set<Link> clusterLinks(TopologyCluster cluster) {
95 + return linksByCluster.get(cluster.id());
96 + }
97 +
98 + @Override
99 + public TopologyCluster clusterFor(DeviceId deviceId) {
100 + return clustersByDevice.get(deviceId);
101 + }
102 +
103 +
104 + // Link weight for measuring link cost as hop count with indirect links
105 + // being as expensive as traversing the entire graph to assume the worst.
106 + private static class HopCountLinkWeight implements LinkWeight {
107 + private final int indirectLinkCost;
108 +
109 + HopCountLinkWeight(int indirectLinkCost) {
110 + this.indirectLinkCost = indirectLinkCost;
111 + }
112 +
113 + @Override
114 + public double weight(TopoEdge edge) {
115 + // To force preference to use direct paths first, make indirect
116 + // links as expensive as the linear vertex traversal.
117 + return edge.link().type() == INDIRECT ? indirectLinkCost : 1;
118 + }
119 + }
120 +
121 + // Link weight for preventing traversal over indirect links.
122 + private static class NoIndirectLinksWeight implements LinkWeight {
123 + @Override
124 + public double weight(TopoEdge edge) {
125 + return edge.link().type() == INDIRECT ? -1 : 1;
126 + }
127 + }
128 +
70 // Constructs the topology graph using the supplied devices and links. 129 // Constructs the topology graph using the supplied devices and links.
71 private Graph<TopoVertex, TopoEdge> buildGraph(Iterable<Device> devices, 130 private Graph<TopoVertex, TopoEdge> buildGraph(Iterable<Device> devices,
72 Iterable<Link> links) { 131 Iterable<Link> links) {
73 - Graph<TopoVertex, TopoEdge> graph = 132 + return new AdjacencyListsGraph<>(buildVertexes(devices),
74 - new AdjacencyListsGraph<>(buildVertexes(devices), 133 + buildEdges(links));
75 - buildEdges(links));
76 - return graph;
77 } 134 }
78 135
79 // Builds a set of topology vertexes from the specified list of devices 136 // Builds a set of topology vertexes from the specified list of devices
80 private Set<TopoVertex> buildVertexes(Iterable<Device> devices) { 137 private Set<TopoVertex> buildVertexes(Iterable<Device> devices) {
81 Set<TopoVertex> vertexes = Sets.newHashSet(); 138 Set<TopoVertex> vertexes = Sets.newHashSet();
82 for (Device device : devices) { 139 for (Device device : devices) {
83 - TopoVertex vertex = new TVertex(device.id()); 140 + TopoVertex vertex = new DefaultTopoVertex(device.id());
84 - vertexesById.put(vertex.deviceId(), vertex);
85 vertexes.add(vertex); 141 vertexes.add(vertex);
142 + vertexesById.put(vertex.deviceId(), vertex);
86 } 143 }
87 return vertexes; 144 return vertexes;
88 } 145 }
...@@ -91,7 +148,8 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -91,7 +148,8 @@ class DefaultTopologyDescription implements TopologyDescription {
91 private Set<TopoEdge> buildEdges(Iterable<Link> links) { 148 private Set<TopoEdge> buildEdges(Iterable<Link> links) {
92 Set<TopoEdge> edges = Sets.newHashSet(); 149 Set<TopoEdge> edges = Sets.newHashSet();
93 for (Link link : links) { 150 for (Link link : links) {
94 - edges.add(new TEdge(vertexOf(link.src()), vertexOf(link.dst()), link)); 151 + edges.add(new DefaultTopoEdge(vertexOf(link.src()),
152 + vertexOf(link.dst()), link));
95 } 153 }
96 return edges; 154 return edges;
97 } 155 }
...@@ -119,6 +177,9 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -119,6 +177,9 @@ class DefaultTopologyDescription implements TopologyDescription {
119 List<Set<TopoVertex>> clusterVertexes = result.clusterVertexes(); 177 List<Set<TopoVertex>> clusterVertexes = result.clusterVertexes();
120 List<Set<TopoEdge>> clusterEdges = result.clusterEdges(); 178 List<Set<TopoEdge>> clusterEdges = result.clusterEdges();
121 179
180 + Builder<ClusterId, DeviceId> devicesBuilder = ImmutableSetMultimap.builder();
181 + Builder<ClusterId, Link> linksBuilder = ImmutableSetMultimap.builder();
182 +
122 // Scan over the lists and create a cluster from the results. 183 // Scan over the lists and create a cluster from the results.
123 for (int i = 0, n = result.clusterCount(); i < n; i++) { 184 for (int i = 0, n = result.clusterCount(); i < n; i++) {
124 Set<TopoVertex> vertexSet = clusterVertexes.get(i); 185 Set<TopoVertex> vertexSet = clusterVertexes.get(i);
...@@ -128,29 +189,32 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -128,29 +189,32 @@ class DefaultTopologyDescription implements TopologyDescription {
128 new DefaultTopologyCluster(ClusterId.clusterId(i), 189 new DefaultTopologyCluster(ClusterId.clusterId(i),
129 vertexSet.size(), edgeSet.size(), 190 vertexSet.size(), edgeSet.size(),
130 findRoot(vertexSet).deviceId()); 191 findRoot(vertexSet).deviceId());
131 - 192 + findClusterDevices(vertexSet, cluster, devicesBuilder);
132 - findClusterDevices(vertexSet, cluster); 193 + findClusterLinks(edgeSet, cluster, linksBuilder);
133 - findClusterLinks(edgeSet, cluster);
134 } 194 }
135 return clusters; 195 return clusters;
136 } 196 }
137 197
138 - // Scan through the set of cluster vertices and convert it to a set of 198 + // Scans through the set of cluster vertexes and puts their devices in a
139 - // device ids; register the cluster by device id as well. 199 + // multi-map associated with the cluster. It also binds the devices to
200 + // the cluster.
140 private void findClusterDevices(Set<TopoVertex> vertexSet, 201 private void findClusterDevices(Set<TopoVertex> vertexSet,
141 - DefaultTopologyCluster cluster) { 202 + DefaultTopologyCluster cluster,
142 - Set<DeviceId> ids = new HashSet<>(vertexSet.size()); 203 + Builder<ClusterId, DeviceId> builder) {
143 - for (TopoVertex v : vertexSet) { 204 + for (TopoVertex vertex : vertexSet) {
144 - DeviceId deviceId = v.deviceId(); 205 + DeviceId deviceId = vertex.deviceId();
145 - devicesByCluster.put(cluster.id(), deviceId); 206 + builder.put(cluster.id(), deviceId);
146 clustersByDevice.put(deviceId, cluster); 207 clustersByDevice.put(deviceId, cluster);
147 } 208 }
148 } 209 }
149 210
211 + // Scans through the set of cluster edges and puts their links in a
212 + // multi-map associated with the cluster.
150 private void findClusterLinks(Set<TopoEdge> edgeSet, 213 private void findClusterLinks(Set<TopoEdge> edgeSet,
151 - DefaultTopologyCluster cluster) { 214 + DefaultTopologyCluster cluster,
152 - for (TopoEdge e : edgeSet) { 215 + Builder<ClusterId, Link> builder) {
153 - linksByCluster.put(cluster.id(), e.link()); 216 + for (TopoEdge edge : edgeSet) {
217 + builder.put(cluster.id(), edge.link());
154 } 218 }
155 } 219 }
156 220
...@@ -174,151 +238,10 @@ class DefaultTopologyDescription implements TopologyDescription { ...@@ -174,151 +238,10 @@ class DefaultTopologyDescription implements TopologyDescription {
174 TopoVertex vertex = vertexesById.get(id); 238 TopoVertex vertex = vertexesById.get(id);
175 if (vertex == null) { 239 if (vertex == null) {
176 // If vertex does not exist, create one and register it. 240 // If vertex does not exist, create one and register it.
177 - vertex = new TVertex(id); 241 + vertex = new DefaultTopoVertex(id);
178 vertexesById.put(id, vertex); 242 vertexesById.put(id, vertex);
179 } 243 }
180 return vertex; 244 return vertex;
181 } 245 }
182 246
183 - @Override
184 - public long timestamp() {
185 - return nanos;
186 - }
187 -
188 - @Override
189 - public Graph<TopoVertex, TopoEdge> graph() {
190 - return graph;
191 - }
192 -
193 - @Override
194 - public Result<TopoVertex, TopoEdge> pathResults(DeviceId srcDeviceId) {
195 - return results.get(srcDeviceId);
196 - }
197 -
198 - @Override
199 - public Set<TopologyCluster> clusters() {
200 - return ImmutableSet.copyOf(clusters.values());
201 - }
202 -
203 - @Override
204 - public Set<DeviceId> clusterDevices(TopologyCluster cluster) {
205 - return null; // clusterDevices.get(cluster.id());
206 - }
207 -
208 - @Override
209 - public Set<Link> clusterLinks(TopologyCluster cluster) {
210 - return null; // clusterLinks.get(cluster.id());
211 - }
212 -
213 - @Override
214 - public TopologyCluster clusterFor(DeviceId deviceId) {
215 - return null; // deviceClusters.get(deviceId);
216 - }
217 -
218 - // Implementation of the topology vertex backed by a device id
219 - private static class TVertex implements TopoVertex {
220 -
221 - private final DeviceId deviceId;
222 -
223 - public TVertex(DeviceId deviceId) {
224 - this.deviceId = deviceId;
225 - }
226 -
227 - @Override
228 - public DeviceId deviceId() {
229 - return deviceId;
230 - }
231 -
232 - @Override
233 - public int hashCode() {
234 - return Objects.hash(deviceId);
235 - }
236 -
237 - @Override
238 - public boolean equals(Object obj) {
239 - if (obj instanceof TVertex) {
240 - final TVertex other = (TVertex) obj;
241 - return Objects.equals(this.deviceId, other.deviceId);
242 - }
243 - return false;
244 - }
245 -
246 - @Override
247 - public String toString() {
248 - return deviceId.toString();
249 - }
250 - }
251 -
252 - // Implementation of the topology edge backed by a link
253 - private class TEdge implements TopoEdge {
254 - private final Link link;
255 - private final TopoVertex src;
256 - private final TopoVertex dst;
257 -
258 - public TEdge(TopoVertex src, TopoVertex dst, Link link) {
259 - this.src = src;
260 - this.dst = dst;
261 - this.link = link;
262 - }
263 -
264 - @Override
265 - public Link link() {
266 - return link;
267 - }
268 -
269 - @Override
270 - public TopoVertex src() {
271 - return src;
272 - }
273 -
274 - @Override
275 - public TopoVertex dst() {
276 - return dst;
277 - }
278 -
279 - @Override
280 - public int hashCode() {
281 - return Objects.hash(link);
282 - }
283 -
284 - @Override
285 - public boolean equals(Object obj) {
286 - if (obj instanceof TEdge) {
287 - final TEdge other = (TEdge) obj;
288 - return Objects.equals(this.link, other.link);
289 - }
290 - return false;
291 - }
292 -
293 - @Override
294 - public String toString() {
295 - return toStringHelper(this).add("src", src).add("dst", dst).toString();
296 - }
297 - }
298 -
299 - // Link weight for measuring link cost as hop count with indirect links
300 - // being as expensive as traversing the entire graph to assume the worst.
301 - private static class HopCountLinkWeight implements LinkWeight {
302 - private final int indirectLinkCost;
303 -
304 - public HopCountLinkWeight(int indirectLinkCost) {
305 - this.indirectLinkCost = indirectLinkCost;
306 - }
307 -
308 - @Override
309 - public double weight(TopoEdge edge) {
310 - // To force preference to use direct paths first, make indirect
311 - // links as expensive as the linear vertex traversal.
312 - return edge.link().type() == INDIRECT ? indirectLinkCost : 1;
313 - }
314 - }
315 -
316 - // Link weight for preventing traversal over indirect links.
317 - private static class NoIndirectLinksWeight implements LinkWeight {
318 - @Override
319 - public double weight(TopoEdge edge) {
320 - return edge.link().type() == INDIRECT ? -1 : 1;
321 - }
322 - }
323 -
324 } 247 }
......
...@@ -115,7 +115,6 @@ public class SimpleTopologyProvider extends AbstractProvider ...@@ -115,7 +115,6 @@ public class SimpleTopologyProvider extends AbstractProvider
115 // Builds the topology using the latest device and link information 115 // Builds the topology using the latest device and link information
116 // and citing the specified events as reasons for the change. 116 // and citing the specified events as reasons for the change.
117 private void buildTopology(List<Event> reasons) { 117 private void buildTopology(List<Event> reasons) {
118 - log.info("YO! Computing topology");
119 if (isStarted) { 118 if (isStarted) {
120 TopologyDescription desc = 119 TopologyDescription desc =
121 new DefaultTopologyDescription(System.nanoTime(), 120 new DefaultTopologyDescription(System.nanoTime(),
......