From 0db7b9f79696495ec45619eb71be05aef1616bff Mon Sep 17 00:00:00 2001
From: Saurav Das <saurav.das@bigswitch.com>
Date: Tue, 26 Mar 2013 09:44:53 -0700
Subject: [PATCH] First check-in for debug counters

---
 .../core/FloodlightProvider.java              |   9 +-
 .../core/internal/Controller.java             |  25 +-
 .../counter/CounterStore.java                 |  33 +--
 .../debugcounter/DebugCounter.java            | 265 ++++++++++++++++++
 .../debugcounter/IDebugCounterService.java    |  76 +++++
 .../debugcounter/NullDebugCounter.java        | 118 ++++++++
 .../internal/DeviceManagerImpl.java           |  20 ++
 .../internal/LinkDiscoveryManager.java        |  21 +-
 .../topology/TopologyManager.java             |  17 ++
 ...htcontroller.core.module.IFloodlightModule |   2 +
 .../resources/floodlightdefault.properties    |   1 +
 11 files changed, 552 insertions(+), 35 deletions(-)
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java

diff --git a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
index da421e55b..df542f03f 100644
--- a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
+++ b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
@@ -27,6 +27,7 @@ import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.counter.ICounterStoreService;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.flowcache.IFlowCacheService;
 import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
 import net.floodlightcontroller.restserver.IRestApiService;
@@ -35,7 +36,7 @@ import net.floodlightcontroller.threadpool.IThreadPoolService;
 
 public class FloodlightProvider implements IFloodlightModule {
     Controller controller;
-    
+
     @Override
     public Collection<Class<? extends IFloodlightService>> getModuleServices() {
         Collection<Class<? extends IFloodlightService>> services =
@@ -48,9 +49,9 @@ public class FloodlightProvider implements IFloodlightModule {
     public Map<Class<? extends IFloodlightService>,
                IFloodlightService> getServiceImpls() {
         controller = new Controller();
-        
+
         Map<Class<? extends IFloodlightService>,
-            IFloodlightService> m = 
+            IFloodlightService> m =
                 new HashMap<Class<? extends IFloodlightService>,
                             IFloodlightService>();
         m.put(IFloodlightProviderService.class, controller);
@@ -78,6 +79,8 @@ public class FloodlightProvider implements IFloodlightModule {
            context.getServiceImpl(IPktInProcessingTimeService.class));
        controller.setCounterStore(
            context.getServiceImpl(ICounterStoreService.class));
+       controller.setDebugCounter(
+           context.getServiceImpl(IDebugCounterService.class));
        controller.setFlowCacheMgr(
            context.getServiceImpl(IFlowCacheService.class));
        controller.setRestApiService(
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 607835b71..21e1244a3 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -66,6 +66,7 @@ import net.floodlightcontroller.core.util.ListenerDispatcher;
 import net.floodlightcontroller.core.util.SingletonTask;
 import net.floodlightcontroller.core.web.CoreWebRoutable;
 import net.floodlightcontroller.counter.ICounterStoreService;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.flowcache.IFlowCacheService;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
@@ -172,6 +173,7 @@ public class Controller implements IFloodlightProviderService,
     // Module dependencies
     protected IRestApiService restApi;
     protected ICounterStoreService counterStore = null;
+    protected IDebugCounterService debugCounter;
     protected IFlowCacheService bigFlowCacheMgr;
     protected IStorageSourceService storageSource;
     protected IPktInProcessingTimeService pktinProcTime;
@@ -191,7 +193,7 @@ public class Controller implements IFloodlightProviderService,
     // we have sent to the listeners. On a transition to slave we first set
     // this role and then notify, on a transition to master we first notify
     // and then set the role. We then use it to make sure we don't forward
-    // OF messages while the modules are in slave role. 
+    // OF messages while the modules are in slave role.
     // The pendingRole is a role change just received, but not sent out
     // notifications yet.
     protected Role pendingRole;
@@ -302,7 +304,7 @@ public class Controller implements IFloodlightProviderService,
                           newRole, oldRole);
             }
             // Set notified role to slave before notifying listeners. This
-            // stops OF messages from being sent to listeners 
+            // stops OF messages from being sent to listeners
             if (newRole == Role.SLAVE)
                 Controller.this.notifiedRole = newRole;
             if (haListeners != null) {
@@ -310,7 +312,7 @@ public class Controller implements IFloodlightProviderService,
                         listener.roleChanged(oldRole, newRole);
                 }
             }
-            // Set notified role to master/equal after notifying listeners. 
+            // Set notified role to master/equal after notifying listeners.
             // We now forward messages again
             if (newRole != Role.SLAVE)
                 Controller.this.notifiedRole = newRole;
@@ -363,6 +365,10 @@ public class Controller implements IFloodlightProviderService,
         this.counterStore = counterStore;
     }
 
+    public void setDebugCounter(IDebugCounterService debugCounter) {
+        this.debugCounter = debugCounter;
+    }
+
     public void setFlowCacheMgr(IFlowCacheService flowCacheMgr) {
         this.bigFlowCacheMgr = flowCacheMgr;
     }
@@ -669,6 +675,7 @@ public class Controller implements IFloodlightProviderService,
                 // Flush all flow-mods/packet-out/stats generated from this "train"
                 OFSwitchBase.flush_all();
                 counterStore.updateFlush();
+                debugCounter.flushCounters();
                 bigFlowCacheMgr.updateFlush();
             }
         }
