/**
* 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.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.internal.IOFSwitchService;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.ver13.OFMeterSerializerVer13;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.protocol.OFFeaturesRequest;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsRequest;
import org.projectfloodlight.openflow.protocol.OFStatsType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.primitives.UnsignedLong;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Base class for server resources related to switches
* @author readams
*
*/
public class SwitchResourceBase extends ServerResource {
protected static Logger log = LoggerFactory.getLogger(SwitchResourceBase.class);
public enum REQUESTTYPE {
OFSTATS,
OFFEATURES
}
@Override
protected void doInit() throws ResourceException {
super.doInit();
}
/**
* Use for requests that originate from the REST server that use their context to get a
* reference to the switch service.
* @param switchId
* @param statType
* @return
*/
@SuppressWarnings("unchecked")
protected List<OFStatsReply> getSwitchStatistics(DatapathId switchId,
OFStatsType statType) {
IOFSwitchService switchService = (IOFSwitchService) getContext().getAttributes().get(IOFSwitchService.class.getCanonicalName());
IOFSwitch sw = switchService.getSwitch(switchId);
ListenableFuture<?> future;
List<OFStatsReply> values = null;
Match match;
if (sw != null) {
OFStatsRequest<?> req = null;
switch (statType) {
case FLOW:
match = sw.getOFFactory().buildMatch().build();
req = sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) == 0 ?
sw.getOFFactory().buildFlowStatsRequest()
.setMatch(match)
.setOutPort(OFPort.ANY)
.setTableId(TableId.ALL)
.build() :
sw.getOFFactory().buildFlowStatsRequest()
.setMatch(match)
.setOutPort(OFPort.ANY)
.setTableId(TableId.ALL)
.setOutGroup(OFGroup.ANY)
.build();
break;
case AGGREGATE:
match = sw.getOFFactory().buildMatch().build();
req = sw.getOFFactory().buildAggregateStatsRequest()
.setMatch(match)
.setOutPort(OFPort.ANY)
.setTableId(TableId.ALL)
.build();
break;
case PORT:
req = sw.getOFFactory().buildPortStatsRequest()
.setPortNo(OFPort.ANY)
.build();
break;
case QUEUE:
req = sw.getOFFactory().buildQueueStatsRequest()
.setPortNo(OFPort.ANY)
.setQueueId(UnsignedLong.MAX_VALUE.longValue())
.build();
break;
case DESC:
// pass - nothing todo besides set the type above
req = sw.getOFFactory().buildDescStatsRequest()
.build();
break;
case GROUP:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
req = sw.getOFFactory().buildGroupStatsRequest()
.build();
}
break;
case METER:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
req = sw.getOFFactory().buildMeterStatsRequest()
.setMeterId(OFMeterSerializerVer13.ALL_VAL)
.build();
}
break;
case GROUP_DESC:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
req = sw.getOFFactory().buildGroupDescStatsRequest()
.build();
}
break;
case GROUP_FEATURES:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
req = sw.getOFFactory().buildGroupFeaturesStatsRequest()
.build();
}
break;
case METER_CONFIG:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
req = sw.getOFFactory().buildMeterConfigStatsRequest()
.setMeterId(0xffFFffFF)
.build();
}
break;
case METER_FEATURES:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
req = sw.getOFFactory().buildMeterFeaturesStatsRequest()
.build();
}
break;
case TABLE:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
req = sw.getOFFactory().buildTableStatsRequest()
.build();
}
break;
case TABLE_FEATURES:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_10) > 0) {
req = sw.getOFFactory().buildTableFeaturesStatsRequest()
.build();
}
break;
case PORT_DESC:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) {
req = sw.getOFFactory().buildPortDescStatsRequest()
.build();
}
break;
case EXPERIMENTER:
log.error("Stats Request Type {} not implemented yet", statType.name());
break;
case BUNDLE_FEATURES:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_15) >= 0) {
req = sw.getOFFactory().buildBundleFeaturesStatsRequest()
.build();
}
break;
case CONTROLLER_STATUS:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_15) >= 0) {
req = sw.getOFFactory().buildControllerStatusStatsRequest()
.build();
}
break;
case FLOW_LIGHTWEIGHT:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_15) >= 0) {
match = sw.getOFFactory().buildMatch().build();
req = sw.getOFFactory().buildFlowLightweightStatsRequest()
.setMatch(match)
.setOutPort(OFPort.ANY)
.setTableId(TableId.ALL)
.build();
}
break;
case FLOW_MONITOR:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_14) >= 0) {
req = sw.getOFFactory().buildFlowMonitorRequest()
.build();
}
break;
case QUEUE_DESC:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_14) >= 0) {
req = sw.getOFFactory().buildQueueDescStatsRequest()
.setPortNo(OFPort.ANY)
.setQueueId(0xffFFffFF) /* all queues */
.build();
}
break;
case TABLE_DESC:
if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_14) >= 0) {
req = sw.getOFFactory().buildTableDescStatsRequest()
.build();
}
break;
/* omit a default so we will know (via warning) if we miss one in the future */
}
try {
if (req != null) {
future = sw.writeStatsRequest(req);
values = (List<OFStatsReply>) future.get(10, TimeUnit.SECONDS);
}
} catch (Exception e) {
log.error("Failure retrieving statistics from switch " + sw, e);
}
}
return values;
}
protected List<OFStatsReply> getSwitchStatistics(String switchId, OFStatsType statType) {
return getSwitchStatistics(DatapathId.of(switchId), statType);
}
protected OFFeaturesReply getSwitchFeaturesReply(DatapathId switchId) {
IOFSwitchService switchService =
(IOFSwitchService) getContext().getAttributes().
get(IOFSwitchService.class.getCanonicalName());
IOFSwitch sw = switchService.getSwitch(switchId);
Future<OFFeaturesReply> future;
OFFeaturesReply featuresReply = null;
OFFeaturesRequest featuresRequest = sw.getOFFactory().buildFeaturesRequest().build();
if (sw != null) {
try {
future = sw.writeRequest(featuresRequest);
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(DatapathId.of(switchId));
}
}