diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index 953851ca8ecea3869f4586c19ce885bb339dc6ef..d62a6c1ba533e144a13a312adf0e5ea8521fe8d6 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -968,6 +968,7 @@ public class Controller // Get the starting time (overall and per-component) of // the processing chain for this packet if performance // monitoring is turned on + pktinProcTime.bootstrap(listeners); pktinProcTime.recordStartTimePktIn(); Command cmd; for (IOFMessageListener listener : listeners) { diff --git a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java index 33a8890beb3dab7abfbff08707c104b313ef4027..e8d76376c4fdfe0491154bf1722a12b1a23352df 100644 --- a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java +++ b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java @@ -28,8 +28,8 @@ import net.floodlightcontroller.core.web.serializers.LinkTupleSerializer; import net.floodlightcontroller.core.web.serializers.OFFeaturesReplyJSONSerializer; import net.floodlightcontroller.core.web.serializers.OFMatchJSONSerializer; import net.floodlightcontroller.core.web.serializers.OFPhysicalPortJSONSerializer; -import net.floodlightcontroller.core.web.serializers.PerfMonCumulativeTimeBucketJSONSerializer; -import net.floodlightcontroller.core.web.serializers.PerfMonOneComponentTimeJSONSerializer; +import net.floodlightcontroller.core.web.serializers.CumulativeTimeBucketJSONSerializer; +import net.floodlightcontroller.core.web.serializers.OneComponentTimeJSONSerializer; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.Version; @@ -66,11 +66,9 @@ public class JacksonCustomConverter extends JacksonConverter { jsonModule.addSerializer(new OFFeaturesReplyJSONSerializer()); jsonModule.addSerializer(new OFPhysicalPortJSONSerializer()); jsonModule.addSerializer(new EventHistoryBaseInfoJSONSerializer()); - jsonModule.addSerializer( - new EventHistoryAttachmentPointJSONSerializer()); - jsonModule.addSerializer(new PerfMonOneComponentTimeJSONSerializer()); - jsonModule.addSerializer( - new PerfMonCumulativeTimeBucketJSONSerializer()); + jsonModule.addSerializer(new EventHistoryAttachmentPointJSONSerializer()); + jsonModule.addSerializer(new OneComponentTimeJSONSerializer()); + jsonModule.addSerializer(new CumulativeTimeBucketJSONSerializer()); jsonModule.addSerializer(new LinkTupleSerializer()); jsonModule.addSerializer(new EventHistoryTopologySwitchJSONSerializer()); jsonModule.addSerializer(new EventHistoryTopologyLinkJSONSerializer()); diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/CumulativeTimeBucketJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/CumulativeTimeBucketJSONSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..a44436d38f155ceaa37d051eb122fc6819f45d79 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/CumulativeTimeBucketJSONSerializer.java @@ -0,0 +1,49 @@ +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; +import java.sql.Timestamp; + +import net.floodlightcontroller.perfmon.CumulativeTimeBucket; +import net.floodlightcontroller.perfmon.OneComponentTime; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +public class CumulativeTimeBucketJSONSerializer + extends JsonSerializer<CumulativeTimeBucket> { + /** + * Performs the serialization of a OneComponentTime object + */ + @Override + public void serialize(CumulativeTimeBucket ctb, + JsonGenerator jGen, + SerializerProvider serializer) + throws IOException, JsonProcessingException { + jGen.writeStartObject(); + Timestamp ts = new Timestamp(ctb.getStartTimeNs()/1000000); + jGen.writeStringField("start-time", ts.toString()); + jGen.writeStringField("current-time", + new Timestamp(System.currentTimeMillis()).toString()); + jGen.writeNumberField("total-packets", ctb.getTotalPktCnt()); + jGen.writeNumberField("average", ctb.getAverageProcTimeNs()); + jGen.writeNumberField("min", ctb.getMinTotalProcTimeNs()); + jGen.writeNumberField("max", ctb.getMaxTotalProcTimeNs()); + jGen.writeNumberField("std-dev", ctb.getTotalSigmaProcTimeNs()); + jGen.writeArrayFieldStart("modules"); + for (OneComponentTime oct : ctb.getModules()) { + serializer.defaultSerializeValue(oct, jGen); + } + jGen.writeEndArray(); + jGen.writeEndObject(); + } + + /** + * Tells SimpleModule that we are the serializer for OFMatch + */ + @Override + public Class<CumulativeTimeBucket> handledType() { + return CumulativeTimeBucket.class; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OneComponentTimeJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OneComponentTimeJSONSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..a91ff89f55c448faa92d779666ab3bbb1b6d43ff --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OneComponentTimeJSONSerializer.java @@ -0,0 +1,42 @@ +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; + +import net.floodlightcontroller.perfmon.OneComponentTime; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +public class OneComponentTimeJSONSerializer + extends JsonSerializer<OneComponentTime> { + /** + * Performs the serialization of a OneComponentTime object + */ + @Override + public void serialize(OneComponentTime oct, + JsonGenerator jGen, + SerializerProvider serializer) + throws IOException, JsonProcessingException { + jGen.writeStartObject(); + jGen.writeStringField("module-name", oct.getCompName()); + jGen.writeNumberField("num-packets", oct.getPktCnt()); + jGen.writeNumberField("total", oct.getSumProcTimeNs()); + jGen.writeNumberField("average", oct.getAvgProcTimeNs()); + jGen.writeNumberField("max", oct.getMaxProcTimeNs()); + jGen.writeNumberField("min", oct.getMinProcTimeNs()); + jGen.writeNumberField("std-dev", oct.getSigmaProcTimeNs()); + jGen.writeNumberField("average-squared", oct.getSumSquaredProcTimeNs()); + jGen.writeEndObject(); + } + + /** + * Tells SimpleModule that we are the serializer for OFMatch + */ + @Override + public Class<OneComponentTime> handledType() { + return OneComponentTime.class; + } +} + diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonCumulativeTimeBucketJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonCumulativeTimeBucketJSONSerializer.java deleted file mode 100644 index 6bc95382d0e120a8fa24195cb8cca26b4c5ec2c7..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonCumulativeTimeBucketJSONSerializer.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.floodlightcontroller.core.web.serializers; - -import java.io.IOException; -import java.sql.Timestamp; - -import net.floodlightcontroller.perfmon.CumulativeTimeBucket; -import net.floodlightcontroller.perfmon.OneComponentTime; - -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; - -public class PerfMonCumulativeTimeBucketJSONSerializer - extends JsonSerializer<CumulativeTimeBucket> { - /** - * Performs the serialization of a OneComponentTime object - */ - @Override - public void serialize(CumulativeTimeBucket ctb, - JsonGenerator jGen, - SerializerProvider serializer) - throws IOException, JsonProcessingException { - // Skip if the number of packets processed is zero - if (ctb.getTotalPktCnt() != 0) { - jGen.writeStartObject(); - jGen.writeNumberField("BktNo", ctb.getBucketNo()); - Timestamp ts = new Timestamp(ctb.getStartTimeNs()); - String tsStr = ts.toString(); - while (tsStr.length() < 23) { - tsStr = tsStr.concat("0"); - } - jGen.writeStringField("StartTime", tsStr); - jGen.writeNumberField("Duration", ctb.getDurationS()); - jGen.writeNumberField("TotPkts", ctb.getTotalPktCnt()); - jGen.writeNumberField("Avg", ctb.getAverageProcTimeNs()); - jGen.writeNumberField("Min", ctb.getMinTotalProcTimeNs()); - jGen.writeNumberField("Max", ctb.getMaxTotalProcTimeNs()); - jGen.writeNumberField("StdDev", ctb.getTotalSigmaProcTimeNs()); - - for (OneComponentTime oct : ctb.getComponentTimes()) { - if (oct.getPktCnt() > 0) { - serializer.defaultSerializeField(oct.getCompName(), oct, jGen); - } - } - jGen.writeEndObject(); - } - } - - /** - * Tells SimpleModule that we are the serializer for OFMatch - */ - @Override - public Class<CumulativeTimeBucket> handledType() { - return CumulativeTimeBucket.class; - } -} diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonOneComponentTimeJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonOneComponentTimeJSONSerializer.java deleted file mode 100644 index 5afe36c6d12ac20170dc34776919b9cfc2bc7012..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/PerfMonOneComponentTimeJSONSerializer.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.floodlightcontroller.core.web.serializers; - -import java.io.IOException; - -import net.floodlightcontroller.perfmon.OneComponentTime; - -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; - -public class PerfMonOneComponentTimeJSONSerializer - extends JsonSerializer<OneComponentTime> { - /** - * Performs the serialization of a OneComponentTime object - */ - @Override - public void serialize(OneComponentTime oCT, - JsonGenerator jGen, - SerializerProvider serializer) - throws IOException, JsonProcessingException { - // Skip if the number of packets processed is zero - if (oCT.getPktCnt() != 0) { - jGen.writeStartObject(); // Called from higher layer - jGen.writeStringField("CompName", oCT.getCompName()); - jGen.writeNumberField("Pkts", oCT.getPktCnt()); - jGen.writeNumberField("Avg", oCT.getAvgProcTime_us()); - jGen.writeNumberField("Max", oCT.getMaxProcTime_us()); - jGen.writeNumberField("Min", oCT.getMinProcTime_us()); - jGen.writeNumberField("StdDev", oCT.getSigmaProcTime_us()); - //jGen.writeNumberField("Sum", oCT.getSumProcTime_us()); - //jGen.writeNumberField("SumSq", oCT.getSumSquaredProcTime_us2()); - jGen.writeEndObject(); - } - } - - /** - * Tells SimpleModule that we are the serializer for OFMatch - */ - @Override - public Class<OneComponentTime> handledType() { - return OneComponentTime.class; - } -} - diff --git a/src/main/java/net/floodlightcontroller/perfmon/CircularTimeBucketSet.java b/src/main/java/net/floodlightcontroller/perfmon/CircularTimeBucketSet.java deleted file mode 100644 index e56c87cf2c073ea618e8ed1bb9ea9f2ed0cfe9dc..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/perfmon/CircularTimeBucketSet.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.floodlightcontroller.perfmon; - -import java.util.Set; - -import net.floodlightcontroller.core.IOFMessageListener; - -public class CircularTimeBucketSet { - /** - * How many timer buckets have valid data, initially it is false then it - * stays at true after the circle is completed - */ - private boolean allBucketsValid; - private int curBucketIdx; // most recent bucket *being* filled - private CumulativeTimeBucket[] timeBucketSet; - private int bucketDurationS = 0; // seconds - - public CircularTimeBucketSet(Set<IOFMessageListener> listeners, int numBuckets, int durationS) { - bucketDurationS = durationS; - timeBucketSet = new CumulativeTimeBucket[numBuckets]; - for (int idx= 0; idx < numBuckets; idx++) { - timeBucketSet[idx] = new CumulativeTimeBucket(listeners, idx, bucketDurationS); - } - allBucketsValid = false; - curBucketIdx = 0; - } - - public CumulativeTimeBucket getCurBucket() { - return timeBucketSet[curBucketIdx]; - } - - public boolean isAllBucketsValid() { - return allBucketsValid; - } - - // Called when the bucket time ends - public void fillTimeBucket(CumulativeTimeBucket ctb) { - if (ctb.getTotalPktCnt() > 0) { - ctb.computeAverages(); - } - - // Move to the new bucket - if (curBucketIdx >= (timeBucketSet.length - 1)) { - curBucketIdx = 0; - allBucketsValid = true; - } else { - curBucketIdx++; - } - // Get the next bucket to be filled ready - ctb = timeBucketSet[curBucketIdx]; - // Empty it's counters - ctb.reset(); - } -} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java b/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java index 03853c8bb020f65e4336f00358ee67ff4d6fdb4f..d359da54af3c24cdd0e6411e6a279d853c0a9082 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java +++ b/src/main/java/net/floodlightcontroller/perfmon/CumulativeTimeBucket.java @@ -1,16 +1,14 @@ package net.floodlightcontroller.perfmon; import java.util.Collection; +import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import net.floodlightcontroller.core.IOFMessageListener; public class CumulativeTimeBucket { - private int bucketNo; private long startTime_ns; // First pkt time-stamp in this bucket - private int durationS; // how long this bucket is valid for in s private Map<Integer, OneComponentTime> compStats; private long totalPktCnt; private long totalProcTimeNs; // total processing time for one pkt in @@ -19,23 +17,11 @@ public class CumulativeTimeBucket { private long minTotalProcTimeNs; private long avgTotalProcTimeNs; private long sigmaTotalProcTimeNs; // std. deviation - - public int getBucketNo() { - return bucketNo; - } - - public int getDurationS() { - return durationS; - } public long getStartTimeNs() { return startTime_ns; } - public void setStartTimeNs(long startTime_ns) { - this.startTime_ns = startTime_ns; - } - public long getTotalPktCnt() { return totalPktCnt; } @@ -59,15 +45,18 @@ public class CumulativeTimeBucket { public int getNumComps() { return compStats.values().size(); } + + public Collection<OneComponentTime> getModules() { + return compStats.values(); + } - public CumulativeTimeBucket(Set<IOFMessageListener> listeners, int bucketNo, int duration) { - this.durationS = duration; - this.bucketNo = bucketNo; + public CumulativeTimeBucket(List<IOFMessageListener> listeners) { compStats = new ConcurrentHashMap<Integer, OneComponentTime>(listeners.size()); for (IOFMessageListener l : listeners) { OneComponentTime oct = new OneComponentTime(l); compStats.put(oct.hashCode(), oct); } + startTime_ns = System.nanoTime(); } private void updateSquaredProcessingTime(long curTimeNs) { @@ -125,10 +114,6 @@ public class CumulativeTimeBucket { } public void updateOneComponent(IOFMessageListener l, long procTimeNs) { - compStats.get(l).updatePerPacketCounters(procTimeNs); - } - - public Collection<OneComponentTime> getComponentTimes() { - return compStats.values(); + compStats.get(l.hashCode()).updatePerPacketCounters(procTimeNs); } } \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java index 2936729b74b9876776f44d7a3e6f3f9c5a68c66f..80dfda0e43c136cfe5a0850eff874eb4e48acfa9 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java +++ b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java @@ -1,6 +1,6 @@ package net.floodlightcontroller.perfmon; -import java.util.Set; +import java.util.List; import org.openflow.protocol.OFMessage; @@ -8,7 +8,6 @@ import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.IFloodlightService; -import net.floodlightcontroller.perfmon.CircularTimeBucketSet; public interface IPktInProcessingTimeService extends IFloodlightService { @@ -16,7 +15,7 @@ public interface IPktInProcessingTimeService extends IFloodlightService { * Creates time buckets for a set of modules to measure their performance * @param listeners The message listeners to create time buckets for */ - public void bootstrap(Set<IOFMessageListener> listeners); + public void bootstrap(List<IOFMessageListener> listeners); /** * Stores a timestamp in ns. Used right before a service handles an @@ -32,5 +31,7 @@ public interface IPktInProcessingTimeService extends IFloodlightService { public boolean isEnabled(); - public CircularTimeBucketSet getCtbs(); + public void setEnabled(boolean enabled); + + public CumulativeTimeBucket getCtb(); } diff --git a/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java index 1c7a25e0b8a6a29dc6ba973b8412836f13b8b2fb..3d9504b164b93fa570348958765b5b17a5d60a60 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java +++ b/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java @@ -3,8 +3,8 @@ package net.floodlightcontroller.perfmon; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Set; import org.openflow.protocol.OFMessage; @@ -15,7 +15,6 @@ 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.perfmon.CircularTimeBucketSet; /** * An IPktInProcessingTimeService implementation that does nothing. @@ -26,8 +25,9 @@ import net.floodlightcontroller.perfmon.CircularTimeBucketSet; */ public class NullPktInProcessingTime implements IFloodlightModule, IPktInProcessingTimeService { - - private CircularTimeBucketSet emptyBucket; + + private CumulativeTimeBucket ctb; + private boolean inited = false; public Collection<Class<? extends IFloodlightService>> getModuleServices() { Collection<Class<? extends IFloodlightService>> l = @@ -57,6 +57,7 @@ public class NullPktInProcessingTime @Override public void init(FloodlightModuleContext context) throws FloodlightModuleException { + } @Override @@ -64,19 +65,15 @@ public class NullPktInProcessingTime // no-op } - @Override - public CircularTimeBucketSet getCtbs() { - return emptyBucket; - } - @Override public boolean isEnabled() { return false; } @Override - public void bootstrap(Set<IOFMessageListener> listeners) { - + public void bootstrap(List<IOFMessageListener> listeners) { + if (!inited) + ctb = new CumulativeTimeBucket(listeners); } @Override @@ -99,4 +96,14 @@ public class NullPktInProcessingTime FloodlightContext cntx) { } + + @Override + public void setEnabled(boolean enabled) { + + } + + @Override + public CumulativeTimeBucket getCtb() { + return ctb; + } } diff --git a/src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java b/src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java index ad953039ad84b2b8ec10bb2a4af39f58623cd592..556fb509cfd026d2eb72f1b2672a91e954cee2b2 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java +++ b/src/main/java/net/floodlightcontroller/perfmon/OneComponentTime.java @@ -42,25 +42,29 @@ public class OneComponentTime { return pktCnt; } - public long getSumProcTime_us() { + public long getSumProcTimeNs() { return totalProcTimeNs; } - public long getMaxProcTime_us() { + public long getMaxProcTimeNs() { return maxProcTimeNs; } - public long getMinProcTime_us() { + public long getMinProcTimeNs() { return minProcTimeNs; } - public long getAvgProcTime_us() { + public long getAvgProcTimeNs() { return avgProcTimeNs; } - public long getSigmaProcTime_us() { + public long getSigmaProcTimeNs() { return sigmaProcTimeNs; } + + public long getSumSquaredProcTimeNs() { + return sumSquaredProcTimeNs2; + } // Methods used to update the counters @@ -68,26 +72,26 @@ public class OneComponentTime { pktCnt++; } - private void updateTotalProcessingTime(long curTimeMs) { - totalProcTimeNs += curTimeMs; + private void updateTotalProcessingTime(long procTimeNs) { + totalProcTimeNs += procTimeNs; } - private void updateAvgProcessTime(long curTimeMs) { + private void updateAvgProcessTime() { avgProcTimeNs = totalProcTimeNs / pktCnt; } - private void updateSquaredProcessingTime(long curTimeMs) { - sumSquaredProcTimeNs2 += (Math.pow(curTimeMs, 2)); + private void updateSquaredProcessingTime(long procTimeNs) { + sumSquaredProcTimeNs2 += (Math.pow(procTimeNs, 2)); } - private void calculateMinProcTime(long curTimeMs) { - if (curTimeMs < minProcTimeNs) - minProcTimeNs = curTimeMs; + private void calculateMinProcTime(long curTimeNs) { + if (curTimeNs < minProcTimeNs) + minProcTimeNs = curTimeNs; } - private void calculateMaxProcTime(long curTimeMs) { - if (curTimeMs > maxProcTimeNs) - maxProcTimeNs = curTimeMs; + private void calculateMaxProcTime(long curTimeNs) { + if (curTimeNs > maxProcTimeNs) + maxProcTimeNs = curTimeNs; } public void computeSigma() { @@ -104,7 +108,7 @@ public class OneComponentTime { updateTotalProcessingTime(procTimeNs); calculateMinProcTime(procTimeNs); calculateMaxProcTime(procTimeNs); - updateAvgProcessTime(procTimeNs); + updateAvgProcessTime(); updateSquaredProcessingTime(procTimeNs); } diff --git a/src/main/java/net/floodlightcontroller/perfmon/PerfMonDataResource.java b/src/main/java/net/floodlightcontroller/perfmon/PerfMonDataResource.java new file mode 100644 index 0000000000000000000000000000000000000000..c43708d9e8a05c8583bc1da8079c705b5c1d726b --- /dev/null +++ b/src/main/java/net/floodlightcontroller/perfmon/PerfMonDataResource.java @@ -0,0 +1,33 @@ +package net.floodlightcontroller.perfmon; + +import org.restlet.data.Status; +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Return the performance monitoring data for the get rest api call + * @author subrata + */ +public class PerfMonDataResource extends ServerResource { + protected static Logger logger = LoggerFactory.getLogger(PerfMonDataResource.class); + + @Get("json") + public CumulativeTimeBucket handleApiQuery() { + IPktInProcessingTimeService pktinProcTime = + (IPktInProcessingTimeService)getContext().getAttributes(). + get(IPktInProcessingTimeService.class.getCanonicalName()); + + setStatus(Status.SUCCESS_OK, "OK"); + // Allocate output object + if (pktinProcTime.isEnabled()) { + CumulativeTimeBucket ctb = pktinProcTime.getCtb(); + ctb.computeAverages(); + return ctb; + } + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/perfmon/PerfMonResource.java b/src/main/java/net/floodlightcontroller/perfmon/PerfMonResource.java deleted file mode 100644 index 9be637e6336019401d0b6ba361c54ff786c710cd..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/perfmon/PerfMonResource.java +++ /dev/null @@ -1,82 +0,0 @@ -package net.floodlightcontroller.perfmon; - -import org.restlet.data.Status; -import org.restlet.resource.Get; -import org.restlet.resource.ServerResource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Return the performance monitoring data for the get rest api call - * @author subrata - */ -public class PerfMonResource extends ServerResource { - protected static Logger logger = LoggerFactory.getLogger(PerfMonResource.class); - byte[] PerfMonResourceSerialized; - - /** - * The input packet parameters to be received via POST - * @author subrata - */ - - /** - * The output model that contains the result of the performance - * monitoring data - * @author subrata - */ - public static class ProcTimePerfMonOutput { - String perfMonType; - Boolean procTimeMonitoringState; - CircularTimeBucketSet procTimeBucketSet; - String Status; - String Explanation; - - public String getPerfMonType() { - return perfMonType; - } - public void setPerfMonType(String perfMonType) { - this.perfMonType = perfMonType; - } - public Boolean getProcTimeMonitoringState() { - return procTimeMonitoringState; - } - public void setProcTimeMonitoringState(Boolean procTimeMonitoringState) { - this.procTimeMonitoringState = procTimeMonitoringState; - } - public CircularTimeBucketSet getProcTimeBucketSet() { - return procTimeBucketSet; - } - public void setProcTimeBucketSet(CircularTimeBucketSet procTimeBucketSet) { - this.procTimeBucketSet = procTimeBucketSet; - } - - } - - @Get("json") - public ProcTimePerfMonOutput handleApiQuery() { - - // Get the type of performance data queried - // Supported types: proc-time - String perfMonType = (String)getRequestAttributes().get("type"); - - logger.info("Perf Mon. API call: type = " + perfMonType); - - IPktInProcessingTimeService pktinProcTime = - (IPktInProcessingTimeService)getContext().getAttributes(). - get(IPktInProcessingTimeService.class.getCanonicalName()); - - // Allocate output object - ProcTimePerfMonOutput output = new ProcTimePerfMonOutput(); - - output.setPerfMonType(perfMonType); - output.setProcTimeMonitoringState(pktinProcTime.isEnabled()); - output.setProcTimeBucketSet(pktinProcTime.getCtbs()); - - setStatus(Status.SUCCESS_OK); - output.Status = "SUCCESS"; - output.Explanation = "OK"; - - return output; - } -} \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/perfmon/PerfMonToggleResource.java b/src/main/java/net/floodlightcontroller/perfmon/PerfMonToggleResource.java new file mode 100644 index 0000000000000000000000000000000000000000..9ea1876e7c2183db40becece8765d719b893f7b2 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/perfmon/PerfMonToggleResource.java @@ -0,0 +1,28 @@ +package net.floodlightcontroller.perfmon; + +import org.restlet.data.Status; +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; + +public class PerfMonToggleResource extends ServerResource { + + @Get("json") + public String retrieve() { + IPktInProcessingTimeService pktinProcTime = + (IPktInProcessingTimeService)getContext().getAttributes(). + get(IPktInProcessingTimeService.class.getCanonicalName()); + + String param = ((String)getRequestAttributes().get("perfmonstate")).toLowerCase(); + if (param.equals("reset")) { + pktinProcTime.getCtb().reset(); + } else { + if (param.equals("enable") || param.equals("true")) { + pktinProcTime.setEnabled(true); + } else if (param.equals("disable") || param.equals("false")) { + pktinProcTime.setEnabled(false); + } + } + setStatus(Status.SUCCESS_OK, "OK"); + return "{ \"enabled\" : " + pktinProcTime.isEnabled() + " }"; + } +} diff --git a/src/main/java/net/floodlightcontroller/perfmon/PerfWebRoutable.java b/src/main/java/net/floodlightcontroller/perfmon/PerfWebRoutable.java index 5ac725a489b9c131e5f903e209b9c04ca14f5849..ace0bc8029f2c1233a1b4345e50bdf70a58bb26e 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/PerfWebRoutable.java +++ b/src/main/java/net/floodlightcontroller/perfmon/PerfWebRoutable.java @@ -11,12 +11,13 @@ public class PerfWebRoutable implements RestletRoutable { @Override public Restlet getRestlet(Context context) { Router router = new Router(context); - router.attach("/data/{type}/json", PerfMonResource.class); + router.attach("/data/json", PerfMonDataResource.class); + router.attach("/{perfmonstate}/json", PerfMonToggleResource.class); // enable, disable, or reset return router; } @Override public String basePath() { - return "/wm/perform"; + return "/wm/performance"; } } diff --git a/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java index 1719f01f03b2f1d055e67867d962eb6b5d14f41f..cdcd30d971c4138b32b0bde01c82ffa5a08650ca 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java +++ b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java @@ -6,8 +6,8 @@ package net.floodlightcontroller.perfmon; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Set; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IOFMessageListener; @@ -17,13 +17,6 @@ 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.storage.IPredicate; -import net.floodlightcontroller.storage.IResultSet; -import net.floodlightcontroller.storage.IStorageSourceListener; -import net.floodlightcontroller.storage.IStorageSourceService; -import net.floodlightcontroller.storage.OperatorPredicate; -import net.floodlightcontroller.storage.StorageException; -import net.floodlightcontroller.storage.OperatorPredicate.Operator; import org.openflow.protocol.OFMessage; import org.slf4j.Logger; @@ -34,7 +27,7 @@ import org.slf4j.LoggerFactory; * */ public class PktInProcessingTime - implements IFloodlightModule, IPktInProcessingTimeService, IStorageSourceListener { + implements IFloodlightModule, IPktInProcessingTimeService { /*** * This class contains a set of buckets (called time buckets as the @@ -62,7 +55,6 @@ public class PktInProcessingTime */ // Our dependencies - private IStorageSourceService storageSource; private IRestApiService restApi; protected long ptWarningThresholdInNano; @@ -79,8 +71,7 @@ public class PktInProcessingTime protected boolean isInited = false; // Maintains the time when the last packet was processed protected long lastPktTime_ns; - public CircularTimeBucketSet ctbs = null; // Set of all time buckets - private int numBuckets = 360; + private CumulativeTimeBucket ctb = null; /*** @@ -92,9 +83,11 @@ public class PktInProcessingTime ONE_BUCKET_DURATION_SECONDS * 1000000000; @Override - public void bootstrap(Set<IOFMessageListener> listeners) { - ctbs = new CircularTimeBucketSet(listeners, numBuckets, ONE_BUCKET_DURATION_SECONDS); - isInited = true; + public void bootstrap(List<IOFMessageListener> listeners) { + if (!isInited) { + ctb = new CumulativeTimeBucket(listeners); + isInited = true; + } } @Override @@ -102,8 +95,15 @@ public class PktInProcessingTime return isEnabled && isInited; } + @Override public void setEnabled(boolean enabled) { - isEnabled = enabled; + this.isEnabled = enabled; + logger.debug("Setting module to " + isEnabled); + } + + @Override + public CumulativeTimeBucket getCtb() { + return ctb; } private long startTimePktNs; @@ -112,7 +112,6 @@ public class PktInProcessingTime public void recordStartTimeComp(IOFMessageListener listener) { if (isEnabled()) { startTimeCompNs = System.nanoTime(); - checkAndStartNextBucket(startTimeCompNs); } } @@ -120,7 +119,7 @@ public class PktInProcessingTime public void recordEndTimeComp(IOFMessageListener listener) { if (isEnabled()) { long procTime = System.nanoTime() - startTimeCompNs; - ctbs.getCurBucket().updateOneComponent(listener, procTime); + ctb.updateOneComponent(listener, procTime); } } @@ -135,7 +134,7 @@ public class PktInProcessingTime public void recordEndTimePktIn(IOFSwitch sw, OFMessage m, FloodlightContext cntx) { if (isEnabled()) { long procTimeNs = System.nanoTime() - startTimePktNs; - ctbs.getCurBucket().updatePerPacketCounters(procTimeNs); + ctb.updatePerPacketCounters(procTimeNs); if (ptWarningThresholdInNano > 0 && procTimeNs > ptWarningThresholdInNano) { logger.warn("Time to process packet-in: {} us", procTimeNs/1000); @@ -144,33 +143,6 @@ public class PktInProcessingTime } } - @Override - public CircularTimeBucketSet getCtbs() { - return ctbs; - } - - /*** - * This function is called when a packet in processing starts - * Check if it is time to go to the next bucket - * @param curTime_ns - */ - private void checkAndStartNextBucket(long curTime_ns) { - // We are not running any timer, packet arrivals themselves drive the - // rotation of the buckets - CumulativeTimeBucket ctb = ctbs.getCurBucket(); - if ((curTime_ns - ctb.getStartTimeNs()) > ONE_BUCKET_DURATION_NANOSECONDS) { - // Go to next bucket - this.ctbs.fillTimeBucket(ctb); - /*** - * We might not have received packets for long time, in which case - * there would be a gap in the start-time of the timer buckets - * indicating that there was no data. This should be a better - * utilization of resources instead of creating several empty - * buckets. - */ - } - } - // IFloodlightModule methods @Override @@ -197,7 +169,6 @@ public class PktInProcessingTime public Collection<Class<? extends IFloodlightService>> getModuleDependencies() { Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>(); - l.add(IStorageSourceService.class); l.add(IRestApiService.class); return l; } @@ -205,18 +176,11 @@ public class PktInProcessingTime @Override public void init(FloodlightModuleContext context) throws FloodlightModuleException { - storageSource = - context.getServiceImpl(IStorageSourceService.class); - restApi = - context.getServiceImpl(IRestApiService.class); + restApi = context.getServiceImpl(IRestApiService.class); } @Override public void startUp(FloodlightModuleContext context) { - // Subscribe to the storage (config change) notifications for the - // controller node - storageSource.addListener(ControllerTableName, this); - // Add our REST API restApi.addRestletRoutable(new PerfWebRoutable()); @@ -228,57 +192,4 @@ public class PktInProcessingTime ptWarningThresholdInNano/1000000); } } - - // IStorageSourceListener - - private boolean readPerfMonFromStorage() { - boolean value=false; - try { - IPredicate predicate = - new OperatorPredicate(COLUMN_ID, Operator.EQ, "localhost"); - IResultSet resultSet = storageSource.executeQuery( - ControllerTableName, - new String[] { COLUMN_PERF_MON }, predicate, null); - if (resultSet.next()) { - value = resultSet.getBoolean(COLUMN_PERF_MON); - } - } catch (StorageException e) { - logger.error("Failed to read controller table: {}", e.getMessage()); - } - return value; - } - - @Override - public void rowsModified(String tableName, Set<Object> rowKeys) { - logger.debug("Processing modification of Table {}", tableName); - if (ControllerTableName.equals(tableName)) { - if (rowKeys.contains("localhost")) { - // Get the current state - boolean oldProcTimeMonitoringState = isEnabled(); - // Get the new state - boolean newProcTimeMonitoringState = readPerfMonFromStorage(); - // See if the state changes from disabled to enabled - if (newProcTimeMonitoringState && !oldProcTimeMonitoringState) { - setEnabled(newProcTimeMonitoringState); - logger.info("Packet-In performance monitoring for " + - "controller localhost is enabled"); - } else if (!newProcTimeMonitoringState && - oldProcTimeMonitoringState) { - setEnabled(newProcTimeMonitoringState); - logger.info("Performance monitoring for controller " + - "localhost is disabled"); - } else { - logger.info("Performance monitoring for controller " + - "localhost is unchanged: {}", - newProcTimeMonitoringState); - } - } - return; - } - } - - @Override - public void rowsDeleted(String tableName, Set<Object> rowKeys) { - // no-op - } }