Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
40 changed files
with
749 additions
and
468 deletions
1 | -package org.onlab.onos.cli; | ||
2 | - | ||
3 | -import org.apache.karaf.shell.commands.Argument; | ||
4 | -import org.apache.karaf.shell.commands.Command; | ||
5 | -import org.onlab.onos.GreetService; | ||
6 | - | ||
7 | -/** | ||
8 | - * Simple command example to demonstrate use of Karaf shell extensions; shows | ||
9 | - * use of an optional parameter as well. | ||
10 | - */ | ||
11 | -@Command(scope = "onos", name = "greet", description = "Issues a greeting") | ||
12 | -public class GreetCommand extends AbstractShellCommand { | ||
13 | - | ||
14 | - @Argument(index = 0, name = "name", description = "Name to greet", | ||
15 | - required = false, multiValued = false) | ||
16 | - String name = "dude"; | ||
17 | - | ||
18 | - @Override | ||
19 | - protected Object doExecute() throws Exception { | ||
20 | - print(getService(GreetService.class).yo(name)); | ||
21 | - return null; | ||
22 | - } | ||
23 | -} |
1 | +package org.onlab.onos.cli.net; | ||
2 | + | ||
3 | +import com.google.common.collect.Lists; | ||
4 | +import org.apache.karaf.shell.commands.Argument; | ||
5 | +import org.apache.karaf.shell.commands.Command; | ||
6 | +import org.onlab.onos.net.DeviceId; | ||
7 | +import org.onlab.onos.net.topology.TopologyCluster; | ||
8 | + | ||
9 | +import java.util.Collections; | ||
10 | +import java.util.Comparator; | ||
11 | +import java.util.List; | ||
12 | + | ||
13 | +import static org.onlab.onos.net.topology.ClusterId.clusterId; | ||
14 | + | ||
15 | +/** | ||
16 | + * Lists devices of the specified topology cluster in the current topology. | ||
17 | + */ | ||
18 | +@Command(scope = "onos", name = "cluster-devices", | ||
19 | + description = "Lists devices of the specified topology cluster in the current topology") | ||
20 | +public class ClusterDevicesCommand extends ClustersListCommand { | ||
21 | + | ||
22 | + @Argument(index = 0, name = "id", description = "Cluster ID", | ||
23 | + required = false, multiValued = false) | ||
24 | + String id = null; | ||
25 | + | ||
26 | + protected static final Comparator<DeviceId> ID_COMPARATOR = new Comparator<DeviceId>() { | ||
27 | + @Override | ||
28 | + public int compare(DeviceId id1, DeviceId id2) { | ||
29 | + return id1.uri().toString().compareTo(id2.uri().toString()); | ||
30 | + } | ||
31 | + }; | ||
32 | + | ||
33 | + @Override | ||
34 | + protected Object doExecute() throws Exception { | ||
35 | + int cid = Integer.parseInt(id); | ||
36 | + init(); | ||
37 | + TopologyCluster cluster = service.getCluster(topology, clusterId(cid)); | ||
38 | + List<DeviceId> ids = Lists.newArrayList(service.getClusterDevices(topology, cluster)); | ||
39 | + Collections.sort(ids, ID_COMPARATOR); | ||
40 | + for (DeviceId deviceId : ids) { | ||
41 | + print("%s", deviceId); | ||
42 | + } | ||
43 | + return null; | ||
44 | + } | ||
45 | + | ||
46 | + | ||
47 | +} |
1 | -package org.onlab.onos.cli; | 1 | +package org.onlab.onos.cli.net; |
2 | 2 | ||
3 | import org.apache.karaf.shell.console.Completer; | 3 | import org.apache.karaf.shell.console.Completer; |
4 | import org.apache.karaf.shell.console.completer.StringsCompleter; | 4 | import org.apache.karaf.shell.console.completer.StringsCompleter; |
5 | -import org.onlab.onos.GreetService; | 5 | +import org.onlab.onos.cli.AbstractShellCommand; |
6 | +import org.onlab.onos.net.topology.Topology; | ||
7 | +import org.onlab.onos.net.topology.TopologyCluster; | ||
8 | +import org.onlab.onos.net.topology.TopologyService; | ||
6 | 9 | ||
7 | -import java.util.Iterator; | ||
8 | import java.util.List; | 10 | import java.util.List; |
9 | import java.util.SortedSet; | 11 | import java.util.SortedSet; |
10 | 12 | ||
11 | /** | 13 | /** |
12 | - * Simple example of a command-line parameter completer. | 14 | + * Cluster ID completer. |
13 | - * For a more open-ended sets a more efficient implementation would be required. | ||
14 | */ | 15 | */ |
15 | -public class NameCompleter implements Completer { | 16 | +public class ClusterIdCompleter implements Completer { |
16 | @Override | 17 | @Override |
17 | public int complete(String buffer, int cursor, List<String> candidates) { | 18 | public int complete(String buffer, int cursor, List<String> candidates) { |
18 | // Delegate string completer | 19 | // Delegate string completer |
19 | StringsCompleter delegate = new StringsCompleter(); | 20 | StringsCompleter delegate = new StringsCompleter(); |
20 | 21 | ||
21 | // Fetch our service and feed it's offerings to the string completer | 22 | // Fetch our service and feed it's offerings to the string completer |
22 | - GreetService greetService = AbstractShellCommand.get(GreetService.class); | 23 | + TopologyService service = AbstractShellCommand.get(TopologyService.class); |
23 | - Iterator<String> it = greetService.names().iterator(); | 24 | + Topology topology = service.currentTopology(); |
25 | + | ||
24 | SortedSet<String> strings = delegate.getStrings(); | 26 | SortedSet<String> strings = delegate.getStrings(); |
25 | - while (it.hasNext()) { | 27 | + for (TopologyCluster cluster : service.getClusters(topology)) { |
26 | - strings.add(it.next()); | 28 | + strings.add(Integer.toString(cluster.id().index())); |
27 | } | 29 | } |
28 | 30 | ||
29 | // Now let the completer do the work for figuring out what to offer. | 31 | // Now let the completer do the work for figuring out what to offer. | ... | ... |
1 | +package org.onlab.onos.cli.net; | ||
2 | + | ||
3 | +import org.apache.karaf.shell.commands.Argument; | ||
4 | +import org.apache.karaf.shell.commands.Command; | ||
5 | +import org.onlab.onos.net.Link; | ||
6 | +import org.onlab.onos.net.topology.TopologyCluster; | ||
7 | + | ||
8 | +import static org.onlab.onos.cli.net.LinksListCommand.linkString; | ||
9 | +import static org.onlab.onos.net.topology.ClusterId.clusterId; | ||
10 | + | ||
11 | +/** | ||
12 | + * Lists links of the specified topology cluster in the current topology. | ||
13 | + */ | ||
14 | +@Command(scope = "onos", name = "cluster-links", | ||
15 | + description = "Lists links of the specified topology cluster in the current topology") | ||
16 | +public class ClusterLinksCommand extends ClustersListCommand { | ||
17 | + | ||
18 | + @Argument(index = 0, name = "id", description = "Cluster ID", | ||
19 | + required = false, multiValued = false) | ||
20 | + String id = null; | ||
21 | + | ||
22 | + @Override | ||
23 | + protected Object doExecute() throws Exception { | ||
24 | + int cid = Integer.parseInt(id); | ||
25 | + init(); | ||
26 | + TopologyCluster cluster = service.getCluster(topology, clusterId(cid)); | ||
27 | + for (Link link : service.getClusterLinks(topology, cluster)) { | ||
28 | + print(linkString(link)); | ||
29 | + } | ||
30 | + return null; | ||
31 | + } | ||
32 | + | ||
33 | + | ||
34 | +} |
1 | +package org.onlab.onos.cli.net; | ||
2 | + | ||
3 | +import com.google.common.collect.Lists; | ||
4 | +import org.apache.karaf.shell.commands.Command; | ||
5 | +import org.onlab.onos.net.topology.TopologyCluster; | ||
6 | + | ||
7 | +import java.util.Collections; | ||
8 | +import java.util.Comparator; | ||
9 | +import java.util.List; | ||
10 | + | ||
11 | +/** | ||
12 | + * Lists all clusters in the current topology. | ||
13 | + */ | ||
14 | +@Command(scope = "onos", name = "clusters", | ||
15 | + description = "Lists all clusters in the current topology") | ||
16 | +public class ClustersListCommand extends TopologyCommand { | ||
17 | + | ||
18 | + private static final String FMT = | ||
19 | + "id=%s, devices=%d, links=%d"; | ||
20 | + | ||
21 | + protected static final Comparator<TopologyCluster> ID_COMPARATOR = | ||
22 | + new Comparator<TopologyCluster>() { | ||
23 | + @Override | ||
24 | + public int compare(TopologyCluster c1, TopologyCluster c2) { | ||
25 | + return c1.id().index() - c2.id().index(); | ||
26 | + } | ||
27 | + }; | ||
28 | + | ||
29 | + @Override | ||
30 | + protected Object doExecute() throws Exception { | ||
31 | + init(); | ||
32 | + List<TopologyCluster> clusters = Lists.newArrayList(service.getClusters(topology)); | ||
33 | + Collections.sort(clusters, ID_COMPARATOR); | ||
34 | + | ||
35 | + for (TopologyCluster cluster : clusters) { | ||
36 | + print(FMT, cluster.id(), cluster.deviceCount(), cluster.linkCount()); | ||
37 | + } | ||
38 | + return null; | ||
39 | + } | ||
40 | + | ||
41 | +} |
... | @@ -27,9 +27,20 @@ public class LinksListCommand extends AbstractShellCommand { | ... | @@ -27,9 +27,20 @@ public class LinksListCommand extends AbstractShellCommand { |
27 | Iterable<Link> links = uri != null ? | 27 | Iterable<Link> links = uri != null ? |
28 | service.getDeviceLinks(deviceId(uri)) : service.getLinks(); | 28 | service.getDeviceLinks(deviceId(uri)) : service.getLinks(); |
29 | for (Link link : links) { | 29 | for (Link link : links) { |
30 | - print(FMT, link.src().deviceId(), link.src().port(), | 30 | + print(linkString(link)); |
31 | - link.dst().deviceId(), link.dst().port(), link.type()); | ||
32 | } | 31 | } |
33 | return null; | 32 | return null; |
34 | } | 33 | } |
34 | + | ||
35 | + /** | ||
36 | + * Returns a formated string representing the gien link. | ||
37 | + * | ||
38 | + * @param link infrastructure link | ||
39 | + * @return formated link string | ||
40 | + */ | ||
41 | + public static String linkString(Link link) { | ||
42 | + return String.format(FMT, link.src().deviceId(), link.src().port(), | ||
43 | + link.dst().deviceId(), link.dst().port(), link.type()); | ||
44 | + | ||
45 | + } | ||
35 | } | 46 | } | ... | ... |
1 | +package org.onlab.onos.cli.net; | ||
2 | + | ||
3 | +import org.apache.karaf.shell.commands.Command; | ||
4 | +import org.onlab.onos.cli.AbstractShellCommand; | ||
5 | +import org.onlab.onos.net.topology.Topology; | ||
6 | +import org.onlab.onos.net.topology.TopologyService; | ||
7 | + | ||
8 | +/** | ||
9 | + * Lists summary of the current topology. | ||
10 | + */ | ||
11 | +@Command(scope = "onos", name = "topology", | ||
12 | + description = "Lists summary of the current topology") | ||
13 | +public class TopologyCommand extends AbstractShellCommand { | ||
14 | + | ||
15 | + private static final String FMT = | ||
16 | + "time=%s, devices=%d, links=%d, clusters=%d, paths=%d"; | ||
17 | + | ||
18 | + protected TopologyService service; | ||
19 | + protected Topology topology; | ||
20 | + | ||
21 | + /** | ||
22 | + * Initializes the context for all cluster commands. | ||
23 | + */ | ||
24 | + protected void init() { | ||
25 | + service = getService(TopologyService.class); | ||
26 | + topology = service.currentTopology(); | ||
27 | + } | ||
28 | + | ||
29 | + @Override | ||
30 | + protected Object doExecute() throws Exception { | ||
31 | + init(); | ||
32 | + print(FMT, topology.time(), topology.deviceCount(), topology.linkCount(), | ||
33 | + topology.clusterCount(), topology.pathCount()); | ||
34 | + return null; | ||
35 | + } | ||
36 | + | ||
37 | +} |
... | @@ -32,16 +32,27 @@ | ... | @@ -32,16 +32,27 @@ |
32 | </command> | 32 | </command> |
33 | 33 | ||
34 | <command> | 34 | <command> |
35 | - <action class="org.onlab.onos.cli.GreetCommand"/> | 35 | + <action class="org.onlab.onos.cli.net.TopologyCommand"/> |
36 | + </command> | ||
37 | + <command> | ||
38 | + <action class="org.onlab.onos.cli.net.ClustersListCommand"/> | ||
39 | + </command> | ||
40 | + <command> | ||
41 | + <action class="org.onlab.onos.cli.net.ClusterDevicesCommand"/> | ||
36 | <completers> | 42 | <completers> |
37 | - <ref component-id="nameCompleter"/> | 43 | + <ref component-id="clusterIdCompleter"/> |
44 | + </completers> | ||
45 | + </command> | ||
46 | + <command> | ||
47 | + <action class="org.onlab.onos.cli.net.ClusterLinksCommand"/> | ||
48 | + <completers> | ||
49 | + <ref component-id="clusterIdCompleter"/> | ||
38 | </completers> | 50 | </completers> |
39 | </command> | 51 | </command> |
40 | </command-bundle> | 52 | </command-bundle> |
41 | 53 | ||
42 | <bean id="deviceIdCompleter" class="org.onlab.onos.cli.net.DeviceIdCompleter"/> | 54 | <bean id="deviceIdCompleter" class="org.onlab.onos.cli.net.DeviceIdCompleter"/> |
55 | + <bean id="clusterIdCompleter" class="org.onlab.onos.cli.net.ClusterIdCompleter"/> | ||
43 | <bean id="roleCompleter" class="org.onlab.onos.cli.net.RoleCompleter"/> | 56 | <bean id="roleCompleter" class="org.onlab.onos.cli.net.RoleCompleter"/> |
44 | 57 | ||
45 | - <bean id="nameCompleter" class="org.onlab.onos.cli.NameCompleter"/> | ||
46 | - | ||
47 | </blueprint> | 58 | </blueprint> | ... | ... |
... | @@ -16,7 +16,7 @@ public class DefaultLink extends AbstractModel implements Link { | ... | @@ -16,7 +16,7 @@ public class DefaultLink extends AbstractModel implements Link { |
16 | private final Type type; | 16 | private final Type type; |
17 | 17 | ||
18 | /** | 18 | /** |
19 | - * Creates a link description using the supplied information. | 19 | + * Creates an infrastructure link using the supplied information. |
20 | * | 20 | * |
21 | * @param providerId provider identity | 21 | * @param providerId provider identity |
22 | * @param src link source | 22 | * @param src link source | ... | ... |
1 | +package org.onlab.onos.net; | ||
2 | + | ||
3 | +import com.google.common.collect.ImmutableList; | ||
4 | +import org.onlab.onos.net.provider.ProviderId; | ||
5 | + | ||
6 | +import java.util.List; | ||
7 | +import java.util.Objects; | ||
8 | + | ||
9 | +import static com.google.common.base.Preconditions.checkArgument; | ||
10 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
11 | + | ||
12 | +/** | ||
13 | + * Default implementation of a network path. | ||
14 | + */ | ||
15 | +public class DefaultPath extends DefaultLink implements Path { | ||
16 | + | ||
17 | + private final List<Link> links; | ||
18 | + private final double cost; | ||
19 | + | ||
20 | + /** | ||
21 | + * Creates a path from the specified source and destination using the | ||
22 | + * supplied list of links. | ||
23 | + * | ||
24 | + * @param providerId provider identity | ||
25 | + * @param links contiguous links that comprise the path | ||
26 | + * @param cost unit-less path cost | ||
27 | + */ | ||
28 | + public DefaultPath(ProviderId providerId, List<Link> links, double cost) { | ||
29 | + super(providerId, source(links), destination(links), Type.INDIRECT); | ||
30 | + this.links = ImmutableList.copyOf(links); | ||
31 | + this.cost = cost; | ||
32 | + } | ||
33 | + | ||
34 | + @Override | ||
35 | + public List<Link> links() { | ||
36 | + return links; | ||
37 | + } | ||
38 | + | ||
39 | + @Override | ||
40 | + public double cost() { | ||
41 | + return cost; | ||
42 | + } | ||
43 | + | ||
44 | + // Returns the source of the first link. | ||
45 | + private static ConnectPoint source(List<Link> links) { | ||
46 | + checkNotNull(links, "List of path links cannot be null"); | ||
47 | + checkArgument(!links.isEmpty(), "List of path links cannot be empty"); | ||
48 | + return links.get(0).src(); | ||
49 | + } | ||
50 | + | ||
51 | + // Returns the destination of the last link. | ||
52 | + private static ConnectPoint destination(List<Link> links) { | ||
53 | + checkNotNull(links, "List of path links cannot be null"); | ||
54 | + checkArgument(!links.isEmpty(), "List of path links cannot be empty"); | ||
55 | + return links.get(links.size() - 1).dst(); | ||
56 | + } | ||
57 | + | ||
58 | + @Override | ||
59 | + public int hashCode() { | ||
60 | + return 31 * super.hashCode() + Objects.hash(links); | ||
61 | + } | ||
62 | + | ||
63 | + @Override | ||
64 | + public boolean equals(Object obj) { | ||
65 | + if (obj instanceof DefaultPath) { | ||
66 | + final DefaultPath other = (DefaultPath) obj; | ||
67 | + return Objects.equals(this.links, other.links); | ||
68 | + } | ||
69 | + return false; | ||
70 | + } | ||
71 | +} |
... | @@ -17,4 +17,11 @@ public interface Path extends Link { | ... | @@ -17,4 +17,11 @@ public interface Path extends Link { |
17 | */ | 17 | */ |
18 | List<Link> links(); | 18 | List<Link> links(); |
19 | 19 | ||
20 | + /** | ||
21 | + * Returns the path cost as a unit-less value. | ||
22 | + * | ||
23 | + * @return unit-less path cost | ||
24 | + */ | ||
25 | + double cost(); | ||
26 | + | ||
20 | } | 27 | } | ... | ... |
... | @@ -27,6 +27,15 @@ public final class ClusterId { | ... | @@ -27,6 +27,15 @@ public final class ClusterId { |
27 | return new ClusterId(id); | 27 | return new ClusterId(id); |
28 | } | 28 | } |
29 | 29 | ||
30 | + /** | ||
31 | + * Returns the backing integer index. | ||
32 | + * | ||
33 | + * @return backing integer index | ||
34 | + */ | ||
35 | + public int index() { | ||
36 | + return id; | ||
37 | + } | ||
38 | + | ||
30 | @Override | 39 | @Override |
31 | public int hashCode() { | 40 | public int hashCode() { |
32 | return Objects.hash(id); | 41 | return Objects.hash(id); | ... | ... |
1 | +package org.onlab.onos.net.topology; | ||
2 | + | ||
3 | +import com.google.common.collect.ImmutableSet; | ||
4 | +import org.onlab.onos.net.Description; | ||
5 | + | ||
6 | +/** | ||
7 | + * Describes attribute(s) of a network graph. | ||
8 | + */ | ||
9 | +public interface GraphDescription extends Description { | ||
10 | + | ||
11 | + /** | ||
12 | + * Returns the creation timestamp of the graph description. This is | ||
13 | + * expressed in system nanos to allow proper sequencing. | ||
14 | + * | ||
15 | + * @return graph description creation timestamp | ||
16 | + */ | ||
17 | + long timestamp(); | ||
18 | + | ||
19 | + /** | ||
20 | + * Returns the set of topology graph vertexes. | ||
21 | + * | ||
22 | + * @return set of graph vertexes | ||
23 | + */ | ||
24 | + ImmutableSet<TopologyVertex> vertexes(); | ||
25 | + | ||
26 | + /** | ||
27 | + * Returns the set of topology graph edges. | ||
28 | + * | ||
29 | + * @return set of graph edges | ||
30 | + */ | ||
31 | + ImmutableSet<TopologyEdge> edges(); | ||
32 | + | ||
33 | +} | ||
34 | + |
... | @@ -6,5 +6,5 @@ import org.onlab.graph.EdgeWeight; | ... | @@ -6,5 +6,5 @@ import org.onlab.graph.EdgeWeight; |
6 | * Entity capable of determining cost or weight of a specified topology | 6 | * Entity capable of determining cost or weight of a specified topology |
7 | * graph edge. | 7 | * graph edge. |
8 | */ | 8 | */ |
9 | -public interface LinkWeight extends EdgeWeight<TopoVertex, TopoEdge> { | 9 | +public interface LinkWeight extends EdgeWeight<TopologyVertex, TopologyEdge> { |
10 | } | 10 | } | ... | ... |
1 | -package org.onlab.onos.net.topology; | ||
2 | - | ||
3 | -import org.onlab.graph.Graph; | ||
4 | -import org.onlab.graph.GraphPathSearch; | ||
5 | -import org.onlab.onos.net.Description; | ||
6 | -import org.onlab.onos.net.DeviceId; | ||
7 | -import org.onlab.onos.net.Link; | ||
8 | - | ||
9 | -import java.util.Set; | ||
10 | - | ||
11 | -/** | ||
12 | - * Describes attribute(s) of a network topology. | ||
13 | - */ | ||
14 | -public interface TopologyDescription extends Description { | ||
15 | - | ||
16 | - /** | ||
17 | - * Returns the creation timestamp of the topology description. This is | ||
18 | - * expressed in system nanos to allow proper sequencing. | ||
19 | - * | ||
20 | - * @return topology description creation timestamp | ||
21 | - */ | ||
22 | - long timestamp(); | ||
23 | - | ||
24 | - /** | ||
25 | - * Returns the topology graph. | ||
26 | - * | ||
27 | - * @return network graph | ||
28 | - */ | ||
29 | - Graph<TopoVertex, TopoEdge> graph(); | ||
30 | - | ||
31 | - /** | ||
32 | - * Returns the results of the path search through the network graph. This | ||
33 | - * is assumed to contain results of seach fro the given device to all | ||
34 | - * other devices. | ||
35 | - * | ||
36 | - * @param srcDeviceId source device identifier | ||
37 | - * @return path search result for the given source node | ||
38 | - */ | ||
39 | - GraphPathSearch.Result pathResults(DeviceId srcDeviceId); | ||
40 | - | ||
41 | - /** | ||
42 | - * Returns the set of topology SCC clusters. | ||
43 | - * | ||
44 | - * @return set of SCC clusters | ||
45 | - */ | ||
46 | - Set<TopologyCluster> clusters(); | ||
47 | - | ||
48 | - /** | ||
49 | - * Returns the set of devices contained by the specified topology cluster. | ||
50 | - * | ||
51 | - * @return set of devices that belong to the specified cluster | ||
52 | - */ | ||
53 | - Set<DeviceId> clusterDevices(TopologyCluster cluster); | ||
54 | - | ||
55 | - /** | ||
56 | - * Returns the set of infrastructure links contained by the specified cluster. | ||
57 | - * | ||
58 | - * @return set of links that form the given cluster | ||
59 | - */ | ||
60 | - Set<Link> clusterLinks(TopologyCluster cluster); | ||
61 | - | ||
62 | - /** | ||
63 | - * Returns the topology SCC cluster which contains the given device. | ||
64 | - * | ||
65 | - * @param deviceId device identifier | ||
66 | - * @return topology cluster that contains the specified device | ||
67 | - */ | ||
68 | - TopologyCluster clusterFor(DeviceId deviceId); | ||
69 | - | ||
70 | -} | ||
71 | - |
... | @@ -6,7 +6,7 @@ import org.onlab.onos.net.Link; | ... | @@ -6,7 +6,7 @@ import org.onlab.onos.net.Link; |
6 | /** | 6 | /** |
7 | * Represents an edge in the topology graph. | 7 | * Represents an edge in the topology graph. |
8 | */ | 8 | */ |
9 | -public interface TopoEdge extends Edge<TopoVertex> { | 9 | +public interface TopologyEdge extends Edge<TopologyVertex> { |
10 | 10 | ||
11 | /** | 11 | /** |
12 | * Returns the associated infrastructure link. | 12 | * Returns the associated infrastructure link. | ... | ... |
... | @@ -10,16 +10,13 @@ import java.util.List; | ... | @@ -10,16 +10,13 @@ import java.util.List; |
10 | */ | 10 | */ |
11 | public interface TopologyProviderService extends ProviderService<TopologyProvider> { | 11 | public interface TopologyProviderService extends ProviderService<TopologyProvider> { |
12 | 12 | ||
13 | - // What can be conveyed in a topology that isn't by individual | ||
14 | - // providers? | ||
15 | - | ||
16 | /** | 13 | /** |
17 | * Signals the core that some aspect of the topology has changed. | 14 | * Signals the core that some aspect of the topology has changed. |
18 | * | 15 | * |
19 | - * @param topoDescription information about topology | 16 | + * @param graphDescription information about the network graph |
20 | - * @param reasons events that triggered topology change | 17 | + * @param reasons events that triggered topology change |
21 | */ | 18 | */ |
22 | - void topologyChanged(TopologyDescription topoDescription, | 19 | + void topologyChanged(GraphDescription graphDescription, |
23 | List<Event> reasons); | 20 | List<Event> reasons); |
24 | 21 | ||
25 | } | 22 | } | ... | ... |
1 | package org.onlab.onos.net.topology; | 1 | package org.onlab.onos.net.topology; |
2 | 2 | ||
3 | -import org.onlab.graph.Graph; | ||
4 | import org.onlab.onos.net.ConnectPoint; | 3 | import org.onlab.onos.net.ConnectPoint; |
5 | import org.onlab.onos.net.DeviceId; | 4 | import org.onlab.onos.net.DeviceId; |
5 | +import org.onlab.onos.net.Link; | ||
6 | import org.onlab.onos.net.Path; | 6 | import org.onlab.onos.net.Path; |
7 | 7 | ||
8 | import java.util.Set; | 8 | import java.util.Set; |
... | @@ -21,12 +21,21 @@ public interface TopologyService { | ... | @@ -21,12 +21,21 @@ public interface TopologyService { |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * Indicates whether the specified topology is the latest or not. | 23 | * Indicates whether the specified topology is the latest or not. |
24 | + * | ||
24 | * @param topology topology descriptor | 25 | * @param topology topology descriptor |
25 | * @return true if the topology is the most recent; false otherwise | 26 | * @return true if the topology is the most recent; false otherwise |
26 | */ | 27 | */ |
27 | boolean isLatest(Topology topology); | 28 | boolean isLatest(Topology topology); |
28 | 29 | ||
29 | /** | 30 | /** |
31 | + * Returns the graph view of the specified topology. | ||
32 | + * | ||
33 | + * @param topology topology descriptor | ||
34 | + * @return topology graph view | ||
35 | + */ | ||
36 | + TopologyGraph getGraph(Topology topology); | ||
37 | + | ||
38 | + /** | ||
30 | * Returns the set of clusters in the specified topology. | 39 | * Returns the set of clusters in the specified topology. |
31 | * | 40 | * |
32 | * @param topology topology descriptor | 41 | * @param topology topology descriptor |
... | @@ -35,12 +44,31 @@ public interface TopologyService { | ... | @@ -35,12 +44,31 @@ public interface TopologyService { |
35 | Set<TopologyCluster> getClusters(Topology topology); | 44 | Set<TopologyCluster> getClusters(Topology topology); |
36 | 45 | ||
37 | /** | 46 | /** |
38 | - * Returns the graph view of the specified topology. | 47 | + * Returns the cluster with the specified ID. |
39 | * | 48 | * |
40 | - * @param topology topology descriptor | 49 | + * @param topology topology descriptor |
41 | - * @return topology graph view | 50 | + * @param clusterId cluster identifier |
51 | + * @return topology cluster | ||
52 | + */ | ||
53 | + TopologyCluster getCluster(Topology topology, ClusterId clusterId); | ||
54 | + | ||
55 | + /** | ||
56 | + * Returns the set of devices that belong to the specified cluster. | ||
57 | + * | ||
58 | + * @param topology topology descriptor | ||
59 | + * @param cluster topology cluster | ||
60 | + * @return set of cluster devices | ||
61 | + */ | ||
62 | + Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster); | ||
63 | + | ||
64 | + /** | ||
65 | + * Returns the set of links that form the specified cluster. | ||
66 | + * | ||
67 | + * @param topology topology descriptor | ||
68 | + * @param cluster topology cluster | ||
69 | + * @return set of cluster links | ||
42 | */ | 70 | */ |
43 | - Graph<TopoVertex, TopoEdge> getGraph(Topology topology); | 71 | + Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster); |
44 | 72 | ||
45 | /** | 73 | /** |
46 | * Returns the set of all shortest paths, precomputed in terms of hop-count, | 74 | * Returns the set of all shortest paths, precomputed in terms of hop-count, | ... | ... |
... | @@ -6,7 +6,7 @@ import org.onlab.onos.net.DeviceId; | ... | @@ -6,7 +6,7 @@ import org.onlab.onos.net.DeviceId; |
6 | /** | 6 | /** |
7 | * Represents a vertex in the topology graph. | 7 | * Represents a vertex in the topology graph. |
8 | */ | 8 | */ |
9 | -public interface TopoVertex extends Vertex { | 9 | +public interface TopologyVertex extends Vertex { |
10 | 10 | ||
11 | /** | 11 | /** |
12 | * Returns the associated infrastructure device identification. | 12 | * Returns the associated infrastructure device identification. | ... | ... |
1 | -package org.onlab.onos.net.trivial.impl; | 1 | +package org.onlab.onos.net.trivial.host.impl; |
2 | 2 | ||
3 | import org.apache.felix.scr.annotations.Activate; | 3 | import org.apache.felix.scr.annotations.Activate; |
4 | import org.apache.felix.scr.annotations.Component; | 4 | import org.apache.felix.scr.annotations.Component; | ... | ... |
1 | -package org.onlab.onos.net.trivial.impl; | 1 | +package org.onlab.onos.net.trivial.host.impl; |
2 | + | ||
3 | +import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED; | ||
4 | +import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED; | ||
5 | +import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED; | ||
6 | +import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED; | ||
7 | + | ||
8 | +import java.util.Collections; | ||
9 | +import java.util.HashSet; | ||
10 | +import java.util.Map; | ||
11 | +import java.util.Set; | ||
12 | +import java.util.concurrent.ConcurrentHashMap; | ||
2 | 13 | ||
3 | import org.onlab.onos.net.ConnectPoint; | 14 | import org.onlab.onos.net.ConnectPoint; |
4 | import org.onlab.onos.net.DefaultHost; | 15 | import org.onlab.onos.net.DefaultHost; |
... | @@ -15,17 +26,6 @@ import com.google.common.collect.HashMultimap; | ... | @@ -15,17 +26,6 @@ import com.google.common.collect.HashMultimap; |
15 | import com.google.common.collect.ImmutableSet; | 26 | import com.google.common.collect.ImmutableSet; |
16 | import com.google.common.collect.Multimap; | 27 | import com.google.common.collect.Multimap; |
17 | 28 | ||
18 | -import java.util.Collections; | ||
19 | -import java.util.HashSet; | ||
20 | -import java.util.Map; | ||
21 | -import java.util.Set; | ||
22 | -import java.util.concurrent.ConcurrentHashMap; | ||
23 | - | ||
24 | -import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED; | ||
25 | -import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED; | ||
26 | -import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED; | ||
27 | -import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED; | ||
28 | - | ||
29 | /** | 29 | /** |
30 | * Manages inventory of end-station hosts using trivial in-memory | 30 | * Manages inventory of end-station hosts using trivial in-memory |
31 | * implementation. | 31 | * implementation. |
... | @@ -36,6 +36,7 @@ public class SimpleHostStore { | ... | @@ -36,6 +36,7 @@ public class SimpleHostStore { |
36 | 36 | ||
37 | // hosts sorted based on their location | 37 | // hosts sorted based on their location |
38 | private final Multimap<ConnectPoint, Host> locations = HashMultimap.create(); | 38 | private final Multimap<ConnectPoint, Host> locations = HashMultimap.create(); |
39 | + | ||
39 | /** | 40 | /** |
40 | * Creates a new host or updates the existing one based on the specified | 41 | * Creates a new host or updates the existing one based on the specified |
41 | * description. | 42 | * description. |
... | @@ -46,7 +47,7 @@ public class SimpleHostStore { | ... | @@ -46,7 +47,7 @@ public class SimpleHostStore { |
46 | * @return appropriate event or null if no change resulted | 47 | * @return appropriate event or null if no change resulted |
47 | */ | 48 | */ |
48 | HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId, | 49 | HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId, |
49 | - HostDescription hostDescription) { | 50 | + HostDescription hostDescription) { |
50 | Host host = hosts.get(hostId); | 51 | Host host = hosts.get(hostId); |
51 | if (host == null) { | 52 | if (host == null) { |
52 | return createHost(providerId, hostId, hostDescription); | 53 | return createHost(providerId, hostId, hostDescription); | ... | ... |
core/trivial/src/main/java/org/onlab/onos/net/trivial/topology/impl/DefaultGraphDescription.java
0 → 100644
1 | +package org.onlab.onos.net.trivial.topology.impl; | ||
2 | + | ||
3 | +import com.google.common.collect.ImmutableSet; | ||
4 | +import com.google.common.collect.Maps; | ||
5 | +import org.onlab.onos.net.ConnectPoint; | ||
6 | +import org.onlab.onos.net.Device; | ||
7 | +import org.onlab.onos.net.DeviceId; | ||
8 | +import org.onlab.onos.net.Link; | ||
9 | +import org.onlab.onos.net.topology.GraphDescription; | ||
10 | +import org.onlab.onos.net.topology.TopologyEdge; | ||
11 | +import org.onlab.onos.net.topology.TopologyVertex; | ||
12 | + | ||
13 | +import java.util.Map; | ||
14 | + | ||
15 | +/** | ||
16 | + * Default implementation of an immutable topology graph data carrier. | ||
17 | + */ | ||
18 | +class DefaultGraphDescription implements GraphDescription { | ||
19 | + | ||
20 | + private final long nanos; | ||
21 | + private final ImmutableSet<TopologyVertex> vertexes; | ||
22 | + private final ImmutableSet<TopologyEdge> edges; | ||
23 | + | ||
24 | + private final Map<DeviceId, TopologyVertex> vertexesById = Maps.newHashMap(); | ||
25 | + | ||
26 | + | ||
27 | + /** | ||
28 | + * Creates a minimal topology graph description to allow core to construct | ||
29 | + * and process the topology graph. | ||
30 | + * | ||
31 | + * @param nanos time in nanos of when the topology description was created | ||
32 | + * @param devices collection of infrastructure devices | ||
33 | + * @param links collection of infrastructure links | ||
34 | + */ | ||
35 | + DefaultGraphDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) { | ||
36 | + this.nanos = nanos; | ||
37 | + this.vertexes = buildVertexes(devices); | ||
38 | + this.edges = buildEdges(links); | ||
39 | + vertexesById.clear(); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + public long timestamp() { | ||
44 | + return nanos; | ||
45 | + } | ||
46 | + | ||
47 | + @Override | ||
48 | + public ImmutableSet<TopologyVertex> vertexes() { | ||
49 | + return vertexes; | ||
50 | + } | ||
51 | + | ||
52 | + @Override | ||
53 | + public ImmutableSet<TopologyEdge> edges() { | ||
54 | + return edges; | ||
55 | + } | ||
56 | + | ||
57 | + // Builds a set of topology vertexes from the specified list of devices | ||
58 | + private ImmutableSet<TopologyVertex> buildVertexes(Iterable<Device> devices) { | ||
59 | + ImmutableSet.Builder<TopologyVertex> vertexes = ImmutableSet.builder(); | ||
60 | + for (Device device : devices) { | ||
61 | + TopologyVertex vertex = new DefaultTopologyVertex(device.id()); | ||
62 | + vertexes.add(vertex); | ||
63 | + vertexesById.put(vertex.deviceId(), vertex); | ||
64 | + } | ||
65 | + return vertexes.build(); | ||
66 | + } | ||
67 | + | ||
68 | + // Builds a set of topology vertexes from the specified list of links | ||
69 | + private ImmutableSet<TopologyEdge> buildEdges(Iterable<Link> links) { | ||
70 | + ImmutableSet.Builder<TopologyEdge> edges = ImmutableSet.builder(); | ||
71 | + for (Link link : links) { | ||
72 | + edges.add(new DefaultTopologyEdge(vertexOf(link.src()), | ||
73 | + vertexOf(link.dst()), link)); | ||
74 | + } | ||
75 | + return edges.build(); | ||
76 | + } | ||
77 | + | ||
78 | + // Fetches a vertex corresponding to the given connection point device. | ||
79 | + private TopologyVertex vertexOf(ConnectPoint connectPoint) { | ||
80 | + DeviceId id = connectPoint.deviceId(); | ||
81 | + TopologyVertex vertex = vertexesById.get(id); | ||
82 | + if (vertex == null) { | ||
83 | + // If vertex does not exist, create one and register it. | ||
84 | + vertex = new DefaultTopologyVertex(id); | ||
85 | + vertexesById.put(id, vertex); | ||
86 | + } | ||
87 | + return vertex; | ||
88 | + } | ||
89 | + | ||
90 | +} |
This diff is collapsed. Click to expand it.
1 | -package org.onlab.onos.net.trivial.topology.provider.impl; | 1 | +package org.onlab.onos.net.trivial.topology.impl; |
2 | 2 | ||
3 | import org.onlab.onos.net.Link; | 3 | import org.onlab.onos.net.Link; |
4 | -import org.onlab.onos.net.topology.TopoEdge; | 4 | +import org.onlab.onos.net.topology.TopologyEdge; |
5 | -import org.onlab.onos.net.topology.TopoVertex; | 5 | +import org.onlab.onos.net.topology.TopologyVertex; |
6 | 6 | ||
7 | import java.util.Objects; | 7 | import java.util.Objects; |
8 | 8 | ||
... | @@ -11,11 +11,11 @@ import static com.google.common.base.MoreObjects.toStringHelper; | ... | @@ -11,11 +11,11 @@ import static com.google.common.base.MoreObjects.toStringHelper; |
11 | /** | 11 | /** |
12 | * Implementation of the topology edge backed by a link. | 12 | * Implementation of the topology edge backed by a link. |
13 | */ | 13 | */ |
14 | -class DefaultTopoEdge implements TopoEdge { | 14 | +class DefaultTopologyEdge implements TopologyEdge { |
15 | 15 | ||
16 | private final Link link; | 16 | private final Link link; |
17 | - private final TopoVertex src; | 17 | + private final TopologyVertex src; |
18 | - private final TopoVertex dst; | 18 | + private final TopologyVertex dst; |
19 | 19 | ||
20 | /** | 20 | /** |
21 | * Creates a new topology edge. | 21 | * Creates a new topology edge. |
... | @@ -24,7 +24,7 @@ class DefaultTopoEdge implements TopoEdge { | ... | @@ -24,7 +24,7 @@ class DefaultTopoEdge implements TopoEdge { |
24 | * @param dst destination vertex | 24 | * @param dst destination vertex |
25 | * @param link infrastructure link | 25 | * @param link infrastructure link |
26 | */ | 26 | */ |
27 | - DefaultTopoEdge(TopoVertex src, TopoVertex dst, Link link) { | 27 | + DefaultTopologyEdge(TopologyVertex src, TopologyVertex dst, Link link) { |
28 | this.src = src; | 28 | this.src = src; |
29 | this.dst = dst; | 29 | this.dst = dst; |
30 | this.link = link; | 30 | this.link = link; |
... | @@ -36,12 +36,12 @@ class DefaultTopoEdge implements TopoEdge { | ... | @@ -36,12 +36,12 @@ class DefaultTopoEdge implements TopoEdge { |
36 | } | 36 | } |
37 | 37 | ||
38 | @Override | 38 | @Override |
39 | - public TopoVertex src() { | 39 | + public TopologyVertex src() { |
40 | return src; | 40 | return src; |
41 | } | 41 | } |
42 | 42 | ||
43 | @Override | 43 | @Override |
44 | - public TopoVertex dst() { | 44 | + public TopologyVertex dst() { |
45 | return dst; | 45 | return dst; |
46 | } | 46 | } |
47 | 47 | ||
... | @@ -52,8 +52,8 @@ class DefaultTopoEdge implements TopoEdge { | ... | @@ -52,8 +52,8 @@ class DefaultTopoEdge implements TopoEdge { |
52 | 52 | ||
53 | @Override | 53 | @Override |
54 | public boolean equals(Object obj) { | 54 | public boolean equals(Object obj) { |
55 | - if (obj instanceof DefaultTopoEdge) { | 55 | + if (obj instanceof DefaultTopologyEdge) { |
56 | - final DefaultTopoEdge other = (DefaultTopoEdge) obj; | 56 | + final DefaultTopologyEdge other = (DefaultTopologyEdge) obj; |
57 | return Objects.equals(this.link, other.link); | 57 | return Objects.equals(this.link, other.link); |
58 | } | 58 | } |
59 | return false; | 59 | return false; | ... | ... |
core/trivial/src/main/java/org/onlab/onos/net/trivial/topology/impl/DefaultTopologyGraph.java
0 → 100644
1 | +package org.onlab.onos.net.trivial.topology.impl; | ||
2 | + | ||
3 | +import org.onlab.graph.AdjacencyListsGraph; | ||
4 | +import org.onlab.onos.net.topology.TopologyEdge; | ||
5 | +import org.onlab.onos.net.topology.TopologyGraph; | ||
6 | +import org.onlab.onos.net.topology.TopologyVertex; | ||
7 | + | ||
8 | +import java.util.Set; | ||
9 | + | ||
10 | +/** | ||
11 | + * Default implementation of an immutable topology graph based on a generic | ||
12 | + * implementation of adjacency lists graph. | ||
13 | + */ | ||
14 | +public class DefaultTopologyGraph | ||
15 | + extends AdjacencyListsGraph<TopologyVertex, TopologyEdge> | ||
16 | + implements TopologyGraph { | ||
17 | + | ||
18 | + /** | ||
19 | + * Creates a topology graph comprising of the specified vertexes and edges. | ||
20 | + * | ||
21 | + * @param vertexes set of graph vertexes | ||
22 | + * @param edges set of graph edges | ||
23 | + */ | ||
24 | + public DefaultTopologyGraph(Set<TopologyVertex> vertexes, Set<TopologyEdge> edges) { | ||
25 | + super(vertexes, edges); | ||
26 | + } | ||
27 | + | ||
28 | +} |
1 | -package org.onlab.onos.net.trivial.topology.provider.impl; | 1 | +package org.onlab.onos.net.trivial.topology.impl; |
2 | 2 | ||
3 | import org.apache.felix.scr.annotations.Activate; | 3 | import org.apache.felix.scr.annotations.Activate; |
4 | import org.apache.felix.scr.annotations.Component; | 4 | import org.apache.felix.scr.annotations.Component; |
... | @@ -16,7 +16,7 @@ import org.onlab.onos.net.link.LinkListener; | ... | @@ -16,7 +16,7 @@ import org.onlab.onos.net.link.LinkListener; |
16 | import org.onlab.onos.net.link.LinkService; | 16 | import org.onlab.onos.net.link.LinkService; |
17 | import org.onlab.onos.net.provider.AbstractProvider; | 17 | import org.onlab.onos.net.provider.AbstractProvider; |
18 | import org.onlab.onos.net.provider.ProviderId; | 18 | import org.onlab.onos.net.provider.ProviderId; |
19 | -import org.onlab.onos.net.topology.TopologyDescription; | 19 | +import org.onlab.onos.net.topology.GraphDescription; |
20 | import org.onlab.onos.net.topology.TopologyProvider; | 20 | import org.onlab.onos.net.topology.TopologyProvider; |
21 | import org.onlab.onos.net.topology.TopologyProviderRegistry; | 21 | import org.onlab.onos.net.topology.TopologyProviderRegistry; |
22 | import org.onlab.onos.net.topology.TopologyProviderService; | 22 | import org.onlab.onos.net.topology.TopologyProviderService; |
... | @@ -32,10 +32,12 @@ import static org.onlab.util.Tools.namedThreads; | ... | @@ -32,10 +32,12 @@ import static org.onlab.util.Tools.namedThreads; |
32 | import static org.slf4j.LoggerFactory.getLogger; | 32 | import static org.slf4j.LoggerFactory.getLogger; |
33 | 33 | ||
34 | /** | 34 | /** |
35 | - * Simple implementation of a network topology provider/computor. | 35 | + * Default implementation of a network topology provider that feeds off |
36 | + * device and link subsystem events to trigger assembly and computation of | ||
37 | + * new topology snapshots. | ||
36 | */ | 38 | */ |
37 | @Component(immediate = true) | 39 | @Component(immediate = true) |
38 | -public class SimpleTopologyProvider extends AbstractProvider | 40 | +public class DefaultTopologyProvider extends AbstractProvider |
39 | implements TopologyProvider { | 41 | implements TopologyProvider { |
40 | 42 | ||
41 | // TODO: make these configurable | 43 | // TODO: make these configurable |
... | @@ -70,13 +72,13 @@ public class SimpleTopologyProvider extends AbstractProvider | ... | @@ -70,13 +72,13 @@ public class SimpleTopologyProvider extends AbstractProvider |
70 | /** | 72 | /** |
71 | * Creates a provider with the supplier identifier. | 73 | * Creates a provider with the supplier identifier. |
72 | */ | 74 | */ |
73 | - public SimpleTopologyProvider() { | 75 | + public DefaultTopologyProvider() { |
74 | super(new ProviderId("org.onlab.onos.provider.topology")); | 76 | super(new ProviderId("org.onlab.onos.provider.topology")); |
75 | } | 77 | } |
76 | 78 | ||
77 | @Activate | 79 | @Activate |
78 | public synchronized void activate() { | 80 | public synchronized void activate() { |
79 | - executor = newFixedThreadPool(MAX_THREADS, namedThreads("topo-compute-%d")); | 81 | + executor = newFixedThreadPool(MAX_THREADS, namedThreads("topo-build-%d")); |
80 | accumulator = new TopologyChangeAccumulator(); | 82 | accumulator = new TopologyChangeAccumulator(); |
81 | 83 | ||
82 | providerService = providerRegistry.register(this); | 84 | providerService = providerRegistry.register(this); |
... | @@ -90,6 +92,8 @@ public class SimpleTopologyProvider extends AbstractProvider | ... | @@ -90,6 +92,8 @@ public class SimpleTopologyProvider extends AbstractProvider |
90 | 92 | ||
91 | @Deactivate | 93 | @Deactivate |
92 | public synchronized void deactivate() { | 94 | public synchronized void deactivate() { |
95 | + isStarted = false; | ||
96 | + | ||
93 | deviceService.removeListener(deviceListener); | 97 | deviceService.removeListener(deviceListener); |
94 | linkService.removeListener(linkListener); | 98 | linkService.removeListener(linkListener); |
95 | providerRegistry.unregister(this); | 99 | providerRegistry.unregister(this); |
... | @@ -98,7 +102,6 @@ public class SimpleTopologyProvider extends AbstractProvider | ... | @@ -98,7 +102,6 @@ public class SimpleTopologyProvider extends AbstractProvider |
98 | executor.shutdownNow(); | 102 | executor.shutdownNow(); |
99 | executor = null; | 103 | executor = null; |
100 | 104 | ||
101 | - isStarted = false; | ||
102 | log.info("Stopped"); | 105 | log.info("Stopped"); |
103 | } | 106 | } |
104 | 107 | ||
... | @@ -108,18 +111,20 @@ public class SimpleTopologyProvider extends AbstractProvider | ... | @@ -108,18 +111,20 @@ public class SimpleTopologyProvider extends AbstractProvider |
108 | * | 111 | * |
109 | * @param reasons events which triggered the topology change | 112 | * @param reasons events which triggered the topology change |
110 | */ | 113 | */ |
111 | - private void triggerTopologyBuild(List<Event> reasons) { | 114 | + private synchronized void triggerTopologyBuild(List<Event> reasons) { |
112 | - executor.execute(new TopologyBuilderTask(reasons)); | 115 | + if (executor != null) { |
116 | + executor.execute(new TopologyBuilderTask(reasons)); | ||
117 | + } | ||
113 | } | 118 | } |
114 | 119 | ||
115 | // Builds the topology using the latest device and link information | 120 | // Builds the topology using the latest device and link information |
116 | // and citing the specified events as reasons for the change. | 121 | // and citing the specified events as reasons for the change. |
117 | private void buildTopology(List<Event> reasons) { | 122 | private void buildTopology(List<Event> reasons) { |
118 | if (isStarted) { | 123 | if (isStarted) { |
119 | - TopologyDescription desc = | 124 | + GraphDescription desc = |
120 | - new DefaultTopologyDescription(System.nanoTime(), | 125 | + new DefaultGraphDescription(System.nanoTime(), |
121 | - deviceService.getDevices(), | 126 | + deviceService.getDevices(), |
122 | - linkService.getLinks()); | 127 | + linkService.getLinks()); |
123 | providerService.topologyChanged(desc, reasons); | 128 | providerService.topologyChanged(desc, reasons); |
124 | } | 129 | } |
125 | } | 130 | } | ... | ... |
1 | -package org.onlab.onos.net.trivial.topology.provider.impl; | 1 | +package org.onlab.onos.net.trivial.topology.impl; |
2 | 2 | ||
3 | import org.onlab.onos.net.DeviceId; | 3 | import org.onlab.onos.net.DeviceId; |
4 | -import org.onlab.onos.net.topology.TopoVertex; | 4 | +import org.onlab.onos.net.topology.TopologyVertex; |
5 | 5 | ||
6 | import java.util.Objects; | 6 | import java.util.Objects; |
7 | 7 | ||
8 | /** | 8 | /** |
9 | * Implementation of the topology vertex backed by a device id. | 9 | * Implementation of the topology vertex backed by a device id. |
10 | */ | 10 | */ |
11 | -class DefaultTopoVertex implements TopoVertex { | 11 | +class DefaultTopologyVertex implements TopologyVertex { |
12 | 12 | ||
13 | private final DeviceId deviceId; | 13 | private final DeviceId deviceId; |
14 | 14 | ||
... | @@ -17,7 +17,7 @@ class DefaultTopoVertex implements TopoVertex { | ... | @@ -17,7 +17,7 @@ class DefaultTopoVertex implements TopoVertex { |
17 | * | 17 | * |
18 | * @param deviceId backing infrastructure device identifier | 18 | * @param deviceId backing infrastructure device identifier |
19 | */ | 19 | */ |
20 | - DefaultTopoVertex(DeviceId deviceId) { | 20 | + DefaultTopologyVertex(DeviceId deviceId) { |
21 | this.deviceId = deviceId; | 21 | this.deviceId = deviceId; |
22 | } | 22 | } |
23 | 23 | ||
... | @@ -33,8 +33,8 @@ class DefaultTopoVertex implements TopoVertex { | ... | @@ -33,8 +33,8 @@ class DefaultTopoVertex implements TopoVertex { |
33 | 33 | ||
34 | @Override | 34 | @Override |
35 | public boolean equals(Object obj) { | 35 | public boolean equals(Object obj) { |
36 | - if (obj instanceof DefaultTopoVertex) { | 36 | + if (obj instanceof DefaultTopologyVertex) { |
37 | - final DefaultTopoVertex other = (DefaultTopoVertex) obj; | 37 | + final DefaultTopologyVertex other = (DefaultTopologyVertex) obj; |
38 | return Objects.equals(this.deviceId, other.deviceId); | 38 | return Objects.equals(this.deviceId, other.deviceId); |
39 | } | 39 | } |
40 | return false; | 40 | return false; | ... | ... |
1 | +package org.onlab.onos.net.trivial.topology.impl; | ||
2 | + | ||
3 | +import org.onlab.onos.net.DeviceId; | ||
4 | + | ||
5 | +import java.util.Objects; | ||
6 | + | ||
7 | +/** | ||
8 | + * Key for filing pre-computed paths between source and destination devices. | ||
9 | + */ | ||
10 | +class PathKey { | ||
11 | + private final DeviceId src; | ||
12 | + private final DeviceId dst; | ||
13 | + | ||
14 | + /** | ||
15 | + * Creates a path key from the given source/dest pair. | ||
16 | + * @param src source device | ||
17 | + * @param dst destination device | ||
18 | + */ | ||
19 | + PathKey(DeviceId src, DeviceId dst) { | ||
20 | + this.src = src; | ||
21 | + this.dst = dst; | ||
22 | + } | ||
23 | + | ||
24 | + @Override | ||
25 | + public int hashCode() { | ||
26 | + return Objects.hash(src, dst); | ||
27 | + } | ||
28 | + | ||
29 | + @Override | ||
30 | + public boolean equals(Object obj) { | ||
31 | + if (obj instanceof PathKey) { | ||
32 | + final PathKey other = (PathKey) obj; | ||
33 | + return Objects.equals(this.src, other.src) && Objects.equals(this.dst, other.dst); | ||
34 | + } | ||
35 | + return false; | ||
36 | + } | ||
37 | +} |
... | @@ -6,22 +6,22 @@ import org.apache.felix.scr.annotations.Deactivate; | ... | @@ -6,22 +6,22 @@ import org.apache.felix.scr.annotations.Deactivate; |
6 | import org.apache.felix.scr.annotations.Reference; | 6 | import org.apache.felix.scr.annotations.Reference; |
7 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 7 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
8 | import org.apache.felix.scr.annotations.Service; | 8 | import org.apache.felix.scr.annotations.Service; |
9 | -import org.onlab.graph.Graph; | ||
10 | import org.onlab.onos.event.AbstractListenerRegistry; | 9 | import org.onlab.onos.event.AbstractListenerRegistry; |
11 | import org.onlab.onos.event.Event; | 10 | import org.onlab.onos.event.Event; |
12 | import org.onlab.onos.event.EventDeliveryService; | 11 | import org.onlab.onos.event.EventDeliveryService; |
13 | import org.onlab.onos.net.ConnectPoint; | 12 | import org.onlab.onos.net.ConnectPoint; |
14 | import org.onlab.onos.net.DeviceId; | 13 | import org.onlab.onos.net.DeviceId; |
14 | +import org.onlab.onos.net.Link; | ||
15 | import org.onlab.onos.net.Path; | 15 | import org.onlab.onos.net.Path; |
16 | import org.onlab.onos.net.provider.AbstractProviderRegistry; | 16 | import org.onlab.onos.net.provider.AbstractProviderRegistry; |
17 | import org.onlab.onos.net.provider.AbstractProviderService; | 17 | import org.onlab.onos.net.provider.AbstractProviderService; |
18 | +import org.onlab.onos.net.topology.ClusterId; | ||
19 | +import org.onlab.onos.net.topology.GraphDescription; | ||
18 | import org.onlab.onos.net.topology.LinkWeight; | 20 | import org.onlab.onos.net.topology.LinkWeight; |
19 | -import org.onlab.onos.net.topology.TopoEdge; | ||
20 | -import org.onlab.onos.net.topology.TopoVertex; | ||
21 | import org.onlab.onos.net.topology.Topology; | 21 | import org.onlab.onos.net.topology.Topology; |
22 | import org.onlab.onos.net.topology.TopologyCluster; | 22 | import org.onlab.onos.net.topology.TopologyCluster; |
23 | -import org.onlab.onos.net.topology.TopologyDescription; | ||
24 | import org.onlab.onos.net.topology.TopologyEvent; | 23 | import org.onlab.onos.net.topology.TopologyEvent; |
24 | +import org.onlab.onos.net.topology.TopologyGraph; | ||
25 | import org.onlab.onos.net.topology.TopologyListener; | 25 | import org.onlab.onos.net.topology.TopologyListener; |
26 | import org.onlab.onos.net.topology.TopologyProvider; | 26 | import org.onlab.onos.net.topology.TopologyProvider; |
27 | import org.onlab.onos.net.topology.TopologyProviderRegistry; | 27 | import org.onlab.onos.net.topology.TopologyProviderRegistry; |
... | @@ -46,6 +46,8 @@ public class SimpleTopologyManager | ... | @@ -46,6 +46,8 @@ public class SimpleTopologyManager |
46 | 46 | ||
47 | public static final String TOPOLOGY_NULL = "Topology cannot be null"; | 47 | public static final String TOPOLOGY_NULL = "Topology cannot be null"; |
48 | private static final String DEVICE_ID_NULL = "Device ID cannot be null"; | 48 | private static final String DEVICE_ID_NULL = "Device ID cannot be null"; |
49 | + private static final String CLUSTER_ID_NULL = "Cluster ID cannot be null"; | ||
50 | + private static final String CLUSTER_NULL = "Topology cluster cannot be null"; | ||
49 | public static final String CONNECTION_POINT_NULL = "Connection point cannot be null"; | 51 | public static final String CONNECTION_POINT_NULL = "Connection point cannot be null"; |
50 | 52 | ||
51 | private final Logger log = getLogger(getClass()); | 53 | private final Logger log = getLogger(getClass()); |
... | @@ -79,19 +81,49 @@ public class SimpleTopologyManager | ... | @@ -79,19 +81,49 @@ public class SimpleTopologyManager |
79 | @Override | 81 | @Override |
80 | public boolean isLatest(Topology topology) { | 82 | public boolean isLatest(Topology topology) { |
81 | checkNotNull(topology, TOPOLOGY_NULL); | 83 | checkNotNull(topology, TOPOLOGY_NULL); |
82 | - return store.isLatest(topology); | 84 | + return store.isLatest(defaultTopology(topology)); |
85 | + } | ||
86 | + | ||
87 | + // Validates the specified topology and returns it as a default | ||
88 | + private DefaultTopology defaultTopology(Topology topology) { | ||
89 | + if (topology instanceof DefaultTopology) { | ||
90 | + return (DefaultTopology) topology; | ||
91 | + } | ||
92 | + throw new IllegalArgumentException("Topology class " + topology.getClass() + | ||
93 | + " not supported"); | ||
83 | } | 94 | } |
84 | 95 | ||
85 | @Override | 96 | @Override |
86 | public Set<TopologyCluster> getClusters(Topology topology) { | 97 | public Set<TopologyCluster> getClusters(Topology topology) { |
87 | checkNotNull(topology, TOPOLOGY_NULL); | 98 | checkNotNull(topology, TOPOLOGY_NULL); |
88 | - return store.getClusters(topology); | 99 | + return store.getClusters(defaultTopology(topology)); |
100 | + } | ||
101 | + | ||
102 | + @Override | ||
103 | + public TopologyCluster getCluster(Topology topology, ClusterId clusterId) { | ||
104 | + checkNotNull(topology, TOPOLOGY_NULL); | ||
105 | + checkNotNull(topology, CLUSTER_ID_NULL); | ||
106 | + return store.getCluster(defaultTopology(topology), clusterId); | ||
107 | + } | ||
108 | + | ||
109 | + @Override | ||
110 | + public Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster) { | ||
111 | + checkNotNull(topology, TOPOLOGY_NULL); | ||
112 | + checkNotNull(topology, CLUSTER_NULL); | ||
113 | + return store.getClusterDevices(defaultTopology(topology), cluster); | ||
114 | + } | ||
115 | + | ||
116 | + @Override | ||
117 | + public Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster) { | ||
118 | + checkNotNull(topology, TOPOLOGY_NULL); | ||
119 | + checkNotNull(topology, CLUSTER_NULL); | ||
120 | + return store.getClusterLinks(defaultTopology(topology), cluster); | ||
89 | } | 121 | } |
90 | 122 | ||
91 | @Override | 123 | @Override |
92 | - public Graph<TopoVertex, TopoEdge> getGraph(Topology topology) { | 124 | + public TopologyGraph getGraph(Topology topology) { |
93 | checkNotNull(topology, TOPOLOGY_NULL); | 125 | checkNotNull(topology, TOPOLOGY_NULL); |
94 | - return store.getGraph(topology); | 126 | + return store.getGraph(defaultTopology(topology)); |
95 | } | 127 | } |
96 | 128 | ||
97 | @Override | 129 | @Override |
... | @@ -99,7 +131,7 @@ public class SimpleTopologyManager | ... | @@ -99,7 +131,7 @@ public class SimpleTopologyManager |
99 | checkNotNull(topology, TOPOLOGY_NULL); | 131 | checkNotNull(topology, TOPOLOGY_NULL); |
100 | checkNotNull(src, DEVICE_ID_NULL); | 132 | checkNotNull(src, DEVICE_ID_NULL); |
101 | checkNotNull(dst, DEVICE_ID_NULL); | 133 | checkNotNull(dst, DEVICE_ID_NULL); |
102 | - return store.getPaths(topology, src, dst); | 134 | + return store.getPaths(defaultTopology(topology), src, dst); |
103 | } | 135 | } |
104 | 136 | ||
105 | @Override | 137 | @Override |
... | @@ -108,21 +140,21 @@ public class SimpleTopologyManager | ... | @@ -108,21 +140,21 @@ public class SimpleTopologyManager |
108 | checkNotNull(src, DEVICE_ID_NULL); | 140 | checkNotNull(src, DEVICE_ID_NULL); |
109 | checkNotNull(dst, DEVICE_ID_NULL); | 141 | checkNotNull(dst, DEVICE_ID_NULL); |
110 | checkNotNull(weight, "Link weight cannot be null"); | 142 | checkNotNull(weight, "Link weight cannot be null"); |
111 | - return store.getPaths(topology, src, dst, weight); | 143 | + return store.getPaths(defaultTopology(topology), src, dst, weight); |
112 | } | 144 | } |
113 | 145 | ||
114 | @Override | 146 | @Override |
115 | public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) { | 147 | public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) { |
116 | checkNotNull(topology, TOPOLOGY_NULL); | 148 | checkNotNull(topology, TOPOLOGY_NULL); |
117 | checkNotNull(connectPoint, CONNECTION_POINT_NULL); | 149 | checkNotNull(connectPoint, CONNECTION_POINT_NULL); |
118 | - return store.isInfrastructure(topology, connectPoint); | 150 | + return store.isInfrastructure(defaultTopology(topology), connectPoint); |
119 | } | 151 | } |
120 | 152 | ||
121 | @Override | 153 | @Override |
122 | public boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint) { | 154 | public boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint) { |
123 | checkNotNull(topology, TOPOLOGY_NULL); | 155 | checkNotNull(topology, TOPOLOGY_NULL); |
124 | checkNotNull(connectPoint, CONNECTION_POINT_NULL); | 156 | checkNotNull(connectPoint, CONNECTION_POINT_NULL); |
125 | - return store.isInBroadcastTree(topology, connectPoint); | 157 | + return store.isInBroadcastTree(defaultTopology(topology), connectPoint); |
126 | } | 158 | } |
127 | 159 | ||
128 | @Override | 160 | @Override |
... | @@ -150,15 +182,14 @@ public class SimpleTopologyManager | ... | @@ -150,15 +182,14 @@ public class SimpleTopologyManager |
150 | } | 182 | } |
151 | 183 | ||
152 | @Override | 184 | @Override |
153 | - public void topologyChanged(TopologyDescription topoDescription, | 185 | + public void topologyChanged(GraphDescription topoDescription, |
154 | List<Event> reasons) { | 186 | List<Event> reasons) { |
155 | checkNotNull(topoDescription, "Topology description cannot be null"); | 187 | checkNotNull(topoDescription, "Topology description cannot be null"); |
156 | 188 | ||
157 | - log.info("Topology changed due to: {}", // to be removed soon | 189 | + TopologyEvent event = store.updateTopology(provider().id(), |
158 | - reasons == null ? "initial compute" : reasons); | 190 | + topoDescription, reasons); |
159 | - TopologyEvent event = store.updateTopology(topoDescription, reasons); | ||
160 | if (event != null) { | 191 | if (event != null) { |
161 | - log.info("Topology changed due to: {}", | 192 | + log.info("Topology {} changed due to: {}", event.subject(), |
162 | reasons == null ? "initial compute" : reasons); | 193 | reasons == null ? "initial compute" : reasons); |
163 | eventDispatcher.post(event); | 194 | eventDispatcher.post(event); |
164 | } | 195 | } | ... | ... |
1 | package org.onlab.onos.net.trivial.topology.impl; | 1 | package org.onlab.onos.net.trivial.topology.impl; |
2 | 2 | ||
3 | -import org.onlab.graph.Graph; | ||
4 | import org.onlab.onos.event.Event; | 3 | import org.onlab.onos.event.Event; |
5 | import org.onlab.onos.net.ConnectPoint; | 4 | import org.onlab.onos.net.ConnectPoint; |
6 | import org.onlab.onos.net.DeviceId; | 5 | import org.onlab.onos.net.DeviceId; |
6 | +import org.onlab.onos.net.Link; | ||
7 | import org.onlab.onos.net.Path; | 7 | import org.onlab.onos.net.Path; |
8 | +import org.onlab.onos.net.provider.ProviderId; | ||
9 | +import org.onlab.onos.net.topology.ClusterId; | ||
10 | +import org.onlab.onos.net.topology.GraphDescription; | ||
8 | import org.onlab.onos.net.topology.LinkWeight; | 11 | import org.onlab.onos.net.topology.LinkWeight; |
9 | -import org.onlab.onos.net.topology.TopoEdge; | ||
10 | -import org.onlab.onos.net.topology.TopoVertex; | ||
11 | import org.onlab.onos.net.topology.Topology; | 12 | import org.onlab.onos.net.topology.Topology; |
12 | import org.onlab.onos.net.topology.TopologyCluster; | 13 | import org.onlab.onos.net.topology.TopologyCluster; |
13 | -import org.onlab.onos.net.topology.TopologyDescription; | ||
14 | import org.onlab.onos.net.topology.TopologyEvent; | 14 | import org.onlab.onos.net.topology.TopologyEvent; |
15 | +import org.onlab.onos.net.topology.TopologyGraph; | ||
15 | 16 | ||
16 | import java.util.List; | 17 | import java.util.List; |
17 | import java.util.Set; | 18 | import java.util.Set; |
... | @@ -45,23 +46,56 @@ class SimpleTopologyStore { | ... | @@ -45,23 +46,56 @@ class SimpleTopologyStore { |
45 | } | 46 | } |
46 | 47 | ||
47 | /** | 48 | /** |
49 | + * Returns the immutable graph view of the current topology. | ||
50 | + * | ||
51 | + * @param topology topology descriptor | ||
52 | + * @return graph view | ||
53 | + */ | ||
54 | + TopologyGraph getGraph(DefaultTopology topology) { | ||
55 | + return topology.getGraph(); | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
48 | * Returns the set of topology SCC clusters. | 59 | * Returns the set of topology SCC clusters. |
49 | * | 60 | * |
50 | * @param topology topology descriptor | 61 | * @param topology topology descriptor |
51 | * @return set of clusters | 62 | * @return set of clusters |
52 | */ | 63 | */ |
53 | - Set<TopologyCluster> getClusters(Topology topology) { | 64 | + Set<TopologyCluster> getClusters(DefaultTopology topology) { |
54 | - return null; | 65 | + return topology.getClusters(); |
55 | } | 66 | } |
56 | 67 | ||
57 | /** | 68 | /** |
58 | - * Returns the immutable graph view of the current topology. | 69 | + * Returns the cluster of the specified topology. |
59 | * | 70 | * |
60 | - * @param topology topology descriptor | 71 | + * @param topology topology descriptor |
61 | - * @return graph view | 72 | + * @param clusterId cluster identity |
73 | + * @return topology cluster | ||
62 | */ | 74 | */ |
63 | - Graph<TopoVertex, TopoEdge> getGraph(Topology topology) { | 75 | + TopologyCluster getCluster(DefaultTopology topology, ClusterId clusterId) { |
64 | - return null; | 76 | + return topology.getCluster(clusterId); |
77 | + } | ||
78 | + | ||
79 | + /** | ||
80 | + * Returns the cluster of the specified topology. | ||
81 | + * | ||
82 | + * @param topology topology descriptor | ||
83 | + * @param cluster topology cluster | ||
84 | + * @return set of cluster links | ||
85 | + */ | ||
86 | + Set<DeviceId> getClusterDevices(DefaultTopology topology, TopologyCluster cluster) { | ||
87 | + return topology.getClusterDevices(cluster); | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
91 | + * Returns the cluster of the specified topology. | ||
92 | + * | ||
93 | + * @param topology topology descriptor | ||
94 | + * @param cluster topology cluster | ||
95 | + * @return set of cluster links | ||
96 | + */ | ||
97 | + Set<Link> getClusterLinks(DefaultTopology topology, TopologyCluster cluster) { | ||
98 | + return topology.getClusterLinks(cluster); | ||
65 | } | 99 | } |
66 | 100 | ||
67 | /** | 101 | /** |
... | @@ -72,8 +106,8 @@ class SimpleTopologyStore { | ... | @@ -72,8 +106,8 @@ class SimpleTopologyStore { |
72 | * @param dst destination device | 106 | * @param dst destination device |
73 | * @return set of shortest paths | 107 | * @return set of shortest paths |
74 | */ | 108 | */ |
75 | - Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) { | 109 | + Set<Path> getPaths(DefaultTopology topology, DeviceId src, DeviceId dst) { |
76 | - return null; | 110 | + return topology.getPaths(src, dst); |
77 | } | 111 | } |
78 | 112 | ||
79 | /** | 113 | /** |
... | @@ -85,9 +119,9 @@ class SimpleTopologyStore { | ... | @@ -85,9 +119,9 @@ class SimpleTopologyStore { |
85 | * @param weight link weight function | 119 | * @param weight link weight function |
86 | * @return set of shortest paths | 120 | * @return set of shortest paths |
87 | */ | 121 | */ |
88 | - Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, | 122 | + Set<Path> getPaths(DefaultTopology topology, DeviceId src, DeviceId dst, |
89 | LinkWeight weight) { | 123 | LinkWeight weight) { |
90 | - return null; | 124 | + return topology.getPaths(src, dst, weight); |
91 | } | 125 | } |
92 | 126 | ||
93 | /** | 127 | /** |
... | @@ -97,8 +131,8 @@ class SimpleTopologyStore { | ... | @@ -97,8 +131,8 @@ class SimpleTopologyStore { |
97 | * @param connectPoint connection point | 131 | * @param connectPoint connection point |
98 | * @return true if infrastructure; false otherwise | 132 | * @return true if infrastructure; false otherwise |
99 | */ | 133 | */ |
100 | - boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) { | 134 | + boolean isInfrastructure(DefaultTopology topology, ConnectPoint connectPoint) { |
101 | - return false; | 135 | + return topology.isInfrastructure(connectPoint); |
102 | } | 136 | } |
103 | 137 | ||
104 | /** | 138 | /** |
... | @@ -108,20 +142,36 @@ class SimpleTopologyStore { | ... | @@ -108,20 +142,36 @@ class SimpleTopologyStore { |
108 | * @param connectPoint connection point | 142 | * @param connectPoint connection point |
109 | * @return true if in broadcast tree; false otherwise | 143 | * @return true if in broadcast tree; false otherwise |
110 | */ | 144 | */ |
111 | - boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint) { | 145 | + boolean isInBroadcastTree(DefaultTopology topology, ConnectPoint connectPoint) { |
112 | - return false; | 146 | + return topology.isInBroadcastTree(connectPoint); |
113 | } | 147 | } |
114 | 148 | ||
115 | /** | 149 | /** |
116 | * Generates a new topology snapshot from the specified description. | 150 | * Generates a new topology snapshot from the specified description. |
117 | * | 151 | * |
118 | - * @param topoDescription topology description | 152 | + * @param providerId provider identification |
119 | - * @param reasons list of events that triggered the update | 153 | + * @param graphDescription topology graph description |
154 | + * @param reasons list of events that triggered the update | ||
120 | * @return topology update event or null if the description is old | 155 | * @return topology update event or null if the description is old |
121 | */ | 156 | */ |
122 | - TopologyEvent updateTopology(TopologyDescription topoDescription, | 157 | + TopologyEvent updateTopology(ProviderId providerId, |
158 | + GraphDescription graphDescription, | ||
123 | List<Event> reasons) { | 159 | List<Event> reasons) { |
124 | - return null; | 160 | + // First off, make sure that what we're given is indeed newer than |
161 | + // what we already have. | ||
162 | + if (current != null && graphDescription.timestamp() < current.time()) { | ||
163 | + return null; | ||
164 | + } | ||
165 | + | ||
166 | + // Have the default topology construct self from the description data. | ||
167 | + DefaultTopology newTopology = | ||
168 | + new DefaultTopology(providerId, graphDescription); | ||
169 | + | ||
170 | + // Promote the new topology to current and return a ready-to-send event. | ||
171 | + synchronized (this) { | ||
172 | + current = newTopology; | ||
173 | + return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, current); | ||
174 | + } | ||
125 | } | 175 | } |
126 | 176 | ||
127 | } | 177 | } | ... | ... |
1 | -package org.onlab.onos.net.trivial.topology.provider.impl; | ||
2 | - | ||
3 | -import com.google.common.collect.ImmutableSet; | ||
4 | -import com.google.common.collect.ImmutableSetMultimap; | ||
5 | -import com.google.common.collect.Maps; | ||
6 | -import com.google.common.collect.Sets; | ||
7 | -import org.onlab.graph.AdjacencyListsGraph; | ||
8 | -import org.onlab.graph.DijkstraGraphSearch; | ||
9 | -import org.onlab.graph.Graph; | ||
10 | -import org.onlab.graph.GraphPathSearch; | ||
11 | -import org.onlab.graph.TarjanGraphSearch; | ||
12 | -import org.onlab.onos.net.ConnectPoint; | ||
13 | -import org.onlab.onos.net.Device; | ||
14 | -import org.onlab.onos.net.DeviceId; | ||
15 | -import org.onlab.onos.net.Link; | ||
16 | -import org.onlab.onos.net.topology.ClusterId; | ||
17 | -import org.onlab.onos.net.topology.DefaultTopologyCluster; | ||
18 | -import org.onlab.onos.net.topology.LinkWeight; | ||
19 | -import org.onlab.onos.net.topology.TopoEdge; | ||
20 | -import org.onlab.onos.net.topology.TopoVertex; | ||
21 | -import org.onlab.onos.net.topology.TopologyCluster; | ||
22 | -import org.onlab.onos.net.topology.TopologyDescription; | ||
23 | - | ||
24 | -import java.util.List; | ||
25 | -import java.util.Map; | ||
26 | -import java.util.Set; | ||
27 | - | ||
28 | -import static com.google.common.collect.ImmutableSetMultimap.Builder; | ||
29 | -import static org.onlab.graph.GraphPathSearch.Result; | ||
30 | -import static org.onlab.graph.TarjanGraphSearch.SCCResult; | ||
31 | -import static org.onlab.onos.net.Link.Type.INDIRECT; | ||
32 | - | ||
33 | -/** | ||
34 | - * Default implementation of an immutable topology data carrier. | ||
35 | - */ | ||
36 | -class DefaultTopologyDescription implements TopologyDescription { | ||
37 | - | ||
38 | - private static final GraphPathSearch<TopoVertex, TopoEdge> DIJKSTRA = | ||
39 | - new DijkstraGraphSearch<>(); | ||
40 | - private static final TarjanGraphSearch<TopoVertex, TopoEdge> TARJAN = | ||
41 | - new TarjanGraphSearch<>(); | ||
42 | - | ||
43 | - private final long nanos; | ||
44 | - private final Map<DeviceId, TopoVertex> vertexesById = Maps.newHashMap(); | ||
45 | - private final Graph<TopoVertex, TopoEdge> graph; | ||
46 | - private final Map<DeviceId, Result<TopoVertex, TopoEdge>> results; | ||
47 | - private final Map<ClusterId, TopologyCluster> clusters; | ||
48 | - | ||
49 | - // Secondary look-up indexes | ||
50 | - private ImmutableSetMultimap<ClusterId, DeviceId> devicesByCluster; | ||
51 | - private ImmutableSetMultimap<ClusterId, Link> linksByCluster; | ||
52 | - private Map<DeviceId, TopologyCluster> clustersByDevice = Maps.newHashMap(); | ||
53 | - | ||
54 | - /** | ||
55 | - * Creates a topology description to carry topology vitals to the core. | ||
56 | - * | ||
57 | - * @param nanos time in nanos of when the topology description was created | ||
58 | - * @param devices collection of infrastructure devices | ||
59 | - * @param links collection of infrastructure links | ||
60 | - */ | ||
61 | - DefaultTopologyDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) { | ||
62 | - this.nanos = nanos; | ||
63 | - this.graph = buildGraph(devices, links); | ||
64 | - this.results = computeDefaultPaths(); | ||
65 | - this.clusters = computeClusters(); | ||
66 | - } | ||
67 | - | ||
68 | - @Override | ||
69 | - public long timestamp() { | ||
70 | - return nanos; | ||
71 | - } | ||
72 | - | ||
73 | - @Override | ||
74 | - public Graph<TopoVertex, TopoEdge> graph() { | ||
75 | - return graph; | ||
76 | - } | ||
77 | - | ||
78 | - @Override | ||
79 | - public Result<TopoVertex, TopoEdge> pathResults(DeviceId srcDeviceId) { | ||
80 | - return results.get(srcDeviceId); | ||
81 | - } | ||
82 | - | ||
83 | - @Override | ||
84 | - public Set<TopologyCluster> clusters() { | ||
85 | - return ImmutableSet.copyOf(clusters.values()); | ||
86 | - } | ||
87 | - | ||
88 | - @Override | ||
89 | - public Set<DeviceId> clusterDevices(TopologyCluster cluster) { | ||
90 | - return devicesByCluster.get(cluster.id()); | ||
91 | - } | ||
92 | - | ||
93 | - @Override | ||
94 | - public Set<Link> clusterLinks(TopologyCluster cluster) { | ||
95 | - return linksByCluster.get(cluster.id()); | ||
96 | - } | ||
97 | - | ||
98 | - @Override | ||
99 | - public TopologyCluster clusterFor(DeviceId deviceId) { | ||
100 | - return clustersByDevice.get(deviceId); | ||
101 | - } | ||
102 | - | ||
103 | - | ||
104 | - // Link weight for measuring link cost as hop count with indirect links | ||
105 | - // being as expensive as traversing the entire graph to assume the worst. | ||
106 | - private static class HopCountLinkWeight implements LinkWeight { | ||
107 | - private final int indirectLinkCost; | ||
108 | - | ||
109 | - HopCountLinkWeight(int indirectLinkCost) { | ||
110 | - this.indirectLinkCost = indirectLinkCost; | ||
111 | - } | ||
112 | - | ||
113 | - @Override | ||
114 | - public double weight(TopoEdge edge) { | ||
115 | - // To force preference to use direct paths first, make indirect | ||
116 | - // links as expensive as the linear vertex traversal. | ||
117 | - return edge.link().type() == INDIRECT ? indirectLinkCost : 1; | ||
118 | - } | ||
119 | - } | ||
120 | - | ||
121 | - // Link weight for preventing traversal over indirect links. | ||
122 | - private static class NoIndirectLinksWeight implements LinkWeight { | ||
123 | - @Override | ||
124 | - public double weight(TopoEdge edge) { | ||
125 | - return edge.link().type() == INDIRECT ? -1 : 1; | ||
126 | - } | ||
127 | - } | ||
128 | - | ||
129 | - // Constructs the topology graph using the supplied devices and links. | ||
130 | - private Graph<TopoVertex, TopoEdge> buildGraph(Iterable<Device> devices, | ||
131 | - Iterable<Link> links) { | ||
132 | - return new AdjacencyListsGraph<>(buildVertexes(devices), | ||
133 | - buildEdges(links)); | ||
134 | - } | ||
135 | - | ||
136 | - // Builds a set of topology vertexes from the specified list of devices | ||
137 | - private Set<TopoVertex> buildVertexes(Iterable<Device> devices) { | ||
138 | - Set<TopoVertex> vertexes = Sets.newHashSet(); | ||
139 | - for (Device device : devices) { | ||
140 | - TopoVertex vertex = new DefaultTopoVertex(device.id()); | ||
141 | - vertexes.add(vertex); | ||
142 | - vertexesById.put(vertex.deviceId(), vertex); | ||
143 | - } | ||
144 | - return vertexes; | ||
145 | - } | ||
146 | - | ||
147 | - // Builds a set of topology vertexes from the specified list of links | ||
148 | - private Set<TopoEdge> buildEdges(Iterable<Link> links) { | ||
149 | - Set<TopoEdge> edges = Sets.newHashSet(); | ||
150 | - for (Link link : links) { | ||
151 | - edges.add(new DefaultTopoEdge(vertexOf(link.src()), | ||
152 | - vertexOf(link.dst()), link)); | ||
153 | - } | ||
154 | - return edges; | ||
155 | - } | ||
156 | - | ||
157 | - // Computes the default shortest paths for all source/dest pairs using | ||
158 | - // the multi-path Dijkstra and hop-count as path cost. | ||
159 | - private Map<DeviceId, Result<TopoVertex, TopoEdge>> computeDefaultPaths() { | ||
160 | - LinkWeight weight = new HopCountLinkWeight(graph.getVertexes().size()); | ||
161 | - Map<DeviceId, Result<TopoVertex, TopoEdge>> results = Maps.newHashMap(); | ||
162 | - | ||
163 | - // Search graph paths for each source to all destinations. | ||
164 | - for (TopoVertex src : vertexesById.values()) { | ||
165 | - results.put(src.deviceId(), DIJKSTRA.search(graph, src, null, weight)); | ||
166 | - } | ||
167 | - return results; | ||
168 | - } | ||
169 | - | ||
170 | - // Computes topology SCC clusters using Tarjan algorithm. | ||
171 | - private Map<ClusterId, TopologyCluster> computeClusters() { | ||
172 | - Map<ClusterId, TopologyCluster> clusters = Maps.newHashMap(); | ||
173 | - SCCResult<TopoVertex, TopoEdge> result = TARJAN.search(graph, new NoIndirectLinksWeight()); | ||
174 | - | ||
175 | - // Extract both vertexes and edges from the results; the lists form | ||
176 | - // pairs along the same index. | ||
177 | - List<Set<TopoVertex>> clusterVertexes = result.clusterVertexes(); | ||
178 | - List<Set<TopoEdge>> clusterEdges = result.clusterEdges(); | ||
179 | - | ||
180 | - Builder<ClusterId, DeviceId> devicesBuilder = ImmutableSetMultimap.builder(); | ||
181 | - Builder<ClusterId, Link> linksBuilder = ImmutableSetMultimap.builder(); | ||
182 | - | ||
183 | - // Scan over the lists and create a cluster from the results. | ||
184 | - for (int i = 0, n = result.clusterCount(); i < n; i++) { | ||
185 | - Set<TopoVertex> vertexSet = clusterVertexes.get(i); | ||
186 | - Set<TopoEdge> edgeSet = clusterEdges.get(i); | ||
187 | - | ||
188 | - DefaultTopologyCluster cluster = | ||
189 | - new DefaultTopologyCluster(ClusterId.clusterId(i), | ||
190 | - vertexSet.size(), edgeSet.size(), | ||
191 | - findRoot(vertexSet).deviceId()); | ||
192 | - findClusterDevices(vertexSet, cluster, devicesBuilder); | ||
193 | - findClusterLinks(edgeSet, cluster, linksBuilder); | ||
194 | - } | ||
195 | - return clusters; | ||
196 | - } | ||
197 | - | ||
198 | - // Scans through the set of cluster vertexes and puts their devices in a | ||
199 | - // multi-map associated with the cluster. It also binds the devices to | ||
200 | - // the cluster. | ||
201 | - private void findClusterDevices(Set<TopoVertex> vertexSet, | ||
202 | - DefaultTopologyCluster cluster, | ||
203 | - Builder<ClusterId, DeviceId> builder) { | ||
204 | - for (TopoVertex vertex : vertexSet) { | ||
205 | - DeviceId deviceId = vertex.deviceId(); | ||
206 | - builder.put(cluster.id(), deviceId); | ||
207 | - clustersByDevice.put(deviceId, cluster); | ||
208 | - } | ||
209 | - } | ||
210 | - | ||
211 | - // Scans through the set of cluster edges and puts their links in a | ||
212 | - // multi-map associated with the cluster. | ||
213 | - private void findClusterLinks(Set<TopoEdge> edgeSet, | ||
214 | - DefaultTopologyCluster cluster, | ||
215 | - Builder<ClusterId, Link> builder) { | ||
216 | - for (TopoEdge edge : edgeSet) { | ||
217 | - builder.put(cluster.id(), edge.link()); | ||
218 | - } | ||
219 | - } | ||
220 | - | ||
221 | - // Finds the vertex whose device id is the lexicographical minimum in the | ||
222 | - // specified set. | ||
223 | - private TopoVertex findRoot(Set<TopoVertex> vertexSet) { | ||
224 | - TopoVertex minVertex = null; | ||
225 | - for (TopoVertex vertex : vertexSet) { | ||
226 | - if (minVertex == null || | ||
227 | - minVertex.deviceId().toString() | ||
228 | - .compareTo(minVertex.deviceId().toString()) < 0) { | ||
229 | - minVertex = vertex; | ||
230 | - } | ||
231 | - } | ||
232 | - return minVertex; | ||
233 | - } | ||
234 | - | ||
235 | - // Fetches a vertex corresponding to the given connection point device. | ||
236 | - private TopoVertex vertexOf(ConnectPoint connectPoint) { | ||
237 | - DeviceId id = connectPoint.deviceId(); | ||
238 | - TopoVertex vertex = vertexesById.get(id); | ||
239 | - if (vertex == null) { | ||
240 | - // If vertex does not exist, create one and register it. | ||
241 | - vertex = new DefaultTopoVertex(id); | ||
242 | - vertexesById.put(id, vertex); | ||
243 | - } | ||
244 | - return vertex; | ||
245 | - } | ||
246 | - | ||
247 | -} |
... | @@ -7,6 +7,7 @@ import org.projectfloodlight.openflow.protocol.OFPacketIn; | ... | @@ -7,6 +7,7 @@ import org.projectfloodlight.openflow.protocol.OFPacketIn; |
7 | import org.projectfloodlight.openflow.protocol.OFPacketOut; | 7 | import org.projectfloodlight.openflow.protocol.OFPacketOut; |
8 | import org.projectfloodlight.openflow.protocol.action.OFAction; | 8 | import org.projectfloodlight.openflow.protocol.action.OFAction; |
9 | import org.projectfloodlight.openflow.protocol.action.OFActionOutput; | 9 | import org.projectfloodlight.openflow.protocol.action.OFActionOutput; |
10 | +import org.projectfloodlight.openflow.protocol.match.MatchField; | ||
10 | import org.projectfloodlight.openflow.types.OFBufferId; | 11 | import org.projectfloodlight.openflow.types.OFBufferId; |
11 | import org.projectfloodlight.openflow.types.OFPort; | 12 | import org.projectfloodlight.openflow.types.OFPort; |
12 | 13 | ||
... | @@ -83,12 +84,18 @@ public final class DefaultPacketContext implements PacketContext { | ... | @@ -83,12 +84,18 @@ public final class DefaultPacketContext implements PacketContext { |
83 | 84 | ||
84 | @Override | 85 | @Override |
85 | public Integer inPort() { | 86 | public Integer inPort() { |
86 | - return pktin.getInPort().getPortNumber(); | 87 | + try { |
88 | + return pktin.getInPort().getPortNumber(); | ||
89 | + } catch (UnsupportedOperationException e) { | ||
90 | + return pktin.getMatch().get(MatchField.IN_PORT).getPortNumber(); | ||
91 | + } | ||
87 | } | 92 | } |
88 | 93 | ||
89 | @Override | 94 | @Override |
90 | public byte[] unparsed() { | 95 | public byte[] unparsed() { |
96 | + | ||
91 | return pktin.getData().clone(); | 97 | return pktin.getData().clone(); |
98 | + | ||
92 | } | 99 | } |
93 | 100 | ||
94 | private OFActionOutput buildOutput(Integer port) { | 101 | private OFActionOutput buildOutput(Integer port) { | ... | ... |
... | @@ -250,9 +250,12 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -250,9 +250,12 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
250 | } | 250 | } |
251 | OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); | 251 | OpenFlowSwitch sw = activeMasterSwitches.remove(dpid); |
252 | if (sw == null) { | 252 | if (sw == null) { |
253 | - log.error("Transition to equal called on sw {}, but switch " | 253 | + sw = getSwitch(dpid); |
254 | - + "was not found in controller-cache", dpid); | 254 | + if (sw == null) { |
255 | - return; | 255 | + log.error("Transition to equal called on sw {}, but switch " |
256 | + + "was not found in controller-cache", dpid); | ||
257 | + return; | ||
258 | + } | ||
256 | } | 259 | } |
257 | log.info("Transitioned switch {} to EQUAL", dpid); | 260 | log.info("Transitioned switch {} to EQUAL", dpid); |
258 | activeEqualSwitches.put(dpid, sw); | 261 | activeEqualSwitches.put(dpid, sw); | ... | ... |
... | @@ -2,10 +2,15 @@ package org.onlab.onos.of.drivers.impl; | ... | @@ -2,10 +2,15 @@ package org.onlab.onos.of.drivers.impl; |
2 | 2 | ||
3 | 3 | ||
4 | 4 | ||
5 | +import java.util.Collections; | ||
6 | +import java.util.List; | ||
7 | + | ||
5 | import org.onlab.onos.of.controller.Dpid; | 8 | import org.onlab.onos.of.controller.Dpid; |
9 | +import org.onlab.onos.of.controller.driver.AbstractOpenFlowSwitch; | ||
6 | import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver; | 10 | import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriver; |
7 | import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriverFactory; | 11 | import org.onlab.onos.of.controller.driver.OpenFlowSwitchDriverFactory; |
8 | import org.projectfloodlight.openflow.protocol.OFDescStatsReply; | 12 | import org.projectfloodlight.openflow.protocol.OFDescStatsReply; |
13 | +import org.projectfloodlight.openflow.protocol.OFMessage; | ||
9 | import org.projectfloodlight.openflow.protocol.OFVersion; | 14 | import org.projectfloodlight.openflow.protocol.OFVersion; |
10 | import org.slf4j.Logger; | 15 | import org.slf4j.Logger; |
11 | import org.slf4j.LoggerFactory; | 16 | import org.slf4j.LoggerFactory; |
... | @@ -51,8 +56,36 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { | ... | @@ -51,8 +56,36 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { |
51 | } | 56 | } |
52 | 57 | ||
53 | log.warn("DriverManager could not identify switch desc: {}. " | 58 | log.warn("DriverManager could not identify switch desc: {}. " |
54 | - + "Assigning OFSwitchImplBase", desc); | 59 | + + "Assigning AbstractOpenFlowSwich", desc); |
55 | - return null; | 60 | + return new AbstractOpenFlowSwitch(dpid) { |
61 | + | ||
62 | + @Override | ||
63 | + public void write(List<OFMessage> msgs) { | ||
64 | + channel.write(msgs); | ||
65 | + } | ||
66 | + | ||
67 | + @Override | ||
68 | + public void write(OFMessage msg) { | ||
69 | + channel.write(Collections.singletonList(msg)); | ||
70 | + | ||
71 | + } | ||
72 | + | ||
73 | + @Override | ||
74 | + public Boolean supportNxRole() { | ||
75 | + return false; | ||
76 | + } | ||
77 | + | ||
78 | + @Override | ||
79 | + public void startDriverHandshake() {} | ||
80 | + | ||
81 | + @Override | ||
82 | + public void processDriverHandshakeMessage(OFMessage m) {} | ||
83 | + | ||
84 | + @Override | ||
85 | + public boolean isDriverHandshakeComplete() { | ||
86 | + return true; | ||
87 | + } | ||
88 | + }; | ||
56 | } | 89 | } |
57 | 90 | ||
58 | /** | 91 | /** | ... | ... |
... | @@ -320,6 +320,7 @@ | ... | @@ -320,6 +320,7 @@ |
320 | <artifactId>maven-javadoc-plugin</artifactId> | 320 | <artifactId>maven-javadoc-plugin</artifactId> |
321 | <version>2.9.1</version> | 321 | <version>2.9.1</version> |
322 | <configuration> | 322 | <configuration> |
323 | + <show>package</show> | ||
323 | <docfilessubdirs>true</docfilessubdirs> | 324 | <docfilessubdirs>true</docfilessubdirs> |
324 | <doctitle>ONOS Java API</doctitle> | 325 | <doctitle>ONOS Java API</doctitle> |
325 | <groups> | 326 | <groups> | ... | ... |
providers/of/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
... | @@ -60,7 +60,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -60,7 +60,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
60 | * Creates an OpenFlow device provider. | 60 | * Creates an OpenFlow device provider. |
61 | */ | 61 | */ |
62 | public OpenFlowDeviceProvider() { | 62 | public OpenFlowDeviceProvider() { |
63 | - super(new ProviderId("org.onlab.onos.provider.of.device")); | 63 | + super(new ProviderId("org.onlab.onos.provider.openflow")); |
64 | } | 64 | } |
65 | 65 | ||
66 | @Activate | 66 | @Activate | ... | ... |
... | @@ -37,7 +37,7 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid | ... | @@ -37,7 +37,7 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid |
37 | * Creates an OpenFlow host provider. | 37 | * Creates an OpenFlow host provider. |
38 | */ | 38 | */ |
39 | public OpenFlowHostProvider() { | 39 | public OpenFlowHostProvider() { |
40 | - super(new ProviderId("org.onlab.onos.provider.of.host")); | 40 | + super(new ProviderId("org.onlab.onos.provider.openflow")); |
41 | } | 41 | } |
42 | 42 | ||
43 | @Activate | 43 | @Activate | ... | ... |
... | @@ -55,7 +55,7 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid | ... | @@ -55,7 +55,7 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid |
55 | * Creates an OpenFlow link provider. | 55 | * Creates an OpenFlow link provider. |
56 | */ | 56 | */ |
57 | public OpenFlowLinkProvider() { | 57 | public OpenFlowLinkProvider() { |
58 | - super(new ProviderId("org.onlab.onos.provider.of.link")); | 58 | + super(new ProviderId("org.onlab.onos.provider.openflow")); |
59 | } | 59 | } |
60 | 60 | ||
61 | @Activate | 61 | @Activate | ... | ... |
-
Please register or login to post a comment