blob: 639623b3d52e0cb4d6b5a4657f1758fca02ed639 [file] [log] [blame]
/**
* Performance monitoring package
*/
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 net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.annotations.LogMessageCategory;
import net.floodlightcontroller.core.annotations.LogMessageDoc;
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 org.openflow.protocol.OFMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class contains a set of buckets (called time buckets as the
* primarily contain 'times' that are used in a circular way to
* store information on packet in processing time.
* Each bucket is meant to store the various processing time
* related data for a fixed duration.
* Buckets are reused to reduce garbage generation! Once the
* last bucket is used up the LRU bucket is reused.
*
* Naming convention for variable or constants
* variable_s : value in seconds
* variable_ms: value in milliseconds
* variable_us: value in microseconds
* variable_ns: value in nanoseconds
*
* Key Constants:
* ONE_BUCKET_DURATION_SECONDS_INT: time duration of each bucket
* BUCKET_SET_SIZE: Number of buckets
* TOT_PROC_TIME_WARN_THRESHOLD_US: if processing time for a packet
* exceeds this threshold then a warning LOG message is generated
* TOT_PROC_TIME_ALERT_THRESHOLD_US: same as above but an alert level
* syslog is generated instead
*
*/
@LogMessageCategory("Performance Monitoring")
public class PktInProcessingTime
implements IFloodlightModule, IPktInProcessingTimeService {
// Our dependencies
private IRestApiService restApi;
protected long ptWarningThresholdInNano;
// DB storage tables
protected static final String ControllerTableName = "controller_controller";
public static final String COLUMN_ID = "id";
public static final String COLUMN_PERF_MON = "performance_monitor_feature";
protected static Logger logger =
LoggerFactory.getLogger(PktInProcessingTime.class);
protected boolean isEnabled = false;
protected boolean isInited = false;
// Maintains the time when the last packet was processed
protected long lastPktTime_ns;
private CumulativeTimeBucket ctb = null;
/***
* BUCKET_SET_SIZE buckets each holding 10s of processing time data, a total
* of 30*10s = 5mins of processing time data is maintained
*/
protected static final int ONE_BUCKET_DURATION_SECONDS = 10;// seconds
protected static final long ONE_BUCKET_DURATION_NANOSECONDS =
ONE_BUCKET_DURATION_SECONDS * 1000000000;
@Override
public void bootstrap(List<IOFMessageListener> listeners) {
if (!isInited) {
ctb = new CumulativeTimeBucket(listeners);
isInited = true;
}
}
@Override
public boolean isEnabled() {
return isEnabled && isInited;
}
@Override
public void setEnabled(boolean enabled) {
this.isEnabled = enabled;
logger.debug("Setting module to " + isEnabled);
}
@Override
public CumulativeTimeBucket getCtb() {
return ctb;
}
private long startTimePktNs;
private long startTimeCompNs;
@Override
public void recordStartTimeComp(IOFMessageListener listener) {
if (isEnabled()) {
startTimeCompNs = System.nanoTime();
}
}
@Override
public void recordEndTimeComp(IOFMessageListener listener) {
if (isEnabled()) {
long procTime = System.nanoTime() - startTimeCompNs;
ctb.updateOneComponent(listener, procTime);
}
}
@Override
public void recordStartTimePktIn() {
if (isEnabled()) {
startTimePktNs = System.nanoTime();
}
}
@Override
@LogMessageDoc(level="WARN",
message="Time to process packet-in exceeded threshold: {}",
explanation="Time to process packet-in exceeded the configured " +
"performance threshold",
recommendation=LogMessageDoc.CHECK_CONTROLLER)
public void recordEndTimePktIn(IOFSwitch sw, OFMessage m, FloodlightContext cntx) {
if (isEnabled()) {
long procTimeNs = System.nanoTime() - startTimePktNs;
ctb.updatePerPacketCounters(procTimeNs);
if (ptWarningThresholdInNano > 0 &&
procTimeNs > ptWarningThresholdInNano) {
logger.warn("Time to process packet-in exceeded threshold: {}",
procTimeNs/1000);
}
}
}
// IFloodlightModule methods
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IPktInProcessingTimeService.class);
return l;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService>
getServiceImpls() {
Map<Class<? extends IFloodlightService>,
IFloodlightService> m =
new HashMap<Class<? extends IFloodlightService>,
IFloodlightService>();
// We are the class that implements the service
m.put(IPktInProcessingTimeService.class, this);
return m;
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l =
new ArrayList<Class<? extends IFloodlightService>>();
l.add(IRestApiService.class);
return l;
}
@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
restApi = context.getServiceImpl(IRestApiService.class);
}
@Override
@LogMessageDoc(level="INFO",
message="Packet processing time threshold for warning" +
" set to {time} ms.",
explanation="Performance monitoring will log a warning if " +
"packet processing time exceeds the configured threshold")
public void startUp(FloodlightModuleContext context) {
// Add our REST API
restApi.addRestletRoutable(new PerfWebRoutable());
// TODO - Alex - change this to a config option
ptWarningThresholdInNano = Long.parseLong(System.getProperty(
"net.floodlightcontroller.core.PTWarningThresholdInMilli", "0")) * 1000000;
if (ptWarningThresholdInNano > 0) {
logger.info("Packet processing time threshold for warning" +
" set to {} ms.", ptWarningThresholdInNano/1000000);
}
}
}