@@ -1061,7 +1068,7 @@ public class Controller implements IFloodlightProviderService,
 
                         if (sw.isConnected()) {
                             // Only dispatch message if the switch is in the
-                            // activeSwitch map and if the switches role is 
+                            // activeSwitch map and if the switches role is
                             // not slave and the modules are not in slave
                             // TODO: Should we dispatch messages that we expect to
                             // receive when we're in the slave role, e.g. port
@@ -1071,7 +1078,7 @@ public class Controller implements IFloodlightProviderService,
                             // to them. On the other hand there might be special
                             // modules that care about all of the connected switches
                             // and would like to receive port status notifications.
-                            if (sw.getHARole() == Role.SLAVE || 
+                            if (sw.getHARole() == Role.SLAVE ||
                                     notifiedRole == Role.SLAVE ||
                                     !activeSwitches.containsKey(sw.getId())) {
                                 // Don't log message if it's a port status message
@@ -1182,7 +1189,7 @@ public class Controller implements IFloodlightProviderService,
                                  FloodlightContext bContext)
             throws IOException {
         Ethernet eth = null;
-        
+
         switch (m.getType()) {
             case PACKET_IN:
                 OFPacketIn pi = (OFPacketIn)m;
@@ -1248,9 +1255,9 @@ public class Controller implements IFloodlightProviderService,
                     }
                     pktinProcTime.recordEndTimePktIn(sw, m, bc);
                 } else {
-                    if (m.getType() != OFType.BARRIER_REPLY) 
+                    if (m.getType() != OFType.BARRIER_REPLY)
                         log.warn("Unhandled OF Message: {} from {}", m, sw);
-                    else 
+                    else
                         log.debug("Received a Barrier Reply, no listeners for it");
                 }
 
@@ -1758,7 +1765,7 @@ public class Controller implements IFloodlightProviderService,
             this.workerThreads = Integer.parseInt(threads);
         }
         log.debug("Number of worker threads set to {}", this.workerThreads);
-        
+
     }
 
     private void initVendorMessages() {
diff --git a/src/main/java/net/floodlightcontroller/counter/CounterStore.java b/src/main/java/net/floodlightcontroller/counter/CounterStore.java
index 9f886dc30..df01fab08 100644
--- a/src/main/java/net/floodlightcontroller/counter/CounterStore.java
+++ b/src/main/java/net/floodlightcontroller/counter/CounterStore.java
@@ -15,9 +15,6 @@
  *    under the License.
  **/
 
-/**
- * Implements a very simple central store for system counters
- */
 package net.floodlightcontroller.counter;
 
 import java.util.ArrayList;
@@ -41,6 +38,17 @@ import org.openflow.protocol.OFPacketIn;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Implements a central store for system counters. These counters include
+ * overall packet-in, packet-out, and flow-mod counters. Additional packet-in
+ * counters are maintained for bcast/unicast/multicast traffic, as well as counters
+ * for traffic types based on ethertype and ip-proto (maintained on a per switch
+ * and controller level). These counters are maintained without the involvement of
+ * any other module in the system. For per-module counters and other detailed
+ * debug services, consider IDebugCounterService.
+ *
+ *  @authors Kyle, Kanzhe, Mandeep and Saurav
+ */
 public class CounterStore implements IFloodlightModule, ICounterStoreService {
     protected static Logger log = LoggerFactory.getLogger(CounterStore.class);
 
@@ -134,8 +142,6 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
     protected ConcurrentHashMap<String, CounterEntry> nameToCEIndex =
             new ConcurrentHashMap<String, CounterEntry>();
 
-
-
     /**
      * Counter Categories grouped by network layers
      * NetworkLayer -> CounterToCategories
@@ -284,23 +290,6 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
     //   Internal Methods
     //*******************************
 
-    protected void printAllKeys() {
-
-        for (Map.Entry<String, CounterEntry> counterEntry : this.nameToCEIndex.entrySet()) {
-            log.info("concurrenthashmapkeys: {}", counterEntry.getKey());
-        }
-
-        for (CounterKeyTuple ctr : pktinCounters.keySet()) {
-            log.info("pktinglobalkeys: {}", ctr);
-        }
-
-        Map<CounterKeyTuple, MutableInt> pktin_buffer = this.pktin_local_buffer.get();
-        for (CounterKeyTuple key : pktin_buffer.keySet()) {
-            log.info("localbufferkeys: {}", key);
-        }
-        log.info("done");
-    }
-
     protected CounterKeyTuple getCountersKey(IOFSwitch sw, OFMessage m, Ethernet eth) {
         byte mtype = m.getType().getTypeValue();
         short l3type = 0;
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java
new file mode 100644
index 000000000..34c48c8ff
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java
@@ -0,0 +1,265 @@
+package net.floodlightcontroller.debugcounter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+/**
+ * This class implements a central store for all counters used for debugging the
+ * system. For counters based on traffic-type, see ICounterStoreService.
+ *
+ * @author Saurav
+ */
+public class DebugCounter implements IFloodlightModule, IDebugCounterService {
+    protected static Logger log = LoggerFactory.getLogger(DebugCounter.class);
+
+    /**
+     * The counter value
+     */
+    protected class MutableLong {
+        long value = 0;
+        public void increment() { value += 1; }
+        public long get() { return value; }
+        public void set(long val) { value = val; }
+      }
+
+    /**
+     * Global debug-counter storage across all threads. These are
+     * updated from the local per thread counters by the update FIXME method.
+     */
+    protected ConcurrentHashMap<String, AtomicLong> debugCounters =
+            new ConcurrentHashMap<String, AtomicLong>();
+
+    /**
+     * Thread local debug counters used for maintaining counters local to a thread.
+     */
+    protected final ThreadLocal<Map<String, MutableLong>> threadlocalCounters =
+            new ThreadLocal<Map<String, MutableLong>>() {
+        @Override
+        protected Map<String, MutableLong> initialValue() {
+            return new HashMap<String, MutableLong>();
+        }
+    };
+
+    /**
+     * protected class to store counter information
+     */
+    protected class CounterInfo {
+        String moduleCounterName;
+        String counterDesc;
+        CounterType ctype;
+        String moduleName;
+        String counterName;
+
+        public CounterInfo(String name, String desc, CounterType ctype) {
+            this.moduleCounterName = name;
+            String[] temp = name.split("-");
+            this.moduleName = temp[0];
+            this.counterName = temp[1];
+            this.counterDesc = desc;
+            this.ctype = ctype;
+        }
+    }
+
+    /**
+     * per module counters, indexed by the module name and storing Counter information.
+     */
+    protected ConcurrentHashMap<String, List<CounterInfo>> moduleCounters =
+            new ConcurrentHashMap<String, List<CounterInfo>>();
+
+    /**
+     * fast cache for counter names that are currently active
+     */
+    Set<String> currentCounters = Collections.newSetFromMap(
+                                      new ConcurrentHashMap<String,Boolean>());
+
+   //*******************************
+   //   IDebugCounterService
+   //*******************************
+
+   @Override
+   public boolean registerCounter(String moduleCounterName, String counterDescription,
+                               CounterType counterType) {
+       if (debugCounters.containsKey(moduleCounterName)) {
+           log.error("Cannot register counter: {}. Counter already exists",
+                     moduleCounterName);
+           return false;
+       }
+       String[] temp = moduleCounterName.split("-");
+       if (temp.length < 2) {
+           log.error("Cannot register counter: {}. Name not of type " +
+                     " <module name>-<counter name>", moduleCounterName);
+           return false;
+       }
+
+       // store counter information on a per module basis
+       String moduleName = temp[0];
+       List<CounterInfo> a;
+       if (moduleCounters.containsKey(moduleName)) {
+           a = moduleCounters.get(moduleName);
+       } else {
+           a = new ArrayList<CounterInfo>();
+           moduleCounters.put(moduleName, a);
+       }
+       a.add(new CounterInfo(moduleCounterName, counterDescription, counterType));
+
+       // create counter in global map
+       debugCounters.put(moduleCounterName, new AtomicLong());
+
+       // create counter in local thread map
+       Map<String, MutableLong> thismap =  this.threadlocalCounters.get();
+       MutableLong ml = thismap.get(moduleCounterName);
+       if (ml == null) {
+           thismap.put(moduleCounterName, new MutableLong());
+       }
+
+       // finally add to cache if it is meant to be always counted
+       if (counterType == CounterType.ALWAYS_COUNT) {
+           currentCounters.add(moduleCounterName);
+       }
+       return true;
+   }
+
+   @Override
+   public void updateCounter(String moduleCounterName) {
+       if (currentCounters.contains(moduleCounterName)) {
+           Map<String, MutableLong> thismap =  this.threadlocalCounters.get();
+           MutableLong ml = thismap.get(moduleCounterName);
+           if (ml == null) {
+               ml = new MutableLong();
+               thismap.put(moduleCounterName, ml);
+           }
+           ml.increment();
+       }
+   }
+
+   @Override
+   public void flushCounters() {
+       Map<String, MutableLong> thismap =  this.threadlocalCounters.get();
+       for (String key : thismap.keySet()) {
+           MutableLong curval = thismap.get(key);
+           long delta = curval.get();
+           if (delta > 0) {
+               debugCounters.get(key).addAndGet(delta);
+               curval.set(0);
+           }
+       }
+       printAllCounters();
+   }
+
+   @Override
+   public void resetCounter(String moduleCounterName) {
+       // TODO Auto-generated method stub
+
+   }
+
+   @Override
+   public void resetAllCounters() {
+       // TODO Auto-generated method stub
+
+   }
+
+   @Override
+   public void resetAllModuleCounters(String moduleName) {
+       // TODO Auto-generated method stub
+
+   }
+
+   @Override
+   public void enableCtrOnDemand(String moduleCounterName) {
+       // TODO Auto-generated method stub
+
+   }
+
+   @Override
+   public void disableCtrOnDemand(String moduleCounterName) {
+       // TODO Auto-generated method stub
+
+   }
+
+   @Override
+   public DebugCounterInfo getCounterValue(String moduleCounterName) {
+       // TODO Auto-generated method stub
+       return null;
+   }
+
+   @Override
+   public List<DebugCounterInfo> getAllCounterValues() {
+       // TODO Auto-generated method stub
+       return null;
+   }
+
+   @Override
+   public List<DebugCounterInfo> getModuleCounterValues() {
+       // TODO Auto-generated method stub
+       return null;
+   }
+
+
+   //*******************************
+   //   Internal Methods
+   //*******************************
+
+   private void printAllCounters() {
+       for (List<CounterInfo> cilist : moduleCounters.values()) {
+           for (CounterInfo ci : cilist) {
+               log.info("Countername {} Countervalue {}", new Object[] {
+                    ci.moduleCounterName, debugCounters.get(ci.moduleCounterName)
+               });
+           }
+       }
+   }
+
+
+    //*******************************
+    //   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 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() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context) throws FloodlightModuleException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+        // TODO Auto-generated method stub
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java
new file mode 100644
index 000000000..6e10e13ac
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java
@@ -0,0 +1,76 @@
+package net.floodlightcontroller.debugcounter;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.debugcounter.DebugCounter.CounterInfo;
+import java.util.List;
+
+public interface IDebugCounterService extends IFloodlightService {
+
+    /**
+     * Different counter types.
+     */
+    public enum CounterType {
+        ALWAYS_COUNT,
+        COUNT_ON_DEMAND
+    }
+
+    public class DebugCounterInfo {
+        CounterInfo counterinfo;
+        Long counterValue;
+    }
+
+    /**
+     * All modules that wish to have the DebugCounterService count for them, must
+     * register their counters by making this call (typically from that module's
+     * 'startUp' method). The counter can then be updated, displayed, reset etc.
+     * using the registered moduleCounterName.
+     *
+     * @param moduleCounterName    the counter name which MUST be have the following
+     *                             syntax:  <module name>-<counter name>
+     *                             eg.: linkdiscovery-incoming
+     * @param counterDescription   a descriptive string that gives more information
+     *                             of what the counter is measuring. For example,
+     *                             "Measures the number of incoming packets seen by
+     *                             this module".
+     * @param counterType          One of CounterType. COUNT_ON_DEMAND counter types
+     *                             need to be explicitly enabled/disabled using other
+     *                             methods in this API -- i.e. registering them is
+     *                             not enough to start counting.
+     * @return                     false if the counter has already been registered
+     *                             or if the moduleCounterName is not as expected.
+     */
+    public boolean registerCounter(String moduleCounterName, String counterDescription,
+                                   CounterType counterType);
+
+    /**
+     * Increments the counter by 1.
+     * @param moduleCounterName   the registered counter name.
+     */
+    public void updateCounter(String moduleCounterName);
+
+    /**
+     * Update the global counter map with values from the thread local maps
+     */
+    public void flushCounters();
+
+    /**
+     *
+     * @param moduleCounterName
+     */
+    public void resetCounter(String moduleCounterName);
+
+    public void resetAllCounters();
+
+    public void resetAllModuleCounters(String moduleName);
+
+    public void enableCtrOnDemand(String moduleCounterName);
+
+    public void disableCtrOnDemand(String moduleCounterName);
+
+    public DebugCounterInfo getCounterValue(String moduleCounterName);
+
+    public  List<DebugCounterInfo> getAllCounterValues();
+
+    public  List<DebugCounterInfo> getModuleCounterValues();
+
+}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java
new file mode 100644
index 000000000..3807f9d96
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java
@@ -0,0 +1,118 @@
+package net.floodlightcontroller.debugcounter;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+public class NullDebugCounter implements IFloodlightModule, IDebugCounterService {
+
+    @Override
+    public boolean registerCounter(String moduleCounterName,
+                                   String counterDescription,
+                                   CounterType counterType) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleServices() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService>
+            getServiceImpls() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleDependencies() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public
+            void
+            init(FloodlightModuleContext context)
+                                                 throws FloodlightModuleException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateCounter(String moduleCounterName) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void flushCounters() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void resetCounter(String moduleCounterName) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void resetAllCounters() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void resetAllModuleCounters(String moduleName) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void enableCtrOnDemand(String moduleCounterName) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void disableCtrOnDemand(String moduleCounterName) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public DebugCounterInfo getCounterValue(String moduleCounterName) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<DebugCounterInfo> getAllCounterValues() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<DebugCounterInfo> getModuleCounterValues() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index c58999b17..4e8ed9491 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -49,6 +49,9 @@ import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.ListenerDispatcher;
 import net.floodlightcontroller.core.util.SingletonTask;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.debugcounter.NullDebugCounter;
+import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
 import net.floodlightcontroller.devicemanager.IDevice;
 import net.floodlightcontroller.devicemanager.IDeviceService;
 import net.floodlightcontroller.devicemanager.IEntityClass;
@@ -104,6 +107,7 @@ IFlowReconcileListener, IInfoProvider, IHAListener {
     protected IRestApiService restApi;
     protected IThreadPoolService threadPool;
     protected IFlowReconcileService flowReconcileMgr;
+    protected IDebugCounterService debugCounters;
 
     /**
      * Time in milliseconds before entities will expire
@@ -593,6 +597,9 @@ IFlowReconcileListener, IInfoProvider, IHAListener {
                            FloodlightContext cntx) {
         switch (msg.getType()) {
             case PACKET_IN:
+                debugCounters.updateCounter("devicemanager-incoming");
+                logger.info("Received PI: {} on switch {}, port {} ***",
+                        new Object[] { (OFPacketIn)msg, sw.getStringId() });
                 return this.processPacketInMessage(sw,
                                                    (OFPacketIn) msg, cntx);
             default:
@@ -715,6 +722,7 @@ IFlowReconcileListener, IInfoProvider, IHAListener {
         this.threadPool = fmc.getServiceImpl(IThreadPoolService.class);
         this.flowReconcileMgr = fmc.getServiceImpl(IFlowReconcileService.class);
         this.entityClassifier = fmc.getServiceImpl(IEntityClassifierService.class);
+        this.debugCounters = fmc.getServiceImpl(IDebugCounterService.class);
     }
 
     @Override
@@ -752,6 +760,18 @@ IFlowReconcileListener, IInfoProvider, IHAListener {
         } else {
             logger.debug("Could not instantiate REST API");
         }
+
+        registerLinkDiscoveryDebugCounters();
+    }
+
+    private void registerLinkDiscoveryDebugCounters() {
+        if (debugCounters == null) {
+            logger.error("Debug Counter Service not found.");
+            debugCounters = new NullDebugCounter();
+            return;
+        }
+        debugCounters.registerCounter(getName() + "-" + "incoming",
+            "All incoming packets seen by this module", CounterType.ALWAYS_COUNT);
     }
 
     // ***************
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
index 2e11e995d..fbd05a10e 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
@@ -57,6 +57,9 @@ 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.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
+import net.floodlightcontroller.debugcounter.NullDebugCounter;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LinkType;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.SwitchType;
@@ -142,6 +145,7 @@ public class LinkDiscoveryManager implements IOFMessageListener,
     protected IStorageSourceService storageSource;
     protected IThreadPoolService threadPool;
     protected IRestApiService restApi;
+    protected IDebugCounterService debugCounters;
 
     // LLDP and BDDP fields
     private static final byte[] LLDP_STANDARD_DST_MAC_STRING =
@@ -510,6 +514,7 @@ public class LinkDiscoveryManager implements IOFMessageListener,
                            FloodlightContext cntx) {
         switch (msg.getType()) {
             case PACKET_IN:
+                debugCounters.updateCounter("linkdiscovery-incoming");
                 return this.handlePacketIn(sw.getId(), (OFPacketIn) msg,
                                            cntx);
             case PORT_STATUS:
@@ -991,7 +996,8 @@ public class LinkDiscoveryManager implements IOFMessageListener,
         lldpClock = (lldpClock + 1) % LLDP_TO_ALL_INTERVAL;
 
         if (lldpClock == 0) {
-            log.debug("Sending LLDP out on all ports.");
+            if (log.isTraceEnabled())
+                log.trace("Sending LLDP out on all ports.");
             discoverOnAllPorts();
         }
     }
@@ -2095,6 +2101,7 @@ public class LinkDiscoveryManager implements IOFMessageListener,
         storageSource = context.getServiceImpl(IStorageSourceService.class);
         threadPool = context.getServiceImpl(IThreadPoolService.class);
         restApi = context.getServiceImpl(IRestApiService.class);
+        debugCounters = context.getServiceImpl(IDebugCounterService.class);
 
         // read our config options
         Map<String, String> configOptions = context.getConfigParams(this);
@@ -2177,6 +2184,8 @@ public class LinkDiscoveryManager implements IOFMessageListener,
                       + "switch table {}", SWITCH_CONFIG_TABLE_NAME);
         }
 
+        registerLinkDiscoveryDebugCounters();
+
         ScheduledExecutorService ses = threadPool.getScheduledExecutor();
 
         // To be started by the first switch connection
@@ -2250,6 +2259,16 @@ public class LinkDiscoveryManager implements IOFMessageListener,
         setControllerTLV();
     }
 
+    private void registerLinkDiscoveryDebugCounters() {
+        if (debugCounters == null) {
+            log.error("Debug Counter Service not found.");
+            debugCounters = new NullDebugCounter();
+            return;
+        }
+        debugCounters.registerCounter(getName() + "-" + "incoming",
+            "All incoming packets seen by this module", CounterType.ALWAYS_COUNT);
+    }
+
     // ****************************************************
     // Topology Manager's Event History members and methods
     // ****************************************************
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index 9bc0f030f..1904a58c6 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -44,6 +44,9 @@ import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.SingletonTask;
 import net.floodlightcontroller.counter.ICounterStoreService;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.debugcounter.NullDebugCounter;
+import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
 import net.floodlightcontroller.packet.BSN;
@@ -111,6 +114,7 @@ public class TopologyManager implements
     protected IThreadPoolService threadPool;
     protected IFloodlightProviderService floodlightProvider;
     protected IRestApiService restApi;
+    protected IDebugCounterService debugCounters;
 
     // Modules that listen to our updates
     protected ArrayList<ITopologyListener> topologyAware;
@@ -645,6 +649,7 @@ public class TopologyManager implements
                            FloodlightContext cntx) {
         switch (msg.getType()) {
             case PACKET_IN:
+                debugCounters.updateCounter("topology-incoming");
                 return this.processPacketInMessage(sw,
                                                    (OFPacketIn) msg, cntx);
             default:
@@ -735,6 +740,7 @@ public class TopologyManager implements
         floodlightProvider =
                 context.getServiceImpl(IFloodlightProviderService.class);
         restApi = context.getServiceImpl(IRestApiService.class);
+        debugCounters = context.getServiceImpl(IDebugCounterService.class);
 
         switchPorts = new HashMap<Long,Set<Short>>();
         switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
@@ -760,6 +766,17 @@ public class TopologyManager implements
         floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
         floodlightProvider.addHAListener(this);
         addRestletRoutable();
+        registerLinkDiscoveryDebugCounters();
+    }
+
+    private void registerLinkDiscoveryDebugCounters() {
+        if (debugCounters == null) {
+            log.error("Debug Counter Service not found.");
+            debugCounters = new NullDebugCounter();
+            return;
+        }
+        debugCounters.registerCounter(getName() + "-" + "incoming",
+            "All incoming packets seen by this module", CounterType.ALWAYS_COUNT);
     }
 
     protected void addRestletRoutable() {
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index 935fe105c..dc38c05b9 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -16,6 +16,8 @@ net.floodlightcontroller.hub.Hub
 net.floodlightcontroller.jython.JythonDebugInterface
 net.floodlightcontroller.counter.CounterStore
 net.floodlightcontroller.counter.NullCounterStore
+net.floodlightcontroller.debugcounter.DebugCounter
+net.floodlightcontroller.debugcounter.NullDebugCounter
 net.floodlightcontroller.threadpool.ThreadPool
 net.floodlightcontroller.ui.web.StaticWebRoutable
 net.floodlightcontroller.virtualnetwork.VirtualNetworkFilter
diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties
index 30dfdcaaa..2d384d3a1 100644
--- a/src/main/resources/floodlightdefault.properties
+++ b/src/main/resources/floodlightdefault.properties
@@ -12,6 +12,7 @@ net.floodlightcontroller.flowcache.FlowCache, \
 net.floodlightcontroller.flowcache.FlowReconcileManager, \
 net.floodlightcontroller.jython.JythonDebugInterface,\
 net.floodlightcontroller.counter.CounterStore,\
+net.floodlightcontroller.debugcounter.DebugCounter,\
 net.floodlightcontroller.perfmon.PktInProcessingTime,\
 net.floodlightcontroller.ui.web.StaticWebRoutable,\
 net.floodlightcontroller.loadbalancer.LoadBalancer
-- 
GitLab