blob: 849ac6d2eb8f975a7f5fac1dd3708912b2335845 [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;
tom4774c8f2014-09-16 11:17:08 -070025import org.onlab.onos.net.provider.ProviderId;
26import org.onlab.onos.net.topology.LinkWeight;
tom545708e2014-10-09 17:10:02 -070027import org.onlab.onos.net.topology.PathService;
tom4774c8f2014-09-16 11:17:08 -070028import 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;
36import static org.slf4j.LoggerFactory.getLogger;
37
38/**
39 * Provides implementation of a path selection service atop the current
40 * topology and host services.
41 */
42@Component(immediate = true)
43@Service
tom10262dd2014-09-19 10:51:19 -070044public class PathManager implements PathService {
tom4774c8f2014-09-16 11:17:08 -070045
tomcbefa232014-09-16 14:17:20 -070046 private static final String ELEMENT_ID_NULL = "Element ID cannot be null";
tom4774c8f2014-09-16 11:17:08 -070047
tom7e02cda2014-09-18 12:05:46 -070048 private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core");
tom4774c8f2014-09-16 11:17:08 -070049 private static final PortNumber P0 = PortNumber.portNumber(0);
50
tomcbefa232014-09-16 14:17:20 -070051 private static final EdgeLink NOT_HOST = new NotHost();
52
tom4774c8f2014-09-16 11:17:08 -070053 private final Logger log = getLogger(getClass());
54
55 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 protected TopologyService topologyService;
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
59 protected HostService hostService;
60
61 @Activate
tomca90c462014-09-22 11:40:58 -070062 public void activate() {
tom4774c8f2014-09-16 11:17:08 -070063 log.info("Started");
64 }
65
66 @Deactivate
tomca90c462014-09-22 11:40:58 -070067 public void deactivate() {
tom4774c8f2014-09-16 11:17:08 -070068 log.info("Stopped");
69 }
70
71 @Override
tomcbefa232014-09-16 14:17:20 -070072 public Set<Path> getPaths(ElementId src, ElementId dst) {
tom4774c8f2014-09-16 11:17:08 -070073 return getPaths(src, dst, null);
74 }
75
76 @Override
tomcbefa232014-09-16 14:17:20 -070077 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
78 checkNotNull(src, ELEMENT_ID_NULL);
79 checkNotNull(dst, ELEMENT_ID_NULL);
tom4774c8f2014-09-16 11:17:08 -070080
81 // Get the source and destination edge locations
tomcbefa232014-09-16 14:17:20 -070082 EdgeLink srcEdge = getEdgeLink(src, true);
83 EdgeLink dstEdge = getEdgeLink(dst, false);
84
tomca90c462014-09-22 11:40:58 -070085 // If either edge is null, bail with no paths.
86 if (srcEdge == null || dstEdge == null) {
87 return ImmutableSet.of();
88 }
89
tomcbefa232014-09-16 14:17:20 -070090 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
91 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
tom4774c8f2014-09-16 11:17:08 -070092
93 // If the source and destination are on the same edge device, there
94 // is just one path, so build it and return it.
tomcbefa232014-09-16 14:17:20 -070095 if (srcDevice.equals(dstDevice)) {
tom4774c8f2014-09-16 11:17:08 -070096 return edgeToEdgePaths(srcEdge, dstEdge);
97 }
98
99 // Otherwise get all paths between the source and destination edge
100 // devices.
101 Topology topology = topologyService.currentTopology();
102 Set<Path> paths = weight == null ?
tomcbefa232014-09-16 14:17:20 -0700103 topologyService.getPaths(topology, srcDevice, dstDevice) :
104 topologyService.getPaths(topology, srcDevice, dstDevice, weight);
tom4774c8f2014-09-16 11:17:08 -0700105
106 return edgeToEdgePaths(srcEdge, dstEdge, paths);
107 }
108
tomcbefa232014-09-16 14:17:20 -0700109 // Finds the host edge link if the element ID is a host id of an existing
110 // host. Otherwise, if the host does not exist, it returns null and if
111 // the element ID is not a host ID, returns NOT_HOST edge link.
112 private EdgeLink getEdgeLink(ElementId elementId, boolean isIngress) {
113 if (elementId instanceof HostId) {
114 // Resolve the host, return null.
115 Host host = hostService.getHost((HostId) elementId);
116 if (host == null) {
117 return null;
118 }
119 return new DefaultEdgeLink(PID, new ConnectPoint(elementId, P0),
120 host.location(), isIngress);
121 }
122 return NOT_HOST;
123 }
124
tomca90c462014-09-22 11:40:58 -0700125 // Produces a set of edge-to-edge paths using the set of infrastructure
126 // paths and the given edge links.
tom4774c8f2014-09-16 11:17:08 -0700127 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
128 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
tomca90c462014-09-22 11:40:58 -0700129 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, null));
tom4774c8f2014-09-16 11:17:08 -0700130 return endToEndPaths;
131 }
132
tom4774c8f2014-09-16 11:17:08 -0700133 // Produces a set of edge-to-edge paths using the set of infrastructure
134 // paths and the given edge links.
135 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
136 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
137 for (Path path : paths) {
138 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
139 }
140 return endToEndPaths;
141 }
142
tomca90c462014-09-22 11:40:58 -0700143 // Produces a direct edge-to-edge path.
tom4774c8f2014-09-16 11:17:08 -0700144 private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
tomca90c462014-09-22 11:40:58 -0700145 List<Link> links = Lists.newArrayListWithCapacity(2);
146 // Add source and destination edge links only if they are real and
147 // add the infrastructure path only if it is not null.
148 if (srcLink != NOT_HOST) {
149 links.add(srcLink);
150 }
151 if (path != null) {
152 links.addAll(path.links());
153 }
154 if (dstLink != NOT_HOST) {
155 links.add(dstLink);
156 }
157 return new DefaultPath(PID, links, 2);
tom4774c8f2014-09-16 11:17:08 -0700158 }
159
tomcbefa232014-09-16 14:17:20 -0700160 // Special value for edge link to represent that this is really not an
161 // edge link since the src or dst are really an infrastructure device.
162 private static class NotHost extends DefaultEdgeLink implements EdgeLink {
163 NotHost() {
tom545708e2014-10-09 17:10:02 -0700164 super(PID, new ConnectPoint(HostId.NONE, P0),
165 new HostLocation(DeviceId.NONE, P0, 0L), false);
tomcbefa232014-09-16 14:17:20 -0700166 }
167 }
tom4774c8f2014-09-16 11:17:08 -0700168}