| /** |
| * 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.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.Future; |
| import java.util.concurrent.TimeUnit; |
| |
| import net.floodlightcontroller.core.IFloodlightProviderService; |
| import net.floodlightcontroller.core.IOFSwitch; |
| import net.floodlightcontroller.core.annotations.LogMessageDoc; |
| import net.onrc.onos.core.drivermanager.OFSwitchImplCPqD13; |
| |
| import org.projectfloodlight.openflow.protocol.OFFeaturesReply; |
| import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; |
| import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry; |
| import org.projectfloodlight.openflow.protocol.OFGroupDescStatsReply; |
| import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry; |
| import org.projectfloodlight.openflow.protocol.OFGroupStatsReply; |
| import org.projectfloodlight.openflow.protocol.OFMatchV3; |
| import org.projectfloodlight.openflow.protocol.OFOxmList; |
| import org.projectfloodlight.openflow.protocol.OFPortStatsEntry; |
| import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; |
| import org.projectfloodlight.openflow.protocol.OFPortStatsReply; |
| import org.projectfloodlight.openflow.protocol.OFPortStatsRequest; |
| import org.projectfloodlight.openflow.protocol.OFStatsReply; |
| import org.projectfloodlight.openflow.protocol.OFStatsRequest; |
| import org.projectfloodlight.openflow.protocol.OFStatsType; |
| import org.projectfloodlight.openflow.types.OFPort; |
| import org.projectfloodlight.openflow.types.TableId; |
| import org.projectfloodlight.openflow.util.HexString; |
| import org.restlet.resource.ResourceException; |
| import org.restlet.resource.ServerResource; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Base class for server resources related to switches |
| * |
| * @author readams |
| */ |
| |
| public class SwitchResourceBase extends ServerResource { |
| protected final static Logger log = LoggerFactory.getLogger(SwitchResourceBase.class); |
| |
| public enum REQUESTTYPE { |
| OFSTATS, |
| OFFEATURES |
| } |
| |
| @Override |
| protected void doInit() throws ResourceException { |
| super.doInit(); |
| |
| } |
| |
| @LogMessageDoc(level = "ERROR", |
| message = "Failure retrieving statistics from switch {switch}", |
| explanation = "An error occurred while retrieving statistics" + |
| "from the switch", |
| recommendation = LogMessageDoc.CHECK_SWITCH + " " + |
| LogMessageDoc.GENERIC_ACTION) |
| |
| protected List<?> getSwitchStatistics(long switchId, |
| OFStatsType statType) { |
| IFloodlightProviderService floodlightProvider = |
| (IFloodlightProviderService) getContext().getAttributes(). |
| get(IFloodlightProviderService.class.getCanonicalName()); |
| |
| IOFSwitch sw = floodlightProvider.getSwitches().get(switchId); |
| Future<List<OFStatsReply>> future; |
| List<OFStatsReply> values = null; |
| if (sw != null) { |
| OFStatsRequest<?> req = null; |
| if (statType == OFStatsType.FLOW) { |
| log.debug("Switch Flow Stats req sent for switch {}", |
| sw.getStringId()); |
| OFMatchV3 match = sw.getFactory().buildMatchV3() |
| .setOxmList(OFOxmList.EMPTY).build(); |
| req = sw.getFactory() |
| .buildFlowStatsRequest() |
| .setMatch(match) |
| .setOutPort(OFPort.ANY) |
| .setTableId(TableId.ALL) |
| .setXid(sw.getNextTransactionId()).build(); |
| List<OFFlowStatsEntryMod> flowStats = new ArrayList<OFFlowStatsEntryMod>(); |
| try { |
| future = sw.getStatistics(req); |
| values = future.get(10, TimeUnit.SECONDS); |
| for (OFFlowStatsEntry entry : ((OFFlowStatsReply)values.get(0)).getEntries()) { |
| OFFlowStatsEntryMod entryMod = new OFFlowStatsEntryMod(entry); |
| flowStats.add(entryMod); |
| } |
| log.debug("Switch flow Stats Entries from switch {} are {}", |
| sw.getStringId(), flowStats); |
| } catch (Exception e) { |
| log.error("Failure retrieving statistics from switch " + sw, e); |
| } |
| return flowStats; |
| } |
| else if (statType == OFStatsType.PORT){ |
| log.debug("Switch Port Stats: req sent for all " |
| + "ports in switch {}", sw.getStringId()); |
| List<OFPortStatsEntryMod> portStats = null; |
| req = sw.getFactory() |
| .buildPortStatsRequest() |
| .setPortNo(OFPort.ANY).setXid |
| (sw.getNextTransactionId()).build(); |
| try { |
| future = sw.getStatistics(req); |
| values = future.get(10, TimeUnit.SECONDS); |
| portStats = new ArrayList<OFPortStatsEntryMod>(); |
| for (OFPortStatsEntry entry : ((OFPortStatsReply)values.get(0)).getEntries()) { |
| OFPortStatsEntryMod entryMod = new OFPortStatsEntryMod(entry); |
| portStats.add(entryMod); |
| } |
| log.debug("Switch Port Stats Entries from switch {} are {}", |
| sw.getStringId(), portStats); |
| } catch (Exception e) { |
| log.error("Failure retrieving statistics from switch " + sw, e); |
| } |
| return portStats; |
| } |
| else if (statType == OFStatsType.GROUP){ |
| log.debug("Switch Group Stats: req sent for all " |
| + "ports in switch {}", sw.getStringId()); |
| req = sw.getFactory().buildGroupStatsRequest().setXid |
| (sw.getNextTransactionId()).build(); |
| List<OFGroupStatsEntryMod> groupStats = new ArrayList<OFGroupStatsEntryMod>(); |
| try { |
| future = sw.getStatistics(req); |
| values = future.get(10, TimeUnit.SECONDS); |
| for (OFGroupStatsEntry entry : ((OFGroupStatsReply)values.get(0)).getEntries()) { |
| OFGroupStatsEntryMod entryMod = new OFGroupStatsEntryMod(entry); |
| groupStats.add(entryMod); |
| } |
| log.debug("Switch Group Stats Entries from switch {} are {}", |
| sw.getStringId(), groupStats); |
| } catch (Exception e) { |
| log.error("Failure retrieving statistics from switch " + sw, e); |
| } |
| return groupStats; |
| } |
| else if (statType == OFStatsType.GROUP_DESC){ |
| log.debug("Switch Group Desc Stats: req sent for all " |
| + "ports in switch {}", sw.getStringId()); |
| List<OFGroupDescStatsEntryMod> GroupDescStats= new ArrayList<OFGroupDescStatsEntryMod>(); |
| req = sw.getFactory().buildGroupDescStatsRequest().setXid |
| (sw.getNextTransactionId()).build(); |
| try { |
| future = sw.getStatistics(req); |
| values = future.get(10, TimeUnit.SECONDS); |
| for (OFGroupDescStatsEntry entry : ((OFGroupDescStatsReply)values.get(0)).getEntries()) { |
| OFGroupDescStatsEntryMod entryMod = new OFGroupDescStatsEntryMod(entry); |
| GroupDescStats.add(entryMod); |
| } |
| log.debug("Switch Group_Desc Stats Entries from switch {} are {}", |
| sw.getStringId(), GroupDescStats); |
| } catch (Exception e) { |
| log.error("Failure retrieving statistics from switch " + sw, e); |
| } |
| return GroupDescStats; |
| } |
| /*else if (statType == OFStatisticsType.AGGREGATE) { |
| OFAggregateStatisticsRequest specificReq = new OFAggregateStatisticsRequest(); |
| OFMatch match = new OFMatch(); |
| match.setWildcards(0xffffffff); |
| specificReq.setMatch(match); |
| specificReq.setOutPort(OFPort.OFPP_NONE.getValue()); |
| specificReq.setTableId((byte) 0xff); |
| req.setStatistics(Collections.singletonList((OFStatistics) specificReq)); |
| requestLength += specificReq.getLength(); |
| } /*else if (statType == OFStatisticsType.QUEUE) { |
| OFQueueStatisticsRequest specificReq = new OFQueueStatisticsRequest(); |
| specificReq.setPortNumber(OFPort.OFPP_ALL.getValue()); |
| // LOOK! openflowj does not define OFPQ_ALL! pulled this from openflow.h |
| // note that I haven't seen this work yet though... |
| specificReq.setQueueId(0xffffffff); |
| req.setStatistics(Collections.singletonList((OFStatistics) specificReq)); |
| requestLength += specificReq.getLength(); |
| } else if (statType == OFStatisticsType.DESC || |
| statType == OFStatisticsType.TABLE) { |
| // pass - nothing todo besides set the type above |
| }*/ |
| // XXX S fix when we fix stats |
| try { |
| future = sw.getStatistics(req); |
| values = future.get(10, TimeUnit.SECONDS); |
| } catch (Exception e) { |
| log.error("Failure retrieving statistics from switch " + sw, e); |
| } |
| } |
| return values; |
| } |
| |
| protected Object getSwitchStatistics(String switchId, OFStatsType statType) { |
| return getSwitchStatistics(HexString.toLong(switchId), statType); |
| } |
| //TODO: Java doc |
| protected List<?> getSwitchStatisticsForTable(long switchId, |
| OFStatsType statType, String tableType) { |
| IFloodlightProviderService floodlightProvider = |
| (IFloodlightProviderService) getContext().getAttributes(). |
| get(IFloodlightProviderService.class.getCanonicalName()); |
| IOFSwitch sw = floodlightProvider.getSwitches().get(switchId); |
| Future<List<OFStatsReply>> future; |
| List<OFStatsReply> values = null; |
| //getting tableId from CPqD driver |
| TableId tableId; |
| if (sw != null) { |
| if((tableId = ((OFSwitchImplCPqD13) sw).getTableId(tableType)) == null){ |
| log.error("Invalid tableType {} " + tableType); |
| return null; |
| } |
| OFStatsRequest<?> req = null; |
| if (statType == OFStatsType.FLOW) { |
| log.debug("Switch Flow Stats req for table {} sent to switch {}", |
| tableType,sw.getStringId()); |
| OFMatchV3 match = sw.getFactory().buildMatchV3() |
| .setOxmList(OFOxmList.EMPTY).build(); |
| req = sw.getFactory() |
| .buildFlowStatsRequest() |
| .setMatch(match) |
| .setOutPort(OFPort.ANY) |
| .setTableId(tableId) |
| .setXid(sw.getNextTransactionId()).build(); |
| List<OFFlowStatsEntryMod> flowStats = new ArrayList<OFFlowStatsEntryMod>(); |
| try { |
| future = sw.getStatistics(req); |
| values = future.get(10, TimeUnit.SECONDS); |
| for (OFFlowStatsEntry entry : ((OFFlowStatsReply)values.get(0)).getEntries()) { |
| OFFlowStatsEntryMod entryMod = new OFFlowStatsEntryMod(entry); |
| flowStats.add(entryMod); |
| } |
| log.debug("Switch flow Stats Entries for table {} from switch {} are {}", |
| tableType, sw.getStringId(), flowStats); |
| } catch (Exception e) { |
| log.error("Failure retrieving per table statistics from switch " + sw, e); |
| } |
| return flowStats; |
| } |
| } |
| //should never get to this point |
| log.error("Failure retrieving {} table statistics from switch {}",tableType, sw); |
| return null; |
| } |
| |
| protected OFFeaturesReply getSwitchFeaturesReply(long switchId) { |
| IFloodlightProviderService floodlightProvider = |
| (IFloodlightProviderService) getContext().getAttributes(). |
| get(IFloodlightProviderService.class.getCanonicalName()); |
| |
| IOFSwitch sw = floodlightProvider.getSwitches().get(switchId); |
| //uture<OFFeaturesReply> future; |
| OFFeaturesReply featuresReply = null; |
| if (sw != null) { |
| // XXX S fix when we fix stats |
| try { |
| //future = sw.getFeaturesReplyFromSwitch(); |
| //featuresReply = future.get(10, TimeUnit.SECONDS); |
| } catch (Exception e) { |
| log.error("Failure getting features reply from switch" + sw, e); |
| } |
| } |
| |
| return featuresReply; |
| } |
| |
| protected OFFeaturesReply getSwitchFeaturesReply(String switchId) { |
| return getSwitchFeaturesReply(HexString.toLong(switchId)); |
| } |
| |
| } |