tom

Added simple link manager implementation.

Added link admin stuff; unit tests to come.
Showing 23 changed files with 476 additions and 33 deletions
......@@ -4,7 +4,7 @@ import org.onlab.onos.net.provider.ProviderId;
import java.util.Objects;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Default infrastructure device model implementation.
......
package org.onlab.onos.net;
import org.onlab.onos.net.link.LinkDescription;
import org.onlab.onos.net.provider.ProviderId;
import java.util.Objects;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Default infrastructure link model implementation.
*/
public class DefaultLink implements LinkDescription {
public class DefaultLink extends AbstractModel implements Link {
private ConnectPoint src;
private ConnectPoint dst;
private final ConnectPoint src;
private final ConnectPoint dst;
private final Type type;
/**
* Creates a link description using the supplied information.
*
* @param src link source
* @param dst link destination
* @param providerId provider identity
* @param src link source
* @param dst link destination
* @param type link type
*/
public DefaultLink(ConnectPoint src, ConnectPoint dst) {
public DefaultLink(ProviderId providerId, ConnectPoint src, ConnectPoint dst,
Type type) {
super(providerId);
this.src = src;
this.dst = dst;
this.type = type;
}
@Override
......@@ -35,18 +41,23 @@ public class DefaultLink implements LinkDescription {
return dst;
}
@Override
public Type type() {
return type;
}
@Override
public int hashCode() {
return Objects.hash(src, dst);
return Objects.hash(src, dst, type);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DefaultDevice) {
if (obj instanceof DefaultLink) {
final DefaultLink other = (DefaultLink) obj;
return Objects.equals(this.src, other.src) &&
Objects.equals(this.dst, other.dst);
Objects.equals(this.dst, other.dst) &&
Objects.equals(this.type, other.type);
}
return false;
}
......@@ -56,6 +67,7 @@ public class DefaultLink implements LinkDescription {
return toStringHelper(this)
.add("src", src)
.add("dst", dst)
.add("type", type)
.toString();
}
......
......@@ -2,7 +2,7 @@ package org.onlab.onos.net;
import java.util.Objects;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Default port implementation.
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.net;
import java.net.URI;
import java.util.Objects;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Immutable representation of a network element identity.
......
......@@ -37,6 +37,13 @@ public interface Link extends Provided {
*/
ConnectPoint dst();
/**
* Returns the link type.
*
* @return link type
*/
Type type();
// LinkInfo info(); // Additional link information / decorations
}
......
......@@ -2,7 +2,7 @@ package org.onlab.onos.net.device;
import java.net.URI;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.onos.net.Device.Type;
......
package org.onlab.onos.net.link;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
/**
* Default implementation of immutable link description entity.
*/
public class DefaultLinkDescription implements LinkDescription {
private ConnectPoint src;
private ConnectPoint dst;
private final ConnectPoint src;
private final ConnectPoint dst;
private final Link.Type type;
/**
* Creates a link description using the supplied information.
*
* @param src link source
* @param dst link destination
* @param src link source
* @param dst link destination
* @param type link type
*/
public DefaultLinkDescription(ConnectPoint src, ConnectPoint dst) {
public DefaultLinkDescription(ConnectPoint src, ConnectPoint dst, Link.Type type) {
this.src = src;
this.dst = dst;
this.type = type;
}
@Override
......@@ -31,4 +35,9 @@ public class DefaultLinkDescription implements LinkDescription {
return dst;
}
@Override
public Link.Type type() {
return null;
}
}
......
package org.onlab.onos.net.link;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
/**
* Service for administering the inventory of infrastructure links.
*/
public interface LinkAdminService {
/**
* Removes all infrastructure links leading to and from the
* specified connection point.
*
* @param connectPoint connection point
*/
void removeLinks(ConnectPoint connectPoint);
/**
* Removes all infrastructure links leading to and from the
* specified device.
*
* @param deviceId device identifier
*/
void removeLinks(DeviceId deviceId);
}
package org.onlab.onos.net.link;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
/**
* Describes an infrastructure link.
......@@ -21,5 +22,13 @@ public interface LinkDescription {
*/
ConnectPoint dst();
/**
* Returns the link type.
*
* @return link type
*/
Link.Type type();
// Add further link attributes
}
......
package org.onlab.onos.net.link;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.provider.ProviderService;
/**
......@@ -21,4 +23,20 @@ public interface LinkProviderService extends ProviderService<LinkProvider> {
*/
void linkVanished(LinkDescription linkDescription);
/**
* Signals that infrastructure links associated with the specified
* connect point have vanished.
*
* @param connectPoint connect point
*/
void linksVanished(ConnectPoint connectPoint);
/**
* Signals that infrastructure links associated with the specified
* device have vanished.
*
* @param deviceId device identifier
*/
void linksVanished(DeviceId deviceId);
}
......
package org.onlab.onos.net.link;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
......@@ -11,6 +12,13 @@ import java.util.Set;
public interface LinkService {
/**
* Returns the count of all known infrastructure links.
*
* @return number of infrastructure links
*/
int getLinkCount();
/**
* Returns a collection of all known infrastructure links.
*
* @return all infrastructure links
......@@ -43,6 +51,43 @@ public interface LinkService {
Set<Link> getDeviceInressLinks(DeviceId deviceId);
/**
* Returns set of all infrastructure links leading to and from the
* specified connection point.
*
* @param connectPoint connection point
* @return set of links
*/
Set<Link> getLinks(ConnectPoint connectPoint);
/**
* Returns set of all infrastructure links leading from the specified
* connection point.
*
* @param connectPoint connection point
* @return set of device egress links
*/
Set<Link> getEgressLinks(ConnectPoint connectPoint);
/**
* Returns set of all infrastructure links leading to the specified
* connection point.
*
* @param connectPoint connection point
* @return set of device ingress links
*/
Set<Link> getInressLinks(ConnectPoint connectPoint);
/**
* Returns set of all infrastructure links between the specified source
* and destination connection points.
*
* @param src source connection point
* @param dst destination connection point
* @return set of links
*/
Set<Link> getLinks(ConnectPoint src, ConnectPoint dst);
/**
* Adds the specified link listener.
*
* @param listener link listener
......
......@@ -2,7 +2,7 @@ package org.onlab.onos.net.provider;
import java.util.Objects;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Notion of provider identity.
......
......@@ -152,6 +152,7 @@ public class SimpleDeviceManager
public void deviceConnected(DeviceId deviceId, DeviceDescription deviceDescription) {
checkNotNull(deviceId, DEVICE_ID_NULL);
checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL);
checkValidity();
log.info("Device {} connected", deviceId);
DeviceEvent event = store.createOrUpdateDevice(provider().id(),
deviceId, deviceDescription);
......@@ -161,6 +162,7 @@ public class SimpleDeviceManager
@Override
public void deviceDisconnected(DeviceId deviceId) {
checkNotNull(deviceId, DEVICE_ID_NULL);
checkValidity();
log.info("Device {} disconnected", deviceId);
DeviceEvent event = store.markOffline(deviceId);
post(event);
......@@ -170,6 +172,7 @@ public class SimpleDeviceManager
public void updatePorts(DeviceId deviceId, List<PortDescription> portDescriptions) {
checkNotNull(deviceId, DEVICE_ID_NULL);
checkNotNull(portDescriptions, "Port descriptions list cannot be null");
checkValidity();
log.info("Device {} ports updated", deviceId);
List<DeviceEvent> events = store.updatePorts(deviceId, portDescriptions);
for (DeviceEvent event : events) {
......@@ -181,13 +184,14 @@ public class SimpleDeviceManager
public void portStatusChanged(DeviceId deviceId, PortDescription portDescription) {
checkNotNull(deviceId, DEVICE_ID_NULL);
checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
checkValidity();
log.info("Device {} port status changed", deviceId);
DeviceEvent event = store.updatePortStatus(deviceId, portDescription);
post(event);
}
}
// Posts the specified event to a local event dispatcher
// Posts the specified event to the local event dispatcher.
private void post(DeviceEvent event) {
if (event != null && eventDispatcher != null) {
eventDispatcher.post(event);
......
......@@ -45,7 +45,7 @@ class SimpleDeviceStore {
*
* @return number of devices
*/
public int getDeviceCount() {
int getDeviceCount() {
return devices.size();
}
......
package org.onlab.onos.net.trivial.impl;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -8,16 +9,24 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.event.AbstractListenerRegistry;
import org.onlab.onos.event.EventDeliveryService;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.link.LinkAdminService;
import org.onlab.onos.net.link.LinkDescription;
import org.onlab.onos.net.link.LinkEvent;
import org.onlab.onos.net.link.LinkListener;
import org.onlab.onos.net.link.LinkProvider;
import org.onlab.onos.net.link.LinkProviderRegistry;
import org.onlab.onos.net.link.LinkProviderService;
import org.onlab.onos.net.link.LinkService;
import org.onlab.onos.net.provider.AbstractProviderRegistry;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
......@@ -27,7 +36,11 @@ import static org.slf4j.LoggerFactory.getLogger;
@Service
public class SimpleLinkManager
extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
implements LinkProviderRegistry {
implements LinkService, LinkAdminService, LinkProviderRegistry {
private static final String DEVICE_ID_NULL = "Device ID cannot be null";
private static final String LINK_DESC_NULL = "Link description cannot be null";
private static final String CONNECT_POINT_NULL = "Connection point cannot be null";
private final Logger log = getLogger(getClass());
......@@ -56,6 +69,82 @@ public class SimpleLinkManager
return new InternalLinkProviderService(provider);
}
@Override
public int getLinkCount() {
return store.getLinkCount();
}
@Override
public Iterable<Link> getLinks() {
return store.getLinks();
}
@Override
public Set<Link> getDeviceLinks(DeviceId deviceId) {
checkNotNull(deviceId, DEVICE_ID_NULL);
return Sets.union(store.getDeviceEgressLinks(deviceId),
store.getDeviceIngressLinks(deviceId));
}
@Override
public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
checkNotNull(deviceId, DEVICE_ID_NULL);
return store.getDeviceEgressLinks(deviceId);
}
@Override
public Set<Link> getDeviceInressLinks(DeviceId deviceId) {
checkNotNull(deviceId, DEVICE_ID_NULL);
return store.getDeviceIngressLinks(deviceId);
}
@Override
public Set<Link> getLinks(ConnectPoint connectPoint) {
checkNotNull(connectPoint, CONNECT_POINT_NULL);
return Sets.union(store.getEgressLinks(connectPoint),
store.getIngressLinks(connectPoint));
}
@Override
public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
checkNotNull(connectPoint, CONNECT_POINT_NULL);
return store.getEgressLinks(connectPoint);
}
@Override
public Set<Link> getInressLinks(ConnectPoint connectPoint) {
checkNotNull(connectPoint, CONNECT_POINT_NULL);
return store.getIngressLinks(connectPoint);
}
@Override
public Set<Link> getLinks(ConnectPoint src, ConnectPoint dst) {
checkNotNull(src, CONNECT_POINT_NULL);
checkNotNull(dst, CONNECT_POINT_NULL);
return Sets.intersection(store.getEgressLinks(src),
store.getIngressLinks(dst));
}
@Override
public void removeLinks(ConnectPoint connectPoint) {
removeLinks(getLinks(connectPoint));
}
@Override
public void removeLinks(DeviceId deviceId) {
removeLinks(getDeviceLinks(deviceId));
}
@Override
public void addListener(LinkListener listener) {
listenerRegistry.addListener(listener);
}
@Override
public void removeListener(LinkListener listener) {
listenerRegistry.removeListener(listener);
}
// Personalized link provider service issued to the supplied provider.
private class InternalLinkProviderService extends AbstractProviderService<LinkProvider>
implements LinkProviderService {
......@@ -66,12 +155,54 @@ public class SimpleLinkManager
@Override
public void linkDetected(LinkDescription linkDescription) {
checkNotNull(linkDescription, LINK_DESC_NULL);
checkValidity();
log.info("Link {} detected", linkDescription);
LinkEvent event = store.createOrUpdateLink(provider().id(),
linkDescription);
post(event);
}
@Override
public void linkVanished(LinkDescription linkDescription) {
checkNotNull(linkDescription, LINK_DESC_NULL);
checkValidity();
log.info("Link {} vanished", linkDescription);
LinkEvent event = store.removeLink(linkDescription.src(),
linkDescription.dst());
post(event);
}
@Override
public void linksVanished(ConnectPoint connectPoint) {
checkNotNull(connectPoint, "Connect point cannot be null");
checkValidity();
log.info("Link for connection point {} vanished", connectPoint);
removeLinks(getLinks(connectPoint));
}
@Override
public void linksVanished(DeviceId deviceId) {
checkNotNull(deviceId, DEVICE_ID_NULL);
checkValidity();
log.info("Link for device {} vanished", deviceId);
removeLinks(getDeviceLinks(deviceId));
}
}
// Removes all links in the specified set and emits appropriate events.
private void removeLinks(Set<Link> links) {
for (Link link : links) {
LinkEvent event = store.removeLink(link.src(), link.dst());
post(event);
}
}
// Posts the specified event to the local event dispatcher.
private void post(LinkEvent event) {
if (event != null && eventDispatcher != null) {
eventDispatcher.post(event);
}
}
}
......
package org.onlab.onos.net.trivial.impl;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultLink;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.link.LinkDescription;
import org.onlab.onos.net.link.LinkEvent;
import org.onlab.onos.net.provider.ProviderId;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Manages inventory of infrastructure links using trivial in-memory link
* implementation.
*/
public class SimpleLinkStore {
class SimpleLinkStore {
// Link inventory
private final Map<LinkKey, DefaultLink> links = new ConcurrentHashMap<>();
// Egress and ingress link sets
private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create();
private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create();
private static final Set<Link> EMPTY = ImmutableSet.copyOf(new Link[]{});
/**
* Returns the number of links in the store.
*
* @return number of links
*/
int getLinkCount() {
return links.size();
}
/**
* Returns an iterable collection of all links in the inventory.
*
* @return collection of all links
*/
Iterable<Link> getLinks() {
return Collections.unmodifiableSet(new HashSet<Link>(links.values()));
}
/**
* Returns all links egressing from the specified device.
*
* @param deviceId device identifier
* @return set of device links
*/
Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
return ImmutableSet.copyOf(srcLinks.get(deviceId));
}
/**
* Returns all links ingressing from the specified device.
*
* @param deviceId device identifier
* @return set of device links
*/
Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
return ImmutableSet.copyOf(dstLinks.get(deviceId));
}
/**
* Returns all links egressing from the specified connection point.
*
* @param src source connection point
* @return set of connection point links
*/
Set<Link> getEgressLinks(ConnectPoint src) {
Set<Link> egress = new HashSet<>();
for (Link link : srcLinks.get(src.deviceId())) {
if (link.src().equals(src)) {
egress.add(link);
}
}
return egress;
}
/**
* Returns all links ingressing to the specified connection point.
*
* @param dst destination connection point
* @return set of connection point links
*/
Set<Link> getIngressLinks(ConnectPoint dst) {
Set<Link> ingress = new HashSet<>();
for (Link link : dstLinks.get(dst.deviceId())) {
if (link.src().equals(dst)) {
ingress.add(link);
}
}
return ingress;
}
/**
* Creates a new link, or updates an existing one, based on the given
* information.
*
* @param providerId provider identity
* @param linkDescription link description
* @return create or update link event, or null if no change resulted
*/
public LinkEvent createOrUpdateLink(ProviderId providerId,
LinkDescription linkDescription) {
LinkKey key = new LinkKey(linkDescription.src(), linkDescription.dst());
DefaultLink link = links.get(key);
if (link == null) {
return createLink(providerId, key, linkDescription);
}
return updateLink(link, linkDescription);
}
// Creates and stores the link and returns the appropriate event.
private LinkEvent createLink(ProviderId providerId, LinkKey key,
LinkDescription linkDescription) {
DefaultLink link = new DefaultLink(providerId, key.src, key.dst,
linkDescription.type());
synchronized (this) {
links.put(key, link);
srcLinks.put(link.src().deviceId(), link);
dstLinks.put(link.dst().deviceId(), link);
}
return new LinkEvent(LinkEvent.Type.LINK_ADDED, link);
}
// Updates, if necessary the specified link and returns the appropriate event.
private LinkEvent updateLink(DefaultLink link, LinkDescription linkDescription) {
return null;
}
/**
* Removes the link based on the specified information.
*
* @param src link source
* @param dst link destination
* @return remove link event, or null if no change resulted
*/
LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
synchronized (this) {
Link link = links.remove(new LinkKey(src, dst));
srcLinks.remove(link.src().deviceId(), link);
dstLinks.remove(link.dst().deviceId(), link);
return link == null ? null : new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
}
}
// Auxiliary key to track links.
private class LinkKey {
final ConnectPoint src;
final ConnectPoint dst;
LinkKey(ConnectPoint src, ConnectPoint dst) {
this.src = src;
this.dst = dst;
}
@Override
public int hashCode() {
return Objects.hash(src, dst);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof LinkKey) {
final LinkKey other = (LinkKey) obj;
return Objects.equals(this.src, other.src) &&
Objects.equals(this.dst, other.dst);
}
return false;
}
}
}
......
......@@ -58,13 +58,13 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>17.0</version>
<version>18.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<version>17.0</version>
<version>18.0</version>
<scope>test</scope>
</dependency>
......
......@@ -2,6 +2,7 @@ package org.onlab.graph;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
/**
......@@ -49,7 +50,7 @@ public abstract class AbstractEdge<V extends Vertex> implements Edge<V> {
@Override
public String toString() {
return com.google.common.base.Objects.toStringHelper(this)
return toStringHelper(this)
.add("src", src)
.add("dst", dst)
.toString();
......
......@@ -6,6 +6,7 @@ import com.google.common.collect.ImmutableSetMultimap;
import java.util.Objects;
import java.util.Set;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
/**
......@@ -94,7 +95,7 @@ public class AdjacencyListsGraph<V extends Vertex, E extends Edge<V>> implements
@Override
public String toString() {
return com.google.common.base.Objects.toStringHelper(this)
return toStringHelper(this)
.add("vertexes", vertexes)
.add("edges", edges)
.toString();
......
......@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
......@@ -91,7 +92,7 @@ public class DefaultMutablePath<V extends Vertex, E extends Edge<V>> implements
@Override
public String toString() {
return com.google.common.base.Objects.toStringHelper(this)
return toStringHelper(this)
.add("src", src())
.add("dst", dst())
.add("cost", cost)
......
......@@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
......@@ -56,7 +57,7 @@ public class DefaultPath<V extends Vertex, E extends Edge<V>> implements Path<V,
@Override
public String toString() {
return com.google.common.base.Objects.toStringHelper(this)
return toStringHelper(this)
.add("src", src)
.add("dst", dst)
.add("cost", cost)
......
......@@ -7,6 +7,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
/**
......@@ -181,7 +182,7 @@ public class Heap<T> {
@Override
public String toString() {
return com.google.common.base.Objects.toStringHelper(this)
return toStringHelper(this)
.add("data", data)
.add("comparator", comparator)
.toString();
......
......@@ -2,7 +2,7 @@ package org.onlab.graph;
import java.util.Objects;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Test edge.
......