diff options
Diffstat (limited to 'framework/src/onos/providers')
23 files changed, 325 insertions, 2572 deletions
diff --git a/framework/src/onos/providers/host/pom.xml b/framework/src/onos/providers/host/pom.xml index e8f32ca1..ddbdbfc5 100644 --- a/framework/src/onos/providers/host/pom.xml +++ b/framework/src/onos/providers/host/pom.xml @@ -29,7 +29,11 @@ <artifactId>onos-host-provider</artifactId> <packaging>bundle</packaging> - <description>ONOS host tracking provider</description> + <properties> + <onos.app.name>org.onosproject.hostprovider</onos.app.name> + </properties> + + <description>ONOS host location provider</description> <dependencies> <dependency> <groupId>org.onosproject</groupId> diff --git a/framework/src/onos/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java b/framework/src/onos/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java index 6cbb623b..566eb0c4 100644 --- a/framework/src/onos/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java +++ b/framework/src/onos/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java @@ -196,16 +196,16 @@ public class HostLocationProviderTest { providerService.clear(); // new host - testProcessor.process(new TestNAPacketContext(DEV4)); + testProcessor.process(new TestNaPacketContext(DEV4)); assertNotNull("new host expected", providerService.added); assertNull("host motion unexpected", providerService.moved); // the host moved to new switch - testProcessor.process(new TestNAPacketContext(DEV5)); + testProcessor.process(new TestNaPacketContext(DEV5)); assertNotNull("host motion expected", providerService.moved); // the host was misheard on a spine - testProcessor.process(new TestNAPacketContext(DEV6)); + testProcessor.process(new TestNaPacketContext(DEV6)); assertNull("host misheard on spine switch", providerService.spine); } @@ -213,7 +213,7 @@ public class HostLocationProviderTest { public void removeHostByDeviceRemove() { provider.modified(CTX_FOR_REMOVE); testProcessor.process(new TestArpPacketContext(DEV1)); - testProcessor.process(new TestNAPacketContext(DEV4)); + testProcessor.process(new TestNaPacketContext(DEV4)); Device device = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), SWITCH, "m", "h", "s", "n", new ChassisId(0L)); @@ -292,8 +292,8 @@ public class HostLocationProviderTest { * When receiving NeighborAdvertisement, updates location and IP. */ @Test - public void testReceiveNA() { - testProcessor.process(new TestNAPacketContext(DEV4)); + public void testReceiveNa() { + testProcessor.process(new TestNaPacketContext(DEV4)); assertNotNull(providerService.added); HostDescription descr = providerService.added; assertThat(descr.location(), is(LOCATION2)); @@ -306,8 +306,8 @@ public class HostLocationProviderTest { * When receiving NeighborSolicitation, updates location and IP. */ @Test - public void testReceiveNS() { - testProcessor.process(new TestNSPacketContext(DEV4)); + public void testReceiveNs() { + testProcessor.process(new TestNsPacketContext(DEV4)); HostDescription descr = providerService.added; assertThat(descr.location(), is(LOCATION2)); assertThat(descr.hwAddress(), is(MAC2)); @@ -319,7 +319,7 @@ public class HostLocationProviderTest { * When receiving RouterAdvertisement, ignores it. */ @Test - public void testReceivesRA() { + public void testReceivesRa() { testProcessor.process(new TestRAPacketContext(DEV4)); assertNull(providerService.added); } @@ -328,7 +328,7 @@ public class HostLocationProviderTest { * When receiving RouterSolicitation, ignores it. */ @Test - public void testReceiveRS() { + public void testReceiveRs() { testProcessor.process(new TestRSPacketContext(DEV4)); assertNull(providerService.added); } @@ -337,8 +337,8 @@ public class HostLocationProviderTest { * When receiving Duplicate Address Detection (DAD), ignores it. */ @Test - public void testReceiveDAD() { - testProcessor.process(new TestDADPacketContext(DEV4)); + public void testReceiveDad() { + testProcessor.process(new TestDadPacketContext(DEV4)); assertNull(providerService.added); } @@ -415,7 +415,7 @@ public class HostLocationProviderTest { public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) { if (added == null) { added = hostDescription; - } else if ((moved == null) && !hostDescription.equals(added)) { + } else if ((moved == null) && hostDescription != added) { moved = hostDescription; } else { spine = hostDescription; @@ -575,10 +575,10 @@ public class HostLocationProviderTest { /** * Generates NeighborAdvertisement packet. */ - private class TestNAPacketContext implements PacketContext { + private class TestNaPacketContext implements PacketContext { private final String deviceId; - public TestNAPacketContext(String deviceId) { + public TestNaPacketContext(String deviceId) { this.deviceId = deviceId; } @@ -637,10 +637,10 @@ public class HostLocationProviderTest { /** * Generates NeighborSolicitation packet. */ - private class TestNSPacketContext implements PacketContext { + private class TestNsPacketContext implements PacketContext { private final String deviceId; - public TestNSPacketContext(String deviceId) { + public TestNsPacketContext(String deviceId) { this.deviceId = deviceId; } @@ -699,10 +699,10 @@ public class HostLocationProviderTest { /** * Generates Duplicate Address Detection packet. */ - private class TestDADPacketContext implements PacketContext { + private class TestDadPacketContext implements PacketContext { private final String deviceId; - public TestDADPacketContext(String deviceId) { + public TestDadPacketContext(String deviceId) { this.deviceId = deviceId; } diff --git a/framework/src/onos/providers/lldp/pom.xml b/framework/src/onos/providers/lldp/pom.xml index e47d26c7..7bf92ed2 100644 --- a/framework/src/onos/providers/lldp/pom.xml +++ b/framework/src/onos/providers/lldp/pom.xml @@ -30,7 +30,11 @@ <artifactId>onos-lldp-provider</artifactId> <packaging>bundle</packaging> - <description>ONOS LLDP Link Discovery</description> + <properties> + <onos.app.name>org.onosproject.lldpprovider</onos.app.name> + </properties> + + <description>ONOS LLDP link provider</description> <dependencies> <dependency> diff --git a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/DiscoveryContext.java b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/DiscoveryContext.java index 0cd19242..a9da92ab 100644 --- a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/DiscoveryContext.java +++ b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/DiscoveryContext.java @@ -58,7 +58,7 @@ interface DiscoveryContext { * * @return true to emit BDDP */ - boolean useBDDP(); + boolean useBddp(); /** * Touches the link identified by the given key to indicate that it's active. diff --git a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java deleted file mode 100644 index 98442033..00000000 --- a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.lldp.impl; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Modified; -import org.apache.felix.scr.annotations.Property; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.onlab.packet.Ethernet; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.cluster.ClusterService; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.mastership.MastershipEvent; -import org.onosproject.mastership.MastershipListener; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.LinkKey; -import org.onosproject.net.Port; -import org.onosproject.net.config.NetworkConfigRegistry; -import org.onosproject.net.device.DeviceEvent; -import org.onosproject.net.device.DeviceListener; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.link.DefaultLinkDescription; -import org.onosproject.net.link.LinkProvider; -import org.onosproject.net.link.LinkProviderRegistry; -import org.onosproject.net.link.LinkProviderService; -import org.onosproject.net.link.LinkService; -import org.onosproject.net.packet.PacketContext; -import org.onosproject.net.packet.PacketPriority; -import org.onosproject.net.packet.PacketProcessor; -import org.onosproject.net.packet.PacketService; -import org.onosproject.net.provider.AbstractProvider; -import org.onosproject.net.provider.ProviderId; -import org.osgi.service.component.ComponentContext; -import org.slf4j.Logger; - -import java.io.IOException; -import java.util.Dictionary; -import java.util.EnumSet; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledExecutorService; - -import static com.google.common.base.Strings.isNullOrEmpty; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.onlab.packet.Ethernet.TYPE_BSN; -import static org.onlab.packet.Ethernet.TYPE_LLDP; -import static org.onlab.util.Tools.get; -import static org.onlab.util.Tools.groupedThreads; -import static org.onosproject.net.Link.Type.DIRECT; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Provider which uses LLDP and BDDP packets to detect network infrastructure links. - */ -@Component(immediate = true) -public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { - - private static final String PROVIDER_NAME = "org.onosproject.provider.lldp"; - - private static final String FORMAT = - "Settings: enabled={}, useBDDP={}, probeRate={}, " + - "staleLinkAge={}, lldpSuppression={}"; - - // When a Device/Port has this annotation, do not send out LLDP/BDDP - public static final String NO_LLDP = "no-lldp"; - - - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected CoreService coreService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LinkProviderRegistry providerRegistry; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DeviceService deviceService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected LinkService linkService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected PacketService packetService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected MastershipService masterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ComponentConfigService cfgService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected NetworkConfigRegistry cfgRegistry; - - private LinkProviderService providerService; - - private ScheduledExecutorService executor; - - // TODO: Add sanity checking for the configurable params based on the delays - private static final long DEVICE_SYNC_DELAY = 5; - private static final long LINK_PRUNER_DELAY = 3; - - private static final String PROP_ENABLED = "enabled"; - @Property(name = PROP_ENABLED, boolValue = true, - label = "If false, link discovery is disabled") - private boolean enabled = false; - - private static final String PROP_USE_BDDP = "useBDDP"; - @Property(name = PROP_USE_BDDP, boolValue = true, - label = "Use BDDP for link discovery") - private boolean useBDDP = true; - - private static final String PROP_PROBE_RATE = "probeRate"; - private static final int DEFAULT_PROBE_RATE = 3_000; - @Property(name = PROP_PROBE_RATE, intValue = DEFAULT_PROBE_RATE, - label = "LLDP and BDDP probe rate specified in millis") - private int probeRate = DEFAULT_PROBE_RATE; - - private static final String PROP_STALE_LINK_AGE = "staleLinkAge"; - private static final int DEFAULT_STALE_LINK_AGE = 10_000; - @Property(name = PROP_STALE_LINK_AGE, intValue = DEFAULT_STALE_LINK_AGE, - label = "Number of millis beyond which links will be considered stale") - private int staleLinkAge = DEFAULT_STALE_LINK_AGE; - - // FIXME: convert to use network config subsystem instead - private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression"; - private static final String DEFAULT_LLDP_SUPPRESSION_CONFIG = "../config/lldp_suppression.json"; - @Property(name = PROP_LLDP_SUPPRESSION, value = DEFAULT_LLDP_SUPPRESSION_CONFIG, - label = "Path to LLDP suppression configuration file") - private String lldpSuppression = DEFAULT_LLDP_SUPPRESSION_CONFIG; - - private final DiscoveryContext context = new InternalDiscoveryContext(); - private final InternalRoleListener roleListener = new InternalRoleListener(); - private final InternalDeviceListener deviceListener = new InternalDeviceListener(); - private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor(); - - // Device link discovery helpers. - protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>(); - - // Most recent time a tracked link was seen; links are tracked if their - // destination connection point is mastered by this controller instance. - private final Map<LinkKey, Long> linkTimes = Maps.newConcurrentMap(); - - private SuppressionRules rules; - private ApplicationId appId; - - /** - * Creates an OpenFlow link provider. - */ - public LLDPLinkProvider() { - super(new ProviderId("lldp", PROVIDER_NAME)); - } - - @Activate - public void activate(ComponentContext context) { - cfgService.registerProperties(getClass()); - appId = coreService.registerApplication(PROVIDER_NAME); - modified(context); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - cfgService.unregisterProperties(getClass(), false); - disable(); - log.info("Stopped"); - } - - @Modified - public void modified(ComponentContext context) { - Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties(); - - boolean newEnabled, newUseBddp; - int newProbeRate, newStaleLinkAge; - String newLldpSuppression; - try { - String s = get(properties, PROP_ENABLED); - newEnabled = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim()); - - s = get(properties, PROP_USE_BDDP); - newUseBddp = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim()); - - s = get(properties, PROP_PROBE_RATE); - newProbeRate = isNullOrEmpty(s) ? probeRate : Integer.parseInt(s.trim()); - - s = get(properties, PROP_STALE_LINK_AGE); - newStaleLinkAge = isNullOrEmpty(s) ? staleLinkAge : Integer.parseInt(s.trim()); - - s = get(properties, PROP_LLDP_SUPPRESSION); - newLldpSuppression = isNullOrEmpty(s) ? DEFAULT_LLDP_SUPPRESSION_CONFIG : s; - - } catch (NumberFormatException e) { - log.warn("Component configuration had invalid values", e); - newEnabled = enabled; - newUseBddp = useBDDP; - newProbeRate = probeRate; - newStaleLinkAge = staleLinkAge; - newLldpSuppression = lldpSuppression; - } - - boolean wasEnabled = enabled; - - enabled = newEnabled; - useBDDP = newUseBddp; - probeRate = newProbeRate; - staleLinkAge = newStaleLinkAge; - lldpSuppression = newLldpSuppression; - - if (!wasEnabled && enabled) { - enable(); - } else if (wasEnabled && !enabled) { - disable(); - } else { - // reflect changes in suppression rules to discovery helpers - // FIXME: After migrating to Network Configuration Subsystem, - // it should be possible to update only changed subset - if (enabled) { - // update all discovery helper state - loadDevices(); - } - } - - log.info(FORMAT, enabled, useBDDP, probeRate, staleLinkAge, lldpSuppression); - } - - /** - * Enables link discovery processing. - */ - private void enable() { - providerService = providerRegistry.register(this); - masterService.addListener(roleListener); - deviceService.addListener(deviceListener); - packetService.addProcessor(packetProcessor, PacketProcessor.advisor(0)); - - loadSuppressionRules(); - loadDevices(); - - executor = newSingleThreadScheduledExecutor(groupedThreads("onos/link", "discovery-%d")); - executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), - DEVICE_SYNC_DELAY, DEVICE_SYNC_DELAY, SECONDS); - executor.scheduleAtFixedRate(new LinkPrunerTask(), - LINK_PRUNER_DELAY, LINK_PRUNER_DELAY, SECONDS); - - requestIntercepts(); - } - - /** - * Disables link discovery processing. - */ - private void disable() { - withdrawIntercepts(); - - providerRegistry.unregister(this); - masterService.removeListener(roleListener); - deviceService.removeListener(deviceListener); - packetService.removeProcessor(packetProcessor); - - if (executor != null) { - executor.shutdownNow(); - } - discoverers.values().forEach(LinkDiscovery::stop); - discoverers.clear(); - - providerService = null; - } - - /** - * Loads available devices and registers their ports to be probed. - */ - private void loadDevices() { - deviceService.getAvailableDevices() - .forEach(d -> updateDevice(d) - .ifPresent(ld -> updatePorts(ld, d.id()))); - } - - /** - * Updates discovery helper for specified device. - * - * Adds and starts a discovery helper for specified device if enabled, - * calls {@link #removeDevice(DeviceId)} otherwise. - * - * @param device device to add - * @return discovery helper if discovery is enabled for the device - */ - private Optional<LinkDiscovery> updateDevice(Device device) { - if (rules.isSuppressed(device)) { - log.trace("LinkDiscovery from {} disabled by configuration", device.id()); - removeDevice(device.id()); - return Optional.empty(); - } - LinkDiscovery ld = discoverers.computeIfAbsent(device.id(), - did -> new LinkDiscovery(device, context)); - if (ld.isStopped()) { - ld.start(); - } - return Optional.of(ld); - } - - /** - * Removes after stopping discovery helper for specified device. - * @param deviceId device to remove - */ - private void removeDevice(final DeviceId deviceId) { - discoverers.computeIfPresent(deviceId, (did, ld) -> { - ld.stop(); - providerService.linksVanished(deviceId); - return null; - }); - - } - - /** - * Updates ports of the specified device to the specified discovery helper. - */ - private void updatePorts(LinkDiscovery discoverer, DeviceId deviceId) { - deviceService.getPorts(deviceId).forEach(p -> updatePort(discoverer, p)); - } - - /** - * Updates discovery helper state of the specified port. - * - * Adds a port to the discovery helper if up and discovery is enabled, - * or calls {@link #removePort(Port)} otherwise. - */ - private void updatePort(LinkDiscovery discoverer, Port port) { - if (rules.isSuppressed(port)) { - log.trace("LinkDiscovery from {} disabled by configuration", port); - removePort(port); - return; - } - - // check if enabled and turn off discovery? - if (!port.isEnabled()) { - removePort(port); - return; - } - - if (!port.number().isLogical()) { - discoverer.addPort(port); - } - } - - /** - * Removes a port from the specified discovery helper. - * @param port the port - */ - private void removePort(Port port) { - if (port.element() instanceof Device) { - Device d = (Device) port.element(); - LinkDiscovery ld = discoverers.get(d.id()); - if (ld != null) { - ld.removePort(port.number()); - } - - ConnectPoint point = new ConnectPoint(d.id(), port.number()); - providerService.linksVanished(point); - } else { - log.warn("Attempted to remove non-Device port", port); - } - } - - /** - * Loads LLDP suppression rules. - */ - private void loadSuppressionRules() { - // FIXME: convert to use network configuration - SuppressionRulesStore store = new SuppressionRulesStore(lldpSuppression); - try { - log.info("Reading suppression rules from {}", lldpSuppression); - rules = store.read(); - } catch (IOException e) { - log.info("Failed to load {}, using built-in rules", lldpSuppression); - // default rule to suppress ROADM to maintain compatibility - rules = new SuppressionRules(ImmutableSet.of(), - EnumSet.of(Device.Type.ROADM), - ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE)); - } - - // should refresh discoverers when we need dynamic reconfiguration - } - - /** - * Requests packet intercepts. - */ - private void requestIntercepts() { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - selector.matchEthType(TYPE_LLDP); - packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId); - - selector.matchEthType(TYPE_BSN); - if (useBDDP) { - packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId); - } else { - packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId); - } - } - - /** - * Withdraws packet intercepts. - */ - private void withdrawIntercepts() { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - selector.matchEthType(TYPE_LLDP); - packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId); - selector.matchEthType(TYPE_BSN); - packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId); - } - - /** - * Processes device mastership role changes. - */ - private class InternalRoleListener implements MastershipListener { - @Override - public void event(MastershipEvent event) { - if (MastershipEvent.Type.BACKUPS_CHANGED.equals(event.type())) { - // only need new master events - return; - } - - DeviceId deviceId = event.subject(); - Device device = deviceService.getDevice(deviceId); - if (device == null) { - log.debug("Device {} doesn't exist, or isn't there yet", deviceId); - return; - } - if (clusterService.getLocalNode().id().equals(event.roleInfo().master())) { - updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id())); - } - } - - } - - /** - * Processes device events. - */ - private class InternalDeviceListener implements DeviceListener { - @Override - public void event(DeviceEvent event) { - Device device = event.subject(); - Port port = event.port(); - if (device == null) { - log.error("Device is null."); - return; - } - log.trace("{} {} {}", event.type(), event.subject(), event); - final DeviceId deviceId = device.id(); - switch (event.type()) { - case DEVICE_ADDED: - case DEVICE_UPDATED: - updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId)); - break; - case PORT_ADDED: - case PORT_UPDATED: - if (port.isEnabled()) { - updateDevice(device).ifPresent(ld -> updatePort(ld, port)); - } else { - log.debug("Port down {}", port); - removePort(port); - } - break; - case PORT_REMOVED: - log.debug("Port removed {}", port); - removePort(port); - break; - case DEVICE_REMOVED: - case DEVICE_SUSPENDED: - log.debug("Device removed {}", deviceId); - removeDevice(deviceId); - break; - case DEVICE_AVAILABILITY_CHANGED: - if (deviceService.isAvailable(deviceId)) { - log.debug("Device up {}", deviceId); - updateDevice(device); - } else { - log.debug("Device down {}", deviceId); - removeDevice(deviceId); - } - break; - case PORT_STATS_UPDATED: - break; - default: - log.debug("Unknown event {}", event); - } - } - } - - /** - * Processes incoming packets. - */ - private class InternalPacketProcessor implements PacketProcessor { - @Override - public void process(PacketContext context) { - if (context == null || context.isHandled()) { - return; - } - - Ethernet eth = context.inPacket().parsed(); - if (eth == null || (eth.getEtherType() != TYPE_LLDP && eth.getEtherType() != TYPE_BSN)) { - return; - } - - LinkDiscovery ld = discoverers.get(context.inPacket().receivedFrom().deviceId()); - if (ld == null) { - return; - } - - if (ld.handleLLDP(context)) { - context.block(); - } - } - } - - /** - * Auxiliary task to keep device ports up to date. - */ - private final class SyncDeviceInfoTask implements Runnable { - @Override - public void run() { - if (Thread.currentThread().isInterrupted()) { - log.info("Interrupted, quitting"); - return; - } - // check what deviceService sees, to see if we are missing anything - try { - loadDevices(); - } catch (Exception e) { - // Catch all exceptions to avoid task being suppressed - log.error("Exception thrown during synchronization process", e); - } - } - } - - /** - * Auxiliary task for pruning stale links. - */ - private class LinkPrunerTask implements Runnable { - @Override - public void run() { - if (Thread.currentThread().isInterrupted()) { - log.info("Interrupted, quitting"); - return; - } - - try { - // TODO: There is still a slight possibility of mastership - // change occurring right with link going stale. This will - // result in the stale link not being pruned. - Maps.filterEntries(linkTimes, e -> { - if (!masterService.isLocalMaster(e.getKey().dst().deviceId())) { - return true; - } - if (isStale(e.getValue())) { - providerService.linkVanished(new DefaultLinkDescription(e.getKey().src(), - e.getKey().dst(), - DIRECT)); - return true; - } - return false; - }).clear(); - - } catch (Exception e) { - // Catch all exceptions to avoid task being suppressed - log.error("Exception thrown during link pruning process", e); - } - } - - private boolean isStale(long lastSeen) { - return lastSeen < System.currentTimeMillis() - staleLinkAge; - } - } - - /** - * Provides processing context for the device link discovery helpers. - */ - private class InternalDiscoveryContext implements DiscoveryContext { - @Override - public MastershipService mastershipService() { - return masterService; - } - - @Override - public LinkProviderService providerService() { - return providerService; - } - - @Override - public PacketService packetService() { - return packetService; - } - - @Override - public long probeRate() { - return probeRate; - } - - @Override - public boolean useBDDP() { - return useBDDP; - } - - @Override - public void touchLink(LinkKey key) { - linkTimes.put(key, System.currentTimeMillis()); - } - } - -} diff --git a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java index 7dc9aed0..4b962ae5 100644 --- a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java +++ b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java @@ -155,7 +155,7 @@ class LinkDiscovery implements TimerTask { * @param packetContext packet context * @return true if handled */ - boolean handleLLDP(PacketContext packetContext) { + boolean handleLldp(PacketContext packetContext) { Ethernet eth = packetContext.inPacket().parsed(); if (eth == null) { return false; @@ -216,7 +216,7 @@ class LinkDiscovery implements TimerTask { * @param port the port * @return Packet_out message with LLDP data */ - private OutboundPacket createOutBoundLLDP(Long port) { + private OutboundPacket createOutBoundLldp(Long port) { if (port == null) { return null; } @@ -233,7 +233,7 @@ class LinkDiscovery implements TimerTask { * @param port the port * @return Packet_out message with LLDP data */ - private OutboundPacket createOutBoundBDDP(Long port) { + private OutboundPacket createOutBoundBddp(Long port) { if (port == null) { return null; } @@ -246,10 +246,10 @@ class LinkDiscovery implements TimerTask { private void sendProbes(Long portNumber) { log.trace("Sending probes out to {}@{}", portNumber, device.id()); - OutboundPacket pkt = createOutBoundLLDP(portNumber); + OutboundPacket pkt = createOutBoundLldp(portNumber); context.packetService().emit(pkt); - if (context.useBDDP()) { - OutboundPacket bpkt = createOutBoundBDDP(portNumber); + if (context.useBddp()) { + OutboundPacket bpkt = createOutBoundBddp(portNumber); context.packetService().emit(bpkt); } } diff --git a/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java b/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java deleted file mode 100644 index 6070b857..00000000 --- a/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.lldp.impl; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.onlab.packet.ChassisId; -import org.onlab.packet.Ethernet; -import org.onlab.packet.ONOSLLDP; -import org.onosproject.cfg.ComponentConfigAdapter; -import org.onosproject.cluster.NodeId; -import org.onosproject.cluster.RoleInfo; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.core.DefaultApplicationId; -import org.onosproject.mastership.MastershipListener; -import org.onosproject.mastership.MastershipService; -import org.onosproject.net.Annotations; -import org.onosproject.net.ConnectPoint; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultDevice; -import org.onosproject.net.DefaultPort; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.device.DeviceEvent; -import org.onosproject.net.device.DeviceListener; -import org.onosproject.net.device.DeviceServiceAdapter; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.link.LinkDescription; -import org.onosproject.net.link.LinkProvider; -import org.onosproject.net.link.LinkProviderRegistry; -import org.onosproject.net.link.LinkProviderService; -import org.onosproject.net.link.LinkServiceAdapter; -import org.onosproject.net.packet.DefaultInboundPacket; -import org.onosproject.net.packet.InboundPacket; -import org.onosproject.net.packet.OutboundPacket; -import org.onosproject.net.packet.PacketContext; -import org.onosproject.net.packet.PacketProcessor; -import org.onosproject.net.packet.PacketServiceAdapter; -import org.onosproject.net.provider.AbstractProviderService; -import org.onosproject.net.provider.ProviderId; - -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CompletableFuture; - -import static org.easymock.EasyMock.*; -import static org.junit.Assert.*; - -public class LLDPLinkProviderTest { - - private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001"); - private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002"); - private static final DeviceId DID3 = DeviceId.deviceId("of:0000000000000003"); - - private static Port pd1; - private static Port pd2; - private static Port pd3; - private static Port pd4; - - private final LLDPLinkProvider provider = new LLDPLinkProvider(); - private final TestLinkRegistry linkRegistry = new TestLinkRegistry(); - private final TestLinkService linkService = new TestLinkService(); - private final TestPacketService packetService = new TestPacketService(); - private final TestDeviceService deviceService = new TestDeviceService(); - private final TestMasterShipService masterService = new TestMasterShipService(); - - private CoreService coreService; - private TestLinkProviderService providerService; - - private PacketProcessor testProcessor; - private DeviceListener deviceListener; - - private ApplicationId appId = - new DefaultApplicationId(100, "org.onosproject.provider.lldp"); - - @Before - public void setUp() { - coreService = createMock(CoreService.class); - expect(coreService.registerApplication(appId.name())) - .andReturn(appId).anyTimes(); - replay(coreService); - - provider.cfgService = new ComponentConfigAdapter(); - provider.coreService = coreService; - - provider.deviceService = deviceService; - provider.linkService = linkService; - provider.packetService = packetService; - provider.providerRegistry = linkRegistry; - provider.masterService = masterService; - - provider.activate(null); - } - - @Test - public void basics() { - assertNotNull("registration expected", providerService); - assertEquals("incorrect provider", provider, providerService.provider()); - } - - @Test - public void switchAdd() { - DeviceEvent de = deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1); - deviceListener.event(de); - - assertFalse("Device not added", provider.discoverers.isEmpty()); - } - - @Test - public void switchRemove() { - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1)); - - final LinkDiscovery linkDiscovery = provider.discoverers.get(DID1); - if (linkDiscovery != null) { - // If LinkDiscovery helper is there after DEVICE_REMOVED, - // it should be stopped - assertTrue("Discoverer is not stopped", linkDiscovery.isStopped()); - } - assertTrue("Device is not gone.", vanishedDpid(DID1)); - } - - /** - * Checks that links on a reconfigured switch are properly removed. - */ - @Test - public void switchSuppressed() { - // add device to stub DeviceService - deviceService.putDevice(device(DID3)); - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3)); - - assertFalse("Device not added", provider.discoverers.isEmpty()); - - // update device in stub DeviceService with suppression config - deviceService.putDevice(device(DID3, DefaultAnnotations.builder() - .set(LLDPLinkProvider.NO_LLDP, "true") - .build())); - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3)); - - assertTrue("Links on suppressed Device was expected to vanish.", vanishedDpid(DID3)); - } - - @Test - public void portUp() { - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); - deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true))); - - assertTrue("Port not added to discoverer", - provider.discoverers.get(DID1).containsPort(3L)); - } - - @Test - public void portDown() { - - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); - deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false))); - - assertFalse("Port added to discoverer", - provider.discoverers.get(DID1).containsPort(1L)); - assertTrue("Port is not gone.", vanishedPort(1L)); - } - - @Test - public void portRemoved() { - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); - deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true))); - deviceListener.event(portEvent(DeviceEvent.Type.PORT_REMOVED, DID1, port(DID1, 3, true))); - - assertTrue("Port is not gone.", vanishedPort(3L)); - assertFalse("Port was not removed from discoverer", - provider.discoverers.get(DID1).containsPort(3L)); - } - - /** - * Checks that discovery on reconfigured switch are properly restarted. - */ - @Test - public void portSuppressedByDeviceConfig() { - - /// When Device is configured with suppression:ON, Port also is same - - // add device in stub DeviceService with suppression configured - deviceService.putDevice(device(DID3, DefaultAnnotations.builder() - .set(LLDPLinkProvider.NO_LLDP, "true") - .build())); - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3)); - - // non-suppressed port added to suppressed device - final long portno3 = 3L; - deviceService.putPorts(DID3, port(DID3, portno3, true)); - deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true))); - - // discovery on device is expected to be stopped - LinkDiscovery linkDiscovery = provider.discoverers.get(DID3); - if (linkDiscovery != null) { - assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped()); - } - - /// When Device is reconfigured without suppression:OFF, - /// Port should be included for discovery - - // update device in stub DeviceService without suppression configured - deviceService.putDevice(device(DID3)); - // update the Port in stub DeviceService. (Port has reference to Device) - deviceService.putPorts(DID3, port(DID3, portno3, true)); - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3)); - - // discovery should come back on - assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped()); - assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3)); - } - - /** - * Checks that discovery on reconfigured port are properly restarted. - */ - @Test - public void portSuppressedByPortConfig() { - // add device in stub DeviceService without suppression configured - deviceService.putDevice(device(DID3)); - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3)); - - // suppressed port added to non-suppressed device - final long portno3 = 3L; - final Port port3 = port(DID3, portno3, true, - DefaultAnnotations.builder() - .set(LLDPLinkProvider.NO_LLDP, "true") - .build()); - deviceService.putPorts(DID3, port3); - deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3)); - - // discovery helper should be there turned on - assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped()); - assertFalse("Discoverer should not contain the port there", - provider.discoverers.get(DID3).containsPort(portno3)); - } - - @Test - public void portUnknown() { - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); - // Note: DID3 hasn't been added to TestDeviceService, but only port is added - deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, 1, false))); - - - assertNull("DeviceId exists", - provider.discoverers.get(DID3)); - } - - @Test - public void unknownPktCtx() { - - // Note: DID3 hasn't been added to TestDeviceService - PacketContext pktCtx = new TestPacketContext(device(DID3)); - - testProcessor.process(pktCtx); - assertFalse("Context should still be free", pktCtx.isHandled()); - } - - @Test - public void knownPktCtx() { - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1)); - deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2)); - PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2)); - - - testProcessor.process(pktCtx); - - assertTrue("Link not detected", detectedLink(DID1, DID2)); - - } - - - @After - public void tearDown() { - provider.deactivate(); - provider.coreService = null; - provider.providerRegistry = null; - provider.deviceService = null; - provider.packetService = null; - } - - private DeviceEvent deviceEvent(DeviceEvent.Type type, DeviceId did) { - return new DeviceEvent(type, deviceService.getDevice(did)); - - } - - private DefaultDevice device(DeviceId did) { - return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH, - "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); - } - - private DefaultDevice device(DeviceId did, Annotations annotations) { - return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH, - "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId(), annotations); - } - - @SuppressWarnings(value = { "unused" }) - private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) { - return new DeviceEvent(type, deviceService.getDevice(did), - deviceService.getPort(did, port)); - } - - private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, Port port) { - return new DeviceEvent(type, deviceService.getDevice(did), port); - } - - private Port port(DeviceId did, long port, boolean enabled) { - return new DefaultPort(deviceService.getDevice(did), - PortNumber.portNumber(port), enabled); - } - - private Port port(DeviceId did, long port, boolean enabled, Annotations annotations) { - return new DefaultPort(deviceService.getDevice(did), - PortNumber.portNumber(port), enabled, annotations); - } - - private boolean vanishedDpid(DeviceId... dids) { - for (int i = 0; i < dids.length; i++) { - if (!providerService.vanishedDpid.contains(dids[i])) { - return false; - } - } - return true; - } - - private boolean vanishedPort(Long... ports) { - for (int i = 0; i < ports.length; i++) { - if (!providerService.vanishedPort.contains(ports[i])) { - return false; - } - } - return true; - } - - private boolean detectedLink(DeviceId src, DeviceId dst) { - for (DeviceId key : providerService.discoveredLinks.keySet()) { - if (key.equals(src)) { - return providerService.discoveredLinks.get(src).equals(dst); - } - } - return false; - } - - - private class TestLinkRegistry implements LinkProviderRegistry { - - @Override - public LinkProviderService register(LinkProvider provider) { - providerService = new TestLinkProviderService(provider); - return providerService; - } - - @Override - public void unregister(LinkProvider provider) { - } - - @Override - public Set<ProviderId> getProviders() { - return null; - } - - } - - private class TestLinkProviderService - extends AbstractProviderService<LinkProvider> - implements LinkProviderService { - - List<DeviceId> vanishedDpid = Lists.newLinkedList(); - List<Long> vanishedPort = Lists.newLinkedList(); - Map<DeviceId, DeviceId> discoveredLinks = Maps.newHashMap(); - - protected TestLinkProviderService(LinkProvider provider) { - super(provider); - } - - @Override - public void linkDetected(LinkDescription linkDescription) { - DeviceId sDid = linkDescription.src().deviceId(); - DeviceId dDid = linkDescription.dst().deviceId(); - discoveredLinks.put(sDid, dDid); - } - - @Override - public void linkVanished(LinkDescription linkDescription) { - } - - @Override - public void linksVanished(ConnectPoint connectPoint) { - vanishedPort.add(connectPoint.port().toLong()); - - } - - @Override - public void linksVanished(DeviceId deviceId) { - vanishedDpid.add(deviceId); - } - - - } - - - - private class TestPacketContext implements PacketContext { - - protected Device device; - protected boolean blocked = false; - - public TestPacketContext(Device dev) { - device = dev; - } - - @Override - public long time() { - return 0; - } - - @Override - public InboundPacket inPacket() { - ONOSLLDP lldp = new ONOSLLDP(); - lldp.setChassisId(device.chassisId()); - lldp.setPortId((int) pd1.number().toLong()); - lldp.setDevice(deviceService.getDevice(DID1).id().toString()); - - - Ethernet ethPacket = new Ethernet(); - ethPacket.setEtherType(Ethernet.TYPE_LLDP); - ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_NICIRA); - ethPacket.setPayload(lldp); - ethPacket.setPad(true); - - - - ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11"); - - ConnectPoint cp = new ConnectPoint(device.id(), pd3.number()); - - return new DefaultInboundPacket(cp, ethPacket, - ByteBuffer.wrap(ethPacket.serialize())); - - } - - @Override - public OutboundPacket outPacket() { - return null; - } - - @Override - public TrafficTreatment.Builder treatmentBuilder() { - return null; - } - - @Override - public void send() { - - } - - @Override - public boolean block() { - blocked = true; - return blocked; - } - - @Override - public boolean isHandled() { - return blocked; - } - - } - - private class TestPacketService extends PacketServiceAdapter { - @Override - public void addProcessor(PacketProcessor processor, int priority) { - testProcessor = processor; - } - } - - private class TestDeviceService extends DeviceServiceAdapter { - - private final Map<DeviceId, Device> devices = new HashMap<>(); - private final ArrayListMultimap<DeviceId, Port> ports = - ArrayListMultimap.create(); - public TestDeviceService() { - Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH, - "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); - Device d2 = new DefaultDevice(ProviderId.NONE, DID2, Device.Type.SWITCH, - "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId()); - devices.put(DID1, d1); - devices.put(DID2, d2); - pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true); - pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true); - pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true); - pd4 = new DefaultPort(d2, PortNumber.portNumber(2), true); - - ports.putAll(DID1, Lists.newArrayList(pd1, pd2)); - ports.putAll(DID2, Lists.newArrayList(pd3, pd4)); - } - - private void putDevice(Device device) { - DeviceId deviceId = device.id(); - devices.put(deviceId, device); - } - - private void putPorts(DeviceId did, Port...ports) { - this.ports.putAll(did, Lists.newArrayList(ports)); - } - - @Override - public int getDeviceCount() { - return devices.values().size(); - } - - @Override - public Iterable<Device> getDevices() { - return ImmutableList.copyOf(devices.values()); - } - - @Override - public Device getDevice(DeviceId deviceId) { - return devices.get(deviceId); - } - - @Override - public MastershipRole getRole(DeviceId deviceId) { - return MastershipRole.MASTER; - } - - @Override - public List<Port> getPorts(DeviceId deviceId) { - return ports.get(deviceId); - } - - @Override - public Port getPort(DeviceId deviceId, PortNumber portNumber) { - for (Port p : ports.get(deviceId)) { - if (p.number().equals(portNumber)) { - return p; - } - } - return null; - } - - @Override - public boolean isAvailable(DeviceId deviceId) { - return true; - } - - @Override - public void addListener(DeviceListener listener) { - deviceListener = listener; - - } - - @Override - public void removeListener(DeviceListener listener) { - - } - } - - private final class TestMasterShipService implements MastershipService { - - @Override - public MastershipRole getLocalRole(DeviceId deviceId) { - return MastershipRole.MASTER; - } - - @Override - public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) { - return CompletableFuture.completedFuture(null); - } - - @Override - public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) { - return null; - } - - @Override - public NodeId getMasterFor(DeviceId deviceId) { - return null; - } - - @Override - public Set<DeviceId> getDevicesOf(NodeId nodeId) { - return null; - } - - @Override - public void addListener(MastershipListener listener) { - - } - - @Override - public void removeListener(MastershipListener listener) { - - } - - @Override - public RoleInfo getNodesFor(DeviceId deviceId) { - return new RoleInfo(new NodeId("foo"), Collections.<NodeId>emptyList()); - } - } - - - private class TestLinkService extends LinkServiceAdapter { - } -} diff --git a/framework/src/onos/providers/netconf/app/app.xml b/framework/src/onos/providers/netconf/app/app.xml index f2d47627..d920d240 100644 --- a/framework/src/onos/providers/netconf/app/app.xml +++ b/framework/src/onos/providers/netconf/app/app.xml @@ -19,6 +19,13 @@ features="${project.artifactId}"> <description>${project.description}</description> + <artifact>mvn:${project.groupId}/onos-netconf-rfc/${project.version}</artifact> + <artifact>mvn:${project.groupId}/onos-netconf-api/${project.version}</artifact> + <artifact>mvn:${project.groupId}/onos-netconf-ctl/${project.version}</artifact> + <artifact>mvn:${project.groupId}/onos-drivers/${project.version}</artifact> + <artifact>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</artifact> + + <!--<artifact>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</artifact>--> <!-- Question: should there be the jnc stuff here? Or is it just for testing --> </app> diff --git a/framework/src/onos/providers/netconf/app/features.xml b/framework/src/onos/providers/netconf/app/features.xml index bc7491e6..ef0fb738 100644 --- a/framework/src/onos/providers/netconf/app/features.xml +++ b/framework/src/onos/providers/netconf/app/features.xml @@ -20,6 +20,9 @@ description="${project.description}"> <feature>onos-api</feature> <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> + <bundle>mvn:${project.groupId}/onos-netconf-api/${project.version}</bundle> + <bundle>mvn:${project.groupId}/onos-netconf-ctl/${project.version}</bundle> + <bundle>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</bundle> <!-- Question: should there be the jnc stuff here? Or is it just for testing --> </feature> diff --git a/framework/src/onos/providers/netconf/device/pom.xml b/framework/src/onos/providers/netconf/device/pom.xml index 3465bc3a..15ad475a 100644 --- a/framework/src/onos/providers/netconf/device/pom.xml +++ b/framework/src/onos/providers/netconf/device/pom.xml @@ -33,129 +33,29 @@ <dependencies> <dependency> - <groupId>org.osgi</groupId> - <artifactId>org.osgi.compendium</artifactId> - </dependency> - <dependency> - <groupId>ch.ethz.ganymed</groupId> - <artifactId>ganymed-ssh2</artifactId> - <version>262</version> - </dependency> - <dependency> - <!-- TODO: change this appropriately when the official TailF JNC is available --> <groupId>org.onosproject</groupId> - <artifactId>jnc</artifactId> - <version>1.0</version> - </dependency> - <dependency> - <groupId>org.jdom</groupId> - <artifactId>jdom2</artifactId> - <version>2.0.5</version> - </dependency> - <dependency> - <groupId>jaxen</groupId> - <artifactId>jaxen</artifactId> - <version>1.1.4</version> - <optional>true</optional> - </dependency> - <dependency> - <groupId>org.osgi</groupId> - <artifactId>org.osgi.core</artifactId> + <artifactId>onlab-junit</artifactId> + <scope>test</scope> </dependency> <dependency> <groupId>org.onosproject</groupId> - <artifactId>onlab-junit</artifactId> - <scope>test</scope> + <artifactId>onos-netconf-api</artifactId> + <version>${project.version}</version> </dependency> <dependency> - <groupId>org.easymock</groupId> - <artifactId>easymock</artifactId> - <scope>test</scope> + <groupId>org.onosproject</groupId> + <artifactId>onos-netconf-ctl</artifactId> + <version>${project.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <version>2.3</version> - <configuration> - <filters> - <filter> - <artifact>com.tailf:JNC</artifact> - <includes> - <include>com/tailf/jnc/**</include> - </includes> - </filter> - <filter> - <artifact>ch.ethz.ganymed:ganymed-ssh2</artifact> - <includes> - <include>ch/ethz/ssh2/**</include> - </includes> - </filter> - <filter> - <artifact>org.jdom:jdom2</artifact> - <includes> - <include>org/jdom2/**</include> - </includes> - </filter> - </filters> - </configuration> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - </execution> - </executions> - </plugin> - <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-scr-plugin</artifactId> </plugin> <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-bundle-plugin</artifactId> - <configuration> - <instructions> - <Export-Package> - com.tailf.jnc, - ch.ethz.ssh2, - ch.ethz.ssh2.auth, - ch.ethz.ssh2.channel, - ch.ethz.ssh2.crypto, - ch.ethz.ssh2.crypto.cipher, - ch.ethz.ssh2.crypto.dh, - ch.ethz.ssh2.crypto.digest, - ch.ethz.ssh2.log, - ch.ethz.ssh2.packets, - ch.ethz.ssh2.server, - ch.ethz.ssh2.sftp, - ch.ethz.ssh2.signature, - ch.ethz.ssh2.transport, - ch.ethz.ssh2.util, - org.jdom2, - org.jdom2.input, - org.jdom2.output, - org.jdom2.adapters, - org.jdom2.filter, - org.jdom2.internal, - org.jdom2.located, - org.jdom2.transform, - org.jdom2.util, - org.jdom2.xpath, - org.jdom2.input.sax, - org.jdom2.input.stax, - org.jdom2.output.support, - org.jdom2.xpath.jaxen, - org.jdom2.xpath.util - </Export-Package> - </instructions> - </configuration> - </plugin> - <plugin> <groupId>org.onosproject</groupId> <artifactId>onos-maven-plugin</artifactId> </plugin> diff --git a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDevice.java b/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDevice.java deleted file mode 100644 index b3d26b06..00000000 --- a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDevice.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.netconf.device.impl; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.onlab.util.Tools.delay; -import static org.slf4j.LoggerFactory.getLogger; - -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -import org.jdom2.Document; -import org.jdom2.Element; -import org.jdom2.input.SAXBuilder; -import org.jdom2.output.Format; -import org.jdom2.output.XMLOutputter; -import org.slf4j.Logger; - -import com.tailf.jnc.Capabilities; -import com.tailf.jnc.JNCException; -import com.tailf.jnc.SSHConnection; -import com.tailf.jnc.SSHSession; - -/** - * This is a logical representation of actual NETCONF device, carrying all the - * necessary information to connect and execute NETCONF operations. - */ -public class NetconfDevice { - private final Logger log = getLogger(NetconfDevice.class); - - /** - * The Device State is used to determine whether the device is active or - * inactive. This state infomation will help Device Creator to add or delete - * the device from the core. - */ - public static enum DeviceState { - /* Used to specify Active state of the device */ - ACTIVE, - /* Used to specify inactive state of the device */ - INACTIVE, - /* Used to specify invalid state of the device */ - INVALID - } - - private static final int DEFAULT_SSH_PORT = 22; - private static final int DEFAULT_CON_TIMEOUT = 0; - private static final String XML_CAPABILITY_KEY = "capability"; - private static final int EVENTINTERVAL = 2000; - private static final int CONNECTION_CHECK_INTERVAL = 3; - private static final String INPUT_HELLO_XML_MSG = new StringBuilder( - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>") - .append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">") - .append("<capabilities><capability>urn:ietf:params:netconf:base:1.0</capability>") - .append("</capabilities></hello>").toString(); - - private String sshHost; - private int sshPort = DEFAULT_SSH_PORT; - private int connectTimeout = DEFAULT_CON_TIMEOUT; - private String username; - private String password; - private boolean reachable = false; - - private List<String> capabilities = new ArrayList<String>(); - private SSHConnection sshConnection = null; - - private DeviceState deviceState = DeviceState.INVALID; - - protected NetconfDevice(String sshHost, int sshPort, String username, - String password) { - this.username = checkNotNull(username, - "Netconf Username Cannot be null"); - this.sshHost = checkNotNull(sshHost, "Netconf Device IP cannot be null"); - this.sshPort = checkNotNull(sshPort, - "Netconf Device SSH port cannot be null"); - this.password = password; - } - - /** - * This will try to connect to NETCONF device and find all the capabilities. - * - * @throws Exception if unable to connect to the device - */ - // FIXME: this should not be a generic Exception; perhaps wrap in some RuntimeException - public void init() throws Exception { - try { - if (sshConnection == null) { - sshConnection = new SSHConnection(sshHost, sshPort, connectTimeout); - sshConnection.authenticateWithPassword(username, password); - } - // Send hello message to retrieve capabilities. - } catch (IOException e) { - log.error("Fatal Error while creating connection to the device: " - + deviceInfo(), e); - throw e; - } catch (JNCException e) { - log.error("Failed to connect to the device: " + deviceInfo(), e); - throw e; - } - - hello(); - } - - private void hello() { - SSHSession ssh = null; - try { - ssh = new SSHSession(sshConnection); - String helloRequestXML = INPUT_HELLO_XML_MSG.trim(); - - log.debug("++++++++++++++++++++++++++++++++++Sending Hello: " - + sshConnection.getGanymedConnection().getHostname() - + "++++++++++++++++++++++++++++++++++"); - printPrettyXML(helloRequestXML); - ssh.print(helloRequestXML); - // ssh.print(endCharSeq); - ssh.flush(); - String xmlResponse = null; - int i = CONNECTION_CHECK_INTERVAL; - while (!ssh.ready() && i > 0) { - delay(EVENTINTERVAL); - i--; - } - - if (ssh.ready()) { - StringBuffer readOne = ssh.readOne(); - if (readOne == null) { - log.error("The Hello Contains No Capabilites"); - throw new JNCException( - JNCException.SESSION_ERROR, - "server does not support NETCONF base capability: " - + Capabilities.NETCONF_BASE_CAPABILITY); - } else { - xmlResponse = readOne.toString().trim(); - - log.debug("++++++++++++++++++++++++++++++++++Reading Capabilities: " - + sshConnection.getGanymedConnection() - .getHostname() - + "++++++++++++++++++++++++++++++++++"); - - printPrettyXML(xmlResponse); - processCapabilities(xmlResponse); - } - } - reachable = true; - } catch (IOException e) { - log.error("Fatal Error while sending Hello Message to the device: " - + deviceInfo(), e); - } catch (JNCException e) { - log.error("Fatal Error while sending Hello Message to the device: " - + deviceInfo(), e); - } finally { - log.debug("Closing the session after successful execution"); - if (ssh != null) { - ssh.close(); - } - } - } - - private void processCapabilities(String xmlResponse) throws JNCException { - if (xmlResponse.isEmpty()) { - log.error("The capability response cannot be empty"); - throw new JNCException( - JNCException.SESSION_ERROR, - "server does not support NETCONF base capability: " - + Capabilities.NETCONF_BASE_CAPABILITY); - } - try { - Document doc = new SAXBuilder() - .build(new StringReader(xmlResponse)); - Element rootElement = doc.getRootElement(); - processCapabilities(rootElement); - } catch (Exception e) { - log.error("ERROR while parsing the XML " + xmlResponse); - } - } - - private void processCapabilities(Element rootElement) { - List<Element> children = rootElement.getChildren(); - if (children.isEmpty()) { - return; - } - for (Element child : children) { - - if (child.getName().equals(XML_CAPABILITY_KEY)) { - capabilities.add(child.getValue()); - } - if (!child.getChildren().isEmpty()) { - processCapabilities(child); - } - } - } - - private void printPrettyXML(String xmlstring) { - try { - Document doc = new SAXBuilder().build(new StringReader(xmlstring)); - XMLOutputter xmOut = new XMLOutputter(Format.getPrettyFormat()); - String outputString = xmOut.outputString(doc); - log.debug(outputString); - } catch (Exception e) { - log.error("ERROR while parsing the XML " + xmlstring, e); - - } - } - - /** - * This would return host IP and host Port, used by this particular Netconf - * Device. - * @return Device Information. - */ - public String deviceInfo() { - return new StringBuilder("host: ").append(sshHost).append(". port: ") - .append(sshPort).toString(); - } - - /** - * This will terminate the device connection. - */ - public void disconnect() { - sshConnection.close(); - reachable = false; - } - - /** - * This will list down all the capabilities supported on the device. - * @return Capability list. - */ - public List<String> getCapabilities() { - return capabilities; - } - - /** - * This api is intended to know whether the device is connected or not. - * @return true if connected - */ - public boolean isReachable() { - return reachable; - } - - /** - * This will return the IP used connect ssh on the device. - * @return Netconf Device IP - */ - public String getSshHost() { - return sshHost; - } - - /** - * This will return the SSH Port used connect the device. - * @return SSH Port number - */ - public int getSshPort() { - return sshPort; - } - - /** - * The usename used to connect Netconf Device. - * @return Device Username - */ - public String getUsername() { - return username; - } - - /** - * Retrieve current state of the device. - * @return Current Device State - */ - public DeviceState getDeviceState() { - return deviceState; - } - - /** - * This is set the state information for the device. - * @param deviceState Next Device State - */ - public void setDeviceState(DeviceState deviceState) { - this.deviceState = deviceState; - } - - /** - * Check whether the device is in Active state. - * @return true if the device is Active - */ - public boolean isActive() { - return deviceState == DeviceState.ACTIVE ? true : false; - } - - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - } -} diff --git a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java b/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java index f9194a7e..d12c6474 100644 --- a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java +++ b/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java @@ -13,39 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.provider.netconf.device.impl; - -import static com.google.common.base.Strings.isNullOrEmpty; -import static org.onlab.util.Tools.delay; -import static org.onlab.util.Tools.get; -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; -import java.io.IOException; -import java.net.SocketTimeoutException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Dictionary; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +package org.onosproject.provider.netconf.device.impl; +import com.google.common.base.Preconditions; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Modified; -import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.onlab.packet.ChassisId; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.cluster.ClusterService; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.incubator.net.config.basics.ConfigException; +import org.onosproject.net.DefaultAnnotations; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.MastershipRole; +import org.onosproject.net.SparseAnnotations; +import org.onosproject.net.config.ConfigFactory; +import org.onosproject.net.config.NetworkConfigEvent; +import org.onosproject.net.config.NetworkConfigListener; +import org.onosproject.net.config.NetworkConfigRegistry; import org.onosproject.net.device.DefaultDeviceDescription; import org.onosproject.net.device.DeviceDescription; import org.onosproject.net.device.DeviceProvider; @@ -54,305 +43,180 @@ import org.onosproject.net.device.DeviceProviderService; import org.onosproject.net.device.DeviceService; import org.onosproject.net.provider.AbstractProvider; import org.onosproject.net.provider.ProviderId; -import org.onosproject.provider.netconf.device.impl.NetconfDevice.DeviceState; -import org.osgi.service.component.ComponentContext; +import org.onosproject.netconf.NetconfController; +import org.onosproject.netconf.NetconfDevice; +import org.onosproject.netconf.NetconfDeviceInfo; +import org.onosproject.netconf.NetconfDeviceListener; import org.slf4j.Logger; +import java.util.Map; + +import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; +import static org.slf4j.LoggerFactory.getLogger; + /** - * Provider which will try to fetch the details of NETCONF devices from the core - * and run a capability discovery on each of the device. + * Provider which uses an NETCONF controller to detect device. */ @Component(immediate = true) public class NetconfDeviceProvider extends AbstractProvider implements DeviceProvider { - - private final Logger log = getLogger(NetconfDeviceProvider.class); - - protected Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>(); - - private DeviceProviderService providerService; + private final Logger log = getLogger(getClass()); @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceProviderRegistry providerRegistry; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceService deviceService; - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; + protected NetconfController controller; //where is initiated ? @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ComponentConfigService cfgService; - - private ExecutorService deviceBuilder = Executors - .newFixedThreadPool(1, groupedThreads("onos/netconf", "device-creator")); + protected NetworkConfigRegistry cfgService; - // Delay between events in ms. - private static final int EVENTINTERVAL = 5; - - private static final String SCHEME = "netconf"; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; - @Property(name = "devConfigs", value = "", label = "Instance-specific configurations") - private String devConfigs = null; - @Property(name = "devPasswords", value = "", label = "Instance-specific password") - private String devPasswords = null; + private DeviceProviderService providerService; + private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener(); + protected static final String ISNOTNULL = "NetconfDeviceInfo is not null"; + private static final String UNKNOWN = "unknown"; + + private final ConfigFactory factory = + new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY, + NetconfProviderConfig.class, + "devices", + true) { + @Override + public NetconfProviderConfig createConfig() { + return new NetconfProviderConfig(); + } + }; + private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener(); + private ApplicationId appId; - /** - * Creates a provider with the supplier identifier. - */ - public NetconfDeviceProvider() { - super(new ProviderId("netconf", "org.onosproject.provider.netconf")); - } @Activate - public void activate(ComponentContext context) { - cfgService.registerProperties(getClass()); + public void activate() { providerService = providerRegistry.register(this); - modified(context); + cfgService.registerConfigFactory(factory); + cfgService.addListener(cfgLister); + controller.addDeviceListener(innerNodeListener); + connectExistingDevices(); log.info("Started"); } + @Deactivate - public void deactivate(ComponentContext context) { - cfgService.unregisterProperties(getClass(), false); - try { - for (Entry<DeviceId, NetconfDevice> deviceEntry : netconfDeviceMap - .entrySet()) { - deviceBuilder.submit(new DeviceCreator(deviceEntry.getValue(), - false)); - } - deviceBuilder.awaitTermination(1000, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - log.error("Device builder did not terminate"); - } - deviceBuilder.shutdownNow(); - netconfDeviceMap.clear(); + public void deactivate() { providerRegistry.unregister(this); providerService = null; + cfgService.unregisterConfigFactory(factory); log.info("Stopped"); } - @Modified - public void modified(ComponentContext context) { - if (context == null) { - log.info("No configuration file"); - return; - } - Dictionary<?, ?> properties = context.getProperties(); - String deviceCfgValue = get(properties, "devConfigs"); - log.info("Settings: devConfigs={}", deviceCfgValue); - if (!isNullOrEmpty(deviceCfgValue)) { - addOrRemoveDevicesConfig(deviceCfgValue); - } - } - - private void addOrRemoveDevicesConfig(String deviceConfig) { - for (String deviceEntry : deviceConfig.split(",")) { - NetconfDevice device = processDeviceEntry(deviceEntry); - if (device != null) { - log.info("Device Detail: username: {}, host={}, port={}, state={}", - device.getUsername(), device.getSshHost(), - device.getSshPort(), device.getDeviceState().name()); - if (device.isActive()) { - deviceBuilder.submit(new DeviceCreator(device, true)); - } else { - deviceBuilder.submit(new DeviceCreator(device, false)); - } - } - } - } - - private NetconfDevice processDeviceEntry(String deviceEntry) { - if (deviceEntry == null) { - log.info("No content for Device Entry, so cannot proceed further."); - return null; - } - log.info("Trying to convert Device Entry String: " + deviceEntry - + " to a Netconf Device Object"); - NetconfDevice device = null; - try { - String userInfo = deviceEntry.substring(0, deviceEntry - .lastIndexOf('@')); - String hostInfo = deviceEntry.substring(deviceEntry - .lastIndexOf('@') + 1); - String[] infoSplit = userInfo.split(":"); - String username = infoSplit[0]; - String password = infoSplit[1]; - infoSplit = hostInfo.split(":"); - String hostIp = infoSplit[0]; - Integer hostPort; - try { - hostPort = Integer.parseInt(infoSplit[1]); - } catch (NumberFormatException nfe) { - log.error("Bad Configuration Data: Failed to parse host port number string: " - + infoSplit[1]); - throw nfe; - } - String deviceState = infoSplit[2]; - if (isNullOrEmpty(username) || isNullOrEmpty(password) - || isNullOrEmpty(hostIp) || hostPort == 0) { - log.warn("Bad Configuration Data: both user and device information parts of Configuration " - + deviceEntry + " should be non-nullable"); - } else { - device = new NetconfDevice(hostIp, hostPort, username, password); - if (!isNullOrEmpty(deviceState)) { - if (deviceState.toUpperCase().equals(DeviceState.ACTIVE - .name())) { - device.setDeviceState(DeviceState.ACTIVE); - } else if (deviceState.toUpperCase() - .equals(DeviceState.INACTIVE.name())) { - device.setDeviceState(DeviceState.INACTIVE); - } else { - log.warn("Device State Information can not be empty, so marking the state as INVALID"); - device.setDeviceState(DeviceState.INVALID); - } - } else { - log.warn("The device entry do not specify state information, so marking the state as INVALID"); - device.setDeviceState(DeviceState.INVALID); - } - } - } catch (ArrayIndexOutOfBoundsException aie) { - log.error("Error while reading config infromation from the config file: " - + "The user, host and device state infomation should be " - + "in the order 'userInfo@hostInfo:deviceState'" - + deviceEntry, aie); - } catch (Exception e) { - log.error("Error while parsing config information for the device entry: " - + deviceEntry, e); - } - return device; + public NetconfDeviceProvider() { + super(new ProviderId("netconf", "org.onosproject.netconf.provider.device")); } @Override public void triggerProbe(DeviceId deviceId) { - // TODO Auto-generated method stub + // TODO: This will be implemented later. + log.info("Triggering probe on device {}", deviceId); } @Override public void roleChanged(DeviceId deviceId, MastershipRole newRole) { - + // TODO: This will be implemented later. } @Override public boolean isReachable(DeviceId deviceId) { - NetconfDevice netconfDevice = netconfDeviceMap.get(deviceId); + Map<DeviceId, NetconfDevice> devices = controller.getDevicesMap(); + + NetconfDevice netconfDevice = null; + for (DeviceId key : devices.keySet()) { + if (key.equals(deviceId)) { + netconfDevice = controller.getDevicesMap().get(key); + } + } if (netconfDevice == null) { log.warn("BAD REQUEST: the requested device id: " - + deviceId.toString() - + " is not associated to any NETCONF Device"); + + deviceId.toString() + + " is not associated to any NETCONF Device"); return false; } - return netconfDevice.isReachable(); + return netconfDevice.isActive(); } - /** - * This class is intended to add or remove Configured Netconf Devices. - * Functionality relies on 'createFlag' and 'NetconfDevice' content. The - * functionality runs as a thread and dependening on the 'createFlag' value - * it will create or remove Device entry from the core. - */ - private class DeviceCreator implements Runnable { + private class InnerNetconfDeviceListener implements NetconfDeviceListener { - private NetconfDevice device; - private boolean createFlag; + @Override + public void deviceAdded(NetconfDeviceInfo nodeId) { + Preconditions.checkNotNull(nodeId, ISNOTNULL); + DeviceId deviceId = nodeId.getDeviceId(); + //TODO filter for not netconf devices + //Netconf configuration object + ChassisId cid = new ChassisId(); + String ipAddress = nodeId.ip().toString(); + SparseAnnotations annotations = DefaultAnnotations.builder() + .set("ipaddress", ipAddress).build(); + DeviceDescription deviceDescription = new DefaultDeviceDescription( + deviceId.uri(), + Device.Type.SWITCH, + UNKNOWN, UNKNOWN, + UNKNOWN, UNKNOWN, + cid, + annotations); + providerService.deviceConnected(deviceId, deviceDescription); - public DeviceCreator(NetconfDevice device, boolean createFlag) { - this.device = device; - this.createFlag = createFlag; } @Override - public void run() { - if (createFlag) { - log.info("Trying to create Device Info on ONOS core"); - advertiseDevices(); - } else { - log.info("Trying to remove Device Info on ONOS core"); - removeDevices(); - } + public void deviceRemoved(NetconfDeviceInfo nodeId) { + Preconditions.checkNotNull(nodeId, ISNOTNULL); + DeviceId deviceId = nodeId.getDeviceId(); + providerService.deviceDisconnected(deviceId); + } + } - /** - * For each Netconf Device, remove the entry from the device store. - */ - private void removeDevices() { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } + private void connectExistingDevices() { + //TODO consolidate + appId = coreService.registerApplication("org.onosproject.netconf"); + connectDevices(); + } + + private void connectDevices() { + NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class); + if (cfg != null) { + log.info("cfg {}", cfg); try { - DeviceId did = getDeviceId(); - if (!netconfDeviceMap.containsKey(did)) { - log.error("BAD Request: 'Currently device is not discovered, " - + "so cannot remove/disconnect the device: " - + device.deviceInfo() + "'"); - return; - } - providerService.deviceDisconnected(did); - device.disconnect(); - netconfDeviceMap.remove(did); - delay(EVENTINTERVAL); - } catch (URISyntaxException uriSyntaxExcpetion) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't remove the device from the store", - uriSyntaxExcpetion); + cfg.getDevicesAddresses().stream().forEach(addr -> controller + .connectDevice(new NetconfDeviceInfo(addr.name(), + addr.password(), + addr.ip(), + addr.port()))); + } catch (ConfigException e) { + log.error("Cannot read config error " + e); } } + } - /** - * Initialize Netconf Device object, and notify core saying device - * connected. - */ - private void advertiseDevices() { - try { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } - device.init(); - DeviceId did = getDeviceId(); - ChassisId cid = new ChassisId(); - DeviceDescription desc = new DefaultDeviceDescription( - did.uri(), - Device.Type.OTHER, - "", "", - "", "", - cid); - log.info("Persisting Device" + did.uri().toString()); - - netconfDeviceMap.put(did, device); - providerService.deviceConnected(did, desc); - log.info("Done with Device Info Creation on ONOS core. Device Info: " - + device.deviceInfo() + " " + did.uri().toString()); - delay(EVENTINTERVAL); - } catch (URISyntaxException e) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't persist the device onto the store", e); - } catch (SocketTimeoutException e) { - log.error("Error while setting connection for the device: " - + device.deviceInfo(), e); - } catch (IOException e) { - log.error("Error while setting connection for the device: " - + device.deviceInfo(), e); - } catch (Exception e) { - log.error("Error while initializing session for the device: " - + (device != null ? device.deviceInfo() : null), e); - } + private class InternalNetworkConfigListener implements NetworkConfigListener { + + + @Override + public void event(NetworkConfigEvent event) { + connectDevices(); } - /** - * This will build a device id for the device. - */ - private DeviceId getDeviceId() throws URISyntaxException { - String additionalSSP = new StringBuilder(device.getUsername()) - .append("@").append(device.getSshHost()).append(":") - .append(device.getSshPort()).toString(); - DeviceId did = DeviceId.deviceId(new URI(SCHEME, additionalSSP, - null)); - return did; + @Override + public boolean isRelevant(NetworkConfigEvent event) { + //TODO refactor + return event.configClass().equals(NetconfProviderConfig.class) && + (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || + event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED); } } } diff --git a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java b/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java deleted file mode 100644 index e56c5959..00000000 --- a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.netconf.device.impl; - -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.junit.Assert.assertFalse; -import static org.onlab.util.Tools.delay; -import static org.onosproject.provider.netconf.device.impl.NetconfDeviceProviderTestConstant.*; -import static org.slf4j.LoggerFactory.getLogger; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collection; -import java.util.Dictionary; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.easymock.EasyMock; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.onlab.packet.ChassisId; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.device.DefaultDeviceDescription; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.DeviceProvider; -import org.onosproject.net.device.DeviceProviderRegistry; -import org.onosproject.net.device.DeviceProviderService; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.device.PortStatistics; -import org.onosproject.net.provider.ProviderId; -import org.osgi.service.component.ComponentContext; -import org.slf4j.Logger; - -import com.tailf.jnc.JNCException; - -/** - * Test Case to Validate Netconf Device Provider. - */ -public class NetconfDeviceProviderTest { - TestDeviceCreator create; - - private final Logger log = getLogger(NetconfDeviceProviderTest.class); - - private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>(); - - private DeviceProviderService providerService; - - private static final DeviceId DID1 = DeviceId.deviceId(DEVICE_ID); - - private final NetconfDeviceProvider provider = new NetconfDeviceProvider(); - private final TestDeviceRegistry registry = new TestDeviceRegistry(); - - private ComponentConfigService mockCfgService; - - @Before - public void setUp() { - mockCfgService = EasyMock.createMock(ComponentConfigService.class); - provider.cfgService = mockCfgService; - provider.providerRegistry = registry; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithoutValues(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)).andReturn(NULL); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithDeviceEntryNull(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)).andReturn(NULL_NULL); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockDeviceEntryNumberFomatEx(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_WITH_INVALID_ENTRY_NUMBER) - .andThrow(new NumberFormatException()); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithoutUsernameAndPassword(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)).andReturn(CONFIG_WITH_NULL_ENTRY); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithDifferentDeviceState(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_WITH_DIFFERENT_DEVICE_STATE); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockDeviceWithArrayOutOFBoundEx(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX) - .andThrow(new ArrayIndexOutOfBoundsException()); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockDeviceEntryForDeactivate(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_ENTRY_FOR_DEACTIVATE) - .andThrow(new ArrayIndexOutOfBoundsException()); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @Ignore - @Test(expected = IOException.class) - public void testSSHAuthentication() throws IOException, JNCException { - TestDeviceCreator objForTestDev = new TestDeviceCreator( - new NetconfDevice( - DEVICE_IP, - DEVICE_PORT, - DEVICE_USERNAME, - DEVICE_PASSWORD), - true); - objForTestDev.run(); - } - - @After - public void tearDown() { - provider.providerRegistry = null; - provider.cfgService = null; - } - - // To check if deviceCfgValue is empty or null - @Test - public void testActiveWithcomponentContextIsNull() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithoutValues(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - // To check deviceEntry and device is null - @Test - public void testActiveWithDeviceEntryIsNull() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithDeviceEntryNull(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithoutUsernameAndPassword() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithoutUsernameAndPassword(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithNumberFomatEx() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockDeviceEntryNumberFomatEx(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithDifferentDeviceState() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithDifferentDeviceState(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithArrayOutOFBoundEx() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockDeviceWithArrayOutOFBoundEx(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void isReachableWithInvalidDeviceId() { - assertFalse("Initially the Device ID Should not be reachable", - provider.isReachable(DID1)); - NetconfDevice device = new NetconfDevice(NULL, ZERO, NULL, NULL); - provider.netconfDeviceMap.put(DID1, device); - assertFalse("Particular Device ID cannot be Reachable", - provider.isReachable(DID1)); - } - - @Test - public void testDeactivate() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockDeviceEntryForDeactivate(componentContext); - replay(componentContext); - testActiveWithDeviceEntryWithDifferentDeviceState(); - provider.deactivate(componentContext); - } - - private class TestDeviceCreator { - - private NetconfDevice device; - private boolean createFlag; - - public TestDeviceCreator(NetconfDevice device, boolean createFlag) { - this.device = device; - this.createFlag = createFlag; - } - - public void run() throws JNCException, IOException { - if (createFlag) { - log.info("Trying to create Device Info on ONOS core"); - advertiseDevices(); - } else { - log.info("Trying to remove Device Info on ONOS core"); - removeDevices(); - } - } - - /** - * For each Netconf Device, remove the entry from the device store. - */ - private void removeDevices() { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } - try { - DeviceId did = getDeviceId(); - if (!netconfDeviceMap.containsKey(did)) { - log.error("BAD Request: 'Currently device is not discovered, " - + "so cannot remove/disconnect the device: " - + device.deviceInfo() + "'"); - return; - } - providerService.deviceDisconnected(did); - device.disconnect(); - netconfDeviceMap.remove(did); - delay(EVENTINTERVAL); - } catch (URISyntaxException uriSyntaxExcpetion) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't remove the device from the store", - uriSyntaxExcpetion); - } - } - - /** - * Initialize Netconf Device object, and notify core saying device - * connected. - */ - private void advertiseDevices() throws JNCException, IOException { - try { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } - device.init(); - DeviceId did = getDeviceId(); - ChassisId cid = new ChassisId(); - DeviceDescription desc = new DefaultDeviceDescription( - did.uri(), - Device.Type.OTHER, - NULL, - NULL, - NULL, - NULL, cid); - log.info("Persisting Device" + did.uri().toString()); - - netconfDeviceMap.put(did, device); - providerService.deviceConnected(did, desc); - log.info("Done with Device Info Creation on ONOS core. Device Info: " - + device.deviceInfo() + " " + did.uri().toString()); - delay(EVENTINTERVAL); - } catch (URISyntaxException e) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't persist the device onto the store", e); - } catch (JNCException e) { - throw e; - } catch (IOException e) { - throw e; - } catch (Exception e) { - log.error("Error while initializing session for the device: " - + device.deviceInfo(), e); - } - } - - private DeviceId getDeviceId() throws URISyntaxException { - String additionalSSP = new StringBuilder(device.getUsername()) - .append(AT_THE_RATE).append(device.getSshHost()) - .append(COLON).append(device.getSshPort()).toString(); - DeviceId did = DeviceId.deviceId(new URI(SCHEME_NETCONF, - additionalSSP, null)); - return did; - } - } - - private class TestDeviceRegistry implements DeviceProviderRegistry { - - @Override - public DeviceProviderService register(DeviceProvider provider) { - return new TestProviderService(); - } - - @Override - public void unregister(DeviceProvider provider) { - } - - @Override - public Set<ProviderId> getProviders() { - return null; - } - - private class TestProviderService implements DeviceProviderService { - - @Override - public DeviceProvider provider() { - return null; - } - - @Override - public void deviceConnected(DeviceId deviceId, - DeviceDescription deviceDescription) { - } - - @Override - public void deviceDisconnected(DeviceId deviceId) { - - } - - @Override - public void updatePorts(DeviceId deviceId, - List<PortDescription> portDescriptions) { - - } - - @Override - public void portStatusChanged(DeviceId deviceId, - PortDescription portDescription) { - - } - - @Override - public void receivedRoleReply(DeviceId deviceId, - MastershipRole requested, - MastershipRole response) { - - } - - @Override - public void updatePortStatistics(DeviceId deviceId, - Collection<PortStatistics> portStatistics) { - - } - } - } -} diff --git a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTestConstant.java b/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTestConstant.java deleted file mode 100644 index 1d848e26..00000000 --- a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTestConstant.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.provider.netconf.device.impl; - -public final class NetconfDeviceProviderTestConstant { - - private NetconfDeviceProviderTestConstant() { - } - - public static final int ZERO = 0; - public static final int EVENTINTERVAL = 5; - public static final String DEV_CONFIG = "devConfigs"; - public static final String CONFIG_WITH_INVALID_ENTRY_NUMBER = "cisco:cisco" - + "@10.18.11.14:cisco:active"; - public static final String CONFIG_WITH_NULL_ENTRY = "null:null@null:0:active"; - public static final String CONFIG_WITH_DIFFERENT_DEVICE_STATE = "cisco:cisco@10.18.11.14:22:active," - + "cisco:cisco@10.18.11.18:22:inactive,cisco:cisco@10.18.11.14:22:invalid," - + "cisco:cisco@10.18.11.14:22:null"; - public static final String CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX = "@10.18.11.14:22:active"; - public static final String CONFIG_ENTRY_FOR_DEACTIVATE = "netconf:cisco" - + "@10.18.11.14:22:active"; - public static final String DEVICE_IP = "10.18.14.19"; - public static final int DEVICE_PORT = 22; - public static final String DEVICE_USERNAME = "cisco"; - public static final String DEVICE_PASSWORD = "cisco"; - public static final String AT_THE_RATE = "@"; - public static final String COLON = ":"; - public static final String NULL = ""; - public static final String NULL_NULL = "null,null"; - public static final String SCHEME_NETCONF = "netconf"; - public static final String DEVICE_ID = "of:0000000000000001"; - -} diff --git a/framework/src/onos/providers/openflow/app/app.xml b/framework/src/onos/providers/openflow/app/app.xml deleted file mode 100644 index e54d1a8a..00000000 --- a/framework/src/onos/providers/openflow/app/app.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright 2015 Open Networking Laboratory - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<app name="org.onosproject.openflow" origin="ON.Lab" version="${project.version}" - featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features" - features="${project.artifactId}"> - <description>${project.description}</description> - - <artifact>mvn:${project.groupId}/onos-of-api/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-of-ctl/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-drivers/${project.version}</artifact> - - <artifact>mvn:${project.groupId}/onos-lldp-provider/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-host-provider/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-of-provider-device/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-of-provider-packet/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-of-provider-flow/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-of-provider-group/${project.version}</artifact> - <artifact>mvn:${project.groupId}/onos-of-provider-meter/${project.version}</artifact> -</app> diff --git a/framework/src/onos/providers/openflow/app/features.xml b/framework/src/onos/providers/openflow/app/features.xml deleted file mode 100644 index 9dbae8af..00000000 --- a/framework/src/onos/providers/openflow/app/features.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<!-- - ~ Copyright 2015 Open Networking Laboratory - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}"> - <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository> - <feature name="${project.artifactId}" version="${project.version}" - description="${project.description}"> - <feature>onos-api</feature> - <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> - <bundle>mvn:${project.groupId}/onos-of-api/${project.version}</bundle> - <bundle>mvn:${project.groupId}/onos-of-ctl/${project.version}</bundle> - - <bundle>mvn:${project.groupId}/onos-lldp-provider/${project.version}</bundle> - <bundle>mvn:${project.groupId}/onos-host-provider/${project.version}</bundle> - <bundle>mvn:${project.groupId}/onos-of-provider-device/${project.version}</bundle> - <bundle>mvn:${project.groupId}/onos-of-provider-packet/${project.version}</bundle> - <bundle>mvn:${project.groupId}/onos-of-provider-flow/${project.version}</bundle> - <bundle>mvn:${project.groupId}/onos-of-provider-group/${project.version}</bundle> - <bundle>mvn:${project.groupId}/onos-of-provider-meter/${project.version}</bundle> - </feature> -</features> diff --git a/framework/src/onos/providers/openflow/app/pom.xml b/framework/src/onos/providers/openflow/app/pom.xml index cb55463b..ac5f6eee 100644 --- a/framework/src/onos/providers/openflow/app/pom.xml +++ b/framework/src/onos/providers/openflow/app/pom.xml @@ -27,55 +27,23 @@ </parent> <artifactId>onos-openflow</artifactId> - <packaging>pom</packaging> + <packaging>bundle</packaging> - <description>OpenFlow protocol southbound providers</description> + <properties> + <onos.app.name>org.onosproject.openflow</onos.app.name> + <onos.app.requires> + org.onosproject.openflow-base, + org.onosproject.hostprovider, + org.onosproject.lldpprovider + </onos.app.requires> + </properties> + + <description>OpenFlow southbound meta application</description> <dependencies> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-of-api</artifactId> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-of-ctl</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-drivers</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-of-provider-device</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-of-provider-packet</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-of-provider-flow</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-of-provider-group</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-lldp-provider</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.onosproject</groupId> - <artifactId>onos-host-provider</artifactId> - <version>${project.version}</version> - </dependency> + <dependency> + <groupId>org.onosproject</groupId> + <artifactId>onos-of-api</artifactId> + </dependency> </dependencies> - </project> diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java index c591f47d..f4ab0173 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java @@ -707,10 +707,13 @@ public class FlowEntryBuilder { long tunnelId = match.get(MatchField.TUNNEL_ID).getValue(); builder.matchTunnelId(tunnelId); break; + case ARP_THA: + mac = MacAddress.valueOf(match.get(MatchField.ARP_THA).getLong()); + builder.matchArpTha(mac); + break; case ARP_OP: case ARP_SHA: case ARP_SPA: - case ARP_THA: case ARP_TPA: case MPLS_TC: default: diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java index 010d7e7c..2e5be654 100644 --- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java +++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java @@ -24,6 +24,7 @@ import org.onosproject.net.OchSignal; import org.onosproject.net.driver.DriverService; import org.onosproject.net.flow.FlowRule; import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.criteria.ArpHaCriterion; import org.onosproject.net.flow.criteria.Criterion; import org.onosproject.net.flow.criteria.EthCriterion; import org.onosproject.net.flow.criteria.EthTypeCriterion; @@ -178,6 +179,7 @@ public abstract class FlowModBuilder { UdpPortCriterion udpPortCriterion; SctpPortCriterion sctpPortCriterion; IPv6NDLinkLayerAddressCriterion llAddressCriterion; + ArpHaCriterion arpHaCriterion; for (Criterion c : selector.criteria()) { switch (c.type()) { @@ -415,10 +417,14 @@ public abstract class FlowModBuilder { mplsBos.mplsBos() ? OFBooleanValue.TRUE : OFBooleanValue.FALSE); break; + case ARP_THA: + arpHaCriterion = (ArpHaCriterion) c; + mBuilder.setExact(MatchField.ARP_THA, + MacAddress.of(arpHaCriterion.mac().toLong())); + break; case ARP_OP: case ARP_SHA: case ARP_SPA: - case ARP_THA: case ARP_TPA: case MPLS_TC: case PBB_ISID: diff --git a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java index d5804f44..c91616df 100644 --- a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java +++ b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java @@ -15,11 +15,25 @@ */ package org.onosproject.provider.of.group.impl; +import static org.slf4j.LoggerFactory.getLogger; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip6Address; import org.onosproject.core.GroupId; +import org.onosproject.net.DeviceId; import org.onosproject.net.PortNumber; +import org.onosproject.net.driver.DefaultDriverData; +import org.onosproject.net.driver.DefaultDriverHandler; +import org.onosproject.net.driver.Driver; +import org.onosproject.net.driver.DriverService; import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flow.instructions.ExtensionInstruction; import org.onosproject.net.flow.instructions.Instruction; import org.onosproject.net.flow.instructions.Instructions; import org.onosproject.net.flow.instructions.L0ModificationInstruction; @@ -28,6 +42,7 @@ import org.onosproject.net.flow.instructions.L3ModificationInstruction; import org.onosproject.net.group.GroupBucket; import org.onosproject.net.group.GroupBuckets; import org.onosproject.net.group.GroupDescription; +import org.onosproject.openflow.controller.ExtensionInterpreter; import org.projectfloodlight.openflow.protocol.OFBucket; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.OFGroupAdd; @@ -52,14 +67,6 @@ import org.projectfloodlight.openflow.types.U32; import org.projectfloodlight.openflow.types.VlanPcp; import org.slf4j.Logger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Optional; - -import static org.slf4j.LoggerFactory.getLogger; - /* * Builder for GroupMod. */ @@ -70,6 +77,7 @@ public final class GroupModBuilder { private GroupDescription.Type type; private OFFactory factory; private Long xid; + private Optional<DriverService> driverService; private final Logger log = getLogger(getClass()); @@ -85,6 +93,16 @@ public final class GroupModBuilder { this.xid = xid.orElse((long) 0); } + private GroupModBuilder(GroupBuckets buckets, GroupId groupId, + GroupDescription.Type type, OFFactory factory, + Optional<Long> xid, Optional<DriverService> driverService) { + this.buckets = buckets; + this.groupId = groupId; + this.type = type; + this.factory = factory; + this.xid = xid.orElse((long) 0); + this.driverService = driverService; + } /** * Creates a builder for GroupMod. * @@ -103,6 +121,24 @@ public final class GroupModBuilder { } /** + * Creates a builder for GroupMod. + * + * @param buckets GroupBuckets object + * @param groupId Group Id to create + * @param type Group type + * @param factory OFFactory object + * @param xid transaction ID + * @param driverService driver Service + * @return GroupModBuilder object + */ + public static GroupModBuilder builder(GroupBuckets buckets, GroupId groupId, + GroupDescription.Type type, OFFactory factory, + Optional<Long> xid, Optional<DriverService> driverService) { + + return new GroupModBuilder(buckets, groupId, type, factory, xid, driverService); + } + + /** * Builds the GroupAdd OF message. * * @return GroupAdd OF message @@ -118,8 +154,17 @@ public final class GroupModBuilder { if (type == GroupDescription.Type.SELECT) { bucketBuilder.setWeight(1); } - bucketBuilder.setWatchGroup(OFGroup.ANY); - bucketBuilder.setWatchPort(OFPort.ANY); + + if (type == GroupDescription.Type.FAILOVER && bucket.watchPort() != null) { + bucketBuilder.setWatchPort(OFPort.of((int) bucket.watchPort().toLong())); + } else { + bucketBuilder.setWatchPort(OFPort.ANY); + } + if (type == GroupDescription.Type.FAILOVER && bucket.watchGroup() != null) { + bucketBuilder.setWatchGroup(OFGroup.of(bucket.watchGroup().id())); + } else { + bucketBuilder.setWatchGroup(OFGroup.ANY); + } OFBucket ofBucket = bucketBuilder.build(); ofBuckets.add(ofBucket); } @@ -218,6 +263,12 @@ public final class GroupModBuilder { .setGroup(OFGroup.of(grp.groupId().id())); actions.add(actgrp.build()); break; + case EXTENSION: + Instructions.ExtensionInstructionWrapper wrapper = + (Instructions.ExtensionInstructionWrapper) i; + actions.add(buildExtensionAction( + wrapper.extensionInstruction(), wrapper.deviceId())); + break; default: log.warn("Instruction type {} not yet implemented.", i.type()); } @@ -372,5 +423,21 @@ public final class GroupModBuilder { } return null; } + + private OFAction buildExtensionAction(ExtensionInstruction i, DeviceId deviceId) { + if (!driverService.isPresent()) { + log.error("No driver service present"); + return null; + } + Driver driver = driverService.get().getDriver(deviceId); + if (driver.hasBehaviour(ExtensionInterpreter.class)) { + DefaultDriverHandler handler = + new DefaultDriverHandler(new DefaultDriverData(driver, deviceId)); + ExtensionInterpreter interpreter = handler.behaviour(ExtensionInterpreter.class); + return interpreter.mapInstruction(factory, i); + } + + return null; + } } diff --git a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java index 5783c842..e69fd6b9 100644 --- a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java +++ b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java @@ -16,7 +16,12 @@ package org.onosproject.provider.of.group.impl; -import com.google.common.collect.Maps; +import static org.slf4j.LoggerFactory.getLogger; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; @@ -26,6 +31,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; import org.onosproject.core.DefaultGroupId; import org.onosproject.core.GroupId; import org.onosproject.net.DeviceId; +import org.onosproject.net.driver.DriverService; import org.onosproject.net.group.DefaultGroup; import org.onosproject.net.group.Group; import org.onosproject.net.group.GroupBuckets; @@ -60,12 +66,7 @@ import org.projectfloodlight.openflow.protocol.OFStatsType; import org.projectfloodlight.openflow.protocol.OFVersion; import org.slf4j.Logger; -import java.util.Collection; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; - -import static org.slf4j.LoggerFactory.getLogger; +import com.google.common.collect.Maps; /** * Provider which uses an OpenFlow controller to handle Group. @@ -81,6 +82,9 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected GroupProviderRegistry providerRegistry; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DriverService driverService; + private GroupProviderService providerService; static final int POLL_INTERVAL = 10; @@ -139,12 +143,21 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv return; } final Long groupModXid = XID_COUNTER.getAndIncrement(); - GroupModBuilder builder = - GroupModBuilder.builder(groupOperation.buckets(), - groupOperation.groupId(), - groupOperation.groupType(), - sw.factory(), - Optional.of(groupModXid)); + GroupModBuilder builder = null; + if (driverService == null) { + builder = GroupModBuilder.builder(groupOperation.buckets(), + groupOperation.groupId(), + groupOperation.groupType(), + sw.factory(), + Optional.of(groupModXid)); + } else { + builder = GroupModBuilder.builder(groupOperation.buckets(), + groupOperation.groupId(), + groupOperation.groupType(), + sw.factory(), + Optional.of(groupModXid), + Optional.of(driverService)); + } OFGroupMod groupMod = null; switch (groupOperation.opType()) { case ADD: @@ -158,6 +171,7 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv break; default: log.error("Unsupported Group operation"); + return; } sw.sendMsg(groupMod); GroupId groudId = new DefaultGroupId(groupMod.getGroup().getGroupNumber()); diff --git a/framework/src/onos/providers/openflow/pom.xml b/framework/src/onos/providers/openflow/pom.xml index c098a609..1250af61 100644 --- a/framework/src/onos/providers/openflow/pom.xml +++ b/framework/src/onos/providers/openflow/pom.xml @@ -37,6 +37,7 @@ <module>flow</module> <module>group</module> <module>meter</module> + <module>base</module> <module>app</module> </modules> diff --git a/framework/src/onos/providers/ovsdb/device/src/main/java/org/onosproject/ovsdb/providers/device/OvsdbDeviceProvider.java b/framework/src/onos/providers/ovsdb/device/src/main/java/org/onosproject/ovsdb/providers/device/OvsdbDeviceProvider.java index 10e745e3..d573458e 100644 --- a/framework/src/onos/providers/ovsdb/device/src/main/java/org/onosproject/ovsdb/providers/device/OvsdbDeviceProvider.java +++ b/framework/src/onos/providers/ovsdb/device/src/main/java/org/onosproject/ovsdb/providers/device/OvsdbDeviceProvider.java @@ -27,6 +27,7 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onlab.packet.ChassisId; +import org.onlab.packet.IpAddress; import org.onosproject.net.DefaultAnnotations; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; @@ -40,6 +41,7 @@ import org.onosproject.net.device.DeviceProviderService; import org.onosproject.net.device.DeviceService; import org.onosproject.net.provider.AbstractProvider; import org.onosproject.net.provider.ProviderId; +import org.onosproject.ovsdb.controller.OvsdbClientService; import org.onosproject.ovsdb.controller.OvsdbController; import org.onosproject.ovsdb.controller.OvsdbNodeId; import org.onosproject.ovsdb.controller.OvsdbNodeListener; @@ -87,8 +89,14 @@ public class OvsdbDeviceProvider extends AbstractProvider @Override public void triggerProbe(DeviceId deviceId) { - // TODO: This will be implemented later. log.info("Triggering probe on device {}", deviceId); + if (!isReachable(deviceId)) { + log.error("Failed to probe device {}", deviceId); + providerService.deviceDisconnected(deviceId); + return; + } else { + log.trace("Confirmed device {} connection", deviceId); + } } @Override @@ -98,7 +106,8 @@ public class OvsdbDeviceProvider extends AbstractProvider @Override public boolean isReachable(DeviceId deviceId) { - return true; + OvsdbClientService ovsdbClient = controller.getOvsdbClient(changeDeviceIdToNodeId(deviceId)); + return !(ovsdbClient == null || !ovsdbClient.isConnected()); } private class InnerOvsdbNodeListener implements OvsdbNodeListener { @@ -131,4 +140,12 @@ public class OvsdbDeviceProvider extends AbstractProvider } } + + private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) { + String[] strings = deviceId.toString().split(":"); + if (strings.length < 1) { + return null; + } + return new OvsdbNodeId(IpAddress.valueOf(strings[1]), 0); + } } |