import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.opendaylight.controller.protocol_plugin.openflow.IInventoryShimExternalListener;
+import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsListener;
import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsManager;
-import org.opendaylight.controller.protocol_plugin.openflow.IStatisticsListener;
import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6StatsReply;
import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6StatsRequest;
+import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.core.Property;
import org.openflow.protocol.OFPort;
import org.openflow.protocol.OFStatisticsRequest;
import org.openflow.protocol.statistics.OFAggregateStatisticsRequest;
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
import org.openflow.protocol.statistics.OFFlowStatisticsReply;
import org.openflow.protocol.statistics.OFFlowStatisticsRequest;
import org.openflow.protocol.statistics.OFPortStatisticsReply;
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;
import org.slf4j.LoggerFactory;
/**
- * It periodically polls the different OF statistics from the OF switches and
- * caches them for quick retrieval for the above layers' modules It also
- * provides an API to directly query the switch about the statistics
+ * Periodically polls the different OF statistics from the OF switches, caches
+ * them, and publishes results towards SAL. It also provides an API to directly
+ * query the switch for any specific statistics.
*/
-public class OFStatisticsManager implements IOFStatisticsManager,
- 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 tickPeriod = 1000;
- private static short statisticsTickNumber = (short) (flowStatsPeriod / tickPeriod);
- private static short descriptionTickNumber = (short) (descriptionStatsPeriod / tickPeriod);
- private static short portTickNumber = (short) (portStatsPeriod / tickPeriod);
+public class OFStatisticsManager implements IOFStatisticsManager, IInventoryShimExternalListener, CommandProvider {
+ private static final Logger log = LoggerFactory.getLogger(OFStatisticsManager.class);
+ private static final int INITIAL_SIZE = 64;
+ private static final long FLOW_STATS_PERIOD = 10000;
+ private static final long DESC_STATS_PERIOD = 60000;
+ private static final long PORT_STATS_PERIOD = 5000;
+ private static final long TABLE_STATS_PERIOD = 10000;
+ private static final long TICK = 1000;
+ private static short statisticsTickNumber = (short) (FLOW_STATS_PERIOD / TICK);
+ private static short descriptionTickNumber = (short) (DESC_STATS_PERIOD / TICK);
+ private static short portTickNumber = (short) (PORT_STATS_PERIOD / TICK);
+ private static short tableTickNumber = (short) (TABLE_STATS_PERIOD / TICK);
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 List<OFStatistics> dummyList;
+ private ConcurrentMap<Long, List<OFStatistics>> tableStatistics;
private ConcurrentMap<Long, StatisticsTicks> statisticsTimerTicks;
protected BlockingQueue<StatsRequest> pendingStatsRequests;
protected BlockingQueue<Long> switchPortStatsUpdated;
private Timer statisticsTimer;
private TimerTask statisticsTimerTask;
private ConcurrentMap<Long, Boolean> switchSupportsVendorExtStats;
- private Map<Long, Map<Short, TxRates>> txRates; // Per port sampled (every
- // portStatsPeriod) transmit
- // rate
- private Set<IStatisticsListener> descriptionListeners;
+ // Per port sampled (every portStatsPeriod) transmit rate
+ private Map<Long, Map<Short, TxRates>> txRates;
+ private Set<IOFStatisticsListener> statisticsListeners = new CopyOnWriteArraySet<IOFStatisticsListener>();
/**
* The object containing the latest factoredSamples tx rate samples for a
* given switch port
*/
protected class TxRates {
- Deque<Long> sampledTxBytes; // contains the latest factoredSamples
- // sampled transmitted bytes
+ // contains the latest factoredSamples sampled transmitted bytes
+ Deque<Long> sampledTxBytes;
public TxRates() {
sampledTxBytes = new LinkedBlockingDeque<Long>();
/**
* Returns the average transmit rate in bps
- *
+ *
* @return the average transmit rate [bps]
*/
public long getAverageTxRate() {
if (sampledTxBytes.size() < factoredSamples) {
return average;
}
- long increment = (long) (sampledTxBytes.getFirst() - sampledTxBytes
- .getLast());
- long timePeriod = (long) (factoredSamples * portStatsPeriod)
- / (long) tickPeriod;
+ long increment = sampledTxBytes.getFirst() - sampledTxBytes
+ .getLast();
+ long timePeriod = factoredSamples * PORT_STATS_PERIOD / TICK;
average = (8L * increment) / timePeriod;
return average;
}
}
}
+ private short getStatsQueueSize() {
+ String statsQueueSizeStr = System.getProperty("of.statsQueueSize");
+ short statsQueueSize = INITIAL_SIZE;
+ if (statsQueueSizeStr != null) {
+ try {
+ statsQueueSize = Short.parseShort(statsQueueSizeStr);
+ if (statsQueueSize <= 0) {
+ statsQueueSize = INITIAL_SIZE;
+ }
+ } catch (Exception e) {
+ }
+ }
+ return statsQueueSize;
+ }
+
+ IPluginOutConnectionService connectionPluginOutService;
+ void setIPluginOutConnectionService(IPluginOutConnectionService s) {
+ connectionPluginOutService = s;
+ }
+
+ void unsetIPluginOutConnectionService(IPluginOutConnectionService s) {
+ if (connectionPluginOutService == s) {
+ connectionPluginOutService = null;
+ }
+ }
+
/**
* 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>>();
- dummyList = new ArrayList<OFStatistics>(1);
- statisticsTimerTicks = new ConcurrentHashMap<Long, StatisticsTicks>(
- initialSize);
- pendingStatsRequests = new LinkedBlockingQueue<StatsRequest>(
- initialSize);
- switchPortStatsUpdated = new LinkedBlockingQueue<Long>(initialSize);
- switchSupportsVendorExtStats = new ConcurrentHashMap<Long, Boolean>(
- initialSize);
- txRates = new HashMap<Long, Map<Short, TxRates>>(initialSize);
- descriptionListeners = new HashSet<IStatisticsListener>();
+ tableStatistics = new ConcurrentHashMap<Long, List<OFStatistics>>();
+ pendingStatsRequests = new LinkedBlockingQueue<StatsRequest>(getStatsQueueSize());
+ statisticsTimerTicks = new ConcurrentHashMap<Long, StatisticsTicks>(INITIAL_SIZE);
+ switchPortStatsUpdated = new LinkedBlockingQueue<Long>(INITIAL_SIZE);
+ switchSupportsVendorExtStats = new ConcurrentHashMap<Long, Boolean>(INITIAL_SIZE);
+ txRates = new HashMap<Long, Map<Short, TxRates>>(INITIAL_SIZE);
+
+ configStatsPollIntervals();
// Initialize managed timers
- statisticsTimer = new Timer();
+ statisticsTimer = new Timer("Statistics Timer Ticks");
statisticsTimerTask = new TimerTask() {
@Override
public void run() {
while (true) {
try {
StatsRequest req = pendingStatsRequests.take();
- acquireStatistics(req.switchId, req.type);
+ queryStatisticsInternal(req.switchId, req.type);
} catch (InterruptedException e) {
log.warn("Flow Statistics Collector thread "
+ "interrupted", e);
+ return;
}
}
}
updatePortsTxRate(switchId);
} catch (InterruptedException e) {
log.warn("TX Rate Updater thread interrupted", e);
+ return;
}
}
}
* 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() {
+ statisticsListeners.clear();
}
/**
* 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
- statisticsTimer.scheduleAtFixedRate(statisticsTimerTask, 0, tickPeriod);
+ statisticsTimer.scheduleAtFixedRate(statisticsTimerTask, 0, TICK);
// Start statistics collector thread
statisticsCollector.start();
* 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
statisticsTimer.cancel();
}
- public void setStatisticsListener(IStatisticsListener s) {
- this.descriptionListeners.add(s);
+ public void setStatisticsListener(IOFStatisticsListener s) {
+ this.statisticsListeners.add(s);
}
- public void unsetStatisticsListener(IStatisticsListener s) {
+ public void unsetStatisticsListener(IOFStatisticsListener s) {
if (s != null) {
- this.descriptionListeners.remove(s);
+ this.statisticsListeners.remove(s);
}
}
private void registerWithOSGIConsole() {
- BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
- .getBundleContext();
- bundleContext.registerService(CommandProvider.class.getName(), this,
- null);
+ BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ bundleContext.registerService(CommandProvider.class.getName(), this, null);
}
private static class StatsRequest {
type = t;
}
+ @Override
public String toString() {
return "SReq = {switchId=" + switchId + ", type=" + type + "}";
}
// extension
// stats
statisticsTimerTicks.put(switchId, new StatisticsTicks(true));
- log.info("Added Switch {} to target pool",
+ log.debug("Added Switch {} to target pool",
HexString.toHexString(switchId.longValue()));
}
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 + "}";
}
}
private void printInfoMessage(String type, StatsRequest request) {
- log.info(
- "{} stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.",
- new Object[] { type, HexString.toHexString(request.switchId),
- pendingStatsRequests.size(),
- statisticsCollector.getState().toString() });
+ log.trace("{} stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.",
+ new Object[] {type, HexString.toHexString(request.switchId), pendingStatsRequests.size(),
+ statisticsCollector.getState().toString() });
}
protected void decrementTicks() {
.entrySet()) {
StatisticsTicks clock = entry.getValue();
Long switchId = entry.getKey();
- if (clock.decrementFlowTicksIsZero() == true) {
- request = (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) ? new StatsRequest(
- switchId, OFStatisticsType.VENDOR) : new StatsRequest(
- switchId, OFStatisticsType.FLOW);
+ if (clock.decrementFlowTicksIsZero()) {
+ request = (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) ?
+ new StatsRequest(switchId, OFStatisticsType.VENDOR) :
+ new StatsRequest(switchId, OFStatisticsType.FLOW);
// If a request for this switch is already in the queue, skip to
// add this new request
if (!pendingStatsRequests.contains(request)
}
}
- if (clock.decrementDescTicksIsZero() == true) {
+ if (clock.decrementDescTicksIsZero()) {
request = new StatsRequest(switchId, OFStatisticsType.DESC);
// If a request for this switch is already in the queue, skip to
// add this new request
}
}
- if (clock.decrementPortTicksIsZero() == true) {
+ if (clock.decrementPortTicksIsZero()) {
request = new StatsRequest(switchId, OFStatisticsType.PORT);
// If a request for this switch is already in the queue, skip to
// add this new request
printInfoMessage("Port", request);
}
}
+
+ if(clock.decrementTableTicksIsZero()) {
+ 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);
+ }
+ }
}
}
private void removeStatsRequestTasks(Long switchId) {
- log.info("Cleaning Statistics database for switch {}",
+ log.debug("Cleaning Statistics database for switch {}",
HexEncode.longToHexString(switchId));
// To be safe, let's attempt removal of both VENDOR and FLOW request. It
// does not hurt
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);
statisticsTimerTicks.remove(switchId);
removeStatsRequestTasks(switchId);
flowStatistics.remove(switchId);
- log.info("Statistics removed for switch {}",
+ log.debug("Statistics removed for switch {}",
HexString.toHexString(switchId));
}
- private void acquireStatistics(Long switchId, OFStatisticsType statType) {
+ private void queryStatisticsInternal(Long switchId, OFStatisticsType statType) {
// Query the switch on all matches
- List<OFStatistics> values = this.acquireStatistics(switchId, statType,
- null);
-
- // Update local caching database if got a valid response
- if (values != null && !values.isEmpty()) {
- if ((statType == OFStatisticsType.FLOW)
- || (statType == OFStatisticsType.VENDOR)) {
- flowStatistics.put(switchId, values);
- } else if (statType == OFStatisticsType.DESC) {
- // Notify who may be interested in a description change
- notifyDescriptionListeners(switchId, values);
-
- // Overwrite cache
- descStatistics.put(switchId, values);
- } else if (statType == OFStatisticsType.PORT) {
- // Overwrite cache with new port statistics for this switch
- portStatistics.put(switchId, values);
-
- // Wake up the thread which maintains the TX byte counters for
- // each port
- switchPortStatsUpdated.offer(switchId);
+ List<OFStatistics> values = this.fetchStatisticsFromSwitch(switchId, statType, null);
+
+ // If got a valid response update local cache and notify listeners
+ if (!values.isEmpty()) {
+ switch (statType) {
+ case FLOW:
+ case VENDOR:
+ flowStatistics.put(switchId, values);
+ notifyFlowUpdate(switchId, values);
+ break;
+ case DESC:
+ // Overwrite cache
+ descStatistics.put(switchId, values);
+ // Notify who may be interested in a description change
+ notifyDescriptionUpdate(switchId, values);
+ break;
+ case PORT:
+ // Overwrite cache with new port statistics for this switch
+ portStatistics.put(switchId, values);
+
+ // Wake up the thread which maintains the TX byte counters for
+ // each port
+ switchPortStatsUpdated.offer(switchId);
+ notifyPortUpdate(switchId, values);
+ break;
+ case TABLE:
+ // Overwrite cache
+ tableStatistics.put(switchId, values);
+ notifyTableUpdate(switchId, values);
+ break;
+ default:
}
}
}
- private void notifyDescriptionListeners(Long switchId,
- List<OFStatistics> values) {
- for (IStatisticsListener l : this.descriptionListeners) {
- l.descriptionRefreshed(switchId,
- ((OFDescriptionStatistics) values.get(0)));
+ private void notifyDescriptionUpdate(Long switchId, List<OFStatistics> values) {
+ for (IOFStatisticsListener l : this.statisticsListeners) {
+ l.descriptionStatisticsRefreshed(switchId, values);
+ }
+ }
+
+ private void notifyFlowUpdate(Long switchId, List<OFStatistics> values) {
+ if (values.get(0) instanceof OFVendorStatistics) {
+ values = this.v6StatsListToOFStatsList(values);
+ }
+
+ for (IOFStatisticsListener l : this.statisticsListeners) {
+ l.flowStatisticsRefreshed(switchId, values);
+ }
+
+ }
+
+ private void notifyPortUpdate(Long switchId, List<OFStatistics> values) {
+ for (IOFStatisticsListener l : this.statisticsListeners) {
+ l.portStatisticsRefreshed(switchId, values);
+ }
+ }
+
+ private void notifyTableUpdate(Long switchId, List<OFStatistics> values) {
+ for (IOFStatisticsListener l : this.statisticsListeners) {
+ l.tableStatisticsRefreshed(switchId, values);
}
}
/*
- * Generic function to get the statistics form a OF switch
+ * Generic function to get the statistics form an OF switch
*/
@SuppressWarnings("unchecked")
- private List<OFStatistics> acquireStatistics(Long switchId,
+ private List<OFStatistics> fetchStatisticsFromSwitch(Long switchId,
OFStatisticsType statsType, Object target) {
- List<OFStatistics> values = null;
+ List<OFStatistics> values = Collections.emptyList();
String type = null;
ISwitch sw = controller.getSwitch(switchId);
// Malformed request
log.warn("Invalid target type for Flow stats request: {}",
target.getClass());
- return null;
+ return Collections.emptyList();
} else {
// Specific flow request
match = (OFMatch) target;
short targetPort;
if (target == null) {
// All ports request
- targetPort = (short) OFPort.OFPP_NONE.getValue();
+ targetPort = OFPort.OFPP_NONE.getValue();
} else if (!(target instanceof Short)) {
// Malformed request
log.warn("Invalid target type for Port stats request: {}",
target.getClass());
- return null;
+ return Collections.emptyList();
} else {
// Specific port request
targetPort = (Short) target;
type = "PORT";
} else if (statsType == OFStatisticsType.QUEUE) {
OFQueueStatisticsRequest specificReq = new OFQueueStatisticsRequest();
- specificReq.setPortNumber((short) OFPort.OFPP_ALL.getValue());
+ specificReq.setPortNumber(OFPort.OFPP_ALL.getValue());
specificReq.setQueueId(0xffffffff);
req.setStatistics(Collections
.singletonList((OFStatistics) specificReq));
} 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 Collections.emptyList();
+ }
+ 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 {}",
* Check on emptiness as interference between add and get is still
* possible on the inner list (the concurrentMap entry's value)
*/
- return (list == null || list.isEmpty()) ? this.dummyList
+ return (list == null || list.isEmpty()) ? Collections.<OFStatistics>emptyList()
: (list.get(0) instanceof OFVendorStatistics) ? this
.v6StatsListToOFStatsList(list) : list;
}
@Override
- public List<OFStatistics> getOFFlowStatistics(Long switchId, OFMatch ofMatch) {
+ public List<OFStatistics> getOFFlowStatistics(Long switchId, OFMatch ofMatch, short priority) {
List<OFStatistics> statsList = flowStatistics.get(switchId);
/*
* possible on the inner list (the concurrentMap entry's value)
*/
if (statsList == null || statsList.isEmpty()) {
- return this.dummyList;
+ return Collections.emptyList();
}
if (statsList.get(0) instanceof OFVendorStatistics) {
for (OFStatistics stats : targetList) {
V6StatsReply v6Stats = (V6StatsReply) stats;
V6Match v6Match = v6Stats.getMatch();
- if (v6Match.equals(targetMatch)) {
+ if (v6Stats.getPriority() == priority && targetMatch.equals(v6Match)) {
List<OFStatistics> list = new ArrayList<OFStatistics>();
list.add(stats);
return list;
} else {
for (OFStatistics stats : statsList) {
OFFlowStatisticsReply flowStats = (OFFlowStatisticsReply) stats;
- if (flowStats.getMatch().equals(ofMatch)) {
+ if (flowStats.getPriority() == priority && ofMatch.equals(flowStats.getMatch())) {
List<OFStatistics> list = new ArrayList<OFStatistics>();
list.add(stats);
return list;
}
}
}
- return this.dummyList;
+ return Collections.emptyList();
}
/*
* Converts the v6 vendor statistics to the OFStatistics
*/
- private List<OFStatistics> v6StatsListToOFStatsList(
- List<OFStatistics> statistics) {
+ private List<OFStatistics> v6StatsListToOFStatsList(List<OFStatistics> statistics) {
+ if (statistics == null || statistics.isEmpty()) {
+ return Collections.emptyList();
+ }
List<OFStatistics> v6statistics = new ArrayList<OFStatistics>();
- if (statistics != null && !statistics.isEmpty()) {
- for (OFStatistics stats : statistics) {
- if (stats instanceof OFVendorStatistics) {
- List<OFStatistics> r = getV6ReplyStatistics((OFVendorStatistics) stats);
- if (r != null) {
- v6statistics.addAll(r);
- }
+ for (OFStatistics stats : statistics) {
+ if (stats instanceof OFVendorStatistics) {
+ List<OFStatistics> r = getV6ReplyStatistics((OFVendorStatistics) stats);
+ if (r != null) {
+ v6statistics.addAll(r);
}
}
}
OFVendorStatistics stat) {
int length = stat.getLength();
List<OFStatistics> results = new ArrayList<OFStatistics>();
- if (length < 12)
- return null; // Nicira Hdr is 12 bytes. We need atleast that much
+ if (length < 12) {
+ // Nicira Hdr is 12 bytes. We need at least that much
+ return Collections.emptyList();
+ }
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) {
log.warn("Unexpected vendor id: 0x{}", Integer.toHexString(vendor));
- return null;
+ return Collections.emptyList();
} else {
// go ahead by 8 bytes which is 8 bytes of 0
data.getLong(); // should be all 0's
while (length > 0) {
v6statsreply = new V6StatsReply();
min_len = v6statsreply.getLength();
- if (length < v6statsreply.getLength())
+ if (length < v6statsreply.getLength()) {
break;
+ }
v6statsreply.setActionFactory(stat.getActionFactory());
v6statsreply.readFrom(data);
- if (v6statsreply.getLength() < min_len)
+ if (v6statsreply.getLength() < min_len) {
break;
+ }
v6statsreply.setVendorId(vendor);
log.trace("V6StatsReply: {}", v6statsreply);
length -= v6statsreply.getLength();
}
}
- List<OFStatistics> list = this.acquireStatistics(switchId, statType,
- target);
+ List<OFStatistics> list = this.fetchStatisticsFromSwitch(switchId, statType, target);
- return (list == null) ? null
- : (statType == OFStatisticsType.VENDOR) ? v6StatsListToOFStatsList(list)
- : list;
+ return (statType == OFStatisticsType.VENDOR) ? v6StatsListToOFStatsList(list) : list;
}
@Override
public List<OFStatistics> getOFDescStatistics(Long switchId) {
- if (!descStatistics.containsKey(switchId))
- return this.dummyList;
+ if (!descStatistics.containsKey(switchId)) {
+ return Collections.emptyList();
+ }
return descStatistics.get(switchId);
}
@Override
public List<OFStatistics> getOFPortStatistics(Long switchId) {
if (!portStatistics.containsKey(switchId)) {
- return this.dummyList;
+ return Collections.emptyList();
}
return portStatistics.get(switchId);
@Override
public List<OFStatistics> getOFPortStatistics(Long switchId, short portId) {
if (!portStatistics.containsKey(switchId)) {
- return this.dummyList;
+ return Collections.emptyList();
}
List<OFStatistics> list = new ArrayList<OFStatistics>(1);
for (OFStatistics stats : portStatistics.get(switchId)) {
return list;
}
+ @Override
+ public List<OFStatistics> getOFTableStatistics(Long switchId) {
+ if (!tableStatistics.containsKey(switchId)) {
+ return Collections.emptyList();
+ }
+
+ return tableStatistics.get(switchId);
+ }
+
+ @Override
+ public List<OFStatistics> getOFTableStatistics(Long switchId, Byte tableId) {
+ if (!tableStatistics.containsKey(switchId)) {
+ return Collections.emptyList();
+ }
+
+ 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) {
- List<OFStatistics> newPortStatistics = this.portStatistics
- .get(switchId);
+ List<OFStatistics> newPortStatistics = this.portStatistics.get(switchId);
if (newPortStatistics == null) {
return;
}
help.append("---OF Statistics Manager utilities---\n");
help.append("\t ofdumpstatsmgr - "
+ "Print Internal Stats Mgr db\n");
+ help.append("\t ofstatsmgrintervals <fP> <pP> <dP> <tP> (all in seconds) - "
+ + "Set/Show flow/port/dedscription stats poll intervals\n");
return help.toString();
}
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) {
public void _ofstatsmgrintervals(CommandInterpreter ci) {
String flowStatsInterv = ci.nextArgument();
String portStatsInterv = ci.nextArgument();
-
- if (flowStatsInterv == null || portStatsInterv == null) {
-
- ci.println("Usage: ostatsmgrintervals <fP> <pP> (in seconds)");
- ci.println("Current Values: fP=" + statisticsTickNumber + "s pP="
- + portTickNumber + "s");
+ String descStatsInterv = ci.nextArgument();
+ String tableStatsInterv = ci.nextArgument();
+
+ if (flowStatsInterv == null || portStatsInterv == null
+ || descStatsInterv == null) {
+ ci.println("Usage: ofstatsmgrintervals <fP> <pP> <dP> <tP> (all in seconds)");
+ ci.println("Current Values: fP=" + statisticsTickNumber + "sec pP="
+ + portTickNumber + "sec dP=" + descriptionTickNumber + "sec tP=" + tableTickNumber + " sec");
return;
}
- Short fP, pP;
+ 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) {
- ci.println("Invalid values. fP and pP 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");
+ + portTickNumber + "s dP=" + descriptionTickNumber + "s tP="
+ + tableTickNumber + "s");
}
+ /**
+ * This method retrieves user configurations from config.ini and updates
+ * statisticsTickNumber/portTickNumber/descriptionTickNumber accordingly.
+ */
+ private void configStatsPollIntervals() {
+ String fsStr = System.getProperty("of.flowStatsPollInterval");
+ String psStr = System.getProperty("of.portStatsPollInterval");
+ String dsStr = System.getProperty("of.descStatsPollInterval");
+ String tsStr = System.getProperty("of.tableStatsPollInterval");
+ Short fs, ps, ds, ts;
+
+ if (fsStr != null) {
+ try {
+ fs = Short.parseShort(fsStr);
+ if (fs > 0) {
+ statisticsTickNumber = fs;
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ if (psStr != null) {
+ try {
+ ps = Short.parseShort(psStr);
+ if (ps > 0) {
+ portTickNumber = ps;
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ if (dsStr != null) {
+ try {
+ ds = Short.parseShort(dsStr);
+ if (ds > 0) {
+ descriptionTickNumber = ds;
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ if (tsStr != null) {
+ try{
+ ts = Short.parseShort(tsStr);
+ if (ts > 0) {
+ tableTickNumber = ts;
+ }
+ } catch (Exception e) {
+ }
+ }
+ }
}