Thomas Vachuska

Added link types of TUNNEL and OPTICAL.

Fixed the optical config json file.
Fixed treatment of links added by ancillary providers.
Added a trap for topology provider errors.
Added CLI to recompute topology.
......@@ -284,7 +284,7 @@ public class OpticalConfigProvider extends AbstractProvider implements DevicePro
DefaultLinkDescription linkDescription =
new DefaultLinkDescription(srcPoint,
snkPoint,
Link.Type.DIRECT,
Link.Type.OPTICAL,
extendedAttributes);
linkProviderService.linkDetected(linkDescription);
......@@ -315,7 +315,7 @@ public class OpticalConfigProvider extends AbstractProvider implements DevicePro
DefaultLinkDescription linkDescription =
new DefaultLinkDescription(srcPoint,
snkPoint,
Link.Type.DIRECT,
Link.Type.OPTICAL,
extendedAttributes);
linkProviderService.linkDetected(linkDescription);
......
{
"opticalSwitches": [
"opticalSwitches": [
{
"allowed": true,
"latitude": 37.6,
......@@ -12,7 +12,7 @@
"type": "Roadm"
},
{
{
"allowed": true,
"latitude": 37.3,
"longitude": 121.9,
......@@ -22,9 +22,9 @@
"numRegen": 0
},
"type": "Roadm"
},
},
{
{
"allowed": true,
"latitude": 33.9,
"longitude": 118.4,
......@@ -34,10 +34,10 @@
"numRegen": 2
},
"type": "Roadm"
}
}
],
"opticalLinks": [
"opticalLinks": [
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
......@@ -51,10 +51,38 @@
"port2": 30
},
"type": "wdmLink"
},
{
"allowed": true,
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:01",
"params": {
"distKms": 1000,
"nodeName1": "ROADM3",
"nodeName2": "ROADM1",
"numWaves": 80,
"port1": 30,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:03",
"params": {
"distKms": 2000,
"nodeName1": "ROADM2",
"nodeName2": "ROADM3",
"numWaves": 80,
"port1": 20,
"port2": 31
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:02",
"params": {
......@@ -66,10 +94,9 @@
"port2": 20
},
"type": "wdmLink"
},
},
{
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:01",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:01",
......@@ -82,8 +109,21 @@
},
"type": "pktOptLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
"nodeDpid2": "00:00:ff:ff:ff:ff:00:01",
"params": {
"nodeName1": "ROADM1",
"nodeName2": "ROUTER1",
"bandWidth": 100000,
"port1": 11,
"port2": 10
},
"type": "pktOptLink"
},
{
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:02",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:02",
......@@ -95,7 +135,20 @@
"port2": 21
},
"type": "pktOptLink"
}
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
"nodeDpid2": "00:00:ff:ff:ff:ff:00:02",
"params": {
"nodeName1": "ROADM2",
"nodeName2": "ROUTER2",
"bandWidth": 100000,
"port1": 21,
"port2": 10
},
"type": "pktOptLink"
}
]
}
......
......@@ -20,8 +20,10 @@ package org.onlab.onos.cli.net;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onlab.onos.cli.AbstractShellCommand;
import org.onlab.onos.net.topology.Topology;
import org.onlab.onos.net.topology.TopologyProvider;
import org.onlab.onos.net.topology.TopologyService;
/**
......@@ -35,6 +37,10 @@ public class TopologyCommand extends AbstractShellCommand {
private static final String FMT =
"time=%s, devices=%d, links=%d, clusters=%d, paths=%d";
@Option(name = "-r", aliases = "--recompute", description = "Trigger topology re-computation",
required = false, multiValued = false)
private boolean recompute = false;
protected TopologyService service;
protected Topology topology;
......@@ -49,7 +55,10 @@ public class TopologyCommand extends AbstractShellCommand {
@Override
protected void execute() {
init();
if (outputJson()) {
if (recompute) {
get(TopologyProvider.class).triggerRecompute();
} else if (outputJson()) {
print("%s", new ObjectMapper().createObjectNode()
.put("time", topology.time())
.put("deviceCount", topology.deviceCount())
......
......@@ -25,7 +25,18 @@ public interface Link extends Annotated, Provided, NetworkResource {
/**
* Signifies that this link is an edge, i.e. host link.
*/
EDGE
EDGE,
/**
* Signifies that this link represents a logical link backed by
* some form of a tunnel.
*/
TUNNEL,
/**
* Signifies that this link is realized by optical connection.
*/
OPTICAL
}
/**
......@@ -49,6 +60,4 @@ public interface Link extends Annotated, Provided, NetworkResource {
*/
Type type();
// LinkInfo info(); // Additional link information / decorations
}
......
......@@ -7,4 +7,9 @@ import org.onlab.onos.net.provider.Provider;
*/
public interface TopologyProvider extends Provider {
/**
* Triggers topology recomputation.
*/
void triggerRecompute();
}
......
......@@ -208,7 +208,7 @@ public class LinkManager
LinkEvent event = store.createOrUpdateLink(provider().id(),
linkDescription);
if (event != null) {
log.debug("Link {} detected", linkDescription);
log.info("Link {} detected", linkDescription);
post(event);
}
}
......
......@@ -5,6 +5,7 @@ import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.event.AbstractEventAccumulator;
import org.onlab.onos.event.Event;
import org.onlab.onos.event.EventAccumulator;
......@@ -39,6 +40,7 @@ import static org.slf4j.LoggerFactory.getLogger;
* new topology snapshots.
*/
@Component(immediate = true)
@Service
public class DefaultTopologyProvider extends AbstractProvider
implements TopologyProvider {
......@@ -89,7 +91,7 @@ public class DefaultTopologyProvider extends AbstractProvider
linkService.addListener(linkListener);
isStarted = true;
triggerTopologyBuild(Collections.<Event>emptyList());
triggerRecompute();
log.info("Started");
}
......@@ -108,6 +110,11 @@ public class DefaultTopologyProvider extends AbstractProvider
log.info("Stopped");
}
@Override
public void triggerRecompute() {
triggerTopologyBuild(Collections.<Event>emptyList());
}
/**
* Triggers assembly of topology data citing the specified events as the
* reason.
......@@ -177,7 +184,11 @@ public class DefaultTopologyProvider extends AbstractProvider
@Override
public void run() {
buildTopology(reasons);
try {
buildTopology(reasons);
} catch (Exception e) {
log.warn("Unable to compute topology due to: {}", e.getMessage());
}
}
}
......
......@@ -195,6 +195,10 @@ public class TopologyManagerTest {
public TestProvider() {
super(PID);
}
@Override
public void triggerRecompute() {
}
}
private static class TestListener implements TopologyListener {
......
......@@ -192,14 +192,6 @@ public class SimpleLinkStore
// Creates and stores the link and returns the appropriate event.
// Guarded by linkDescs value (=locking each Link)
private LinkEvent createLink(LinkKey key, Link newLink) {
if (newLink.providerId().isAncillary()) {
// TODO: revisit ancillary only Link handling
// currently treating ancillary only as down (not visible outside)
return null;
}
links.put(key, newLink);
srcLinks.put(newLink.src().deviceId(), key);
dstLinks.put(newLink.dst().deviceId(), key);
......@@ -209,10 +201,8 @@ public class SimpleLinkStore
// Updates, if necessary the specified link and returns the appropriate event.
// Guarded by linkDescs value (=locking each Link)
private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) {
if (newLink.providerId().isAncillary()) {
// TODO: revisit ancillary only Link handling
// currently treating ancillary only as down (not visible outside)
return null;
}
......
package org.onlab.onos.store.trivial.impl;
import static org.junit.Assert.*;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.Link.Type.*;
import static org.onlab.onos.net.link.LinkEvent.Type.*;
import static org.onlab.onos.store.trivial.impl.SimpleDeviceStoreTest.assertAnnotationsEquals;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Iterables;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
......@@ -23,17 +11,27 @@ import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultAnnotations;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Link.Type;
import org.onlab.onos.net.LinkKey;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.onos.net.Link.Type;
import org.onlab.onos.net.link.DefaultLinkDescription;
import org.onlab.onos.net.link.LinkEvent;
import org.onlab.onos.net.link.LinkStore;
import org.onlab.onos.net.link.LinkStoreDelegate;
import org.onlab.onos.net.provider.ProviderId;
import com.google.common.collect.Iterables;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.Link.Type.*;
import static org.onlab.onos.net.link.LinkEvent.Type.*;
import static org.onlab.onos.store.trivial.impl.SimpleDeviceStoreTest.assertAnnotationsEquals;
/**
* Test of the simple LinkStore implementation.
......@@ -301,7 +299,7 @@ public class SimpleLinkStoreTest {
LinkEvent event = linkStore.createOrUpdateLink(PIDA,
new DefaultLinkDescription(src, dst, INDIRECT, A1));
assertNull("Ancillary only link is ignored", event);
assertNotNull("Ancillary only link is ignored", event);
// add Primary link
LinkEvent event2 = linkStore.createOrUpdateLink(PID,
......@@ -309,7 +307,7 @@ public class SimpleLinkStoreTest {
assertLink(DID1, P1, DID2, P2, INDIRECT, event2.subject());
assertAnnotationsEquals(event2.subject().annotations(), A2, A1);
assertEquals(LINK_ADDED, event2.type());
assertEquals(LINK_UPDATED, event2.type());
// update link type
LinkEvent event3 = linkStore.createOrUpdateLink(PID,
......@@ -375,7 +373,7 @@ public class SimpleLinkStoreTest {
}
@Test
public final void testAncillaryOnlyNotVisible() {
public final void testAncillaryVisible() {
ConnectPoint src = new ConnectPoint(DID1, P1);
ConnectPoint dst = new ConnectPoint(DID2, P2);
......@@ -384,18 +382,8 @@ public class SimpleLinkStoreTest {
new DefaultLinkDescription(src, dst, INDIRECT, A1));
// Ancillary only link should not be visible
assertEquals(0, linkStore.getLinkCount());
assertTrue(Iterables.isEmpty(linkStore.getLinks()));
assertNull(linkStore.getLink(src, dst));
assertEquals(Collections.emptySet(), linkStore.getIngressLinks(dst));
assertEquals(Collections.emptySet(), linkStore.getEgressLinks(src));
assertEquals(Collections.emptySet(), linkStore.getDeviceEgressLinks(DID1));
assertEquals(Collections.emptySet(), linkStore.getDeviceIngressLinks(DID2));
assertEquals(1, linkStore.getLinkCount());
assertNotNull(linkStore.getLink(src, dst));
}
// If Delegates should be called only on remote events,
......