import org.openflow.protocol.statistics.OFQueueStatisticsRequest;
import org.openflow.protocol.statistics.OFStatistics;
import org.openflow.protocol.statistics.OFStatisticsType;
+import org.openflow.protocol.statistics.OFTableStatistics;
import org.openflow.protocol.statistics.OFVendorStatistics;
import org.openflow.util.HexString;
import org.osgi.framework.BundleContext;
* provides an API to directly query the switch about the statistics
*/
public class OFStatisticsManager implements IOFStatisticsManager,
- IInventoryShimExternalListener, CommandProvider {
+IInventoryShimExternalListener, CommandProvider {
private static final Logger log = LoggerFactory
.getLogger(OFStatisticsManager.class);
private static final int initialSize = 64;
private static final long flowStatsPeriod = 10000;
private static final long descriptionStatsPeriod = 60000;
private static final long portStatsPeriod = 5000;
+ private static final long tableStatsPeriod = 10000;
private static final long tickPeriod = 1000;
private static short statisticsTickNumber = (short) (flowStatsPeriod / tickPeriod);
private static short descriptionTickNumber = (short) (descriptionStatsPeriod / tickPeriod);
private static short portTickNumber = (short) (portStatsPeriod / tickPeriod);
+ private static short tableTickNumber = (short) (tableStatsPeriod / tickPeriod);
private static short factoredSamples = (short) 2;
private static short counter = 1;
private IController controller = null;
private ConcurrentMap<Long, List<OFStatistics>> flowStatistics;
private ConcurrentMap<Long, List<OFStatistics>> descStatistics;
private ConcurrentMap<Long, List<OFStatistics>> portStatistics;
+ private ConcurrentMap<Long, List<OFStatistics>> tableStatistics;
private List<OFStatistics> dummyList;
private ConcurrentMap<Long, StatisticsTicks> statisticsTimerTicks;
protected BlockingQueue<StatsRequest> pendingStatsRequests;
/**
* Returns the average transmit rate in bps
- *
+ *
* @return the average transmit rate [bps]
*/
public long getAverageTxRate() {
/**
* Function called by the dependency manager when all the required
* dependencies are satisfied
- *
+ *
*/
void init() {
flowStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
descStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
portStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
+ tableStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
dummyList = new ArrayList<OFStatistics>(1);
statisticsTimerTicks = new ConcurrentHashMap<Long, StatisticsTicks>(
initialSize);
descriptionListeners = new HashSet<IStatisticsListener>();
configStatsPollIntervals();
-
+
// Initialize managed timers
statisticsTimer = new Timer();
statisticsTimerTask = new TimerTask() {
* Function called by the dependency manager when at least one dependency
* become unsatisfied or when the component is shutting down because for
* example bundle is being stopped.
- *
+ *
*/
void destroy() {
}
/**
* Function called by dependency manager after "init ()" is called and after
* the services provided by the class are registered in the service registry
- *
+ *
*/
void start() {
// Start managed timers
* Function called by the dependency manager before the services exported by
* the component are unregistered, this will be followed by a "destroy ()"
* calls
- *
+ *
*/
void stop() {
// Stop managed timers
type = t;
}
+ @Override
public String toString() {
return "SReq = {switchId=" + switchId + ", type=" + type + "}";
}
private short flowStatisticsTicks;
private short descriptionTicks;
private short portStatisticsTicks;
+ private short tableStatisticsTicks;
public StatisticsTicks(boolean scattered) {
if (scattered) {
% statisticsTickNumber);
descriptionTicks = (short) (1 + counter % descriptionTickNumber);
portStatisticsTicks = (short) (1 + counter % portTickNumber);
+ tableStatisticsTicks = (short) (1 + counter % tableTickNumber);
} else {
flowStatisticsTicks = statisticsTickNumber;
descriptionTicks = descriptionTickNumber;
portStatisticsTicks = portTickNumber;
+ tableStatisticsTicks = tableTickNumber;
}
}
return false;
}
+ public boolean decrementTableTicksIsZero() {
+ // Please ensure no code is inserted between the if check and the
+ // descriptionTicks reset
+ if(--tableStatisticsTicks == 0) {
+ tableStatisticsTicks = tableTickNumber;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public String toString() {
return "{fT=" + flowStatisticsTicks + ",dT=" + descriptionTicks
- + ",pT=" + portStatisticsTicks + "}";
+ + ",pT=" + portStatisticsTicks + ",tT=" + tableStatisticsTicks + "}";
}
}
printInfoMessage("Port", request);
}
}
+
+ if(clock.decrementTableTicksIsZero() == true) {
+ request = new StatsRequest(switchId, OFStatisticsType.TABLE);
+ // If a request for this switch is already in the queue, skip to
+ // add this new request
+ if (!pendingStatsRequests.contains(request)
+ && false == pendingStatsRequests.offer(request)) {
+ printInfoMessage("Table", request);
+ }
+ }
}
}
OFStatisticsType.DESC));
pendingStatsRequests.remove(new StatsRequest(switchId,
OFStatisticsType.PORT));
+ pendingStatsRequests.remove(new StatsRequest(switchId,
+ OFStatisticsType.TABLE));
// Take care of the TX rate databases
switchPortStatsUpdated.remove(switchId);
txRates.remove(switchId);
// Wake up the thread which maintains the TX byte counters for
// each port
switchPortStatsUpdated.offer(switchId);
+ } else if (statType == OFStatisticsType.TABLE) {
+ // Overwrite cache
+ tableStatistics.put(switchId, values);
}
}
}
} else if (statsType == OFStatisticsType.DESC) {
type = "DESC";
} else if (statsType == OFStatisticsType.TABLE) {
+ if(target != null){
+ if (!(target instanceof Byte)) {
+ // Malformed request
+ log.warn("Invalid table id for table stats request: {}",
+ target.getClass());
+ return null;
+ }
+ byte targetTable = (Byte) target;
+ OFTableStatistics specificReq = new OFTableStatistics();
+ specificReq.setTableId(targetTable);
+ req.setStatistics(Collections
+ .singletonList((OFStatistics) specificReq));
+ requestLength += specificReq.getLength();
+ }
type = "TABLE";
}
req.setLengthU(requestLength);
} else if (result instanceof OFError) {
log.warn("Switch {} failed to handle ({}) stats request: {}",
new Object[] { HexString.toHexString(switchId), type,
- Utils.getOFErrorString((OFError) result) });
+ Utils.getOFErrorString((OFError) result) });
if (this.switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) {
log.warn(
"Switching back to regular Flow stats requests for switch {}",
ByteBuffer data = ByteBuffer.allocate(length);
stat.writeTo(data);
data.rewind();
- log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}",
- HexString.toHexString(data.array()));
+ if (log.isTraceEnabled()) {
+ log.trace("getV6ReplyStatistics: Buffer BYTES ARE {}",
+ HexString.toHexString(data.array()));
+ }
int vendor = data.getInt(); // first 4 bytes is vendor id.
if (vendor != V6StatsRequest.NICIRA_VENDOR_ID) {
return list;
}
+ @Override
+ public List<OFStatistics> getOFTableStatistics(Long switchId) {
+ if (!tableStatistics.containsKey(switchId)) {
+ return this.dummyList;
+ }
+
+ return tableStatistics.get(switchId);
+ }
+
+ @Override
+ public List<OFStatistics> getOFTableStatistics(Long switchId, Byte tableId) {
+ if (!tableStatistics.containsKey(switchId)) {
+ return this.dummyList;
+ }
+
+ List<OFStatistics> list = new ArrayList<OFStatistics>(1);
+ for (OFStatistics stats : tableStatistics.get(switchId)) {
+ if (((OFTableStatistics) stats).getTableId() == tableId) {
+ list.add(stats);
+ break;
+ }
+ }
+ return list;
+ }
+
@Override
public int getFlowsNumber(long switchId) {
return this.flowStatistics.get(switchId).size();
/**
* Update the cached port rates for this switch with the latest retrieved
* port transmit byte count
- *
+ *
* @param switchId
*/
private synchronized void updatePortsTxRate(long switchId) {
ci.println("Flow Stats Period: " + statisticsTickNumber + " s");
ci.println("Desc Stats Period: " + descriptionTickNumber + " s");
ci.println("Port Stats Period: " + portTickNumber + " s");
+ ci.println("Table Stats Period: " + tableTickNumber + " s");
}
public void _resetSwitchCapability(CommandInterpreter ci) {
String flowStatsInterv = ci.nextArgument();
String portStatsInterv = ci.nextArgument();
String descStatsInterv = ci.nextArgument();
+ String tableStatsInterv = ci.nextArgument();
if (flowStatsInterv == null || portStatsInterv == null
|| descStatsInterv == null) {
+ portTickNumber + "s dP=" + descriptionTickNumber + "s");
return;
}
- Short fP, pP, dP;
+ Short fP, pP, dP, tP;
try {
fP = Short.parseShort(flowStatsInterv);
pP = Short.parseShort(portStatsInterv);
dP = Short.parseShort(descStatsInterv);
+ tP = Short.parseShort(tableStatsInterv);
} catch (Exception e) {
ci.println("Invalid format values: " + e.getMessage());
return;
}
- if (pP <= 1 || fP <= 1 || dP <= 1) {
- ci.println("Invalid values. fP, pP, dP have to be greater than 1.");
+ if (pP <= 1 || fP <= 1 || dP <= 1 || tP <= 1) {
+ ci.println("Invalid values. fP, pP, dP, tP have to be greater than 1.");
return;
}
statisticsTickNumber = fP;
portTickNumber = pP;
descriptionTickNumber = dP;
+ tableTickNumber = tP;
ci.println("New Values: fP=" + statisticsTickNumber + "s pP="
- + portTickNumber + "s dP=" + descriptionTickNumber + "s");
+ + portTickNumber + "s dP=" + descriptionTickNumber + "s tP="
+ + tableTickNumber + "s");
}
/**
String fsStr = System.getProperty("of.flowStatsPollInterval");
String psStr = System.getProperty("of.portStatsPollInterval");
String dsStr = System.getProperty("of.descStatsPollInterval");
- Short fs, ps, ds;
+ String tsStr = System.getProperty("of.tableStatsPollInterval");
+ Short fs, ps, ds, ts;
if (fsStr != null) {
try {
} catch (Exception e) {
}
}
+
+ if (tsStr != null) {
+ try{
+ ts = Short.parseShort(tsStr);
+ if (ts > 0) {
+ tableTickNumber = ts;
+ }
+ } catch (Exception e) {
+ }
+ }
}
}