blob: 085244766db6f3f8a332cfaf52b9301d4f8d2146 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.topology.impl;
tom4774c8f2014-09-16 11:17:08 -070017
tomca90c462014-09-22 11:40:58 -070018import com.google.common.collect.ImmutableSet;
tom4774c8f2014-09-16 11:17:08 -070019import com.google.common.collect.Lists;
20import com.google.common.collect.Sets;
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.apache.felix.scr.annotations.Service;
Changhoon Yoon541ef712015-05-23 17:18:34 +090027import org.onosproject.core.Permission;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.ConnectPoint;
29import org.onosproject.net.DefaultEdgeLink;
30import org.onosproject.net.DefaultPath;
31import org.onosproject.net.DeviceId;
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;
42import org.onosproject.net.topology.LinkWeight;
43import org.onosproject.net.topology.PathService;
44import org.onosproject.net.topology.Topology;
45import org.onosproject.net.topology.TopologyService;
tom4774c8f2014-09-16 11:17:08 -070046import org.slf4j.Logger;
47
48import java.util.List;
49import java.util.Set;
50
51import static com.google.common.base.Preconditions.checkNotNull;
52import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoon541ef712015-05-23 17:18:34 +090053import static org.onosproject.security.AppGuard.checkPermission;
54
tom4774c8f2014-09-16 11:17:08 -070055
56/**
57 * Provides implementation of a path selection service atop the current
58 * topology and host services.
59 */
60@Component(immediate = true)
61@Service
tom10262dd2014-09-19 10:51:19 -070062public class PathManager implements PathService {
tom4774c8f2014-09-16 11:17:08 -070063
tomcbefa232014-09-16 14:17:20 -070064 private static final String ELEMENT_ID_NULL = "Element ID cannot be null";
tom4774c8f2014-09-16 11:17:08 -070065
Brian O'Connorabafb502014-12-02 22:26:20 -080066 private static final ProviderId PID = new ProviderId("core", "org.onosproject.core");
tom4774c8f2014-09-16 11:17:08 -070067 private static final PortNumber P0 = PortNumber.portNumber(0);
68
tomcbefa232014-09-16 14:17:20 -070069 private static final EdgeLink NOT_HOST = new NotHost();
70
tom4774c8f2014-09-16 11:17:08 -070071 private final Logger log = getLogger(getClass());
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected TopologyService topologyService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected HostService hostService;
78
79 @Activate
tomca90c462014-09-22 11:40:58 -070080 public void activate() {
tom4774c8f2014-09-16 11:17:08 -070081 log.info("Started");
82 }
83
84 @Deactivate
tomca90c462014-09-22 11:40:58 -070085 public void deactivate() {
tom4774c8f2014-09-16 11:17:08 -070086 log.info("Stopped");
87 }
88
89 @Override
tomcbefa232014-09-16 14:17:20 -070090 public Set<Path> getPaths(ElementId src, ElementId dst) {
Changhoon Yoon541ef712015-05-23 17:18:34 +090091 checkPermission(Permission.TOPOLOGY_READ);
92
tom4774c8f2014-09-16 11:17:08 -070093 return getPaths(src, dst, null);
94 }
95
96 @Override
tomcbefa232014-09-16 14:17:20 -070097 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
Changhoon Yoon541ef712015-05-23 17:18:34 +090098 checkPermission(Permission.TOPOLOGY_READ);
99
tomcbefa232014-09-16 14:17:20 -0700100 checkNotNull(src, ELEMENT_ID_NULL);
101 checkNotNull(dst, ELEMENT_ID_NULL);
tom4774c8f2014-09-16 11:17:08 -0700102
103 // Get the source and destination edge locations
tomcbefa232014-09-16 14:17:20 -0700104 EdgeLink srcEdge = getEdgeLink(src, true);
105 EdgeLink dstEdge = getEdgeLink(dst, false);
106
tomca90c462014-09-22 11:40:58 -0700107 // If either edge is null, bail with no paths.
108 if (srcEdge == null || dstEdge == null) {
109 return ImmutableSet.of();
110 }
111
tomcbefa232014-09-16 14:17:20 -0700112 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
113 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
tom4774c8f2014-09-16 11:17:08 -0700114
115 // If the source and destination are on the same edge device, there
116 // is just one path, so build it and return it.
tomcbefa232014-09-16 14:17:20 -0700117 if (srcDevice.equals(dstDevice)) {
tom4774c8f2014-09-16 11:17:08 -0700118 return edgeToEdgePaths(srcEdge, dstEdge);
119 }
120
121 // Otherwise get all paths between the source and destination edge
122 // devices.
123 Topology topology = topologyService.currentTopology();
124 Set<Path> paths = weight == null ?
tomcbefa232014-09-16 14:17:20 -0700125 topologyService.getPaths(topology, srcDevice, dstDevice) :
126 topologyService.getPaths(topology, srcDevice, dstDevice, weight);
tom4774c8f2014-09-16 11:17:08 -0700127
128 return edgeToEdgePaths(srcEdge, dstEdge, paths);
129 }
130
tomcbefa232014-09-16 14:17:20 -0700131 // Finds the host edge link if the element ID is a host id of an existing
132 // host. Otherwise, if the host does not exist, it returns null and if
133 // the element ID is not a host ID, returns NOT_HOST edge link.
134 private EdgeLink getEdgeLink(ElementId elementId, boolean isIngress) {
135 if (elementId instanceof HostId) {
136 // Resolve the host, return null.
137 Host host = hostService.getHost((HostId) elementId);
138 if (host == null) {
139 return null;
140 }
141 return new DefaultEdgeLink(PID, new ConnectPoint(elementId, P0),
142 host.location(), isIngress);
143 }
144 return NOT_HOST;
145 }
146
tomca90c462014-09-22 11:40:58 -0700147 // Produces a set of edge-to-edge paths using the set of infrastructure
148 // paths and the given edge links.
tom4774c8f2014-09-16 11:17:08 -0700149 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
150 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
tomca90c462014-09-22 11:40:58 -0700151 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null));
tom4774c8f2014-09-16 11:17:08 -0700152 return endToEndPaths;
153 }
154
tom4774c8f2014-09-16 11:17:08 -0700155 // Produces a set of edge-to-edge paths using the set of infrastructure
156 // paths and the given edge links.
157 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
158 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
159 for (Path path : paths) {
160 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
161 }
162 return endToEndPaths;
163 }
164
tomca90c462014-09-22 11:40:58 -0700165 // Produces a direct edge-to-edge path.
tom4774c8f2014-09-16 11:17:08 -0700166 private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
tomca90c462014-09-22 11:40:58 -0700167 List<Link> links = Lists.newArrayListWithCapacity(2);
168 // Add source and destination edge links only if they are real and
169 // add the infrastructure path only if it is not null.
170 if (srcLink != NOT_HOST) {
171 links.add(srcLink);
172 }
173 if (path != null) {
174 links.addAll(path.links());
175 }
176 if (dstLink != NOT_HOST) {
177 links.add(dstLink);
178 }
179 return new DefaultPath(PID, links, 2);
tom4774c8f2014-09-16 11:17:08 -0700180 }
181
tomcbefa232014-09-16 14:17:20 -0700182 // Special value for edge link to represent that this is really not an
183 // edge link since the src or dst are really an infrastructure device.
184 private static class NotHost extends DefaultEdgeLink implements EdgeLink {
185 NotHost() {
tom545708e2014-10-09 17:10:02 -0700186 super(PID, new ConnectPoint(HostId.NONE, P0),
187 new HostLocation(DeviceId.NONE, P0, 0L), false);
tomcbefa232014-09-16 14:17:20 -0700188 }
189 }
tom4774c8f2014-09-16 11:17:08 -0700190}