Claudine Chiu
Committed by Gerrit Code Review

ONOS-2184 - initial impl. of virtual network path service; move path related me…

…thods from PathManager to AbstractPathService (since they are reused for VirtualNetworkPathService).

Change-Id: Ib4211d69a15c23a50de420b771877bb659539c22
1 +/*
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 +
19 +package org.onosproject.net.topology;
20 +
21 +import com.google.common.collect.ImmutableSet;
22 +import com.google.common.collect.Lists;
23 +import com.google.common.collect.Sets;
24 +import org.apache.felix.scr.annotations.Reference;
25 +import org.apache.felix.scr.annotations.ReferenceCardinality;
26 +import org.onosproject.net.ConnectPoint;
27 +import org.onosproject.net.DefaultDisjointPath;
28 +import org.onosproject.net.DefaultEdgeLink;
29 +import org.onosproject.net.DefaultPath;
30 +import org.onosproject.net.DeviceId;
31 +import org.onosproject.net.DisjointPath;
32 +import org.onosproject.net.EdgeLink;
33 +import org.onosproject.net.ElementId;
34 +import org.onosproject.net.Host;
35 +import org.onosproject.net.HostId;
36 +import org.onosproject.net.HostLocation;
37 +import org.onosproject.net.Link;
38 +import org.onosproject.net.Path;
39 +import org.onosproject.net.PortNumber;
40 +import org.onosproject.net.host.HostService;
41 +import org.onosproject.net.provider.ProviderId;
42 +
43 +import java.util.List;
44 +import java.util.Map;
45 +import java.util.Set;
46 +
47 +import static com.google.common.base.Preconditions.checkNotNull;
48 +
49 +/**
50 + * Helper class for path service.
51 + */
52 +public 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 +}
...@@ -15,43 +15,23 @@ ...@@ -15,43 +15,23 @@
15 */ 15 */
16 package org.onosproject.net.topology.impl; 16 package org.onosproject.net.topology.impl;
17 17
18 -import com.google.common.collect.ImmutableSet;
19 -import com.google.common.collect.Lists;
20 -import com.google.common.collect.Sets;
21 import org.apache.felix.scr.annotations.Activate; 18 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 19 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 20 import org.apache.felix.scr.annotations.Deactivate;
24 -import org.apache.felix.scr.annotations.Reference;
25 -import org.apache.felix.scr.annotations.ReferenceCardinality;
26 import org.apache.felix.scr.annotations.Service; 21 import org.apache.felix.scr.annotations.Service;
27 -import org.onosproject.net.ConnectPoint;
28 -import org.onosproject.net.DefaultEdgeLink;
29 -import org.onosproject.net.DefaultPath;
30 import org.onosproject.net.DisjointPath; 22 import org.onosproject.net.DisjointPath;
31 -import org.onosproject.net.DefaultDisjointPath;
32 -import org.onosproject.net.DeviceId;
33 -import org.onosproject.net.EdgeLink;
34 import org.onosproject.net.ElementId; 23 import org.onosproject.net.ElementId;
35 -import org.onosproject.net.Host;
36 -import org.onosproject.net.HostId;
37 -import org.onosproject.net.HostLocation;
38 import org.onosproject.net.Link; 24 import org.onosproject.net.Link;
39 import org.onosproject.net.Path; 25 import org.onosproject.net.Path;
40 -import org.onosproject.net.PortNumber;
41 -import org.onosproject.net.host.HostService;
42 -import org.onosproject.net.provider.ProviderId;
43 import org.onosproject.net.topology.LinkWeight; 26 import org.onosproject.net.topology.LinkWeight;
44 import org.onosproject.net.topology.PathService; 27 import org.onosproject.net.topology.PathService;
45 -import org.onosproject.net.topology.Topology; 28 +import org.onosproject.net.topology.AbstractPathService;
46 -import org.onosproject.net.topology.TopologyService;
47 import org.slf4j.Logger; 29 import org.slf4j.Logger;
48 30
49 -import java.util.List;
50 import java.util.Set; 31 import java.util.Set;
51 import java.util.Map; 32 import java.util.Map;
52 33
53 34
54 -import static com.google.common.base.Preconditions.checkNotNull;
55 import static org.slf4j.LoggerFactory.getLogger; 35 import static org.slf4j.LoggerFactory.getLogger;
56 import static org.onosproject.security.AppGuard.checkPermission; 36 import static org.onosproject.security.AppGuard.checkPermission;
57 import static org.onosproject.security.AppPermission.Type.*; 37 import static org.onosproject.security.AppPermission.Type.*;
...@@ -63,23 +43,11 @@ import static org.onosproject.security.AppPermission.Type.*; ...@@ -63,23 +43,11 @@ import static org.onosproject.security.AppPermission.Type.*;
63 */ 43 */
64 @Component(immediate = true) 44 @Component(immediate = true)
65 @Service 45 @Service
66 -public class PathManager implements PathService { 46 +public class PathManager extends AbstractPathService implements PathService {
67 47
68 - private static final String ELEMENT_ID_NULL = "Element ID cannot be null";
69 -
70 - private static final ProviderId PID = new ProviderId("core", "org.onosproject.core");
71 - private static final PortNumber P0 = PortNumber.portNumber(0);
72 -
73 - private static final EdgeLink NOT_HOST = new NotHost();
74 48
75 private final Logger log = getLogger(getClass()); 49 private final Logger log = getLogger(getClass());
76 50
77 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 - protected TopologyService topologyService;
79 -
80 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 - protected HostService hostService;
82 -
83 @Activate 51 @Activate
84 public void activate() { 52 public void activate() {
85 log.info("Started"); 53 log.info("Started");
...@@ -100,37 +68,9 @@ public class PathManager implements PathService { ...@@ -100,37 +68,9 @@ public class PathManager implements PathService {
100 @Override 68 @Override
101 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) { 69 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
102 checkPermission(TOPOLOGY_READ); 70 checkPermission(TOPOLOGY_READ);
103 - 71 + return super.getPaths(src, dst, weight);
104 - checkNotNull(src, ELEMENT_ID_NULL);
105 - checkNotNull(dst, ELEMENT_ID_NULL);
106 -
107 - // Get the source and destination edge locations
108 - EdgeLink srcEdge = getEdgeLink(src, true);
109 - EdgeLink dstEdge = getEdgeLink(dst, false);
110 -
111 - // If either edge is null, bail with no paths.
112 - if (srcEdge == null || dstEdge == null) {
113 - return ImmutableSet.of();
114 } 72 }
115 73
116 - DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
117 - DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
118 -
119 - // If the source and destination are on the same edge device, there
120 - // is just one path, so build it and return it.
121 - if (srcDevice.equals(dstDevice)) {
122 - return edgeToEdgePaths(srcEdge, dstEdge);
123 - }
124 -
125 - // Otherwise get all paths between the source and destination edge
126 - // devices.
127 - Topology topology = topologyService.currentTopology();
128 - Set<Path> paths = weight == null ?
129 - topologyService.getPaths(topology, srcDevice, dstDevice) :
130 - topologyService.getPaths(topology, srcDevice, dstDevice, weight);
131 -
132 - return edgeToEdgePaths(srcEdge, dstEdge, paths);
133 - }
134 74
135 @Override 75 @Override
136 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) { 76 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) {
...@@ -141,35 +81,7 @@ public class PathManager implements PathService { ...@@ -141,35 +81,7 @@ public class PathManager implements PathService {
141 @Override 81 @Override
142 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) { 82 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight) {
143 checkPermission(TOPOLOGY_READ); 83 checkPermission(TOPOLOGY_READ);
144 - checkNotNull(src, ELEMENT_ID_NULL); 84 + return super.getDisjointPaths(src, dst, weight);
145 - checkNotNull(dst, ELEMENT_ID_NULL);
146 -
147 - // Get the source and destination edge locations
148 - EdgeLink srcEdge = getEdgeLink(src, true);
149 - EdgeLink dstEdge = getEdgeLink(dst, false);
150 -
151 - // If either edge is null, bail with no paths.
152 - if (srcEdge == null || dstEdge == null) {
153 - return ImmutableSet.of();
154 - }
155 -
156 - DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
157 - DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
158 -
159 - // If the source and destination are on the same edge device, there
160 - // is just one path, so build it and return it.
161 - if (srcDevice.equals(dstDevice)) {
162 - return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
163 - }
164 -
165 - // Otherwise get all paths between the source and destination edge
166 - // devices.
167 - Topology topology = topologyService.currentTopology();
168 - Set<DisjointPath> paths = weight == null ?
169 - topologyService.getDisjointPaths(topology, srcDevice, dstDevice) :
170 - topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight);
171 -
172 - return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
173 } 85 }
174 86
175 @Override 87 @Override
...@@ -183,126 +95,7 @@ public class PathManager implements PathService { ...@@ -183,126 +95,7 @@ public class PathManager implements PathService {
183 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight, 95 public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, LinkWeight weight,
184 Map<Link, Object> riskProfile) { 96 Map<Link, Object> riskProfile) {
185 checkPermission(TOPOLOGY_READ); 97 checkPermission(TOPOLOGY_READ);
186 - checkNotNull(src, ELEMENT_ID_NULL); 98 + return super.getDisjointPaths(src, dst, weight, riskProfile);
187 - checkNotNull(dst, ELEMENT_ID_NULL);
188 -
189 - // Get the source and destination edge locations
190 - EdgeLink srcEdge = getEdgeLink(src, true);
191 - EdgeLink dstEdge = getEdgeLink(dst, false);
192 -
193 - // If either edge is null, bail with no paths.
194 - if (srcEdge == null || dstEdge == null) {
195 - return ImmutableSet.of();
196 - }
197 -
198 - DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
199 - DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
200 -
201 - // If the source and destination are on the same edge device, there
202 - // is just one path, so build it and return it.
203 - if (srcDevice.equals(dstDevice)) {
204 - return edgeToEdgePathsDisjoint(srcEdge, dstEdge);
205 - }
206 -
207 - // Otherwise get all paths between the source and destination edge
208 - // devices.
209 - Topology topology = topologyService.currentTopology();
210 - Set<DisjointPath> paths = weight == null ?
211 - topologyService.getDisjointPaths(topology, srcDevice, dstDevice, riskProfile) :
212 - topologyService.getDisjointPaths(topology, srcDevice, dstDevice, weight, riskProfile);
213 -
214 - return edgeToEdgePathsDisjoint(srcEdge, dstEdge, paths);
215 - }
216 -
217 - // Finds the host edge link if the element ID is a host id of an existing
218 - // host. Otherwise, if the host does not exist, it returns null and if
219 - // the element ID is not a host ID, returns NOT_HOST edge link.
220 - private EdgeLink getEdgeLink(ElementId elementId, boolean isIngress) {
221 - if (elementId instanceof HostId) {
222 - // Resolve the host, return null.
223 - Host host = hostService.getHost((HostId) elementId);
224 - if (host == null) {
225 - return null;
226 - }
227 - return new DefaultEdgeLink(PID, new ConnectPoint(elementId, P0),
228 - host.location(), isIngress);
229 - }
230 - return NOT_HOST;
231 - }
232 -
233 - // Produces a set of edge-to-edge paths using the set of infrastructure
234 - // paths and the given edge links.
235 - private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
236 - Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
237 - endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null));
238 - return endToEndPaths;
239 } 99 }
240 100
241 - // Produces a set of edge-to-edge paths using the set of infrastructure
242 - // paths and the given edge links.
243 - private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
244 - Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
245 - for (Path path : paths) {
246 - endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
247 - }
248 - return endToEndPaths;
249 - }
250 -
251 - private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink) {
252 - Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
253 - endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, null));
254 - return endToEndPaths;
255 - }
256 -
257 - private Set<DisjointPath> edgeToEdgePathsDisjoint(EdgeLink srcLink, EdgeLink dstLink, Set<DisjointPath> paths) {
258 - Set<DisjointPath> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
259 - for (DisjointPath path : paths) {
260 - endToEndPaths.add(edgeToEdgePathD(srcLink, dstLink, path));
261 - }
262 - return endToEndPaths;
263 - }
264 -
265 - // Produces a direct edge-to-edge path.
266 - private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
267 - List<Link> links = Lists.newArrayListWithCapacity(2);
268 - double cost = 0;
269 -
270 - // Add source and destination edge links only if they are real and
271 - // add the infrastructure path only if it is not null.
272 - if (srcLink != NOT_HOST) {
273 - links.add(srcLink);
274 - cost++;
275 - }
276 - if (path != null) {
277 - links.addAll(path.links());
278 - cost += path.cost();
279 - }
280 - if (dstLink != NOT_HOST) {
281 - links.add(dstLink);
282 - cost++;
283 - }
284 - return new DefaultPath(PID, links, cost);
285 - }
286 -
287 - // Produces a direct edge-to-edge path.
288 - private DisjointPath edgeToEdgePathD(EdgeLink srcLink, EdgeLink dstLink, DisjointPath path) {
289 - Path primary = null;
290 - Path backup = null;
291 - if (path != null) {
292 - primary = path.primary();
293 - backup = path.backup();
294 - }
295 - return new DefaultDisjointPath(PID, (DefaultPath) edgeToEdgePath(srcLink, dstLink, primary),
296 - (DefaultPath) edgeToEdgePath(srcLink, dstLink, backup));
297 - }
298 -
299 -
300 - // Special value for edge link to represent that this is really not an
301 - // edge link since the src or dst are really an infrastructure device.
302 - private static class NotHost extends DefaultEdgeLink implements EdgeLink {
303 - NotHost() {
304 - super(PID, new ConnectPoint(HostId.NONE, P0),
305 - new HostLocation(DeviceId.NONE, P0, 0L), false);
306 - }
307 - }
308 } 101 }
......
...@@ -18,6 +18,7 @@ package org.onosproject.net.topology.impl; ...@@ -18,6 +18,7 @@ package org.onosproject.net.topology.impl;
18 import org.junit.After; 18 import org.junit.After;
19 import org.junit.Before; 19 import org.junit.Before;
20 import org.junit.Test; 20 import org.junit.Test;
21 +import org.onlab.junit.TestUtils;
21 import org.onosproject.net.DeviceId; 22 import org.onosproject.net.DeviceId;
22 import org.onosproject.net.ElementId; 23 import org.onosproject.net.ElementId;
23 import org.onosproject.net.Host; 24 import org.onosproject.net.Host;
...@@ -53,11 +54,11 @@ public class PathManagerTest { ...@@ -53,11 +54,11 @@ public class PathManagerTest {
53 private FakeHostMgr fakeHostMgr = new FakeHostMgr(); 54 private FakeHostMgr fakeHostMgr = new FakeHostMgr();
54 55
55 @Before 56 @Before
56 - public void setUp() { 57 + public void setUp() throws Exception {
57 mgr = new PathManager(); 58 mgr = new PathManager();
58 service = mgr; 59 service = mgr;
59 - mgr.topologyService = fakeTopoMgr; 60 + TestUtils.setField(mgr, "topologyService", fakeTopoMgr);
60 - mgr.hostService = fakeHostMgr; 61 + TestUtils.setField(mgr, "hostService", fakeHostMgr);
61 mgr.activate(); 62 mgr.activate();
62 } 63 }
63 64
......
...@@ -61,6 +61,7 @@ import org.onosproject.net.intent.IntentState; ...@@ -61,6 +61,7 @@ import org.onosproject.net.intent.IntentState;
61 import org.onosproject.net.link.LinkService; 61 import org.onosproject.net.link.LinkService;
62 import org.onosproject.net.provider.AbstractListenerProviderRegistry; 62 import org.onosproject.net.provider.AbstractListenerProviderRegistry;
63 import org.onosproject.net.provider.AbstractProviderService; 63 import org.onosproject.net.provider.AbstractProviderService;
64 +import org.onosproject.net.topology.PathService;
64 import org.onosproject.net.topology.TopologyService; 65 import org.onosproject.net.topology.TopologyService;
65 import org.slf4j.Logger; 66 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory; 67 import org.slf4j.LoggerFactory;
...@@ -371,6 +372,8 @@ public class VirtualNetworkManager ...@@ -371,6 +372,8 @@ public class VirtualNetworkManager
371 service = new VirtualNetworkIntentService(this, network, new DefaultServiceDirectory()); 372 service = new VirtualNetworkIntentService(this, network, new DefaultServiceDirectory());
372 } else if (serviceKey.serviceClass.equals(HostService.class)) { 373 } else if (serviceKey.serviceClass.equals(HostService.class)) {
373 service = new VirtualNetworkHostService(this, network); 374 service = new VirtualNetworkHostService(this, network);
375 + } else if (serviceKey.serviceClass.equals(PathService.class)) {
376 + service = new VirtualNetworkPathService(this, network);
374 } else { 377 } else {
375 return null; 378 return null;
376 } 379 }
......
1 +/*
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 +
19 +package org.onosproject.incubator.net.virtual.impl;
20 +
21 +import org.onosproject.incubator.net.virtual.VirtualNetwork;
22 +import org.onosproject.incubator.net.virtual.VirtualNetworkService;
23 +import org.onosproject.net.DisjointPath;
24 +import org.onosproject.net.ElementId;
25 +import org.onosproject.net.Link;
26 +import org.onosproject.net.Path;
27 +import org.onosproject.net.host.HostService;
28 +import org.onosproject.net.topology.LinkWeight;
29 +import org.onosproject.net.topology.PathService;
30 +import org.onosproject.net.topology.AbstractPathService;
31 +import org.onosproject.net.topology.TopologyService;
32 +
33 +import java.util.Map;
34 +import java.util.Set;
35 +
36 +import static com.google.common.base.Preconditions.checkNotNull;
37 +
38 +/**
39 + * Path service implementation built on the virtual network service.
40 + */
41 +public class VirtualNetworkPathService extends AbstractPathService
42 + implements PathService, VnetService {
43 +
44 + private static final String NETWORK_NULL = "Network ID cannot be null";
45 +
46 + private final VirtualNetwork network;
47 +
48 + /**
49 + * Creates a new virtual network path service object.
50 + *
51 + * @param virtualNetworkManager virtual network manager service
52 + * @param network virtual network
53 + */
54 +
55 + public VirtualNetworkPathService(VirtualNetworkService virtualNetworkManager, VirtualNetwork network) {
56 + checkNotNull(network, NETWORK_NULL);
57 + this.network = network;
58 + topologyService = virtualNetworkManager.get(network.id(), TopologyService.class);
59 + hostService = virtualNetworkManager.get(network.id(), HostService.class);
60 + }
61 +
62 + @Override
63 + public Set<Path> getPaths(ElementId src, ElementId dst) {
64 + return getPaths(src, dst, null);
65 + }
66 +
67 + @Override
68 + public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) {
69 + return getDisjointPaths(src, dst, (LinkWeight) null);
70 + }
71 +
72 + @Override
73 + public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, Map<Link, Object> riskProfile) {
74 + return getDisjointPaths(src, dst, null, riskProfile);
75 + }
76 +
77 + @Override
78 + public VirtualNetwork network() {
79 + return network;
80 + }
81 +}
1 +/*
2 + * Copyright 2016-present 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.incubator.net.virtual.impl;
18 +
19 +import org.junit.After;
20 +import org.junit.Before;
21 +import org.junit.Test;
22 +import org.onlab.junit.TestUtils;
23 +import org.onosproject.common.event.impl.TestEventDispatcher;
24 +import org.onosproject.core.CoreService;
25 +import org.onosproject.incubator.net.virtual.TenantId;
26 +import org.onosproject.incubator.net.virtual.VirtualDevice;
27 +import org.onosproject.incubator.net.virtual.VirtualLink;
28 +import org.onosproject.incubator.net.virtual.VirtualNetwork;
29 +import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
30 +import org.onosproject.net.ConnectPoint;
31 +import org.onosproject.net.DefaultPort;
32 +import org.onosproject.net.DeviceId;
33 +import org.onosproject.net.DisjointPath;
34 +import org.onosproject.net.ElementId;
35 +import org.onosproject.net.Link;
36 +import org.onosproject.net.NetTestTools;
37 +import org.onosproject.net.Path;
38 +import org.onosproject.net.PortNumber;
39 +import org.onosproject.net.TestDeviceParams;
40 +import org.onosproject.net.intent.FakeIntentManager;
41 +import org.onosproject.net.intent.TestableIntentService;
42 +import org.onosproject.net.topology.LinkWeight;
43 +import org.onosproject.net.topology.PathService;
44 +import org.onosproject.store.service.TestStorageService;
45 +
46 +import java.util.Set;
47 +
48 +import static org.junit.Assert.assertEquals;
49 +
50 +/**
51 + * Junit tests for VirtualNetworkPathService.
52 + */
53 +public class VirtualNetworkPathServiceTest extends TestDeviceParams {
54 + private final String tenantIdValue1 = "TENANT_ID1";
55 +
56 + private VirtualNetworkManager manager;
57 + private DistributedVirtualNetworkStore virtualNetworkManagerStore;
58 + private final TestableIntentService intentService = new FakeIntentManager();
59 +
60 + @Before
61 + public void setUp() throws Exception {
62 + virtualNetworkManagerStore = new DistributedVirtualNetworkStore();
63 +
64 + CoreService coreService = new TestCoreService();
65 + virtualNetworkManagerStore.setCoreService(coreService);
66 + TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService());
67 + virtualNetworkManagerStore.activate();
68 +
69 + manager = new VirtualNetworkManager();
70 + manager.store = virtualNetworkManagerStore;
71 + manager.intentService = intentService;
72 + NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());
73 + manager.activate();
74 + }
75 +
76 + @After
77 + public void tearDown() {
78 + virtualNetworkManagerStore.deactivate();
79 + manager.deactivate();
80 + NetTestTools.injectEventDispatcher(manager, null);
81 + }
82 +
83 + /**
84 + * Sets up an empty virtual network (no devices, links).
85 + *
86 + * @return virtual network
87 + */
88 + private VirtualNetwork setupEmptyVnet() {
89 + manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
90 + return manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
91 + }
92 +
93 + /**
94 + * Creates a virtual network for further testing.
95 + *
96 + * @return virtual network
97 + */
98 + private VirtualNetwork setupVnet() {
99 + manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
100 + VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
101 + VirtualDevice virtualDevice1 =
102 + manager.createVirtualDevice(virtualNetwork.id(), DID1);
103 + VirtualDevice virtualDevice2 =
104 + manager.createVirtualDevice(virtualNetwork.id(), DID2);
105 + VirtualDevice virtualDevice3 =
106 + manager.createVirtualDevice(virtualNetwork.id(), DID3);
107 + VirtualDevice virtualDevice4 =
108 + manager.createVirtualDevice(virtualNetwork.id(), DID4);
109 +
110 + ConnectPoint cp11 = createConnectPointAndVirtualPort(virtualNetwork, virtualDevice1, 1);
111 + ConnectPoint cp12 = createConnectPointAndVirtualPort(virtualNetwork, virtualDevice1, 2);
112 + ConnectPoint cp23 = createConnectPointAndVirtualPort(virtualNetwork, virtualDevice2, 3);
113 + ConnectPoint cp24 = createConnectPointAndVirtualPort(virtualNetwork, virtualDevice2, 4);
114 + ConnectPoint cp35 = createConnectPointAndVirtualPort(virtualNetwork, virtualDevice3, 5);
115 + ConnectPoint cp36 = createConnectPointAndVirtualPort(virtualNetwork, virtualDevice3, 6);
116 + VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), cp11, cp23);
117 + virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE);
118 + VirtualLink link2 = manager.createVirtualLink(virtualNetwork.id(), cp23, cp11);
119 + virtualNetworkManagerStore.updateLink(link2, link2.tunnelId(), Link.State.ACTIVE);
120 + VirtualLink link3 = manager.createVirtualLink(virtualNetwork.id(), cp24, cp35);
121 + virtualNetworkManagerStore.updateLink(link3, link3.tunnelId(), Link.State.ACTIVE);
122 + VirtualLink link4 = manager.createVirtualLink(virtualNetwork.id(), cp35, cp24);
123 + virtualNetworkManagerStore.updateLink(link4, link4.tunnelId(), Link.State.ACTIVE);
124 + VirtualLink link5 = manager.createVirtualLink(virtualNetwork.id(), cp12, cp36);
125 + virtualNetworkManagerStore.updateLink(link5, link5.tunnelId(), Link.State.ACTIVE);
126 + VirtualLink link6 = manager.createVirtualLink(virtualNetwork.id(), cp36, cp12);
127 + virtualNetworkManagerStore.updateLink(link6, link6.tunnelId(), Link.State.ACTIVE);
128 +
129 + return virtualNetwork;
130 + }
131 +
132 + /**
133 + * Creates a connect point and related virtual port.
134 + *
135 + * @param vnet virtual network
136 + * @param vDev virtual device
137 + * @param portNumber port number
138 + * @return connect point
139 + */
140 + private ConnectPoint createConnectPointAndVirtualPort(
141 + VirtualNetwork vnet, VirtualDevice vDev, long portNumber) {
142 + ConnectPoint cp = new ConnectPoint(vDev.id(), PortNumber.portNumber(portNumber));
143 + manager.createVirtualPort(vnet.id(), cp.deviceId(), cp.port(),
144 + new DefaultPort(vDev, cp.port(), true));
145 + return cp;
146 + }
147 +
148 + /**
149 + * Tests getPaths(), getDisjointPaths()
150 + * on a non-empty virtual network.
151 + */
152 + @Test
153 + public void testGetPathsOnNonEmptyVnet() {
154 + VirtualNetwork vnet = setupVnet();
155 + PathService pathService = manager.get(vnet.id(), PathService.class);
156 +
157 + // src and dest are in vnet and are connected by a virtual link
158 + Set<Path> paths = pathService.getPaths(DID1, DID3);
159 + validatePaths(paths, 1, 1, DID1, DID3, 1.0);
160 +
161 + LinkWeight linkWeight = edge -> 2.0;
162 + paths = pathService.getPaths(DID1, DID3, linkWeight);
163 + validatePaths(paths, 1, 1, DID1, DID3, 2.0);
164 +
165 + Set<DisjointPath> disjointPaths = pathService.getDisjointPaths(DID1, DID3);
166 + validatePaths(disjointPaths, 1, 1, DID1, DID3, 1.0);
167 +
168 + disjointPaths = pathService.getDisjointPaths(DID1, DID3, linkWeight);
169 + validatePaths(disjointPaths, 1, 1, DID1, DID3, 2.0);
170 +
171 + // src and dest are in vnet but are not connected
172 + paths = pathService.getPaths(DID4, DID3);
173 + assertEquals("incorrect path count", 0, paths.size());
174 +
175 + disjointPaths = pathService.getDisjointPaths(DID4, DID3);
176 + assertEquals("incorrect path count", 0, disjointPaths.size());
177 +
178 + // src is in vnet, but dest is not in vnet.
179 + DeviceId nonExistentDeviceId = DeviceId.deviceId("nonExistentDevice");
180 + paths = pathService.getPaths(DID2, nonExistentDeviceId);
181 + assertEquals("incorrect path count", 0, paths.size());
182 +
183 + disjointPaths = pathService.getDisjointPaths(DID2, nonExistentDeviceId);
184 + assertEquals("incorrect path count", 0, disjointPaths.size());
185 + }
186 +
187 + /**
188 + * Tests getPaths(), getDisjointPaths()
189 + * on an empty virtual network.
190 + */
191 + @Test
192 + public void testGetPathsOnEmptyVnet() {
193 + VirtualNetwork vnet = setupEmptyVnet();
194 + PathService pathService = manager.get(vnet.id(), PathService.class);
195 +
196 + Set<Path> paths = pathService.getPaths(DID1, DID3);
197 + assertEquals("incorrect path count", 0, paths.size());
198 +
199 + Set<DisjointPath> disjointPaths = pathService.getDisjointPaths(DID1, DID3);
200 + assertEquals("incorrect path count", 0, disjointPaths.size());
201 + }
202 +
203 + /**
204 + * Tests getPaths() using a null source device on an empty virtual network.
205 + */
206 + @Test(expected = NullPointerException.class)
207 + public void testGetPathsWithNullSrc() {
208 + VirtualNetwork vnet = setupEmptyVnet();
209 + PathService pathService = manager.get(vnet.id(), PathService.class);
210 + pathService.getPaths(null, DID3);
211 + }
212 +
213 + /**
214 + * Tests getPaths() using a null destination device on a non-empty virtual network.
215 + */
216 + @Test(expected = NullPointerException.class)
217 + public void testGetPathsWithNullDest() {
218 + VirtualNetwork vnet = setupVnet();
219 + PathService pathService = manager.get(vnet.id(), PathService.class);
220 + pathService.getPaths(DID1, null);
221 + }
222 +
223 +
224 + // Makes sure the set of paths meets basic expectations.
225 + private void validatePaths(Set<? extends Path> paths, int count, int length,
226 + ElementId src, ElementId dst, double cost) {
227 + assertEquals("incorrect path count", count, paths.size());
228 + for (Path path : paths) {
229 + assertEquals("incorrect length", length, path.links().size());
230 + assertEquals("incorrect source", src, path.src().elementId());
231 + assertEquals("incorrect destination", dst, path.dst().elementId());
232 + assertEquals("incorrect cost", cost, path.cost(), 0);
233 + }
234 + }
235 +}