diff options
author | Ashlee Young <ashlee@onosfw.com> | 2015-09-22 12:49:09 -0700 |
---|---|---|
committer | Ashlee Young <ashlee@onosfw.com> | 2015-09-22 12:49:09 -0700 |
commit | 81391595dca425ae58e2294898f09f11d9a32dbc (patch) | |
tree | f5d65c39a732150b2b29daa8de98a35d1236d3fb /framework/src/onos/providers/lldp | |
parent | 0aa37e73dcb3a55b8d889b0c32ff74055551b1f3 (diff) |
bringing src to commit tag 65d551b50e782b0c1ea76c1a9ed1c5a801a5a7e4
Change-Id: Ib2da78962eaef856f418636c31b0f5c84286244f
Diffstat (limited to 'framework/src/onos/providers/lldp')
6 files changed, 398 insertions, 283 deletions
diff --git a/framework/src/onos/providers/lldp/pom.xml b/framework/src/onos/providers/lldp/pom.xml index bc13793e..e47d26c7 100644 --- a/framework/src/onos/providers/lldp/pom.xml +++ b/framework/src/onos/providers/lldp/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>org.onosproject</groupId> <artifactId>onos-providers</artifactId> - <version>1.3.0-SNAPSHOT</version> + <version>1.4.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> 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 new file mode 100644 index 00000000..0cd19242 --- /dev/null +++ b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/DiscoveryContext.java @@ -0,0 +1,69 @@ +/* + * 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.lldp.impl; + +import org.onosproject.mastership.MastershipService; +import org.onosproject.net.LinkKey; +import org.onosproject.net.link.LinkProviderService; +import org.onosproject.net.packet.PacketService; + +/** + * Shared context for use by link discovery. + */ +interface DiscoveryContext { + + /** + * Returns the shared mastership service reference. + * + * @return mastership service + */ + MastershipService mastershipService(); + + /** + * Returns the shared link provider service reference. + * + * @return link provider service + */ + LinkProviderService providerService(); + + /** + * Returns the shared packet service reference. + * + * @return packet service + */ + PacketService packetService(); + + /** + * Returns the probe rate in millis. + * + * @return probe rate + */ + long probeRate(); + + /** + * Indicates whether to emit BDDP. + * + * @return true to emit BDDP + */ + boolean useBDDP(); + + /** + * Touches the link identified by the given key to indicate that it's active. + * + * @param key link key + */ + void touchLink(LinkKey key); +} 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 index e9e2bfad..386d838f 100644 --- 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 @@ -15,9 +15,9 @@ */ package org.onosproject.provider.lldp.impl; -import com.google.common.base.Strings; 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; @@ -35,15 +35,18 @@ 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.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; @@ -57,29 +60,29 @@ import java.io.IOException; import java.util.Dictionary; import java.util.EnumSet; import java.util.Map; +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.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 an OpenFlow controller to detect network - * infrastructure links. + * 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 PROP_USE_BDDP = "useBDDP"; - private static final String PROP_DISABLE_LD = "disableLinkDiscovery"; - private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression"; - - private static final String DEFAULT_LLDP_SUPPRESSION_CONFIG = "../config/lldp_suppression.json"; + private static final String FORMAT = + "Settings: enabled={}, useBDDP={}, probeRate={}, " + + "staleLinkAge={}, lldpSuppression={}"; private final Logger log = getLogger(getClass()); @@ -93,6 +96,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { protected DeviceService deviceService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected LinkService linkService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected PacketService packetService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) @@ -105,28 +111,51 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { 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; - @Property(name = PROP_DISABLE_LD, boolValue = false, - label = "Permanently disable link discovery") - private boolean disableLinkDiscovery = false; + 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 long INIT_DELAY = 5; - private static final long DELAY = 5; + 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 InternalLinkProvider listener = new InternalLinkProvider(); - + 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; @@ -141,39 +170,125 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { public void activate(ComponentContext context) { cfgService.registerProperties(getClass()); appId = coreService.registerApplication(PROVIDER_NAME); - - // to load configuration at startup modified(context); - if (disableLinkDiscovery) { - log.info("LinkDiscovery has been permanently disabled by configuration"); - return; + 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(e.getMessage()); + 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(); } + log.info(FORMAT, enabled, useBDDP, probeRate, staleLinkAge, lldpSuppression); + } + + /** + * Enables link discovery processing. + */ + private void enable() { providerService = providerRegistry.register(this); - deviceService.addListener(listener); - packetService.addProcessor(listener, PacketProcessor.advisor(0)); 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(); - LinkDiscovery ld; + providerService = null; + } + + /** + * Loads available devices and registers their ports to be probed. + */ + private void loadDevices() { for (Device device : deviceService.getAvailableDevices()) { if (rules.isSuppressed(device)) { log.debug("LinkDiscovery from {} disabled by configuration", device.id()); continue; } - ld = new LinkDiscovery(device, packetService, masterService, - providerService, useBDDP); + LinkDiscovery ld = new LinkDiscovery(device, context); discoverers.put(device.id(), ld); addPorts(ld, device.id()); } - - executor = newSingleThreadScheduledExecutor(groupedThreads("onos/device", "sync-%d")); - executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), INIT_DELAY, DELAY, SECONDS); - - requestIntercepts(); - - log.info("Started"); } + /** + * Adds ports of the specified device to the specified discovery helper. + */ private void addPorts(LinkDiscovery discoverer, DeviceId deviceId) { for (Port p : deviceService.getPorts(deviceId)) { if (rules.isSuppressed(p)) { @@ -185,54 +300,12 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { } } - @Deactivate - public void deactivate() { - cfgService.unregisterProperties(getClass(), false); - if (disableLinkDiscovery) { - return; - } - - withdrawIntercepts(); - - providerRegistry.unregister(this); - deviceService.removeListener(listener); - packetService.removeProcessor(listener); - masterService.removeListener(roleListener); - - executor.shutdownNow(); - discoverers.values().forEach(LinkDiscovery::stop); - discoverers.clear(); - providerService = null; - - log.info("Stopped"); - } - - @Modified - public void modified(ComponentContext context) { - if (context == null) { - loadSuppressionRules(); - return; - } - @SuppressWarnings("rawtypes") - Dictionary properties = context.getProperties(); - - String s = get(properties, PROP_DISABLE_LD); - if (!Strings.isNullOrEmpty(s)) { - disableLinkDiscovery = Boolean.valueOf(s); - } - s = get(properties, PROP_USE_BDDP); - if (!Strings.isNullOrEmpty(s)) { - useBDDP = Boolean.valueOf(s); - } - s = get(properties, PROP_LLDP_SUPPRESSION); - if (!Strings.isNullOrEmpty(s)) { - lldpSuppression = s; - } - requestIntercepts(); - loadSuppressionRules(); - } + /** + * 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); @@ -249,7 +322,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { } /** - * Request packet intercepts. + * Requests packet intercepts. */ private void requestIntercepts() { TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); @@ -265,7 +338,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { } /** - * Withdraw packet intercepts. + * Withdraws packet intercepts. */ private void withdrawIntercepts() { TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); @@ -275,13 +348,10 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId); } - private LinkDiscovery createLinkDiscovery(Device device) { - return new LinkDiscovery(device, packetService, masterService, - providerService, useBDDP); - } - + /** + * Processes device mastership role changes. + */ private class InternalRoleListener implements MastershipListener { - @Override public void event(MastershipEvent event) { if (MastershipEvent.Type.BACKUPS_CHANGED.equals(event.type())) { @@ -298,22 +368,18 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { if (rules.isSuppressed(device)) { return; } - synchronized (discoverers) { - if (!discoverers.containsKey(deviceId)) { - // ideally, should never reach here - log.debug("Device mastership changed ({}) {}", event.type(), deviceId); - discoverers.put(deviceId, createLinkDiscovery(device)); - } - } + discoverers.computeIfAbsent(deviceId, k -> new LinkDiscovery(device, context)); } } - private class InternalLinkProvider implements PacketProcessor, DeviceListener { - + /** + * Processes device events. + */ + private class InternalDeviceListener implements DeviceListener { @Override public void event(DeviceEvent event) { - LinkDiscovery ld = null; + LinkDiscovery ld; Device device = event.subject(); Port port = event.port(); if (device == null) { @@ -333,7 +399,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { return; } log.debug("Device added ({}) {}", event.type(), deviceId); - discoverers.put(deviceId, createLinkDiscovery(device)); + discoverers.put(deviceId, new LinkDiscovery(device, context)); } else { if (ld.isStopped()) { log.debug("Device restarted ({}) {}", event.type(), deviceId); @@ -400,7 +466,12 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { log.debug("Unknown event {}", event); } } + } + /** + * Processes incoming packets. + */ + private class InternalPacketProcessor implements PacketProcessor { @Override public void process(PacketContext context) { if (context == null) { @@ -417,8 +488,10 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { } } + /** + * Auxiliary task to keep device ports up to date. + */ private final class SyncDeviceInfoTask implements Runnable { - @Override public void run() { if (Thread.currentThread().isInterrupted()) { @@ -433,20 +506,90 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { } DeviceId did = dev.id(); synchronized (discoverers) { - LinkDiscovery discoverer = discoverers.get(did); - if (discoverer == null) { - discoverer = createLinkDiscovery(dev); - discoverers.put(did, discoverer); - } - - addPorts(discoverer, did); + LinkDiscovery ld = discoverers + .computeIfAbsent(did, k -> new LinkDiscovery(dev, context)); + addPorts(ld, did); } } } catch (Exception e) { - // catch all Exception to avoid Scheduled task being suppressed. + // 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 a81eeb1d..8cdfd50f 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 @@ -15,44 +15,34 @@ */ package org.onosproject.provider.lldp.impl; -import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.jboss.netty.util.Timeout; import org.jboss.netty.util.TimerTask; import org.onlab.packet.Ethernet; import org.onlab.packet.ONOSLLDP; import org.onlab.util.Timer; -import org.onosproject.mastership.MastershipService; import org.onosproject.net.ConnectPoint; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Link.Type; +import org.onosproject.net.LinkKey; import org.onosproject.net.Port; import org.onosproject.net.PortNumber; import org.onosproject.net.link.DefaultLinkDescription; import org.onosproject.net.link.LinkDescription; -import org.onosproject.net.link.LinkProviderService; import org.onosproject.net.packet.DefaultOutboundPacket; import org.onosproject.net.packet.OutboundPacket; import org.onosproject.net.packet.PacketContext; -import org.onosproject.net.packet.PacketService; import org.slf4j.Logger; import java.nio.ByteBuffer; -import java.util.Iterator; -import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import static com.google.common.base.Preconditions.checkNotNull; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.onosproject.net.PortNumber.portNumber; import static org.onosproject.net.flow.DefaultTrafficTreatment.builder; import static org.slf4j.LoggerFactory.getLogger; -// TODO: add 'fast discovery' mode: drop LLDPs in destination switch but listen for flow_removed messages -// FIXME: add ability to track links using port pairs or the link inventory - /** * Run discovery process from a physical switch. Ports are initially labeled as * slow ports. When an LLDP is successfully received, label the remote port as @@ -60,57 +50,36 @@ import static org.slf4j.LoggerFactory.getLogger; * LLDP, send an LLDP for a single slow port. Based on FlowVisor topology * discovery implementation. */ -public class LinkDiscovery implements TimerTask { +class LinkDiscovery implements TimerTask { private final Logger log = getLogger(getClass()); - private static final short MAX_PROBE_COUNT = 3; // probes to send before link is removed - private static final short DEFAULT_PROBE_RATE = 3000; // millis private static final String SRC_MAC = "DE:AD:BE:EF:BA:11"; - private static final String SERVICE_NULL = "Service cannot be null"; private final Device device; - - // send 1 probe every probeRate milliseconds - private final long probeRate = DEFAULT_PROBE_RATE; - - private final Set<Long> slowPorts = Sets.newConcurrentHashSet(); - // ports, known to have incoming links - private final Set<Long> fastPorts = Sets.newConcurrentHashSet(); - - // number of unacknowledged probes per port - private final Map<Long, AtomicInteger> portProbeCount = Maps.newHashMap(); + private final DiscoveryContext context; private final ONOSLLDP lldpPacket; private final Ethernet ethPacket; private Ethernet bddpEth; - private final boolean useBDDP; private Timeout timeout; private volatile boolean isStopped; - private final LinkProviderService linkProvider; - private final PacketService pktService; - private final MastershipService mastershipService; + // Set of ports to be probed + private final Set<Long> ports = Sets.newConcurrentHashSet(); /** * Instantiates discovery manager for the given physical switch. Creates a * generic LLDP packet that will be customized for the port it is sent out on. * Starts the the timer for the discovery process. * - * @param device the physical switch - * @param pktService packet service - * @param masterService mastership service - * @param providerService link provider service - * @param useBDDP flag to also use BDDP for discovery + * @param device the physical switch + * @param context discovery context */ - public LinkDiscovery(Device device, PacketService pktService, - MastershipService masterService, - LinkProviderService providerService, Boolean... useBDDP) { + LinkDiscovery(Device device, DiscoveryContext context) { this.device = device; - this.linkProvider = checkNotNull(providerService, SERVICE_NULL); - this.pktService = checkNotNull(pktService, SERVICE_NULL); - this.mastershipService = checkNotNull(masterService, SERVICE_NULL); + this.context = context; lldpPacket = new ONOSLLDP(); lldpPacket.setChassisId(device.chassisId()); @@ -122,15 +91,11 @@ public class LinkDiscovery implements TimerTask { ethPacket.setPayload(this.lldpPacket); ethPacket.setPad(true); - this.useBDDP = useBDDP.length > 0 ? useBDDP[0] : false; - if (this.useBDDP) { - bddpEth = new Ethernet(); - bddpEth.setPayload(lldpPacket); - bddpEth.setEtherType(Ethernet.TYPE_BSN); - bddpEth.setDestinationMACAddress(ONOSLLDP.BDDP_MULTICAST); - bddpEth.setPad(true); - log.info("Using BDDP to discover network"); - } + bddpEth = new Ethernet(); + bddpEth.setPayload(lldpPacket); + bddpEth.setEtherType(Ethernet.TYPE_BSN); + bddpEth.setDestinationMACAddress(ONOSLLDP.BDDP_MULTICAST); + bddpEth.setPad(true); isStopped = true; start(); @@ -138,82 +103,52 @@ public class LinkDiscovery implements TimerTask { } - /** - * Add physical port port to discovery process. - * Send out initial LLDP and label it as slow port. - * - * @param port the port - */ - public void addPort(Port port) { - boolean newPort = false; - synchronized (this) { - if (!containsPort(port.number().toLong())) { - newPort = true; - slowPorts.add(port.number().toLong()); - } + synchronized void stop() { + if (!isStopped) { + isStopped = true; + timeout.cancel(); + } else { + log.warn("LinkDiscovery stopped multiple times?"); } + } - boolean isMaster = mastershipService.isLocalMaster(device.id()); - if (newPort && isMaster) { - log.debug("Sending init probe to port {}@{}", port.number().toLong(), device.id()); - sendProbes(port.number().toLong()); + synchronized void start() { + if (isStopped) { + isStopped = false; + timeout = Timer.getTimer().newTimeout(this, 0, MILLISECONDS); + } else { + log.warn("LinkDiscovery started multiple times?"); } } - /** - * Removes physical port from discovery process. - * - * @param port the port - */ - public void removePort(Port port) { - // Ignore ports that are not on this switch - long portnum = port.number().toLong(); - synchronized (this) { - if (slowPorts.contains(portnum)) { - slowPorts.remove(portnum); - - } else if (fastPorts.contains(portnum)) { - fastPorts.remove(portnum); - portProbeCount.remove(portnum); - // no iterator to update - } else { - log.warn("Tried to dynamically remove non-existing port {}", portnum); - } - } + synchronized boolean isStopped() { + return isStopped || timeout.isCancelled(); } /** - * Method called by remote port to acknowledge receipt of LLDP sent by - * this port. If slow port, updates label to fast. If fast port, decrements - * number of unacknowledged probes. + * Add physical port port to discovery process. + * Send out initial LLDP and label it as slow port. * - * @param portNumber the port + * @param port the port */ - public void ackProbe(Long portNumber) { - synchronized (this) { - if (slowPorts.contains(portNumber)) { - log.debug("Setting slow port to fast: {}:{}", device.id(), portNumber); - slowPorts.remove(portNumber); - fastPorts.add(portNumber); - portProbeCount.put(portNumber, new AtomicInteger(0)); - } else if (fastPorts.contains(portNumber)) { - portProbeCount.get(portNumber).set(0); - } else { - log.debug("Got ackProbe for non-existing port: {}", portNumber); - } + void addPort(Port port) { + boolean newPort = ports.add(port.number().toLong()); + boolean isMaster = context.mastershipService().isLocalMaster(device.id()); + if (newPort && isMaster) { + log.debug("Sending initial probe to port {}@{}", port.number().toLong(), device.id()); + sendProbes(port.number().toLong()); } } - /** - * Handles an incoming LLDP packet. Creates link in topology and sends ACK - * to port where LLDP originated. + * Handles an incoming LLDP packet. Creates link in topology and adds the + * link for staleness tracking. * - * @param context packet context + * @param packetContext packet context * @return true if handled */ - public boolean handleLLDP(PacketContext context) { - Ethernet eth = context.inPacket().parsed(); + boolean handleLLDP(PacketContext packetContext) { + Ethernet eth = packetContext.inPacket().parsed(); if (eth == null) { return false; } @@ -221,10 +156,9 @@ public class LinkDiscovery implements TimerTask { ONOSLLDP onoslldp = ONOSLLDP.parseONOSLLDP(eth); if (onoslldp != null) { PortNumber srcPort = portNumber(onoslldp.getPort()); - PortNumber dstPort = context.inPacket().receivedFrom().port(); + PortNumber dstPort = packetContext.inPacket().receivedFrom().port(); DeviceId srcDeviceId = DeviceId.deviceId(onoslldp.getDeviceString()); - DeviceId dstDeviceId = context.inPacket().receivedFrom().deviceId(); - ackProbe(dstPort.toLong()); + DeviceId dstDeviceId = packetContext.inPacket().receivedFrom().deviceId(); ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort); ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort); @@ -234,7 +168,8 @@ public class LinkDiscovery implements TimerTask { new DefaultLinkDescription(src, dst, Type.INDIRECT); try { - linkProvider.linkDetected(ld); + context.providerService().linkDetected(ld); + context.touchLink(LinkKey.linkKey(src, dst)); } catch (IllegalStateException e) { return true; } @@ -256,61 +191,14 @@ public class LinkDiscovery implements TimerTask { if (isStopped()) { return; } - if (!mastershipService.isLocalMaster(device.id())) { - if (!isStopped()) { - // reschedule timer - timeout = Timer.getTimer().newTimeout(this, probeRate, MILLISECONDS); - } - return; - } - log.trace("Sending probes from {}", device.id()); - synchronized (this) { - Iterator<Long> fastIterator = fastPorts.iterator(); - while (fastIterator.hasNext()) { - long portNumber = fastIterator.next(); - int probeCount = portProbeCount.get(portNumber).getAndIncrement(); - - if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) { - log.trace("Sending fast probe to port {}", portNumber); - sendProbes(portNumber); - - } else { - // Link down, demote to slowPorts; update fast and slow ports - fastIterator.remove(); - slowPorts.add(portNumber); - portProbeCount.remove(portNumber); - - ConnectPoint cp = new ConnectPoint(device.id(), portNumber(portNumber)); - log.debug("Link down -> {}", cp); - linkProvider.linksVanished(cp); - } - } - - // send a probe for the next slow port - for (long portNumber : slowPorts) { - log.trace("Sending slow probe to port {}", portNumber); - sendProbes(portNumber); - } + if (context.mastershipService().isLocalMaster(device.id())) { + log.trace("Sending probes from {}", device.id()); + ports.forEach(this::sendProbes); } if (!isStopped()) { - // reschedule timer - timeout = Timer.getTimer().newTimeout(this, probeRate, MILLISECONDS); - } - } - - public synchronized void stop() { - isStopped = true; - timeout.cancel(); - } - - public synchronized void start() { - if (isStopped) { - isStopped = false; - timeout = Timer.getTimer().newTimeout(this, 0, MILLISECONDS); - } else { - log.warn("LinkDiscovery started multiple times?"); + timeout = Timer.getTimer().newTimeout(this, context.probeRate(), MILLISECONDS); } } @@ -351,19 +239,15 @@ public class LinkDiscovery implements TimerTask { private void sendProbes(Long portNumber) { log.trace("Sending probes out to {}@{}", portNumber, device.id()); OutboundPacket pkt = createOutBoundLLDP(portNumber); - pktService.emit(pkt); - if (useBDDP) { + context.packetService().emit(pkt); + if (context.useBDDP()) { OutboundPacket bpkt = createOutBoundBDDP(portNumber); - pktService.emit(bpkt); + context.packetService().emit(bpkt); } } - public boolean containsPort(Long portNumber) { - return slowPorts.contains(portNumber) || fastPorts.contains(portNumber); - } - - public synchronized boolean isStopped() { - return isStopped || timeout.isCancelled(); + boolean containsPort(long portNumber) { + return ports.contains(portNumber); } } 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 index 1d63a15d..b4b7b7b6 100644 --- 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 @@ -48,6 +48,7 @@ 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; @@ -79,7 +80,8 @@ public class LLDPLinkProviderTest { private static Port pd4; private final LLDPLinkProvider provider = new LLDPLinkProvider(); - private final TestLinkRegistry linkService = new TestLinkRegistry(); + 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(); @@ -104,11 +106,11 @@ public class LLDPLinkProviderTest { provider.coreService = coreService; provider.deviceService = deviceService; + provider.linkService = linkService; provider.packetService = packetService; - provider.providerRegistry = linkService; + provider.providerRegistry = linkRegistry; provider.masterService = masterService; - provider.activate(null); } @@ -499,4 +501,6 @@ public class LLDPLinkProviderTest { } + private class TestLinkService extends LinkServiceAdapter { + } } diff --git a/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/SuppressionRulesTest.java b/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/SuppressionRulesTest.java index 52f0bb1e..03d431af 100644 --- a/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/SuppressionRulesTest.java +++ b/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/SuppressionRulesTest.java @@ -1,3 +1,18 @@ +/* + * 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.lldp.impl; import static org.junit.Assert.*; |