Nikhil Cheerla
Committed by Thomas Vachuska

[Emu] Disjoint Path Utils Exposed (to DefaultTopology)

Change-Id: I1d59d7a5a89618bd7419f00a0da674e87fe9bdb3
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net;
18 +
19 +import org.onosproject.net.provider.ProviderId;
20 +
21 +import java.util.List;
22 +import java.util.Objects;
23 +import static com.google.common.collect.ImmutableSet.of;
24 +
25 +/**
26 + * Default implementation of a network disjoint path pair.
27 + */
28 +public class DefaultDisjointPath extends DefaultPath implements DisjointPath {
29 +
30 + private final DefaultPath path1;
31 + private final DefaultPath path2;
32 +
33 + boolean usingPath1 = true;
34 +
35 + /**
36 + * Creates a disjoint path pair from two default paths.
37 + *
38 + * @param providerId provider identity
39 + * @param path1 primary path
40 + * @param path2 backup path
41 + */
42 + public DefaultDisjointPath(ProviderId providerId, DefaultPath path1, DefaultPath path2) {
43 + super(providerId, path1.links(), path1.cost() + path2.cost());
44 + this.path1 = path1;
45 + this.path2 = path2;
46 + }
47 +
48 + @Override
49 + public List<Link> links() {
50 + if (usingPath1) {
51 + return path1.links();
52 + } else {
53 + return path2.links();
54 + }
55 + }
56 +
57 + @Override
58 + public double cost() {
59 + if (usingPath1) {
60 + return path1.cost();
61 + }
62 + return path2.cost();
63 + }
64 +
65 + @Override
66 + public Path primary() {
67 + return path1;
68 + }
69 +
70 + @Override
71 + public Path backup() {
72 + return path2;
73 + }
74 +
75 + @Override
76 + public int hashCode() {
77 + return Objects.hash(of(path1, path2), src(), dst());
78 + }
79 +
80 + @Override
81 + public boolean equals(Object obj) {
82 + if (this == obj) {
83 + return true;
84 + }
85 + if (obj instanceof DefaultDisjointPath) {
86 + final DefaultDisjointPath other = (DefaultDisjointPath) obj;
87 + return Objects.equals(this.path1, other.path1) && Objects.equals(this.path2, other.path2);
88 + }
89 + return false;
90 + }
91 +
92 + @Override
93 + public boolean useBackup() {
94 + if (path2 == null || path2.links() == null) {
95 + return false;
96 + }
97 + usingPath1 = !usingPath1;
98 + return true;
99 + }
100 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net;
18 +
19 +
20 +/**
21 + * Representation of a contiguous directed path in a network. Path comprises
22 + * of a sequence of links, where adjacent links must share the same device,
23 + * meaning that destination of the source of one link must coincide with the
24 + * destination of the previous link.
25 + */
26 +public interface DisjointPath extends Path {
27 +
28 + /**
29 + * Uses backup path.
30 + *
31 + * @return boolean corresponding to whether request to use
32 + * backup was successful.
33 + */
34 + boolean useBackup();
35 +
36 + /**
37 + * Gets primary path.
38 + *
39 + * @return primary path
40 + */
41 + Path primary();
42 +
43 + /**
44 + * Gets secondary path.
45 + *
46 + * @return secondary path
47 + */
48 + Path backup();
49 +}
...@@ -25,12 +25,16 @@ import com.google.common.collect.ImmutableSetMultimap.Builder; ...@@ -25,12 +25,16 @@ import com.google.common.collect.ImmutableSetMultimap.Builder;
25 import org.onlab.graph.DijkstraGraphSearch; 25 import org.onlab.graph.DijkstraGraphSearch;
26 import org.onlab.graph.GraphPathSearch; 26 import org.onlab.graph.GraphPathSearch;
27 import org.onlab.graph.GraphPathSearch.Result; 27 import org.onlab.graph.GraphPathSearch.Result;
28 +import org.onlab.graph.SRLGGraphSearch;
29 +import org.onlab.graph.SuurballeGraphSearch;
28 import org.onlab.graph.TarjanGraphSearch; 30 import org.onlab.graph.TarjanGraphSearch;
29 import org.onlab.graph.TarjanGraphSearch.SCCResult; 31 import org.onlab.graph.TarjanGraphSearch.SCCResult;
30 import org.onosproject.net.AbstractModel; 32 import org.onosproject.net.AbstractModel;
31 import org.onosproject.net.ConnectPoint; 33 import org.onosproject.net.ConnectPoint;
34 +import org.onosproject.net.DefaultDisjointPath;
32 import org.onosproject.net.DefaultPath; 35 import org.onosproject.net.DefaultPath;
33 import org.onosproject.net.DeviceId; 36 import org.onosproject.net.DeviceId;
37 +import org.onosproject.net.DisjointPath;
34 import org.onosproject.net.Link; 38 import org.onosproject.net.Link;
35 import org.onosproject.net.Path; 39 import org.onosproject.net.Path;
36 import org.onosproject.net.provider.ProviderId; 40 import org.onosproject.net.provider.ProviderId;
...@@ -46,6 +50,7 @@ import org.onosproject.net.topology.TopologyGraph; ...@@ -46,6 +50,7 @@ import org.onosproject.net.topology.TopologyGraph;
46 import org.onosproject.net.topology.TopologyVertex; 50 import org.onosproject.net.topology.TopologyVertex;
47 51
48 import java.util.ArrayList; 52 import java.util.ArrayList;
53 +import java.util.HashMap;
49 import java.util.List; 54 import java.util.List;
50 import java.util.Map; 55 import java.util.Map;
51 import java.util.Set; 56 import java.util.Set;
...@@ -67,6 +72,9 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -67,6 +72,9 @@ public class DefaultTopology extends AbstractModel implements Topology {
67 72
68 private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>(); 73 private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>();
69 private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>(); 74 private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>();
75 + private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE =
76 + new SuurballeGraphSearch<>();
77 +
70 78
71 private final long time; 79 private final long time;
72 private final long creationTime; 80 private final long creationTime;
...@@ -314,6 +322,142 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -314,6 +322,142 @@ public class DefaultTopology extends AbstractModel implements Topology {
314 } 322 }
315 return builder.build(); 323 return builder.build();
316 } 324 }
325 + /**
326 + /**
327 + * Returns the set of pre-computed shortest disjoint path pairs between source and
328 + * destination devices.
329 + *
330 + * @param src source device
331 + * @param dst destination device
332 + * @return set of shortest disjoint path pairs
333 + */
334 + Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst) {
335 + return getDisjointPaths(src, dst, null);
336 + }
337 +
338 + /**
339 + * Computes on-demand the set of shortest disjoint path pairs between source and
340 + * destination devices.
341 + *
342 + * @param src source device
343 + * @param dst destination device
344 + * @param weight link weight function
345 + * @return set of disjoint shortest path pairs
346 + */
347 + Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
348 + final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
349 + final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
350 + Set<TopologyVertex> vertices = graph.getVertexes();
351 + if (!vertices.contains(srcV) || !vertices.contains(dstV)) {
352 + // src or dst not part of the current graph
353 + return ImmutableSet.of();
354 + }
355 +
356 + GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
357 + SUURBALLE.search(graph, srcV, dstV, weight, ALL_PATHS);
358 + ImmutableSet.Builder<DisjointPath> builder = ImmutableSet.builder();
359 + for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
360 + builder.add(networkDisjointPath((org.onlab.graph.DisjointPathPair<TopologyVertex, TopologyEdge>) path));
361 + }
362 + return builder.build();
363 + }
364 +
365 + /**
366 + * Computes on-demand the set of shortest disjoint risk groups path pairs between source and
367 + * destination devices.
368 + *
369 + * @param src source device
370 + * @param dst destination device
371 + * @param riskProfile map representing risk groups for each edge
372 + * @return set of shortest disjoint paths
373 + */
374 + Set<DisjointPath> getSRLGDisjointPathsD(DeviceId src, DeviceId dst, Map<TopologyEdge, Object> riskProfile) {
375 + return getSRLGDisjointPathsD(src, dst, null, riskProfile);
376 + }
377 +
378 + /**
379 + * Computes on-demand the set of shortest disjoint risk groups path pairs between source and
380 + * destination devices.
381 + *
382 + * @param src source device
383 + * @param dst destination device
384 + * @param weight edge weight object
385 + * @param riskProfile map representing risk groups for each edge
386 + * @return set of shortest disjoint paths
387 + */
388 + Set<DisjointPath> getSRLGDisjointPathsD(DeviceId src, DeviceId dst, LinkWeight weight, Map<TopologyEdge,
389 + Object> riskProfile) {
390 + final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
391 + final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
392 + Set<TopologyVertex> vertices = graph.getVertexes();
393 + if (!vertices.contains(srcV) || !vertices.contains(dstV)) {
394 + // src or dst not part of the current graph
395 + return ImmutableSet.of();
396 + }
397 +
398 + SRLGGraphSearch<TopologyVertex, TopologyEdge> srlg = new SRLGGraphSearch<>(riskProfile);
399 + GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
400 + srlg.search(graph, srcV, dstV, weight, ALL_PATHS);
401 + ImmutableSet.Builder<DisjointPath> builder = ImmutableSet.builder();
402 + for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
403 + builder.add(networkDisjointPath((org.onlab.graph.DisjointPathPair<TopologyVertex, TopologyEdge>) path));
404 + }
405 + return builder.build();
406 + }
407 +
408 + /**
409 + * Computes on-demand the set of shortest disjoint risk groups path pairs between source and
410 + * destination devices.
411 + *
412 + * @param src source device
413 + * @param dst destination device
414 + * @param weight edge weight object
415 + * @param riskProfile map representing risk groups for each link
416 + * @return set of shortest disjoint paths
417 + */
418 + Set<DisjointPath> getSRLGDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight,
419 + Map<Link, Object> riskProfile) {
420 + Map<TopologyEdge, Object> riskProfile2 = new HashMap<>();
421 + for (Link l : riskProfile.keySet()) {
422 + riskProfile2.put(new TopologyEdge() {
423 + final Link cur = l;
424 +
425 + public Link link() {
426 + return cur;
427 + }
428 +
429 + public TopologyVertex src() {
430 + return new TopologyVertex() {
431 + public DeviceId deviceId() {
432 + return src;
433 + }
434 + };
435 + }
436 +
437 + public TopologyVertex dst() {
438 + return new TopologyVertex() {
439 + public DeviceId deviceId() {
440 + return dst;
441 + }
442 + };
443 + }
444 + }, riskProfile.get(l));
445 + }
446 + return getSRLGDisjointPathsD(src, dst, weight, riskProfile2);
447 + }
448 +
449 + /**
450 + * Computes on-demand the set of shortest disjoint risk groups path pairs between source and
451 + * destination devices.
452 + *
453 + * @param src source device
454 + * @param dst destination device
455 + * @param riskProfile map representing risk groups for each link
456 + * @return set of shortest disjoint paths
457 + */
458 + Set<DisjointPath> getSRLGDisjointPaths(DeviceId src, DeviceId dst, Map<Link, Object> riskProfile) {
459 + return getSRLGDisjointPaths(src, dst, null, riskProfile);
460 + }
317 461
318 // Converts graph path to a network path with the same cost. 462 // Converts graph path to a network path with the same cost.
319 private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) { 463 private Path networkPath(org.onlab.graph.Path<TopologyVertex, TopologyEdge> path) {
...@@ -324,6 +468,11 @@ public class DefaultTopology extends AbstractModel implements Topology { ...@@ -324,6 +468,11 @@ public class DefaultTopology extends AbstractModel implements Topology {
324 return new DefaultPath(CORE_PROVIDER_ID, links, path.cost()); 468 return new DefaultPath(CORE_PROVIDER_ID, links, path.cost());
325 } 469 }
326 470
471 + private DisjointPath networkDisjointPath(org.onlab.graph.DisjointPathPair<TopologyVertex, TopologyEdge> path) {
472 + return new DefaultDisjointPath(CORE_PROVIDER_ID,
473 + (DefaultPath) networkPath(path.path1), (DefaultPath) networkPath(path.path2));
474 + }
475 +
327 // Searches for SCC clusters in the network topology graph using Tarjan 476 // Searches for SCC clusters in the network topology graph using Tarjan
328 // algorithm. 477 // algorithm.
329 private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() { 478 private SCCResult<TopologyVertex, TopologyEdge> searchForClusters() {
......