blob: 86be9a52f2ea58ca77b1e0d79a8b890cd0cd8a94 [file] [log] [blame]
tombe988312014-09-19 18:38:47 -07001package org.onlab.onos.net.topology.impl;
tom4774c8f2014-09-16 11:17:08 -07002
tomca90c462014-09-22 11:40:58 -07003import com.google.common.collect.ImmutableSet;
tom4774c8f2014-09-16 11:17:08 -07004import com.google.common.collect.Lists;
5import com.google.common.collect.Sets;
6import org.apache.felix.scr.annotations.Activate;
7import org.apache.felix.scr.annotations.Component;
8import org.apache.felix.scr.annotations.Deactivate;
9import org.apache.felix.scr.annotations.Reference;
10import org.apache.felix.scr.annotations.ReferenceCardinality;
11import org.apache.felix.scr.annotations.Service;
12import org.onlab.onos.net.ConnectPoint;
13import org.onlab.onos.net.DefaultEdgeLink;
14import org.onlab.onos.net.DefaultPath;
15import org.onlab.onos.net.DeviceId;
16import org.onlab.onos.net.EdgeLink;
tomcbefa232014-09-16 14:17:20 -070017import org.onlab.onos.net.ElementId;
tom4774c8f2014-09-16 11:17:08 -070018import org.onlab.onos.net.Host;
19import org.onlab.onos.net.HostId;
tomcbefa232014-09-16 14:17:20 -070020import org.onlab.onos.net.HostLocation;
tom4774c8f2014-09-16 11:17:08 -070021import org.onlab.onos.net.Link;
22import org.onlab.onos.net.Path;
23import org.onlab.onos.net.PortNumber;
24import org.onlab.onos.net.host.HostService;
tom210f3f32014-09-16 17:33:40 -070025import org.onlab.onos.net.topology.PathService;
tom4774c8f2014-09-16 11:17:08 -070026import org.onlab.onos.net.provider.ProviderId;
27import org.onlab.onos.net.topology.LinkWeight;
28import org.onlab.onos.net.topology.Topology;
29import org.onlab.onos.net.topology.TopologyService;
30import org.slf4j.Logger;
31
32import java.util.List;
33import java.util.Set;
34
35import static com.google.common.base.Preconditions.checkNotNull;
tomcbefa232014-09-16 14:17:20 -070036import static org.onlab.onos.net.DeviceId.deviceId;
tom4774c8f2014-09-16 11:17:08 -070037import static org.slf4j.LoggerFactory.getLogger;
38
39/**
40 * Provides implementation of a path selection service atop the current
41 * topology and host services.
42 */
43@Component(immediate = true)
44@Service
tom10262dd2014-09-19 10:51:19 -070045public class PathManager implements PathService {
tom4774c8f2014-09-16 11:17:08 -070046
tomcbefa232014-09-16 14:17:20 -070047 private static final String ELEMENT_ID_NULL = "Element ID cannot be null";
tom4774c8f2014-09-16 11:17:08 -070048
tom7e02cda2014-09-18 12:05:46 -070049 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core");
tom4774c8f2014-09-16 11:17:08 -070050 private static final PortNumber P0 = PortNumber.portNumber(0);
51
tomcbefa232014-09-16 14:17:20 -070052 private static final EdgeLink NOT_HOST = new NotHost();
53
tom4774c8f2014-09-16 11:17:08 -070054 private final Logger log = getLogger(getClass());
55
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 protected TopologyService topologyService;
58
59 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 protected HostService hostService;
61
62 @Activate
tomca90c462014-09-22 11:40:58 -070063 public void activate() {
tom4774c8f2014-09-16 11:17:08 -070064 log.info("Started");
65 }
66
67 @Deactivate
tomca90c462014-09-22 11:40:58 -070068 public void deactivate() {
tom4774c8f2014-09-16 11:17:08 -070069 log.info("Stopped");
70 }
71
72 @Override
tomcbefa232014-09-16 14:17:20 -070073 public Set<Path> getPaths(ElementId src, ElementId dst) {
tom4774c8f2014-09-16 11:17:08 -070074 return getPaths(src, dst, null);
75 }
76
77 @Override
tomcbefa232014-09-16 14:17:20 -070078 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
79 checkNotNull(src, ELEMENT_ID_NULL);
80 checkNotNull(dst, ELEMENT_ID_NULL);
tom4774c8f2014-09-16 11:17:08 -070081
82 // Get the source and destination edge locations
tomcbefa232014-09-16 14:17:20 -070083 EdgeLink srcEdge = getEdgeLink(src, true);
84 EdgeLink dstEdge = getEdgeLink(dst, false);
85
tomca90c462014-09-22 11:40:58 -070086 // If either edge is null, bail with no paths.
87 if (srcEdge == null || dstEdge == null) {
88 return ImmutableSet.of();
89 }
90
tomcbefa232014-09-16 14:17:20 -070091 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
92 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
tom4774c8f2014-09-16 11:17:08 -070093
94 // If the source and destination are on the same edge device, there
95 // is just one path, so build it and return it.
tomcbefa232014-09-16 14:17:20 -070096 if (srcDevice.equals(dstDevice)) {
tom4774c8f2014-09-16 11:17:08 -070097 return edgeToEdgePaths(srcEdge, dstEdge);
98 }
99
100 // Otherwise get all paths between the source and destination edge
101 // devices.
102 Topology topology = topologyService.currentTopology();
103 Set<Path> paths = weight == null ?
tomcbefa232014-09-16 14:17:20 -0700104 topologyService.getPaths(topology, srcDevice, dstDevice) :
105 topologyService.getPaths(topology, srcDevice, dstDevice, weight);
tom4774c8f2014-09-16 11:17:08 -0700106
107 return edgeToEdgePaths(srcEdge, dstEdge, paths);
108 }
109
tomcbefa232014-09-16 14:17:20 -0700110 // Finds the host edge link if the element ID is a host id of an existing
111 // host. Otherwise, if the host does not exist, it returns null and if
112 // the element ID is not a host ID, returns NOT_HOST edge link.
113 private EdgeLink getEdgeLink(ElementId elementId, boolean isIngress) {
114 if (elementId instanceof HostId) {
115 // Resolve the host, return null.
116 Host host = hostService.getHost((HostId) elementId);
117 if (host == null) {
118 return null;
119 }
120 return new DefaultEdgeLink(PID, new ConnectPoint(elementId, P0),
121 host.location(), isIngress);
122 }
123 return NOT_HOST;
124 }
125
tomca90c462014-09-22 11:40:58 -0700126 // Produces a set of edge-to-edge paths using the set of infrastructure
127 // paths and the given edge links.
tom4774c8f2014-09-16 11:17:08 -0700128 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
129 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
tomca90c462014-09-22 11:40:58 -0700130 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null));
tom4774c8f2014-09-16 11:17:08 -0700131 return endToEndPaths;
132 }
133
tom4774c8f2014-09-16 11:17:08 -0700134 // Produces a set of edge-to-edge paths using the set of infrastructure
135 // paths and the given edge links.
136 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
137 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
138 for (Path path : paths) {
139 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
140 }
141 return endToEndPaths;
142 }
143
tomca90c462014-09-22 11:40:58 -0700144 // Produces a direct edge-to-edge path.
tom4774c8f2014-09-16 11:17:08 -0700145 private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
tomca90c462014-09-22 11:40:58 -0700146 List<Link> links = Lists.newArrayListWithCapacity(2);
147 // Add source and destination edge links only if they are real and
148 // add the infrastructure path only if it is not null.
149 if (srcLink != NOT_HOST) {
150 links.add(srcLink);
151 }
152 if (path != null) {
153 links.addAll(path.links());
154 }
155 if (dstLink != NOT_HOST) {
156 links.add(dstLink);
157 }
158 return new DefaultPath(PID, links, 2);
tom4774c8f2014-09-16 11:17:08 -0700159 }
160
tomcbefa232014-09-16 14:17:20 -0700161 // Special value for edge link to represent that this is really not an
162 // edge link since the src or dst are really an infrastructure device.
163 private static class NotHost extends DefaultEdgeLink implements EdgeLink {
164 NotHost() {
165 super(PID, new ConnectPoint(HostId.hostId("nic:none"), P0),
166 new HostLocation(deviceId("none:none"), P0, 0L), false);
167 }
168 }
tom4774c8f2014-09-16 11:17:08 -0700169}