blob: 433cdcd966ca6755762d051d002f615e46209ebc [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 */
tombe988312014-09-19 18:38:47 -070016package org.onlab.onos.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;
27import org.onlab.onos.net.ConnectPoint;
28import org.onlab.onos.net.DefaultEdgeLink;
29import org.onlab.onos.net.DefaultPath;
30import org.onlab.onos.net.DeviceId;
31import org.onlab.onos.net.EdgeLink;
tomcbefa232014-09-16 14:17:20 -070032import org.onlab.onos.net.ElementId;
tom4774c8f2014-09-16 11:17:08 -070033import org.onlab.onos.net.Host;
34import org.onlab.onos.net.HostId;
tomcbefa232014-09-16 14:17:20 -070035import org.onlab.onos.net.HostLocation;
tom4774c8f2014-09-16 11:17:08 -070036import org.onlab.onos.net.Link;
37import org.onlab.onos.net.Path;
38import org.onlab.onos.net.PortNumber;
39import org.onlab.onos.net.host.HostService;
tom4774c8f2014-09-16 11:17:08 -070040import org.onlab.onos.net.provider.ProviderId;
41import org.onlab.onos.net.topology.LinkWeight;
tom545708e2014-10-09 17:10:02 -070042import org.onlab.onos.net.topology.PathService;
tom4774c8f2014-09-16 11:17:08 -070043import org.onlab.onos.net.topology.Topology;
44import org.onlab.onos.net.topology.TopologyService;
45import org.slf4j.Logger;
46
47import java.util.List;
48import java.util.Set;
49
50import static com.google.common.base.Preconditions.checkNotNull;
51import static org.slf4j.LoggerFactory.getLogger;
52
53/**
54 * Provides implementation of a path selection service atop the current
55 * topology and host services.
56 */
57@Component(immediate = true)
58@Service
tom10262dd2014-09-19 10:51:19 -070059public class PathManager implements PathService {
tom4774c8f2014-09-16 11:17:08 -070060
tomcbefa232014-09-16 14:17:20 -070061 private static final String ELEMENT_ID_NULL = "Element ID cannot be null";
tom4774c8f2014-09-16 11:17:08 -070062
tom7e02cda2014-09-18 12:05:46 -070063 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core");
tom4774c8f2014-09-16 11:17:08 -070064 private static final PortNumber P0 = PortNumber.portNumber(0);
65
tomcbefa232014-09-16 14:17:20 -070066 private static final EdgeLink NOT_HOST = new NotHost();
67
tom4774c8f2014-09-16 11:17:08 -070068 private final Logger log = getLogger(getClass());
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected TopologyService topologyService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected HostService hostService;
75
76 @Activate
tomca90c462014-09-22 11:40:58 -070077 public void activate() {
tom4774c8f2014-09-16 11:17:08 -070078 log.info("Started");
79 }
80
81 @Deactivate
tomca90c462014-09-22 11:40:58 -070082 public void deactivate() {
tom4774c8f2014-09-16 11:17:08 -070083 log.info("Stopped");
84 }
85
86 @Override
tomcbefa232014-09-16 14:17:20 -070087 public Set<Path> getPaths(ElementId src, ElementId dst) {
tom4774c8f2014-09-16 11:17:08 -070088 return getPaths(src, dst, null);
89 }
90
91 @Override
tomcbefa232014-09-16 14:17:20 -070092 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
93 checkNotNull(src, ELEMENT_ID_NULL);
94 checkNotNull(dst, ELEMENT_ID_NULL);
tom4774c8f2014-09-16 11:17:08 -070095
96 // Get the source and destination edge locations
tomcbefa232014-09-16 14:17:20 -070097 EdgeLink srcEdge = getEdgeLink(src, true);
98 EdgeLink dstEdge = getEdgeLink(dst, false);
99
tomca90c462014-09-22 11:40:58 -0700100 // If either edge is null, bail with no paths.
101 if (srcEdge == null || dstEdge == null) {
102 return ImmutableSet.of();
103 }
104
tomcbefa232014-09-16 14:17:20 -0700105 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
106 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
tom4774c8f2014-09-16 11:17:08 -0700107
108 // If the source and destination are on the same edge device, there
109 // is just one path, so build it and return it.
tomcbefa232014-09-16 14:17:20 -0700110 if (srcDevice.equals(dstDevice)) {
tom4774c8f2014-09-16 11:17:08 -0700111 return edgeToEdgePaths(srcEdge, dstEdge);
112 }
113
114 // Otherwise get all paths between the source and destination edge
115 // devices.
116 Topology topology = topologyService.currentTopology();
117 Set<Path> paths = weight == null ?
tomcbefa232014-09-16 14:17:20 -0700118 topologyService.getPaths(topology, srcDevice, dstDevice) :
119 topologyService.getPaths(topology, srcDevice, dstDevice, weight);
tom4774c8f2014-09-16 11:17:08 -0700120
121 return edgeToEdgePaths(srcEdge, dstEdge, paths);
122 }
123
tomcbefa232014-09-16 14:17:20 -0700124 // Finds the host edge link if the element ID is a host id of an existing
125 // host. Otherwise, if the host does not exist, it returns null and if
126 // the element ID is not a host ID, returns NOT_HOST edge link.
127 private EdgeLink getEdgeLink(ElementId elementId, boolean isIngress) {
128 if (elementId instanceof HostId) {
129 // Resolve the host, return null.
130 Host host = hostService.getHost((HostId) elementId);
131 if (host == null) {
132 return null;
133 }
134 return new DefaultEdgeLink(PID, new ConnectPoint(elementId, P0),
135 host.location(), isIngress);
136 }
137 return NOT_HOST;
138 }
139
tomca90c462014-09-22 11:40:58 -0700140 // Produces a set of edge-to-edge paths using the set of infrastructure
141 // paths and the given edge links.
tom4774c8f2014-09-16 11:17:08 -0700142 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
143 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
tomca90c462014-09-22 11:40:58 -0700144 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null));
tom4774c8f2014-09-16 11:17:08 -0700145 return endToEndPaths;
146 }
147
tom4774c8f2014-09-16 11:17:08 -0700148 // Produces a set of edge-to-edge paths using the set of infrastructure
149 // paths and the given edge links.
150 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
151 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
152 for (Path path : paths) {
153 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
154 }
155 return endToEndPaths;
156 }
157
tomca90c462014-09-22 11:40:58 -0700158 // Produces a direct edge-to-edge path.
tom4774c8f2014-09-16 11:17:08 -0700159 private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
tomca90c462014-09-22 11:40:58 -0700160 List<Link> links = Lists.newArrayListWithCapacity(2);
161 // Add source and destination edge links only if they are real and
162 // add the infrastructure path only if it is not null.
163 if (srcLink != NOT_HOST) {
164 links.add(srcLink);
165 }
166 if (path != null) {
167 links.addAll(path.links());
168 }
169 if (dstLink != NOT_HOST) {
170 links.add(dstLink);
171 }
172 return new DefaultPath(PID, links, 2);
tom4774c8f2014-09-16 11:17:08 -0700173 }
174
tomcbefa232014-09-16 14:17:20 -0700175 // Special value for edge link to represent that this is really not an
176 // edge link since the src or dst are really an infrastructure device.
177 private static class NotHost extends DefaultEdgeLink implements EdgeLink {
178 NotHost() {
tom545708e2014-10-09 17:10:02 -0700179 super(PID, new ConnectPoint(HostId.NONE, P0),
180 new HostLocation(DeviceId.NONE, P0, 0L), false);
tomcbefa232014-09-16 14:17:20 -0700181 }
182 }
tom4774c8f2014-09-16 11:17:08 -0700183}