X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fprotocol_plugins%2Fopenflow%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fprotocol_plugin%2Fopenflow%2Finternal%2FOFStatisticsManager.java;h=78fddc773637c8aefb338b729d4e416e66e85441;hb=refs%2Fchanges%2F49%2F449%2F1;hp=bd31f8b7b3b1aec1c15b5eda79b677966ebb9823;hpb=29f7cfb54b580928c7feac63abce028a7014b0d5;p=controller.git 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 bd31f8b7b3..78fddc7736 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 @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -30,13 +29,18 @@ 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.IOFInventoryService; 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.core.Node; +import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.Property; +import org.opendaylight.controller.sal.core.UpdateType; +import org.opendaylight.controller.sal.utils.HexEncode; import org.openflow.protocol.OFError; import org.openflow.protocol.OFMatch; import org.openflow.protocol.OFPort; @@ -50,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; @@ -57,42 +62,32 @@ import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.opendaylight.controller.sal.core.Name; -import org.opendaylight.controller.sal.core.Node; -import org.opendaylight.controller.sal.core.NodeConnector; -import org.opendaylight.controller.sal.core.Property; -import org.opendaylight.controller.sal.core.UpdateType; -import org.opendaylight.controller.sal.utils.GlobalConstants; -import org.opendaylight.controller.sal.utils.HexEncode; -import org.opendaylight.controller.sal.utils.ServiceHelper; - /** - * 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 - * - * - * + * 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 */ 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 long statisticsTimeout = 4000; + 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> flowStatistics; private ConcurrentMap> descStatistics; private ConcurrentMap> portStatistics; + private ConcurrentMap> tableStatistics; private List dummyList; private ConcurrentMap statisticsTimerTicks; protected BlockingQueue pendingStatsRequests; @@ -102,15 +97,18 @@ public class OFStatisticsManager implements IOFStatisticsManager, private Timer statisticsTimer; private TimerTask statisticsTimerTask; private ConcurrentMap switchSupportsVendorExtStats; - private Map switchNamesDB; - private Map> txRates; // Per port sampled (every portStatsPeriod) transmit rate + private Map> txRates; // Per port sampled (every + // portStatsPeriod) transmit + // rate + private Set descriptionListeners; /** - * The object containing the latest factoredSamples tx rate samples - * for a given switch port + * 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 + Deque sampledTxBytes; // contains the latest factoredSamples + // sampled transmitted bytes public TxRates() { sampledTxBytes = new LinkedBlockingDeque(); @@ -118,8 +116,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, public void update(Long txBytes) { /* - * Based on how many samples our average works on, - * we might have to remove the oldest sample + * Based on how many samples our average works on, we might have to + * remove the oldest sample */ if (sampledTxBytes.size() == factoredSamples) { sampledTxBytes.removeLast(); @@ -131,6 +129,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, /** * Returns the average transmit rate in bps + * * @return the average transmit rate [bps] */ public long getAverageTxRate() { @@ -145,7 +144,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, .getLast()); long timePeriod = (long) (factoredSamples * portStatsPeriod) / (long) tickPeriod; - average = (8 * increment) / timePeriod; + average = (8L * increment) / timePeriod; return average; } } @@ -163,57 +162,14 @@ public class OFStatisticsManager implements IOFStatisticsManager, /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ void init() { - } - - /** - * 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 - statisticsTimer.scheduleAtFixedRate(statisticsTimerTask, 0, tickPeriod); - - // Start statistics collector thread - statisticsCollector.start(); - - // Start bandwidth utilization computer thread - txRatesUpdater.start(); - - // OSGI console - registerWithOSGIConsole(); - } - - /** - * 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 OFStatisticsManager() { flowStatistics = new ConcurrentHashMap>(); descStatistics = new ConcurrentHashMap>(); portStatistics = new ConcurrentHashMap>(); + tableStatistics = new ConcurrentHashMap>(); dummyList = new ArrayList(1); - switchNamesDB = new HashMap(); statisticsTimerTicks = new ConcurrentHashMap( initialSize); pendingStatsRequests = new LinkedBlockingQueue( @@ -222,6 +178,9 @@ public class OFStatisticsManager implements IOFStatisticsManager, switchSupportsVendorExtStats = new ConcurrentHashMap( initialSize); txRates = new HashMap>(initialSize); + descriptionListeners = new HashSet(); + + configStatsPollIntervals(); // Initialize managed timers statisticsTimer = new Timer(); @@ -239,11 +198,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, while (true) { try { StatsRequest req = pendingStatsRequests.take(); - acquireStatistics(req.switchId, req.type, - statisticsTimeout); + acquireStatistics(req.switchId, req.type); } catch (InterruptedException e) { - log - .warn("Flow Statistics Collector thread interrupted"); + log.warn("Flow Statistics Collector thread " + + "interrupted", e); } } } @@ -258,12 +216,60 @@ public class OFStatisticsManager implements IOFStatisticsManager, long switchId = switchPortStatsUpdated.take(); updatePortsTxRate(switchId); } catch (InterruptedException e) { - log.warn("TX Rate Updater thread interrupted"); + log.warn("TX Rate Updater thread interrupted", e); } } } }, "TX Rate Updater"); + } + + /** + * 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 + statisticsTimer.scheduleAtFixedRate(statisticsTimerTask, 0, tickPeriod); + + // Start statistics collector thread + statisticsCollector.start(); + // Start bandwidth utilization computer thread + txRatesUpdater.start(); + + // OSGI console + registerWithOSGIConsole(); + } + + /** + * 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 unsetStatisticsListener(IStatisticsListener s) { + if (s != null) { + this.descriptionListeners.remove(s); + } } private void registerWithOSGIConsole() { @@ -282,6 +288,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, type = t; } + @Override public String toString() { return "SReq = {switchId=" + switchId + ", type=" + type + "}"; } @@ -323,16 +330,22 @@ public class OFStatisticsManager implements IOFStatisticsManager, } private void addStatisticsTicks(Long switchId) { - switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume switch supports Vendor extension stats + switchSupportsVendorExtStats.put(switchId, Boolean.TRUE); // Assume + // switch + // supports + // Vendor + // extension + // stats statisticsTimerTicks.put(switchId, new StatisticsTicks(true)); - log.info("Added Switch {} to target pool", HexString - .toHexString(switchId.longValue())); + log.info("Added Switch {} to target pool", + HexString.toHexString(switchId.longValue())); } protected static class StatisticsTicks { private short flowStatisticsTicks; private short descriptionTicks; private short portStatisticsTicks; + private short tableStatisticsTicks; public StatisticsTicks(boolean scattered) { if (scattered) { @@ -344,15 +357,18 @@ 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; } } public boolean decrementFlowTicksIsZero() { - // Please ensure no code is inserted between the if check and the flowStatisticsTicks reset + // Please ensure no code is inserted between the if check and the + // flowStatisticsTicks reset if (--flowStatisticsTicks == 0) { flowStatisticsTicks = statisticsTickNumber; return true; @@ -361,7 +377,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, } public boolean decrementDescTicksIsZero() { - // Please ensure no code is inserted between the if check and the descriptionTicks reset + // Please ensure no code is inserted between the if check and the + // descriptionTicks reset if (--descriptionTicks == 0) { descriptionTicks = descriptionTickNumber; return true; @@ -370,7 +387,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, } public boolean decrementPortTicksIsZero() { - // Please ensure no code is inserted between the if check and the descriptionTicks reset + // Please ensure no code is inserted between the if check and the + // descriptionTicks reset if (--portStatisticsTicks == 0) { portStatisticsTicks = portTickNumber; return true; @@ -378,20 +396,29 @@ 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( - type - + " stats request not inserted for switch: {}. Queue size: {}. Collector state: {}.", - new Object[] { HexString.toHexString(request.switchId), - pendingStatsRequests.size(), - statisticsCollector.getState().toString() }); + log.info( + "{} 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() { @@ -402,9 +429,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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 a request for this switch is already in the queue, skip to add this new request + 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) && false == pendingStatsRequests.offer(request)) { printInfoMessage("Flow", request); @@ -413,7 +441,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, if (clock.decrementDescTicksIsZero() == true) { request = new StatsRequest(switchId, OFStatisticsType.DESC); - // If a request for this switch is already in the queue, skip to add this new request + // 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("Description", request); @@ -422,19 +451,31 @@ public class OFStatisticsManager implements IOFStatisticsManager, if (clock.decrementPortTicksIsZero() == true) { request = new StatsRequest(switchId, OFStatisticsType.PORT); - // If a request for this switch is already in the queue, skip to add this new request + // 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("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); + } + } } } private void removeStatsRequestTasks(Long switchId) { - log.info("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 + log.info("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 pendingStatsRequests.remove(new StatsRequest(switchId, OFStatisticsType.VENDOR)); pendingStatsRequests.remove(new StatsRequest(switchId, @@ -443,6 +484,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); @@ -452,16 +495,15 @@ public class OFStatisticsManager implements IOFStatisticsManager, statisticsTimerTicks.remove(switchId); removeStatsRequestTasks(switchId); flowStatistics.remove(switchId); - log.info("Statistics removed for switch " - + HexString.toHexString(switchId)); + log.info("Statistics removed for switch {}", + HexString.toHexString(switchId)); } - private void acquireStatistics(Long switchId, OFStatisticsType statType, - long timeout) { + private void acquireStatistics(Long switchId, OFStatisticsType statType) { // Query the switch on all matches List values = this.acquireStatistics(switchId, statType, - null, timeout); + null); // Update local caching database if got a valid response if (values != null && !values.isEmpty()) { @@ -469,48 +511,39 @@ public class OFStatisticsManager implements IOFStatisticsManager, || (statType == OFStatisticsType.VENDOR)) { flowStatistics.put(switchId, values); } else if (statType == OFStatisticsType.DESC) { - if ((switchNamesDB != null) - && switchNamesDB.containsKey(switchId)) { - // Check if user manually configured a name for the switch - for (OFStatistics entry : values) { - OFDescriptionStatistics reply = (OFDescriptionStatistics) entry; - reply.setSerialNumber(switchNamesDB.get(switchId)); - } - } - // check if notification is needed - if (descStatistics.get(switchId) == null - || !(descStatistics.get(switchId).get(0).equals(values - .get(0)))) { - IOFInventoryService inventory = (IOFInventoryService) ServiceHelper - .getInstance(IOFInventoryService.class, - GlobalConstants.DEFAULT.toString(), this); - if (inventory != null) { - // Notify Inventory Service about the name update - Set propSet = new HashSet(1); - Name name = new Name(((OFDescriptionStatistics) values - .get(0)).getSerialNumber()); - propSet.add(name); - inventory.updateSwitchProperty(switchId, propSet); - } - } - // overwrite cache + // 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 + // 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); } } } + private void notifyDescriptionListeners(Long switchId, + List values) { + for (IStatisticsListener l : this.descriptionListeners) { + l.descriptionRefreshed(switchId, + ((OFDescriptionStatistics) values.get(0))); + } + } + /* * Generic function to get the statistics form a OF switch */ @SuppressWarnings("unchecked") private List acquireStatistics(Long switchId, - OFStatisticsType statsType, Object target, long timeout) { + OFStatisticsType statsType, Object target) { List values = null; String type = null; ISwitch sw = controller.getSwitch(switchId); @@ -528,8 +561,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, match.setWildcards(0xffffffff); } else if (!(target instanceof OFMatch)) { // Malformed request - log.warn("Invalid target type for Flow stats request: " - + target.getClass()); + log.warn("Invalid target type for Flow stats request: {}", + target.getClass()); return null; } else { // Specific flow request @@ -569,8 +602,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, targetPort = (short) OFPort.OFPP_NONE.getValue(); } else if (!(target instanceof Short)) { // Malformed request - log.warn("Invalid target type for Port stats request: " - + target.getClass()); + log.warn("Invalid target type for Port stats request: {}", + target.getClass()); return null; } else { // Specific port request @@ -593,6 +626,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 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); @@ -602,14 +649,13 @@ public class OFStatisticsManager implements IOFStatisticsManager, log.warn("Request Timed Out for ({}) from switch {}", type, HexString.toHexString(switchId)); } else if (result instanceof OFError) { - log.warn("Switch {} failed to handle ({}) stats request: " - + Utils.getOFErrorString((OFError) result), HexString - .toHexString(switchId), type); + log.warn("Switch {} failed to handle ({}) stats request: {}", + new Object[] { HexString.toHexString(switchId), type, + Utils.getOFErrorString((OFError) result) }); if (this.switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) { - log - .warn( - "Switching back to regular Flow stats requests for switch {}", - HexString.toHexString(switchId)); + log.warn( + "Switching back to regular Flow stats requests for switch {}", + HexString.toHexString(switchId)); this.switchSupportsVendorExtStats.put(switchId, Boolean.FALSE); } @@ -625,8 +671,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, List list = flowStatistics.get(switchId); /* - * Check on emptiness as interference between add and get is still - * possible on the inner list (the concurrentMap entry's value) + * 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 : (list.get(0) instanceof OFVendorStatistics) ? this @@ -638,8 +684,8 @@ public class OFStatisticsManager implements IOFStatisticsManager, List statsList = flowStatistics.get(switchId); /* - * Check on emptiness as interference between add and get is still - * possible on the inner list (the concurrentMap entry's value) + * Check on emptiness as interference between add and get is still + * possible on the inner list (the concurrentMap entry's value) */ if (statsList == null || statsList.isEmpty()) { return this.dummyList; @@ -647,10 +693,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, if (statsList.get(0) instanceof OFVendorStatistics) { /* - * Caller could provide regular OF match when we - * instead pull the vendor statistics from this node - * Caller is not supposed to know whether this switch supports - * vendor extensions statistics requests + * Caller could provide regular OF match when we instead pull the + * vendor statistics from this node Caller is not supposed to know + * whether this switch supports vendor extensions statistics + * requests */ V6Match targetMatch = (ofMatch instanceof V6Match) ? (V6Match) ofMatch : new V6Match(ofMatch); @@ -706,19 +752,20 @@ public class OFStatisticsManager implements IOFStatisticsManager, 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. + int vendor = data.getInt(); // first 4 bytes is vendor id. if (vendor != V6StatsRequest.NICIRA_VENDOR_ID) { - log - .debug("Unexpected vendor id: 0x{}", Integer - .toHexString(vendor)); + log.warn("Unexpected vendor id: 0x{}", Integer.toHexString(vendor)); return null; } else { - //go ahead by 8 bytes which is 8 bytes of 0 - data.getLong(); //should be all 0's - length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have been consumed + // go ahead by 8 bytes which is 8 bytes of 0 + data.getLong(); // should be all 0's + length -= 12; // 4 bytes Nicira Hdr + 8 bytes from above line have + // been consumed } V6StatsReply v6statsreply; @@ -742,10 +789,10 @@ public class OFStatisticsManager implements IOFStatisticsManager, @Override public List queryStatistics(Long switchId, - OFStatisticsType statType, Object target, long timeout) { + OFStatisticsType statType, Object target) { /* - * Caller does not know and it is not supposed to know whether - * this switch supports vendor extension. We adjust the target for him + * Caller does not know and it is not supposed to know whether this + * switch supports vendor extension. We adjust the target for him */ if (statType == OFStatisticsType.FLOW) { if (switchSupportsVendorExtStats.get(switchId) == Boolean.TRUE) { @@ -754,7 +801,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, } List list = this.acquireStatistics(switchId, statType, - target, timeout); + target); return (list == null) ? null : (statType == OFStatisticsType.VENDOR) ? v6StatsListToOFStatsList(list) @@ -793,13 +840,39 @@ public class OFStatisticsManager implements IOFStatisticsManager, return list; } + @Override + public List getOFTableStatistics(Long switchId) { + if (!tableStatistics.containsKey(switchId)) { + return this.dummyList; + } + + return tableStatistics.get(switchId); + } + + @Override + public List getOFTableStatistics(Long switchId, Byte tableId) { + if (!tableStatistics.containsKey(switchId)) { + return this.dummyList; + } + + 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(); } /* - * InventoryShim replay for us all the switch addition which happened before we were brought up + * InventoryShim replay for us all the switch addition which happened before + * we were brought up */ @Override public void updateNode(Node node, UpdateType type, Set props) { @@ -821,8 +894,9 @@ public class OFStatisticsManager implements IOFStatisticsManager, } /** - * Update the cached port rates for this switch with the latest - * retrieved port transmit byte count + * Update the cached port rates for this switch with the latest retrieved + * port transmit byte count + * * @param switchId */ private synchronized void updatePortsTxRate(long switchId) { @@ -877,17 +951,11 @@ public class OFStatisticsManager implements IOFStatisticsManager, @Override public String getHelp() { StringBuffer help = new StringBuffer(); - help.append("---OF Switch ID to Name Mapping---\n"); - help - .append("\t ofaddname - Add a switchId to name mapping entry\n"); - help - .append("\t ofdeletename - Delete a switchId from the mapping db\n"); - help.append("\t ofprintnames - Print the mapping db\n"); help.append("---OF Statistics Manager utilities---\n"); - help - .append("\t ofdumpstatsmgr - Print Internal Stats Mgr db\n"); - help - .append("\t ofstatstimeout - Change Statistics request's timeout value\n"); + help.append("\t ofdumpstatsmgr - " + + "Print Internal Stats Mgr db\n"); + help.append("\t ofstatsmgrintervals (in seconds) - " + + "Set/Show flow/port/dedscription stats poll intervals\n"); return help.toString(); } @@ -918,43 +986,6 @@ public class OFStatisticsManager implements IOFStatisticsManager, return Long.parseLong(switchString, radix); } - public void _ofaddname(CommandInterpreter ci) { - if (switchNamesDB == null) - switchNamesDB = new HashMap(); - String switchId = ci.nextArgument(); - if (!isValidSwitchId(switchId)) { - ci.println("Please provide a valid SwithcId"); - return; - } - Long sid = getSwitchIDLong(switchId); - String switchName = ci.nextArgument(); - if (switchName == null) { - ci.println("Please provide a valid Switch name"); - return; - } - switchNamesDB.put(sid, switchName); - } - - public void _ofdeletename(CommandInterpreter ci) { - if (switchNamesDB == null) - return; - String switchId = ci.nextArgument(); - if (!isValidSwitchId(switchId)) { - ci.println("Please provide a valid SwitchId"); - return; - } - Long sid = getSwitchIDLong(switchId); - switchNamesDB.remove(sid); - } - - public void _ofprintnames(CommandInterpreter ci) { - if (switchNamesDB == null) - return; - for (Long key : switchNamesDB.keySet()) { - ci.println(key + " -> " + switchNamesDB.get(key) + "\n"); - } - } - /* * Internal information dump code */ @@ -971,9 +1002,7 @@ public class OFStatisticsManager implements IOFStatisticsManager, public void _ofdumpstatsmgr(CommandInterpreter ci) { ci.println("Global Counter: " + counter); - ci - .println("Timer Ticks: " - + prettyPrintSwitchMap(statisticsTimerTicks)); + ci.println("Timer Ticks: " + prettyPrintSwitchMap(statisticsTimerTicks)); ci.println("PendingStatsQueue: " + pendingStatsRequests); ci.println("PendingStatsQueue size: " + pendingStatsRequests.size()); ci.println("Stats Collector alive: " + statisticsCollector.isAlive()); @@ -983,24 +1012,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("Stats request timeout: " + Float.valueOf(statisticsTimeout) - / 1000.0 + " s"); - } - - public void _ofstatstimeout(CommandInterpreter ci) { - String timeoutString = ci.nextArgument(); - if (timeoutString == null || !timeoutString.matches("^[0-9]+$")) { - ci.println("Invalid value. Has to be numeric."); - return; - } - - long newTimeout = Long.valueOf(timeoutString); - if (newTimeout < 50 || newTimeout > 60000) { - ci.println("Invalid value. Valid range is [50-60000]ms"); - return; - } - this.statisticsTimeout = newTimeout; - ci.println("New value: " + statisticsTimeout + " ms"); + ci.println("Table Stats Period: " + tableTickNumber + " s"); } public void _resetSwitchCapability(CommandInterpreter ci) { @@ -1053,11 +1065,9 @@ public class OFStatisticsManager implements IOFStatisticsManager, String averageWindow = ci.nextArgument(); short seconds = 0; if (averageWindow == null) { - ci - .println("Insert the length in seconds of the average window for tx rate"); - ci - .println("Current: " + factoredSamples * portTickNumber - + " secs"); + ci.println("Insert the length in seconds of the median " + + "window for tx rate"); + ci.println("Current: " + factoredSamples * portTickNumber + " secs"); return; } try { @@ -1069,4 +1079,94 @@ public class OFStatisticsManager implements IOFStatisticsManager, ci.println("New: " + factoredSamples * portTickNumber + " secs"); } + public void _ofstatsmgrintervals(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) { + ci.println("Usage: ostatsmgrintervals (in seconds)"); + ci.println("Current Values: fP=" + statisticsTickNumber + "s pP=" + + portTickNumber + "s dP=" + descriptionTickNumber + "s"); + return; + } + 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 || 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 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) { + } + } + } }