X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fprotocol_plugins%2Fopenflow%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fprotocol_plugin%2Fopenflow%2Finternal%2FOFStatisticsManager.java;h=e5883d671740e1f0950b4264a2558d65d4ce4228;hp=d6100e3fdc499c2bd53eb9eb45c414c70e8517d1;hb=dad78e1fc8a7c67fa4b88cf09d6a952443462feb;hpb=1757a30c3631e2a5ef97c6b5e79ad2c87fc7d855 diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java index d6100e3fdc..e5883d6717 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java @@ -13,7 +13,6 @@ import java.util.ArrayList; 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; @@ -23,19 +22,21 @@ import java.util.TimerTask; 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; @@ -46,7 +47,6 @@ import org.openflow.protocol.OFMatch; 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; @@ -54,6 +54,7 @@ import org.openflow.protocol.statistics.OFPortStatisticsRequest; 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; @@ -62,29 +63,29 @@ import org.slf4j.Logger; 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> flowStatistics; private ConcurrentMap> descStatistics; private ConcurrentMap> portStatistics; - private List dummyList; + private ConcurrentMap> tableStatistics; private ConcurrentMap statisticsTimerTicks; protected BlockingQueue pendingStatsRequests; protected BlockingQueue switchPortStatsUpdated; @@ -93,18 +94,17 @@ public class OFStatisticsManager implements IOFStatisticsManager, private Timer statisticsTimer; private TimerTask statisticsTimerTask; private ConcurrentMap switchSupportsVendorExtStats; - private Map> txRates; // Per port sampled (every - // portStatsPeriod) transmit - // rate - private Set descriptionListeners; + // Per port sampled (every portStatsPeriod) transmit rate + private Map> txRates; + private Set statisticsListeners = new CopyOnWriteArraySet(); /** * The object containing the latest factoredSamples tx rate samples for a * given switch port */ protected class TxRates { - Deque sampledTxBytes; // contains the latest factoredSamples - // sampled transmitted bytes + // contains the latest factoredSamples sampled transmitted bytes + Deque sampledTxBytes; public TxRates() { sampledTxBytes = new LinkedBlockingDeque(); @@ -125,7 +125,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, /** * Returns the average transmit rate in bps - * + * * @return the average transmit rate [bps] */ public long getAverageTxRate() { @@ -136,10 +136,9 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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; } @@ -155,30 +154,52 @@ public class OFStatisticsManager implements IOFStatisticsManager, } } + 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>(); descStatistics = new ConcurrentHashMap>(); portStatistics = new ConcurrentHashMap>(); - dummyList = new ArrayList(1); - statisticsTimerTicks = new ConcurrentHashMap( - initialSize); - pendingStatsRequests = new LinkedBlockingQueue( - initialSize); - switchPortStatsUpdated = new LinkedBlockingQueue(initialSize); - switchSupportsVendorExtStats = new ConcurrentHashMap( - initialSize); - txRates = new HashMap>(initialSize); - descriptionListeners = new HashSet(); + tableStatistics = new ConcurrentHashMap>(); + pendingStatsRequests = new LinkedBlockingQueue(getStatsQueueSize()); + statisticsTimerTicks = new ConcurrentHashMap(INITIAL_SIZE); + switchPortStatsUpdated = new LinkedBlockingQueue(INITIAL_SIZE); + switchSupportsVendorExtStats = new ConcurrentHashMap(INITIAL_SIZE); + txRates = new HashMap>(INITIAL_SIZE); configStatsPollIntervals(); // Initialize managed timers - statisticsTimer = new Timer(); + statisticsTimer = new Timer("Statistics Timer Ticks"); statisticsTimerTask = new TimerTask() { @Override public void run() { @@ -193,10 +214,11 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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; } } } @@ -212,6 +234,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, updatePortsTxRate(switchId); } catch (InterruptedException e) { log.warn("TX Rate Updater thread interrupted", e); + return; } } } @@ -222,19 +245,20 @@ public class OFStatisticsManager implements IOFStatisticsManager, * 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(); @@ -250,28 +274,26 @@ public class OFStatisticsManager implements IOFStatisticsManager, * 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 { @@ -283,6 +305,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, type = t; } + @Override public String toString() { return "SReq = {switchId=" + switchId + ", type=" + type + "}"; } @@ -331,7 +354,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, // 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())); } @@ -339,6 +362,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, private short flowStatisticsTicks; private short descriptionTicks; private short portStatisticsTicks; + private short tableStatisticsTicks; public StatisticsTicks(boolean scattered) { if (scattered) { @@ -350,10 +374,12 @@ public class OFStatisticsManager implements IOFStatisticsManager, % 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; } } @@ -387,18 +413,27 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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() { @@ -407,10 +442,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, .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) @@ -419,7 +454,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, } } - 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 @@ -429,7 +464,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, } } - 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 @@ -438,11 +473,21 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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 @@ -454,6 +499,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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); @@ -463,53 +510,84 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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 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 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 values) { - for (IStatisticsListener l : this.descriptionListeners) { - l.descriptionRefreshed(switchId, - ((OFDescriptionStatistics) values.get(0))); + private void notifyDescriptionUpdate(Long switchId, List values) { + for (IOFStatisticsListener l : this.statisticsListeners) { + l.descriptionStatisticsRefreshed(switchId, values); + } + } + + private void notifyFlowUpdate(Long switchId, List 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 values) { + for (IOFStatisticsListener l : this.statisticsListeners) { + l.portStatisticsRefreshed(switchId, values); + } + } + + private void notifyTableUpdate(Long switchId, List 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 acquireStatistics(Long switchId, + private List fetchStatisticsFromSwitch(Long switchId, OFStatisticsType statsType, Object target) { - List values = null; + List values = Collections.emptyList(); String type = null; ISwitch sw = controller.getSwitch(switchId); @@ -528,7 +606,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, // 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; @@ -564,12 +642,12 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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; @@ -582,7 +660,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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)); @@ -591,6 +669,20 @@ public class OFStatisticsManager implements IOFStatisticsManager, } 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); @@ -602,7 +694,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, } 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 {}", @@ -625,13 +717,13 @@ public class OFStatisticsManager implements IOFStatisticsManager, * 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.emptyList() : (list.get(0) instanceof OFVendorStatistics) ? this .v6StatsListToOFStatsList(list) : list; } @Override - public List getOFFlowStatistics(Long switchId, OFMatch ofMatch) { + public List getOFFlowStatistics(Long switchId, OFMatch ofMatch, short priority) { List statsList = flowStatistics.get(switchId); /* @@ -639,7 +731,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, * 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) { @@ -656,7 +748,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, for (OFStatistics stats : targetList) { V6StatsReply v6Stats = (V6StatsReply) stats; V6Match v6Match = v6Stats.getMatch(); - if (v6Match.equals(targetMatch)) { + if (v6Stats.getPriority() == priority && targetMatch.equals(v6Match)) { List list = new ArrayList(); list.add(stats); return list; @@ -665,29 +757,29 @@ public class OFStatisticsManager implements IOFStatisticsManager, } else { for (OFStatistics stats : statsList) { OFFlowStatisticsReply flowStats = (OFFlowStatisticsReply) stats; - if (flowStats.getMatch().equals(ofMatch)) { + if (flowStats.getPriority() == priority && ofMatch.equals(flowStats.getMatch())) { List list = new ArrayList(); list.add(stats); return list; } } } - return this.dummyList; + return Collections.emptyList(); } /* * Converts the v6 vendor statistics to the OFStatistics */ - private List v6StatsListToOFStatsList( - List statistics) { + private List v6StatsListToOFStatsList(List statistics) { + if (statistics == null || statistics.isEmpty()) { + return Collections.emptyList(); + } List v6statistics = new ArrayList(); - if (statistics != null && !statistics.isEmpty()) { - for (OFStatistics stats : statistics) { - if (stats instanceof OFVendorStatistics) { - List r = getV6ReplyStatistics((OFVendorStatistics) stats); - if (r != null) { - v6statistics.addAll(r); - } + for (OFStatistics stats : statistics) { + if (stats instanceof OFVendorStatistics) { + List r = getV6ReplyStatistics((OFVendorStatistics) stats); + if (r != null) { + v6statistics.addAll(r); } } } @@ -698,8 +790,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, OFVendorStatistics stat) { int length = stat.getLength(); List results = new ArrayList(); - 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(); @@ -711,7 +805,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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 @@ -724,12 +818,14 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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(); @@ -751,18 +847,16 @@ public class OFStatisticsManager implements IOFStatisticsManager, } } - List list = this.acquireStatistics(switchId, statType, - target); + List 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 getOFDescStatistics(Long switchId) { - if (!descStatistics.containsKey(switchId)) - return this.dummyList; + if (!descStatistics.containsKey(switchId)) { + return Collections.emptyList(); + } return descStatistics.get(switchId); } @@ -770,7 +864,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, @Override public List getOFPortStatistics(Long switchId) { if (!portStatistics.containsKey(switchId)) { - return this.dummyList; + return Collections.emptyList(); } return portStatistics.get(switchId); @@ -779,7 +873,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, @Override public List getOFPortStatistics(Long switchId, short portId) { if (!portStatistics.containsKey(switchId)) { - return this.dummyList; + return Collections.emptyList(); } List list = new ArrayList(1); for (OFStatistics stats : portStatistics.get(switchId)) { @@ -791,6 +885,31 @@ public class OFStatisticsManager implements IOFStatisticsManager, return list; } + @Override + public List getOFTableStatistics(Long switchId) { + if (!tableStatistics.containsKey(switchId)) { + return Collections.emptyList(); + } + + return tableStatistics.get(switchId); + } + + @Override + public List getOFTableStatistics(Long switchId, Byte tableId) { + if (!tableStatistics.containsKey(switchId)) { + return Collections.emptyList(); + } + + List list = new ArrayList(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(); @@ -822,12 +941,11 @@ public class OFStatisticsManager implements IOFStatisticsManager, /** * 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 newPortStatistics = this.portStatistics - .get(switchId); + List newPortStatistics = this.portStatistics.get(switchId); if (newPortStatistics == null) { return; } @@ -880,7 +998,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, help.append("---OF Statistics Manager utilities---\n"); help.append("\t ofdumpstatsmgr - " + "Print Internal Stats Mgr db\n"); - help.append("\t ofstatsmgrintervals (in seconds) - " + help.append("\t ofstatsmgrintervals (all in seconds) - " + "Set/Show flow/port/dedscription stats poll intervals\n"); return help.toString(); } @@ -938,6 +1056,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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) { @@ -1008,35 +1127,39 @@ public class OFStatisticsManager implements IOFStatisticsManager, String flowStatsInterv = ci.nextArgument(); String portStatsInterv = ci.nextArgument(); String descStatsInterv = ci.nextArgument(); + String tableStatsInterv = ci.nextArgument(); if (flowStatsInterv == null || portStatsInterv == null || descStatsInterv == null) { - ci.println("Usage: ostatsmgrintervals (in seconds)"); - ci.println("Current Values: fP=" + statisticsTickNumber + "s pP=" - + portTickNumber + "s dP=" + descriptionTickNumber + "s"); + ci.println("Usage: ofstatsmgrintervals (all in seconds)"); + ci.println("Current Values: fP=" + statisticsTickNumber + "sec pP=" + + portTickNumber + "sec dP=" + descriptionTickNumber + "sec tP=" + tableTickNumber + " sec"); 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"); } /** @@ -1047,7 +1170,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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 { @@ -1078,5 +1202,15 @@ public class OFStatisticsManager implements IOFStatisticsManager, } catch (Exception e) { } } + + if (tsStr != null) { + try{ + ts = Short.parseShort(tsStr); + if (ts > 0) { + tableTickNumber = ts; + } + } catch (Exception e) { + } + } } }