blob: 5fe779330c67159cf399f8ff99266ab05b94e5fe [file] [log] [blame]
tom210f3f32014-09-16 17:33:40 -07001package org.onlab.onos.net.trivial.topology.impl;
tom4774c8f2014-09-16 11:17:08 -07002
3import com.google.common.collect.Lists;
4import com.google.common.collect.Sets;
5import org.apache.felix.scr.annotations.Activate;
6import org.apache.felix.scr.annotations.Component;
7import org.apache.felix.scr.annotations.Deactivate;
8import org.apache.felix.scr.annotations.Reference;
9import org.apache.felix.scr.annotations.ReferenceCardinality;
10import org.apache.felix.scr.annotations.Service;
11import org.onlab.onos.net.ConnectPoint;
12import org.onlab.onos.net.DefaultEdgeLink;
13import org.onlab.onos.net.DefaultPath;
14import org.onlab.onos.net.DeviceId;
15import org.onlab.onos.net.EdgeLink;
tomcbefa232014-09-16 14:17:20 -070016import org.onlab.onos.net.ElementId;
tom4774c8f2014-09-16 11:17:08 -070017import org.onlab.onos.net.Host;
18import org.onlab.onos.net.HostId;
tomcbefa232014-09-16 14:17:20 -070019import org.onlab.onos.net.HostLocation;
tom4774c8f2014-09-16 11:17:08 -070020import org.onlab.onos.net.Link;
21import org.onlab.onos.net.Path;
22import org.onlab.onos.net.PortNumber;
23import org.onlab.onos.net.host.HostService;
tom210f3f32014-09-16 17:33:40 -070024import org.onlab.onos.net.topology.PathService;
tom4774c8f2014-09-16 11:17:08 -070025import org.onlab.onos.net.provider.ProviderId;
26import org.onlab.onos.net.topology.LinkWeight;
27import org.onlab.onos.net.topology.Topology;
28import org.onlab.onos.net.topology.TopologyService;
29import org.slf4j.Logger;
30
31import java.util.List;
32import java.util.Set;
33
34import static com.google.common.base.Preconditions.checkNotNull;
tomcbefa232014-09-16 14:17:20 -070035import static org.onlab.onos.net.DeviceId.deviceId;
tom4774c8f2014-09-16 11:17:08 -070036import 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
tomcbefa232014-09-16 14:17:20 -070044public class SimplePathManager 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
62 public void setUp() {
63 log.info("Started");
64 }
65
66 @Deactivate
67 public void tearDown() {
68 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
85 DeviceId srcDevice = srcEdge != NOT_HOST ? srcEdge.dst().deviceId() : (DeviceId) src;
86 DeviceId dstDevice = dstEdge != NOT_HOST ? dstEdge.src().deviceId() : (DeviceId) dst;
tom4774c8f2014-09-16 11:17:08 -070087
88 // If the source and destination are on the same edge device, there
89 // is just one path, so build it and return it.
tomcbefa232014-09-16 14:17:20 -070090 if (srcDevice.equals(dstDevice)) {
tom4774c8f2014-09-16 11:17:08 -070091 return edgeToEdgePaths(srcEdge, dstEdge);
92 }
93
94 // Otherwise get all paths between the source and destination edge
95 // devices.
96 Topology topology = topologyService.currentTopology();
97 Set<Path> paths = weight == null ?
tomcbefa232014-09-16 14:17:20 -070098 topologyService.getPaths(topology, srcDevice, dstDevice) :
99 topologyService.getPaths(topology, srcDevice, dstDevice, weight);
tom4774c8f2014-09-16 11:17:08 -0700100
101 return edgeToEdgePaths(srcEdge, dstEdge, paths);
102 }
103
tomcbefa232014-09-16 14:17:20 -0700104 // Finds the host edge link if the element ID is a host id of an existing
105 // host. Otherwise, if the host does not exist, it returns null and if
106 // the element ID is not a host ID, returns NOT_HOST edge link.
107 private EdgeLink getEdgeLink(ElementId elementId, boolean isIngress) {
108 if (elementId instanceof HostId) {
109 // Resolve the host, return null.
110 Host host = hostService.getHost((HostId) elementId);
111 if (host == null) {
112 return null;
113 }
114 return new DefaultEdgeLink(PID, new ConnectPoint(elementId, P0),
115 host.location(), isIngress);
116 }
117 return NOT_HOST;
118 }
119
tom4774c8f2014-09-16 11:17:08 -0700120 // Produces a set of direct edge-to-edge paths.
121 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink) {
122 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(1);
tomcbefa232014-09-16 14:17:20 -0700123 if (srcLink != NOT_HOST || dstLink != NOT_HOST) {
124 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink));
125 }
tom4774c8f2014-09-16 11:17:08 -0700126 return endToEndPaths;
127 }
128
129 // Produces a direct edge-to-edge path.
130 private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink) {
131 List<Link> links = Lists.newArrayListWithCapacity(2);
tomcbefa232014-09-16 14:17:20 -0700132 // Add source and destination edge links only if they are real.
133 if (srcLink != NOT_HOST) {
134 links.add(srcLink);
135 }
136 if (dstLink != NOT_HOST) {
137 links.add(dstLink);
138 }
tom4774c8f2014-09-16 11:17:08 -0700139 return new DefaultPath(PID, links, 2);
140 }
141
142 // Produces a set of edge-to-edge paths using the set of infrastructure
143 // paths and the given edge links.
144 private Set<Path> edgeToEdgePaths(EdgeLink srcLink, EdgeLink dstLink, Set<Path> paths) {
145 Set<Path> endToEndPaths = Sets.newHashSetWithExpectedSize(paths.size());
146 for (Path path : paths) {
147 endToEndPaths.add(edgeToEdgePath(srcLink, dstLink, path));
148 }
149 return endToEndPaths;
150 }
151
152 // Produces an edge-to-edge path using the specified infrastructure path
153 // and edge links.
154 private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) {
155 List<Link> links = Lists.newArrayListWithCapacity(path.links().size() + 2);
156 links.add(srcLink);
157 links.addAll(path.links());
158 links.add(dstLink);
159 return new DefaultPath(path.providerId(), links, path.cost() + 2);
160 }
161
tomcbefa232014-09-16 14:17:20 -0700162 // Special value for edge link to represent that this is really not an
163 // edge link since the src or dst are really an infrastructure device.
164 private static class NotHost extends DefaultEdgeLink implements EdgeLink {
165 NotHost() {
166 super(PID, new ConnectPoint(HostId.hostId("nic:none"), P0),
167 new HostLocation(deviceId("none:none"), P0, 0L), false);
168 }
169 }
tom4774c8f2014-09-16 11:17:08 -0700170}