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/