diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java index 45ef6e9978fdebf82e3476dd8dfe6b94552499b4..c4d3419eb20c4822a16746fe44c9c7466d4caeff 100644 --- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java +++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java @@ -1,7 +1,7 @@ /** -* Copyright 2011, Big Switch Networks, Inc. +* Copyright 2011, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University -* +* * 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 @@ -18,6 +18,9 @@ package net.floodlightcontroller.core.web; import net.floodlightcontroller.core.module.ModuleLoaderResource; +import net.floodlightcontroller.debugcounter.DebugCounterGetResource; +import net.floodlightcontroller.debugcounter.DebugCounterResetResource; +import net.floodlightcontroller.debugcounter.DebugCounterStateResource; import net.floodlightcontroller.restserver.RestletRoutable; import org.restlet.Context; @@ -60,6 +63,9 @@ public class CoreWebRoutable implements RestletRoutable { router.attach("/role/json", ControllerRoleResource.class); router.attach("/health/json", HealthCheckResource.class); router.attach("/system/uptime/json", SystemUptimeResource.class); + router.attach("/debugcounter/{param}/json", DebugCounterGetResource.class); + router.attach("/debugcounter/reset/{param}/json", DebugCounterResetResource.class); + router.attach("/debugcounter/{moduleCounterName}/{state}/json", DebugCounterStateResource.class); return router; } } diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java index 10fd4656cd676127a59cbfb1a1612be9c67916b9..fd88187ce69bade2cb26954622829d5ea9eeedc5 100644 --- a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java @@ -74,6 +74,12 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService { this.counterDesc = desc; this.ctype = ctype; } + + public String getModuleCounterName() { return moduleCounterName; } + public String getCounterDesc() { return counterDesc; } + public CounterType getCtype() { return ctype; } + public String getModuleName() { return moduleName; } + public String getCounterName() { return counterName; } } /** @@ -258,7 +264,7 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService { for (CounterInfo ci : cil) { if (ci.moduleCounterName.equals(moduleCounterName)) { DebugCounterInfo dci = new DebugCounterInfo(); - dci.counterinfo = ci; + dci.counterInfo = ci; dci.counterValue = counterValue; return dci; } @@ -274,7 +280,7 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService { AtomicLong ctr = debugCounters.get(ci.moduleCounterName); if (ctr != null) { DebugCounterInfo dci = new DebugCounterInfo(); - dci.counterinfo = ci; + dci.counterInfo = ci; dci.counterValue = ctr.longValue(); dcilist.add(dci); } @@ -292,7 +298,7 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService { AtomicLong ctr = debugCounters.get(ci.moduleCounterName); if (ctr != null) { DebugCounterInfo dci = new DebugCounterInfo(); - dci.counterinfo = ci; + dci.counterInfo = ci; dci.counterValue = ctr.longValue(); dcilist.add(dci); } @@ -301,6 +307,23 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService { return dcilist; } + @Override + public boolean containsMCName(String moduleCounterName) { + if (debugCounters.containsKey(moduleCounterName)) return true; + // it is possible that the counter may be disabled + for (List<CounterInfo> cil : moduleCounters.values()) { + for (CounterInfo ci : cil) { + if (ci.moduleCounterName.equals(moduleCounterName)) + return true; + } + } + return false; + } + + @Override + public boolean containsModName(String moduleName) { + return (moduleCounters.containsKey(moduleName)) ? true : false; + } //******************************* // Internal Methods @@ -316,40 +339,41 @@ public class DebugCounter implements IFloodlightModule, IDebugCounterService { } } + //******************************* + // IFloodlightModule + //******************************* - //******************************* - // IFloodlightModule - //******************************* + @Override + public Collection<Class<? extends IFloodlightService>> getModuleServices() { + Collection<Class<? extends IFloodlightService>> l = + new ArrayList<Class<? extends IFloodlightService>>(); + l.add(IDebugCounterService.class); + return l; + } - @Override - public Collection<Class<? extends IFloodlightService>> getModuleServices() { - Collection<Class<? extends IFloodlightService>> l = - new ArrayList<Class<? extends IFloodlightService>>(); - l.add(IDebugCounterService.class); - return l; - } + @Override + public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { + Map<Class<? extends IFloodlightService>, IFloodlightService> m = + new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); + m.put(IDebugCounterService.class, this); + return m; + } - @Override - public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() { - Map<Class<? extends IFloodlightService>, IFloodlightService> m = - new HashMap<Class<? extends IFloodlightService>, IFloodlightService>(); - m.put(IDebugCounterService.class, this); - return m; - } + @Override + public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { + return null; + } - @Override - public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { - return null; - } + @Override + public void init(FloodlightModuleContext context) throws FloodlightModuleException { - @Override - public void init(FloodlightModuleContext context) throws FloodlightModuleException { + } - } + @Override + public void startUp(FloodlightModuleContext context) { + + } - @Override - public void startUp(FloodlightModuleContext context) { - } } diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterGetResource.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterGetResource.java new file mode 100644 index 0000000000000000000000000000000000000000..6ef162de16785584fe5e34a359fa46538b3f6e0b --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterGetResource.java @@ -0,0 +1,130 @@ +package net.floodlightcontroller.debugcounter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.floodlightcontroller.debugcounter.IDebugCounterService.DebugCounterInfo; + +import org.restlet.resource.Get; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Return the debug counter data for the get rest-api call + * + * URI must be in one of the following forms: + * "http://<controller-hostname>:8080/wm/core/debugcounter/<param>/json + * + * where <param> must be one of (no quotes) + * all returns value/info on all active counters + * <moduleName> returns value/info on all active counters for the specified module + * <moduleCounterName> returns value/info for specific counter if it is enabled + * + * @author Saurav + */ +public class DebugCounterGetResource extends DebugCounterResourceBase { + protected static Logger logger = + LoggerFactory.getLogger(DebugCounterGetResource.class); + + /** + * The output JSON model that contains the counter information + */ + public static class DebugCounterInfoOutput { + public Map<String, DebugCounterInfo> counterMap; + public String error; + + DebugCounterInfoOutput() { + counterMap = new HashMap<String, DebugCounterInfo>(); + error = null; + } + public Map<String, DebugCounterInfo> getCounterMap() { + return counterMap; + } + + public String getError() { + return error; + } + + } + + public enum Option { + ALL, ONE_MODULE, ONE_MODULE_COUNTER, ERROR_BAD_MODULE_NAME, ERROR_BAD_PARAM, + ERROR_BAD_MODULE_COUNTER_NAME + } + + @Get("json") + public DebugCounterInfoOutput handleCounterInfoQuery() { + DebugCounterInfoOutput output = new DebugCounterInfoOutput(); + Option choice = Option.ERROR_BAD_PARAM; + + String param = (String)getRequestAttributes().get("param"); + if (param == null) { + param = "all"; + choice = Option.ALL; + } else if (param.equals("all")) { + choice = Option.ALL; + } else if (param.contains("-")) { + // differentiate between disabled and non-existing counters + boolean isRegistered = debugCounter.containsMCName(param); + if (isRegistered) { + choice = Option.ONE_MODULE_COUNTER; + } else { + choice = Option.ERROR_BAD_MODULE_COUNTER_NAME; + } + } else { + boolean isRegistered = debugCounter.containsModName(param); + if (isRegistered) { + choice = Option.ONE_MODULE; + } else { + choice = Option.ERROR_BAD_MODULE_NAME; + } + } + + switch (choice) { + case ALL: + poplulateAllCounters(debugCounter.getAllCounterValues(), output); + break; + case ONE_MODULE: + populateModuleCounters(debugCounter.getModuleCounterValues(param), output); + break; + case ONE_MODULE_COUNTER: + populateSingleCounter(debugCounter.getCounterValue(param), output); + break; + case ERROR_BAD_MODULE_NAME: + output.error = "Module name has no corresponding registered counters"; + break; + case ERROR_BAD_MODULE_COUNTER_NAME: + output.error = "Counter not registered"; + break; + case ERROR_BAD_PARAM: + output.error = "Bad param"; + } + + return output; + } + + private void populateSingleCounter(DebugCounterInfo debugCounterInfo, + DebugCounterInfoOutput output) { + if (debugCounterInfo != null) + output.counterMap.put(debugCounterInfo.counterInfo.moduleCounterName, + debugCounterInfo); + } + + private void populateModuleCounters(List<DebugCounterInfo> moduleCounterValues, + DebugCounterInfoOutput output) { + for (DebugCounterInfo dci : moduleCounterValues) { + populateSingleCounter(dci, output); + } + } + + private void poplulateAllCounters(List<DebugCounterInfo> allCounterValues, + DebugCounterInfoOutput output) { + for (DebugCounterInfo dci : allCounterValues) { + populateSingleCounter(dci, output); + } + } + + + +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResetResource.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResetResource.java new file mode 100644 index 0000000000000000000000000000000000000000..4c0d1f6cda632a7948edd11ac160411b262fd976 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResetResource.java @@ -0,0 +1,98 @@ +package net.floodlightcontroller.debugcounter; + +import org.restlet.resource.Get; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Reset debug counter values + * + * URI must be in one of the following forms: " + + * "http://<controller-hostname>:8080/wm/core/debugcounter/reset/<param>/json + * + * where <param> must be one of (no quotes) + * all resets all active counters + * <moduleName> resets all active counters for the specified module + * <moduleCounterName> resets specific counter if it is enabled + * + * @author Saurav + */ +public class DebugCounterResetResource extends DebugCounterResourceBase { + protected static Logger logger = + LoggerFactory.getLogger(DebugCounterGetResource.class); + + public enum Option { + ALL, ONE_MODULE, ONE_MODULE_COUNTER, ERROR_BAD_MODULE_NAME, ERROR_BAD_PARAM, + ERROR_BAD_MODULE_COUNTER_NAME + } + + public static class ResetOutput { + String error; + + public ResetOutput() { + error = null; + } + + public String getError() { + return error; + } + + } + + @Get("json") + public ResetOutput handleCounterResetCmd() { + Option choice = Option.ERROR_BAD_PARAM; + ResetOutput output = new ResetOutput(); + + String param = (String)getRequestAttributes().get("param"); + if (param == null) { + param = "all"; + choice = Option.ALL; + } else if (param.equals("all")) { + choice = Option.ALL; + } else if (param.contains("-")) { + // differentiate between disabled and non-existing counters + boolean isRegistered = debugCounter.containsMCName(param); + if (isRegistered) { + choice = Option.ONE_MODULE_COUNTER; + } else { + choice = Option.ERROR_BAD_MODULE_COUNTER_NAME; + } + } else { + boolean isRegistered = debugCounter.containsModName(param); + if (isRegistered) { + choice = Option.ONE_MODULE; + } else { + choice = Option.ERROR_BAD_MODULE_NAME; + } + } + + switch (choice) { + case ALL: + debugCounter.resetAllCounters(); + output.error = "None"; + break; + case ONE_MODULE: + debugCounter.resetAllModuleCounters(param); + output.error = "None"; + break; + case ONE_MODULE_COUNTER: + debugCounter.resetCounter(param); + output.error = "None"; + break; + case ERROR_BAD_MODULE_NAME: + output.error = "Module name has no corresponding registered counters"; + break; + case ERROR_BAD_MODULE_COUNTER_NAME: + output.error = "Counter not registered"; + break; + case ERROR_BAD_PARAM: + output.error = "Bad param"; + } + + return output; + } + + + +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java new file mode 100644 index 0000000000000000000000000000000000000000..9edd47473a75564334c217b240002612d31e6219 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java @@ -0,0 +1,16 @@ +package net.floodlightcontroller.debugcounter; + +import org.restlet.resource.ResourceException; +import org.restlet.resource.ServerResource; + +public class DebugCounterResourceBase extends ServerResource { + + protected IDebugCounterService debugCounter; + + @Override + protected void doInit() throws ResourceException { + super.doInit(); + debugCounter = (IDebugCounterService)getContext().getAttributes(). + get(IDebugCounterService.class.getCanonicalName()); + } +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterStateResource.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterStateResource.java new file mode 100644 index 0000000000000000000000000000000000000000..daff21c619c04e11d76391440bb56d0bfa802a03 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterStateResource.java @@ -0,0 +1,17 @@ +package net.floodlightcontroller.debugcounter; + +/** + * Enable/disable on-demand counters + * + * URI must be in one of the following forms: " + + * "http://<controller-hostname>:8080/wm/core/debugcounter/<moduleCounterName>/<state>/json + * + * where <state> must be one of (no quotes) + * enable enables counter <moduleCounterName> if it is an on-demand counter + * disable disables counter <moduleCounterName> if it is an on-demand counter + * + * @author Saurav + */ +public class DebugCounterStateResource extends DebugCounterResourceBase { + +} diff --git a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java index 807144021edca9b512f28dd060cf9a74332cd06e..18fab72cbb7bfe43035377d720b0718b7d4e1331 100644 --- a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java +++ b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java @@ -16,8 +16,15 @@ public interface IDebugCounterService extends IFloodlightService { } public class DebugCounterInfo { - CounterInfo counterinfo; + CounterInfo counterInfo; Long counterValue; + + public CounterInfo getCounterInfo() { + return counterInfo; + } + public Long getCounterValue() { + return counterValue; + } } /** @@ -103,7 +110,8 @@ public interface IDebugCounterService extends IFloodlightService { public void disableCtrOnDemand(String moduleCounterName); /** - * Get counter value and associated information for a specific counter + * Get counter value and associated information for a specific counter if it + * is active. * * @param moduleCounterName * @return DebugCounterInfo or null if the counter could not be found @@ -111,14 +119,14 @@ public interface IDebugCounterService extends IFloodlightService { public DebugCounterInfo getCounterValue(String moduleCounterName); /** - * Get counter values and associated information for all counters + * Get counter values and associated information for all active counters * * @return the list of values/info or an empty list */ public List<DebugCounterInfo> getAllCounterValues(); /** - * Get counter values and associated information for all counters associated + * Get counter values and associated information for all active counters associated * with a module. * * @param moduleName @@ -126,4 +134,26 @@ public interface IDebugCounterService extends IFloodlightService { */ public List<DebugCounterInfo> getModuleCounterValues(String moduleName); + /** + * Convenience method to figure out if the the given 'moduleCounterName' corresponds + * to a registered moduleCounterName or not. Note that the counter may or + * may not be enabled for counting, but if it is registered the method will + * return true. + * + * @param param + * @return false if moduleCounterName is not a registered counter + */ + public boolean containsMCName(String moduleCounterName); + + /** + * Convenience method to figure out if the the given 'moduleName' corresponds + * to a registered moduleName or not. Note that the module may or may not have + * a counter enabled for counting, but if it is registered the method will + * return true. + * + * @param param + * @return false if moduleName is not a registered counter + */ + public boolean containsModName(String moduleName); + } diff --git a/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java index 8b6a1cb1972ea3806a6dca67ad76707e1ababb11..5e5ffbba2f3de68af207d63c08909451bd032186 100644 --- a/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java +++ b/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java @@ -99,4 +99,14 @@ public class NullDebugCounter implements IFloodlightModule, IDebugCounterService return null; } + @Override + public boolean containsMCName(String moduleCounterName) { + return false; + } + + @Override + public boolean containsModName(String moduleName) { + return false; + } + } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index 52ebdf0493fcdc5e60e595df0273d761810e8d1d..8b228836c1fc1e9434eeb8f95cc0bb059b45a274 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -759,10 +759,10 @@ IFlowReconcileListener, IInfoProvider, IHAListener { logger.debug("Could not instantiate REST API"); } - registerLinkDiscoveryDebugCounters(); + registerDeviceManagerDebugCounters(); } - private void registerLinkDiscoveryDebugCounters() { + private void registerDeviceManagerDebugCounters() { if (debugCounters == null) { logger.error("Debug Counter Service not found."); debugCounters = new NullDebugCounter(); diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java index 1904a58c61af16431fb43426cae27755950f79a2..1543783aee6af49bce384e0691d1dc4f4a935e94 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java @@ -766,10 +766,10 @@ public class TopologyManager implements floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); floodlightProvider.addHAListener(this); addRestletRoutable(); - registerLinkDiscoveryDebugCounters(); + registerTopologyDebugCounters(); } - private void registerLinkDiscoveryDebugCounters() { + private void registerTopologyDebugCounters() { if (debugCounters == null) { log.error("Debug Counter Service not found."); debugCounters = new NullDebugCounter();