Renamed networkgraph package to topology.
Moved NetworkGraphPublisher into new topology package.
net.onrc.onos.ofcontroller.networkgraph.* => net.onrc.onos.core.topology.*
net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher => net.onrc.onos.core.topology.NetworkGraphPublisher
Change-Id: I8b156d0fcbba520fee61e92ab659bb02cfa704ac
diff --git a/src/main/java/net/onrc/onos/core/topology/NetworkGraphPublisher.java b/src/main/java/net/onrc/onos/core/topology/NetworkGraphPublisher.java
new file mode 100644
index 0000000..0727a27
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/topology/NetworkGraphPublisher.java
@@ -0,0 +1,304 @@
+package net.onrc.onos.core.topology;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.core.util.SingletonTask;
+import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.onrc.onos.core.devicemanager.IOnosDeviceListener;
+import net.onrc.onos.core.devicemanager.IOnosDeviceService;
+import net.onrc.onos.core.devicemanager.OnosDevice;
+import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryListener;
+import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.core.main.IOFSwitchPortListener;
+import net.onrc.onos.core.topology.PortEvent.SwitchPort;
+import net.onrc.onos.registry.controller.IControllerRegistryService;
+import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
+import net.onrc.onos.registry.controller.RegistryException;
+
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.net.InetAddresses;
+
+/**
+ * The NetworkGraphPublisher subscribes to topology network events from the
+ * discovery modules. These events are reformatted and relayed to the topology
+ * part of the network graph
+ *
+ */
+public class NetworkGraphPublisher implements /*IOFSwitchListener,*/
+ IOFSwitchPortListener,
+ ILinkDiscoveryListener,
+ IFloodlightModule,
+ IOnosDeviceListener {
+ private static final Logger log =
+ LoggerFactory.getLogger(NetworkGraphPublisher.class);
+
+ private IFloodlightProviderService floodlightProvider;
+ private ILinkDiscoveryService linkDiscovery;
+ private IControllerRegistryService registryService;
+ private INetworkGraphService networkGraphService;
+
+ private IOnosDeviceService onosDeviceService;
+
+ private NetworkGraph networkGraph;
+ private NetworkGraphDiscoveryInterface networkGraphDiscoveryInterface;
+
+ private static final String ENABLE_CLEANUP_PROPERTY = "EnableCleanup";
+ private boolean cleanupEnabled = true;
+ private static final int CLEANUP_TASK_INTERVAL = 60; // in seconds
+ private SingletonTask cleanupTask;
+
+ /**
+ * Cleanup old switches from the network graph. Old switches are those
+ * which have no controller in the registry.
+ */
+ private class SwitchCleanup implements ControlChangeCallback, Runnable {
+ @Override
+ public void run() {
+ String old = Thread.currentThread().getName();
+ Thread.currentThread().setName("SwitchCleanup@" + old);
+
+ try {
+ if (log.isTraceEnabled()) {
+ log.trace("Running cleanup thread");
+ }
+ switchCleanup();
+ } finally {
+ cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
+ TimeUnit.SECONDS);
+ Thread.currentThread().setName(old);
+ }
+ }
+
+ /**
+ * First half of the switch cleanup operation. This method will attempt
+ * to get control of any switch it sees without a controller via the
+ * registry.
+ */
+ private void switchCleanup() {
+ Iterable<Switch> switches = networkGraph.getSwitches();
+
+ if (log.isTraceEnabled()) {
+ log.trace("Checking for inactive switches");
+ }
+ // For each switch check if a controller exists in controller registry
+ for (Switch sw: switches) {
+ try {
+ String controller =
+ registryService.getControllerForSwitch(sw.getDpid());
+ if (controller == null) {
+ log.debug("Requesting control to set switch {} INACTIVE",
+ HexString.toHexString(sw.getDpid()));
+ registryService.requestControl(sw.getDpid(), this);
+ }
+ } catch (RegistryException e) {
+ log.error("Caught RegistryException in cleanup thread", e);
+ }
+ }
+ }
+
+ /**
+ * Second half of the switch cleanup operation. If the registry grants
+ * control of a switch, we can be sure no other instance is writing
+ * this switch to the network graph, so we can remove it now.
+ * @param dpid the dpid of the switch we requested control for
+ * @param hasControl whether we got control or not
+ */
+ @Override
+ public void controlChanged(long dpid, boolean hasControl) {
+ if (hasControl) {
+ log.debug("Got control to set switch {} INACTIVE",
+ HexString.toHexString(dpid));
+
+ SwitchEvent switchEvent = new SwitchEvent(dpid);
+ networkGraphDiscoveryInterface.
+ removeSwitchDiscoveryEvent(switchEvent);
+ registryService.releaseControl(dpid);
+ }
+ }
+ }
+
+ @Override
+ public void linkDiscoveryUpdate(LDUpdate update) {
+ LinkEvent linkEvent = new LinkEvent(update.getSrc(),
+ (long) update.getSrcPort(), update.getDst(),
+ (long) update.getDstPort());
+
+ switch (update.getOperation()) {
+ case LINK_ADDED:
+ networkGraphDiscoveryInterface.putLinkDiscoveryEvent(linkEvent);
+ break;
+ case LINK_UPDATED:
+ // We don't use the LINK_UPDATED event (unsure what it means)
+ break;
+ case LINK_REMOVED:
+ networkGraphDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
+ break;
+ default:
+ break;
+ }
+ }
+
+ @Override
+ public void switchPortAdded(Long switchId, OFPhysicalPort port) {
+ PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
+ networkGraphDiscoveryInterface.putPortDiscoveryEvent(portEvent);
+ linkDiscovery.RemoveFromSuppressLLDPs(switchId, port.getPortNumber());
+ }
+
+ @Override
+ public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
+ PortEvent portEvent = new PortEvent(switchId, (long) port.getPortNumber());
+ networkGraphDiscoveryInterface.removePortDiscoveryEvent(portEvent);
+ }
+
+ @Override
+ public void addedSwitch(IOFSwitch sw) {
+ // TODO Not very robust
+ if (!registryService.hasControl(sw.getId())) {
+ return;
+ }
+
+ SwitchEvent switchEvent = new SwitchEvent(sw.getId());
+
+ List<PortEvent> portEvents = new ArrayList<PortEvent>();
+ for (OFPhysicalPort port : sw.getPorts()) {
+ portEvents.add(new PortEvent(sw.getId(), (long) port.getPortNumber()));
+ }
+ networkGraphDiscoveryInterface
+ .putSwitchDiscoveryEvent(switchEvent, portEvents);
+
+ for (OFPhysicalPort port : sw.getPorts()) {
+ // Allow links to be discovered on this port now that it's
+ // in the database
+ linkDiscovery.RemoveFromSuppressLLDPs(sw.getId(), port.getPortNumber());
+ }
+ }
+
+ @Override
+ public void removedSwitch(IOFSwitch sw) {
+ // We don't use this event - switch remove is done by cleanup thread
+ }
+
+ @Override
+ public void switchPortChanged(Long switchId) {
+ // We don't use this event
+ }
+
+ @Override
+ public String getName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* *****************
+ * IFloodlightModule
+ * *****************/
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+ return null;
+ }
+
+ @Override
+ public Map<Class<? extends IFloodlightService>, IFloodlightService>
+ getServiceImpls() {
+ return null;
+ }
+
+ @Override
+ public Collection<Class<? extends IFloodlightService>>
+ getModuleDependencies() {
+ Collection<Class<? extends IFloodlightService>> l =
+ new ArrayList<Class<? extends IFloodlightService>>();
+ l.add(IFloodlightProviderService.class);
+ l.add(ILinkDiscoveryService.class);
+ l.add(IThreadPoolService.class);
+ l.add(IControllerRegistryService.class);
+ l.add(INetworkGraphService.class);
+ l.add(IOnosDeviceService.class);
+ return l;
+ }
+
+ @Override
+ public void init(FloodlightModuleContext context)
+ throws FloodlightModuleException {
+ floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+ linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
+ registryService = context.getServiceImpl(IControllerRegistryService.class);
+ onosDeviceService = context.getServiceImpl(IOnosDeviceService.class);
+
+ networkGraphService = context.getServiceImpl(INetworkGraphService.class);
+ }
+
+ @Override
+ public void startUp(FloodlightModuleContext context) {
+ floodlightProvider.addOFSwitchListener(this);
+ linkDiscovery.addListener(this);
+ onosDeviceService.addOnosDeviceListener(this);
+
+ networkGraph = networkGraphService.getNetworkGraph();
+ networkGraphDiscoveryInterface =
+ networkGraphService.getNetworkGraphDiscoveryInterface();
+
+ // Run the cleanup thread
+ String enableCleanup =
+ context.getConfigParams(this).get(ENABLE_CLEANUP_PROPERTY);
+ if (enableCleanup != null
+ && enableCleanup.equalsIgnoreCase("false")) {
+ cleanupEnabled = false;
+ }
+
+ log.debug("Cleanup thread is {}enabled", (cleanupEnabled) ? "" : "not ");
+
+ if (cleanupEnabled) {
+ IThreadPoolService threadPool =
+ context.getServiceImpl(IThreadPoolService.class);
+ cleanupTask = new SingletonTask(threadPool.getScheduledExecutor(),
+ new SwitchCleanup());
+ // Run the cleanup task immediately on startup
+ cleanupTask.reschedule(0, TimeUnit.SECONDS);
+ }
+ }
+
+ @Override
+ public void onosDeviceAdded(OnosDevice device) {
+ log.debug("Called onosDeviceAdded mac {}", device.getMacAddress());
+
+ SwitchPort sp = new SwitchPort(device.getSwitchDPID(),
+ (long) device.getSwitchPort());
+ List<SwitchPort> spLists = new ArrayList<SwitchPort>();
+ spLists.add(sp);
+ DeviceEvent event = new DeviceEvent(device.getMacAddress());
+ event.setAttachmentPoints(spLists);
+ event.setLastSeenTime(device.getLastSeenTimestamp().getTime());
+ if (device.getIpv4Address() != null) {
+ InetAddress ip = InetAddresses.fromInteger(device.getIpv4Address());
+ event.addIpAddress(ip);
+ }
+ // Does not use vlan info now.
+
+ networkGraphDiscoveryInterface.putDeviceDiscoveryEvent(event);
+ }
+
+ @Override
+ public void onosDeviceRemoved(OnosDevice device) {
+ log.debug("Called onosDeviceRemoved");
+ DeviceEvent event = new DeviceEvent(device.getMacAddress());
+ networkGraphDiscoveryInterface.removeDeviceDiscoveryEvent(event);
+ }
+}