tom

Started to work on topology abstraction.

Added more unit tests.
Changed mastership application to be synchronous.
...@@ -37,7 +37,7 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink { ...@@ -37,7 +37,7 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink {
37 } 37 }
38 38
39 @Override 39 @Override
40 - public ConnectPoint connectPoint() { 40 + public HostLocation hostLocation() {
41 return hostLocation; 41 return hostLocation;
42 } 42 }
43 } 43 }
......
...@@ -27,7 +27,7 @@ public final class DeviceId extends ElementId { ...@@ -27,7 +27,7 @@ public final class DeviceId extends ElementId {
27 * @param string device URI string 27 * @param string device URI string
28 */ 28 */
29 public static DeviceId deviceId(String string) { 29 public static DeviceId deviceId(String string) {
30 - return new DeviceId(URI.create(string)); 30 + return deviceId(URI.create(string));
31 } 31 }
32 32
33 } 33 }
......
...@@ -17,8 +17,8 @@ public interface EdgeLink extends Link { ...@@ -17,8 +17,8 @@ public interface EdgeLink extends Link {
17 * Returns the connection point where the host attaches to the 17 * Returns the connection point where the host attaches to the
18 * network infrastructure. 18 * network infrastructure.
19 * 19 *
20 - * @return host connection point 20 + * @return host location point
21 */ 21 */
22 - ConnectPoint connectPoint(); 22 + HostLocation hostLocation();
23 23
24 } 24 }
......
...@@ -27,7 +27,7 @@ public final class HostId extends ElementId { ...@@ -27,7 +27,7 @@ public final class HostId extends ElementId {
27 * @param string device URI string 27 * @param string device URI string
28 */ 28 */
29 public static HostId hostId(String string) { 29 public static HostId hostId(String string) {
30 - return new HostId(URI.create(string)); 30 + return hostId(URI.create(string));
31 } 31 }
32 32
33 } 33 }
......
1 +package org.onlab.onos.net.topology;
2 +
3 +import org.onlab.graph.EdgeWeight;
4 +
5 +/**
6 + * Entity capable of determining cost or weight of a specified topology
7 + * graph edge.
8 + */
9 +public interface LinkWeight extends EdgeWeight<TopoVertex, TopoEdge> {
10 +}
1 +package org.onlab.onos.net.topology;
2 +
3 +import org.onlab.graph.Edge;
4 +import org.onlab.onos.net.Link;
5 +
6 +/**
7 + * Represents an edge in the topology graph.
8 + */
9 +public interface TopoEdge extends Edge<TopoVertex> {
10 +
11 + /**
12 + * Returns the associated infrastructure link.
13 + *
14 + * @return backing infrastructure link
15 + */
16 + Link link();
17 +
18 +}
1 +package org.onlab.onos.net.topology;
2 +
3 +import org.onlab.graph.Vertex;
4 +import org.onlab.onos.net.DeviceId;
5 +
6 +/**
7 + * Represents a vertex in the topology graph.
8 + */
9 +public interface TopoVertex extends Vertex {
10 +
11 + /**
12 + * Returns the associated infrastructure device identification.
13 + *
14 + * @return device identifier
15 + */
16 + DeviceId deviceId();
17 +
18 +}
1 +package org.onlab.onos.net.topology;
2 +
3 +/**
4 + * Representation of an SCC (strongly-connected component) in a network topology.
5 + */
6 +public interface TopologyCluster {
7 +
8 + // TODO: add stuff in here: id, deviceCount, linkCount
9 +
10 +}
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;
5 +import org.onlab.onos.net.DeviceId;
6 +import org.onlab.onos.net.Path;
3 import org.onlab.onos.net.Topology; 7 import org.onlab.onos.net.Topology;
4 8
9 +import java.util.Set;
10 +
5 /** 11 /**
6 * Service for providing network topology information. 12 * Service for providing network topology information.
7 */ 13 */
...@@ -14,13 +20,64 @@ public interface TopologyService { ...@@ -14,13 +20,64 @@ public interface TopologyService {
14 */ 20 */
15 Topology currentTopology(); 21 Topology currentTopology();
16 22
17 - // TODO: Figure out hot to best export graph traversal methods via Graph/Vertex/Edge 23 + /**
18 - // TODO: figure out how we want this to be presented, via Topology or via TopologyService 24 + * Returns the set of clusters in the specified topology.
19 - // Set<TopologyCluster> getClusters(Topology topology); 25 + *
20 - // Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst); 26 + * @param topology topology descriptor
21 - // Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeight weight); 27 + * @return set of topology clusters
22 - // boolean isInfrastructure(Topology topology, ConnectPoint connectPoint); 28 + */
23 - // boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint); 29 + Set<TopologyCluster> getClusters(Topology topology);
30 +
31 + /**
32 + * Returns the graph view of the specified topology.
33 + *
34 + * @param topology topology descriptor
35 + * @return topology graph view
36 + */
37 + Graph<TopoVertex, TopoEdge> getGraph(Topology topology);
38 +
39 + /**
40 + * Returns the set of all shortest paths, in terms of hop-count, between
41 + * the specified source and destination devices.
42 + *
43 + * @param topology topology descriptor
44 + * @param src source device
45 + * @param dst destination device
46 + * @return set of all shortest paths between the two devices
47 + */
48 + Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst);
49 +
50 + /**
51 + * Returns the set of all shortest paths, computed using the supplied
52 + * edge-weight entity, between the specified source and destination devices.
53 + *
54 + * @param topology topology descriptor
55 + * @param src source device
56 + * @param dst destination device
57 + * @return set of all shortest paths between the two devices
58 + */
59 + Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
60 + LinkWeight weight);
61 +
62 + /**
63 + * Indicates whether the specified connection point is part of the network
64 + * infrastructure or part of network edge.
65 + *
66 + * @param topology topology descriptor
67 + * @param connectPoint connection point
68 + * @return true of connection point is in infrastructure; false if edge
69 + */
70 + boolean isInfrastructure(Topology topology, ConnectPoint connectPoint);
71 +
72 +
73 + /**
74 + * Indicates whether the specified connection point allows broadcast.
75 + *
76 + * @param topology topology descriptor
77 + * @param connectPoint connection point
78 + * @return true if broadcast is permissible
79 + */
80 + boolean isInBroadcastTree(Topology topology, ConnectPoint connectPoint);
24 81
25 /** 82 /**
26 * Adds the specified topology listener. 83 * Adds the specified topology listener.
......
1 +package org.onlab.onos.net;
2 +
3 +import com.google.common.testing.EqualsTester;
4 +import org.junit.Test;
5 +import org.onlab.onos.net.provider.ProviderId;
6 +
7 +import static org.junit.Assert.assertEquals;
8 +import static org.onlab.onos.net.DefaultLinkTest.cp;
9 +import static org.onlab.onos.net.DeviceId.deviceId;
10 +import static org.onlab.onos.net.HostId.hostId;
11 +import static org.onlab.onos.net.PortNumber.portNumber;
12 +
13 +/**
14 + * Test of the default edge link model entity.
15 + */
16 +public class DefaultEdgeLinkTest {
17 +
18 + private static final ProviderId PID = new ProviderId("foo");
19 + private static final DeviceId DID1 = deviceId("of:foo");
20 + private static final HostId HID1 = hostId("nic:foobar");
21 + private static final HostId HID2 = hostId("nic:barfoo");
22 + private static final PortNumber P0 = portNumber(0);
23 + private static final PortNumber P1 = portNumber(1);
24 +
25 + @Test
26 + public void testEquality() {
27 + EdgeLink l1 = new DefaultEdgeLink(PID, cp(HID1, P0),
28 + new HostLocation(DID1, P1, 123L), true);
29 + EdgeLink l2 = new DefaultEdgeLink(PID, cp(HID1, P0),
30 + new HostLocation(DID1, P1, 123L), true);
31 +
32 + EdgeLink l3 = new DefaultEdgeLink(PID, cp(HID2, P0),
33 + new HostLocation(DID1, P1, 123L), false);
34 + EdgeLink l4 = new DefaultEdgeLink(PID, cp(HID2, P0),
35 + new HostLocation(DID1, P1, 123L), false);
36 +
37 + EdgeLink l5 = new DefaultEdgeLink(PID, cp(HID1, P0),
38 + new HostLocation(DID1, P1, 123L), false);
39 +
40 + new EqualsTester().addEqualityGroup(l1, l2)
41 + .addEqualityGroup(l3, l4)
42 + .addEqualityGroup(l5)
43 + .testEquals();
44 + }
45 +
46 + @Test
47 + public void basics() {
48 + HostLocation hostLocation = new HostLocation(DID1, P1, 123L);
49 + EdgeLink link = new DefaultEdgeLink(PID, cp(HID1, P0), hostLocation, false);
50 + assertEquals("incorrect src", cp(HID1, P0), link.src());
51 + assertEquals("incorrect dst", hostLocation, link.dst());
52 + assertEquals("incorrect type", Link.Type.EDGE, link.type());
53 + assertEquals("incorrect hostId", HID1, link.hostId());
54 + assertEquals("incorrect connect point", hostLocation, link.hostLocation());
55 + assertEquals("incorrect time", 123L, link.hostLocation().time());
56 + }
57 +
58 +}
...@@ -21,7 +21,7 @@ public class DefaultLinkTest { ...@@ -21,7 +21,7 @@ public class DefaultLinkTest {
21 private static final PortNumber P1 = portNumber(1); 21 private static final PortNumber P1 = portNumber(1);
22 private static final PortNumber P2 = portNumber(2); 22 private static final PortNumber P2 = portNumber(2);
23 23
24 - public static ConnectPoint cp(DeviceId id, PortNumber pn) { 24 + public static ConnectPoint cp(ElementId id, PortNumber pn) {
25 return new ConnectPoint(id, pn); 25 return new ConnectPoint(id, pn);
26 } 26 }
27 27
......
1 +package org.onlab.onos.net;
2 +
3 +import com.google.common.testing.EqualsTester;
4 +import org.junit.Test;
5 +import org.onlab.onos.net.provider.ProviderId;
6 +
7 +import static org.junit.Assert.assertEquals;
8 +import static org.onlab.onos.net.Device.Type.SWITCH;
9 +import static org.onlab.onos.net.DeviceId.deviceId;
10 +import static org.onlab.onos.net.PortNumber.portNumber;
11 +
12 +/**
13 + * Test of the default port model entity.
14 + */
15 +public class DefaultPortTest {
16 +
17 + private static final ProviderId PID = new ProviderId("foo");
18 + private static final DeviceId DID1 = deviceId("of:foo");
19 + private static final DeviceId DID2 = deviceId("of:bar");
20 + private static final PortNumber P1 = portNumber(1);
21 + private static final PortNumber P2 = portNumber(2);
22 +
23 + @Test
24 + public void testEquality() {
25 + Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n");
26 + Port p1 = new DefaultPort(device, portNumber(1), true);
27 + Port p2 = new DefaultPort(device, portNumber(1), true);
28 + Port p3 = new DefaultPort(device, portNumber(2), true);
29 + Port p4 = new DefaultPort(device, portNumber(2), true);
30 + Port p5 = new DefaultPort(device, portNumber(1), false);
31 +
32 + new EqualsTester().addEqualityGroup(p1, p2)
33 + .addEqualityGroup(p3, p4)
34 + .addEqualityGroup(p5)
35 + .testEquals();
36 + }
37 +
38 + @Test
39 + public void basics() {
40 + Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n");
41 + Port port = new DefaultPort(device, portNumber(1), true);
42 + assertEquals("incorrect element", device, port.element());
43 + assertEquals("incorrect number", portNumber(1), port.number());
44 + assertEquals("incorrect state", true, port.isEnabled());
45 + }
46 +
47 +}
1 +package org.onlab.onos.net;
2 +
3 +import com.google.common.testing.EqualsTester;
4 +import org.junit.Test;
5 +
6 +import static org.onlab.onos.net.HostId.hostId;
7 +
8 +/**
9 + * Test of the host identifier.
10 + */
11 +public class HostIdTest extends ElementIdTest {
12 +
13 + @Test
14 + public void basics() {
15 + new EqualsTester()
16 + .addEqualityGroup(hostId("nic:foo"),
17 + hostId("nic:foo"))
18 + .addEqualityGroup(hostId("nic:bar"))
19 + .testEquals();
20 + }
21 +
22 +}
...@@ -27,11 +27,8 @@ import org.onlab.onos.net.provider.AbstractProviderService; ...@@ -27,11 +27,8 @@ import org.onlab.onos.net.provider.AbstractProviderService;
27 import org.slf4j.Logger; 27 import org.slf4j.Logger;
28 28
29 import java.util.List; 29 import java.util.List;
30 -import java.util.concurrent.ExecutorService;
31 30
32 import static com.google.common.base.Preconditions.checkNotNull; 31 import static com.google.common.base.Preconditions.checkNotNull;
33 -import static java.util.concurrent.Executors.newSingleThreadExecutor;
34 -import static org.onlab.util.Tools.namedThreads;
35 import static org.slf4j.LoggerFactory.getLogger; 32 import static org.slf4j.LoggerFactory.getLogger;
36 33
37 /** 34 /**
...@@ -56,9 +53,6 @@ public class SimpleDeviceManager ...@@ -56,9 +53,6 @@ public class SimpleDeviceManager
56 53
57 private final SimpleDeviceStore store = new SimpleDeviceStore(); 54 private final SimpleDeviceStore store = new SimpleDeviceStore();
58 55
59 - private final ExecutorService executor =
60 - newSingleThreadExecutor(namedThreads("onos-device-%d"));
61 -
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected EventDeliveryService eventDispatcher; 57 protected EventDeliveryService eventDispatcher;
64 58
...@@ -139,7 +133,7 @@ public class SimpleDeviceManager ...@@ -139,7 +133,7 @@ public class SimpleDeviceManager
139 Device device = event.subject(); 133 Device device = event.subject();
140 DeviceProvider provider = getProvider(device.providerId()); 134 DeviceProvider provider = getProvider(device.providerId());
141 if (provider != null) { 135 if (provider != null) {
142 - triggerRoleSelection(device, provider); 136 + provider.roleChanged(device, newRole);
143 } 137 }
144 post(event); 138 post(event);
145 } 139 }
...@@ -168,11 +162,12 @@ public class SimpleDeviceManager ...@@ -168,11 +162,12 @@ public class SimpleDeviceManager
168 log.info("Device {} connected", deviceId); 162 log.info("Device {} connected", deviceId);
169 DeviceEvent event = store.createOrUpdateDevice(provider().id(), 163 DeviceEvent event = store.createOrUpdateDevice(provider().id(),
170 deviceId, deviceDescription); 164 deviceId, deviceDescription);
171 - post(event);
172 165
173 // If there was a change of any kind, trigger role selection process. 166 // If there was a change of any kind, trigger role selection process.
174 if (event != null) { 167 if (event != null) {
175 - triggerRoleSelection(event.subject(), provider()); 168 + Device device = event.subject();
169 + provider().roleChanged(device, store.getRole(device.id()));
170 + post(event);
176 } 171 }
177 } 172 }
178 173
...@@ -210,22 +205,6 @@ public class SimpleDeviceManager ...@@ -210,22 +205,6 @@ public class SimpleDeviceManager
210 } 205 }
211 } 206 }
212 207
213 - /**
214 - * Triggers asynchronous role selection.
215 - *
216 - * @param device device
217 - * @param provider device provider
218 - */
219 - private void triggerRoleSelection(final Device device,
220 - final DeviceProvider provider) {
221 - executor.execute(new Runnable() {
222 - @Override
223 - public void run() {
224 - provider.roleChanged(device, store.getRole(device.id()));
225 - }
226 - });
227 - }
228 -
229 // Posts the specified event to the local event dispatcher. 208 // Posts the specified event to the local event dispatcher.
230 private void post(DeviceEvent event) { 209 private void post(DeviceEvent event) {
231 if (event != null && eventDispatcher != null) { 210 if (event != null && eventDispatcher != null) {
......
...@@ -148,8 +148,6 @@ public class SimpleDeviceManagerTest { ...@@ -148,8 +148,6 @@ public class SimpleDeviceManagerTest {
148 admin.setRole(DID1, MastershipRole.STANDBY); 148 admin.setRole(DID1, MastershipRole.STANDBY);
149 validateEvents(DEVICE_ADDED, DEVICE_MASTERSHIP_CHANGED); 149 validateEvents(DEVICE_ADDED, DEVICE_MASTERSHIP_CHANGED);
150 assertEquals("incorrect role", MastershipRole.STANDBY, service.getRole(DID1)); 150 assertEquals("incorrect role", MastershipRole.STANDBY, service.getRole(DID1));
151 -
152 - Thread.sleep(200); // FIXME: replace this with more reliable and faster testing means!!!
153 assertEquals("incorrect device", DID1, provider.deviceReceived.id()); 151 assertEquals("incorrect device", DID1, provider.deviceReceived.id());
154 assertEquals("incorrect role", MastershipRole.STANDBY, provider.roleReceived); 152 assertEquals("incorrect role", MastershipRole.STANDBY, provider.roleReceived);
155 } 153 }
......