blob: d718d15b156a1a8cf1fb4e508994e1ce314d297f [file] [log] [blame]
Claudine Chiu45920dd2016-07-28 19:19:46 +00001/*
Brian O'Connord03d7dd2016-08-02 23:33:25 -07002 * Copyright 2016-present Open Networking Laboratory
Claudine Chiu45920dd2016-07-28 19:19:46 +00003 *
Brian O'Connord03d7dd2016-08-02 23:33:25 -07004 * 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
Claudine Chiu45920dd2016-07-28 19:19:46 +00007 *
Brian O'Connord03d7dd2016-08-02 23:33:25 -07008 * 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.
Claudine Chiu45920dd2016-07-28 19:19:46 +000015 */
Claudine Chiu45920dd2016-07-28 19:19:46 +000016package org.onosproject.net.topology;
17
18import com.google.common.collect.ImmutableSet;
19import com.google.common.collect.Lists;
20import com.google.common.collect.Sets;
Claudine Chiu45920dd2016-07-28 19:19:46 +000021import org.onosproject.net.ConnectPoint;
22import org.onosproject.net.DefaultDisjointPath;
23import org.onosproject.net.DefaultEdgeLink;
24import org.onosproject.net.DefaultPath;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.DisjointPath;
27import org.onosproject.net.EdgeLink;
28import org.onosproject.net.ElementId;
29import org.onosproject.net.Host;
30import org.onosproject.net.HostId;
31import org.onosproject.net.HostLocation;
32import org.onosproject.net.Link;
33import org.onosproject.net.Path;
34import org.onosproject.net.PortNumber;
35import org.onosproject.net.host.HostService;
36import org.onosproject.net.provider.ProviderId;
37
38import java.util.List;
39import java.util.Map;
40import java.util.Set;
41
42import static com.google.common.base.Preconditions.checkNotNull;
43
44/**
45 * Helper class for path service.
Yuta HIGUCHI90e12292016-08-02 18:02:53 -070046 * <p>
47 * Class inheriting this must manually initialize {@code topologyService}
48 * and {@code hostService} fields.
Claudine Chiu45920dd2016-07-28 19:19:46 +000049 */
Yuta HIGUCHI90e12292016-08-02 18:02:53 -070050public abstract class AbstractPathService
51 implements PathService {
Claudine Chiu45920dd2016-07-28 19:19:46 +000052
53 private static final String ELEMENT_ID_NULL = "Element ID cannot be null";
54 private static final EdgeLink NOT_HOST = new NotHost();
55
56 private static final ProviderId PID = new ProviderId("core", "org.onosproject.core");
57 private static final PortNumber P0 = PortNumber.portNumber(0);
58
Claudine Chiu45920dd2016-07-28 19:19:46 +000059 protected TopologyService topologyService;
60
Claudine Chiu45920dd2016-07-28 19:19:46 +000061 protected HostService hostService;
62
Yuta HIGUCHI90e12292016-08-02 18:02:53 -070063 @Override
Claudine Chiu45920dd2016-07-28 19:19:46 +000064 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
65 checkNotNull(src, ELEMENT_ID_NULL);
66 checkNotNull(dst, ELEMENT_ID_NULL);
67
68 // Get the source and destination edge locations
69 EdgeLink srcEdge = getEdgeLink(src, true);
70 EdgeLink dstEdge = getEdgeLink(dst, false);
71
72 // If either edge is null, bail with no paths.
73 if (srcEdge == null || dstEdge == null) {
74 return ImmutableSet.of();
75 }
76
77 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
78 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
79
80 // If the source and destination are on the same edge device, there
81 // is just one path, so build it and return it.
82 if (srcDevice.equals(dstDevice)) {
83 return edgeToEdgePaths(srcEdge, dstEdge);
84 }
85
86 // Otherwise get all paths between the source and destination edge
87 // devices.
88 Topology topology = topologyService.currentTopology();
89 Set<Path> paths = weight == null ?
90 topologyService.getPaths(topology, srcDevice, dstDevice) :
91 topologyService.getPaths(topology, srcDevice, dstDevice, weight);
92
93 return edgeToEdgePaths(srcEdge, dstEdge, paths);
94 }
95
Yuta HIGUCHI90e12292016-08-02 18:02:53 -070096 @Override
Claudine Chiu45920dd2016-07-28 19:19:46 +000097 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) {
98 checkNotNull(src, ELEMENT_ID_NULL);
99 checkNotNull(dst, ELEMENT_ID_NULL);
100
101 // Get the source and destination edge locations
102 EdgeLink srcEdge = getEdgeLink(src, true);
103 EdgeLink dstEdge = getEdgeLink(dst, false);
104
105 // If either edge is null, bail with no paths.
106 if (srcEdge == null || dstEdge == null) {
107 return ImmutableSet.of();
108 }
109
110 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
111 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
112
113 // If the source and destination are on the same edge device, there
114 // is just one path, so build it and return it.
115 if (srcDevice.equals(dstDevice)) {
116 return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
117 }
118
119 // Otherwise get all paths between the source and destination edge
120 // devices.
121 Topology topology = topologyService.currentTopology();
122 Set<DisjointPath> paths = weight == null ?
123 topologyService.getDisjointPaths(topology, srcDevice, dstDevice) :
124 topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight);
125
126 return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
127 }
128
Yuta HIGUCHI90e12292016-08-02 18:02:53 -0700129 @Override
Claudine Chiu45920dd2016-07-28 19:19:46 +0000130 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}