diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java index d16c5e20f97b2420b4991b9ba252e450cdc3b6ee..045b8035a28083ae0f3b35cec0e649a874d0b3b7 100644 --- a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java +++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java @@ -27,6 +27,7 @@ import org.projectfloodlight.openflow.protocol.OFPortDesc; import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; import org.projectfloodlight.openflow.protocol.OFPortStatus; +import net.floodlightcontroller.core.internal.SwitchCounters; import net.floodlightcontroller.util.OrderedCollection; /** @@ -182,5 +183,13 @@ public interface IOFSwitchBackend extends IOFSwitch { * @return true if another viable master exists */ boolean hasAnotherMaster(); + + /** + * Retrieve the SwitchCounters from the switch. + * This is in IOFSwitchBackend as opposed to IOFSwitch to prevent + * modules from easily getting and messing with the counters. + * @return SwitchCounters + */ + SwitchCounters getCounters(); } diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/OFSwitch.java index c85d42a7c56a8548850861b2e8e4f8420390a16b..227ee3b1e654a1de2e640618917a8b9a57a6f11f 100644 --- a/src/main/java/net/floodlightcontroller/core/OFSwitch.java +++ b/src/main/java/net/floodlightcontroller/core/OFSwitch.java @@ -39,8 +39,10 @@ import javax.annotation.Nonnull; import net.floodlightcontroller.core.annotations.LogMessageDoc; import net.floodlightcontroller.core.internal.IOFSwitchManager; +import net.floodlightcontroller.core.internal.SwitchCounters; import net.floodlightcontroller.core.util.AppCookie; import net.floodlightcontroller.core.util.URIUtil; +import net.floodlightcontroller.debugcounter.IDebugCounterService; import org.projectfloodlight.openflow.protocol.OFActionType; import org.projectfloodlight.openflow.protocol.OFBsnControllerConnection; @@ -112,17 +114,19 @@ public class OFSwitch implements IOFSwitchBackend { private boolean flowTableFull = false; protected SwitchDescription description; + + protected SwitchCounters counters; private SwitchStatus status; public static final int OFSWITCH_APP_ID = ident(5); - + static { AppCookie.registerApp(OFSwitch.OFSWITCH_APP_ID, "switch"); } public OFSwitch(IOFConnectionBackend connection, @Nonnull OFFactory factory, @Nonnull IOFSwitchManager switchManager, - @Nonnull DatapathId datapathId) { + @Nonnull DatapathId datapathId, @Nonnull IDebugCounterService debugCounterService) { if(connection == null) throw new NullPointerException("connection must not be null"); if(!connection.getAuxId().equals(OFAuxId.MAIN)) @@ -141,6 +145,7 @@ public class OFSwitch implements IOFSwitchBackend { this.description = new SwitchDescription(); this.portManager = new PortManager(); this.status = SwitchStatus.HANDSHAKE; + this.counters = new SwitchCounters(debugCounterService, datapathId); // Connections this.connections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>(); @@ -772,7 +777,9 @@ public class OFSwitch implements IOFSwitchBackend { this.connections.remove(entry.getKey()); } log.debug("~~~~~~~SWITCH DISCONNECTED~~~~~~"); + // Remove all counters from the store connected = false; + switchManager.switchDisconnected(this); //TODO @Ryan Possible bug? I think this should be here to make sure the manager knows too if a module manually disconnects a switch... } @Override @@ -1101,4 +1108,18 @@ public class OFSwitch implements IOFSwitchBackend { } return false; } + + @Override + /** + * Retrieve the counters for incrementing and clearing. User modules + * should not have access to this method, nor should use it. The counters + * will be kept by the controller core. This method should only be used + * by "authorized" modules to perform bookkeeping. Unfortunately, this + * needs to be exposed to allow the Controller access to counters. + * If only there were a "friend" C++ equivalent in Java... + * @return the counters to be incremented or cleared. + */ + public SwitchCounters getCounters() { + return counters; + } } diff --git a/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java index 81a85346ca78e944cf2cf6dd4d52d6fb7d74ee16..787acc10949e997f287001ed5344114c73bc0000 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java +++ b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java @@ -28,7 +28,7 @@ public interface IOFSwitchManager { /** * Called when a switch disconnects - * @param sw the added switch + * @param sw the removed switch */ void switchDisconnected(IOFSwitchBackend sw); diff --git a/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java index a0cdf915338a43ad93536c6b19f37227b43dd1f2..8e33433b1515e8604eecd4ddf172e8ca57272e1e 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java +++ b/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java @@ -4,6 +4,8 @@ import net.floodlightcontroller.core.IOFConnectionBackend; import net.floodlightcontroller.core.IOFSwitchBackend; import net.floodlightcontroller.core.IOFSwitchDriver; import net.floodlightcontroller.core.SwitchDescription; +import net.floodlightcontroller.debugcounter.IDebugCounterService; + import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.types.DatapathId; @@ -56,10 +58,11 @@ public interface ISwitchDriverRegistry { * IOFSwitch implementation * @param factory The factory to use to create OF messages. * @param datapathId + * @param debugCounterService; used to create a new switch if one does not exist * @return A IOFSwitch implementation matching the description or an * OFSwitchImpl if no driver returned a more concrete instance. * @throws NullPointerException If the SwitchDescription or any of its * members is null. */ - IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, SwitchDescription description, OFFactory factory, DatapathId datapathId); + IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, SwitchDescription description, OFFactory factory, DatapathId datapathId, IDebugCounterService debugCounterService); } diff --git a/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java index 6f2fffed183dd3e58ab59729a5f8d636ad3a9009..cc68b7b17b9f54fd86159739ed62c6114e17b1b9 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java +++ b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java @@ -13,6 +13,8 @@ import net.floodlightcontroller.core.IOFSwitchBackend; import net.floodlightcontroller.core.IOFSwitchDriver; import net.floodlightcontroller.core.OFSwitch; import net.floodlightcontroller.core.SwitchDescription; +import net.floodlightcontroller.debugcounter.IDebugCounterService; + import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.types.DatapathId; import org.slf4j.Logger; @@ -69,7 +71,7 @@ class NaiveSwitchDriverRegistry implements ISwitchDriverRegistry { // but it's probably not worth it. public synchronized IOFSwitchBackend getOFSwitchInstance(@Nonnull IOFConnectionBackend connection, @Nonnull SwitchDescription description, - @Nonnull OFFactory factory, @Nonnull DatapathId id) { + @Nonnull OFFactory factory, @Nonnull DatapathId id, @Nonnull IDebugCounterService debugCounterService) { Preconditions.checkNotNull(connection, "connection"); Preconditions.checkNotNull(description, "description"); Preconditions.checkNotNull(factory, "factory"); @@ -94,7 +96,7 @@ class NaiveSwitchDriverRegistry implements ISwitchDriverRegistry { } } // no switch found - IOFSwitchBackend sw = new OFSwitch(connection, factory, switchManager, id); + IOFSwitchBackend sw = new OFSwitch(connection, factory, switchManager, id, debugCounterService); sw.setSwitchProperties(description); return sw; } diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java index 2fbc8ff045ed63f12634b0850978ce868a66e10f..ead4c4303d2c37a12cec34cefc66f3e172684d0f 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java +++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java @@ -62,7 +62,6 @@ import org.sdnplatform.sync.IStoreListener; import org.sdnplatform.sync.ISyncService; import org.sdnplatform.sync.Versioned; import org.sdnplatform.sync.error.SyncException; -import org.sdnplatform.sync.error.UnknownStoreException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -235,8 +234,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen if (presentSw != sw) { // Note == for object equality, not .equals for value - counters.errorActivatedSwitchNotPresent - .increment(); + counters.errorActivatedSwitchNotPresent.increment(); log.warn("Switch {} disconnect but not present in sync manager", sw); return; } @@ -472,7 +470,7 @@ public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListen public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, SwitchDescription description, OFFactory factory, DatapathId datapathId) { - return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId); + return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId, debugCounterService); } @Override diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchCounters.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchCounters.java new file mode 100644 index 0000000000000000000000000000000000000000..a75751570a3477f1b082dce41afff1cc6fbdf594 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/internal/SwitchCounters.java @@ -0,0 +1,109 @@ +package net.floodlightcontroller.core.internal; + +import org.projectfloodlight.openflow.types.DatapathId; + +import net.floodlightcontroller.debugcounter.IDebugCounter; +import net.floodlightcontroller.debugcounter.IDebugCounterService; + +public class SwitchCounters { + + public final String moduleName = OFSwitchManager.class.getSimpleName(); + private IDebugCounterService debugCounterService; + private String dpidString; + public final IDebugCounter deviceAdded; + public final IDebugCounter deviceRemoved; + public final IDebugCounter portEnabled; + public final IDebugCounter portDisabled; + public final IDebugCounter portUp; + public final IDebugCounter portDown; + public final IDebugCounter packetIn; + public final IDebugCounter packetOut; + public final IDebugCounter flowAdded; + public final IDebugCounter flowRemoved; + + /** + * Maintains counters for a connected switch. The OFSwitchManager should be + * registered with the IDebugCounterService prior to adding a particular + * switch's counters. All switch counters will be housed under the umbrella + * of the OFSwitchManagerModule, where each switch's counters can be accessed + * by the DPID of that switch followed by the hierarchy of the counter: + * ofswitchmanagerservice/00:11:22:33:44:55:66:77/device-added + * ofswitchmanagerservice/88:99:AA:BB:CC:DD:EE:FF/port-down + * + * @param debugCounters + * @param dpid + */ + public SwitchCounters(IDebugCounterService debugCounters, DatapathId dpid) { + debugCounterService = debugCounters; + dpidString = dpid.toString(); + + /* Register the switch itself, although it's not a counter technically. + * An exception will be thrown if a sub-counter of the DPID is registered + * prior to the DPID itself. + */ + debugCounters.registerCounter(moduleName, dpidString, "Switch DPID base for counters"); + + deviceAdded = + debugCounters.registerCounter( + moduleName, dpidString + "/device-added", + "Device added to switch"); + + deviceRemoved = + debugCounters.registerCounter( + moduleName, dpidString + "/device-removed", + "Device removed from switch"); + + portEnabled = + debugCounters.registerCounter( + moduleName, dpidString + "/port-enabled", + "Port enabled on switch"); + + portDisabled = + debugCounters.registerCounter( + moduleName, dpidString + "/port-disabled", + "Port disabled on switch"); + + portUp = + debugCounters.registerCounter( + moduleName, dpidString + "/port-up", + "Port up on switch; device connected"); + + portDown = + debugCounters.registerCounter( + moduleName, dpidString + "/port-down", + "Port down on switch; device disconnected"); + + packetIn = + debugCounters.registerCounter( + moduleName, dpidString + "/packet-in", + "Packet in from switch"); + + packetOut = + debugCounters.registerCounter( + moduleName, dpidString + "/packet-out", + "Packet out to switch"); + + flowAdded = + debugCounters.registerCounter( + moduleName, dpidString + "/flow-added", + "Flow added to switch"); + flowRemoved = + debugCounters.registerCounter( + moduleName, dpidString + "/flow-removed", + "Flow removed from switch"); + } + + public String getPrefix(){ + return this.moduleName; + } + + /** + * Remove all counters from the IDebugCounterService. Should be done + * if the switch disconnects from the controller, in which case all + * the counters will be invalid. + * @return true if successful; false if switch was not found + */ + public boolean uninstallCounters() { + return debugCounterService.removeCounterHierarchy(moduleName, dpidString); + } +}