blob: 74e94b12b6dd00052fe8c42b3941094df4a3a3ff [file] [log] [blame]
Thomas Vachuskaedc944c2014-11-04 15:42:25 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuskaedc944c2014-11-04 15:42:25 -08003 *
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 */
Sho SHIMIZU6c28f832015-02-20 16:12:19 -080016package org.onosproject.net.intent.impl.compiler;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080017
Sho SHIMIZU9909d172014-11-11 18:33:11 -080018import com.google.common.collect.FluentIterable;
Sho SHIMIZU56531512014-11-10 15:27:49 -080019import com.google.common.collect.ImmutableList;
Brian O'Connor023a1c72015-03-20 01:11:29 +000020import org.apache.felix.scr.annotations.Component;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080021import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
Andrey Komarov2398d962016-09-26 15:11:23 +030023import org.onlab.graph.DefaultEdgeWeigher;
24import org.onlab.graph.ScalarWeight;
25import org.onlab.graph.Weight;
helenyrwu2a674902016-07-20 09:48:04 -070026import org.onosproject.net.DisjointPath;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.ElementId;
28import org.onosproject.net.Path;
29import org.onosproject.net.intent.ConnectivityIntent;
30import org.onosproject.net.intent.Constraint;
31import org.onosproject.net.intent.IntentCompiler;
32import org.onosproject.net.intent.IntentExtensionService;
jaegonkim7e876632017-01-25 06:01:49 +090033import org.onosproject.net.intent.constraint.HashedPathSelectionConstraint;
Sho SHIMIZU6c28f832015-02-20 16:12:19 -080034import org.onosproject.net.intent.impl.PathNotFoundException;
Sho SHIMIZUa6b4dc72016-03-11 19:00:20 -080035import org.onosproject.net.resource.ResourceQueryService;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.provider.ProviderId;
Andrey Komarov2398d962016-09-26 15:11:23 +030037import org.onosproject.net.topology.LinkWeigher;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.topology.PathService;
39import org.onosproject.net.topology.TopologyEdge;
Andrey Komarov2398d962016-09-26 15:11:23 +030040import org.onosproject.net.topology.TopologyVertex;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080041
Sho SHIMIZU56531512014-11-10 15:27:49 -080042import java.util.Collections;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080043import java.util.Iterator;
44import java.util.List;
45import java.util.Set;
46
47/**
48 * Base class for compilers of various
Brian O'Connorabafb502014-12-02 22:26:20 -080049 * {@link org.onosproject.net.intent.ConnectivityIntent connectivity intents}.
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080050 */
Brian O'Connor023a1c72015-03-20 01:11:29 +000051@Component(immediate = true)
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080052public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent>
53 implements IntentCompiler<T> {
54
Brian O'Connorabafb502014-12-02 22:26:20 -080055 private static final ProviderId PID = new ProviderId("core", "org.onosproject.core", true);
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080056
57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 protected IntentExtensionService intentManager;
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected PathService pathService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZUa6b4dc72016-03-11 19:00:20 -080064 protected ResourceQueryService resourceService;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080065
66 /**
67 * Returns an edge-weight capable of evaluating links on the basis of the
68 * specified constraints.
69 *
70 * @param constraints path constraints
71 * @return edge-weight function
72 */
Andrey Komarov2398d962016-09-26 15:11:23 +030073 protected LinkWeigher weigher(List<Constraint> constraints) {
74 return new ConstraintBasedLinkWeigher(constraints);
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080075 }
76
77 /**
78 * Validates the specified path against the given constraints.
79 *
Thomas Vachuskab14c77a2014-11-04 18:08:01 -080080 * @param path path to be checked
81 * @param constraints path constraints
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080082 * @return true if the path passes all constraints
83 */
84 protected boolean checkPath(Path path, List<Constraint> constraints) {
85 for (Constraint constraint : constraints) {
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -080086 if (!constraint.validate(path, resourceService::isAvailable)) {
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080087 return false;
88 }
89 }
90 return true;
91 }
92
93 /**
94 * Computes a path between two ConnectPoints.
95 *
Thomas Vachuskab14c77a2014-11-04 18:08:01 -080096 * @param intent intent on which behalf path is being computed
97 * @param one start of the path
98 * @param two end of the path
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080099 * @return Path between the two
100 * @throws PathNotFoundException if a path cannot be found
101 */
Luca Preted26ea652017-01-03 15:59:30 -0800102 @Deprecated
103 protected Path getPathOrException(ConnectivityIntent intent,
104 ElementId one, ElementId two) {
105 Path path = getPath(intent, one, two);
106 if (path == null) {
107 throw new PathNotFoundException(one, two);
108 }
109 // TODO: let's be more intelligent about this eventually
110 return path;
111 }
112
113 /**
114 * Computes a path between two ConnectPoints.
115 *
116 * @param intent intent on which behalf path is being computed
117 * @param one start of the path
118 * @param two end of the path
119 * @return Path between the two, or null if no path can be found
120 */
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800121 protected Path getPath(ConnectivityIntent intent,
122 ElementId one, ElementId two) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300123 Set<Path> paths = pathService.getPaths(one, two, weigher(intent.constraints()));
Sho SHIMIZU9909d172014-11-11 18:33:11 -0800124 final List<Constraint> constraints = intent.constraints();
125 ImmutableList<Path> filtered = FluentIterable.from(paths)
Sho SHIMIZU8b7b3b22015-09-04 16:04:50 -0700126 .filter(path -> checkPath(path, constraints))
127 .toList();
Sho SHIMIZU9909d172014-11-11 18:33:11 -0800128 if (filtered.isEmpty()) {
Luca Preted26ea652017-01-03 15:59:30 -0800129 return null;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800130 }
jaegonkim7e876632017-01-25 06:01:49 +0900131
132 if (constraints.stream().anyMatch(c -> c instanceof HashedPathSelectionConstraint)) {
133 return filtered.get(intent.hashCode() % filtered.size());
134 }
135
Sho SHIMIZU9909d172014-11-11 18:33:11 -0800136 return filtered.iterator().next();
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800137 }
138
139 /**
helenyrwu2a674902016-07-20 09:48:04 -0700140 * Computes a disjoint path between two ConnectPoints.
141 *
142 * @param intent intent on which behalf path is being computed
143 * @param one start of the path
144 * @param two end of the path
145 * @return DisjointPath between the two
146 * @throws PathNotFoundException if two paths cannot be found
147 */
148 protected DisjointPath getDisjointPath(ConnectivityIntent intent,
149 ElementId one, ElementId two) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300150 Set<DisjointPath> paths = pathService.getDisjointPaths(one, two, weigher(intent.constraints()));
helenyrwu2a674902016-07-20 09:48:04 -0700151 final List<Constraint> constraints = intent.constraints();
152 ImmutableList<DisjointPath> filtered = FluentIterable.from(paths)
153 .filter(path -> checkPath(path, constraints))
154 .toList();
155 if (filtered.isEmpty()) {
156 throw new PathNotFoundException(one, two);
157 }
jaegonkim7e876632017-01-25 06:01:49 +0900158
159 if (constraints.stream().anyMatch(c -> c instanceof HashedPathSelectionConstraint)) {
160 return filtered.get(intent.hashCode() % filtered.size());
161 }
162
helenyrwu2a674902016-07-20 09:48:04 -0700163 return filtered.iterator().next();
164 }
165
166 /**
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800167 * Edge-weight capable of evaluating link cost using a set of constraints.
168 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300169 protected class ConstraintBasedLinkWeigher extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
170 implements LinkWeigher {
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800171
172 private final List<Constraint> constraints;
173
174 /**
175 * Creates a new edge-weight function capable of evaluating links
176 * on the basis of the specified constraints.
177 *
178 * @param constraints path constraints
179 */
Andrey Komarov2398d962016-09-26 15:11:23 +0300180 ConstraintBasedLinkWeigher(List<Constraint> constraints) {
Sho SHIMIZU56531512014-11-10 15:27:49 -0800181 if (constraints == null) {
182 this.constraints = Collections.emptyList();
183 } else {
184 this.constraints = ImmutableList.copyOf(constraints);
185 }
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800186 }
187
188 @Override
Andrey Komarov2398d962016-09-26 15:11:23 +0300189 public Weight weight(TopologyEdge edge) {
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800190
191 // iterate over all constraints in order and return the weight of
192 // the first one with fast fail over the first failure
193 Iterator<Constraint> it = constraints.iterator();
Ray Milkey460f4022014-11-05 15:41:43 -0800194
Yuta HIGUCHIa0b0a132016-09-16 15:47:49 -0700195 if (!it.hasNext()) {
Yuta HIGUCHIfa9ee8c2017-02-02 20:00:14 -0800196 return DEFAULT_HOP_WEIGHT;
Yuta HIGUCHIa0b0a132016-09-16 15:47:49 -0700197 }
198
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800199 double cost = it.next().cost(edge.link(), resourceService::isAvailable);
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800200 while (it.hasNext() && cost > 0) {
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800201 if (it.next().cost(edge.link(), resourceService::isAvailable) < 0) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300202 cost = -1;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800203 }
204 }
Andrey Komarov2398d962016-09-26 15:11:23 +0300205 return new ScalarWeight(cost);
Ray Milkey460f4022014-11-05 15:41:43 -0800206
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800207 }
208 }
209
210}