| /** |
| * Copyright 2011, Big Switch Networks, Inc. |
| * Originally created by David Erickson, Stanford University |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may |
| * not use this file except in compliance with the License. You may obtain |
| * a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| **/ |
| |
| package net.floodlightcontroller.core.web; |
| |
| import java.lang.Thread.State; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import net.floodlightcontroller.core.IFloodlightProviderService; |
| import org.openflow.protocol.OFFeaturesReply; |
| import org.openflow.protocol.statistics.OFStatistics; |
| import org.openflow.protocol.statistics.OFStatisticsType; |
| import org.openflow.util.HexString; |
| import org.restlet.resource.Get; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Return switch statistics information for all switches |
| * @author readams |
| */ |
| public class AllSwitchStatisticsResource extends SwitchResourceBase { |
| protected final static Logger log = |
| LoggerFactory.getLogger(AllSwitchStatisticsResource.class); |
| |
| @Get("json") |
| public Map<String, Object> retrieve() { |
| String statType = (String) getRequestAttributes().get("statType"); |
| return retrieveInternal(statType); |
| } |
| |
| public Map<String, Object> retrieveInternal(String statType) { |
| HashMap<String, Object> model = new HashMap<String, Object>(); |
| |
| OFStatisticsType type = null; |
| REQUESTTYPE rType = null; |
| |
| if (statType.equals("port")) { |
| type = OFStatisticsType.PORT; |
| rType = REQUESTTYPE.OFSTATS; |
| } else if (statType.equals("queue")) { |
| type = OFStatisticsType.QUEUE; |
| rType = REQUESTTYPE.OFSTATS; |
| } else if (statType.equals("flow")) { |
| type = OFStatisticsType.FLOW; |
| rType = REQUESTTYPE.OFSTATS; |
| } else if (statType.equals("aggregate")) { |
| type = OFStatisticsType.AGGREGATE; |
| rType = REQUESTTYPE.OFSTATS; |
| } else if (statType.equals("desc")) { |
| type = OFStatisticsType.DESC; |
| rType = REQUESTTYPE.OFSTATS; |
| } else if (statType.equals("table")) { |
| type = OFStatisticsType.TABLE; |
| rType = REQUESTTYPE.OFSTATS; |
| } else if (statType.equals("features")) { |
| rType = REQUESTTYPE.OFFEATURES; |
| } else { |
| return model; |
| } |
| |
| IFloodlightProviderService floodlightProvider = |
| (IFloodlightProviderService)getContext().getAttributes(). |
| get(IFloodlightProviderService.class.getCanonicalName()); |
| Long[] switchDpids = floodlightProvider.getSwitches().keySet().toArray(new Long[0]); |
| List<GetConcurrentStatsThread> activeThreads = new ArrayList<GetConcurrentStatsThread>(switchDpids.length); |
| List<GetConcurrentStatsThread> pendingRemovalThreads = new ArrayList<GetConcurrentStatsThread>(); |
| GetConcurrentStatsThread t; |
| for (Long l : switchDpids) { |
| t = new GetConcurrentStatsThread(l, rType, type); |
| activeThreads.add(t); |
| t.start(); |
| } |
| |
| // Join all the threads after the timeout. Set a hard timeout |
| // of 12 seconds for the threads to finish. If the thread has not |
| // finished the switch has not replied yet and therefore we won't |
| // add the switch's stats to the reply. |
| for (int iSleepCycles = 0; iSleepCycles < 12; iSleepCycles++) { |
| for (GetConcurrentStatsThread curThread : activeThreads) { |
| if (curThread.getState() == State.TERMINATED) { |
| if (rType == REQUESTTYPE.OFSTATS) { |
| model.put(HexString.toHexString(curThread.getSwitchId()), curThread.getStatisticsReply()); |
| } else if (rType == REQUESTTYPE.OFFEATURES) { |
| model.put(HexString.toHexString(curThread.getSwitchId()), curThread.getFeaturesReply()); |
| } |
| pendingRemovalThreads.add(curThread); |
| } |
| } |
| |
| // remove the threads that have completed the queries to the switches |
| for (GetConcurrentStatsThread curThread : pendingRemovalThreads) { |
| activeThreads.remove(curThread); |
| } |
| // clear the list so we don't try to double remove them |
| pendingRemovalThreads.clear(); |
| |
| // if we are done finish early so we don't always get the worst case |
| if (activeThreads.isEmpty()) { |
| break; |
| } |
| |
| // sleep for 1 s here |
| try { |
| Thread.sleep(1000); |
| } catch (InterruptedException e) { |
| log.error("Interrupted while waiting for statistics", e); |
| } |
| } |
| |
| return model; |
| } |
| |
| protected class GetConcurrentStatsThread extends Thread { |
| private List<OFStatistics> switchReply; |
| private long switchId; |
| private OFStatisticsType statType; |
| private REQUESTTYPE requestType; |
| private OFFeaturesReply featuresReply; |
| |
| public GetConcurrentStatsThread(long switchId, REQUESTTYPE requestType, OFStatisticsType statType) { |
| this.switchId = switchId; |
| this.requestType = requestType; |
| this.statType = statType; |
| this.switchReply = null; |
| this.featuresReply = null; |
| } |
| |
| public List<OFStatistics> getStatisticsReply() { |
| return switchReply; |
| } |
| |
| public OFFeaturesReply getFeaturesReply() { |
| return featuresReply; |
| } |
| |
| public long getSwitchId() { |
| return switchId; |
| } |
| |
| public void run() { |
| if ((requestType == REQUESTTYPE.OFSTATS) && (statType != null)) { |
| switchReply = getSwitchStatistics(switchId, statType); |
| } else if (requestType == REQUESTTYPE.OFFEATURES) { |
| featuresReply = getSwitchFeaturesReply(switchId); |
| } |
| } |
| } |
| } |