blob: 0292f70c6659d69a4ec343774770dc573b963e36 [file] [log] [blame]
Claudine Chiu45920dd2016-07-28 19:19:46 +00001/*
2 *
3 * * Copyright 2016-present Open Networking Laboratory
4 * *
5 * * Licensed under the Apache License, Version 2.0 (the "License");
6 * * you may not use this file except in compliance with the License.
7 * * You may obtain a copy of the License at
8 * *
9 * * http://www.apache.org/licenses/LICENSE-2.0
10 * *
11 * * Unless required by applicable law or agreed to in writing, software
12 * * distributed under the License is distributed on an "AS IS" BASIS,
13 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * * See the License for the specific language governing permissions and
15 * * limitations under the License.
16 *
17 */
18
19package org.onosproject.net.topology;
20
21import com.google.common.collect.ImmutableSet;
22import com.google.common.collect.Lists;
23import com.google.common.collect.Sets;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.onosproject.net.ConnectPoint;
27import org.onosproject.net.DefaultDisjointPath;
28import org.onosproject.net.DefaultEdgeLink;
29import org.onosproject.net.DefaultPath;
30import org.onosproject.net.DeviceId;
31import org.onosproject.net.DisjointPath;
32import org.onosproject.net.EdgeLink;
33import org.onosproject.net.ElementId;
34import org.onosproject.net.Host;
35import org.onosproject.net.HostId;
36import org.onosproject.net.HostLocation;
37import org.onosproject.net.Link;
38import org.onosproject.net.Path;
39import org.onosproject.net.PortNumber;
40import org.onosproject.net.host.HostService;
41import org.onosproject.net.provider.ProviderId;
42
43import java.util.List;
44import java.util.Map;
45import java.util.Set;
46
47import static com.google.common.base.Preconditions.checkNotNull;
48
49/**
50 * Helper class for path service.
51 */
52public abstract class AbstractPathService {
53
54 private static final String ELEMENT_ID_NULL = "Element ID cannot be null";
55 private static final EdgeLink NOT_HOST = new NotHost();
56
57 private static final ProviderId PID = new ProviderId("core", "org.onosproject.core");
58 private static final PortNumber P0 = PortNumber.portNumber(0);
59
60 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 protected TopologyService topologyService;
62
63 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
64 protected HostService hostService;
65
66 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
67 checkNotNull(src, ELEMENT_ID_NULL);
68 checkNotNull(dst, ELEMENT_ID_NULL);
69
70 // Get the source and destination edge locations
71 EdgeLink srcEdge = getEdgeLink(src, true);
72 EdgeLink dstEdge = getEdgeLink(dst, false);
73
74 // If either edge is null, bail with no paths.
75 if (srcEdge == null || dstEdge == null) {
76 return ImmutableSet.of();
77 }
78
79 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
80 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
81
82 // If the source and destination are on the same edge device, there
83 // is just one path, so build it and return it.
84 if (srcDevice.equals(dstDevice)) {
85 return edgeToEdgePaths(srcEdge, dstEdge);
86 }
87
88 // Otherwise get all paths between the source and destination edge
89 // devices.
90 Topology topology = topologyService.currentTopology();
91 Set<Path> paths = weight == null ?
92 topologyService.getPaths(topology, srcDevice, dstDevice) :
93 topologyService.getPaths(topology, srcDevice, dstDevice, weight);
94
95 return edgeToEdgePaths(srcEdge, dstEdge, paths);
96 }
97
98 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) {
99 checkNotNull(src, ELEMENT_ID_NULL);
100 checkNotNull(dst, ELEMENT_ID_NULL);
101
102 // Get the source and destination edge locations
103 EdgeLink srcEdge = getEdgeLink(src, true);
104 EdgeLink dstEdge = getEdgeLink(dst, false);
105
106 // If either edge is null, bail with no paths.
107 if (srcEdge == null || dstEdge == null) {
108 return ImmutableSet.of();
109 }
110
111 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
112 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
113
114 // If the source and destination are on the same edge device, there
115 // is just one path, so build it and return it.
116 if (srcDevice.equals(dstDevice)) {
117 return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
118 }
119
120 // Otherwise get all paths between the source and destination edge
121 // devices.
122 Topology topology = topologyService.currentTopology();
123 Set<DisjointPath> paths = weight == null ?
124 topologyService.getDisjointPaths(topology, srcDevice, dstDevice) :
125 topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight);
126
127 return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
128 }
129
130 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight,
131 Map<Link, Object> riskProfile) {
132 checkNotNull(src, ELEMENT_ID_NULL);
133 checkNotNull(dst, ELEMENT_ID_NULL);
134
135 // Get the source and destination edge locations
136 EdgeLink srcEdge = getEdgeLink(src, true);
137 EdgeLink dstEdge = getEdgeLink(dst, false);
138
139 // If either edge is null, bail with no paths.
140 if (srcEdge == null || dstEdge == null) {
141 return ImmutableSet.of();
142 }
143
144 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
145 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
146
147 // If the source and destination are on the same edge device, there
148 // is just one path, so build it and return it.
149 if (srcDevice.equals(dstDevice)) {
150 return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
151 }
152
153 // Otherwise get all paths between the source and destination edge
154 // devices.
155 Topology topology = topologyService.currentTopology();
156 Set<DisjointPath> paths = weight == null ?
157 topologyService.getDisjointPaths(topology, srcDevice, dstDevice, riskProfile) :
158 topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight, riskProfile);
159
160 return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
161 }
162
163 // Finds the host edge link if the element ID is a host id of an existing
164 // host. Otherwise, if the host does not exist, it returns null and if
165 // the element ID is not a host ID, returns NOT_HOST edge link.
166 private EdgeLink getEdgeLink(ElementId elementId, boolean isIngress) {
167 if (elementId instanceof HostId) {
168 // Resolve the host, return null.
169 Host host = hostService.getHost((HostId) elementId);
170 if (host == null) {
171 return null;
172 }
173 return new DefaultEdgeLink(PID, new ConnectPoint(elementId, P0),
174 host.location(), isIngress);
175 }
176 return NOT_HOST;
177 }
178
179 // Produces a set of edge-to-edge paths using the set of infrastructure
180 // paths and the given edge links.
181 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
182 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
183 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null));
184 return endToEndPaths;
185 }
186
187 // Produces a set of edge-to-edge paths using the set of infrastructure
188 // paths and the given edge links.
189 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
190 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
191 for (Path path : paths) {
192 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
193 }
194 return endToEndPaths;
195 }
196
197 private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink) {
198 Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
199 endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, null));
200 return endToEndPaths;
201 }
202
203 private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink,
204 Set<DisjointPath> paths) {
205 Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
206 for (DisjointPath path : paths) {
207 endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, path));
208 }
209 return endToEndPaths;
210 }
211
212 // Produces a direct edge-to-edge path.
213 private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
214 List<Link> links = Lists.newArrayListWithCapacity(2);
215 double cost = 0;
216
217 // Add source and destination edge links only if they are real and
218 // add the infrastructure path only if it is not null.
219 if (srcLink != NOT_HOST) {
220 links.add(srcLink);
221 cost++;
222 }
223 if (path != null) {
224 links.addAll(path.links());
225 cost += path.cost();
226 }
227 if (dstLink != NOT_HOST) {
228 links.add(dstLink);
229 cost++;
230 }
231 return new DefaultPath(PID, links, cost);
232 }
233
234 // Produces a direct edge-to-edge path.
235 private DisjointPath edgeToEdgePathD(EdgeLink srcLink, EdgeLink dstLink, DisjointPath path) {
236 Path primary = null;
237 Path backup = null;
238 if (path != null) {
239 primary = path.primary();
240 backup = path.backup();
241 }
242 return new DefaultDisjointPath(PID, (DefaultPath) edgeToEdgePath(srcLink, dstLink, primary),
243 (DefaultPath) edgeToEdgePath(srcLink, dstLink, backup));
244 }
245
246
247 // Special value for edge link to represent that this is really not an
248 // edge link since the src or dst are really an infrastructure device.
249 private static class NotHost extends DefaultEdgeLink implements EdgeLink {
250 NotHost() {
251 super(PID, new ConnectPoint(HostId.NONE, P0),
252 new HostLocation(DeviceId.NONE, P0, 0L), false);
253 }
254 }
255}