mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-05 12:16:13 +02:00
ONOS-6225 Expose k-shortest path search as part of TopologyService.
Change-Id: Idf812a707aba0b972fcfbde871c624dfc86b6e1b
This commit is contained in:
parent
d31bc6e6f6
commit
ac8b229375
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user