tom

Restructured to separate stores and managers into different bundles. Reactive fo…

…rwarding does not seem to work; will investigate.
Showing 34 changed files with 147 additions and 96 deletions
......@@ -10,8 +10,7 @@ import org.onlab.onos.net.provider.ProviderId;
import java.util.List;
/**
* Manages inventory of infrastructure devices. It may do so using whatever
* means are appropriate.
* Manages inventory of infrastructure devices.
*/
public interface DeviceStore {
......
package org.onlab.onos.net.flow;
import org.onlab.onos.net.DeviceId;
/**
* Manages inventory of flow rules.
*/
public interface FlowRuleStore {
/**
* Returns the flow entries associated with a device.
*
* @param deviceId the device ID
* @return the flow entries
*/
Iterable<FlowRule> getFlowEntries(DeviceId deviceId);
/**
* Stores a new flow rule, and generates a FlowRule for it.
*
* @param rule the flow rule to add
* @return a flow entry
*/
FlowRule storeFlowRule(FlowRule rule);
/**
* Stores a new flow rule, or updates an existing entry.
*
* @param rule the flow rule to add or update
* @return flow_added event, or null if just an update
*/
FlowRuleEvent addOrUpdateFlowRule(FlowRule rule);
/**
* @param rule the flow rule to remove
* @return flow_removed event, or null if nothing removed
*/
FlowRuleEvent removeFlowRule(FlowRule rule);
}
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
......@@ -6,16 +6,13 @@ import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.topology.GraphDescription;
import org.onlab.onos.net.topology.TopologyEdge;
import org.onlab.onos.net.topology.TopologyVertex;
import java.util.Map;
/**
* Default implementation of an immutable topology graph data carrier.
*/
class DefaultGraphDescription implements GraphDescription {
public class DefaultGraphDescription implements GraphDescription {
private final long nanos;
private final ImmutableSet<TopologyVertex> vertexes;
......@@ -32,7 +29,7 @@ class DefaultGraphDescription implements GraphDescription {
* @param devices collection of infrastructure devices
* @param links collection of infrastructure links
*/
DefaultGraphDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) {
public DefaultGraphDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) {
this.nanos = nanos;
this.vertexes = buildVertexes(devices);
this.edges = buildEdges(links);
......
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.topology.TopologyEdge;
import org.onlab.onos.net.topology.TopologyVertex;
import java.util.Objects;
......@@ -11,7 +9,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Implementation of the topology edge backed by a link.
*/
class DefaultTopologyEdge implements TopologyEdge {
public class DefaultTopologyEdge implements TopologyEdge {
private final Link link;
private final TopologyVertex src;
......@@ -24,7 +22,7 @@ class DefaultTopologyEdge implements TopologyEdge {
* @param dst destination vertex
* @param link infrastructure link
*/
DefaultTopologyEdge(TopologyVertex src, TopologyVertex dst, Link link) {
public DefaultTopologyEdge(TopologyVertex src, TopologyVertex dst, Link link) {
this.src = src;
this.dst = dst;
this.link = link;
......
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.topology.TopologyVertex;
import java.util.Objects;
/**
* Implementation of the topology vertex backed by a device id.
*/
class DefaultTopologyVertex implements TopologyVertex {
public class DefaultTopologyVertex implements TopologyVertex {
private final DeviceId deviceId;
......@@ -17,7 +16,7 @@ class DefaultTopologyVertex implements TopologyVertex {
*
* @param deviceId backing infrastructure device identifier
*/
DefaultTopologyVertex(DeviceId deviceId) {
public DefaultTopologyVertex(DeviceId deviceId) {
this.deviceId = deviceId;
}
......
......@@ -21,6 +21,14 @@
<groupId>org.onlab.onos</groupId>
<artifactId>onos-api</artifactId>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-core-trivial</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
......
package org.onlab.onos.net.trivial.device.impl;
package org.onlab.onos.net.device.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
......
package org.onlab.onos.net.trivial.flow.impl;
package org.onlab.onos.net.flow.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
......@@ -24,6 +24,7 @@ import org.onlab.onos.net.flow.FlowRuleProvider;
import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
import org.onlab.onos.net.flow.FlowRuleProviderService;
import org.onlab.onos.net.flow.FlowRuleService;
import org.onlab.onos.net.flow.FlowRuleStore;
import org.onlab.onos.net.provider.AbstractProviderRegistry;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
......@@ -31,8 +32,8 @@ import org.slf4j.Logger;
@Component(immediate = true)
@Service
public class SimpleFlowRuleManager
extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
implements FlowRuleService, FlowRuleProviderRegistry {
extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
implements FlowRuleService, FlowRuleProviderRegistry {
public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
private final Logger log = getLogger(getClass());
......@@ -40,7 +41,8 @@ implements FlowRuleService, FlowRuleProviderRegistry {
private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
listenerRegistry = new AbstractListenerRegistry<>();
private final SimpleFlowRuleStore store = new SimpleFlowRuleStore();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowRuleStore store;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EventDeliveryService eventDispatcher;
......
/**
* Core subsystem for tracking and manipulating global flow state.
*/
package org.onlab.onos.net.trivial.flow.impl;
package org.onlab.onos.net.flow.impl;
......
package org.onlab.onos.net.trivial.host.impl;
package org.onlab.onos.net.host.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
......
package org.onlab.onos.net.trivial.host.impl;
package org.onlab.onos.net.host.impl;
import java.util.HashSet;
import java.util.Set;
......
/**
* Core subsystem for tracking global inventory of end-station hosts.
*/
package org.onlab.onos.net.trivial.host.impl;
package org.onlab.onos.net.host.impl;
......
package org.onlab.onos.net.trivial.link.impl;
package org.onlab.onos.net.link.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
......
package org.onlab.onos.net.trivial.packet.impl;
package org.onlab.onos.net.packet.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
......
......@@ -3,4 +3,4 @@
* Processing of inbound packets is always in the local context only, but
* emitting outbound packets allows for cluster-wide operation.
*/
package org.onlab.onos.net.trivial.packet.impl;
package org.onlab.onos.net.packet.impl;
......
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
......@@ -16,6 +16,7 @@ import org.onlab.onos.net.link.LinkListener;
import org.onlab.onos.net.link.LinkService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.DefaultGraphDescription;
import org.onlab.onos.net.topology.GraphDescription;
import org.onlab.onos.net.topology.TopologyProvider;
import org.onlab.onos.net.topology.TopologyProviderRegistry;
......
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
......
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
......
/**
* Core subsystem for tracking global &amp; consistent topology graph views.
*/
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology.impl;
......
package org.onlab.onos.net.trivial.device.impl;
package org.onlab.onos.net.device.impl;
import org.junit.After;
import org.junit.Before;
......@@ -23,6 +23,7 @@ import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.event.impl.TestEventDispatcher;
import org.onlab.onos.net.trivial.device.impl.SimpleDeviceStore;
import java.util.ArrayList;
import java.util.Iterator;
......
package org.onlab.onos.net.trivial.flow.impl;
package org.onlab.onos.net.flow.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
......@@ -40,6 +40,7 @@ import org.onlab.onos.net.provider.ProviderId;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.onos.net.trivial.flow.impl.SimpleFlowRuleStore;
/**
* Test codifying the flow rule service & flow rule provider service contracts.
......@@ -62,6 +63,7 @@ public class SimpleFlowRuleManagerTest {
@Before
public void setUp() {
mgr = new SimpleFlowRuleManager();
mgr.store = new SimpleFlowRuleStore();
mgr.eventDispatcher = new TestEventDispatcher();
mgr.deviceService = new TestDeviceService();
service = mgr;
......
package org.onlab.onos.net.trivial.host.impl;
package org.onlab.onos.net.host.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
......@@ -28,6 +28,7 @@ import org.onlab.onos.net.host.HostProviderRegistry;
import org.onlab.onos.net.host.HostProviderService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.trivial.host.impl.SimpleHostStore;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
......
package org.onlab.onos.net.trivial.link.impl;
package org.onlab.onos.net.link.impl;
import com.google.common.collect.ImmutableSet;
import org.junit.After;
......@@ -22,7 +22,8 @@ import org.onlab.onos.net.link.LinkService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.event.impl.TestEventDispatcher;
import org.onlab.onos.net.trivial.device.impl.DeviceManager;
import org.onlab.onos.net.device.impl.DeviceManager;
import org.onlab.onos.net.trivial.link.impl.SimpleLinkStore;
import java.util.ArrayList;
import java.util.Iterator;
......
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology.impl;
import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -8,27 +9,24 @@ import org.onlab.onos.event.impl.TestEventDispatcher;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.impl.DeviceManager;
import org.onlab.onos.net.link.LinkEvent;
import org.onlab.onos.net.link.impl.LinkManager;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.GraphDescription;
import org.onlab.onos.net.topology.TopologyProvider;
import org.onlab.onos.net.topology.TopologyProviderRegistry;
import org.onlab.onos.net.topology.TopologyProviderService;
import org.onlab.onos.net.trivial.device.impl.DeviceManager;
import org.onlab.onos.net.trivial.link.impl.LinkManager;
import java.util.List;
import java.util.Set;
import static com.google.common.collect.ImmutableSet.of;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.onlab.junit.TestTools.assertAfter;
import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED;
import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
import static org.onlab.onos.net.trivial.topology.impl.TopologyManagerTest.device;
import static org.onlab.onos.net.trivial.topology.impl.TopologyManagerTest.link;
/**
* Test of the default topology provider implementation.
......@@ -81,8 +79,8 @@ public class DefaultTopologyProviderTest {
@Override
public void run() {
validateSubmission();
deviceService.post(new DeviceEvent(DEVICE_ADDED, device("z"), null));
linkService.post(new LinkEvent(LINK_ADDED, link("z", 1, "a", 4)));
deviceService.post(new DeviceEvent(DEVICE_ADDED, TopologyManagerTest.device("z"), null));
linkService.post(new LinkEvent(LINK_ADDED, TopologyManagerTest.link("z", 1, "a", 4)));
validateSubmission();
}
});
......@@ -130,9 +128,9 @@ public class DefaultTopologyProviderTest {
@Override
public Iterable<Device> getDevices() {
return of(device("a"), device("b"),
device("c"), device("d"),
device("e"), device("f"));
return ImmutableSet.of(TopologyManagerTest.device("a"), TopologyManagerTest.device("b"),
TopologyManagerTest.device("c"), TopologyManagerTest.device("d"),
TopologyManagerTest.device("e"), TopologyManagerTest.device("f"));
}
void post(DeviceEvent event) {
......@@ -148,11 +146,11 @@ public class DefaultTopologyProviderTest {
@Override
public Iterable<Link> getLinks() {
return of(link("a", 1, "b", 1), link("b", 1, "a", 1),
link("b", 2, "c", 1), link("c", 1, "b", 2),
link("c", 2, "d", 1), link("d", 1, "c", 2),
link("d", 2, "a", 2), link("a", 2, "d", 2),
link("e", 1, "f", 1), link("f", 1, "e", 1));
return ImmutableSet.of(TopologyManagerTest.link("a", 1, "b", 1), TopologyManagerTest.link("b", 1, "a", 1),
TopologyManagerTest.link("b", 2, "c", 1), TopologyManagerTest.link("c", 1, "b", 2),
TopologyManagerTest.link("c", 2, "d", 1), TopologyManagerTest.link("d", 1, "c", 2),
TopologyManagerTest.link("d", 2, "a", 2), TopologyManagerTest.link("a", 2, "d", 2),
TopologyManagerTest.link("e", 1, "f", 1), TopologyManagerTest.link("f", 1, "e", 1));
}
void post(LinkEvent event) {
......
package org.onlab.onos.net.trivial.topology.impl;
package org.onlab.onos.net.topology.impl;
import org.junit.After;
import org.junit.Before;
......@@ -14,6 +14,7 @@ import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.DefaultGraphDescription;
import org.onlab.onos.net.topology.GraphDescription;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.Topology;
......@@ -26,6 +27,7 @@ import org.onlab.onos.net.topology.TopologyProvider;
import org.onlab.onos.net.topology.TopologyProviderRegistry;
import org.onlab.onos.net.topology.TopologyProviderService;
import org.onlab.onos.net.topology.TopologyService;
import org.onlab.onos.net.trivial.topology.impl.SimpleTopologyStore;
import java.util.ArrayList;
import java.util.List;
......@@ -183,20 +185,20 @@ public class TopologyManagerTest {
}
// Short-hand for creating a link.
static Link link(String src, int sp, String dst, int dp) {
public static Link link(String src, int sp, String dst, int dp) {
return new DefaultLink(PID, new ConnectPoint(did(src), portNumber(sp)),
new ConnectPoint(did(dst), portNumber(dp)),
Link.Type.DIRECT);
}
// Crates a new device with the specified id
static Device device(String id) {
public static Device device(String id) {
return new DefaultDevice(PID, did(id), Device.Type.SWITCH,
"mfg", "1.0", "1.1", "1234");
}
// Short-hand for producing a device id from a string
static DeviceId did(String id) {
public static DeviceId did(String id) {
return deviceId("of:" + id);
}
......
package org.onlab.onos.net.trivial.flow.impl;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.flow.DefaultFlowRule;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.FlowRuleEvent;
import org.onlab.onos.net.flow.FlowRuleStore;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import static org.onlab.onos.net.flow.FlowRuleEvent.Type.*;
import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
/**
* Manages inventory of flow rules using trivial in-memory implementation.
*/
public class SimpleFlowRuleStore {
public class SimpleFlowRuleStore implements FlowRuleStore {
// store entries as a pile of rules, no info about device tables
private final Multimap<DeviceId, FlowRule> flowEntries = HashMultimap.create();
/**
* Returns the flow entries associated with a device.
*
* @param deviceId the device ID
* @return the flow entries
*/
Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
@Override
public Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
return ImmutableSet.copyOf(flowEntries.get(deviceId));
}
/**
* Stores a new flow rule, and generates a FlowRule for it.
*
* @param rule the flow rule to add
* @return a flow entry
*/
FlowRule storeFlowRule(FlowRule rule) {
@Override
public FlowRule storeFlowRule(FlowRule rule) {
DeviceId did = rule.deviceId();
FlowRule entry = new DefaultFlowRule(did,
rule.selector(), rule.treatment(), rule.priority());
......@@ -43,13 +34,8 @@ public class SimpleFlowRuleStore {
return entry;
}
/**
* Stores a new flow rule, or updates an existing entry.
*
* @param rule the flow rule to add or update
* @return flow_added event, or null if just an update
*/
FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
@Override
public FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
DeviceId did = rule.deviceId();
// check if this new rule is an update to an existing entry
......@@ -63,13 +49,8 @@ public class SimpleFlowRuleStore {
return new FlowRuleEvent(RULE_ADDED, rule);
}
/**
*
* @param rule the flow rule to remove
* @return flow_removed event, or null if nothing removed
*/
FlowRuleEvent removeFlowRule(FlowRule rule) {
@Override
public FlowRuleEvent removeFlowRule(FlowRule rule) {
synchronized (this) {
if (flowEntries.remove(rule.deviceId(), rule)) {
return new FlowRuleEvent(RULE_REMOVED, rule);
......
......@@ -15,6 +15,7 @@ import org.onlab.onos.net.Path;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.ClusterId;
import org.onlab.onos.net.topology.DefaultTopologyCluster;
import org.onlab.onos.net.topology.DefaultTopologyVertex;
import org.onlab.onos.net.topology.GraphDescription;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.Topology;
......
......@@ -3,6 +3,8 @@ package org.onlab.onos.net.trivial.topology.impl;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultDevice;
import org.onlab.onos.net.DefaultLink;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link;
......@@ -10,6 +12,7 @@ import org.onlab.onos.net.Path;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.ClusterId;
import org.onlab.onos.net.topology.DefaultGraphDescription;
import org.onlab.onos.net.topology.GraphDescription;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.TopologyCluster;
......@@ -21,8 +24,6 @@ import static com.google.common.collect.ImmutableSet.of;
import static org.junit.Assert.*;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.PortNumber.portNumber;
import static org.onlab.onos.net.trivial.topology.impl.TopologyManagerTest.device;
import static org.onlab.onos.net.trivial.topology.impl.TopologyManagerTest.link;
/**
* Test of the default topology implementation.
......@@ -108,4 +109,22 @@ public class DefaultTopologyTest {
assertFalse("cluster should not contain D5", devs.contains(D5));
}
// Short-hand for creating a link.
public static Link link(String src, int sp, String dst, int dp) {
return new DefaultLink(PID, new ConnectPoint(did(src), portNumber(sp)),
new ConnectPoint(did(dst), portNumber(dp)),
Link.Type.DIRECT);
}
// Crates a new device with the specified id
public static Device device(String id) {
return new DefaultDevice(PID, did(id), Device.Type.SWITCH,
"mfg", "1.0", "1.1", "1234");
}
// Short-hand for producing a device id from a string
public static DeviceId did(String id) {
return deviceId("of:" + id);
}
}
......
......@@ -36,6 +36,7 @@
<feature name="onos-core" version="1.0.0"
description="ONOS core components">
<feature>onos-api</feature>
<bundle>mvn:org.onlab.onos/onos-core-net/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-core-trivial/1.0.0-SNAPSHOT</bundle>
</feature>
......
......@@ -28,7 +28,7 @@
<br>
<img src="doc-files/onos-subsystem.png" alt="ONOS subsystem structure"><br>
For example, the device-subsystem comprises of a core
{@link org.onlab.onos.net.trivial.device.impl.DeviceManager},
{@link org.onlab.onos.net.device.impl.DeviceManager},
which exposes a north-bound
{@link org.onlab.onos.net.device.DeviceService} through which applications or other core components
can learn about the global infrastructure device inventory and through
......@@ -39,7 +39,7 @@
</p>
<p>
On the south-bound side, the core {@link org.onlab.onos.net.trivial.device.impl.DeviceManager}
On the south-bound side, the core {@link org.onlab.onos.net.device.impl.DeviceManager}
exposes a {@link org.onlab.onos.net.device.DeviceProviderRegistry} through which any number of
{@link org.onlab.onos.net.device.DeviceProvider} entities can register and in turn obtain a
{@link org.onlab.onos.net.device.DeviceProviderService}. Device and port information can then be
......