| /** |
| * 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); |
| } |
| } |
| } |