blob: a34f9204bcb65d1116d08def868601158e0512b5 [file] [log] [blame]
Thomas Vachuskaedc944c2014-11-04 15:42:25 -08001/*
2 * Copyright 2014 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 */
16package org.onlab.onos.net.intent.impl;
17
Sho SHIMIZU9909d172014-11-11 18:33:11 -080018import com.google.common.base.Predicate;
19import com.google.common.collect.FluentIterable;
Sho SHIMIZU56531512014-11-10 15:27:49 -080020import com.google.common.collect.ImmutableList;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080021import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.onlab.onos.net.ElementId;
25import org.onlab.onos.net.Path;
26import org.onlab.onos.net.intent.ConnectivityIntent;
27import org.onlab.onos.net.intent.Constraint;
28import org.onlab.onos.net.intent.IntentCompiler;
29import org.onlab.onos.net.intent.IntentExtensionService;
30import org.onlab.onos.net.provider.ProviderId;
31import org.onlab.onos.net.resource.LinkResourceService;
32import org.onlab.onos.net.topology.LinkWeight;
33import org.onlab.onos.net.topology.PathService;
34import org.onlab.onos.net.topology.TopologyEdge;
35
Sho SHIMIZU56531512014-11-10 15:27:49 -080036import java.util.Collections;
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080037import java.util.Iterator;
38import java.util.List;
39import java.util.Set;
40
41/**
42 * Base class for compilers of various
43 * {@link org.onlab.onos.net.intent.ConnectivityIntent connectivity intents}.
44 */
45@Component(immediate = true)
46public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent>
47 implements IntentCompiler<T> {
48
49 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true);
50
51 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
52 protected IntentExtensionService intentManager;
53
54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 protected PathService pathService;
56
57 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 protected LinkResourceService resourceService;
59
60 /**
61 * Returns an edge-weight capable of evaluating links on the basis of the
62 * specified constraints.
63 *
64 * @param constraints path constraints
65 * @return edge-weight function
66 */
67 protected LinkWeight weight(List<Constraint> constraints) {
68 return new ConstraintBasedLinkWeight(constraints);
69 }
70
71 /**
72 * Validates the specified path against the given constraints.
73 *
Thomas Vachuskab14c77a2014-11-04 18:08:01 -080074 * @param path path to be checked
75 * @param constraints path constraints
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080076 * @return true if the path passes all constraints
77 */
78 protected boolean checkPath(Path path, List<Constraint> constraints) {
79 for (Constraint constraint : constraints) {
80 if (!constraint.validate(path, resourceService)) {
81 return false;
82 }
83 }
84 return true;
85 }
86
87 /**
88 * Computes a path between two ConnectPoints.
89 *
Thomas Vachuskab14c77a2014-11-04 18:08:01 -080090 * @param intent intent on which behalf path is being computed
91 * @param one start of the path
92 * @param two end of the path
Thomas Vachuskaedc944c2014-11-04 15:42:25 -080093 * @return Path between the two
94 * @throws PathNotFoundException if a path cannot be found
95 */
96 protected Path getPath(ConnectivityIntent intent,
97 ElementId one, ElementId two) {
98 Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints()));
Sho SHIMIZU9909d172014-11-11 18:33:11 -080099 final List<Constraint> constraints = intent.constraints();
100 ImmutableList<Path> filtered = FluentIterable.from(paths)
101 .filter(new Predicate<Path>() {
102 @Override
103 public boolean apply(Path path) {
104 return checkPath(path, constraints);
105 }
106 }).toList();
107 if (filtered.isEmpty()) {
Ray Milkeya505e4f2014-11-24 11:44:08 -0800108 throw new PathNotFoundException("No packet path from " + one + " to " + two);
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800109 }
110 // TODO: let's be more intelligent about this eventually
Sho SHIMIZU9909d172014-11-11 18:33:11 -0800111 return filtered.iterator().next();
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800112 }
113
114 /**
115 * Edge-weight capable of evaluating link cost using a set of constraints.
116 */
117 protected class ConstraintBasedLinkWeight implements LinkWeight {
118
119 private final List<Constraint> constraints;
120
121 /**
122 * Creates a new edge-weight function capable of evaluating links
123 * on the basis of the specified constraints.
124 *
125 * @param constraints path constraints
126 */
127 ConstraintBasedLinkWeight(List<Constraint> constraints) {
Sho SHIMIZU56531512014-11-10 15:27:49 -0800128 if (constraints == null) {
129 this.constraints = Collections.emptyList();
130 } else {
131 this.constraints = ImmutableList.copyOf(constraints);
132 }
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800133 }
134
135 @Override
136 public double weight(TopologyEdge edge) {
Sho SHIMIZU56531512014-11-10 15:27:49 -0800137 if (!constraints.iterator().hasNext()) {
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800138 return 1.0;
139 }
140
141 // iterate over all constraints in order and return the weight of
142 // the first one with fast fail over the first failure
143 Iterator<Constraint> it = constraints.iterator();
Ray Milkey460f4022014-11-05 15:41:43 -0800144
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800145 double cost = it.next().cost(edge.link(), resourceService);
146 while (it.hasNext() && cost > 0) {
147 if (it.next().cost(edge.link(), resourceService) < 0) {
148 return -1;
149 }
150 }
151 return cost;
Ray Milkey460f4022014-11-05 15:41:43 -0800152
Thomas Vachuskaedc944c2014-11-04 15:42:25 -0800153 }
154 }
155
156}