ONOS-3515 Added ability to configure different link-weight functions as defaults; or inject custom ones.
ONOS-3516 Added ability to inject alternate graph path search algorithms.
Change-Id: If5831c198a831ae79a9933fc794eb7deab776e2f
diff --git a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
index 8c5fb79..4f81e92 100644
--- a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
+++ b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
@@ -25,7 +25,6 @@
*/
public final class AnnotationKeys {
-
// Prohibit instantiation
private AnnotationKeys() {
}
@@ -81,6 +80,12 @@
public static final String DURABLE = "durable";
/**
+ * Annotation key for link metric; used by
+ * {@link org.onosproject.net.topology.MetricLinkWeight} function.
+ */
+ public static final String METRIC = "metric";
+
+ /**
* Annotation key for latency.
*
* @deprecated since Cardinal
@@ -112,8 +117,14 @@
*/
public static final String ROUTER_ID = "routerId";
+ /**
+ * Annotation key for the static lambda.
+ */
public static final String STATIC_LAMBDA = "staticLambda";
+ /**
+ * Annotation key for the static port.
+ */
public static final String STATIC_PORT = "staticPort";
/**
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
index e962110..ed807b8 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
@@ -15,22 +15,32 @@
*/
package org.onosproject.net.config.basics;
+import com.fasterxml.jackson.databind.JsonNode;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
-import com.fasterxml.jackson.databind.JsonNode;
import java.time.Duration;
+import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
+
/**
* Basic configuration for network infrastructure link.
*/
public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> {
public static final String TYPE = "type";
+ public static final String METRIC = "metric";
public static final String LATENCY = "latency";
public static final String BANDWIDTH = "bandwidth";
public static final String IS_DURABLE = "durable";
+ @Override
+ public boolean isValid() {
+ return hasOnlyFields(TYPE, METRIC, LATENCY, BANDWIDTH, IS_DURABLE) &&
+ isNumber(METRIC, OPTIONAL) && isNumber(LATENCY, OPTIONAL) &&
+ isNumber(BANDWIDTH, OPTIONAL);
+ }
+
/**
* Returns the link type.
*
@@ -51,6 +61,27 @@
}
/**
+ * Returns link metric value for use by
+ * {@link org.onosproject.net.topology.MetricLinkWeight} function.
+ *
+ * @return link metric; -1 if not set
+ */
+ public double metric() {
+ return get(METRIC, -1);
+ }
+
+ /**
+ * Sets the link metric for use by
+ * {@link org.onosproject.net.topology.MetricLinkWeight} function.
+ *
+ * @param metric new metric; null to clear
+ * @return self
+ */
+ public BasicLinkConfig metric(Double metric) {
+ return (BasicLinkConfig) setOrClear(METRIC, metric);
+ }
+
+ /**
* Returns link latency in terms of nanos.
*
* @return link latency; -1 if not set
diff --git a/core/api/src/main/java/org/onosproject/net/topology/GeoDistanceLinkWeight.java b/core/api/src/main/java/org/onosproject/net/topology/GeoDistanceLinkWeight.java
new file mode 100644
index 0000000..c966902
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/topology/GeoDistanceLinkWeight.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.topology;
+
+import org.onlab.util.GeoLocation;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+
+import static java.lang.Double.MAX_VALUE;
+
+/**
+ * Link weight for measuring link cost using the geo distance between link
+ * vertices as determined by the element longitude/latitude annotation.
+ */
+public class GeoDistanceLinkWeight implements LinkWeight {
+
+ private static final double MAX_KM = 40_075 / 2.0;
+
+ private final DeviceService deviceService;
+
+ /**
+ * Creates a new link-weight with access to the specified device service.
+ *
+ * @param deviceService device service reference
+ */
+ public GeoDistanceLinkWeight(DeviceService deviceService) {
+ this.deviceService = deviceService;
+ }
+
+ @Override
+ public double weight(TopologyEdge edge) {
+ GeoLocation src = getLocation(edge.link().src().deviceId());
+ GeoLocation dst = getLocation(edge.link().dst().deviceId());
+ return src != null && dst != null ? src.kilometersTo(dst) : MAX_KM;
+ }
+
+ private GeoLocation getLocation(DeviceId deviceId) {
+ Device d = deviceService.getDevice(deviceId);
+ Annotations a = d != null ? d.annotations() : null;
+ double latitude = getDouble(a, AnnotationKeys.LATITUDE);
+ double longitude = getDouble(a, AnnotationKeys.LONGITUDE);
+ return latitude == MAX_VALUE || longitude == MAX_VALUE ? null :
+ new GeoLocation(latitude, longitude);
+ }
+
+ private double getDouble(Annotations a, String key) {
+ String value = a != null ? a.value(key) : null;
+ try {
+ return value != null ? Double.parseDouble(value) : MAX_VALUE;
+ } catch (NumberFormatException e) {
+ return MAX_VALUE;
+ }
+ }
+}
+
diff --git a/core/api/src/main/java/org/onosproject/net/topology/HopCountLinkWeight.java b/core/api/src/main/java/org/onosproject/net/topology/HopCountLinkWeight.java
new file mode 100644
index 0000000..c557016
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/topology/HopCountLinkWeight.java
@@ -0,0 +1,36 @@
+package org.onosproject.net.topology;
+
+import static org.onosproject.net.Link.State.ACTIVE;
+import static org.onosproject.net.Link.Type.INDIRECT;
+
+/**
+ * Link weight for measuring link cost as hop count with indirect links
+ * being as expensive as traversing the entire graph to assume the worst.
+ */
+public class HopCountLinkWeight implements LinkWeight {
+ private final int indirectLinkCost;
+
+ /**
+ * Creates a new hop-count weight.
+ */
+ public HopCountLinkWeight() {
+ this.indirectLinkCost = Short.MAX_VALUE;
+ }
+
+ /**
+ * Creates a new hop-count weight with the specified cost of indirect links.
+ */
+ public HopCountLinkWeight(int indirectLinkCost) {
+ this.indirectLinkCost = indirectLinkCost;
+ }
+
+ @Override
+ public double weight(TopologyEdge edge) {
+ // To force preference to use direct paths first, make indirect
+ // links as expensive as the linear vertex traversal.
+ return edge.link().state() ==
+ ACTIVE ? (edge.link().type() ==
+ INDIRECT ? indirectLinkCost : 1) : -1;
+ }
+}
+
diff --git a/core/api/src/main/java/org/onosproject/net/topology/MetricLinkWeight.java b/core/api/src/main/java/org/onosproject/net/topology/MetricLinkWeight.java
new file mode 100644
index 0000000..8463e08
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/topology/MetricLinkWeight.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.topology;
+
+import org.onosproject.net.AnnotationKeys;
+
+/**
+ * Link weight for measuring link cost using the link metric annotation.
+ */
+public class MetricLinkWeight implements LinkWeight {
+
+ @Override
+ public double weight(TopologyEdge edge) {
+ String v = edge.link().annotations().value(AnnotationKeys.METRIC);
+ try {
+ return v != null ? Double.parseDouble(v) : 1;
+ } catch (NumberFormatException e) {
+ return 1;
+ }
+ }
+}
+
diff --git a/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java b/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java
new file mode 100644
index 0000000..9d077e1
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/topology/PathAdminService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.topology;
+
+import org.onlab.graph.GraphPathSearch;
+
+/**
+ * Provides administrative abilities to tailor the path service behaviours.
+ */
+public interface PathAdminService {
+
+ /**
+ * Sets the specified link-weight function to be used as a default.
+ * If null is specified, the builtin default hop-count link-weight will be
+ * used.
+ *
+ * @param linkWeight default link-weight function
+ */
+ void setDefaultLinkWeight(LinkWeight linkWeight);
+
+ /**
+ * Sets the specified graph path search algorightm to be used as a default.
+ * If null is specified, the builtin default all-shortest-paths Dijkstra
+ * algorithm will be used.
+ *
+ * @param graphPathSearch default graph path search algorithm
+ */
+ void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/topology/PathService.java b/core/api/src/main/java/org/onosproject/net/topology/PathService.java
index 0bd4d75..3895407 100644
--- a/core/api/src/main/java/org/onosproject/net/topology/PathService.java
+++ b/core/api/src/main/java/org/onosproject/net/topology/PathService.java
@@ -30,8 +30,9 @@
public interface PathService {
/**
- * Returns the set of all shortest paths, precomputed in terms of hop-count,
- * between the specified source and destination elements.
+ * Returns the set of all shortest paths between the specified source and
+ * destination elements. The path is computed using the default edge-weight
+ * function, which by default is hop-count.
*
* @param src source element
* @param dst destination element
@@ -40,9 +41,9 @@
Set<Path> getPaths(ElementId src, ElementId dst);
/**
- * Returns the set of all shortest paths, computed using the supplied
- * edge-weight entity, between the specified source and destination
- * network elements.
+ * Returns the set of all shortest paths between the specified source and
+ * destination network elements. The path is computed using the supplied
+ * edge-weight function.
*
* @param src source element
* @param dst destination element
@@ -52,8 +53,9 @@
Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight);
/**
- * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count,
- * between the specified source and destination devices.
+ * Returns the set of all disjoint shortest path pairs between the
+ * specified source and destination elements. The path is computed using
+ * the default edge-weight function, which by default is hop-count.
*
* @param src source device
* @param dst destination device
@@ -62,8 +64,9 @@
Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst);
/**
- * Returns the set of all disjoint shortest path pairs, computed using the supplied
- * edge-weight entity, between the specified source and destination devices.
+ * Returns the set of all disjoint shortest path pairs between the
+ * specified source and destination elements. The path is computed using
+ * the supplied edge-weight function.
*
* @param src source device
* @param dst destination device
@@ -74,8 +77,10 @@
LinkWeight weight);
/**
- * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count,
- * between the specified source and destination devices.
+ * Returns the set of all disjoint shortest path pairs between the
+ * specified source and destination elements and taking into consideration
+ * the provided risk profile. The path is computed using the default
+ * edge-weight function, which by default is hop-count.
*
* @param src source device
* @param dst destination device
@@ -86,8 +91,10 @@
Map<Link, Object> riskProfile);
/**
- * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count,
- * between the specified source and destination devices.
+ * Returns the set of all disjoint shortest path pairs between the
+ * specified source and destination elements and taking into consideration
+ * the provided risk profile. The path is computed using the supplied
+ * edge-weight function.
*
* @param src source device
* @param dst destination device
@@ -96,6 +103,7 @@
* @return set of all shortest paths between the two devices
*/
Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst,
- LinkWeight weight, Map<Link, Object> riskProfile);
+ LinkWeight weight,
+ Map<Link, Object> riskProfile);
}
diff --git a/core/common/src/main/java/org/onosproject/common/DefaultTopology.java b/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
index 84cde42..c5263ed 100644
--- a/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
+++ b/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
@@ -43,12 +43,15 @@
import org.onosproject.net.topology.DefaultTopologyCluster;
import org.onosproject.net.topology.DefaultTopologyVertex;
import org.onosproject.net.topology.GraphDescription;
+import org.onosproject.net.topology.HopCountLinkWeight;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyCluster;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyGraph;
import org.onosproject.net.topology.TopologyVertex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
@@ -61,7 +64,6 @@
import static org.onlab.graph.GraphPathSearch.ALL_PATHS;
import static org.onlab.util.Tools.isNullOrEmpty;
import static org.onosproject.core.CoreService.CORE_PROVIDER_ID;
-import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.Link.State.INACTIVE;
import static org.onosproject.net.Link.Type.INDIRECT;
@@ -71,18 +73,22 @@
*/
public class DefaultTopology extends AbstractModel implements Topology {
+ private static final Logger log = LoggerFactory.getLogger(DefaultTopology.class);
+
private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>();
private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>();
- private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE =
- new SuurballeGraphSearch<>();
+ private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE = new SuurballeGraphSearch<>();
+ private static LinkWeight defaultLinkWeight = null;
+ private static GraphPathSearch<TopologyVertex, TopologyEdge> defaultGraphPathSearch = null;
private final long time;
private final long creationTime;
private final long computeCost;
private final TopologyGraph graph;
- private final LinkWeight weight;
+ private final LinkWeight hopCountWeight;
+
private final Supplier<SccResult<TopologyVertex, TopologyEdge>> clusterResults;
private final Supplier<ImmutableMap<ClusterId, TopologyCluster>> clusters;
private final Supplier<ImmutableSet<ConnectPoint>> infrastructurePoints;
@@ -91,6 +97,30 @@
private final Supplier<ClusterIndexes> clusterIndexes;
/**
+ * Sets the default link-weight to be used when computing paths. If null is
+ * specified, the builtin default link-weight measuring hop-counts will be
+ * used.
+ *
+ * @param linkWeight new default link-weight
+ */
+ public static void setDefaultLinkWeight(LinkWeight linkWeight) {
+ log.info("Setting new default link-weight function to {}", linkWeight);
+ defaultLinkWeight = linkWeight;
+ }
+
+ /**
+ * Sets the default lpath search algorighm to be used when computing paths.
+ * If null is specified, the builtin default Dijkstra will be used.
+ *
+ * @param graphPathSearch new default algorithm
+ */
+ public static void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) {
+ log.info("Setting new default graph path algorithm to {}", graphPathSearch);
+ defaultGraphPathSearch = graphPathSearch;
+ }
+
+
+ /**
* Creates a topology descriptor attributed to the specified provider.
*
* @param providerId identity of the provider
@@ -113,7 +143,7 @@
this.clusterIndexes = Suppliers.memoize(() -> buildIndexes());
- this.weight = new HopCountLinkWeight(graph.getVertexes().size());
+ this.hopCountWeight = new HopCountLinkWeight(graph.getVertexes().size());
this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets());
this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints());
this.computeCost = Math.max(0, System.nanoTime() - time);
@@ -294,7 +324,7 @@
* @return set of shortest paths
*/
public Set<Path> getPaths(DeviceId src, DeviceId dst) {
- return getPaths(src, dst, null);
+ return getPaths(src, dst, linkWeight());
}
/**
@@ -307,8 +337,8 @@
* @return set of shortest paths
*/
public Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
- final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
- final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
+ 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
@@ -316,7 +346,7 @@
}
GraphPathSearch.Result<TopologyVertex, TopologyEdge> result =
- DIJKSTRA.search(graph, srcV, dstV, weight, ALL_PATHS);
+ graphPathSearch().search(graph, srcV, dstV, weight, ALL_PATHS);
ImmutableSet.Builder<Path> builder = ImmutableSet.builder();
for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) {
builder.add(networkPath(path));
@@ -334,7 +364,7 @@
* @return set of shortest disjoint path pairs
*/
public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst) {
- return getDisjointPaths(src, dst, (LinkWeight) null);
+ return getDisjointPaths(src, dst, linkWeight());
}
/**
@@ -347,8 +377,8 @@
* @return set of disjoint shortest path pairs
*/
public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight) {
- final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
- final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
+ 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
@@ -375,7 +405,7 @@
* @return set of shortest disjoint paths
*/
private Set<DisjointPath> disjointPaths(DeviceId src, DeviceId dst, LinkWeight weight,
- Map<TopologyEdge, Object> riskProfile) {
+ Map<TopologyEdge, Object> riskProfile) {
DefaultTopologyVertex srcV = new DefaultTopologyVertex(src);
DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst);
@@ -438,7 +468,7 @@
* @return set of shortest disjoint paths
*/
public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, Map<Link, Object> riskProfile) {
- return getDisjointPaths(src, dst, null, riskProfile);
+ return getDisjointPaths(src, dst, linkWeight(), riskProfile);
}
// Converts graph path to a network path with the same cost.
@@ -499,8 +529,7 @@
// Processes a map of broadcast sets for each cluster.
private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() {
- Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap
- .builder();
+ Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap.builder();
for (TopologyCluster cluster : clusters.get().values()) {
addClusterBroadcastSet(cluster, builder);
}
@@ -512,7 +541,7 @@
// all other devices within the cluster.
private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) {
// Use the graph root search results to build the broadcast set.
- Result<TopologyVertex, TopologyEdge> result = DIJKSTRA.search(graph, cluster.root(), null, weight, 1);
+ Result<TopologyVertex, TopologyEdge> result = DIJKSTRA.search(graph, cluster.root(), null, hopCountWeight, 1);
for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) {
TopologyVertex vertex = entry.getKey();
@@ -577,23 +606,12 @@
linksBuilder.build());
}
- // Link weight for measuring link cost as hop count with indirect links
- // being as expensive as traversing the entire graph to assume the worst.
- private static class HopCountLinkWeight implements LinkWeight {
- private final int indirectLinkCost;
+ private GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch() {
+ return defaultGraphPathSearch != null ? defaultGraphPathSearch : DIJKSTRA;
+ }
- HopCountLinkWeight(int indirectLinkCost) {
- this.indirectLinkCost = indirectLinkCost;
- }
-
- @Override
- public double weight(TopologyEdge edge) {
- // To force preference to use direct paths first, make indirect
- // links as expensive as the linear vertex traversal.
- return edge.link().state() ==
- ACTIVE ? (edge.link().type() ==
- INDIRECT ? indirectLinkCost : 1) : -1;
- }
+ private LinkWeight linkWeight() {
+ return defaultLinkWeight != null ? defaultLinkWeight : hopCountWeight;
}
// Link weight for preventing traversal over indirect links.
diff --git a/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java b/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java
index 801092f..ff74dbd 100644
--- a/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java
+++ b/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java
@@ -38,6 +38,7 @@
public final class BasicLinkOperator implements ConfigOperator {
private static final long DEF_BANDWIDTH = -1L;
+ private static final double DEF_METRIC = -1;
private static final Duration DEF_DURATION = Duration.ofNanos(-1L);
private static final Logger log = getLogger(BasicLinkOperator.class);
@@ -77,6 +78,9 @@
*/
public static SparseAnnotations combine(BasicLinkConfig cfg, SparseAnnotations an) {
DefaultAnnotations.Builder b = DefaultAnnotations.builder();
+ if (cfg.metric() != DEF_METRIC) {
+ b.set(AnnotationKeys.METRIC, String.valueOf(cfg.metric()));
+ }
if (cfg.latency() != DEF_DURATION) {
b.set(AnnotationKeys.LATENCY, cfg.latency().toString());
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java b/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java
index da4e3cc..2641635 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/topology/impl/DistributedTopologyStore.java
@@ -15,44 +15,43 @@
*/
package org.onosproject.store.topology.impl;
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.onlab.util.Tools.isNullOrEmpty;
-import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.graph.GraphPathSearch;
import org.onlab.util.KryoNamespace;
+import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.common.DefaultTopology;
import org.onosproject.event.Event;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.DisjointPath;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
-import org.onosproject.net.DisjointPath;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.ClusterId;
import org.onosproject.net.topology.DefaultGraphDescription;
+import org.onosproject.net.topology.GeoDistanceLinkWeight;
import org.onosproject.net.topology.GraphDescription;
import org.onosproject.net.topology.LinkWeight;
+import org.onosproject.net.topology.MetricLinkWeight;
+import org.onosproject.net.topology.PathAdminService;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyCluster;
+import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyEvent;
import org.onosproject.net.topology.TopologyGraph;
import org.onosproject.net.topology.TopologyStore;
import org.onosproject.net.topology.TopologyStoreDelegate;
+import org.onosproject.net.topology.TopologyVertex;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.EventuallyConsistentMap;
@@ -60,8 +59,23 @@
import org.onosproject.store.service.EventuallyConsistentMapListener;
import org.onosproject.store.service.LogicalClockService;
import org.onosproject.store.service.StorageService;
+import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onlab.util.Tools.get;
+import static org.onlab.util.Tools.isNullOrEmpty;
+import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED;
+import static org.slf4j.LoggerFactory.getLogger;
+
/**
* Manages inventory of topology snapshots using trivial in-memory
* structures implementation.
@@ -73,9 +87,12 @@
@Service
public class DistributedTopologyStore
extends AbstractStore<TopologyEvent, TopologyStoreDelegate>
- implements TopologyStore {
+ implements TopologyStore, PathAdminService {
private final Logger log = getLogger(getClass());
+
+ private static final String FORMAT = "Settings: linkWeightFunction={}";
+
private volatile DefaultTopology current =
new DefaultTopology(ProviderId.NONE,
new DefaultGraphDescription(0L, System.currentTimeMillis(),
@@ -91,6 +108,21 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MastershipService mastershipService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ComponentConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ private static final String HOP_COUNT = "hopCount";
+ private static final String LINK_METRIC = "linkMetric";
+ private static final String GEO_DISTANCE = "geoDistance";
+
+ private static final String DEFAULT_LINK_WEIGHT_FUNCTION = "hopCount";
+ @Property(name = "linkWeightFunction", value = DEFAULT_LINK_WEIGHT_FUNCTION,
+ label = "Default link-weight function: hopCount, linkMetric, geoDistance")
+ private String linkWeightFunction = DEFAULT_LINK_WEIGHT_FUNCTION;
+
// Cluster root to broadcast points bindings to allow convergence to
// a shared broadcast tree; node that is the master of the cluster root
// is the primary.
@@ -100,7 +132,8 @@
new InternalBroadcastPointListener();
@Activate
- public void activate() {
+ protected void activate() {
+ configService.registerProperties(getClass());
KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API);
@@ -114,12 +147,30 @@
}
@Deactivate
- public void deactivate() {
+ protected void deactivate() {
+ configService.unregisterProperties(getClass(), false);
broadcastPoints.removeListener(listener);
broadcastPoints.destroy();
log.info("Stopped");
}
+ @Modified
+ protected void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+
+ String newLinkWeightFunction = get(properties, "linkWeightFunction");
+ if (newLinkWeightFunction != null &&
+ !Objects.equals(newLinkWeightFunction, linkWeightFunction)) {
+ linkWeightFunction = newLinkWeightFunction;
+ LinkWeight weight = linkWeightFunction.equals(LINK_METRIC) ?
+ new MetricLinkWeight() :
+ linkWeightFunction.equals(GEO_DISTANCE) ?
+ new GeoDistanceLinkWeight(deviceService) : null;
+ setDefaultLinkWeight(weight);
+ }
+ log.info(FORMAT, linkWeightFunction);
+ }
+
@Override
public Topology currentTopology() {
return current;
@@ -263,6 +314,16 @@
return (DefaultTopology) topology;
}
+ @Override
+ public void setDefaultLinkWeight(LinkWeight linkWeight) {
+ DefaultTopology.setDefaultLinkWeight(linkWeight);
+ }
+
+ @Override
+ public void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) {
+ DefaultTopology.setDefaultGraphPathSearch(graphPathSearch);
+ }
+
private class InternalBroadcastPointListener
implements EventuallyConsistentMapListener<DeviceId, Set<ConnectPoint>> {
@Override
diff --git a/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java b/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java
index c568841..68c536b 100644
--- a/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java
+++ b/providers/null/src/main/java/org/onosproject/provider/nil/NullProviders.java
@@ -168,7 +168,7 @@
@Activate
- public void activate(ComponentContext context) {
+ public void activate() {
cfgService.registerProperties(getClass());
deviceProviderService = deviceProviderRegistry.register(deviceProvider);
@@ -180,7 +180,7 @@
}
@Deactivate
- public void deactivate(ComponentContext context) {
+ public void deactivate() {
cfgService.unregisterProperties(getClass(), false);
tearDown();
diff --git a/utils/misc/src/main/java/org/onlab/util/GeoLocation.java b/utils/misc/src/main/java/org/onlab/util/GeoLocation.java
new file mode 100644
index 0000000..7e54653
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/util/GeoLocation.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.util;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Geo location specified in terms of longitude and latitude.
+ */
+public class GeoLocation {
+
+ public static final double EARTH_RADIUS_KM = 6378.1370D;
+
+ private final double latitude;
+ private final double longitude;
+
+ /**
+ * Creates a new location using the specified coordinates.
+ *
+ * @param latitude latitude line
+ * @param longitude longitude line
+ */
+ public GeoLocation(double latitude, double longitude) {
+ this.latitude = latitude;
+ this.longitude = longitude;
+ }
+
+ /**
+ * Returns the latitude of this location.
+ *
+ * @return latitude
+ */
+ public double latitude() {
+ return latitude;
+ }
+
+ /**
+ * Returns the longitude of this location.
+ *
+ * @return longitude
+ */
+ public double longitude() {
+ return longitude;
+ }
+
+ /**
+ * Returns the distance in kilometers, between this location and another.
+ *
+ * @param other other geo location
+ * @return distance in kilometers
+ */
+ public double kilometersTo(GeoLocation other) {
+ double hereLat = Math.toRadians(latitude);
+ double hereLon = Math.toRadians(longitude);
+ double thereLat = Math.toRadians(other.latitude);
+ double thereLon = Math.toRadians(other.longitude);
+
+ double cos = Math.sin(hereLat) * Math.sin(thereLat) +
+ Math.cos(hereLat) * Math.cos(thereLat) * Math.cos(hereLon - thereLon);
+ return Math.acos(cos) * EARTH_RADIUS_KM;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("latitude", latitude)
+ .add("longitude", longitude)
+ .toString();
+ }
+
+}
diff --git a/utils/misc/src/test/java/org/onlab/util/GeoLocationTest.java b/utils/misc/src/test/java/org/onlab/util/GeoLocationTest.java
new file mode 100644
index 0000000..a497bcc
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/util/GeoLocationTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.util;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test suite of the geo location.
+ */
+public class GeoLocationTest {
+
+ @Test
+ public void basics() {
+ GeoLocation nLoc = new GeoLocation(40.7127, -74.0059);
+ GeoLocation wLoc = new GeoLocation(38.9047, -77.0164);
+
+ assertEquals("incorrect latitude", 40.7127, nLoc.latitude(), 0.0001);
+ assertEquals("incorrect longitude", -74.00598, nLoc.longitude(), 0.0001);
+ assertEquals("incorrect distance", 326.74, nLoc.kilometersTo(wLoc), 0.01);
+ }
+
+}
\ No newline at end of file