Committed by
Gerrit Code Review
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
Showing
13 changed files
with
510 additions
and
66 deletions
| ... | @@ -25,7 +25,6 @@ package org.onosproject.net; | ... | @@ -25,7 +25,6 @@ package org.onosproject.net; |
| 25 | */ | 25 | */ |
| 26 | public final class AnnotationKeys { | 26 | public final class AnnotationKeys { |
| 27 | 27 | ||
| 28 | - | ||
| 29 | // Prohibit instantiation | 28 | // Prohibit instantiation |
| 30 | private AnnotationKeys() { | 29 | private AnnotationKeys() { |
| 31 | } | 30 | } |
| ... | @@ -81,6 +80,12 @@ public final class AnnotationKeys { | ... | @@ -81,6 +80,12 @@ public final class AnnotationKeys { |
| 81 | public static final String DURABLE = "durable"; | 80 | public static final String DURABLE = "durable"; |
| 82 | 81 | ||
| 83 | /** | 82 | /** |
| 83 | + * Annotation key for link metric; used by | ||
| 84 | + * {@link org.onosproject.net.topology.MetricLinkWeight} function. | ||
| 85 | + */ | ||
| 86 | + public static final String METRIC = "metric"; | ||
| 87 | + | ||
| 88 | + /** | ||
| 84 | * Annotation key for latency. | 89 | * Annotation key for latency. |
| 85 | * | 90 | * |
| 86 | * @deprecated since Cardinal | 91 | * @deprecated since Cardinal |
| ... | @@ -112,8 +117,14 @@ public final class AnnotationKeys { | ... | @@ -112,8 +117,14 @@ public final class AnnotationKeys { |
| 112 | */ | 117 | */ |
| 113 | public static final String ROUTER_ID = "routerId"; | 118 | public static final String ROUTER_ID = "routerId"; |
| 114 | 119 | ||
| 120 | + /** | ||
| 121 | + * Annotation key for the static lambda. | ||
| 122 | + */ | ||
| 115 | public static final String STATIC_LAMBDA = "staticLambda"; | 123 | public static final String STATIC_LAMBDA = "staticLambda"; |
| 116 | 124 | ||
| 125 | + /** | ||
| 126 | + * Annotation key for the static port. | ||
| 127 | + */ | ||
| 117 | public static final String STATIC_PORT = "staticPort"; | 128 | public static final String STATIC_PORT = "staticPort"; |
| 118 | 129 | ||
| 119 | /** | 130 | /** | ... | ... |
| ... | @@ -15,22 +15,32 @@ | ... | @@ -15,22 +15,32 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.net.config.basics; | 16 | package org.onosproject.net.config.basics; |
| 17 | 17 | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 18 | import org.onosproject.net.Link; | 19 | import org.onosproject.net.Link; |
| 19 | import org.onosproject.net.LinkKey; | 20 | import org.onosproject.net.LinkKey; |
| 20 | -import com.fasterxml.jackson.databind.JsonNode; | ||
| 21 | 21 | ||
| 22 | import java.time.Duration; | 22 | import java.time.Duration; |
| 23 | 23 | ||
| 24 | +import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL; | ||
| 25 | + | ||
| 24 | /** | 26 | /** |
| 25 | * Basic configuration for network infrastructure link. | 27 | * Basic configuration for network infrastructure link. |
| 26 | */ | 28 | */ |
| 27 | public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> { | 29 | public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> { |
| 28 | 30 | ||
| 29 | public static final String TYPE = "type"; | 31 | public static final String TYPE = "type"; |
| 32 | + public static final String METRIC = "metric"; | ||
| 30 | public static final String LATENCY = "latency"; | 33 | public static final String LATENCY = "latency"; |
| 31 | public static final String BANDWIDTH = "bandwidth"; | 34 | public static final String BANDWIDTH = "bandwidth"; |
| 32 | public static final String IS_DURABLE = "durable"; | 35 | public static final String IS_DURABLE = "durable"; |
| 33 | 36 | ||
| 37 | + @Override | ||
| 38 | + public boolean isValid() { | ||
| 39 | + return hasOnlyFields(TYPE, METRIC, LATENCY, BANDWIDTH, IS_DURABLE) && | ||
| 40 | + isNumber(METRIC, OPTIONAL) && isNumber(LATENCY, OPTIONAL) && | ||
| 41 | + isNumber(BANDWIDTH, OPTIONAL); | ||
| 42 | + } | ||
| 43 | + | ||
| 34 | /** | 44 | /** |
| 35 | * Returns the link type. | 45 | * Returns the link type. |
| 36 | * | 46 | * |
| ... | @@ -51,6 +61,27 @@ public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> { | ... | @@ -51,6 +61,27 @@ public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> { |
| 51 | } | 61 | } |
| 52 | 62 | ||
| 53 | /** | 63 | /** |
| 64 | + * Returns link metric value for use by | ||
| 65 | + * {@link org.onosproject.net.topology.MetricLinkWeight} function. | ||
| 66 | + * | ||
| 67 | + * @return link metric; -1 if not set | ||
| 68 | + */ | ||
| 69 | + public double metric() { | ||
| 70 | + return get(METRIC, -1); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * Sets the link metric for use by | ||
| 75 | + * {@link org.onosproject.net.topology.MetricLinkWeight} function. | ||
| 76 | + * | ||
| 77 | + * @param metric new metric; null to clear | ||
| 78 | + * @return self | ||
| 79 | + */ | ||
| 80 | + public BasicLinkConfig metric(Double metric) { | ||
| 81 | + return (BasicLinkConfig) setOrClear(METRIC, metric); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + /** | ||
| 54 | * Returns link latency in terms of nanos. | 85 | * Returns link latency in terms of nanos. |
| 55 | * | 86 | * |
| 56 | * @return link latency; -1 if not set | 87 | * @return link latency; -1 if not set | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2014-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.topology; | ||
| 18 | + | ||
| 19 | +import org.onlab.util.GeoLocation; | ||
| 20 | +import org.onosproject.net.AnnotationKeys; | ||
| 21 | +import org.onosproject.net.Annotations; | ||
| 22 | +import org.onosproject.net.Device; | ||
| 23 | +import org.onosproject.net.DeviceId; | ||
| 24 | +import org.onosproject.net.device.DeviceService; | ||
| 25 | + | ||
| 26 | +import static java.lang.Double.MAX_VALUE; | ||
| 27 | + | ||
| 28 | +/** | ||
| 29 | + * Link weight for measuring link cost using the geo distance between link | ||
| 30 | + * vertices as determined by the element longitude/latitude annotation. | ||
| 31 | + */ | ||
| 32 | +public class GeoDistanceLinkWeight implements LinkWeight { | ||
| 33 | + | ||
| 34 | + private static final double MAX_KM = 40_075 / 2.0; | ||
| 35 | + | ||
| 36 | + private final DeviceService deviceService; | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * Creates a new link-weight with access to the specified device service. | ||
| 40 | + * | ||
| 41 | + * @param deviceService device service reference | ||
| 42 | + */ | ||
| 43 | + public GeoDistanceLinkWeight(DeviceService deviceService) { | ||
| 44 | + this.deviceService = deviceService; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @Override | ||
| 48 | + public double weight(TopologyEdge edge) { | ||
| 49 | + GeoLocation src = getLocation(edge.link().src().deviceId()); | ||
| 50 | + GeoLocation dst = getLocation(edge.link().dst().deviceId()); | ||
| 51 | + return src != null && dst != null ? src.kilometersTo(dst) : MAX_KM; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + private GeoLocation getLocation(DeviceId deviceId) { | ||
| 55 | + Device d = deviceService.getDevice(deviceId); | ||
| 56 | + Annotations a = d != null ? d.annotations() : null; | ||
| 57 | + double latitude = getDouble(a, AnnotationKeys.LATITUDE); | ||
| 58 | + double longitude = getDouble(a, AnnotationKeys.LONGITUDE); | ||
| 59 | + return latitude == MAX_VALUE || longitude == MAX_VALUE ? null : | ||
| 60 | + new GeoLocation(latitude, longitude); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + private double getDouble(Annotations a, String key) { | ||
| 64 | + String value = a != null ? a.value(key) : null; | ||
| 65 | + try { | ||
| 66 | + return value != null ? Double.parseDouble(value) : MAX_VALUE; | ||
| 67 | + } catch (NumberFormatException e) { | ||
| 68 | + return MAX_VALUE; | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | +} | ||
| 72 | + |
| 1 | +package org.onosproject.net.topology; | ||
| 2 | + | ||
| 3 | +import static org.onosproject.net.Link.State.ACTIVE; | ||
| 4 | +import static org.onosproject.net.Link.Type.INDIRECT; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * Link weight for measuring link cost as hop count with indirect links | ||
| 8 | + * being as expensive as traversing the entire graph to assume the worst. | ||
| 9 | + */ | ||
| 10 | +public class HopCountLinkWeight implements LinkWeight { | ||
| 11 | + private final int indirectLinkCost; | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * Creates a new hop-count weight. | ||
| 15 | + */ | ||
| 16 | + public HopCountLinkWeight() { | ||
| 17 | + this.indirectLinkCost = Short.MAX_VALUE; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * Creates a new hop-count weight with the specified cost of indirect links. | ||
| 22 | + */ | ||
| 23 | + public HopCountLinkWeight(int indirectLinkCost) { | ||
| 24 | + this.indirectLinkCost = indirectLinkCost; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + @Override | ||
| 28 | + public double weight(TopologyEdge edge) { | ||
| 29 | + // To force preference to use direct paths first, make indirect | ||
| 30 | + // links as expensive as the linear vertex traversal. | ||
| 31 | + return edge.link().state() == | ||
| 32 | + ACTIVE ? (edge.link().type() == | ||
| 33 | + INDIRECT ? indirectLinkCost : 1) : -1; | ||
| 34 | + } | ||
| 35 | +} | ||
| 36 | + |
| 1 | +/* | ||
| 2 | + * Copyright 2014-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.topology; | ||
| 18 | + | ||
| 19 | +import org.onosproject.net.AnnotationKeys; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * Link weight for measuring link cost using the link metric annotation. | ||
| 23 | + */ | ||
| 24 | +public class MetricLinkWeight implements LinkWeight { | ||
| 25 | + | ||
| 26 | + @Override | ||
| 27 | + public double weight(TopologyEdge edge) { | ||
| 28 | + String v = edge.link().annotations().value(AnnotationKeys.METRIC); | ||
| 29 | + try { | ||
| 30 | + return v != null ? Double.parseDouble(v) : 1; | ||
| 31 | + } catch (NumberFormatException e) { | ||
| 32 | + return 1; | ||
| 33 | + } | ||
| 34 | + } | ||
| 35 | +} | ||
| 36 | + |
| 1 | +/* | ||
| 2 | + * Copyright 2014-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.topology; | ||
| 18 | + | ||
| 19 | +import org.onlab.graph.GraphPathSearch; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * Provides administrative abilities to tailor the path service behaviours. | ||
| 23 | + */ | ||
| 24 | +public interface PathAdminService { | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * Sets the specified link-weight function to be used as a default. | ||
| 28 | + * If null is specified, the builtin default hop-count link-weight will be | ||
| 29 | + * used. | ||
| 30 | + * | ||
| 31 | + * @param linkWeight default link-weight function | ||
| 32 | + */ | ||
| 33 | + void setDefaultLinkWeight(LinkWeight linkWeight); | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * Sets the specified graph path search algorightm to be used as a default. | ||
| 37 | + * If null is specified, the builtin default all-shortest-paths Dijkstra | ||
| 38 | + * algorithm will be used. | ||
| 39 | + * | ||
| 40 | + * @param graphPathSearch default graph path search algorithm | ||
| 41 | + */ | ||
| 42 | + void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch); | ||
| 43 | + | ||
| 44 | +} |
| ... | @@ -30,8 +30,9 @@ import java.util.Set; | ... | @@ -30,8 +30,9 @@ import java.util.Set; |
| 30 | public interface PathService { | 30 | public interface PathService { |
| 31 | 31 | ||
| 32 | /** | 32 | /** |
| 33 | - * Returns the set of all shortest paths, precomputed in terms of hop-count, | 33 | + * Returns the set of all shortest paths between the specified source and |
| 34 | - * between the specified source and destination elements. | 34 | + * destination elements. The path is computed using the default edge-weight |
| 35 | + * function, which by default is hop-count. | ||
| 35 | * | 36 | * |
| 36 | * @param src source element | 37 | * @param src source element |
| 37 | * @param dst destination element | 38 | * @param dst destination element |
| ... | @@ -40,9 +41,9 @@ public interface PathService { | ... | @@ -40,9 +41,9 @@ public interface PathService { |
| 40 | Set<Path> getPaths(ElementId src, ElementId dst); | 41 | Set<Path> getPaths(ElementId src, ElementId dst); |
| 41 | 42 | ||
| 42 | /** | 43 | /** |
| 43 | - * Returns the set of all shortest paths, computed using the supplied | 44 | + * Returns the set of all shortest paths between the specified source and |
| 44 | - * edge-weight entity, between the specified source and destination | 45 | + * destination network elements. The path is computed using the supplied |
| 45 | - * network elements. | 46 | + * edge-weight function. |
| 46 | * | 47 | * |
| 47 | * @param src source element | 48 | * @param src source element |
| 48 | * @param dst destination element | 49 | * @param dst destination element |
| ... | @@ -52,8 +53,9 @@ public interface PathService { | ... | @@ -52,8 +53,9 @@ public interface PathService { |
| 52 | Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight); | 53 | Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight); |
| 53 | 54 | ||
| 54 | /** | 55 | /** |
| 55 | - * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count, | 56 | + * Returns the set of all disjoint shortest path pairs between the |
| 56 | - * between the specified source and destination devices. | 57 | + * specified source and destination elements. The path is computed using |
| 58 | + * the default edge-weight function, which by default is hop-count. | ||
| 57 | * | 59 | * |
| 58 | * @param src source device | 60 | * @param src source device |
| 59 | * @param dst destination device | 61 | * @param dst destination device |
| ... | @@ -62,8 +64,9 @@ public interface PathService { | ... | @@ -62,8 +64,9 @@ public interface PathService { |
| 62 | Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst); | 64 | Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst); |
| 63 | 65 | ||
| 64 | /** | 66 | /** |
| 65 | - * Returns the set of all disjoint shortest path pairs, computed using the supplied | 67 | + * Returns the set of all disjoint shortest path pairs between the |
| 66 | - * edge-weight entity, between the specified source and destination devices. | 68 | + * specified source and destination elements. The path is computed using |
| 69 | + * the supplied edge-weight function. | ||
| 67 | * | 70 | * |
| 68 | * @param src source device | 71 | * @param src source device |
| 69 | * @param dst destination device | 72 | * @param dst destination device |
| ... | @@ -74,8 +77,10 @@ public interface PathService { | ... | @@ -74,8 +77,10 @@ public interface PathService { |
| 74 | LinkWeight weight); | 77 | LinkWeight weight); |
| 75 | 78 | ||
| 76 | /** | 79 | /** |
| 77 | - * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count, | 80 | + * Returns the set of all disjoint shortest path pairs between the |
| 78 | - * between the specified source and destination devices. | 81 | + * specified source and destination elements and taking into consideration |
| 82 | + * the provided risk profile. The path is computed using the default | ||
| 83 | + * edge-weight function, which by default is hop-count. | ||
| 79 | * | 84 | * |
| 80 | * @param src source device | 85 | * @param src source device |
| 81 | * @param dst destination device | 86 | * @param dst destination device |
| ... | @@ -86,8 +91,10 @@ public interface PathService { | ... | @@ -86,8 +91,10 @@ public interface PathService { |
| 86 | Map<Link, Object> riskProfile); | 91 | Map<Link, Object> riskProfile); |
| 87 | 92 | ||
| 88 | /** | 93 | /** |
| 89 | - * Returns the set of all disjoint shortest path pairs, precomputed in terms of hop-count, | 94 | + * Returns the set of all disjoint shortest path pairs between the |
| 90 | - * between the specified source and destination devices. | 95 | + * specified source and destination elements and taking into consideration |
| 96 | + * the provided risk profile. The path is computed using the supplied | ||
| 97 | + * edge-weight function. | ||
| 91 | * | 98 | * |
| 92 | * @param src source device | 99 | * @param src source device |
| 93 | * @param dst destination device | 100 | * @param dst destination device |
| ... | @@ -96,6 +103,7 @@ public interface PathService { | ... | @@ -96,6 +103,7 @@ public interface PathService { |
| 96 | * @return set of all shortest paths between the two devices | 103 | * @return set of all shortest paths between the two devices |
| 97 | */ | 104 | */ |
| 98 | Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, | 105 | Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, |
| 99 | - LinkWeight weight, Map<Link, Object> riskProfile); | 106 | + LinkWeight weight, |
| 107 | + Map<Link, Object> riskProfile); | ||
| 100 | 108 | ||
| 101 | } | 109 | } | ... | ... |
| ... | @@ -43,12 +43,15 @@ import org.onosproject.net.topology.ClusterId; | ... | @@ -43,12 +43,15 @@ import org.onosproject.net.topology.ClusterId; |
| 43 | import org.onosproject.net.topology.DefaultTopologyCluster; | 43 | import org.onosproject.net.topology.DefaultTopologyCluster; |
| 44 | import org.onosproject.net.topology.DefaultTopologyVertex; | 44 | import org.onosproject.net.topology.DefaultTopologyVertex; |
| 45 | import org.onosproject.net.topology.GraphDescription; | 45 | import org.onosproject.net.topology.GraphDescription; |
| 46 | +import org.onosproject.net.topology.HopCountLinkWeight; | ||
| 46 | import org.onosproject.net.topology.LinkWeight; | 47 | import org.onosproject.net.topology.LinkWeight; |
| 47 | import org.onosproject.net.topology.Topology; | 48 | import org.onosproject.net.topology.Topology; |
| 48 | import org.onosproject.net.topology.TopologyCluster; | 49 | import org.onosproject.net.topology.TopologyCluster; |
| 49 | import org.onosproject.net.topology.TopologyEdge; | 50 | import org.onosproject.net.topology.TopologyEdge; |
| 50 | import org.onosproject.net.topology.TopologyGraph; | 51 | import org.onosproject.net.topology.TopologyGraph; |
| 51 | import org.onosproject.net.topology.TopologyVertex; | 52 | import org.onosproject.net.topology.TopologyVertex; |
| 53 | +import org.slf4j.Logger; | ||
| 54 | +import org.slf4j.LoggerFactory; | ||
| 52 | 55 | ||
| 53 | import java.util.HashMap; | 56 | import java.util.HashMap; |
| 54 | import java.util.List; | 57 | import java.util.List; |
| ... | @@ -61,7 +64,6 @@ import static com.google.common.base.Preconditions.checkArgument; | ... | @@ -61,7 +64,6 @@ import static com.google.common.base.Preconditions.checkArgument; |
| 61 | import static org.onlab.graph.GraphPathSearch.ALL_PATHS; | 64 | import static org.onlab.graph.GraphPathSearch.ALL_PATHS; |
| 62 | import static org.onlab.util.Tools.isNullOrEmpty; | 65 | import static org.onlab.util.Tools.isNullOrEmpty; |
| 63 | import static org.onosproject.core.CoreService.CORE_PROVIDER_ID; | 66 | import static org.onosproject.core.CoreService.CORE_PROVIDER_ID; |
| 64 | -import static org.onosproject.net.Link.State.ACTIVE; | ||
| 65 | import static org.onosproject.net.Link.State.INACTIVE; | 67 | import static org.onosproject.net.Link.State.INACTIVE; |
| 66 | import static org.onosproject.net.Link.Type.INDIRECT; | 68 | import static org.onosproject.net.Link.Type.INDIRECT; |
| 67 | 69 | ||
| ... | @@ -71,18 +73,22 @@ import static org.onosproject.net.Link.Type.INDIRECT; | ... | @@ -71,18 +73,22 @@ import static org.onosproject.net.Link.Type.INDIRECT; |
| 71 | */ | 73 | */ |
| 72 | public class DefaultTopology extends AbstractModel implements Topology { | 74 | public class DefaultTopology extends AbstractModel implements Topology { |
| 73 | 75 | ||
| 76 | + private static final Logger log = LoggerFactory.getLogger(DefaultTopology.class); | ||
| 77 | + | ||
| 74 | private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>(); | 78 | private static final DijkstraGraphSearch<TopologyVertex, TopologyEdge> DIJKSTRA = new DijkstraGraphSearch<>(); |
| 75 | private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>(); | 79 | private static final TarjanGraphSearch<TopologyVertex, TopologyEdge> TARJAN = new TarjanGraphSearch<>(); |
| 76 | - private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE = | 80 | + private static final SuurballeGraphSearch<TopologyVertex, TopologyEdge> SUURBALLE = new SuurballeGraphSearch<>(); |
| 77 | - new SuurballeGraphSearch<>(); | ||
| 78 | 81 | ||
| 82 | + private static LinkWeight defaultLinkWeight = null; | ||
| 83 | + private static GraphPathSearch<TopologyVertex, TopologyEdge> defaultGraphPathSearch = null; | ||
| 79 | 84 | ||
| 80 | private final long time; | 85 | private final long time; |
| 81 | private final long creationTime; | 86 | private final long creationTime; |
| 82 | private final long computeCost; | 87 | private final long computeCost; |
| 83 | private final TopologyGraph graph; | 88 | private final TopologyGraph graph; |
| 84 | 89 | ||
| 85 | - private final LinkWeight weight; | 90 | + private final LinkWeight hopCountWeight; |
| 91 | + | ||
| 86 | private final Supplier<SccResult<TopologyVertex, TopologyEdge>> clusterResults; | 92 | private final Supplier<SccResult<TopologyVertex, TopologyEdge>> clusterResults; |
| 87 | private final Supplier<ImmutableMap<ClusterId, TopologyCluster>> clusters; | 93 | private final Supplier<ImmutableMap<ClusterId, TopologyCluster>> clusters; |
| 88 | private final Supplier<ImmutableSet<ConnectPoint>> infrastructurePoints; | 94 | private final Supplier<ImmutableSet<ConnectPoint>> infrastructurePoints; |
| ... | @@ -91,6 +97,30 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -91,6 +97,30 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 91 | private final Supplier<ClusterIndexes> clusterIndexes; | 97 | private final Supplier<ClusterIndexes> clusterIndexes; |
| 92 | 98 | ||
| 93 | /** | 99 | /** |
| 100 | + * Sets the default link-weight to be used when computing paths. If null is | ||
| 101 | + * specified, the builtin default link-weight measuring hop-counts will be | ||
| 102 | + * used. | ||
| 103 | + * | ||
| 104 | + * @param linkWeight new default link-weight | ||
| 105 | + */ | ||
| 106 | + public static void setDefaultLinkWeight(LinkWeight linkWeight) { | ||
| 107 | + log.info("Setting new default link-weight function to {}", linkWeight); | ||
| 108 | + defaultLinkWeight = linkWeight; | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + /** | ||
| 112 | + * Sets the default lpath search algorighm to be used when computing paths. | ||
| 113 | + * If null is specified, the builtin default Dijkstra will be used. | ||
| 114 | + * | ||
| 115 | + * @param graphPathSearch new default algorithm | ||
| 116 | + */ | ||
| 117 | + public static void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) { | ||
| 118 | + log.info("Setting new default graph path algorithm to {}", graphPathSearch); | ||
| 119 | + defaultGraphPathSearch = graphPathSearch; | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + | ||
| 123 | + /** | ||
| 94 | * Creates a topology descriptor attributed to the specified provider. | 124 | * Creates a topology descriptor attributed to the specified provider. |
| 95 | * | 125 | * |
| 96 | * @param providerId identity of the provider | 126 | * @param providerId identity of the provider |
| ... | @@ -113,7 +143,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -113,7 +143,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 113 | 143 | ||
| 114 | this.clusterIndexes = Suppliers.memoize(() -> buildIndexes()); | 144 | this.clusterIndexes = Suppliers.memoize(() -> buildIndexes()); |
| 115 | 145 | ||
| 116 | - this.weight = new HopCountLinkWeight(graph.getVertexes().size()); | 146 | + this.hopCountWeight = new HopCountLinkWeight(graph.getVertexes().size()); |
| 117 | this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets()); | 147 | this.broadcastSets = Suppliers.memoize(() -> buildBroadcastSets()); |
| 118 | this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints()); | 148 | this.infrastructurePoints = Suppliers.memoize(() -> findInfrastructurePoints()); |
| 119 | this.computeCost = Math.max(0, System.nanoTime() - time); | 149 | this.computeCost = Math.max(0, System.nanoTime() - time); |
| ... | @@ -294,7 +324,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -294,7 +324,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 294 | * @return set of shortest paths | 324 | * @return set of shortest paths |
| 295 | */ | 325 | */ |
| 296 | public Set<Path> getPaths(DeviceId src, DeviceId dst) { | 326 | public Set<Path> getPaths(DeviceId src, DeviceId dst) { |
| 297 | - return getPaths(src, dst, null); | 327 | + return getPaths(src, dst, linkWeight()); |
| 298 | } | 328 | } |
| 299 | 329 | ||
| 300 | /** | 330 | /** |
| ... | @@ -307,8 +337,8 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -307,8 +337,8 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 307 | * @return set of shortest paths | 337 | * @return set of shortest paths |
| 308 | */ | 338 | */ |
| 309 | public Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { | 339 | public Set<Path> getPaths(DeviceId src, DeviceId dst, LinkWeight weight) { |
| 310 | - final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); | 340 | + DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); |
| 311 | - final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); | 341 | + DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); |
| 312 | Set<TopologyVertex> vertices = graph.getVertexes(); | 342 | Set<TopologyVertex> vertices = graph.getVertexes(); |
| 313 | if (!vertices.contains(srcV) || !vertices.contains(dstV)) { | 343 | if (!vertices.contains(srcV) || !vertices.contains(dstV)) { |
| 314 | // src or dst not part of the current graph | 344 | // src or dst not part of the current graph |
| ... | @@ -316,7 +346,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -316,7 +346,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 316 | } | 346 | } |
| 317 | 347 | ||
| 318 | GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = | 348 | GraphPathSearch.Result<TopologyVertex, TopologyEdge> result = |
| 319 | - DIJKSTRA.search(graph, srcV, dstV, weight, ALL_PATHS); | 349 | + graphPathSearch().search(graph, srcV, dstV, weight, ALL_PATHS); |
| 320 | ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); | 350 | ImmutableSet.Builder<Path> builder = ImmutableSet.builder(); |
| 321 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { | 351 | for (org.onlab.graph.Path<TopologyVertex, TopologyEdge> path : result.paths()) { |
| 322 | builder.add(networkPath(path)); | 352 | builder.add(networkPath(path)); |
| ... | @@ -334,7 +364,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -334,7 +364,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 334 | * @return set of shortest disjoint path pairs | 364 | * @return set of shortest disjoint path pairs |
| 335 | */ | 365 | */ |
| 336 | public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst) { | 366 | public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst) { |
| 337 | - return getDisjointPaths(src, dst, (LinkWeight) null); | 367 | + return getDisjointPaths(src, dst, linkWeight()); |
| 338 | } | 368 | } |
| 339 | 369 | ||
| 340 | /** | 370 | /** |
| ... | @@ -347,8 +377,8 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -347,8 +377,8 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 347 | * @return set of disjoint shortest path pairs | 377 | * @return set of disjoint shortest path pairs |
| 348 | */ | 378 | */ |
| 349 | public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight) { | 379 | public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, LinkWeight weight) { |
| 350 | - final DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); | 380 | + DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); |
| 351 | - final DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); | 381 | + DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); |
| 352 | Set<TopologyVertex> vertices = graph.getVertexes(); | 382 | Set<TopologyVertex> vertices = graph.getVertexes(); |
| 353 | if (!vertices.contains(srcV) || !vertices.contains(dstV)) { | 383 | if (!vertices.contains(srcV) || !vertices.contains(dstV)) { |
| 354 | // src or dst not part of the current graph | 384 | // src or dst not part of the current graph |
| ... | @@ -375,7 +405,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -375,7 +405,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 375 | * @return set of shortest disjoint paths | 405 | * @return set of shortest disjoint paths |
| 376 | */ | 406 | */ |
| 377 | private Set<DisjointPath> disjointPaths(DeviceId src, DeviceId dst, LinkWeight weight, | 407 | private Set<DisjointPath> disjointPaths(DeviceId src, DeviceId dst, LinkWeight weight, |
| 378 | - Map<TopologyEdge, Object> riskProfile) { | 408 | + Map<TopologyEdge, Object> riskProfile) { |
| 379 | DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); | 409 | DefaultTopologyVertex srcV = new DefaultTopologyVertex(src); |
| 380 | DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); | 410 | DefaultTopologyVertex dstV = new DefaultTopologyVertex(dst); |
| 381 | 411 | ||
| ... | @@ -438,7 +468,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -438,7 +468,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 438 | * @return set of shortest disjoint paths | 468 | * @return set of shortest disjoint paths |
| 439 | */ | 469 | */ |
| 440 | public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, Map<Link, Object> riskProfile) { | 470 | public Set<DisjointPath> getDisjointPaths(DeviceId src, DeviceId dst, Map<Link, Object> riskProfile) { |
| 441 | - return getDisjointPaths(src, dst, null, riskProfile); | 471 | + return getDisjointPaths(src, dst, linkWeight(), riskProfile); |
| 442 | } | 472 | } |
| 443 | 473 | ||
| 444 | // Converts graph path to a network path with the same cost. | 474 | // Converts graph path to a network path with the same cost. |
| ... | @@ -499,8 +529,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -499,8 +529,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 499 | 529 | ||
| 500 | // Processes a map of broadcast sets for each cluster. | 530 | // Processes a map of broadcast sets for each cluster. |
| 501 | private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() { | 531 | private ImmutableSetMultimap<ClusterId, ConnectPoint> buildBroadcastSets() { |
| 502 | - Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap | 532 | + Builder<ClusterId, ConnectPoint> builder = ImmutableSetMultimap.builder(); |
| 503 | - .builder(); | ||
| 504 | for (TopologyCluster cluster : clusters.get().values()) { | 533 | for (TopologyCluster cluster : clusters.get().values()) { |
| 505 | addClusterBroadcastSet(cluster, builder); | 534 | addClusterBroadcastSet(cluster, builder); |
| 506 | } | 535 | } |
| ... | @@ -512,7 +541,7 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -512,7 +541,7 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 512 | // all other devices within the cluster. | 541 | // all other devices within the cluster. |
| 513 | private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) { | 542 | private void addClusterBroadcastSet(TopologyCluster cluster, Builder<ClusterId, ConnectPoint> builder) { |
| 514 | // Use the graph root search results to build the broadcast set. | 543 | // Use the graph root search results to build the broadcast set. |
| 515 | - Result<TopologyVertex, TopologyEdge> result = DIJKSTRA.search(graph, cluster.root(), null, weight, 1); | 544 | + Result<TopologyVertex, TopologyEdge> result = DIJKSTRA.search(graph, cluster.root(), null, hopCountWeight, 1); |
| 516 | for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) { | 545 | for (Map.Entry<TopologyVertex, Set<TopologyEdge>> entry : result.parents().entrySet()) { |
| 517 | TopologyVertex vertex = entry.getKey(); | 546 | TopologyVertex vertex = entry.getKey(); |
| 518 | 547 | ||
| ... | @@ -577,23 +606,12 @@ public class DefaultTopology extends AbstractModel implements Topology { | ... | @@ -577,23 +606,12 @@ public class DefaultTopology extends AbstractModel implements Topology { |
| 577 | linksBuilder.build()); | 606 | linksBuilder.build()); |
| 578 | } | 607 | } |
| 579 | 608 | ||
| 580 | - // Link weight for measuring link cost as hop count with indirect links | 609 | + private GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch() { |
| 581 | - // being as expensive as traversing the entire graph to assume the worst. | 610 | + return defaultGraphPathSearch != null ? defaultGraphPathSearch : DIJKSTRA; |
| 582 | - private static class HopCountLinkWeight implements LinkWeight { | 611 | + } |
| 583 | - private final int indirectLinkCost; | ||
| 584 | - | ||
| 585 | - HopCountLinkWeight(int indirectLinkCost) { | ||
| 586 | - this.indirectLinkCost = indirectLinkCost; | ||
| 587 | - } | ||
| 588 | 612 | ||
| 589 | - @Override | 613 | + private LinkWeight linkWeight() { |
| 590 | - public double weight(TopologyEdge edge) { | 614 | + return defaultLinkWeight != null ? defaultLinkWeight : hopCountWeight; |
| 591 | - // To force preference to use direct paths first, make indirect | ||
| 592 | - // links as expensive as the linear vertex traversal. | ||
| 593 | - return edge.link().state() == | ||
| 594 | - ACTIVE ? (edge.link().type() == | ||
| 595 | - INDIRECT ? indirectLinkCost : 1) : -1; | ||
| 596 | - } | ||
| 597 | } | 615 | } |
| 598 | 616 | ||
| 599 | // Link weight for preventing traversal over indirect links. | 617 | // Link weight for preventing traversal over indirect links. | ... | ... |
| ... | @@ -38,6 +38,7 @@ import org.slf4j.Logger; | ... | @@ -38,6 +38,7 @@ import org.slf4j.Logger; |
| 38 | public final class BasicLinkOperator implements ConfigOperator { | 38 | public final class BasicLinkOperator implements ConfigOperator { |
| 39 | 39 | ||
| 40 | private static final long DEF_BANDWIDTH = -1L; | 40 | private static final long DEF_BANDWIDTH = -1L; |
| 41 | + private static final double DEF_METRIC = -1; | ||
| 41 | private static final Duration DEF_DURATION = Duration.ofNanos(-1L); | 42 | private static final Duration DEF_DURATION = Duration.ofNanos(-1L); |
| 42 | private static final Logger log = getLogger(BasicLinkOperator.class); | 43 | private static final Logger log = getLogger(BasicLinkOperator.class); |
| 43 | 44 | ||
| ... | @@ -77,6 +78,9 @@ public final class BasicLinkOperator implements ConfigOperator { | ... | @@ -77,6 +78,9 @@ public final class BasicLinkOperator implements ConfigOperator { |
| 77 | */ | 78 | */ |
| 78 | public static SparseAnnotations combine(BasicLinkConfig cfg, SparseAnnotations an) { | 79 | public static SparseAnnotations combine(BasicLinkConfig cfg, SparseAnnotations an) { |
| 79 | DefaultAnnotations.Builder b = DefaultAnnotations.builder(); | 80 | DefaultAnnotations.Builder b = DefaultAnnotations.builder(); |
| 81 | + if (cfg.metric() != DEF_METRIC) { | ||
| 82 | + b.set(AnnotationKeys.METRIC, String.valueOf(cfg.metric())); | ||
| 83 | + } | ||
| 80 | if (cfg.latency() != DEF_DURATION) { | 84 | if (cfg.latency() != DEF_DURATION) { |
| 81 | b.set(AnnotationKeys.LATENCY, cfg.latency().toString()); | 85 | b.set(AnnotationKeys.LATENCY, cfg.latency().toString()); |
| 82 | } | 86 | } | ... | ... |
| ... | @@ -15,44 +15,43 @@ | ... | @@ -15,44 +15,43 @@ |
| 15 | */ | 15 | */ |
| 16 | package org.onosproject.store.topology.impl; | 16 | package org.onosproject.store.topology.impl; |
| 17 | 17 | ||
| 18 | -import static com.google.common.base.Preconditions.checkArgument; | ||
| 19 | -import static org.onlab.util.Tools.isNullOrEmpty; | ||
| 20 | -import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED; | ||
| 21 | -import static org.slf4j.LoggerFactory.getLogger; | ||
| 22 | - | ||
| 23 | -import java.util.Collections; | ||
| 24 | -import java.util.Map; | ||
| 25 | -import java.util.List; | ||
| 26 | -import java.util.Set; | ||
| 27 | -import java.util.stream.Collectors; | ||
| 28 | - | ||
| 29 | import org.apache.felix.scr.annotations.Activate; | 18 | import org.apache.felix.scr.annotations.Activate; |
| 30 | import org.apache.felix.scr.annotations.Component; | 19 | import org.apache.felix.scr.annotations.Component; |
| 31 | import org.apache.felix.scr.annotations.Deactivate; | 20 | import org.apache.felix.scr.annotations.Deactivate; |
| 21 | +import org.apache.felix.scr.annotations.Modified; | ||
| 22 | +import org.apache.felix.scr.annotations.Property; | ||
| 32 | import org.apache.felix.scr.annotations.Reference; | 23 | import org.apache.felix.scr.annotations.Reference; |
| 33 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 34 | import org.apache.felix.scr.annotations.Service; | 25 | import org.apache.felix.scr.annotations.Service; |
| 26 | +import org.onlab.graph.GraphPathSearch; | ||
| 35 | import org.onlab.util.KryoNamespace; | 27 | import org.onlab.util.KryoNamespace; |
| 28 | +import org.onosproject.cfg.ComponentConfigService; | ||
| 36 | import org.onosproject.common.DefaultTopology; | 29 | import org.onosproject.common.DefaultTopology; |
| 37 | import org.onosproject.event.Event; | 30 | import org.onosproject.event.Event; |
| 38 | import org.onosproject.mastership.MastershipService; | 31 | import org.onosproject.mastership.MastershipService; |
| 39 | import org.onosproject.net.ConnectPoint; | 32 | import org.onosproject.net.ConnectPoint; |
| 40 | import org.onosproject.net.Device; | 33 | import org.onosproject.net.Device; |
| 41 | import org.onosproject.net.DeviceId; | 34 | import org.onosproject.net.DeviceId; |
| 35 | +import org.onosproject.net.DisjointPath; | ||
| 42 | import org.onosproject.net.Link; | 36 | import org.onosproject.net.Link; |
| 43 | import org.onosproject.net.Path; | 37 | import org.onosproject.net.Path; |
| 44 | -import org.onosproject.net.DisjointPath; | 38 | +import org.onosproject.net.device.DeviceService; |
| 45 | import org.onosproject.net.provider.ProviderId; | 39 | import org.onosproject.net.provider.ProviderId; |
| 46 | import org.onosproject.net.topology.ClusterId; | 40 | import org.onosproject.net.topology.ClusterId; |
| 47 | import org.onosproject.net.topology.DefaultGraphDescription; | 41 | import org.onosproject.net.topology.DefaultGraphDescription; |
| 42 | +import org.onosproject.net.topology.GeoDistanceLinkWeight; | ||
| 48 | import org.onosproject.net.topology.GraphDescription; | 43 | import org.onosproject.net.topology.GraphDescription; |
| 49 | import org.onosproject.net.topology.LinkWeight; | 44 | import org.onosproject.net.topology.LinkWeight; |
| 45 | +import org.onosproject.net.topology.MetricLinkWeight; | ||
| 46 | +import org.onosproject.net.topology.PathAdminService; | ||
| 50 | import org.onosproject.net.topology.Topology; | 47 | import org.onosproject.net.topology.Topology; |
| 51 | import org.onosproject.net.topology.TopologyCluster; | 48 | import org.onosproject.net.topology.TopologyCluster; |
| 49 | +import org.onosproject.net.topology.TopologyEdge; | ||
| 52 | import org.onosproject.net.topology.TopologyEvent; | 50 | import org.onosproject.net.topology.TopologyEvent; |
| 53 | import org.onosproject.net.topology.TopologyGraph; | 51 | import org.onosproject.net.topology.TopologyGraph; |
| 54 | import org.onosproject.net.topology.TopologyStore; | 52 | import org.onosproject.net.topology.TopologyStore; |
| 55 | import org.onosproject.net.topology.TopologyStoreDelegate; | 53 | import org.onosproject.net.topology.TopologyStoreDelegate; |
| 54 | +import org.onosproject.net.topology.TopologyVertex; | ||
| 56 | import org.onosproject.store.AbstractStore; | 55 | import org.onosproject.store.AbstractStore; |
| 57 | import org.onosproject.store.serializers.KryoNamespaces; | 56 | import org.onosproject.store.serializers.KryoNamespaces; |
| 58 | import org.onosproject.store.service.EventuallyConsistentMap; | 57 | import org.onosproject.store.service.EventuallyConsistentMap; |
| ... | @@ -60,8 +59,23 @@ import org.onosproject.store.service.EventuallyConsistentMapEvent; | ... | @@ -60,8 +59,23 @@ import org.onosproject.store.service.EventuallyConsistentMapEvent; |
| 60 | import org.onosproject.store.service.EventuallyConsistentMapListener; | 59 | import org.onosproject.store.service.EventuallyConsistentMapListener; |
| 61 | import org.onosproject.store.service.LogicalClockService; | 60 | import org.onosproject.store.service.LogicalClockService; |
| 62 | import org.onosproject.store.service.StorageService; | 61 | import org.onosproject.store.service.StorageService; |
| 62 | +import org.osgi.service.component.ComponentContext; | ||
| 63 | import org.slf4j.Logger; | 63 | import org.slf4j.Logger; |
| 64 | 64 | ||
| 65 | +import java.util.Collections; | ||
| 66 | +import java.util.Dictionary; | ||
| 67 | +import java.util.List; | ||
| 68 | +import java.util.Map; | ||
| 69 | +import java.util.Objects; | ||
| 70 | +import java.util.Set; | ||
| 71 | +import java.util.stream.Collectors; | ||
| 72 | + | ||
| 73 | +import static com.google.common.base.Preconditions.checkArgument; | ||
| 74 | +import static org.onlab.util.Tools.get; | ||
| 75 | +import static org.onlab.util.Tools.isNullOrEmpty; | ||
| 76 | +import static org.onosproject.net.topology.TopologyEvent.Type.TOPOLOGY_CHANGED; | ||
| 77 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 78 | + | ||
| 65 | /** | 79 | /** |
| 66 | * Manages inventory of topology snapshots using trivial in-memory | 80 | * Manages inventory of topology snapshots using trivial in-memory |
| 67 | * structures implementation. | 81 | * structures implementation. |
| ... | @@ -73,9 +87,12 @@ import org.slf4j.Logger; | ... | @@ -73,9 +87,12 @@ import org.slf4j.Logger; |
| 73 | @Service | 87 | @Service |
| 74 | public class DistributedTopologyStore | 88 | public class DistributedTopologyStore |
| 75 | extends AbstractStore<TopologyEvent, TopologyStoreDelegate> | 89 | extends AbstractStore<TopologyEvent, TopologyStoreDelegate> |
| 76 | - implements TopologyStore { | 90 | + implements TopologyStore, PathAdminService { |
| 77 | 91 | ||
| 78 | private final Logger log = getLogger(getClass()); | 92 | private final Logger log = getLogger(getClass()); |
| 93 | + | ||
| 94 | + private static final String FORMAT = "Settings: linkWeightFunction={}"; | ||
| 95 | + | ||
| 79 | private volatile DefaultTopology current = | 96 | private volatile DefaultTopology current = |
| 80 | new DefaultTopology(ProviderId.NONE, | 97 | new DefaultTopology(ProviderId.NONE, |
| 81 | new DefaultGraphDescription(0L, System.currentTimeMillis(), | 98 | new DefaultGraphDescription(0L, System.currentTimeMillis(), |
| ... | @@ -91,6 +108,21 @@ public class DistributedTopologyStore | ... | @@ -91,6 +108,21 @@ public class DistributedTopologyStore |
| 91 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 108 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 92 | protected MastershipService mastershipService; | 109 | protected MastershipService mastershipService; |
| 93 | 110 | ||
| 111 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 112 | + protected ComponentConfigService configService; | ||
| 113 | + | ||
| 114 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
| 115 | + protected DeviceService deviceService; | ||
| 116 | + | ||
| 117 | + private static final String HOP_COUNT = "hopCount"; | ||
| 118 | + private static final String LINK_METRIC = "linkMetric"; | ||
| 119 | + private static final String GEO_DISTANCE = "geoDistance"; | ||
| 120 | + | ||
| 121 | + private static final String DEFAULT_LINK_WEIGHT_FUNCTION = "hopCount"; | ||
| 122 | + @Property(name = "linkWeightFunction", value = DEFAULT_LINK_WEIGHT_FUNCTION, | ||
| 123 | + label = "Default link-weight function: hopCount, linkMetric, geoDistance") | ||
| 124 | + private String linkWeightFunction = DEFAULT_LINK_WEIGHT_FUNCTION; | ||
| 125 | + | ||
| 94 | // Cluster root to broadcast points bindings to allow convergence to | 126 | // Cluster root to broadcast points bindings to allow convergence to |
| 95 | // a shared broadcast tree; node that is the master of the cluster root | 127 | // a shared broadcast tree; node that is the master of the cluster root |
| 96 | // is the primary. | 128 | // is the primary. |
| ... | @@ -100,7 +132,8 @@ public class DistributedTopologyStore | ... | @@ -100,7 +132,8 @@ public class DistributedTopologyStore |
| 100 | new InternalBroadcastPointListener(); | 132 | new InternalBroadcastPointListener(); |
| 101 | 133 | ||
| 102 | @Activate | 134 | @Activate |
| 103 | - public void activate() { | 135 | + protected void activate() { |
| 136 | + configService.registerProperties(getClass()); | ||
| 104 | KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() | 137 | KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() |
| 105 | .register(KryoNamespaces.API); | 138 | .register(KryoNamespaces.API); |
| 106 | 139 | ||
| ... | @@ -114,12 +147,30 @@ public class DistributedTopologyStore | ... | @@ -114,12 +147,30 @@ public class DistributedTopologyStore |
| 114 | } | 147 | } |
| 115 | 148 | ||
| 116 | @Deactivate | 149 | @Deactivate |
| 117 | - public void deactivate() { | 150 | + protected void deactivate() { |
| 151 | + configService.unregisterProperties(getClass(), false); | ||
| 118 | broadcastPoints.removeListener(listener); | 152 | broadcastPoints.removeListener(listener); |
| 119 | broadcastPoints.destroy(); | 153 | broadcastPoints.destroy(); |
| 120 | log.info("Stopped"); | 154 | log.info("Stopped"); |
| 121 | } | 155 | } |
| 122 | 156 | ||
| 157 | + @Modified | ||
| 158 | + protected void modified(ComponentContext context) { | ||
| 159 | + Dictionary<?, ?> properties = context.getProperties(); | ||
| 160 | + | ||
| 161 | + String newLinkWeightFunction = get(properties, "linkWeightFunction"); | ||
| 162 | + if (newLinkWeightFunction != null && | ||
| 163 | + !Objects.equals(newLinkWeightFunction, linkWeightFunction)) { | ||
| 164 | + linkWeightFunction = newLinkWeightFunction; | ||
| 165 | + LinkWeight weight = linkWeightFunction.equals(LINK_METRIC) ? | ||
| 166 | + new MetricLinkWeight() : | ||
| 167 | + linkWeightFunction.equals(GEO_DISTANCE) ? | ||
| 168 | + new GeoDistanceLinkWeight(deviceService) : null; | ||
| 169 | + setDefaultLinkWeight(weight); | ||
| 170 | + } | ||
| 171 | + log.info(FORMAT, linkWeightFunction); | ||
| 172 | + } | ||
| 173 | + | ||
| 123 | @Override | 174 | @Override |
| 124 | public Topology currentTopology() { | 175 | public Topology currentTopology() { |
| 125 | return current; | 176 | return current; |
| ... | @@ -263,6 +314,16 @@ public class DistributedTopologyStore | ... | @@ -263,6 +314,16 @@ public class DistributedTopologyStore |
| 263 | return (DefaultTopology) topology; | 314 | return (DefaultTopology) topology; |
| 264 | } | 315 | } |
| 265 | 316 | ||
| 317 | + @Override | ||
| 318 | + public void setDefaultLinkWeight(LinkWeight linkWeight) { | ||
| 319 | + DefaultTopology.setDefaultLinkWeight(linkWeight); | ||
| 320 | + } | ||
| 321 | + | ||
| 322 | + @Override | ||
| 323 | + public void setDefaultGraphPathSearch(GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) { | ||
| 324 | + DefaultTopology.setDefaultGraphPathSearch(graphPathSearch); | ||
| 325 | + } | ||
| 326 | + | ||
| 266 | private class InternalBroadcastPointListener | 327 | private class InternalBroadcastPointListener |
| 267 | implements EventuallyConsistentMapListener<DeviceId, Set<ConnectPoint>> { | 328 | implements EventuallyConsistentMapListener<DeviceId, Set<ConnectPoint>> { |
| 268 | @Override | 329 | @Override | ... | ... |
| ... | @@ -168,7 +168,7 @@ public class NullProviders { | ... | @@ -168,7 +168,7 @@ public class NullProviders { |
| 168 | 168 | ||
| 169 | 169 | ||
| 170 | @Activate | 170 | @Activate |
| 171 | - public void activate(ComponentContext context) { | 171 | + public void activate() { |
| 172 | cfgService.registerProperties(getClass()); | 172 | cfgService.registerProperties(getClass()); |
| 173 | 173 | ||
| 174 | deviceProviderService = deviceProviderRegistry.register(deviceProvider); | 174 | deviceProviderService = deviceProviderRegistry.register(deviceProvider); |
| ... | @@ -180,7 +180,7 @@ public class NullProviders { | ... | @@ -180,7 +180,7 @@ public class NullProviders { |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | @Deactivate | 182 | @Deactivate |
| 183 | - public void deactivate(ComponentContext context) { | 183 | + public void deactivate() { |
| 184 | cfgService.unregisterProperties(getClass(), false); | 184 | cfgService.unregisterProperties(getClass(), false); |
| 185 | tearDown(); | 185 | tearDown(); |
| 186 | 186 | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2014-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.onlab.util; | ||
| 18 | + | ||
| 19 | +import com.google.common.base.MoreObjects; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * Geo location specified in terms of longitude and latitude. | ||
| 23 | + */ | ||
| 24 | +public class GeoLocation { | ||
| 25 | + | ||
| 26 | + public static final double EARTH_RADIUS_KM = 6378.1370D; | ||
| 27 | + | ||
| 28 | + private final double latitude; | ||
| 29 | + private final double longitude; | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * Creates a new location using the specified coordinates. | ||
| 33 | + * | ||
| 34 | + * @param latitude latitude line | ||
| 35 | + * @param longitude longitude line | ||
| 36 | + */ | ||
| 37 | + public GeoLocation(double latitude, double longitude) { | ||
| 38 | + this.latitude = latitude; | ||
| 39 | + this.longitude = longitude; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * Returns the latitude of this location. | ||
| 44 | + * | ||
| 45 | + * @return latitude | ||
| 46 | + */ | ||
| 47 | + public double latitude() { | ||
| 48 | + return latitude; | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * Returns the longitude of this location. | ||
| 53 | + * | ||
| 54 | + * @return longitude | ||
| 55 | + */ | ||
| 56 | + public double longitude() { | ||
| 57 | + return longitude; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * Returns the distance in kilometers, between this location and another. | ||
| 62 | + * | ||
| 63 | + * @param other other geo location | ||
| 64 | + * @return distance in kilometers | ||
| 65 | + */ | ||
| 66 | + public double kilometersTo(GeoLocation other) { | ||
| 67 | + double hereLat = Math.toRadians(latitude); | ||
| 68 | + double hereLon = Math.toRadians(longitude); | ||
| 69 | + double thereLat = Math.toRadians(other.latitude); | ||
| 70 | + double thereLon = Math.toRadians(other.longitude); | ||
| 71 | + | ||
| 72 | + double cos = Math.sin(hereLat) * Math.sin(thereLat) + | ||
| 73 | + Math.cos(hereLat) * Math.cos(thereLat) * Math.cos(hereLon - thereLon); | ||
| 74 | + return Math.acos(cos) * EARTH_RADIUS_KM; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Override | ||
| 78 | + public String toString() { | ||
| 79 | + return MoreObjects.toStringHelper(this) | ||
| 80 | + .add("latitude", latitude) | ||
| 81 | + .add("longitude", longitude) | ||
| 82 | + .toString(); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2014-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.onlab.util; | ||
| 18 | + | ||
| 19 | +import org.junit.Test; | ||
| 20 | + | ||
| 21 | +import static org.junit.Assert.assertEquals; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Test suite of the geo location. | ||
| 25 | + */ | ||
| 26 | +public class GeoLocationTest { | ||
| 27 | + | ||
| 28 | + @Test | ||
| 29 | + public void basics() { | ||
| 30 | + GeoLocation nLoc = new GeoLocation(40.7127, -74.0059); | ||
| 31 | + GeoLocation wLoc = new GeoLocation(38.9047, -77.0164); | ||
| 32 | + | ||
| 33 | + assertEquals("incorrect latitude", 40.7127, nLoc.latitude(), 0.0001); | ||
| 34 | + assertEquals("incorrect longitude", -74.00598, nLoc.longitude(), 0.0001); | ||
| 35 | + assertEquals("incorrect distance", 326.74, nLoc.kilometersTo(wLoc), 0.01); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment