ONOS-6225 Expose k-shortest path search as part of TopologyService.

Change-Id: Idf812a707aba0b972fcfbde871c624dfc86b6e1b
This commit is contained in:
Yuta HIGUCHI 2017-03-30 19:21:57 -07:00 committed by Yuta HIGUCHI
parent d31bc6e6f6
commit ac8b229375
6 changed files with 228 additions and 3 deletions

View File

@ -15,6 +15,7 @@
*/
package org.onosproject.net.topology;
import org.onlab.util.GuavaCollectors;
import org.onosproject.event.ListenerService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
@ -24,6 +25,7 @@ import org.onosproject.net.Path;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
/**
* Service for providing network topology information.
@ -129,6 +131,48 @@ public interface TopologyService
Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
LinkWeigher weigher);
/**
* Returns the k-shortest paths between source and
* destination devices.
*
* The first {@code maxPaths} paths will be returned
* in ascending order according to the provided {@code weigher}
*
* @param topology topology descriptor
* @param src source device
* @param dst destination device
* @param weigher edge-weight entity
* @param maxPaths maximum number of paths (k)
* @return set of k-shortest paths
*/
default Set<Path> getKShortestPaths(Topology topology,
DeviceId src, DeviceId dst,
LinkWeigher weigher,
int maxPaths) {
return getKShortestPaths(topology, src, dst, weigher)
.limit(maxPaths)
.collect(GuavaCollectors.toImmutableSet());
}
/**
* Returns the k-shortest paths between source and
* destination devices.
*
* The first {@code maxPaths} paths will be returned
* in ascending order according to the provided {@code weigher}
*
* @param topology topology descriptor
* @param src source device
* @param dst destination device
* @param weigher edge-weight entity
* @return stream of k-shortest paths
*/
default Stream<Path> getKShortestPaths(Topology topology,
DeviceId src, DeviceId dst,
LinkWeigher weigher) {
return getPaths(topology, src, dst, weigher).stream();
}
/**
* Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count,
* between the specified source and destination devices.

View File

@ -15,6 +15,7 @@
*/
package org.onosproject.net.topology;
import org.onlab.util.GuavaCollectors;
import org.onosproject.event.Event;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
@ -26,6 +27,7 @@ import org.onosproject.store.Store;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import java.util.Map;
/**
@ -128,6 +130,45 @@ public interface TopologyStore extends Store<TopologyEvent, TopologyStoreDelegat
Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
LinkWeigher weigher);
/**
* Computes and returns the k-shortest paths between source and
* destination devices.
*
* The first {@code maxPaths} paths will be returned
* in ascending order according to the provided {@code weigher}
*
* @param topology topology descriptor
* @param src source device
* @param dst destination device
* @param weigher edge-weight entity
* @param maxPaths maximum number of paths (k)
* @return set of k-shortest paths
*/
default Set<Path> getKShortestPaths(Topology topology,
DeviceId src, DeviceId dst,
LinkWeigher weigher,
int maxPaths) {
return getKShortestPaths(topology, src, dst, weigher)
.limit(maxPaths)
.collect(GuavaCollectors.toImmutableSet());
}
/**
* Computes and returns the k-shortest paths between source and
* destination devices.
*
* @param topology topology descriptor
* @param src source device
* @param dst destination device
* @param weigher edge-weight entity
* @return stream of k-shortest paths
*/
default Stream<Path> getKShortestPaths(Topology topology,
DeviceId src, DeviceId dst,
LinkWeigher weigher) {
return getPaths(topology, src, dst, weigher).stream();
}
/**
* Computes and returns the set of disjoint shortest path pairs
* between src and dst.

View File

@ -27,12 +27,15 @@ import org.onlab.graph.DijkstraGraphSearch;
import org.onlab.graph.DisjointPathPair;
import org.onlab.graph.GraphPathSearch;
import org.onlab.graph.GraphPathSearch.Result;
import org.onlab.graph.KShortestPathsSearch;
import org.onlab.graph.LazyKShortestPathsSearch;
import org.onlab.graph.ScalarWeight;
import org.onlab.graph.SrlgGraphSearch;
import org.onlab.graph.SuurballeGraphSearch;
import org.onlab.graph.TarjanGraphSearch;
import org.onlab.graph.TarjanGraphSearch.SccResult;
import org.onlab.graph.Weight;
import org.onlab.util.GuavaCollectors;
import org.onosproject.net.AbstractModel;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDisjointPath;
@ -62,6 +65,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
@ -86,6 +90,11 @@ public class DefaultTopology extends AbstractModel implements Topology {
new TarjanGraphSearch<>();
private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE =
new SuurballeGraphSearch<>();
private static final KShortestPathsSearch<TopologyVertex, TopologyEdge> KSHORTEST =
new KShortestPathsSearch<>();
private static final LazyKShortestPathsSearch<TopologyVertex, TopologyEdge> LAZY_KSHORTEST =
new LazyKShortestPathsSearch<>();
private static LinkWeigher defaultLinkWeigher = null;
private static GraphPathSearch<TopologyVertex, TopologyEdge> defaultGraphPathSearch = null;
@ -387,7 +396,88 @@ public class DefaultTopology extends AbstractModel implements Topology {
}
/**
* /**
* Computes on-demand the k-shortest paths between source and
* destination devices.
*
* @param src source device
* @param dst destination device
* @param maxPaths maximum number of paths (k)
* @return set of k-shortest paths
*/
public Set<Path> getKShortestPaths(DeviceId src, DeviceId dst,
int maxPaths) {
return getKShortestPaths(src, dst, linkWeight(), maxPaths);
}
/**
* Computes on-demand the k-shortest paths between source and
* destination devices.
*
* The first {@code maxPaths} paths will be returned
* in ascending order according to the provided {@code weigher}
*
* @param src source device
* @param dst destination device
* @param weigher link weight function
* @param maxPaths maximum number of paths (k)
* @return set of k-shortest paths
*/
public Set<Path> getKShortestPaths(DeviceId src, DeviceId dst,
LinkWeigher weigher,
int maxPaths) {
DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
Set<TopologyVertex> vertices = graph.getVertexes();
if (!vertices.contains(srcV) || !vertices.contains(dstV)) {
// src or dst not part of the current graph
return ImmutableSet.of();
}
return KSHORTEST.search(graph, srcV, dstV, weigher, maxPaths)
.paths().stream()
.map(this::networkPath)
.collect(GuavaCollectors.toImmutableSet());
}
/**
* Lazily computes on-demand the k-shortest paths between source and
* destination devices.
*
*
* @param src source device
* @param dst destination device
* @return stream of k-shortest paths
*/
public Stream<Path> getKShortestPaths(DeviceId src, DeviceId dst) {
return getKShortestPaths(src, dst, linkWeight());
}
/**
* Lazily computes on-demand the k-shortest paths between source and
* destination devices.
*
*
* @param src source device
* @param dst destination device
* @param weigher link weight function
* @return stream of k-shortest paths
*/
public Stream<Path> getKShortestPaths(DeviceId src, DeviceId dst,
LinkWeigher weigher) {
DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
Set<TopologyVertex> vertices = graph.getVertexes();
if (!vertices.contains(srcV) || !vertices.contains(dstV)) {
// src or dst not part of the current graph
return Stream.empty();
}
return LAZY_KSHORTEST.lazyPathSearch(graph, srcV, dstV, weigher)
.map(this::networkPath);
}
/**
* Returns the set of pre-computed shortest disjoint path pairs between
* source and destination devices.
*

View File

@ -40,7 +40,6 @@ import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyVertex;
import java.util.Set;
import static com.google.common.collect.ImmutableSet.of;
import static org.junit.Assert.*;
import static org.onosproject.net.DeviceId.deviceId;
@ -121,6 +120,12 @@ public class DefaultTopologyTest {
paths = dt.getPaths(D1, D3, WEIGHER);
assertEquals("incorrect path count", 1, paths.size());
paths = dt.getKShortestPaths(D1, D2, 42);
assertEquals("incorrect path count", 2, paths.size());
assertEquals("incorrect path count", 2, dt.getKShortestPaths(D1, D2).limit(42).count());
}
@Test

View File

@ -48,6 +48,7 @@ import org.slf4j.Logger;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
@ -169,10 +170,37 @@ public class TopologyManager
checkNotNull(topology, TOPOLOGY_NULL);
checkNotNull(src, DEVICE_ID_NULL);
checkNotNull(dst, DEVICE_ID_NULL);
checkNotNull(weigher, "Link weight cannot be null");
checkNotNull(weigher, LINK_WEIGHT_NULL);
return store.getPaths(topology, src, dst, weigher);
}
@Override
public Set<Path> getKShortestPaths(Topology topology, DeviceId src,
DeviceId dst, LinkWeigher weigher,
int maxPaths) {
checkPermission(TOPOLOGY_READ);
checkNotNull(topology, TOPOLOGY_NULL);
checkNotNull(src, DEVICE_ID_NULL);
checkNotNull(dst, DEVICE_ID_NULL);
checkNotNull(weigher, LINK_WEIGHT_NULL);
return store.getKShortestPaths(topology, src, dst, weigher, maxPaths);
}
@Override
public Stream<Path> getKShortestPaths(Topology topology,
DeviceId src,
DeviceId dst,
LinkWeigher weigher) {
checkPermission(TOPOLOGY_READ);
checkNotNull(topology, TOPOLOGY_NULL);
checkNotNull(src, DEVICE_ID_NULL);
checkNotNull(dst, DEVICE_ID_NULL);
checkNotNull(weigher, LINK_WEIGHT_NULL);
return store.getKShortestPaths(topology, src, dst, weigher);
}
@Override
public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
DeviceId dst) {

View File

@ -69,6 +69,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkArgument;
import static org.onlab.util.Tools.get;
@ -225,6 +226,22 @@ public class DistributedTopologyStore
return defaultTopology(topology).getPaths(src, dst, weigher);
}
@Override
public Set<Path> getKShortestPaths(Topology topology,
DeviceId src, DeviceId dst,
LinkWeigher weigher,
int maxPaths) {
return defaultTopology(topology).getKShortestPaths(src, dst, weigher, maxPaths);
}
@Override
public Stream<Path> getKShortestPaths(Topology topology,
DeviceId src,
DeviceId dst,
LinkWeigher weigher) {
return defaultTopology(topology).getKShortestPaths(src, dst, weigher);
}
@Override
public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src, DeviceId dst) {
return defaultTopology(topology).getDisjointPaths(src, dst);