diff --git a/src/main/java/net/floodlightcontroller/statistics/IStatisticsService.java b/src/main/java/net/floodlightcontroller/statistics/IStatisticsService.java
new file mode 100644
index 0000000000000000000000000000000000000000..46d41fc7986d1ab5e7d36c1f7bd4b70f74d4f905
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/statistics/IStatisticsService.java
@@ -0,0 +1,16 @@
+package net.floodlightcontroller.statistics;
+
+import java.util.Map;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.topology.NodePortTuple;
+
+public interface IStatisticsService extends IFloodlightService {
+
+	public SwitchPortBandwidth getBandwidthConsumption(DatapathId dpid, OFPort p);
+		
+	public Map<NodePortTuple, SwitchPortBandwidth> getBandwidthConsumption();
+}
diff --git a/src/main/java/net/floodlightcontroller/statistics/StatisticsCollector.java b/src/main/java/net/floodlightcontroller/statistics/StatisticsCollector.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ee967c562882427817fd78ce7ca8f8f54547634
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/statistics/StatisticsCollector.java
@@ -0,0 +1,359 @@
+package net.floodlightcontroller.statistics;
+
+import java.lang.Thread.State;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.ver13.OFMeterSerializerVer13;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TableId;
+import org.projectfloodlight.openflow.types.U64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.primitives.UnsignedLong;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.internal.IOFSwitchService;
+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.restserver.IRestApiService;
+import net.floodlightcontroller.statistics.web.SwitchStatisticsWebRoutable;
+import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.floodlightcontroller.topology.NodePortTuple;
+
+public class StatisticsCollector implements IFloodlightModule, IStatisticsService {
+	private static final Logger log = LoggerFactory.getLogger(StatisticsCollector.class);
+
+	private static IOFSwitchService switchService;
+	private static IThreadPoolService threadPoolService;
+	private static IRestApiService restApiService;
+
+	private static int portStatsInterval = 10;
+
+	private static final long BITS_PER_BYTE = 8;
+	private static final long MILLIS_PER_SEC = 1000;
+
+	private static final HashMap<NodePortTuple, SwitchPortBandwidth> portStats = new HashMap<NodePortTuple, SwitchPortBandwidth>();
+	private static final HashMap<NodePortTuple, SwitchPortBandwidth> tentativePortStats = new HashMap<NodePortTuple, SwitchPortBandwidth>();
+
+	private class PortStatsCollector implements Runnable {
+
+		@Override
+		public void run() {
+			Map<DatapathId, List<OFStatsReply>> replies = getSwitchStatistics(switchService.getAllSwitchDpids(), OFStatsType.PORT);
+			for (Entry<DatapathId, List<OFStatsReply>> e : replies.entrySet()) {
+				for (OFStatsReply r : e.getValue()) {
+					OFPortStatsReply psr = (OFPortStatsReply) r;
+					for (OFPortStatsEntry pse : psr.getEntries()) {
+						NodePortTuple npt = new NodePortTuple(e.getKey(), pse.getPortNo());
+						SwitchPortBandwidth spb;
+						if (portStats.containsKey(npt) || tentativePortStats.containsKey(npt)) {
+							if (portStats.containsKey(npt)) { /* update */
+								spb = portStats.get(npt);
+							} else if (tentativePortStats.containsKey(npt)) { /* finish */
+								spb = tentativePortStats.get(npt);
+								tentativePortStats.remove(npt);
+							} else {
+								log.error("Inconsistent state between tentative and official port stats lists.");
+								return;
+							}
+
+							/* Get counted bytes over the elapsed period. Check for counter overflow. */
+							U64 rxBytesCounted;
+							U64 txBytesCounted;
+							if (spb.getPriorByteValueRx().compareTo(pse.getRxBytes()) > 0) { /* overflow */
+								U64 upper = U64.NO_MASK.subtract(spb.getPriorByteValueRx());
+								U64 lower = pse.getRxBytes();
+								rxBytesCounted = upper.add(lower);
+							} else {
+								rxBytesCounted = pse.getRxBytes().subtract(spb.getPriorByteValueRx());
+							}
+							if (spb.getPriorByteValueTx().compareTo(pse.getTxBytes()) > 0) { /* overflow */
+								U64 upper = U64.NO_MASK.subtract(spb.getPriorByteValueTx());
+								U64 lower = pse.getTxBytes();
+								txBytesCounted = upper.add(lower);
+							} else {
+								txBytesCounted = pse.getTxBytes().subtract(spb.getPriorByteValueTx());
+							}
+							long timeDifSec = (System.currentTimeMillis() - spb.getUpdateTime()) / MILLIS_PER_SEC;
+							portStats.put(npt, SwitchPortBandwidth.of(npt.getNodeId(), npt.getPortId(), 
+									U64.ofRaw((rxBytesCounted.getValue() * BITS_PER_BYTE) / timeDifSec), 
+									U64.ofRaw((txBytesCounted.getValue() * BITS_PER_BYTE) / timeDifSec), 
+									pse.getRxBytes(), pse.getTxBytes())
+									);
+							
+						} else { /* initialize */
+							tentativePortStats.put(npt, SwitchPortBandwidth.of(npt.getNodeId(), npt.getPortId(), U64.ZERO, U64.ZERO, pse.getRxBytes(), pse.getTxBytes()));
+						}
+					}
+				}
+			}
+		}
+	}
+
+	private class GetStatisticsThread extends Thread {
+		private List<OFStatsReply> statsReply;
+		private DatapathId switchId;
+		private OFStatsType statType;
+
+		public GetStatisticsThread(DatapathId switchId, OFStatsType statType) {
+			this.switchId = switchId;
+			this.statType = statType;
+			this.statsReply = null;
+		}
+
+		public List<OFStatsReply> getStatisticsReply() {
+			return statsReply;
+		}
+
+		public DatapathId getSwitchId() {
+			return switchId;
+		}
+
+		@Override
+		public void run() {
+			statsReply = getSwitchStatistics(switchId, statType);
+		}
+	}
+	
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+		Collection<Class<? extends IFloodlightService>> l =
+				new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IStatisticsService.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(IStatisticsService.class, this);
+		return m;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l =
+				new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IOFSwitchService.class);
+		l.add(IThreadPoolService.class);
+		l.add(IRestApiService.class);
+		return l;
+	}
+
+	@Override
+	public void init(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+		switchService = context.getServiceImpl(IOFSwitchService.class);
+		threadPoolService = context.getServiceImpl(IThreadPoolService.class);
+		restApiService = context.getServiceImpl(IRestApiService.class);
+
+		//TODO Map<String, String> config = context.getConfigParams(this);
+	}
+
+	@Override
+	public void startUp(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+		threadPoolService.getScheduledExecutor().scheduleAtFixedRate(new PortStatsCollector(), portStatsInterval, portStatsInterval, TimeUnit.SECONDS);
+		restApiService.addRestletRoutable(new SwitchStatisticsWebRoutable());
+	}
+
+	@Override
+	public SwitchPortBandwidth getBandwidthConsumption(DatapathId dpid, OFPort p) {
+		return portStats.get(new NodePortTuple(dpid, p));
+	}
+	
+
+	@Override
+	public Map<NodePortTuple, SwitchPortBandwidth> getBandwidthConsumption() {
+		return Collections.unmodifiableMap(portStats);
+	}
+
+	private Map<DatapathId, List<OFStatsReply>> getSwitchStatistics(Set<DatapathId> dpids, OFStatsType statsType) {
+		HashMap<DatapathId, List<OFStatsReply>> model = new HashMap<DatapathId, List<OFStatsReply>>();
+
+		List<GetStatisticsThread> activeThreads = new ArrayList<GetStatisticsThread>(dpids.size());
+		List<GetStatisticsThread> pendingRemovalThreads = new ArrayList<GetStatisticsThread>();
+		GetStatisticsThread t;
+		for (DatapathId d : dpids) {
+			t = new GetStatisticsThread(d, statsType);
+			activeThreads.add(t);
+			t.start();
+		}
+
+		// Join all the threads after the timeout. Set a hard timeout
+		// of 12 seconds for the threads to finish. If the thread has not
+		// finished the switch has not replied yet and therefore we won't
+		// add the switch's stats to the reply.
+		for (int iSleepCycles = 0; iSleepCycles < portStatsInterval; iSleepCycles++) {
+			for (GetStatisticsThread curThread : activeThreads) {
+				if (curThread.getState() == State.TERMINATED) {
+					model.put(curThread.getSwitchId(), curThread.getStatisticsReply());
+					pendingRemovalThreads.add(curThread);
+				}
+			}
+
+			// remove the threads that have completed the queries to the switches
+			for (GetStatisticsThread curThread : pendingRemovalThreads) {
+				activeThreads.remove(curThread);
+			}
+			// clear the list so we don't try to double remove them
+			pendingRemovalThreads.clear();
+
+			// if we are done finish early so we don't always get the worst case
+			if (activeThreads.isEmpty()) {
+				break;
+			}
+
+			// sleep for 1 s here
+			try {
+				Thread.sleep(1000);
+			} catch (InterruptedException e) {
+				log.error("Interrupted while waiting for statistics", e);
+			}
+		}
+
+		return model;
+	}
+
+	@SuppressWarnings("unchecked")
+	protected List<OFStatsReply> getSwitchStatistics(DatapathId switchId, OFStatsType statsType) {
+		IOFSwitch sw = switchService.getSwitch(switchId);
+		ListenableFuture<?> future;
+		List<OFStatsReply> values = null;
+		Match match;
+		if (sw != null) {
+			OFStatsRequest<?> req = null;
+			switch (statsType) {
+			case FLOW:
+				match = sw.getOFFactory().buildMatch().build();
+				req = sw.getOFFactory().buildFlowStatsRequest()
+						.setMatch(match)
+						.setOutPort(OFPort.ANY)
+						.setTableId(TableId.ALL)
+						.build();
+				break;
+			case AGGREGATE:
+				match = sw.getOFFactory().buildMatch().build();
+				req = sw.getOFFactory().buildAggregateStatsRequest()
+						.setMatch(match)
+						.setOutPort(OFPort.ANY)
+						.setTableId(TableId.ALL)
+						.build();
+				break;
+			case PORT:
+				req = sw.getOFFactory().buildPortStatsRequest()
+				.setPortNo(OFPort.ANY)
+				.build();
+				break;
+			case QUEUE:
+				req = sw.getOFFactory().buildQueueStatsRequest()
+				.setPortNo(OFPort.ANY)
+				.setQueueId(UnsignedLong.MAX_VALUE.longValue())
+				.build();
+				break;
+			case DESC:
+				// pass - nothing todo besides set the type above
+				req = sw.getOFFactory().buildDescStatsRequest()
+				.build();
+				break;
+			case GROUP:
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
+					req = sw.getOFFactory().buildGroupStatsRequest()				
+							.build();
+				}
+				break;
+
+			case METER:
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
+					req = sw.getOFFactory().buildMeterStatsRequest()
+							.setMeterId(OFMeterSerializerVer13.ALL_VAL)
+							.build();
+				}
+				break;
+
+			case GROUP_DESC:			
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
+					req = sw.getOFFactory().buildGroupDescStatsRequest()			
+							.build();
+				}
+				break;
+
+			case GROUP_FEATURES:
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
+					req = sw.getOFFactory().buildGroupFeaturesStatsRequest()
+							.build();
+				}
+				break;
+
+			case METER_CONFIG:
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
+					req = sw.getOFFactory().buildMeterConfigStatsRequest()
+							.build();
+				}
+				break;
+
+			case METER_FEATURES:
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
+					req = sw.getOFFactory().buildMeterFeaturesStatsRequest()
+							.build();
+				}
+				break;
+
+			case TABLE:
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
+					req = sw.getOFFactory().buildTableStatsRequest()
+							.build();
+				}
+				break;
+
+			case TABLE_FEATURES:	
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
+					req = sw.getOFFactory().buildTableFeaturesStatsRequest()
+							.build();		
+				}
+				break;
+			case PORT_DESC:
+				if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
+					req = sw.getOFFactory().buildPortDescStatsRequest()
+							.build();
+				}
+				break;
+			case EXPERIMENTER:		
+			default:
+				log.error("Stats Request Type {} not implemented yet", statsType.name());
+				break;
+			}
+
+			try {
+				if (req != null) {
+					future = sw.writeStatsRequest(req); 
+					values = (List<OFStatsReply>) future.get(portStatsInterval / 2, TimeUnit.SECONDS);
+				}
+			} catch (Exception e) {
+				log.error("Failure retrieving statistics from switch {}. {}", sw, e);
+			}
+		}
+		return values;
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/statistics/SwitchPortBandwidth.java b/src/main/java/net/floodlightcontroller/statistics/SwitchPortBandwidth.java
new file mode 100644
index 0000000000000000000000000000000000000000..56648ca0307ccaa5611e660c294684860da049d2
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/statistics/SwitchPortBandwidth.java
@@ -0,0 +1,113 @@
+package net.floodlightcontroller.statistics;
+
+import java.util.Date;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.U64;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+import net.floodlightcontroller.statistics.web.SwitchPortBandwidthSerializer;
+
+@JsonSerialize(using=SwitchPortBandwidthSerializer.class)
+public class SwitchPortBandwidth {
+	private DatapathId id;
+	private OFPort pt;
+	private U64 rx;
+	private U64 tx;
+	private Date time;
+	private U64 rxValue;
+	private U64 txValue;
+	
+	private SwitchPortBandwidth() {}
+	private SwitchPortBandwidth(DatapathId d, OFPort p, U64 rx, U64 tx, U64 rxValue, U64 txValue) {
+		id = d;
+		pt = p;
+		this.rx = rx;
+		this.tx = tx;
+		time = new Date();
+		this.rxValue = rxValue;
+		this.txValue = txValue;
+	}
+	
+	public static SwitchPortBandwidth of(DatapathId d, OFPort p, U64 rx, U64 tx, U64 rxValue, U64 txValue) {
+		if (d == null) {
+			throw new IllegalArgumentException("Datapath ID cannot be null");
+		}
+		if (p == null) {
+			throw new IllegalArgumentException("Port cannot be null");
+		}
+		if (rx == null) {
+			throw new IllegalArgumentException("RX bandwidth cannot be null");
+		}
+		if (tx == null) {
+			throw new IllegalArgumentException("TX bandwidth cannot be null");
+		}
+		if (rxValue == null) {
+			throw new IllegalArgumentException("RX value cannot be null");
+		}
+		if (txValue == null) {
+			throw new IllegalArgumentException("TX value cannot be null");
+		}
+		return new SwitchPortBandwidth(d, p, rx, tx, rxValue, txValue);
+	}
+	
+	public DatapathId getSwitchId() {
+		return id;
+	}
+	
+	public OFPort getSwitchPort() {
+		return pt;
+	}
+	
+	public U64 getBitsPerSecondRx() {
+		return rx;
+	}
+	
+	public U64 getBitsPerSecondTx() {
+		return tx;
+	}
+	
+	protected U64 getPriorByteValueRx() {
+		return rxValue;
+	}
+	
+	protected U64 getPriorByteValueTx() {
+		return txValue;
+	}
+	
+	public long getUpdateTime() {
+		return time.getTime();
+	}
+		
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		result = prime * result + ((pt == null) ? 0 : pt.hashCode());
+		return result;
+	}
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		SwitchPortBandwidth other = (SwitchPortBandwidth) obj;
+		if (id == null) {
+			if (other.id != null)
+				return false;
+		} else if (!id.equals(other.id))
+			return false;
+		if (pt == null) {
+			if (other.pt != null)
+				return false;
+		} else if (!pt.equals(other.pt))
+			return false;
+		return true;
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/statistics/web/BandwidthResource.java b/src/main/java/net/floodlightcontroller/statistics/web/BandwidthResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..a09e5f9e0d4d49fce8467f7825f0310eaa981b52
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/statistics/web/BandwidthResource.java
@@ -0,0 +1,75 @@
+package net.floodlightcontroller.statistics.web;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import net.floodlightcontroller.core.internal.IOFSwitchService;
+import net.floodlightcontroller.statistics.IStatisticsService;
+import net.floodlightcontroller.statistics.SwitchPortBandwidth;
+
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BandwidthResource extends ServerResource {
+	private static final Logger log = LoggerFactory.getLogger(BandwidthResource.class);
+
+	@Get("json")
+	public Object retrieve() {
+		IStatisticsService statisticsService = (IStatisticsService) getContext().getAttributes().get(IStatisticsService.class.getCanonicalName());
+		IOFSwitchService switchService = (IOFSwitchService) getContext().getAttributes().get(IOFSwitchService.class.getCanonicalName());
+
+		String d = (String) getRequestAttributes().get(SwitchStatisticsWebRoutable.DPID_STR);
+		String p = (String) getRequestAttributes().get(SwitchStatisticsWebRoutable.PORT_STR);
+
+		DatapathId dpid = DatapathId.NONE;
+
+		if (!d.trim().equalsIgnoreCase("all")) {
+			try {
+				dpid = DatapathId.of(d);
+			} catch (Exception e) {
+				log.error("Could not parse DPID {}", d);
+				return Collections.singletonMap("ERROR", "Could not parse DPID" + d);
+			}
+		} /* else assume it's all */
+
+		OFPort port = OFPort.ALL;
+		if (!p.trim().equalsIgnoreCase("all")) {
+			try {
+				port = OFPort.of(Integer.parseInt(p));
+			} catch (Exception e) {
+				log.error("Could not parse port {}", p);
+				return Collections.singletonMap("ERROR", "Could not parse port" + p);
+			}
+		}
+
+		Set<SwitchPortBandwidth> spbs;
+		if (dpid.equals(DatapathId.NONE)) { /* do all DPIDs */
+			if (port.equals(OFPort.ALL)) { /* do all ports */
+				spbs = new HashSet<SwitchPortBandwidth>(statisticsService.getBandwidthConsumption().values());
+			} else {
+				spbs = new HashSet<SwitchPortBandwidth>();
+				for (DatapathId id : switchService.getAllSwitchDpids()) {
+					SwitchPortBandwidth spb = statisticsService.getBandwidthConsumption(id, port);
+					if (spb != null) {
+						spbs.add(spb);
+					}
+				}
+			}
+		} else {
+			spbs = new HashSet<SwitchPortBandwidth>();
+			for (OFPortDesc pd : switchService.getSwitch(dpid).getPorts()) {
+				SwitchPortBandwidth spb = statisticsService.getBandwidthConsumption(dpid, pd.getPortNo());
+				if (spb != null) {
+					spbs.add(spb);
+				}
+			}
+		}
+		return spbs;
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/statistics/web/SwitchPortBandwidthSerializer.java b/src/main/java/net/floodlightcontroller/statistics/web/SwitchPortBandwidthSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..253bb8c8798c0048a75393ccefb7b983097972f4
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/statistics/web/SwitchPortBandwidthSerializer.java
@@ -0,0 +1,29 @@
+package net.floodlightcontroller.statistics.web;
+
+import java.io.IOException;
+import java.util.Date;
+
+import net.floodlightcontroller.statistics.SwitchPortBandwidth;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonGenerator.Feature;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+public class SwitchPortBandwidthSerializer extends JsonSerializer<SwitchPortBandwidth> {
+
+	@Override
+	public void serialize(SwitchPortBandwidth spb, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException {
+		jGen.configure(Feature.WRITE_NUMBERS_AS_STRINGS, true);
+
+		jGen.writeStartObject();
+		jGen.writeStringField("dpid", spb.getSwitchId().toString());
+		jGen.writeStringField("port", spb.getSwitchPort().toString());
+		jGen.writeStringField("updated", new Date(spb.getUpdateTime()).toString());
+		jGen.writeStringField("bits-per-second-rx", spb.getBitsPerSecondRx().getBigInteger().toString());
+		jGen.writeStringField("bits-per-second-tx", spb.getBitsPerSecondTx().getBigInteger().toString());
+		jGen.writeEndObject();
+	}
+
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/statistics/web/SwitchStatisticsWebRoutable.java b/src/main/java/net/floodlightcontroller/statistics/web/SwitchStatisticsWebRoutable.java
new file mode 100644
index 0000000000000000000000000000000000000000..748cb5f3e96829f6310d984b38dedaf42f49f33e
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/statistics/web/SwitchStatisticsWebRoutable.java
@@ -0,0 +1,27 @@
+package net.floodlightcontroller.statistics.web;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+
+import org.restlet.Context;
+import org.restlet.routing.Router;
+
+public class SwitchStatisticsWebRoutable implements RestletRoutable {
+	protected static final String DPID_STR = "dpid";
+	protected static final String PORT_STR = "port";
+	
+	@Override
+    public Router getRestlet(Context context) {
+        Router router = new Router(context);
+        router.attach("/bandwidth/{" + DPID_STR + "}/{" + PORT_STR + "}/json", BandwidthResource.class);
+        return router;
+    }
+
+    /**
+     * Set the base path for the Topology
+     */
+    @Override
+    public String basePath() {
+        return "/wm/statistics";
+    }
+}
\ No newline at end of file
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 e11880981126a0cdae3c604e5c9f4a0783f9db5c..b7dfe953e276c4fea382bdb2bd1ff63851d52f74 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
@@ -26,4 +26,5 @@ net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl
 net.floodlightcontroller.firewall.Firewall
 net.floodlightcontroller.accesscontrollist.ACL
 net.floodlightcontroller.dhcpserver.DHCPServer
-net.floodlightcontroller.learningswitch.LearningSwitch
\ No newline at end of file
+net.floodlightcontroller.learningswitch.LearningSwitch
+net.floodlightcontroller.statistics.StatisticsCollector
\ No newline at end of file
diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties
index 5b909f849c42df0dfeb5012b465aaaa7fa3cd27f..9d40c9525174875c6b1e70909e8ce8e7855d346c 100644
--- a/src/main/resources/floodlightdefault.properties
+++ b/src/main/resources/floodlightdefault.properties
@@ -15,7 +15,8 @@ net.floodlightcontroller.ui.web.StaticWebRoutable,\
 net.floodlightcontroller.loadbalancer.LoadBalancer,\
 net.floodlightcontroller.firewall.Firewall,\
 net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl,\
-net.floodlightcontroller.accesscontrollist.ACL
+net.floodlightcontroller.accesscontrollist.ACL,\
+net.floodlightcontroller.statistics.StatisticsCollector
 org.sdnplatform.sync.internal.SyncManager.authScheme=CHALLENGE_RESPONSE
 org.sdnplatform.sync.internal.SyncManager.keyStorePath=/etc/floodlight/auth_credentials.jceks
 org.sdnplatform.sync.internal.SyncManager.dbPath=/var/lib/floodlight/