--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+ <artifactId>protocol_plugins.openflow_netty</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.opendaylight.controller.sal.packet,
+ org.opendaylight.controller.sal.action,
+ org.opendaylight.controller.sal.connection,
+ org.opendaylight.controller.sal.discovery,
+ org.opendaylight.controller.sal.topology,
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.sal.flowprogrammer,
+ org.opendaylight.controller.sal.reader,
+ org.opendaylight.controller.sal.inventory,
+ org.opendaylight.controller.sal.match,
+ org.opendaylight.controller.sal.utils,
+ org.apache.commons.lang3.builder,
+ org.apache.commons.lang3.tuple,
+ org.apache.felix.dm,
+ org.slf4j,
+ org.eclipse.osgi.framework.console,
+ org.osgi.framework,
+ javax.net.ssl,
+ org.jboss.netty.*
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.controller.protocol_plugin.openflow.core.internal;-split-package:=merge-first,
+ org.opendaylight.controller.protocol_plugin.openflow.core;-split-package:=merge-first,
+ </Export-Package>
+ <Embed-Dependency>
+ org.openflow.openflowj_netty,org.jboss.netty;protocol_plugins.openflow;type=!pom;inline=false
+ </Embed-Dependency>
+ <Embed-Transitive>
+ false
+ </Embed-Transitive>
+ <Bundle-Activator>
+ org.opendaylight.controller.protocol_plugin.openflow.internal.EnhancedActivator
+ </Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.connection</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ </dependency>
+ <!-- Make sure this comes before protocol_plugins.openflow Maven
+ honors the classpath order to reliable builds and here we
+ want to make sure that the openflowJ embedded is picking the
+ netty one over the non-netty enabled-->
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>org.openflow.openflowj_netty</artifactId>
+ <version>1.0.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>protocol_plugins.openflow</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.netty</groupId>
+ <artifactId>netty</artifactId>
+ <version>3.2.6.Final</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.protocol_plugin.openflow.core;
+
+import java.net.SocketAddress;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFStatisticsRequest;
+
+/**
+ * This interface defines an abstraction of an Open Flow Switch.
+ *
+ */
+public interface IEnhancedSwitch extends ISwitch {
+ public void startHandler();
+
+ public void shutDownHandler();
+
+ public void handleMessage(OFMessage ofMessage);
+
+ public void flushBufferedMessages();
+
+ public SocketAddress getRemoteAddress();
+
+ public SocketAddress getLocalAddress();
+}
--- /dev/null
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.RejectedExecutionException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SocketChannel;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictorFactory;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.jboss.netty.handler.execution.ExecutionHandler;
+import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
+import org.jboss.netty.handler.timeout.IdleStateAwareChannelUpstreamHandler;
+import org.jboss.netty.handler.timeout.IdleStateEvent;
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.ObjectSizeEstimator;
+import org.jboss.netty.handler.timeout.ReadTimeoutException;
+
+
+
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.MessageParseException;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IEnhancedSwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
+import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitchStateListener;
+import org.opendaylight.controller.sal.connection.ConnectionConstants;
+import org.opendaylight.controller.sal.connection.IPluginInConnectionService;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+//import org.opendaylight.controller.protocol_plugin.openflow.core.internal.OFChannelState.HandshakeState;
+//import org.openflow.protocol.OFType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+
+public class EnhancedController implements IController, IPluginInConnectionService {
+
+
+ protected BasicFactory factory;
+
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(EnhancedController.class);
+
+
+ // Track connected switches via SwitchID
+ private ConcurrentHashMap<Long, ISwitch> connectedSwitches;
+
+ // Track connected switches via ChannelID. Whenever the message
+ private ConcurrentHashMap<Integer, IEnhancedSwitch> channelIDToSwitchMap;
+
+ // only 1 message listener per OFType
+ private ConcurrentMap<OFType, IMessageListener> messageListeners;
+
+ // only 1 switch state listener
+ private ISwitchStateListener switchStateListener;
+ private AtomicInteger switchInstanceNumber;
+
+
+ private OFChannelHandler ofChannelHandler = null;
+ private ControllerServerBootstrap bootstrap = null;
+
+ private ThreadPoolExecutor execHandler = null;
+
+ private static final int SEND_BUFFER_SIZE = 1 * 1024 * 1024;
+ private static final int RECEIVE_BUFFER_SIZE = 1 * 1024 * 1024;
+ private static final int WRITE_BUFFER_LOW_WATERMARK = 32 * 1024;
+ private static final int WRITE_BUFFER_HIGH_WATERMARK = 64 * 1024;
+ private static final String CONTROLLER_HOST = null;
+ private static final int CONTROLLER_PORT = 6633;
+
+ private static final int OMATPE_CORE_POOL_SIZE = 200;
+ private static final int OMATPE_PER_CHANNEL_SIZE = 2 * 1048576;
+ private static final int OMATPE_POOL_WIDE_SIZE = 0; //1073741824;
+ private static final int OMATPE_THREAD_KEEP_ALIVE_IN_MILLISECONDS = 100;
+ private static final int EXPERIMENTAL_OMATPE_OBJECT_SIZE = 1000; // bytes
+
+ private HashedWheelTimer hashedWheelTimer = null;
+
+ // This executor would be used by individual switches to handle
+ // cases like Stats Request/Response or Sync* methods which sends request and
+ // waits via Future for responses. Please note that threads in this
+ // pool are shared across multiple threads. So, if all threads are busy,
+ // Socket IO thread would get blocked creating sharp decline in performance
+ // If possible TOTALLY avoid any thread usage which does network level
+ // request / response by making a thread in this pool wait for response
+ // Consider storing the Future reference against the "sent" request and
+ // fire-event to wake-up the same when response is received rather than making the
+ // sender thread getting into a "wait" mode. That would never scale
+ private ExecutorService executorService = null;
+
+ // IMPORTANT: DO NOT REDUCE THIS THREAD COUNT TO 0
+ // THIS THREAD COUNT WOULD BE USED FOR SOCKET-IO + FOLLOWING EXECUTION CHAIN
+ // Plugin + SAL + North-to-SAL + Egress (flow_provisioning)
+ private static final int WORKER_THREAD_COUNT = 4;
+
+ // This is a handy thread-pool if WORKER_THREAD_COUNT is not able to cope with
+ // Socket IO + Execution of the following handling chain
+ // Plugin + SAL + North-to-SAL + Egress (flow_provisioning)
+ private static final int EXECUTION_HANDLER_THREAD_POOL_SIZE = 0;
+
+ // This is the thread-pool which can be optionally used for
+ // building synchronous semantics for flow_mod and stats handling cycle
+ // Flow_Mod in synchronous model could involve FLOW_MOD + BARRIER_MSG
+ // sending and receiving with wait timeout for reply
+ // Stats handling in synchronous model could involve STATS_REQUEST + STATS_REPLY
+ // sending and receiving with wait timeout for reply
+ private static final int THREAD_POOL_SIZE_FOR_EGRESS_SYNC_MSGS = 30;
+
+ private TrafficStatisticsHandler statsHandler = null;
+
+ // Lock for locking messagelisteners list while escalating the switch
+ // messages
+ private ReentrantLock lock = new ReentrantLock();
+
+ private static final int FLUSH_BATCH_SIZE = 100;
+
+ //****************** IController Interafce Methods Begin ******************
+
+ @Override
+ public void addMessageListener(OFType type, IMessageListener listener) {
+ IMessageListener currentListener = this.messageListeners.get(type);
+ if (currentListener != null) {
+ logger.warn("{} is already listened by {}", type.toString(),
+ currentListener.toString());
+ }
+ this.messageListeners.put(type, listener);
+ logger.debug("{} is now listened by {}", type.toString(),
+ listener.toString());
+
+ }
+
+ @Override
+ public void removeMessageListener(OFType type, IMessageListener listener) {
+ IMessageListener currentListener = this.messageListeners.get(type);
+ if ((currentListener != null) && (currentListener == listener)) {
+ logger.debug("{} listener {} is Removed", type.toString(),
+ listener.toString());
+ this.messageListeners.remove(type);
+ }
+
+ }
+
+ @Override
+ public void addSwitchStateListener(ISwitchStateListener listener) {
+ if (this.switchStateListener != null) {
+ logger.warn("Switch events are already listened by {}",
+ this.switchStateListener.toString());
+ }
+ this.switchStateListener = listener;
+ logger.debug("Switch events are now listened by {}",
+ listener.toString());
+
+ }
+
+ @Override
+ public void removeSwitchStateListener(ISwitchStateListener listener) {
+ if ((this.switchStateListener != null)
+ && (this.switchStateListener == listener)) {
+ logger.debug("SwitchStateListener {} is Removed",
+ listener.toString());
+ this.switchStateListener = null;
+ }
+
+ }
+
+ @Override
+ public Map<Long, ISwitch> getSwitches() {
+ return this.connectedSwitches;
+ }
+
+ @Override
+ public ISwitch getSwitch(Long switchId) {
+ return this.connectedSwitches.get(switchId);
+ }
+
+ //****************** IController Interafce Methods End ******************
+
+
+
+ //****************** Dependency-manager callbacks Begin ******************
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ public void init() {
+ logger.debug("Initializing!");
+ this.connectedSwitches = new ConcurrentHashMap<Long, ISwitch>();
+ this.channelIDToSwitchMap = new ConcurrentHashMap<Integer, IEnhancedSwitch>();
+ this.messageListeners = new ConcurrentHashMap<OFType, IMessageListener>();
+ this.switchStateListener = null;
+ this.hashedWheelTimer = new HashedWheelTimer();
+ this.statsHandler = new TrafficStatisticsHandler(hashedWheelTimer);
+ this.switchInstanceNumber = new AtomicInteger(0);
+ this.factory = new BasicFactory();
+ this.bootstrap = new ControllerServerBootstrap(this);
+ this.executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE_FOR_EGRESS_SYNC_MSGS);
+
+
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called and after
+ * the services provided by the class are registered in the service registry
+ *
+ */
+ public void start() {
+ this.statsHandler.init();
+ logger.debug("Starting!");
+ bootstrap.startServer(WORKER_THREAD_COUNT,
+ CONTROLLER_HOST,
+ CONTROLLER_PORT,
+ ofChannelHandler);
+
+
+ }
+
+ /**
+ * Function called by the dependency manager before the services exported by
+ * the component are unregistered, this will be followed by a "destroy ()"
+ * calls
+ *
+ */
+ public void stop() {
+ for (Iterator<Entry<Integer, IEnhancedSwitch>> it = channelIDToSwitchMap.entrySet().iterator(); it
+ .hasNext();) {
+ Entry<Integer, IEnhancedSwitch> entry = it.next();
+ ((EnhancedSwitchHandler) entry.getValue()).stop();
+ }
+
+ hashedWheelTimer.stop();
+
+ executorService.shutdown();
+ }
+
+ /**
+ * 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.
+ *
+ */
+ public void destroy() {
+ }
+ //****************** Dependency-manager callbacks End ******************
+
+
+
+ public OFChannelHandler getChannelHandler(){
+ return new OFChannelHandler(this);
+ }
+
+
+ protected class OFChannelHandler extends IdleStateAwareChannelUpstreamHandler{
+
+
+ protected EnhancedController controller = null;
+ protected Channel channel = null;
+
+
+ public OFChannelHandler(EnhancedController controller){
+ this.controller = controller;
+ }
+
+
+ @Override
+ public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
+ throws Exception {
+ List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+ msglist.add(factory.getMessage(OFType.ECHO_REQUEST));
+ e.getChannel().write(msglist);
+ statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REQUEST_SENT);
+ }
+
+ @Override
+ public void channelConnected(ChannelHandlerContext ctx,
+ ChannelStateEvent e) throws Exception {
+ channel = e.getChannel();
+ logger.info("New switch connection from {}",
+ channel.getRemoteAddress());
+
+ Integer channelID = e.getChannel().getId();
+
+ IEnhancedSwitch switchHandler = new EnhancedSwitchHandler(controller,
+ channelID, channel, hashedWheelTimer, executorService, statsHandler);
+ switchHandler.startHandler();
+ channelIDToSwitchMap.put(channelID, switchHandler);
+ statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONNECTED_SWITCHES);
+
+ }
+
+ @Override
+ public void channelDisconnected(ChannelHandlerContext ctx,
+ ChannelStateEvent e) throws Exception {
+ // when SwitchHandler.shutDownHandler is called, Controller would
+ // get the feedback via switchDeleted method. So that both SwitchHandler and
+ // controller both release resources of the switch concerned
+
+ Integer channelID = e.getChannel().getId();
+ IEnhancedSwitch switchHandler = channelIDToSwitchMap.get(channelID);
+ if (switchHandler != null){
+ switchHandler.shutDownHandler();
+ }
+ statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.DISCONNECTED_SWITCHES);
+
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
+ throws Exception {
+
+ EnhancedSwitchHandler sw = null;
+
+ if (e.getCause() instanceof ReadTimeoutException) {
+ // switch timeout
+ logger.error("Disconnecting switch {} due to read timeout",
+ e.getChannel().getId(), e.getCause().getMessage());
+ ctx.getChannel().close();
+ sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+ sw.stop();
+ /*
+ } else if (e.getCause() instanceof HandshakeTimeoutException) {
+ logger.error("Disconnecting switch {}: failed to complete handshake",
+ e.getChannel().getId());
+ ctx.getChannel().close();
+ channelIDToSwitchMap.remove(e.getChannel().getId());
+ */
+ } else if (e.getCause() instanceof ClosedChannelException) {
+ logger.warn("Channel for sw {} already closed Error : {}",
+ e.getChannel().getId(), e.getCause().getMessage());
+ ctx.getChannel().close();
+ sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+ sw.stop();
+ } else if (e.getCause() instanceof IOException) {
+ logger.error("Disconnecting switch {} due to IO Error: {}",
+ e.getChannel().getId(), e.getCause().getMessage());
+ ctx.getChannel().close();
+ sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+ sw.stop();
+ /*
+ } else if (e.getCause() instanceof SwitchStateException) {
+ logger.error("Disconnecting switch {} due to switch state error: {}",
+ e.getChannel().getId(), e.getCause().getMessage());
+ ctx.getChannel().close();
+ channelIDToSwitchMap.remove(e.getChannel().getId());
+
+ } else if (e.getCause() instanceof MessageParseException) {
+ logger.error("Disconnecting switch {} due to message parse error Error : {}",
+ e.getChannel().getId(), e.getCause().getMessage());
+ ctx.getChannel().close();
+ sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+ sw.stop(); */
+ } else if (e.getCause() instanceof RejectedExecutionException) {
+ logger.warn("Could not process message: queue full");
+ ctx.getChannel().close();
+ sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+ sw.stop();
+ } else {
+ logger.error("Error while processing message from switch {} Error : {}",
+ e.getChannel().getId(), e.getCause().getMessage());
+ e.getCause().printStackTrace();
+ ctx.getChannel().close();
+ sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+ sw.stop();
+ }
+
+ statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.EXCEPTION_CAUGHT);
+ }
+
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
+ throws Exception {
+ Integer messageChannelId = e.getChannel().getId();
+ IEnhancedSwitch swHan = (EnhancedSwitchHandler)channelIDToSwitchMap.get(messageChannelId);
+
+ if (e.getMessage() instanceof List) {
+ //@SuppressWarnings("unchecked")
+ List<OFMessage> msglist = (List<OFMessage>)e.getMessage();
+ if (msglist != null){ // this check actually brought down rate to some extent - weird !!!
+ for (OFMessage ofm : msglist) {
+ try {
+
+ // Do the actual packet processing
+ processOFMessage(ofm, messageChannelId);
+ }
+ catch (Exception ex) {
+ // We are the last handler in the stream, so run the
+ // exception through the channel again by passing in
+ // ctx.getChannel().
+ Channels.fireExceptionCaught(ctx.getChannel(), ex);
+ }
+ }
+ }
+ }
+
+ // Flush all flow-mods/packet-out/stats generated from this "train"
+ swHan.flushBufferedMessages();
+
+ statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.MESSAGE_RECEIVED);
+
+
+ }
+
+
+ public void processOFMessage(OFMessage ofm, Integer channelID){
+ IEnhancedSwitch switchHandler = (IEnhancedSwitch) channelIDToSwitchMap.get(channelID);
+ statsHandler.countForEntitySimpleMeasurement(channelID, TrafficStatisticsHandler.ENTITY_COUNTER_RCV_MSG);
+ if (switchHandler != null){
+ switchHandler.handleMessage(ofm);
+ }
+ }
+
+
+ }
+
+
+ protected class ControllerServerBootstrap{
+
+ private int workerThreads = 0;
+ private EnhancedController controller = null;
+
+ public ControllerServerBootstrap(EnhancedController controller){
+ this.controller = controller;
+ }
+
+
+ public void startServer(int numWorkerThreads, String openFlowHost, int openFlowPort, OFChannelHandler ofchan){
+ this.workerThreads = numWorkerThreads;
+ try {
+ final ServerBootstrap bootstrap = createServerBootStrap();
+
+ bootstrap.setOption("reuseAddr", true);
+ bootstrap.setOption("child.keepAlive", true);
+ bootstrap.setOption("child.tcpNoDelay", true);
+ bootstrap.setOption("child.receiveBufferSize", EnhancedController.RECEIVE_BUFFER_SIZE);
+ bootstrap.setOption("child.sendBufferSize", EnhancedController.SEND_BUFFER_SIZE);
+
+ // better to have an receive buffer predictor
+ //bootstrap.setOption("receiveBufferSizePredictorFactory",
+ // new AdaptiveReceiveBufferSizePredictorFactory());
+ //if the server is sending 1000 messages per sec, optimum write buffer water marks will
+ //prevent unnecessary throttling, Check NioSocketChannelConfig doc
+ //bootstrap.setOption("writeBufferLowWaterMark", WRITE_BUFFER_LOW_WATERMARK);
+ //bootstrap.setOption("writeBufferHighWaterMark", WRITE_BUFFER_HIGH_WATERMARK);
+
+ // TODO: IMPORTANT: If the threadpool is supplied as null, ExecutionHandler would
+ // not be present in pipeline. If the load increases and ordering is required ,
+ // use OrderedMemoryAwareThreadPoolExecutor as argument instead of null
+
+ /*
+ execHandler = new OrderedMemoryAwareThreadPoolExecutor(
+ OMATPE_CORE_POOL_SIZE,
+ OMATPE_PER_CHANNEL_SIZE,
+ OMATPE_POOL_WIDE_SIZE,
+ OMATPE_THREAD_KEEP_ALIVE_IN_MILLISECONDS,
+ TimeUnit.MILLISECONDS,
+ new ObjectSizeEstimator() {
+
+ @Override
+ public int estimateSize(Object o) {
+ return 30000;
+ }
+ },
+ Executors.defaultThreadFactory()); */
+
+ execHandler = new OrderedMemoryAwareThreadPoolExecutor(
+ OMATPE_CORE_POOL_SIZE,
+ OMATPE_PER_CHANNEL_SIZE,
+ OMATPE_POOL_WIDE_SIZE,
+ OMATPE_THREAD_KEEP_ALIVE_IN_MILLISECONDS,
+ TimeUnit.MILLISECONDS);
+
+
+
+ ChannelPipelineFactory pfact =
+ new OpenflowPipelineFactory(controller, execHandler);
+ bootstrap.setPipelineFactory(pfact);
+ InetSocketAddress sa =
+ (openFlowHost == null)
+ ? new InetSocketAddress(openFlowPort)
+ : new InetSocketAddress(openFlowHost, openFlowPort);
+ final ChannelGroup cg = new DefaultChannelGroup();
+ cg.add(bootstrap.bind(sa));
+
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private ServerBootstrap createServerBootStrap() {
+ if (workerThreads == 0) {
+ return new ServerBootstrap(
+ new NioServerSocketChannelFactory(
+ Executors.newCachedThreadPool(),
+ Executors.newCachedThreadPool()));
+ } else {
+ return new ServerBootstrap(
+ new NioServerSocketChannelFactory(
+ Executors.newCachedThreadPool(),
+ Executors.newCachedThreadPool(), workerThreads));
+ }
+ }
+
+
+
+ }
+
+
+ /**
+ * Method called by SwitchHandler once the handshake state is completed
+ *
+ * @param sw
+ */
+ public void switchAdded(SwitchEvent switchEv, Integer switchChannelID){
+
+ ISwitch sw = switchEv.getSwitch();
+ Long switchId = sw.getId();
+
+ connectedSwitches.put(switchId, sw);
+ statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONNECTED_SWITCHES);
+
+ logger.info("Switch with DPID : {} connected ", switchId);
+
+ notifySwitchAdded(sw);
+ }
+
+
+ /**
+ * Method called by SwitchHandler switch is disconnected
+ *
+ * @param sw
+ */
+
+ public void switchDeleted(SwitchEvent switchEv, Integer switchChannelID){
+ ISwitch sw = switchEv.getSwitch();
+ disconnectSwitch(sw, switchChannelID);
+ }
+
+
+ /**
+ * Method called by SwitchHandler when it encounters any errors
+ *
+ *
+ * @param sw
+ */
+
+ public void switchError(SwitchEvent switchEv, Integer switchChannelID){
+
+ }
+
+
+ public void switchMessage(SwitchEvent switchEv, Integer switchChannelID){
+ long startTime = 0L;
+ long endTime = 0L;
+
+
+ OFMessage msg = switchEv.getMsg();
+ ISwitch sw = switchEv.getSwitch();
+ if (msg != null) {
+ //try{
+ // lock.lock();
+ IMessageListener listener = messageListeners
+ .get(msg.getType());
+ if (listener != null) {
+ //logger.debug("delegating to msg-receiver");
+ //startTime = System.nanoTime();
+ listener.receive(sw, msg);
+ //endTime = System.nanoTime();
+ //this.statsHandler.reportPacketInProcessingTime(endTime - startTime);
+ }
+ //}
+ //finally{
+ // lock.unlock();
+ //}
+ }
+ }
+
+ public void disconnectSwitch(ISwitch sw, Integer switchChannelID){
+ Long sid = null;
+ if (((EnhancedSwitchHandler) sw).isOperational()) {
+ sid = sw.getId();
+
+ this.connectedSwitches.remove(sid);
+ this.channelIDToSwitchMap.remove(switchChannelID);
+ notifySwitchDeleted(sw);
+ }
+ //((EnhancedSwitchHandler) sw).stop();
+ logger.info("Switch with DPID {} disconnected", sid);
+ sw = null;
+ }
+
+
+ private void notifySwitchAdded(ISwitch sw) {
+ if (switchStateListener != null) {
+ switchStateListener.switchAdded(sw);
+ }
+ }
+
+ private void notifySwitchDeleted(ISwitch sw) {
+ if (switchStateListener != null) {
+ switchStateListener.switchDeleted(sw);
+ }
+ }
+
+ @Override
+ public Status disconnect(Node node) {
+ ISwitch sw = getSwitch((Long)node.getID());
+ if (sw != null) {
+ if (sw instanceof EnhancedSwitchHandler) {
+ EnhancedSwitchHandler eSw = (EnhancedSwitchHandler)sw;
+ disconnectSwitch(sw, eSw.getSwitchChannelID());
+ }
+ }
+ return new Status(StatusCode.SUCCESS);
+ }
+
+ @Override
+ public Node connect(String connectionIdentifier, Map<ConnectionConstants, String> params) {
+ return null;
+ }
+
+ /**
+ * View Change notification
+ */
+ public void notifyClusterViewChanged() {
+ for (ISwitch sw : connectedSwitches.values()) {
+ notifySwitchAdded(sw);
+ }
+ }
+
+ /**
+ * Node Disconnected from the node's master controller.
+ */
+ @Override
+ public void notifyNodeDisconnectFromMaster(Node node) {
+ ISwitch sw = connectedSwitches.get((Long)node.getID());
+ if (sw != null) notifySwitchAdded(sw);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedSelectorException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.TimerTask;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IEnhancedSwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.internal.SwitchEvent.SwitchEventType;
+import org.openflow.protocol.OFBarrierReply;
+import org.openflow.protocol.OFBarrierRequest;
+import org.openflow.protocol.OFEchoReply;
+import org.openflow.protocol.OFError;
+import org.openflow.protocol.OFFeaturesReply;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFGetConfigReply;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFPortStatus;
+import org.openflow.protocol.OFSetConfig;
+import org.openflow.protocol.OFStatisticsReply;
+import org.openflow.protocol.OFStatisticsRequest;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
+import org.openflow.protocol.OFPhysicalPort.OFPortFeatures;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
+import org.openflow.protocol.OFPortStatus.OFPortReason;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.MessageParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EnhancedSwitchHandler implements IEnhancedSwitch {
+
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(EnhancedSwitchHandler.class);
+ private static final int switchLivenessTimeout = getSwitchLivenessTimeout();
+ private int MESSAGE_RESPONSE_TIMER = 2000;
+
+ private EnhancedController controller = null;
+ private Integer switchChannelID = null;
+ private Channel channel;
+ private long lastMsgReceivedTimeStamp = 0;
+ private SwitchState state = null;
+ private BasicFactory factory = null;
+ private HashedWheelTimer timer = null;
+ private SwitchLivelinessTimerTask switchLivelinessTask = null;
+ private Timeout switchLivelinessTaskHandle = null;
+ private long sid;
+ private AtomicInteger xid;
+ private int buffers;
+ private int capabilities;
+ private byte tables;
+ private int actions;
+ private Map<Short, OFPhysicalPort> physicalPorts;
+ private Map<Short, Integer> portBandwidth;
+ private Date connectedDate;
+ private ExecutorService executor = null;
+ private ConcurrentHashMap<Integer, Callable<Object>> messageWaitingDone;
+ private Integer responseTimerValue;
+ private TrafficStatisticsHandler trafficStatsHandler = null;
+ private static final boolean START_LIVELINESS_TIMER = false;
+
+ private static final int BATCH_COUNT_FOR_FLUSHING = 3;
+ private int flushBatchTrack = 0;
+
+ /*
+ private List<OFMessage> msgBuffer = new ArrayList<OFMessage>();
+ private int bufferTrack = 0;
+ private static final int BATCH_BUFFER_THRESHOLD = 100;
+ */
+
+
+ // PLEASE .. IF THERE IS SOMETHING CALLED GOD, HELP ME GET THE THROUGHPUT WITH THIS !!
+ private List<OFMessage> flushableMsgBuffer = new ArrayList<OFMessage>();
+
+
+ public enum SwitchState {
+ NON_OPERATIONAL(0),
+ WAIT_FEATURES_REPLY(1),
+ WAIT_CONFIG_REPLY(2),
+ OPERATIONAL(3);
+
+ private int value;
+
+ private SwitchState(int value) {
+ this.value = value;
+ }
+
+ @SuppressWarnings("unused")
+ public int value() {
+ return this.value;
+ }
+ }
+
+
+ public EnhancedSwitchHandler(EnhancedController controller,
+ Integer switchConnectionChannelID,
+ Channel channel,
+ HashedWheelTimer timer,
+ ExecutorService executor,
+ TrafficStatisticsHandler tHandler){
+
+ this.controller = controller;
+ this.physicalPorts = new HashMap<Short, OFPhysicalPort>();
+ this.portBandwidth = new HashMap<Short, Integer>();
+ this.switchChannelID = switchConnectionChannelID;
+ this.timer = timer;
+ this.sid = (long) 0;
+ this.tables = (byte) 0;
+ this.actions = (int) 0;
+ this.capabilities = (int) 0;
+ this.buffers = (int) 0;
+ this.connectedDate = new Date();
+ this.state = SwitchState.NON_OPERATIONAL;
+ this.executor = executor;
+ this.messageWaitingDone = new ConcurrentHashMap<Integer, Callable<Object>>();
+ this.responseTimerValue = MESSAGE_RESPONSE_TIMER;
+ this.channel = channel;
+ this.xid = new AtomicInteger(this.channel.hashCode());
+ this.trafficStatsHandler = tHandler;
+
+ }
+
+ Integer getSwitchChannelID() {
+ return this.switchChannelID;
+ }
+
+ public void startHandler(){
+ this.factory = new BasicFactory();
+ start();
+
+ }
+
+
+ public void shutDownHandler(){
+ stop();
+
+ }
+
+
+ public void handleChannelIdle(){
+ // TODO: this is already handled by OFChannelHandler
+ // so DON'T care
+
+
+ }
+
+
+ public void start() {
+ sendFirstHello();
+ }
+
+ public void stop() {
+ cancelSwitchTimer();
+ SwitchEvent ev = new SwitchEvent(SwitchEventType.SWITCH_DELETE, this, null);
+ controller.switchDeleted(ev, switchChannelID);
+ }
+
+ private void cancelSwitchTimer() {
+ if (switchLivelinessTaskHandle != null){
+ this.switchLivelinessTaskHandle.cancel();
+ }
+ }
+
+
+ public void handleCaughtException(){
+
+
+
+ }
+
+
+
+
+ @Override
+ public int getNextXid() {
+ return this.xid.incrementAndGet();
+ }
+
+ @Override
+ public Long getId() {
+ return this.sid;
+ }
+
+ @Override
+ public Byte getTables() {
+ return this.tables;
+ }
+
+ @Override
+ public Integer getActions() {
+ return this.actions;
+ }
+
+ @Override
+ public Integer getCapabilities() {
+ return this.capabilities;
+ }
+
+ @Override
+ public Integer getBuffers() {
+ return this.buffers;
+ }
+
+ @Override
+ public Date getConnectedDate() {
+ return this.connectedDate;
+ }
+
+ @Override
+ public Integer asyncSend(OFMessage msg) {
+ return asyncSend(msg, getNextXid());
+ }
+
+
+ @Override
+ public Integer asyncSend(OFMessage msg, int xid) {
+ // TODO:
+ // BATCHING IMPLEMENTATION. Please think hard before enablng this !!
+ // Some messages could be latency-sensitive and some could be batched
+ // for better throughput. So, below decision may not bring better
+ // throughput for latency-sensitive cases like FLOW-MODs or
+ // PACKET-OUTs
+
+ /*
+ if (bufferTrack == BUFFER_THRESHOLD){
+ this.channel.write(msgBuffer);
+ msgBuffer.clear();
+ bufferTrack = 0;
+
+ }
+ msg.setXid(xid);
+ msgBuffer.add(msg);
+ bufferTrack++;
+ */
+
+
+
+ //List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+ msg.setXid(xid);
+ synchronized( flushableMsgBuffer ) {
+ flushableMsgBuffer.add(msg);
+ }
+
+ trafficStatsHandler.countForEntitySimpleMeasurement(switchChannelID,
+ TrafficStatisticsHandler.ENTITY_COUNTER_SND_MSG);
+
+ //this.channel.write(msglist);
+
+ /*
+ if (msg.getType() == OFType.FLOW_MOD){
+ this.trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.FLOW_MOD_SENT);
+ this.trafficStatsHandler.countForRateMeasurement(TrafficStatisticsHandler.FLOW_MOD_SENT);
+ }
+ */
+
+
+ return xid;
+ }
+
+
+ @Override
+ public Integer asyncFastSend(OFMessage msg) {
+ return asyncFastSend(msg, getNextXid());
+ }
+
+ @Override
+ public Integer asyncFastSend(OFMessage msg, int xid) {
+ msg.setXid(xid);
+ List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+ msglist.add(msg);
+ this.channel.write(msglist);
+ trafficStatsHandler.countForEntitySimpleMeasurement(switchChannelID,
+ TrafficStatisticsHandler.ENTITY_COUNTER_SND_MSG);
+ return xid;
+ }
+
+ @Override
+ public Object syncSend(OFMessage msg) {
+ int xid = getNextXid();
+ return syncSend(msg, xid);
+ }
+
+ private Object syncSend(OFMessage msg, int xid) {
+ return syncMessageInternal(msg, xid, true);
+ }
+
+ @Override
+ public Map<Short, OFPhysicalPort> getPhysicalPorts() {
+ return this.physicalPorts;
+ }
+
+ @Override
+ public Set<Short> getPorts() {
+ return this.physicalPorts.keySet();
+ }
+
+ @Override
+ public OFPhysicalPort getPhysicalPort(Short portNumber) {
+ return this.physicalPorts.get(portNumber);
+ }
+
+ @Override
+ public Integer getPortBandwidth(Short portNumber) {
+ return this.portBandwidth.get(portNumber);
+ }
+
+ @Override
+ public boolean isPortEnabled(short portNumber) {
+ return isPortEnabled(physicalPorts.get(portNumber));
+ }
+
+ @Override
+ public boolean isPortEnabled(OFPhysicalPort port) {
+ if (port == null) {
+ return false;
+ }
+ int portConfig = port.getConfig();
+ int portState = port.getState();
+ if ((portConfig & OFPortConfig.OFPPC_PORT_DOWN.getValue()) > 0) {
+ return false;
+ }
+ if ((portState & OFPortState.OFPPS_LINK_DOWN.getValue()) > 0) {
+ return false;
+ }
+ if ((portState & OFPortState.OFPPS_STP_MASK.getValue()) == OFPortState.OFPPS_STP_BLOCK
+ .getValue()) {
+ return false;
+ }
+ return true;
+
+ }
+
+ @Override
+ public List<OFPhysicalPort> getEnabledPorts() {
+ List<OFPhysicalPort> result = new ArrayList<OFPhysicalPort>();
+ synchronized (this.physicalPorts) {
+ for (OFPhysicalPort port : physicalPorts.values()) {
+ if (isPortEnabled(port)) {
+ result.add(port);
+ }
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * WARNING: CALLER WOULD BE BLOCKED
+ *
+ */
+ @Override
+ public Object getStatistics(OFStatisticsRequest req) {
+ int xid = getNextXid();
+ StatisticsCollector worker = new StatisticsCollector(this, xid, req);
+ messageWaitingDone.put(xid, worker);
+ Future<Object> submit = executor.submit(worker);
+ Object result = null;
+ try {
+ result = submit.get(responseTimerValue, TimeUnit.MILLISECONDS);
+ return result;
+ } catch (Exception e) {
+ logger.warn("Timeout while waiting for {} replies", req.getType());
+ result = null; // to indicate timeout has occurred
+ return result;
+ }
+ }
+
+ @Override
+ public boolean isOperational() {
+ return ((this.state == SwitchState.WAIT_CONFIG_REPLY) || (this.state == SwitchState.OPERATIONAL));
+ }
+
+ @Override
+ public Object syncSendBarrierMessage() {
+ OFBarrierRequest barrierMsg = new OFBarrierRequest();
+ return syncSend(barrierMsg);
+ }
+
+ @Override
+ public Object asyncSendBarrierMessage() {
+ List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+ OFBarrierRequest barrierMsg = new OFBarrierRequest();
+ int xid = getNextXid();
+
+ barrierMsg.setXid(xid);
+ msglist.add(barrierMsg);
+
+ this.channel.write(msglist);
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.BARRIER_REQUEST_SENT);
+ return Boolean.TRUE;
+ }
+
+
+ @Override
+ public void handleMessage(OFMessage ofMessage) {
+
+
+ logger.debug("Message received: {}", ofMessage.toString());
+ this.lastMsgReceivedTimeStamp = System.currentTimeMillis();
+ OFType type = ofMessage.getType();
+ switch (type) {
+ case HELLO:
+ logger.debug("<<<< HELLO");
+ // send feature request
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.HELLO_RECEIVED);
+ OFMessage featureRequest = factory
+ .getMessage(OFType.FEATURES_REQUEST);
+ asyncFastSend(featureRequest);
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.FEATURES_REQUEST_SENT);
+ // delete all pre-existing flows
+ OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL);
+ OFFlowMod flowMod = (OFFlowMod) factory
+ .getMessage(OFType.FLOW_MOD);
+ flowMod.setMatch(match).setCommand(OFFlowMod.OFPFC_DELETE)
+ .setOutPort(OFPort.OFPP_NONE)
+ .setLength((short) OFFlowMod.MINIMUM_LENGTH);
+ asyncFastSend(flowMod);
+ this.state = SwitchState.WAIT_FEATURES_REPLY;
+ if (START_LIVELINESS_TIMER){
+ startSwitchTimer();
+ }
+ break;
+ case ECHO_REQUEST:
+ logger.debug("<<<< ECHO REQUEST");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REQUEST_RECEIVED);
+ OFEchoReply echoReply = (OFEchoReply) factory
+ .getMessage(OFType.ECHO_REPLY);
+ asyncFastSend(echoReply);
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REPLY_SENT);
+
+ break;
+ case ECHO_REPLY:
+ logger.debug("<<<< ECHO REPLY");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REPLY_RECEIVED);
+ //this.probeSent = false;
+ break;
+ case FEATURES_REPLY:
+ logger.debug("<<<< FEATURES REPLY");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.FEATURES_REPLY_RECEIVED);
+ processFeaturesReply((OFFeaturesReply) ofMessage);
+ break;
+ case GET_CONFIG_REPLY:
+ logger.debug("<<<< CONFIG REPLY");
+ // make sure that the switch can send the whole packet to the
+ // controller
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONFIG_REPLY_RECEIVED);
+ if (((OFGetConfigReply) ofMessage).getMissSendLength() == (short) 0xffff) {
+ this.state = SwitchState.OPERATIONAL;
+ }
+ break;
+ case BARRIER_REPLY:
+ logger.debug("<<<< BARRIER REPLY");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.BARRIER_REPLY_RECEIVED);
+ processBarrierReply((OFBarrierReply) ofMessage);
+ break;
+ case ERROR:
+ logger.debug("<<<< ERROR");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ERROR_MSG_RECEIVED);
+ processErrorReply((OFError) ofMessage);
+ break;
+ case PORT_STATUS:
+ logger.debug("<<<< PORT STATUS");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.PORT_STATUS_RECEIVED);
+ processPortStatusMsg((OFPortStatus) ofMessage);
+ break;
+ case STATS_REPLY:
+ logger.debug("<<<< STATS REPLY");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.STATS_RESPONSE_RECEIVED);
+ processStatsReply((OFStatisticsReply) ofMessage);
+ break;
+ case PACKET_IN:
+ logger.debug("<<<< PACKET_IN");
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.PACKET_IN_RECEIVED);
+ trafficStatsHandler.countForRateMeasurement(TrafficStatisticsHandler.PACKET_IN_RECEIVED);
+ break;
+ default:
+ break;
+ } // end of switch
+ if (isOperational()) {
+ logger.debug("SWITCH IS OPERATIONAL ... forwarding");
+ SwitchEvent ev = new SwitchEvent(
+ SwitchEvent.SwitchEventType.SWITCH_MESSAGE, this, ofMessage);
+ controller.switchMessage(ev, switchChannelID);
+ }
+ }
+
+
+ private void startSwitchTimer(){
+ if (this.timer != null){
+ if (switchLivelinessTask == null){
+ switchLivelinessTask = new SwitchLivelinessTimerTask();
+ }
+ switchLivelinessTaskHandle = timer.newTimeout(switchLivelinessTask,
+ switchLivenessTimeout, TimeUnit.SECONDS);
+ }
+ }
+
+
+
+ /**
+ * This method returns the switch liveness timeout value. If controller did
+ * not receive any message from the switch for such a long period,
+ * controller will tear down the connection to the switch.
+ *
+ * @return The timeout value
+ */
+ private static int getSwitchLivenessTimeout() {
+ String timeout = System.getProperty("of.switchLivenessTimeout");
+ int rv = 60500;
+ try {
+ if (timeout != null) {
+ rv = Integer.parseInt(timeout);
+ }
+ } catch (Exception e) {
+ }
+ return rv;
+ }
+
+
+ private void processFeaturesReply(OFFeaturesReply reply) {
+ if (this.state == SwitchState.WAIT_FEATURES_REPLY) {
+ this.sid = reply.getDatapathId();
+ this.buffers = reply.getBuffers();
+ this.capabilities = reply.getCapabilities();
+ this.tables = reply.getTables();
+ this.actions = reply.getActions();
+ // notify core of this error event
+ for (OFPhysicalPort port : reply.getPorts()) {
+ updatePhysicalPort(port);
+ }
+ // config the switch to send full data packet
+ OFSetConfig config = (OFSetConfig) factory
+ .getMessage(OFType.SET_CONFIG);
+ config.setMissSendLength((short) 0xffff).setLengthU(
+ OFSetConfig.MINIMUM_LENGTH);
+ asyncFastSend(config);
+ // send config request to make sure the switch can handle the set
+ // config
+ OFMessage getConfig = factory.getMessage(OFType.GET_CONFIG_REQUEST);
+ asyncFastSend(getConfig);
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONFIG_REQUEST_SENT);
+ this.state = SwitchState.WAIT_CONFIG_REPLY;
+ // inform core that a new switch is now operational
+ reportSwitchStateChange(true);
+ }
+ }
+
+
+ private void updatePhysicalPort(OFPhysicalPort port) {
+ Short portNumber = port.getPortNumber();
+ physicalPorts.put(portNumber, port);
+ portBandwidth
+ .put(portNumber,
+ port.getCurrentFeatures()
+ & (OFPortFeatures.OFPPF_10MB_FD.getValue()
+ | OFPortFeatures.OFPPF_10MB_HD
+ .getValue()
+ | OFPortFeatures.OFPPF_100MB_FD
+ .getValue()
+ | OFPortFeatures.OFPPF_100MB_HD
+ .getValue()
+ | OFPortFeatures.OFPPF_1GB_FD
+ .getValue()
+ | OFPortFeatures.OFPPF_1GB_HD
+ .getValue() | OFPortFeatures.OFPPF_10GB_FD
+ .getValue()));
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.UPDATE_PHYSICAL_PORT);
+ }
+
+
+ private void reportSwitchStateChange(boolean added) {
+ SwitchEvent ev = null;
+ if (added) {
+ ev = new SwitchEvent(SwitchEvent.SwitchEventType.SWITCH_ADD, this, null);
+ controller.switchAdded(ev, switchChannelID);
+ } else {
+ ev = new SwitchEvent(SwitchEvent.SwitchEventType.SWITCH_DELETE, this, null);
+ controller.switchDeleted(ev, switchChannelID);
+ }
+ }
+
+
+ protected class SwitchLivelinessTimerTask implements TimerTask {
+
+ @Override
+ public void run(Timeout timeout) throws Exception {
+
+ // set this reference in parent so that cancellation is
+ // possible
+ switchLivelinessTaskHandle = timeout;
+ Long now = System.currentTimeMillis();
+ if ((now - lastMsgReceivedTimeStamp) > switchLivenessTimeout) {
+ if (state == SwitchState.WAIT_FEATURES_REPLY) {
+ // send another features request
+ OFMessage request = factory
+ .getMessage(OFType.FEATURES_REQUEST);
+ asyncFastSend(request);
+ } else {
+ if (state == SwitchState.WAIT_CONFIG_REPLY) {
+ // send another config request
+ OFSetConfig config = (OFSetConfig) factory
+ .getMessage(OFType.SET_CONFIG);
+ config.setMissSendLength((short) 0xffff)
+ .setLengthU(OFSetConfig.MINIMUM_LENGTH);
+ asyncFastSend(config);
+ OFMessage getConfig = factory
+ .getMessage(OFType.GET_CONFIG_REQUEST);
+ asyncFastSend(getConfig);
+ }
+ }
+ }
+ timer.newTimeout(this, switchLivenessTimeout, TimeUnit.SECONDS);
+
+ }
+ }
+
+
+ /*
+ * Either a BarrierReply or a OFError is received. If this is a reply for an
+ * outstanding sync message, wake up associated task so that it can continue
+ */
+ private void processBarrierReply(OFBarrierReply msg) {
+ Integer xid = msg.getXid();
+ SynchronousMessage worker = (SynchronousMessage) messageWaitingDone
+ .remove(xid);
+ if (worker == null) {
+ return;
+ }
+ worker.wakeup();
+ }
+
+ private void processErrorReply(OFError errorMsg) {
+ try{
+ OFMessage offendingMsg = errorMsg.getOffendingMsg();
+ Integer xi = 0;
+ if (offendingMsg != null) {
+ xi = offendingMsg.getXid();
+ } else {
+ xi = errorMsg.getXid();
+ }
+ }
+ catch(MessageParseException mpe){
+ reportError(mpe);
+ }
+ }
+
+ private void processPortStatusMsg(OFPortStatus msg) {
+ OFPhysicalPort port = msg.getDesc();
+ if (msg.getReason() == (byte) OFPortReason.OFPPR_MODIFY.ordinal()) {
+ updatePhysicalPort(port);
+ } else if (msg.getReason() == (byte) OFPortReason.OFPPR_ADD.ordinal()) {
+ updatePhysicalPort(port);
+ } else if (msg.getReason() == (byte) OFPortReason.OFPPR_DELETE
+ .ordinal()) {
+ deletePhysicalPort(port);
+ }
+
+ }
+
+ private void deletePhysicalPort(OFPhysicalPort port) {
+ Short portNumber = port.getPortNumber();
+ physicalPorts.remove(portNumber);
+ portBandwidth.remove(portNumber);
+ }
+
+ private void processStatsReply(OFStatisticsReply reply) {
+ Integer xid = reply.getXid();
+ StatisticsCollector worker = (StatisticsCollector) messageWaitingDone
+ .get(xid);
+ if (worker == null) {
+ return;
+ }
+ if (worker.collect(reply)) {
+ // if all the stats records are received (collect() returns true)
+ // then we are done.
+ messageWaitingDone.remove(xid);
+ worker.wakeup();
+ }
+ }
+
+
+ /**
+ * This method performs synchronous operations for a given message. If
+ * syncRequest is set to true, the message will be sent out followed by a
+ * Barrier request message. Then it's blocked until the Barrier rely arrives
+ * or timeout. If syncRequest is false, it simply skips the message send and
+ * just waits for the response back.
+ *
+ * @param msg
+ * Message to be sent
+ * @param xid
+ * Message XID
+ * @param request
+ * If set to true, the message the message will be sent out
+ * followed by a Barrier request message. If set to false, it
+ * simply skips the sending and just waits for the Barrier reply.
+ * @return the result
+ */
+ private Object syncMessageInternal(OFMessage msg, int xid, boolean syncRequest) {
+ Object result = null;
+
+ SynchronousMessage worker = new SynchronousMessage(this, xid, msg, syncRequest);
+ messageWaitingDone.put(xid, worker);
+
+ Boolean status = false;
+ Future<Object> submit = executor.submit(worker);
+ try {
+ result = submit.get(responseTimerValue, TimeUnit.MILLISECONDS);
+ messageWaitingDone.remove(xid);
+ if (result == null) {
+ // if result is null, then it means the switch can handle this
+ // message successfully
+ // convert the result into a Boolean with value true
+ status = true;
+ // logger.debug("Successfully send " +
+ // msg.getType().toString());
+ result = status;
+ } else {
+ // if result is not null, this means the switch can't handle
+ // this message
+ // the result if OFError already
+ logger.debug("Send {} failed --> {}", msg.getType().toString(),
+ ((OFError) result).toString());
+ }
+ return result;
+ } catch (Exception e) {
+ logger.warn("Timeout while waiting for {} reply", msg.getType()
+ .toString());
+ // convert the result into a Boolean with value false
+ status = false;
+ result = status;
+ return result;
+ }
+
+
+ }
+
+
+ private void sendFirstHello() {
+ try {
+ OFMessage msg = factory.getMessage(OFType.HELLO);
+ asyncFastSend(msg);
+ trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.HELLO_SENT);
+ trafficStatsHandler.addEntityForCounter(switchChannelID, TrafficStatisticsHandler.ENTITY_COUNTER_RCV_MSG);
+ trafficStatsHandler.addEntityForCounter(switchChannelID, TrafficStatisticsHandler.ENTITY_COUNTER_SND_MSG);
+ } catch (Exception e) {
+ reportError(e);
+ }
+ }
+
+
+ private void reportError(Exception e) {
+ if (e instanceof AsynchronousCloseException
+ || e instanceof InterruptedException
+ || e instanceof SocketException || e instanceof IOException
+ || e instanceof ClosedSelectorException) {
+ logger.error("Caught exception {}", e.getMessage());
+ } else {
+ logger.error("Caught exception ", e);
+ }
+ // notify core of this error event and disconnect the switch
+
+ // TODO: We do not need this because except-hanling is done by
+ // Controller's OFChannelHandler
+
+ /*
+ SwitchEvent ev = new SwitchEvent(
+ SwitchEvent.SwitchEventType.SWITCH_ERROR, this, null);
+
+ controller.switchError(ev, switchChannelID);
+ */
+ }
+
+
+ @Override
+ public void flushBufferedMessages() {
+ //flushBatchTrack++;
+ //if (flushBatchTrack > BATCH_COUNT_FOR_FLUSHING){
+ synchronized (flushableMsgBuffer) {
+ if (flushableMsgBuffer.size() > 0){
+ channel.write(flushableMsgBuffer);
+ flushableMsgBuffer.clear();
+ }
+ }
+ // flushBatchTrack = 0;
+ //}
+
+ }
+
+ @Override
+ public SocketAddress getRemoteAddress() {
+ return (channel != null) ? channel.getRemoteAddress() : null;
+ }
+
+ @Override
+ public SocketAddress getLocalAddress() {
+ return (channel != null) ? channel.getLocalAddress() : null;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openflow.protocol.OFFeaturesReply;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.statistics.OFDescriptionStatistics;
+
+/**
+ * Wrapper class to hold state for the OpenFlow switch connection
+ * @author readams
+ */
+class OFChannelState {
+
+ /**
+ * State for handling the switch handshake
+ */
+ protected enum HandshakeState {
+ /**
+ * Beginning state
+ */
+ START,
+
+ /**
+ * Received HELLO from switch
+ */
+ HELLO,
+
+ /**
+ * We've received the features reply
+ * Waiting for Config and Description reply
+ */
+ FEATURES_REPLY,
+
+ /**
+ * Switch is ready for processing messages
+ */
+ READY
+
+ }
+
+ protected volatile HandshakeState hsState = HandshakeState.START;
+ protected boolean hasGetConfigReply = false;
+ protected boolean hasDescription = false;
+ protected boolean switchBindingDone = false;
+
+ protected OFFeaturesReply featuresReply = null;
+ protected OFDescriptionStatistics description = null;
+ protected List<OFMessage> queuedOFMessages = new ArrayList<OFMessage>();
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.frame.FrameDecoder;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.OFMessageFactory;
+
+/**
+ * Decode an openflow message from a Channel, for use in a netty
+ * pipeline
+ * @author readams
+ */
+public class OFMessageDecoder extends FrameDecoder {
+
+ OFMessageFactory factory = new BasicFactory();
+
+ @Override
+ protected Object decode(ChannelHandlerContext ctx, Channel channel,
+ ChannelBuffer buffer) throws Exception {
+ if (!channel.isConnected()) {
+ // In testing, I see decode being called AFTER decode last.
+ // This check avoids that from reading curroupted frames
+ return null;
+ }
+
+ List<OFMessage> message = factory.parseMessage(buffer);
+ return message;
+ }
+
+ @Override
+ protected Object decodeLast(ChannelHandlerContext ctx, Channel channel,
+ ChannelBuffer buffer) throws Exception {
+ // This is not strictly needed atthis time. It is used to detect
+ // connection reset detection from netty (for debug)
+ return null;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
+import org.openflow.protocol.OFMessage;
+
+/**
+ * Encode an openflow message for output into a ChannelBuffer, for use in a
+ * netty pipeline
+ * @author readams
+ */
+public class OFMessageEncoder extends OneToOneEncoder {
+
+ @Override
+ protected Object encode(ChannelHandlerContext ctx, Channel channel,
+ Object msg) throws Exception {
+ if (!( msg instanceof List))
+ return msg;
+
+ @SuppressWarnings("unchecked")
+ List<OFMessage> msglist = (List<OFMessage>)msg;
+ int size = 0;
+ for (OFMessage ofm : msglist) {
+ size += ofm.getLengthU();
+ }
+
+ ChannelBuffer buf = ChannelBuffers.buffer(size);;
+ for (OFMessage ofm : msglist) {
+ ofm.writeTo(buf);
+ }
+ return buf;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.handler.execution.ExecutionHandler;
+import org.jboss.netty.handler.timeout.IdleStateHandler;
+import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timer;
+
+/**
+ * Creates a ChannelPipeline for a server-side openflow channel
+ * @author readams
+ */
+public class OpenflowPipelineFactory implements ChannelPipelineFactory {
+
+ private static final int READ_TIMEOUT = 30;
+ private static final int READER_IDLE_TIMEOUT = 20;
+ private static final int WRITER_IDLE_TIMEOUT = 25;
+ private static final int ALL_IDLE_TIMEOUT = 0;
+
+ protected EnhancedController controller;
+ protected ThreadPoolExecutor pipelineExecutor;
+ protected Timer timer;
+ protected IdleStateHandler idleHandler;
+ protected ReadTimeoutHandler readTimeoutHandler;
+
+ public OpenflowPipelineFactory(EnhancedController controller,
+ ThreadPoolExecutor pipelineExecutor) {
+ super();
+ this.controller = controller;
+ this.pipelineExecutor = pipelineExecutor;
+ this.timer = new HashedWheelTimer();
+ this.idleHandler = new IdleStateHandler(timer, READER_IDLE_TIMEOUT, WRITER_IDLE_TIMEOUT, ALL_IDLE_TIMEOUT);
+ this.readTimeoutHandler = new ReadTimeoutHandler(timer, READ_TIMEOUT);
+ }
+
+ @Override
+ public ChannelPipeline getPipeline() throws Exception {
+ //OFChannelState state = new OFChannelState();
+
+
+ ChannelPipeline pipeline = Channels.pipeline();
+
+ /*
+ if (pipelineExecutor != null)
+ pipeline.addLast("pipelineExecutor",
+ new ExecutionHandler(pipelineExecutor));*/
+ pipeline.addLast("ofmessagedecoder", new OFMessageDecoder());
+ pipeline.addLast("ofmessageencoder", new OFMessageEncoder());
+ pipeline.addLast("idle", idleHandler);
+ //pipeline.addLast("timeout", readTimeoutHandler);
+ //pipeline.addLast("handshaketimeout",
+ // new HandshakeTimeoutHandler(state, timer, 15));
+
+ /*
+ if (pipelineExecutor != null)
+ pipeline.addLast("pipelineExecutor",
+ new ExecutionHandler(pipelineExecutor));*/
+ pipeline.addLast("handler", controller.getChannelHandler());
+ return pipeline;
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.TimerTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+public class TrafficStatisticsHandler {
+
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(EnhancedController.class);
+
+ private Timeout statsTaskHandle = null;
+
+ private Map<String, AtomicLong> currentCounterMap = new ConcurrentHashMap<String, AtomicLong>();
+ private Map<String, AtomicLong> lastCounterMap = new ConcurrentHashMap<String, AtomicLong>();
+ private Map<String, Long> lastMeasurementTStamp = new ConcurrentHashMap<String, Long>();
+ private List<String> rawRateMeasurementData = new ArrayList<String>();
+
+ private ConcurrentHashMap<Integer, AtomicLong> msgRcvEntityCounter =
+ new ConcurrentHashMap<Integer, AtomicLong>();
+ private ConcurrentHashMap<Integer, AtomicLong> msgSndEntityCounter =
+ new ConcurrentHashMap<Integer, AtomicLong>();
+
+
+
+ private static final long STATISTICS_RATE_INTERVAL = 25000;
+ private static final int STATISTICS_PRINT_INTREVAL = 180;
+ private static List<Long> packetInProcessingTimeList = new ArrayList<Long>();
+ private static List<Integer> pendingTaskCountList = new ArrayList<Integer>();
+
+
+ public static final String ENTITY_COUNTER_RCV_MSG = "SWITCHWISE_RCV_MSG_COUNT";
+ public static final String ENTITY_COUNTER_SND_MSG = "SWITCHWISE_SND_MSG_COUNT";
+
+ private HashedWheelTimer hashedWheelTimer = null;
+
+ public static final String ADDED_SWITCHES = "ADDED_SWITCHES";
+ public static final String CONNECTED_SWITCHES = "CONNECTED_SWITCHES";
+ public static final String DELETED_SWITCHES = "DELETED_SWITCHES";
+ public static final String DISCONNECTED_SWITCHES = "DISCONNECTED_SWITCHES";
+ public static final String SWITCH_ERROR = "SWITCH_ERROR";
+
+
+
+ public static final String EXCEPTION_CAUGHT = "EXCEPTION_CAUGHT";
+ public static final String MESSAGE_RECEIVED = "MESSAGE_RECEIVED"; // DO RATE-MEASUREMENTS
+
+ public static final String MSG_LISTENER_INVOCATION = "MSG_LISTENER_INVOCATION";
+ public static final String HELLO_RECEIVED = "HELLO_RECEIVED";
+ public static final String HELLO_SENT = "HELLO_SENT";
+ public static final String ECHO_REQUEST_SENT = "ECHO_REQUEST_SENT";
+ public static final String ECHO_REQUEST_RECEIVED = "ECHO_REQUEST_RECEIVED";
+ public static final String ECHO_REPLY_SENT = "ECHO_REPLY_SENT";
+ public static final String ECHO_REPLY_RECEIVED = "ECHO_REPLY_RECEIVED";
+ public static final String FEATURES_REQUEST_SENT = "FEATURES_REQUEST_SENT";
+ public static final String FEATURES_REQUEST_RECEIVED = "FEATURES_REQUEST_RECEIVED";
+ public static final String FEATURES_REPLY_SENT = "FEATURES_REPLY_SENT";
+ public static final String FEATURES_REPLY_RECEIVED = "FEATURES_REPLY_RECEIVED";
+ public static final String CONFIG_REQUEST_SENT = "CONFIG_REQUEST_SENT";
+ public static final String CONFIG_REQUEST_RECEIVED = "CONFIG_REQUEST_RECEIVED";
+ public static final String CONFIG_REPLY_SENT = "CONFIG_REPLY_SENT";
+ public static final String CONFIG_REPLY_RECEIVED = "CONFIG_REPLY_RECEIVED";
+ public static final String BARRIER_REQUEST_SENT = "BARRIER_REQUEST_SENT";
+ public static final String BARRIER_REPLY_RECEIVED = "BARRIER_REPLY_RECEIVED";
+ public static final String ERROR_MSG_RECEIVED = "ERROR_MSG_RECEIVED";
+ public static final String PORT_STATUS_RECEIVED = "PORT_STATUS";
+ public static final String PACKET_IN_RECEIVED = "PACKET_IN"; // DO RATE-MEASUREMENTS
+ public static final String FLOW_MOD_SENT = "FLOW_MOD_SENT"; // DO RATE-MEASUREMENTS ==> To be determined as to where to collect this data from
+ public static final String STATS_REQUEST_SENT = "STATS_REQUEST_SENT"; // DO RATE-MEASUREMENTS ==> To be determined as to where to collect this data from
+ public static final String STATS_RESPONSE_RECEIVED = "STATS_RESPONSE_RECEIVED";
+
+ public static final String UPDATE_PHYSICAL_PORT = "UPDATE_PHYSICAL_PORT";
+
+ private static final int TASK_SCHEDULE_INITIAL_DELAY_IN_SECONDS = 10;
+
+ private int trackPktInProcessing = 0;
+ private static final int PKT_IN_PROCESSING_DURATION_SAMPLING_COUNT = 100000;
+
+
+ public TrafficStatisticsHandler(HashedWheelTimer timer){
+ this.hashedWheelTimer = timer;
+ }
+
+
+ public void init(){
+
+ currentCounterMap.put(MSG_LISTENER_INVOCATION, new AtomicLong(0));
+ currentCounterMap.put(ADDED_SWITCHES, new AtomicLong(0));
+ currentCounterMap.put(DELETED_SWITCHES, new AtomicLong(0));
+ currentCounterMap.put(CONNECTED_SWITCHES, new AtomicLong(0));
+ currentCounterMap.put(DISCONNECTED_SWITCHES, new AtomicLong(0));
+ currentCounterMap.put(SWITCH_ERROR, new AtomicLong(0));
+ currentCounterMap.put(HELLO_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(HELLO_SENT, new AtomicLong(0));
+ currentCounterMap.put(ECHO_REQUEST_SENT, new AtomicLong(0));
+ currentCounterMap.put(ECHO_REQUEST_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(ECHO_REPLY_SENT, new AtomicLong(0));
+ currentCounterMap.put(ECHO_REPLY_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(EXCEPTION_CAUGHT, new AtomicLong(0));
+ currentCounterMap.put(MESSAGE_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(FEATURES_REQUEST_SENT, new AtomicLong(0));
+ currentCounterMap.put(FEATURES_REQUEST_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(FEATURES_REPLY_SENT, new AtomicLong(0));
+ currentCounterMap.put(FEATURES_REPLY_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(CONFIG_REQUEST_SENT, new AtomicLong(0));
+ currentCounterMap.put(CONFIG_REQUEST_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(CONFIG_REPLY_SENT, new AtomicLong(0));
+ currentCounterMap.put(CONFIG_REPLY_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(BARRIER_REQUEST_SENT, new AtomicLong(0));
+ currentCounterMap.put(BARRIER_REPLY_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(ERROR_MSG_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(PORT_STATUS_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(PACKET_IN_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(FLOW_MOD_SENT, new AtomicLong(0));
+ currentCounterMap.put(STATS_REQUEST_SENT, new AtomicLong(0));
+ currentCounterMap.put(STATS_RESPONSE_RECEIVED, new AtomicLong(0));
+ currentCounterMap.put(UPDATE_PHYSICAL_PORT, new AtomicLong(0));
+
+ lastCounterMap.put(MSG_LISTENER_INVOCATION, new AtomicLong(0));
+ lastCounterMap.put(ADDED_SWITCHES, new AtomicLong(0));
+ lastCounterMap.put(DELETED_SWITCHES, new AtomicLong(0));
+ lastCounterMap.put(CONNECTED_SWITCHES, new AtomicLong(0));
+ lastCounterMap.put(DISCONNECTED_SWITCHES, new AtomicLong(0));
+ lastCounterMap.put(SWITCH_ERROR, new AtomicLong(0));
+ lastCounterMap.put(HELLO_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(HELLO_SENT, new AtomicLong(0));
+ lastCounterMap.put(FEATURES_REQUEST_SENT, new AtomicLong(0));
+ lastCounterMap.put(FEATURES_REQUEST_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(ECHO_REQUEST_SENT, new AtomicLong(0));
+ lastCounterMap.put(ECHO_REQUEST_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(ECHO_REPLY_SENT, new AtomicLong(0));
+ lastCounterMap.put(ECHO_REPLY_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(EXCEPTION_CAUGHT, new AtomicLong(0));
+ lastCounterMap.put(MESSAGE_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(FEATURES_REPLY_SENT, new AtomicLong(0));
+ lastCounterMap.put(FEATURES_REPLY_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(CONFIG_REQUEST_SENT, new AtomicLong(0));
+ lastCounterMap.put(CONFIG_REQUEST_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(CONFIG_REPLY_SENT, new AtomicLong(0));
+ lastCounterMap.put(CONFIG_REPLY_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(BARRIER_REQUEST_SENT, new AtomicLong(0));
+ lastCounterMap.put(BARRIER_REPLY_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(ERROR_MSG_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(PORT_STATUS_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(PACKET_IN_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(FLOW_MOD_SENT, new AtomicLong(0));
+ lastCounterMap.put(STATS_REQUEST_SENT, new AtomicLong(0));
+ lastCounterMap.put(STATS_RESPONSE_RECEIVED, new AtomicLong(0));
+ lastCounterMap.put(UPDATE_PHYSICAL_PORT, new AtomicLong(0));
+
+ lastMeasurementTStamp.put(MSG_LISTENER_INVOCATION, new Long(0));
+ lastMeasurementTStamp.put(ADDED_SWITCHES, new Long(0));
+ lastMeasurementTStamp.put(DELETED_SWITCHES, new Long(0));
+ lastMeasurementTStamp.put(CONNECTED_SWITCHES, new Long(0));
+ lastMeasurementTStamp.put(DISCONNECTED_SWITCHES, new Long(0));
+ lastMeasurementTStamp.put(SWITCH_ERROR, new Long(0));
+ lastMeasurementTStamp.put(HELLO_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(HELLO_SENT, new Long(0));
+ lastMeasurementTStamp.put(ECHO_REQUEST_SENT, new Long(0));
+ lastMeasurementTStamp.put(ECHO_REQUEST_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(ECHO_REPLY_SENT, new Long(0));
+ lastMeasurementTStamp.put(ECHO_REPLY_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(EXCEPTION_CAUGHT, new Long(0));
+ lastMeasurementTStamp.put(MESSAGE_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(FEATURES_REQUEST_SENT, new Long(0));
+ lastMeasurementTStamp.put(FEATURES_REQUEST_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(FEATURES_REPLY_SENT, new Long(0));
+ lastMeasurementTStamp.put(FEATURES_REPLY_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(CONFIG_REQUEST_SENT, new Long(0));
+ lastMeasurementTStamp.put(CONFIG_REQUEST_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(CONFIG_REPLY_SENT, new Long(0));
+ lastMeasurementTStamp.put(CONFIG_REPLY_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(BARRIER_REQUEST_SENT, new Long(0));
+ lastMeasurementTStamp.put(BARRIER_REPLY_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(ERROR_MSG_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(PORT_STATUS_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(PACKET_IN_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(FLOW_MOD_SENT, new Long(0));
+ lastMeasurementTStamp.put(STATS_REQUEST_SENT, new Long(0));
+ lastMeasurementTStamp.put(STATS_RESPONSE_RECEIVED, new Long(0));
+ lastMeasurementTStamp.put(UPDATE_PHYSICAL_PORT, new Long(0));
+
+ /*
+ rateMap.put(HELLO_SENT, new Double(0.00000000));
+ rateMap.put(FEATURES_REQUEST, new Double(0.00000000));
+ rateMap.put(FEATURES_REPLY, new Double(0.00000000));
+ rateMap.put(CONFIG_REQUEST, new Double(0.00000000));
+ rateMap.put(CONFIG_REPLY, new Double(0.00000000));
+ rateMap.put(PORT_STATUS, new Double(0.00000000));
+ rateMap.put(PACKET_IN, new Double(0.00000000));
+ rateMap.put(FLOW_MOD_SENT, new Double(0.00000000));
+
+
+ history.put(HELLO_SENT, new ArrayList());
+ history.put(FEATURES_REQUEST, new ArrayList());
+ history.put(FEATURES_REPLY, new ArrayList());
+ history.put(CONFIG_REQUEST, new ArrayList());
+ history.put(CONFIG_REPLY, new ArrayList());
+ history.put(PORT_STATUS, new ArrayList());
+ history.put(PACKET_IN, new ArrayList());
+ history.put(FLOW_MOD_SENT, new ArrayList());
+ */
+
+ statsTaskHandle = this.hashedWheelTimer.newTimeout(new StatsOutTask(),
+ TASK_SCHEDULE_INITIAL_DELAY_IN_SECONDS, TimeUnit.SECONDS);
+
+ }
+
+ public void stopStatsHandler(){
+ if (statsTaskHandle != null){
+ statsTaskHandle.cancel();
+ }
+ }
+
+ public void reportPacketInProcessingTime(long duration){
+ trackPktInProcessing++;
+ if (trackPktInProcessing > PKT_IN_PROCESSING_DURATION_SAMPLING_COUNT){
+ packetInProcessingTimeList.add(new Long(duration));
+ trackPktInProcessing = 0;
+ }
+ }
+
+ public void addEntityForCounter(Integer entityID, String counterType){
+ if (counterType.equalsIgnoreCase(ENTITY_COUNTER_RCV_MSG)){
+ msgRcvEntityCounter.put(entityID, new AtomicLong(0));
+ }
+ else{
+ msgSndEntityCounter.put(entityID, new AtomicLong(0));
+ }
+ }
+
+ public void countForEntitySimpleMeasurement(Integer entityID, String counterType){
+ if (counterType.equalsIgnoreCase(ENTITY_COUNTER_RCV_MSG)){
+ //msgRcvEntityCounter.get(entityID).incrementAndGet();
+ }
+ else{
+ //msgSndEntityCounter.get(entityID).incrementAndGet();
+ }
+ }
+
+
+ public void countForSimpleMeasurement(String counterName){
+ currentCounterMap.get(counterName).incrementAndGet();
+ }
+
+ public void countForRateMeasurement(String counterName){
+
+ long currCntr = currentCounterMap.get(counterName).incrementAndGet();
+ if (lastMeasurementTStamp.get(counterName) == 0){
+ lastMeasurementTStamp.put(counterName, System.currentTimeMillis());
+ }
+
+ Long currentCount = new Long(currCntr);
+ Long lastCount = lastCounterMap.get(counterName).get();
+
+ //Double rate = 0.00000000000;
+ if ((currentCount - lastCount) == STATISTICS_RATE_INTERVAL){
+ Long currentTime = System.currentTimeMillis();
+ Long lastTime = lastMeasurementTStamp.get(counterName);
+ //rate = new Double((STATISTICS_RATE_INTERVAL/(currentTime-lastTime))*1000); //convert to count/sec
+ rawRateMeasurementData.add("CN:" + counterName +
+ ",CC:" + currentCount +
+ ",LC:" + lastCount +
+ ",CT:" + currentTime +
+ ",LT:" + lastTime +
+ ",CV:" + ((STATISTICS_RATE_INTERVAL/(currentTime-lastTime))*1000));
+ lastCounterMap.put(counterName, new AtomicLong(currentCount));
+ lastMeasurementTStamp.put(counterName, currentTime);
+ //history.get(counterName).add(String.valueOf(rate.doubleValue()));
+ //rateMap.put(counterName, rate);
+ }
+
+ }
+
+
+ private class StatsOutTask implements TimerTask {
+
+ @Override
+ public void run(Timeout timeout) throws Exception {
+
+ statsTaskHandle = timeout;
+ logger.warn(">>>>>>Raw Counter values at controller BEGIN<<<<<<<<");
+
+ for (Entry<String, AtomicLong> entry : currentCounterMap.entrySet()){
+ logger.warn("{} {}", entry.getKey(), entry.getValue());
+ }
+ logger.warn(">>>>>>Counter values at controller END <<<<<<<<");
+
+ logger.warn(">>>>>>Entity Counter values at controller BEGIN<<<<<<<<");
+
+ for (Entry<Integer, AtomicLong> entry : msgRcvEntityCounter.entrySet()){
+ logger.warn("SwitchID {} : Rcv Msg Count {}", entry.getKey(), entry.getValue());
+ }
+ logger.warn(">>>>>>Entity Counter values at controller END <<<<<<<<");
+
+ logger.warn(">>>>>>Raw data rate values at controller BEGIN<<<<<<<<");
+
+ for (String str : rawRateMeasurementData ){
+ logger.warn("{}", str);
+ }
+ logger.warn(">>>>>>Raw data rate values at controller END <<<<<<<<");
+
+
+ if (packetInProcessingTimeList.size() > 0){
+ logger.warn("================ MAX PACKET_IN PROC TIME in microseconds : {}",
+ Collections.max(packetInProcessingTimeList)/1000);
+ logger.warn("================ MIN PACKET_IN PROC TIME in microseconds : {}",
+ Collections.min(packetInProcessingTimeList)/1000);
+ long v = 0L;
+ int track = 0;
+ for (Long val : packetInProcessingTimeList){
+ v = v + val.longValue();
+ track++;
+ }
+ logger.warn("================ AVG PACKET_IN PROC TIME in microseconds : {}",
+ ((double)(v/track))/1000);
+ }
+ hashedWheelTimer.newTimeout(this, STATISTICS_PRINT_INTREVAL, TimeUnit.SECONDS);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.protocol_plugin.openflow.internal;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.protocol_plugin.openflow.core.internal.EnhancedController;
+import org.opendaylight.controller.protocol_plugin.openflow.core.internal.Controller;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Openflow protocol plugin Activator
+ *
+ *
+ */
+public class EnhancedActivator extends Activator {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(EnhancedActivator.class);
+
+ // Default Constructor for the activator
+ public EnhancedActivator() {
+ super();
+ logger.debug("Enhanced activator called!");
+ }
+
+ /**
+ * Function that is used to communicate to dependency manager the list of
+ * known implementations for services that are container independent.
+ *
+ *
+ * @return An array containing all the CLASS objects that will be
+ * instantiated in order to get an fully working implementation
+ * Object
+ */
+ @Override
+ public Object[] getGlobalImplementations() {
+ Object[] res = super.getGlobalImplementations();
+ // Now remove the Controller.class and return the
+ // EnhancedController
+ List resList = new ArrayList(Arrays.asList(res));
+ resList.remove(Controller.class);
+ resList.add(EnhancedController.class);
+ return resList.toArray();
+ }
+
+ /**
+ * Function that is called when configuration of the dependencies is
+ * required.
+ *
+ * @param c
+ * dependency manager Component object, used for configuring the
+ * dependencies exported and imported
+ * @param imp
+ * Implementation class that is being configured, needed as long
+ * as the same routine can configure multiple implementations
+ */
+ @Override
+ public void configureGlobalInstance(Component c, Object imp) {
+ if (imp.equals(EnhancedController.class)) {
+ // Configure it like if was the Controller.class
+ super.configureGlobalInstance(c, Controller.class);
+ } else {
+ super.configureGlobalInstance(c, imp);
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.0</maven>
+ </prerequisites>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.thirdparty</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
+ <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+ <sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
+ <siteplugin>3.2</siteplugin>
+ <projectinfo>2.6</projectinfo>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <compiler.version>2.3.2</compiler.version>
+ <surefire.version>2.13</surefire.version>
+ </properties>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>central2</id>
+ <name>central2</name>
+ <url>${nexusproxy}/repositories/central2/</url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <profiles>
+ <profile>
+ <id>fastreassembly</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <id>copyfastreassembly</id>
+ <phase>install</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${project.version}</version>
+ <destFileName>${project.groupId}.${project.artifactId}-${project.version}.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${fastreassembly.directory}</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
+ <artifactId>maven-java-formatter-plugin</artifactId>
+ <version>0.3.1</version>
+ <configuration>
+ <excludes>
+ <exclude>**/*</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>${siteplugin}</version>
+ <configuration>
+ <reportPlugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>${projectinfo}</version>
+ <configuration>
+ <dependencyDetailsEnabled>false</dependencyDetailsEnabled>
+ <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+ </configuration>
+ <reports>
+ <report>index</report>
+ <report>project-team</report>
+ <report>license</report>
+ <report>mailing-list</report>
+ <report>plugin-management</report>
+ <report>cim</report>
+ <report>issue-tracking</report>
+ <report>scm</report>
+ <report>summary</report>
+ </reports>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.10</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.8.1</version>
+ <configuration>
+ <doclet>org.jboss.apiviz.APIviz</doclet>
+ <docletArtifact>
+ <groupId>org.jboss.apiviz</groupId>
+ <artifactId>apiviz</artifactId>
+ <version>1.3.2.GA</version>
+ </docletArtifact>
+ <finalName>${project.artifactId}-${build.suffix}</finalName>
+ <useStandardDocletOptions>true</useStandardDocletOptions>
+ <charset>UTF-8</charset>
+ <encoding>UTF-8</encoding>
+ <docencoding>UTF-8</docencoding>
+ <breakiterator>true</breakiterator>
+ <version>true</version>
+ <author>true</author>
+ <keywords>true</keywords>
+ <excludePackageNames>net.sf.jnetlib.*:cern.*:corejava</excludePackageNames>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.3</version>
+ <configuration>
+ <aggregate>true</aggregate>
+ <linkJavadoc>true</linkJavadoc>
+ </configuration>
+ </plugin>
+ </reportPlugins>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <repositories>
+ <!-- Maven repo2 mirror -->
+ <repository>
+ <id>central2</id>
+ <name>central2</name>
+ <url>${nexusproxy}/repositories/central2/</url>
+ </repository>
+ <!-- Maven repo1 mirror -->
+ <repository>
+ <id>central</id>
+ <name>central</name>
+ <url>${nexusproxy}/repositories/central/</url>
+ </repository>
+ <!-- Third Packages hosted in local maven because not available in
+ other places -->
+ <repository>
+ <id>thirdparty</id>
+ <name>thirdparty</name>
+ <url>${nexusproxy}/repositories/thirdparty</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <!-- OpenDayLight Released artifact -->
+ <repository>
+ <id>opendaylight-release</id>
+ <url>${nexusproxy}/repositories/opendaylight.release/</url>
+ </repository>
+ <!-- OpenDayLight Snapshot artifact -->
+ <snapshotRepository>
+ <id>opendaylight-snapshot</id>
+ <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ </snapshotRepository>
+ <!-- Site deployment -->
+ <site>
+ <id>website</id>
+ <url>${sitedeploy}</url>
+ </site>
+ </distributionManagement>
+</project>
--- /dev/null
+Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+University
+
+We are making the OpenFlow specification and associated documentation
+(Software) available for public use and benefit with the expectation that
+others will use, modify and enhance the Software and contribute those
+enhancements back to the community. However, since we would like to make the
+Software available for broadest use, with as few restrictions as possible
+permission is hereby granted, free of charge, to any person obtaining a copy of
+this Software to deal in the Software under the copyrights without restriction,
+including without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+The name and trademarks of copyright holder(s) may NOT be used in advertising
+or publicity pertaining to the Software or any derivatives without specific,
+written prior permission.
--- /dev/null
+# Because I am old and crotchety and my fingers can't stop from running
+# `make` commands
+all:
+ ant
+
+run:
+ ant run
+
+doc:
+ ant javadoc
+
+tests:
+ ant tests
+
+count:
+ @find . -name \*.java | xargs wc -l | sort -n
+
+clean:
+ ant clean
--- /dev/null
+OpenFlow Java - v1.0.0
+
+A Java implementation of low-level OpenFlow packet marshalling/unmarshalling
+and IO operations. Implements v1.0 of the OpenFlow specification at
+http://www.openflow.org.
+
+ - David Erickson (daviderickson@cs.stanford.edu)
+ - Rob Sherwood (rob.sherwood@stanford.edu)
+
+Building requires Maven 2.x+ (http://maven.apache.org/).
+
+To build:
+ mvn package
+
+To build javadocs:
+ mvn javadoc:javadoc
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="11">
+<profile kind="CodeFormatterProfile" name="OpenFlowJ" version="11">
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+</profile>
+</profiles>
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>org.openflow.openflowj_netty</artifactId>
+ <version>1.0.2-SNAPSHOT</version>
+ <name>OpenFlow Java</name>
+ <description>A Java implemention of the OpenFlow v1.0 protocol</description>
+
+ <!-- Get some common settings for the project we are using it in -->
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.thirdparty</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../commons/thirdparty</relativePath>
+ </parent>
+
+ <developers>
+ <developer>
+ <name>David Erickson</name>
+ <email>daviderickson@cs.stanford.edu</email>
+ </developer>
+ <developer>
+ <name>Rob Sherwood</name>
+ <email>rob.sherwood@stanford.edu</email>
+ </developer>
+ </developers>
+ <packaging>bundle</packaging>
+ <url>http://www.openflow.org</url>
+ <licenses>
+ <license>
+ <name>The OpenFlow License</name>
+ <url>http://www.openflowswitch.org/wp/legal/</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:git://gitosis.stanford.edu:openflowj.git</connection>
+ <url>https://openflow.stanford.edu/fisheye/browse/OpenFlowJ</url>
+ </scm>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <!-- For GPG release signing, use mvn release:perform -->
+ <profiles>
+ <profile>
+ <id>release-sign-artifacts</id>
+ <activation>
+ <property>
+ <name>performRelease</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <mavenExecutorId>forked-path</mavenExecutorId>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.jboss.netty.*
+ </Import-Package>
+ <Export-Package>
+ org.openflow.*
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.netty</groupId>
+ <artifactId>netty</artifactId>
+ <version>3.2.6.Final</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public interface Instantiable<E> {
+
+ /**
+ * Create a new instance of a given subclass.
+ * @return the new instance.
+ */
+ public E instantiate();
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+/**
+ * Represents an OFPT_BARRIER_REPLY message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFBarrierReply extends OFMessage {
+ public OFBarrierReply() {
+ super();
+ this.type = OFType.BARRIER_REPLY;
+ this.length = U16.t(OFMessage.MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+/**
+ * Represents an OFPT_BARRIER_REQUEST message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFBarrierRequest extends OFMessage {
+ public OFBarrierRequest() {
+ super();
+ this.type = OFType.BARRIER_REQUEST;
+ this.length = U16.t(OFMessage.MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_echo_reply message
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+
+public class OFEchoReply extends OFEchoRequest {
+ public static int MINIMUM_LENGTH = 8;
+
+ public OFEchoReply() {
+ super();
+ this.type = OFType.ECHO_REPLY;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_echo_request message
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+
+public class OFEchoRequest extends OFMessage {
+ public static int MINIMUM_LENGTH = 8;
+ byte[] payload;
+
+ public OFEchoRequest() {
+ super();
+ this.type = OFType.ECHO_REQUEST;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer bb) {
+ super.readFrom(bb);
+ int datalen = this.getLengthU() - MINIMUM_LENGTH;
+ if (datalen > 0) {
+ this.payload = new byte[datalen];
+ bb.readBytes(payload);
+ }
+ }
+
+ /**
+ * @return the payload
+ */
+ public byte[] getPayload() {
+ return payload;
+ }
+
+ /**
+ * @param payload
+ * the payload to set
+ */
+ public void setPayload(byte[] payload) {
+ this.payload = payload;
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer bb) {
+ super.writeTo(bb);
+ if (payload != null)
+ bb.writeBytes(payload);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(payload);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OFEchoRequest other = (OFEchoRequest) obj;
+ if (!Arrays.equals(payload, other.payload))
+ return false;
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.factory.MessageParseException;
+import org.openflow.protocol.factory.OFMessageFactory;
+import org.openflow.protocol.factory.OFMessageFactoryAware;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_error_msg
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+public class OFError extends OFMessage implements OFMessageFactoryAware {
+ public static int MINIMUM_LENGTH = 12;
+
+ public enum OFErrorType {
+ // OFPET_VENDOR_ERROR is an extension that was added in Open vSwitch and isn't
+ // in the OF 1.0 spec, but it was easier to add it here instead of adding
+ // generic support for extensible vendor-defined error messages.
+ // It uses the random value 0xb0c2 to avoid conflicts with other possible new
+ // error types. Support for vendor-defined extended errors has been standardized
+ // in the OF 1.2 spec, so this workaround is only needed for 1.0.
+ OFPET_HELLO_FAILED, OFPET_BAD_REQUEST, OFPET_BAD_ACTION, OFPET_FLOW_MOD_FAILED, OFPET_PORT_MOD_FAILED, OFPET_QUEUE_OP_FAILED, OFPET_VENDOR_ERROR((short)0xb0c2);
+
+ protected short value;
+
+ private OFErrorType() {
+ this.value = (short) this.ordinal();
+ }
+
+ private OFErrorType(short value) {
+ this.value = value;
+ }
+
+ public short getValue() {
+ return value;
+ }
+ }
+
+ public enum OFHelloFailedCode {
+ OFPHFC_INCOMPATIBLE, OFPHFC_EPERM
+ }
+
+ public enum OFBadRequestCode {
+ OFPBRC_BAD_VERSION, OFPBRC_BAD_TYPE, OFPBRC_BAD_STAT, OFPBRC_BAD_VENDOR, OFPBRC_BAD_SUBTYPE, OFPBRC_EPERM, OFPBRC_BAD_LEN, OFPBRC_BUFFER_EMPTY, OFPBRC_BUFFER_UNKNOWN
+ }
+
+ public enum OFBadActionCode {
+ OFPBAC_BAD_TYPE, OFPBAC_BAD_LEN, OFPBAC_BAD_VENDOR, OFPBAC_BAD_VENDOR_TYPE, OFPBAC_BAD_OUT_PORT, OFPBAC_BAD_ARGUMENT, OFPBAC_EPERM, OFPBAC_TOO_MANY, OFPBAC_BAD_QUEUE
+ }
+
+ public enum OFFlowModFailedCode {
+ OFPFMFC_ALL_TABLES_FULL, OFPFMFC_OVERLAP, OFPFMFC_EPERM, OFPFMFC_BAD_EMERG_TIMEOUT, OFPFMFC_BAD_COMMAND, OFPFMFC_UNSUPPORTED
+ }
+
+ public enum OFPortModFailedCode {
+ OFPPMFC_BAD_PORT, OFPPMFC_BAD_HW_ADDR
+ }
+
+ public enum OFQueueOpFailedCode {
+ OFPQOFC_BAD_PORT, OFPQOFC_BAD_QUEUE, OFPQOFC_EPERM
+ }
+
+ protected short errorType;
+ protected short errorCode;
+ protected int vendor;
+ protected int vendorErrorType;
+ protected short vendorErrorCode;
+ protected OFMessageFactory factory;
+ protected byte[] error;
+ protected boolean errorIsAscii;
+
+ public OFError() {
+ super();
+ this.type = OFType.ERROR;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /** convenience constructor */
+ public OFError(OFErrorType errorType) {
+ this();
+ setErrorType(errorType);
+ }
+
+ /**
+ * @return the errorType
+ */
+ public short getErrorType() {
+ return errorType;
+ }
+
+ /**
+ * @param errorType
+ * the errorType to set
+ */
+ public void setErrorType(short errorType) {
+ this.errorType = errorType;
+ }
+
+ public void setErrorType(OFErrorType type) {
+ this.errorType = type.getValue();
+ }
+
+ /**
+ * @return true if the error is an extended vendor error
+ */
+ public boolean isVendorError() {
+ return errorType == OFErrorType.OFPET_VENDOR_ERROR.getValue();
+ }
+
+ /**
+ * @return the errorCode
+ */
+ public short getErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * @param errorCode
+ * the errorCode to set
+ */
+ public void setErrorCode(OFHelloFailedCode code) {
+ this.errorCode = (short) code.ordinal();
+ }
+
+ public void setErrorCode(short errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ public void setErrorCode(OFBadRequestCode code) {
+ this.errorCode = (short) code.ordinal();
+ }
+
+ public void setErrorCode(OFBadActionCode code) {
+ this.errorCode = (short) code.ordinal();
+ }
+
+ public void setErrorCode(OFFlowModFailedCode code) {
+ this.errorCode = (short) code.ordinal();
+ }
+
+ public void setErrorCode(OFPortModFailedCode code) {
+ this.errorCode = (short) code.ordinal();
+ }
+
+ public void setErrorCode(OFQueueOpFailedCode code) {
+ this.errorCode = (short) code.ordinal();
+ }
+
+ public int getVendorErrorType() {
+ return vendorErrorType;
+ }
+
+ public void setVendorErrorType(int vendorErrorType) {
+ this.vendorErrorType = vendorErrorType;
+ }
+
+ public short getVendorErrorCode() {
+ return vendorErrorCode;
+ }
+
+ public void setVendorErrorCode(short vendorErrorCode) {
+ this.vendorErrorCode = vendorErrorCode;
+ }
+
+ public OFMessage getOffendingMsg() throws MessageParseException {
+ // should only have one message embedded; if more than one, just
+ // grab first
+ if (this.error == null)
+ return null;
+ ChannelBuffer errorMsg = ChannelBuffers.wrappedBuffer(this.error);
+ if (factory == null)
+ throw new RuntimeException("MessageFactory not set");
+
+ List<OFMessage> msglist = this.factory.parseMessage(errorMsg);
+ if (msglist == null)
+ return null;
+ return msglist.get(0);
+ }
+
+ /**
+ * Write this offending message into the payload of the Error message
+ *
+ * @param offendingMsg
+ */
+
+ public void setOffendingMsg(OFMessage offendingMsg) {
+ if (offendingMsg == null) {
+ super.setLengthU(MINIMUM_LENGTH);
+ } else {
+ this.error = new byte[offendingMsg.getLengthU()];
+ ChannelBuffer data = ChannelBuffers.wrappedBuffer(this.error);
+ data.writerIndex(0);
+ offendingMsg.writeTo(data);
+ super.setLengthU(MINIMUM_LENGTH + offendingMsg.getLengthU());
+ }
+ }
+
+ public OFMessageFactory getFactory() {
+ return factory;
+ }
+
+ @Override
+ public void setMessageFactory(OFMessageFactory factory) {
+ this.factory = factory;
+ }
+
+ /**
+ * @return the error
+ */
+ public byte[] getError() {
+ return error;
+ }
+
+ /**
+ * @param error
+ * the error to set
+ */
+ public void setError(byte[] error) {
+ this.error = error;
+ }
+
+ /**
+ * @return the errorIsAscii
+ */
+ public boolean isErrorIsAscii() {
+ return errorIsAscii;
+ }
+
+ /**
+ * @param errorIsAscii
+ * the errorIsAscii to set
+ */
+ public void setErrorIsAscii(boolean errorIsAscii) {
+ this.errorIsAscii = errorIsAscii;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.errorType = data.readShort();
+ this.errorCode = data.readShort();
+ int dataLength = this.getLengthU() - MINIMUM_LENGTH;
+ if (dataLength > 0) {
+ this.error = new byte[dataLength];
+ data.readBytes(this.error);
+ if (this.errorType == OFErrorType.OFPET_HELLO_FAILED.getValue())
+ this.errorIsAscii = true;
+ }
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(errorType);
+ data.writeShort(errorCode);
+ if (error != null)
+ data.writeBytes(error);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(error);
+ result = prime * result + errorCode;
+ result = prime * result + (errorIsAscii ? 1231 : 1237);
+ result = prime * result + errorType;
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OFError other = (OFError) obj;
+ if (!Arrays.equals(error, other.error))
+ return false;
+ if (errorCode != other.errorCode)
+ return false;
+ if (errorIsAscii != other.errorIsAscii)
+ return false;
+ if (errorType != other.errorType)
+ return false;
+ return true;
+ }
+
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+
+/**
+ * Represents a features reply message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ *
+ */
+
+public class OFFeaturesReply extends OFMessage {
+ public static int MINIMUM_LENGTH = 32;
+
+ /**
+ * Corresponds to bits on the capabilities field
+ */
+ public enum OFCapabilities {
+ OFPC_FLOW_STATS (1 << 0),
+ OFPC_TABLE_STATS (1 << 1),
+ OFPC_PORT_STATS (1 << 2),
+ OFPC_STP (1 << 3),
+ OFPC_RESERVED (1 << 4),
+ OFPC_IP_REASM (1 << 5),
+ OFPC_QUEUE_STATS (1 << 6),
+ OFPC_ARP_MATCH_IP (1 << 7);
+
+ protected int value;
+
+ private OFCapabilities(int value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+ }
+
+ protected long datapathId;
+ protected int buffers;
+ protected byte tables;
+ protected int capabilities;
+ protected int actions;
+ protected List<OFPhysicalPort> ports;
+
+ public OFFeaturesReply() {
+ super();
+ this.type = OFType.FEATURES_REPLY;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the datapathId
+ */
+ public long getDatapathId() {
+ return datapathId;
+ }
+
+ /**
+ * @param datapathId the datapathId to set
+ */
+ public void setDatapathId(long datapathId) {
+ this.datapathId = datapathId;
+ }
+
+ /**
+ * @return the buffers
+ */
+ public int getBuffers() {
+ return buffers;
+ }
+
+ /**
+ * @param buffers the buffers to set
+ */
+ public void setBuffers(int buffers) {
+ this.buffers = buffers;
+ }
+
+ /**
+ * @return the tables
+ */
+ public byte getTables() {
+ return tables;
+ }
+
+ /**
+ * @param tables the tables to set
+ */
+ public void setTables(byte tables) {
+ this.tables = tables;
+ }
+
+ /**
+ * @return the capabilities
+ */
+ public int getCapabilities() {
+ return capabilities;
+ }
+
+ /**
+ * @param capabilities the capabilities to set
+ */
+ public void setCapabilities(int capabilities) {
+ this.capabilities = capabilities;
+ }
+
+ /**
+ * @return the actions
+ */
+ public int getActions() {
+ return actions;
+ }
+
+ /**
+ * @param actions the actions to set
+ */
+ public void setActions(int actions) {
+ this.actions = actions;
+ }
+
+ /**
+ * @return the ports
+ */
+ public List<OFPhysicalPort> getPorts() {
+ return ports;
+ }
+
+ /**
+ * @param ports the ports to set
+ */
+ public void setPorts(List<OFPhysicalPort> ports) {
+ this.ports = ports;
+ if (ports == null) {
+ this.setLengthU(MINIMUM_LENGTH);
+ } else {
+ this.setLengthU(MINIMUM_LENGTH + ports.size()
+ * OFPhysicalPort.MINIMUM_LENGTH);
+ }
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.datapathId = data.readLong();
+ this.buffers = data.readInt();
+ this.tables = data.readByte();
+ data.readerIndex(data.readerIndex() + 3); // pad
+ this.capabilities = data.readInt();
+ this.actions = data.readInt();
+ if (this.ports == null) {
+ this.ports = new ArrayList<OFPhysicalPort>();
+ } else {
+ this.ports.clear();
+ }
+ int portCount = (super.getLengthU() - 32)
+ / OFPhysicalPort.MINIMUM_LENGTH;
+ OFPhysicalPort port;
+ for (int i = 0; i < portCount; ++i) {
+ port = new OFPhysicalPort();
+ port.readFrom(data);
+ this.ports.add(port);
+ }
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeLong(this.datapathId);
+ data.writeInt(this.buffers);
+ data.writeByte(this.tables);
+ data.writeShort((short) 0); // pad
+ data.writeByte((byte) 0); // pad
+ data.writeInt(this.capabilities);
+ data.writeInt(this.actions);
+ if (this.ports != null)
+ for (OFPhysicalPort port : this.ports) {
+ port.writeTo(data);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 139;
+ int result = super.hashCode();
+ result = prime * result + actions;
+ result = prime * result + buffers;
+ result = prime * result + capabilities;
+ result = prime * result + (int) (datapathId ^ (datapathId >>> 32));
+ result = prime * result + ((ports == null) ? 0 : ports.hashCode());
+ result = prime * result + tables;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFFeaturesReply)) {
+ return false;
+ }
+ OFFeaturesReply other = (OFFeaturesReply) obj;
+ if (actions != other.actions) {
+ return false;
+ }
+ if (buffers != other.buffers) {
+ return false;
+ }
+ if (capabilities != other.capabilities) {
+ return false;
+ }
+ if (datapathId != other.datapathId) {
+ return false;
+ }
+ if (ports == null) {
+ if (other.ports != null) {
+ return false;
+ }
+ } else if (!ports.equals(other.ports)) {
+ return false;
+ }
+ if (tables != other.tables) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+
+/**
+ * Represents a features request message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ *
+ */
+public class OFFeaturesRequest extends OFMessage {
+ public static int MINIMUM_LENGTH = 8;
+
+ public OFFeaturesRequest() {
+ super();
+ this.type = OFType.FEATURES_REQUEST;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.factory.OFActionFactory;
+import org.openflow.protocol.factory.OFActionFactoryAware;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_flow_mod message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ *
+ */
+public class OFFlowMod extends OFMessage implements OFActionFactoryAware, Cloneable {
+ public static int MINIMUM_LENGTH = 72;
+
+ public static final short OFPFC_ADD = 0; /* New flow. */
+ public static final short OFPFC_MODIFY = 1; /* Modify all matching flows. */
+ public static final short OFPFC_MODIFY_STRICT = 2; /* Modify entry strictly matching wildcards */
+ public static final short OFPFC_DELETE=3; /* Delete all matching flows. */
+ public static final short OFPFC_DELETE_STRICT =4; /* Strictly match wildcards and priority. */
+
+ // Open Flow Flow Mod Flags. Use "or" operation to set multiple flags
+ public static final short OFPFF_SEND_FLOW_REM = 0x1; // 1 << 0
+ public static final short OFPFF_CHECK_OVERLAP = 0x2; // 1 << 1
+ public static final short OFPFF_EMERG = 0x4; // 1 << 2
+
+ protected OFActionFactory actionFactory;
+ protected OFMatch match;
+ protected long cookie;
+ protected short command;
+ protected short idleTimeout;
+ protected short hardTimeout;
+ protected short priority;
+ protected int bufferId;
+ protected short outPort;
+ protected short flags;
+ protected List<OFAction> actions;
+
+ public OFFlowMod() {
+ super();
+ this.outPort = OFPort.OFPP_NONE.getValue();
+ this.type = OFType.FLOW_MOD;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * Get buffer_id
+ * @return
+ */
+ public int getBufferId() {
+ return this.bufferId;
+ }
+
+ /**
+ * Set buffer_id
+ * @param bufferId
+ */
+ public OFFlowMod setBufferId(int bufferId) {
+ this.bufferId = bufferId;
+ return this;
+ }
+
+ /**
+ * Get cookie
+ * @return
+ */
+ public long getCookie() {
+ return this.cookie;
+ }
+
+ /**
+ * Set cookie
+ * @param cookie
+ */
+ public OFFlowMod setCookie(long cookie) {
+ this.cookie = cookie;
+ return this;
+ }
+
+ /**
+ * Get command
+ * @return
+ */
+ public short getCommand() {
+ return this.command;
+ }
+
+ /**
+ * Set command
+ * @param command
+ */
+ public OFFlowMod setCommand(short command) {
+ this.command = command;
+ return this;
+ }
+
+ /**
+ * Get flags
+ * @return
+ */
+ public short getFlags() {
+ return this.flags;
+ }
+
+ /**
+ * Set flags
+ * @param flags
+ */
+ public OFFlowMod setFlags(short flags) {
+ this.flags = flags;
+ return this;
+ }
+
+ /**
+ * Get hard_timeout
+ * @return
+ */
+ public short getHardTimeout() {
+ return this.hardTimeout;
+ }
+
+ /**
+ * Set hard_timeout
+ * @param hardTimeout
+ */
+ public OFFlowMod setHardTimeout(short hardTimeout) {
+ this.hardTimeout = hardTimeout;
+ return this;
+ }
+
+ /**
+ * Get idle_timeout
+ * @return
+ */
+ public short getIdleTimeout() {
+ return this.idleTimeout;
+ }
+
+ /**
+ * Set idle_timeout
+ * @param idleTimeout
+ */
+ public OFFlowMod setIdleTimeout(short idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ return this;
+ }
+
+ /**
+ * Gets a copy of the OFMatch object for this FlowMod, changes to this
+ * object do not modify the FlowMod
+ * @return
+ */
+ public OFMatch getMatch() {
+ return this.match;
+ }
+
+ /**
+ * Set match
+ * @param match
+ */
+ public OFFlowMod setMatch(OFMatch match) {
+ this.match = match;
+ return this;
+ }
+
+ /**
+ * Get out_port
+ * @return
+ */
+ public short getOutPort() {
+ return this.outPort;
+ }
+
+ /**
+ * Set out_port
+ * @param outPort
+ */
+ public OFFlowMod setOutPort(short outPort) {
+ this.outPort = outPort;
+ return this;
+ }
+
+ /**
+ * Set out_port
+ * @param port
+ */
+ public OFFlowMod setOutPort(OFPort port) {
+ this.outPort = port.getValue();
+ return this;
+ }
+
+ /**
+ * Get priority
+ * @return
+ */
+ public short getPriority() {
+ return this.priority;
+ }
+
+ /**
+ * Set priority
+ * @param priority
+ */
+ public OFFlowMod setPriority(short priority) {
+ this.priority = priority;
+ return this;
+ }
+
+ /**
+ * Returns read-only copies of the actions contained in this Flow Mod
+ * @return a list of ordered OFAction objects
+ */
+ public List<OFAction> getActions() {
+ return this.actions;
+ }
+
+ /**
+ * Sets the list of actions this Flow Mod contains
+ * @param actions a list of ordered OFAction objects
+ */
+ public OFFlowMod setActions(List<OFAction> actions) {
+ this.actions = actions;
+ return this;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ if (this.match == null)
+ this.match = new OFMatch();
+ this.match.readFrom(data);
+ this.cookie = data.readLong();
+ this.command = data.readShort();
+ this.idleTimeout = data.readShort();
+ this.hardTimeout = data.readShort();
+ this.priority = data.readShort();
+ this.bufferId = data.readInt();
+ this.outPort = data.readShort();
+ this.flags = data.readShort();
+ if (this.actionFactory == null)
+ throw new RuntimeException("OFActionFactory not set");
+ this.actions = this.actionFactory.parseActions(data, getLengthU() -
+ MINIMUM_LENGTH);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ this.match.writeTo(data);
+ data.writeLong(cookie);
+ data.writeShort(command);
+ data.writeShort(idleTimeout);
+ data.writeShort(hardTimeout);
+ data.writeShort(priority);
+ data.writeInt(bufferId);
+ data.writeShort(outPort);
+ data.writeShort(flags);
+ if (actions != null) {
+ for (OFAction action : actions) {
+ action.writeTo(data);
+ }
+ }
+ }
+
+ @Override
+ public void setActionFactory(OFActionFactory actionFactory) {
+ this.actionFactory = actionFactory;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 227;
+ int result = super.hashCode();
+ result = prime * result + ((actions == null) ? 0 : actions.hashCode());
+ result = prime * result + bufferId;
+ result = prime * result + command;
+ result = prime * result + (int) (cookie ^ (cookie >>> 32));
+ result = prime * result + flags;
+ result = prime * result + hardTimeout;
+ result = prime * result + idleTimeout;
+ result = prime * result + ((match == null) ? 0 : match.hashCode());
+ result = prime * result + outPort;
+ result = prime * result + priority;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFFlowMod)) {
+ return false;
+ }
+ OFFlowMod other = (OFFlowMod) obj;
+ if (actions == null) {
+ if (other.actions != null) {
+ return false;
+ }
+ } else if (!actions.equals(other.actions)) {
+ return false;
+ }
+ if (bufferId != other.bufferId) {
+ return false;
+ }
+ if (command != other.command) {
+ return false;
+ }
+ if (cookie != other.cookie) {
+ return false;
+ }
+ if (flags != other.flags) {
+ return false;
+ }
+ if (hardTimeout != other.hardTimeout) {
+ return false;
+ }
+ if (idleTimeout != other.idleTimeout) {
+ return false;
+ }
+ if (match == null) {
+ if (other.match != null) {
+ return false;
+ }
+ } else if (!match.equals(other.match)) {
+ return false;
+ }
+ if (outPort != other.outPort) {
+ return false;
+ }
+ if (priority != other.priority) {
+ return false;
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public OFFlowMod clone() throws CloneNotSupportedException {
+ OFMatch neoMatch = match.clone();
+ OFFlowMod flowMod= (OFFlowMod) super.clone();
+ flowMod.setMatch(neoMatch);
+ List<OFAction> neoActions = new LinkedList<OFAction>();
+ for(OFAction action: this.actions)
+ neoActions.add((OFAction) action.clone());
+ flowMod.setActions(neoActions);
+ return flowMod;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "OFFlowMod [actionFactory=" + actionFactory + ", actions="
+ + actions + ", bufferId=" + bufferId + ", command=" + command
+ + ", cookie=" + cookie + ", flags=" + flags + ", hardTimeout="
+ + hardTimeout + ", idleTimeout=" + idleTimeout + ", match="
+ + match + ", outPort=" + outPort + ", priority=" + priority
+ + ", length=" + length + ", type=" + type + ", version="
+ + version + ", xid=" + xid + "]";
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_flow_removed message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ *
+ */
+public class OFFlowRemoved extends OFMessage {
+ public static int MINIMUM_LENGTH = 88;
+
+ public enum OFFlowRemovedReason {
+ OFPRR_IDLE_TIMEOUT,
+ OFPRR_HARD_TIMEOUT,
+ OFPRR_DELETE
+ }
+
+ protected OFMatch match;
+ protected long cookie;
+ protected short priority;
+ protected OFFlowRemovedReason reason;
+ protected int durationSeconds;
+ protected int durationNanoseconds;
+ protected short idleTimeout;
+ protected long packetCount;
+ protected long byteCount;
+
+ public OFFlowRemoved() {
+ super();
+ this.type = OFType.FLOW_REMOVED;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * Get cookie
+ * @return
+ */
+ public long getCookie() {
+ return this.cookie;
+ }
+
+ /**
+ * Set cookie
+ * @param cookie
+ */
+ public void setCookie(long cookie) {
+ this.cookie = cookie;
+ }
+
+ /**
+ * Get idle_timeout
+ * @return
+ */
+ public short getIdleTimeout() {
+ return this.idleTimeout;
+ }
+
+ /**
+ * Set idle_timeout
+ * @param idleTimeout
+ */
+ public void setIdleTimeout(short idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ }
+
+ /**
+ * Gets a copy of the OFMatch object for this FlowMod, changes to this
+ * object do not modify the FlowMod
+ * @return
+ */
+ public OFMatch getMatch() {
+ return this.match;
+ }
+
+ /**
+ * Set match
+ * @param match
+ */
+ public void setMatch(OFMatch match) {
+ this.match = match;
+ }
+
+ /**
+ * Get priority
+ * @return
+ */
+ public short getPriority() {
+ return this.priority;
+ }
+
+ /**
+ * Set priority
+ * @param priority
+ */
+ public void setPriority(short priority) {
+ this.priority = priority;
+ }
+
+ /**
+ * @return the reason
+ */
+ public OFFlowRemovedReason getReason() {
+ return reason;
+ }
+
+ /**
+ * @param reason the reason to set
+ */
+ public void setReason(OFFlowRemovedReason reason) {
+ this.reason = reason;
+ }
+
+ /**
+ * @return the durationSeconds
+ */
+ public int getDurationSeconds() {
+ return durationSeconds;
+ }
+
+ /**
+ * @param durationSeconds the durationSeconds to set
+ */
+ public void setDurationSeconds(int durationSeconds) {
+ this.durationSeconds = durationSeconds;
+ }
+
+ /**
+ * @return the durationNanoseconds
+ */
+ public int getDurationNanoseconds() {
+ return durationNanoseconds;
+ }
+
+ /**
+ * @param durationNanoseconds the durationNanoseconds to set
+ */
+ public void setDurationNanoseconds(int durationNanoseconds) {
+ this.durationNanoseconds = durationNanoseconds;
+ }
+
+ /**
+ * @return the packetCount
+ */
+ public long getPacketCount() {
+ return packetCount;
+ }
+
+ /**
+ * @param packetCount the packetCount to set
+ */
+ public void setPacketCount(long packetCount) {
+ this.packetCount = packetCount;
+ }
+
+ /**
+ * @return the byteCount
+ */
+ public long getByteCount() {
+ return byteCount;
+ }
+
+ /**
+ * @param byteCount the byteCount to set
+ */
+ public void setByteCount(long byteCount) {
+ this.byteCount = byteCount;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ if (this.match == null)
+ this.match = new OFMatch();
+ this.match.readFrom(data);
+ this.cookie = data.readLong();
+ this.priority = data.readShort();
+ int reasonIndex = (int)(0xff & data.readByte());
+ if (reasonIndex >= OFFlowRemovedReason.values().length) {
+ reasonIndex = OFFlowRemovedReason.values().length - 1;
+ }
+ this.reason = OFFlowRemovedReason.values()[reasonIndex];
+ data.readByte(); // pad
+ this.durationSeconds = data.readInt();
+ this.durationNanoseconds = data.readInt();
+ this.idleTimeout = data.readShort();
+ data.readByte(); // pad
+ data.readByte(); // pad
+ this.packetCount = data.readLong();
+ this.byteCount = data.readLong();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ this.match.writeTo(data);
+ data.writeLong(cookie);
+ data.writeShort(priority);
+ data.writeByte((byte) this.reason.ordinal());
+ data.writeByte((byte) 0);
+ data.writeInt(this.durationSeconds);
+ data.writeInt(this.durationNanoseconds);
+ data.writeShort(idleTimeout);
+ data.writeByte((byte) 0); // pad
+ data.writeByte((byte) 0); // pad
+ data.writeLong(this.packetCount);
+ data.writeLong(this.byteCount);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 271;
+ int result = super.hashCode();
+ result = prime * result + (int) (byteCount ^ (byteCount >>> 32));
+ result = prime * result + (int) (cookie ^ (cookie >>> 32));
+ result = prime * result + durationNanoseconds;
+ result = prime * result + durationSeconds;
+ result = prime * result + idleTimeout;
+ result = prime * result + ((match == null) ? 0 : match.hashCode());
+ result = prime * result + (int) (packetCount ^ (packetCount >>> 32));
+ result = prime * result + priority;
+ result = prime * result + ((reason == null) ? 0 : reason.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFFlowRemoved)) {
+ return false;
+ }
+ OFFlowRemoved other = (OFFlowRemoved) obj;
+ if (byteCount != other.byteCount) {
+ return false;
+ }
+ if (cookie != other.cookie) {
+ return false;
+ }
+ if (durationNanoseconds != other.durationNanoseconds) {
+ return false;
+ }
+ if (durationSeconds != other.durationSeconds) {
+ return false;
+ }
+ if (idleTimeout != other.idleTimeout) {
+ return false;
+ }
+ if (match == null) {
+ if (other.match != null) {
+ return false;
+ }
+ } else if (!match.equals(other.match)) {
+ return false;
+ }
+ if (packetCount != other.packetCount) {
+ return false;
+ }
+ if (priority != other.priority) {
+ return false;
+ }
+ if (reason == null) {
+ if (other.reason != null) {
+ return false;
+ }
+ } else if (!reason.equals(other.reason)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+/**
+ * Represents an OFPT_GET_CONFIG_REPLY type message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFGetConfigReply extends OFSwitchConfig {
+ public OFGetConfigReply() {
+ super();
+ this.type = OFType.GET_CONFIG_REPLY;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+/**
+ * Represents an OFPT_GET_CONFIG_REQUEST type message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFGetConfigRequest extends OFMessage {
+ public OFGetConfigRequest() {
+ super();
+ this.type = OFType.GET_CONFIG_REQUEST;
+ this.length = U16.t(OFMessage.MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+
+/**
+ * Represents an ofp_hello message
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 8, 2010
+ */
+public class OFHello extends OFMessage {
+ public static int MINIMUM_LENGTH = 8;
+
+ /**
+ * Construct a ofp_hello message
+ */
+ public OFHello() {
+ super();
+ this.type = OFType.HELLO;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+ * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+ * 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 org.openflow.protocol;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.HexString;
+import org.openflow.util.U16;
+import org.openflow.util.U8;
+
+/**
+ * Represents an ofp_match structure
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+public class OFMatch implements Cloneable, Serializable {
+
+ /**
+ *
+ */
+
+ public static final short VLAN_UNTAGGED = (short)0xffff;
+
+ private static final long serialVersionUID = 1L;
+ public static int MINIMUM_LENGTH = 40;
+ final public static int OFPFW_ALL = ((1 << 22) - 1);
+
+ final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
+ final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
+ final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
+ final public static int OFPFW_DL_DST = 1 << 3; /*
+ * Ethernet destination
+ * address.
+ */
+ final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
+ final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
+ final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
+ final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
+
+ /*
+ * IP source address wildcard bit count. 0 is exact match, 1 ignores the
+ * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
+ * the entire field. This is the *opposite* of the usual convention where
+ * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
+ */
+ final public static int OFPFW_NW_SRC_SHIFT = 8;
+ final public static int OFPFW_NW_SRC_BITS = 6;
+ final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
+ final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
+
+ /* IP destination address wildcard bit count. Same format as source. */
+ final public static int OFPFW_NW_DST_SHIFT = 14;
+ final public static int OFPFW_NW_DST_BITS = 6;
+ final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
+ final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
+
+ final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
+ final public static int OFPFW_NW_TOS = 1 << 21; /*
+ * IP ToS (DSCP field, 6
+ * bits).
+ */
+
+ final public static int OFPFW_ALL_SANITIZED = (((1 << 22) - 1)
+ & ~OFPFW_NW_SRC_MASK & ~OFPFW_NW_DST_MASK)
+ | OFPFW_NW_SRC_ALL
+ | OFPFW_NW_DST_ALL;
+
+ /* List of Strings for marshalling and unmarshalling to human readable forms */
+ final public static String STR_IN_PORT = "in_port";
+ final public static String STR_DL_DST = "dl_dst";
+ final public static String STR_DL_SRC = "dl_src";
+ final public static String STR_DL_TYPE = "dl_type";
+ final public static String STR_DL_VLAN = "dl_vlan";
+ final public static String STR_DL_VLAN_PCP = "dl_vlan_pcp";
+ final public static String STR_NW_DST = "nw_dst";
+ final public static String STR_NW_SRC = "nw_src";
+ final public static String STR_NW_PROTO = "nw_proto";
+ final public static String STR_NW_TOS = "nw_tos";
+ final public static String STR_TP_DST = "tp_dst";
+ final public static String STR_TP_SRC = "tp_src";
+
+ protected int wildcards;
+ protected short inputPort;
+ protected byte[] dataLayerSource;
+ protected byte[] dataLayerDestination;
+ protected short dataLayerVirtualLan;
+ protected byte dataLayerVirtualLanPriorityCodePoint;
+ protected short dataLayerType;
+ protected byte networkTypeOfService;
+ protected byte networkProtocol;
+ protected int networkSource;
+ protected int networkDestination;
+ protected short transportSource;
+ protected short transportDestination;
+
+ /**
+ * By default, create a OFMatch that matches everything (mostly because it's
+ * the least amount of work to make a valid OFMatch)
+ */
+ public OFMatch() {
+ this.wildcards = OFPFW_ALL;
+ this.dataLayerDestination = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0 };
+ this.dataLayerSource = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+ this.dataLayerVirtualLan = VLAN_UNTAGGED;
+ this.dataLayerVirtualLanPriorityCodePoint = 0;
+ this.dataLayerType = 0;
+ this.inputPort = 0;
+ this.networkProtocol = 0;
+ this.networkTypeOfService = 0;
+ this.networkSource = 0;
+ this.networkDestination = 0;
+ this.transportDestination = 0;
+ this.transportSource = 0;
+ }
+
+ /**
+ * Get dl_dst
+ *
+ * @return an arrays of bytes
+ */
+ public byte[] getDataLayerDestination() {
+ return this.dataLayerDestination;
+ }
+
+ /**
+ * Set dl_dst
+ *
+ * @param dataLayerDestination
+ */
+ public OFMatch setDataLayerDestination(byte[] dataLayerDestination) {
+ this.dataLayerDestination = dataLayerDestination;
+ return this;
+ }
+
+ /**
+ * Set dl_dst, but first translate to byte[] using HexString
+ *
+ * @param mac
+ * A colon separated string of 6 pairs of octets, e..g.,
+ * "00:17:42:EF:CD:8D"
+ */
+ public OFMatch setDataLayerDestination(String mac) {
+ byte bytes[] = HexString.fromHexString(mac);
+ if (bytes.length != 6)
+ throw new IllegalArgumentException(
+ "expected string with 6 octets, got '"
+ + mac
+ + "'");
+ this.dataLayerDestination = bytes;
+ return this;
+ }
+
+ /**
+ * Get dl_src
+ *
+ * @return an array of bytes
+ */
+ public byte[] getDataLayerSource() {
+ return this.dataLayerSource;
+ }
+
+ /**
+ * Set dl_src
+ *
+ * @param dataLayerSource
+ */
+ public OFMatch setDataLayerSource(byte[] dataLayerSource) {
+ this.dataLayerSource = dataLayerSource;
+ return this;
+ }
+
+ /**
+ * Set dl_src, but first translate to byte[] using HexString
+ *
+ * @param mac
+ * A colon separated string of 6 pairs of octets, e..g.,
+ * "00:17:42:EF:CD:8D"
+ */
+ public OFMatch setDataLayerSource(String mac) {
+ byte bytes[] = HexString.fromHexString(mac);
+ if (bytes.length != 6)
+ throw new IllegalArgumentException(
+ "expected string with 6 octets, got '"
+ + mac
+ + "'");
+ this.dataLayerSource = bytes;
+ return this;
+ }
+
+ /**
+ * Get dl_type
+ *
+ * @return ether_type
+ */
+ public short getDataLayerType() {
+ return this.dataLayerType;
+ }
+
+ /**
+ * Set dl_type
+ *
+ * @param dataLayerType
+ */
+ public OFMatch setDataLayerType(short dataLayerType) {
+ this.dataLayerType = dataLayerType;
+ return this;
+ }
+
+ /**
+ * Get dl_vlan
+ *
+ * @return vlan tag; VLAN_NONE == no tag
+ */
+ public short getDataLayerVirtualLan() {
+ return this.dataLayerVirtualLan;
+ }
+
+ /**
+ * Set dl_vlan
+ *
+ * @param dataLayerVirtualLan
+ */
+ public OFMatch setDataLayerVirtualLan(short dataLayerVirtualLan) {
+ this.dataLayerVirtualLan = dataLayerVirtualLan;
+ return this;
+ }
+
+ /**
+ * Get dl_vlan_pcp
+ *
+ * @return
+ */
+ public byte getDataLayerVirtualLanPriorityCodePoint() {
+ return this.dataLayerVirtualLanPriorityCodePoint;
+ }
+
+ /**
+ * Set dl_vlan_pcp
+ *
+ * @param pcp
+ */
+ public OFMatch setDataLayerVirtualLanPriorityCodePoint(byte pcp) {
+ this.dataLayerVirtualLanPriorityCodePoint = pcp;
+ return this;
+ }
+
+ /**
+ * Get in_port
+ *
+ * @return
+ */
+ public short getInputPort() {
+ return this.inputPort;
+ }
+
+ /**
+ * Set in_port
+ *
+ * @param inputPort
+ */
+ public OFMatch setInputPort(short inputPort) {
+ this.inputPort = inputPort;
+ return this;
+ }
+
+ /**
+ * Get nw_dst
+ *
+ * @return
+ */
+ public int getNetworkDestination() {
+ return this.networkDestination;
+ }
+
+ /**
+ * Set nw_dst
+ *
+ * @param networkDestination
+ */
+ public OFMatch setNetworkDestination(int networkDestination) {
+ this.networkDestination = networkDestination;
+ return this;
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return a number between 0 (matches all IPs) and 63 ( 32>= implies exact
+ * match)
+ */
+ public int getNetworkDestinationMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+ 0);
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return a number between 0 (matches all IPs) and 32 (exact match)
+ */
+ public int getNetworkSourceMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+ 0);
+ }
+
+ /**
+ * Get nw_proto
+ *
+ * @return
+ */
+ public byte getNetworkProtocol() {
+ return this.networkProtocol;
+ }
+
+ /**
+ * Set nw_proto
+ *
+ * @param networkProtocol
+ */
+ public OFMatch setNetworkProtocol(byte networkProtocol) {
+ this.networkProtocol = networkProtocol;
+ return this;
+ }
+
+ /**
+ * Get nw_src
+ *
+ * @return
+ */
+ public int getNetworkSource() {
+ return this.networkSource;
+ }
+
+ /**
+ * Set nw_src
+ *
+ * @param networkSource
+ */
+ public OFMatch setNetworkSource(int networkSource) {
+ this.networkSource = networkSource;
+ return this;
+ }
+
+ /**
+ * Get nw_tos OFMatch stores the ToS bits as top 6-bits, so right shift by 2
+ * bits before returning the value
+ *
+ * @return : 6-bit DSCP value (0-63)
+ */
+ public byte getNetworkTypeOfService() {
+ return (byte) ((this.networkTypeOfService >> 2) & 0x3f);
+ }
+
+ /**
+ * Set nw_tos OFMatch stores the ToS bits as top 6-bits, so left shift by 2
+ * bits before storing the value
+ *
+ * @param networkTypeOfService
+ * : 6-bit DSCP value (0-63)
+ */
+ public OFMatch setNetworkTypeOfService(byte networkTypeOfService) {
+ this.networkTypeOfService = (byte) (networkTypeOfService << 2);
+ return this;
+ }
+
+ /**
+ * Get tp_dst
+ *
+ * @return
+ */
+ public short getTransportDestination() {
+ return this.transportDestination;
+ }
+
+ /**
+ * Set tp_dst
+ *
+ * @param transportDestination
+ */
+ public OFMatch setTransportDestination(short transportDestination) {
+ this.transportDestination = transportDestination;
+ return this;
+ }
+
+ /**
+ * Get tp_src
+ *
+ * @return
+ */
+ public short getTransportSource() {
+ return this.transportSource;
+ }
+
+ /**
+ * Set tp_src
+ *
+ * @param transportSource
+ */
+ public OFMatch setTransportSource(short transportSource) {
+ this.transportSource = transportSource;
+ return this;
+ }
+
+ /**
+ * Get wildcards
+ *
+ * @return
+ */
+ public int getWildcards() {
+ return this.wildcards;
+ }
+
+ /**
+ * Get wildcards
+ *
+ * @return
+ */
+ public Wildcards getWildcardObj() {
+ return Wildcards.of(wildcards);
+ }
+
+ /**
+ * Set wildcards
+ *
+ * @param wildcards
+ */
+ public OFMatch setWildcards(int wildcards) {
+ this.wildcards = wildcards;
+ return this;
+ }
+
+ /** set the wildcard using the Wildcards convenience object */
+ public OFMatch setWildcards(Wildcards wildcards) {
+ this.wildcards = wildcards.getInt();
+ return this;
+ }
+
+ /**
+ * Initializes this OFMatch structure with the corresponding data from the
+ * specified packet. Must specify the input port, to ensure that
+ * this.in_port is set correctly. Specify OFPort.NONE or OFPort.ANY if input
+ * port not applicable or available
+ *
+ * @param packetData
+ * The packet's data
+ * @param inputPort
+ * the port the packet arrived on
+ */
+ public OFMatch loadFromPacket(byte[] packetData, short inputPort) {
+ short scratch;
+ int transportOffset = 34;
+ ByteBuffer packetDataBB = ByteBuffer.wrap(packetData);
+ int limit = packetDataBB.limit();
+
+ this.wildcards = 0; // all fields have explicit entries
+
+ this.inputPort = inputPort;
+
+ if (inputPort == OFPort.OFPP_ALL.getValue())
+ this.wildcards |= OFPFW_IN_PORT;
+
+ assert (limit >= 14);
+ // dl dst
+ this.dataLayerDestination = new byte[6];
+ packetDataBB.get(this.dataLayerDestination);
+ // dl src
+ this.dataLayerSource = new byte[6];
+ packetDataBB.get(this.dataLayerSource);
+ // dl type
+ this.dataLayerType = packetDataBB.getShort();
+
+ if (getDataLayerType() != (short) 0x8100) { // need cast to avoid signed
+ // bug
+ setDataLayerVirtualLan((short) 0xffff);
+ setDataLayerVirtualLanPriorityCodePoint((byte) 0);
+ } else {
+ // has vlan tag
+ scratch = packetDataBB.getShort();
+ setDataLayerVirtualLan((short) (0xfff & scratch));
+ setDataLayerVirtualLanPriorityCodePoint((byte) ((0xe000 & scratch) >> 13));
+ this.dataLayerType = packetDataBB.getShort();
+ }
+
+ switch (getDataLayerType()) {
+ case 0x0800:
+ // ipv4
+ // check packet length
+ scratch = packetDataBB.get();
+ scratch = (short) (0xf & scratch);
+ transportOffset = (packetDataBB.position() - 1)
+ + (scratch * 4);
+ // nw tos (dscp)
+ scratch = packetDataBB.get();
+ setNetworkTypeOfService((byte) ((0xfc & scratch) >> 2));
+ // nw protocol
+ packetDataBB.position(packetDataBB.position() + 7);
+ this.networkProtocol = packetDataBB.get();
+ // nw src
+ packetDataBB.position(packetDataBB.position() + 2);
+ this.networkSource = packetDataBB.getInt();
+ // nw dst
+ this.networkDestination = packetDataBB.getInt();
+ packetDataBB.position(transportOffset);
+ break;
+ case 0x0806:
+ // arp
+ int arpPos = packetDataBB.position();
+ // opcode
+ scratch = packetDataBB.getShort(arpPos + 6);
+ setNetworkProtocol((byte) (0xff & scratch));
+
+ scratch = packetDataBB.getShort(arpPos + 2);
+ // if ipv4 and addr len is 4
+ if (scratch == 0x800 && packetDataBB.get(arpPos + 5) == 4) {
+ // nw src
+ this.networkSource = packetDataBB.getInt(arpPos + 14);
+ // nw dst
+ this.networkDestination = packetDataBB.getInt(arpPos + 24);
+ } else {
+ setNetworkSource(0);
+ setNetworkDestination(0);
+ }
+ break;
+ default:
+ setNetworkTypeOfService((byte) 0);
+ setNetworkProtocol((byte) 0);
+ setNetworkSource(0);
+ setNetworkDestination(0);
+ break;
+ }
+
+ switch (getNetworkProtocol()) {
+ case 0x01:
+ // icmp
+ // type
+ this.transportSource = U8.f(packetDataBB.get());
+ // code
+ this.transportDestination = U8.f(packetDataBB.get());
+ break;
+ case 0x06:
+ // tcp
+ // tcp src
+ this.transportSource = packetDataBB.getShort();
+ // tcp dest
+ this.transportDestination = packetDataBB.getShort();
+ break;
+ case 0x11:
+ // udp
+ // udp src
+ this.transportSource = packetDataBB.getShort();
+ // udp dest
+ this.transportDestination = packetDataBB.getShort();
+ break;
+ default:
+ setTransportDestination((short) 0);
+ setTransportSource((short) 0);
+ break;
+ }
+ return this;
+ }
+
+ /**
+ * Read this message off the wire from the specified ByteBuffer
+ *
+ * @param data
+ */
+ public void readFrom(ChannelBuffer data) {
+ this.wildcards = data.readInt();
+ this.inputPort = data.readShort();
+ this.dataLayerSource = new byte[6];
+ data.readBytes(this.dataLayerSource);
+ this.dataLayerDestination = new byte[6];
+ data.readBytes(this.dataLayerDestination);
+ this.dataLayerVirtualLan = data.readShort();
+ this.dataLayerVirtualLanPriorityCodePoint = data.readByte();
+ data.readByte(); // pad
+ this.dataLayerType = data.readShort();
+ this.networkTypeOfService = data.readByte();
+ this.networkProtocol = data.readByte();
+ data.readByte(); // pad
+ data.readByte(); // pad
+ this.networkSource = data.readInt();
+ this.networkDestination = data.readInt();
+ this.transportSource = data.readShort();
+ this.transportDestination = data.readShort();
+ }
+
+ /**
+ * Write this message's binary format to the specified ByteBuffer
+ *
+ * @param data
+ */
+ public void writeTo(ChannelBuffer data) {
+ data.writeInt(wildcards);
+ data.writeShort(inputPort);
+ data.writeBytes(this.dataLayerSource);
+ data.writeBytes(this.dataLayerDestination);
+ data.writeShort(dataLayerVirtualLan);
+ data.writeByte(dataLayerVirtualLanPriorityCodePoint);
+ data.writeByte((byte) 0x0); // pad
+ data.writeShort(dataLayerType);
+ data.writeByte(networkTypeOfService);
+ data.writeByte(networkProtocol);
+ data.writeByte((byte) 0x0); // pad
+ data.writeByte((byte) 0x0); // pad
+ data.writeInt(networkSource);
+ data.writeInt(networkDestination);
+ data.writeShort(transportSource);
+ data.writeShort(transportDestination);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 131;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(dataLayerDestination);
+ result = prime * result + Arrays.hashCode(dataLayerSource);
+ result = prime * result + dataLayerType;
+ result = prime * result + dataLayerVirtualLan;
+ result = prime * result + dataLayerVirtualLanPriorityCodePoint;
+ result = prime * result + inputPort;
+ result = prime * result + networkDestination;
+ result = prime * result + networkProtocol;
+ result = prime * result + networkSource;
+ result = prime * result + networkTypeOfService;
+ result = prime * result + transportDestination;
+ result = prime * result + transportSource;
+ result = prime * result + wildcards;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFMatch)) {
+ return false;
+ }
+ OFMatch other = (OFMatch) obj;
+ if (!Arrays.equals(dataLayerDestination, other.dataLayerDestination)) {
+ return false;
+ }
+ if (!Arrays.equals(dataLayerSource, other.dataLayerSource)) {
+ return false;
+ }
+ if (dataLayerType != other.dataLayerType) {
+ return false;
+ }
+ if (dataLayerVirtualLan != other.dataLayerVirtualLan) {
+ return false;
+ }
+ if (dataLayerVirtualLanPriorityCodePoint != other.dataLayerVirtualLanPriorityCodePoint) {
+ return false;
+ }
+ if (inputPort != other.inputPort) {
+ return false;
+ }
+ if (networkDestination != other.networkDestination) {
+ return false;
+ }
+ if (networkProtocol != other.networkProtocol) {
+ return false;
+ }
+ if (networkSource != other.networkSource) {
+ return false;
+ }
+ if (networkTypeOfService != other.networkTypeOfService) {
+ return false;
+ }
+ if (transportDestination != other.transportDestination) {
+ return false;
+ }
+ if (transportSource != other.transportSource) {
+ return false;
+ }
+ if ((wildcards & OFMatch.OFPFW_ALL) != (other.wildcards & OFPFW_ALL)) { // only
+ // consider
+ // allocated
+ // part
+ // of
+ // wildcards
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Implement clonable interface
+ */
+ @Override
+ public OFMatch clone() {
+ try {
+ OFMatch ret = (OFMatch) super.clone();
+ ret.dataLayerDestination = this.dataLayerDestination.clone();
+ ret.dataLayerSource = this.dataLayerSource.clone();
+ return ret;
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Output a dpctl-styled string, i.e., only list the elements that are not
+ * wildcarded A match-everything OFMatch outputs "OFMatch[]"
+ *
+ * @return
+ * "OFMatch[dl_src:00:20:01:11:22:33,nw_src:192.168.0.0/24,tp_dst:80]"
+ */
+ @Override
+ public String toString() {
+ String str = "";
+
+ // l1
+ if ((wildcards & OFPFW_IN_PORT) == 0)
+ str += "," + STR_IN_PORT + "="
+ + U16.f(this.inputPort);
+
+ // l2
+ if ((wildcards & OFPFW_DL_DST) == 0)
+ str += ","
+ + STR_DL_DST
+ + "="
+ + HexString.toHexString(this.dataLayerDestination);
+ if ((wildcards & OFPFW_DL_SRC) == 0)
+ str += ","
+ + STR_DL_SRC
+ + "="
+ + HexString.toHexString(this.dataLayerSource);
+ if ((wildcards & OFPFW_DL_TYPE) == 0)
+ str += ","
+ + STR_DL_TYPE
+ + "=0x"
+ + Integer.toHexString(U16.f(this.dataLayerType));
+ if ((wildcards & OFPFW_DL_VLAN) == 0)
+ str += ","
+ + STR_DL_VLAN
+ + "=0x"
+ + Integer.toHexString(U16.f(this.dataLayerVirtualLan));
+ if ((wildcards & OFPFW_DL_VLAN_PCP) == 0)
+ str += ","
+ + STR_DL_VLAN_PCP
+ + "="
+ + Integer.toHexString(U8.f(this.dataLayerVirtualLanPriorityCodePoint));
+
+ // l3
+ if (getNetworkDestinationMaskLen() > 0)
+ str += ","
+ + STR_NW_DST
+ + "="
+ + cidrToString(networkDestination,
+ getNetworkDestinationMaskLen());
+ if (getNetworkSourceMaskLen() > 0)
+ str += ","
+ + STR_NW_SRC
+ + "="
+ + cidrToString(networkSource,
+ getNetworkSourceMaskLen());
+ if ((wildcards & OFPFW_NW_PROTO) == 0)
+ str += "," + STR_NW_PROTO
+ + "="
+ + this.networkProtocol;
+ if ((wildcards & OFPFW_NW_TOS) == 0)
+ str += ","
+ + STR_NW_TOS
+ + "="
+ + this.getNetworkTypeOfService();
+
+ // l4
+ if ((wildcards & OFPFW_TP_DST) == 0)
+ str += ","
+ + STR_TP_DST
+ + "="
+ + this.transportDestination;
+ if ((wildcards & OFPFW_TP_SRC) == 0)
+ str += "," + STR_TP_SRC + "="
+ + this.transportSource;
+ if ((str.length() > 0) && (str.charAt(0) == ','))
+ str = str.substring(1); // trim
+ // the
+ // leading
+ // ","
+ // done
+ return "OFMatch[" + str + "]";
+ }
+
+ /**
+ * debug a set of wildcards
+ */
+ public static String debugWildCards(int wildcards) {
+ String str = "";
+
+ // l1
+ if ((wildcards & OFPFW_IN_PORT) != 0) str += "|" + STR_IN_PORT;
+
+ // l2
+ if ((wildcards & OFPFW_DL_DST) != 0) str += "|" + STR_DL_DST;
+ if ((wildcards & OFPFW_DL_SRC) != 0) str += "|" + STR_DL_SRC;
+ if ((wildcards & OFPFW_DL_TYPE) != 0) str += "|" + STR_DL_TYPE;
+ if ((wildcards & OFPFW_DL_VLAN) != 0) str += "|" + STR_DL_VLAN;
+ if ((wildcards & OFPFW_DL_VLAN_PCP) != 0)
+ str += "|"
+ + STR_DL_VLAN_PCP;
+
+ int nwDstMask = Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+ 0);
+ int nwSrcMask = Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+ 0);
+
+ // l3
+ if (nwDstMask < 32)
+ str += "|" + STR_NW_DST + "(/" + nwDstMask + ")";
+
+ if (nwSrcMask < 32)
+ str += "|" + STR_NW_SRC + "(/" + nwSrcMask + ")";
+
+ if ((wildcards & OFPFW_NW_PROTO) != 0) str += "|" + STR_NW_PROTO;
+ if ((wildcards & OFPFW_NW_TOS) != 0) str += "|" + STR_NW_TOS;
+
+ // l4
+ if ((wildcards & OFPFW_TP_DST) != 0) str += "|" + STR_TP_DST;
+ if ((wildcards & OFPFW_TP_SRC) != 0) str += "|" + STR_TP_SRC;
+ if ((str.length() > 0) && (str.charAt(0) == '|'))
+ str = str.substring(1); // trim
+ // the
+ // leading
+ // ","
+ // done
+ return str;
+ }
+
+ private String cidrToString(int ip, int prefix) {
+ String str;
+ if (prefix >= 32) {
+ str = ipToString(ip);
+ } else {
+ // use the negation of mask to fake endian magic
+ int mask = ~((1 << (32 - prefix)) - 1);
+ str = ipToString(ip & mask) + "/" + prefix;
+ }
+
+ return str;
+ }
+
+ /**
+ * Set this OFMatch's parameters based on a comma-separated key=value pair
+ * dpctl-style string, e.g., from the output of OFMatch.toString() <br>
+ * <p>
+ * Supported keys/values include <br>
+ * <p>
+ * <TABLE border=1>
+ * <TR>
+ * <TD>KEY(s)
+ * <TD>VALUE
+ * </TR>
+ * <TR>
+ * <TD>"in_port","input_port"
+ * <TD>integer
+ * </TR>
+ * <TR>
+ * <TD>"dl_src","eth_src", "dl_dst","eth_dst"
+ * <TD>hex-string
+ * </TR>
+ * <TR>
+ * <TD>"dl_type", "dl_vlan", "dl_vlan_pcp"
+ * <TD>integer
+ * </TR>
+ * <TR>
+ * <TD>"nw_src", "nw_dst", "ip_src", "ip_dst"
+ * <TD>CIDR-style netmask
+ * </TR>
+ * <TR>
+ * <TD>"tp_src","tp_dst"
+ * <TD>integer (max 64k)
+ * </TR>
+ * </TABLE>
+ * <p>
+ * The CIDR-style netmasks assume 32 netmask if none given, so:
+ * "128.8.128.118/32" is the same as "128.8.128.118"
+ *
+ * @param match
+ * a key=value comma separated string, e.g.
+ * "in_port=5,ip_dst=192.168.0.0/16,tp_src=80"
+ * @throws IllegalArgumentException
+ * on unexpected key or value
+ */
+
+ public void fromString(String match) throws IllegalArgumentException {
+ if (match.equals("") || match.equalsIgnoreCase("any")
+ || match.equalsIgnoreCase("all") || match.equals("[]"))
+ match = "OFMatch[]";
+ String[] tokens = match.split("[\\[,\\]]");
+ String[] values;
+ int initArg = 0;
+ if (tokens[0].equals("OFMatch")) initArg = 1;
+ this.wildcards = OFPFW_ALL;
+ int i;
+ for (i = initArg; i < tokens.length; i++) {
+ values = tokens[i].split("=");
+ if (values.length != 2)
+ throw new IllegalArgumentException(
+ "Token "
+ + tokens[i]
+ + " does not have form 'key=value' parsing "
+ + match);
+ values[0] = values[0].toLowerCase(); // try to make this case insens
+ if (values[0].equals(STR_IN_PORT)
+ || values[0].equals("input_port")) {
+ this.inputPort = U16.t(Integer.valueOf(values[1]));
+ this.wildcards &= ~OFPFW_IN_PORT;
+ } else if (values[0].equals(STR_DL_DST)
+ || values[0].equals("eth_dst")) {
+ this.dataLayerDestination = HexString.fromHexString(values[1]);
+ this.wildcards &= ~OFPFW_DL_DST;
+ } else if (values[0].equals(STR_DL_SRC)
+ || values[0].equals("eth_src")) {
+ this.dataLayerSource = HexString.fromHexString(values[1]);
+ this.wildcards &= ~OFPFW_DL_SRC;
+ } else if (values[0].equals(STR_DL_TYPE)
+ || values[0].equals("eth_type")) {
+ if (values[1].startsWith("0x"))
+ this.dataLayerType = U16.t(Integer.valueOf(values[1].replaceFirst("0x",
+ ""),
+ 16));
+ else
+ this.dataLayerType = U16.t(Integer.valueOf(values[1]));
+ this.wildcards &= ~OFPFW_DL_TYPE;
+ } else if (values[0].equals(STR_DL_VLAN)) {
+ if (values[1].startsWith("0x"))
+ this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1].replaceFirst("0x",
+ ""),
+ 16));
+ else
+ this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1]));
+ this.wildcards &= ~OFPFW_DL_VLAN;
+ } else if (values[0].equals(STR_DL_VLAN_PCP)) {
+ this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short.valueOf(values[1]));
+ this.wildcards &= ~OFPFW_DL_VLAN_PCP;
+ } else if (values[0].equals(STR_NW_DST)
+ || values[0].equals("ip_dst")) {
+ setFromCIDR(values[1], STR_NW_DST);
+ } else if (values[0].equals(STR_NW_SRC)
+ || values[0].equals("ip_src")) {
+ setFromCIDR(values[1], STR_NW_SRC);
+ } else if (values[0].equals(STR_NW_PROTO)) {
+ if (values[1].startsWith("0x"))
+ this.networkProtocol = U8.t(Short.valueOf(values[1].replaceFirst("0x",""),16));
+ else
+ this.networkProtocol = U8.t(Short.valueOf(values[1]));
+ this.wildcards &= ~OFPFW_NW_PROTO;
+ } else if (values[0].equals(STR_NW_TOS)) {
+ this.setNetworkTypeOfService(U8.t(Short.valueOf(values[1])));
+ this.wildcards &= ~OFPFW_NW_TOS;
+ } else if (values[0].equals(STR_TP_DST)) {
+ this.transportDestination = U16.t(Integer.valueOf(values[1]));
+ this.wildcards &= ~OFPFW_TP_DST;
+ } else if (values[0].equals(STR_TP_SRC)) {
+ this.transportSource = U16.t(Integer.valueOf(values[1]));
+ this.wildcards &= ~OFPFW_TP_SRC;
+ } else {
+ throw new IllegalArgumentException("unknown token "
+ + tokens[i] + " parsing "
+ + match);
+ }
+ }
+ }
+
+ /**
+ * Set the networkSource or networkDestionation address and their wildcards
+ * from the CIDR string
+ *
+ * @param cidr
+ * "192.168.0.0/16" or "172.16.1.5"
+ * @param which
+ * one of STR_NW_DST or STR_NW_SRC
+ * @throws IllegalArgumentException
+ */
+ private
+ void
+ setFromCIDR(String cidr, String which)
+ throws IllegalArgumentException {
+ String values[] = cidr.split("/");
+ String[] ip_str = values[0].split("\\.");
+ int ip = 0;
+ ip += Integer.valueOf(ip_str[0]) << 24;
+ ip += Integer.valueOf(ip_str[1]) << 16;
+ ip += Integer.valueOf(ip_str[2]) << 8;
+ ip += Integer.valueOf(ip_str[3]);
+ int prefix = 32; // all bits are fixed, by default
+
+ if (values.length >= 2) prefix = Integer.valueOf(values[1]);
+ int mask = 32 - prefix;
+ if (which.equals(STR_NW_DST)) {
+ this.networkDestination = ip;
+ this.wildcards = (wildcards & ~OFPFW_NW_DST_MASK)
+ | (mask << OFPFW_NW_DST_SHIFT);
+ } else if (which.equals(STR_NW_SRC)) {
+ this.networkSource = ip;
+ this.wildcards = (wildcards & ~OFPFW_NW_SRC_MASK)
+ | (mask << OFPFW_NW_SRC_SHIFT);
+ }
+ }
+
+ protected static String ipToString(int ip) {
+ return Integer.toString(U8.f((byte) ((ip & 0xff000000) >> 24)))
+ + "." + Integer.toString((ip & 0x00ff0000) >> 16) + "."
+ + Integer.toString((ip & 0x0000ff00) >> 8) + "."
+ + Integer.toString(ip & 0x000000ff);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.beans.SimpleBeanInfo;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Extra info for how to treat OFMatch as a JavaBean
+ *
+ * For some (inane!) reason, using chained setters in OFMatch breaks a lot of the JavaBean defaults.
+ *
+ * We don't really use OFMatch as a java bean, but there are a lot of nice XML utils that work for
+ * free if OFMatch follows the java bean paradigm.
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ *
+ */
+
+public class OFMatchBeanInfo extends SimpleBeanInfo {
+
+ @Override
+ public PropertyDescriptor[] getPropertyDescriptors() {
+ List<PropertyDescriptor> descs = new LinkedList<PropertyDescriptor>();
+ Field[] fields = OFMatch.class.getDeclaredFields();
+ String name;
+ for (int i=0; i< fields.length; i++) {
+ int mod = fields[i].getModifiers();
+ if(Modifier.isFinal(mod) || // don't expose static or final fields
+ Modifier.isStatic(mod))
+ continue;
+
+ name = fields[i].getName();
+ Class<?> type = fields[i].getType();
+
+ try {
+ descs.add(new PropertyDescriptor(name,
+ name2getter(OFMatch.class, name),
+ name2setter(OFMatch.class, name, type)));
+ } catch (IntrospectionException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ return descs.toArray(new PropertyDescriptor[0]);
+ }
+
+
+ private Method name2setter(Class<OFMatch> c, String name, Class<?> type) {
+ String mName = "set" + toLeadingCaps(name);
+ Method m = null;
+ try {
+ m = c.getMethod(mName, new Class[]{ type});
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ return m;
+ }
+
+ private Method name2getter(Class<OFMatch> c, String name) {
+ String mName= "get" + toLeadingCaps(name);
+ Method m = null;
+ try {
+ m = c.getMethod(mName, new Class[]{});
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ return m;
+ }
+
+ private String toLeadingCaps(String s) {
+ char[] array = s.toCharArray();
+ array[0] = Character.toUpperCase(array[0]);
+ return String.valueOf(array, 0, array.length);
+ }
+}
--- /dev/null
+/**
+ * Copyright 2013, Big Switch Networks, Inc.
+ *
+ * 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 org.openflow.protocol;
+
+import org.openflow.util.HexString;
+
+public class OFMatchWithSwDpid {
+ protected OFMatch ofMatch;
+ protected long switchDataPathId;
+
+ public OFMatchWithSwDpid() {
+ this.ofMatch = new OFMatch();
+ this.switchDataPathId = 0;
+ }
+
+ public OFMatchWithSwDpid(OFMatch ofm, long swDpid) {
+ this.ofMatch = ofm.clone();
+ this.switchDataPathId = swDpid;
+ }
+ public OFMatch getOfMatch() {
+ return ofMatch;
+ }
+
+ public void setOfMatch(OFMatch ofMatch) {
+ this.ofMatch = ofMatch.clone();
+ }
+
+ public long getSwitchDataPathId() {
+ return this.switchDataPathId;
+ }
+
+ public OFMatchWithSwDpid setSwitchDataPathId(long dpid) {
+ this.switchDataPathId = dpid;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "OFMatchWithSwDpid [" + HexString.toHexString(switchDataPathId) + ofMatch + "]";
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.HexString;
+import org.openflow.util.U16;
+import org.openflow.util.U32;
+import org.openflow.util.U8;
+
+/**
+ * The base class for all OpenFlow protocol messages. This class contains the
+ * equivalent of the ofp_header which is present in all OpenFlow messages.
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 3, 2010
+ * @author Rob Sherwood (rob.sherwood@stanford.edu) - Feb 3, 2010
+ */
+public class OFMessage {
+ public static final int MAXIMUM_LENGTH = (1 << 16) - 1;
+ public static byte OFP_VERSION = 0x01;
+ public static int MINIMUM_LENGTH = 8;
+
+ protected byte version;
+ protected OFType type;
+ protected short length;
+ protected int xid;
+
+ private ConcurrentHashMap<String, Object> storage;
+
+ public OFMessage() {
+ storage = null;
+ this.version = OFP_VERSION;
+ }
+
+ protected synchronized ConcurrentHashMap<String, Object> getMessageStore() {
+ if (storage == null) {
+ storage = new ConcurrentHashMap<String, Object>();;
+ }
+ return storage;
+ }
+
+ /**
+ * Get the length of this message
+ *
+ * @return
+ */
+ public short getLength() {
+ return length;
+ }
+
+ /**
+ * Get the length of this message, unsigned
+ *
+ * @return
+ */
+ public int getLengthU() {
+ return U16.f(length);
+ }
+
+ /**
+ * Set the length of this message
+ *
+ * @param length
+ */
+ public OFMessage setLength(short length) {
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Set the length of this message, unsigned
+ *
+ * @param length
+ */
+ public OFMessage setLengthU(int length) {
+ this.length = U16.t(length);
+ return this;
+ }
+
+ /**
+ * Get the type of this message
+ *
+ * @return
+ */
+ public OFType getType() {
+ return type;
+ }
+
+ /**
+ * Set the type of this message
+ *
+ * @param type
+ */
+ public void setType(OFType type) {
+ this.type = type;
+ }
+
+ /**
+ * Get the OpenFlow version of this message
+ *
+ * @return
+ */
+ public byte getVersion() {
+ return version;
+ }
+
+ /**
+ * Set the OpenFlow version of this message
+ *
+ * @param version
+ */
+ public void setVersion(byte version) {
+ this.version = version;
+ }
+
+ /**
+ * Get the transaction id of this message
+ *
+ * @return
+ */
+ public int getXid() {
+ return xid;
+ }
+
+ /**
+ * Set the transaction id of this message
+ *
+ * @param xid
+ */
+ public void setXid(int xid) {
+ this.xid = xid;
+ }
+
+ /**
+ * Read this message off the wire from the specified ByteBuffer
+ * @param data
+ */
+ public void readFrom(ChannelBuffer data) {
+ this.version = data.readByte();
+ this.type = OFType.valueOf(data.readByte());
+ this.length = data.readShort();
+ this.xid = data.readInt();
+ }
+
+ /**
+ * Write this message's binary format to the specified ByteBuffer
+ * @param data
+ */
+ public void writeTo(ChannelBuffer data) {
+ data.writeByte(version);
+ data.writeByte(type.getTypeValue());
+ data.writeShort(length);
+ data.writeInt(xid);
+ }
+
+ /**
+ * Returns a summary of the message
+ * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid"
+ */
+ @Override
+ public String toString() {
+ return "ofmsg" +
+ ":v=" + U8.f(this.getVersion()) +
+ ";t=" + this.getType() +
+ ";l=" + this.getLengthU() +
+ ";x=" + U32.f(this.getXid());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 97;
+ int result = 1;
+ result = prime * result + length;
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + version;
+ result = prime * result + xid;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFMessage)) {
+ return false;
+ }
+ OFMessage other = (OFMessage) obj;
+ if (length != other.length) {
+ return false;
+ }
+ if (type == null) {
+ if (other.type != null) {
+ return false;
+ }
+ } else if (!type.equals(other.type)) {
+ return false;
+ }
+ if (version != other.version) {
+ return false;
+ }
+ if (xid != other.xid) {
+ return false;
+ }
+ return true;
+ }
+
+ /*
+ public static String getDataAsString(IOFSwitch sw, OFMessage msg) {
+
+
+ Ethernet eth;
+ StringBuffer sb = new StringBuffer("");
+
+ DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+ Date date = new Date();
+
+ sb.append(dateFormat.format(date));
+ sb.append(" ");
+
+ switch (msg.getType()) {
+ case PACKET_IN:
+ OFPacketIn pktIn = (OFPacketIn) msg;
+ sb.append("packet_in [ ");
+ sb.append(sw.getStringId());
+ sb.append(" -> Controller");
+ sb.append(" ]");
+
+ sb.append("\ntotal length: ");
+ sb.append(pktIn.getTotalLength());
+ sb.append("\nin_port: ");
+ sb.append(pktIn.getInPort());
+ sb.append("\ndata_length: ");
+ sb.append(pktIn.getTotalLength() - OFPacketIn.MINIMUM_LENGTH);
+ sb.append("\nbuffer: ");
+ sb.append(pktIn.getBufferId());
+
+ break;
+
+ case PACKET_OUT:
+ OFPacketOut pktOut = (OFPacketOut) msg;
+ sb.append("packet_out [ ");
+ sb.append("Controller -> ");
+ sb.append(HexString.toHexString(sw.getId()));
+ sb.append(" ]");
+
+ sb.append("\nin_port: ");
+ sb.append(pktOut.getInPort());
+ sb.append("\nactions_len: ");
+ sb.append(pktOut.getActionsLength());
+ if (pktOut.getActions() != null) {
+ sb.append("\nactions: ");
+ sb.append(pktOut.getActions().toString());
+ }
+ break;
+
+ case FLOW_MOD:
+ OFFlowMod fm = (OFFlowMod) msg;
+ sb.append("flow_mod [ ");
+ sb.append("Controller -> ");
+ sb.append(HexString.toHexString(sw.getId()));
+ sb.append(" ]");
+
+
+ sb.append("\nADD: cookie: ");
+ sb.append(fm.getCookie());
+ sb.append(" idle: ");
+ sb.append(fm.getIdleTimeout());
+ sb.append(" hard: ");
+ sb.append(fm.getHardTimeout());
+ sb.append(" pri: ");
+ sb.append(fm.getPriority());
+ sb.append(" buf: ");
+ sb.append(fm.getBufferId());
+ sb.append(" flg: ");
+ sb.append(fm.getFlags());
+ if (fm.getActions() != null) {
+ sb.append("\nactions: ");
+ sb.append(fm.getActions().toString());
+ }
+ break;
+
+ default:
+ sb.append("[Unknown Packet]");
+ }
+
+ sb.append("\n\n");
+ return sb.toString();
+
+ }
+ */
+
+
+ // Check if this is really required
+ /*
+ public static byte[] getData(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+ return OFMessage.getDataAsString(sw, msg, cntx).getBytes();
+ }
+ */
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.protocol.OFMessage;
+
+public class OFMessageContextStore<V> {
+ protected OFMessage msg;
+ String namespace;
+
+ public OFMessageContextStore(OFMessage msg, String namespace) {
+ this.msg = msg;
+ this.namespace = namespace;
+ }
+
+ @SuppressWarnings("unchecked")
+ public V get(String key) {
+ return (V)msg.getMessageStore().get(namespace + "|" + key);
+ }
+
+ public void put(String key, V value) {
+ msg.getMessageStore().put(namespace + "|" + key, value);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+import org.openflow.util.U32;
+import org.openflow.util.U8;
+
+/**
+ * Represents an ofp_packet_in
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 8, 2010
+ */
+public class OFPacketIn extends OFMessage {
+ public static short MINIMUM_LENGTH = 18;
+
+ public enum OFPacketInReason {
+ NO_MATCH, ACTION
+ }
+
+ protected int bufferId;
+ protected short totalLength;
+ protected short inPort;
+ protected OFPacketInReason reason;
+ protected byte[] packetData;
+
+ public OFPacketIn() {
+ super();
+ this.type = OFType.PACKET_IN;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * Get buffer_id
+ * @return
+ */
+ public int getBufferId() {
+ return this.bufferId;
+ }
+
+ /**
+ * Set buffer_id
+ * @param bufferId
+ */
+ public OFPacketIn setBufferId(int bufferId) {
+ this.bufferId = bufferId;
+ return this;
+ }
+
+ /**
+ * Returns the packet data
+ * @return
+ */
+ public byte[] getPacketData() {
+ return this.packetData;
+ }
+
+ /**
+ * Sets the packet data, and updates the length of this message
+ * @param packetData
+ */
+ public OFPacketIn setPacketData(byte[] packetData) {
+ this.packetData = packetData;
+ this.length = U16.t(OFPacketIn.MINIMUM_LENGTH + packetData.length);
+ return this;
+ }
+
+ /**
+ * Get in_port
+ * @return
+ */
+ public short getInPort() {
+ return this.inPort;
+ }
+
+ /**
+ * Set in_port
+ * @param inPort
+ */
+ public OFPacketIn setInPort(short inPort) {
+ this.inPort = inPort;
+ return this;
+ }
+
+ /**
+ * Get reason
+ * @return
+ */
+ public OFPacketInReason getReason() {
+ return this.reason;
+ }
+
+ /**
+ * Set reason
+ * @param reason
+ */
+ public OFPacketIn setReason(OFPacketInReason reason) {
+ this.reason = reason;
+ return this;
+ }
+
+ /**
+ * Get total_len
+ * @return
+ */
+ public short getTotalLength() {
+ return this.totalLength;
+ }
+
+ /**
+ * Set total_len
+ * @param totalLength
+ */
+ public OFPacketIn setTotalLength(short totalLength) {
+ this.totalLength = totalLength;
+ return this;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.bufferId = data.readInt();
+ this.totalLength = data.readShort();
+ this.inPort = data.readShort();
+ this.reason = OFPacketInReason.values()[U8.f(data.readByte())];
+ data.readByte(); // pad
+ this.packetData = new byte[getLengthU() - MINIMUM_LENGTH];
+ data.readBytes(this.packetData);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeInt(bufferId);
+ data.writeShort(totalLength);
+ data.writeShort(inPort);
+ data.writeByte((byte) reason.ordinal());
+ data.writeByte((byte) 0x0); // pad
+ data.writeBytes(this.packetData);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 283;
+ int result = super.hashCode();
+ result = prime * result + bufferId;
+ result = prime * result + inPort;
+ result = prime * result + Arrays.hashCode(packetData);
+ result = prime * result + ((reason == null) ? 0 : reason.hashCode());
+ result = prime * result + totalLength;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFPacketIn)) {
+ return false;
+ }
+ OFPacketIn other = (OFPacketIn) obj;
+ if (bufferId != other.bufferId) {
+ return false;
+ }
+ if (inPort != other.inPort) {
+ return false;
+ }
+ if (!Arrays.equals(packetData, other.packetData)) {
+ return false;
+ }
+ if (reason == null) {
+ if (other.reason != null) {
+ return false;
+ }
+ } else if (!reason.equals(other.reason)) {
+ return false;
+ }
+ if (totalLength != other.totalLength) {
+ return false;
+ }
+ return true;
+ }
+
+ public String toString() {
+ String myStr = super.toString();
+ return "packetIn" +
+ ":bufferId=" + U32.f(this.bufferId) + myStr;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.factory.OFActionFactory;
+import org.openflow.protocol.factory.OFActionFactoryAware;
+import org.openflow.util.HexString;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_packet_out message
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 12, 2010
+ */
+public class OFPacketOut extends OFMessage implements OFActionFactoryAware {
+ public static int MINIMUM_LENGTH = 16;
+ public static int BUFFER_ID_NONE = 0xffffffff;
+
+ protected OFActionFactory actionFactory;
+ protected int bufferId;
+ protected short inPort;
+ protected short actionsLength;
+ protected List<OFAction> actions;
+ protected byte[] packetData;
+
+ public OFPacketOut() {
+ super();
+ this.type = OFType.PACKET_OUT;
+ this.length = U16.t(MINIMUM_LENGTH);
+ this.bufferId = BUFFER_ID_NONE;
+ }
+
+ /**
+ * Get buffer_id
+ * @return
+ */
+ public int getBufferId() {
+ return this.bufferId;
+ }
+
+ /**
+ * Set buffer_id
+ * @param bufferId
+ */
+ public OFPacketOut setBufferId(int bufferId) {
+ if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) {
+ throw new IllegalArgumentException(
+ "PacketOut should not have both bufferId and packetData set");
+ }
+ this.bufferId = bufferId;
+ return this;
+ }
+
+ /**
+ * Returns the packet data
+ * @return
+ */
+ public byte[] getPacketData() {
+ return this.packetData;
+ }
+
+ /**
+ * Sets the packet data
+ * @param packetData
+ */
+ public OFPacketOut setPacketData(byte[] packetData) {
+ if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) {
+ throw new IllegalArgumentException(
+ "PacketOut should not have both bufferId and packetData set");
+ }
+ this.packetData = packetData;
+ return this;
+ }
+
+ /**
+ * Get in_port
+ * @return
+ */
+ public short getInPort() {
+ return this.inPort;
+ }
+
+ /**
+ * Set in_port
+ * @param inPort
+ */
+ public OFPacketOut setInPort(short inPort) {
+ this.inPort = inPort;
+ return this;
+ }
+
+ /**
+ * Set in_port. Convenience method using OFPort enum.
+ * @param inPort
+ */
+ public OFPacketOut setInPort(OFPort inPort) {
+ this.inPort = inPort.getValue();
+ return this;
+ }
+
+ /**
+ * Get actions_len
+ * @return
+ */
+ public short getActionsLength() {
+ return this.actionsLength;
+ }
+
+ /**
+ * Get actions_len, unsigned
+ * @return
+ */
+ public int getActionsLengthU() {
+ return U16.f(this.actionsLength);
+ }
+
+ /**
+ * Set actions_len
+ * @param actionsLength
+ */
+ public OFPacketOut setActionsLength(short actionsLength) {
+ this.actionsLength = actionsLength;
+ return this;
+ }
+
+ /**
+ * Returns the actions contained in this message
+ * @return a list of ordered OFAction objects
+ */
+ public List<OFAction> getActions() {
+ return this.actions;
+ }
+
+ /**
+ * Sets the list of actions on this message
+ * @param actions a list of ordered OFAction objects
+ */
+ public OFPacketOut setActions(List<OFAction> actions) {
+ this.actions = actions;
+ return this;
+ }
+
+ @Override
+ public void setActionFactory(OFActionFactory actionFactory) {
+ this.actionFactory = actionFactory;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.bufferId = data.readInt();
+ this.inPort = data.readShort();
+ this.actionsLength = data.readShort();
+ if ( this.actionFactory == null)
+ throw new RuntimeException("ActionFactory not set");
+ this.actions = this.actionFactory.parseActions(data, getActionsLengthU());
+ this.packetData = new byte[getLengthU() - MINIMUM_LENGTH - getActionsLengthU()];
+ data.readBytes(this.packetData);
+ validate();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ validate();
+ super.writeTo(data);
+ data.writeInt(bufferId);
+ data.writeShort(inPort);
+ data.writeShort(actionsLength);
+ for (OFAction action : actions) {
+ action.writeTo(data);
+ }
+ if (this.packetData != null)
+ data.writeBytes(this.packetData);
+ }
+
+ /** validate the invariants of this OFMessage hold */
+ public void validate() {
+ if (!((bufferId != BUFFER_ID_NONE) ^ (packetData != null && packetData.length > 0))) {
+ throw new IllegalStateException(
+ "OFPacketOut must have exactly one of (bufferId, packetData) set (not one, not both)");
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 293;
+ int result = super.hashCode();
+ result = prime * result + ((actions == null) ? 0 : actions.hashCode());
+ result = prime * result + actionsLength;
+ result = prime * result + bufferId;
+ result = prime * result + inPort;
+ result = prime * result + Arrays.hashCode(packetData);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFPacketOut)) {
+ return false;
+ }
+ OFPacketOut other = (OFPacketOut) obj;
+ if (actions == null) {
+ if (other.actions != null) {
+ return false;
+ }
+ } else if (!actions.equals(other.actions)) {
+ return false;
+ }
+ if (actionsLength != other.actionsLength) {
+ return false;
+ }
+ if (bufferId != other.bufferId) {
+ return false;
+ }
+ if (inPort != other.inPort) {
+ return false;
+ }
+ if (!Arrays.equals(packetData, other.packetData)) {
+ return false;
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "OFPacketOut [actionFactory=" + actionFactory + ", actions="
+ + actions + ", actionsLength=" + actionsLength + ", bufferId=0x"
+ + Integer.toHexString(bufferId) + ", inPort=" + inPort + ", packetData="
+ + HexString.toHexString(packetData) + "]";
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.protocol;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * Represents ofp_packet_queue
+ * @author Andrew Ferguson (adf@cs.brown.edu)
+ */
+public class OFPacketQueue {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected int queueId;
+ protected short length;
+ protected List<OFQueueProp> properties = new ArrayList<OFQueueProp>();
+
+ public OFPacketQueue() {
+ this.queueId = -1;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ public OFPacketQueue(int queueId) {
+ this.queueId = queueId;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the queueId
+ */
+ public long getQueueId() {
+ return queueId;
+ }
+
+ /**
+ * @param queueId the queueId to set
+ */
+ public void setQueueId(int queueId) {
+ this.queueId = queueId;
+ }
+
+ /**
+ * @return the queue's properties
+ */
+ public List<OFQueueProp> getProperties() {
+ return properties;
+ }
+
+ /**
+ * @param properties the properties to set
+ */
+ public void setProperties(List<OFQueueProp> properties) {
+ this.properties = properties;
+
+ this.length = U16.t(MINIMUM_LENGTH);
+ for (OFQueueProp prop : properties) {
+ this.length += prop.getLength();
+ }
+ }
+
+ /**
+ * @return the length
+ */
+ public short getLength() {
+ return length;
+ }
+
+ public void readFrom(ChannelBuffer data) {
+ this.queueId = data.readInt();
+ this.length = data.readShort();
+ data.readShort(); // pad
+
+ int availLength = (this.length - MINIMUM_LENGTH);
+ this.properties.clear();
+
+ while (availLength > 0) {
+ OFQueueProp prop = new OFQueueProp();
+ prop.readFrom(data);
+ properties.add(prop);
+ availLength -= prop.getLength();
+ }
+ }
+
+ public void writeTo(ChannelBuffer data) {
+ data.writeInt(queueId);
+ data.writeShort(length);
+ data.writeShort(0); // pad
+
+ for (OFQueueProp prop : properties) {
+ prop.writeTo(data);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 359;
+ int result = super.hashCode();
+ result = prime * result + queueId;
+ result = prime * result + length;
+ result = prime * result + properties.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFPacketQueue)) {
+ return false;
+ }
+ OFPacketQueue other = (OFPacketQueue) obj;
+ if (queueId != other.queueId) {
+ return false;
+ }
+ if (! properties.equals(other.properties)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents ofp_phy_port
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 25, 2010
+ */
+public class OFPhysicalPort {
+ public static int MINIMUM_LENGTH = 48;
+ public static int OFP_ETH_ALEN = 6;
+
+ public enum OFPortConfig {
+ OFPPC_PORT_DOWN (1 << 0) {
+ public String toString() {
+ return "port-down (0x1)";
+ }
+ },
+ OFPPC_NO_STP (1 << 1) {
+ public String toString() {
+ return "no-stp (0x2)";
+ }
+ },
+ OFPPC_NO_RECV (1 << 2) {
+ public String toString() {
+ return "no-recv (0x4)";
+ }
+ },
+ OFPPC_NO_RECV_STP (1 << 3) {
+ public String toString() {
+ return "no-recv-stp (0x8)";
+ }
+ },
+ OFPPC_NO_FLOOD (1 << 4) {
+ public String toString() {
+ return "no-flood (0x10)";
+ }
+ },
+ OFPPC_NO_FWD (1 << 5) {
+ public String toString() {
+ return "no-fwd (0x20)";
+ }
+ },
+ OFPPC_NO_PACKET_IN (1 << 6) {
+ public String toString() {
+ return "no-pkt-in (0x40)";
+ }
+ };
+
+ protected int value;
+
+ private OFPortConfig(int value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+ }
+
+ public enum OFPortState {
+ OFPPS_LINK_DOWN (1 << 0) {
+ public String toString() {
+ return "link-down (0x1)";
+ }
+ },
+ OFPPS_STP_LISTEN (0 << 8) {
+ public String toString() {
+ return "listen (0x0)";
+ }
+ },
+ OFPPS_STP_LEARN (1 << 8) {
+ public String toString() {
+ return "learn-no-relay (0x100)";
+ }
+ },
+ OFPPS_STP_FORWARD (2 << 8) {
+ public String toString() {
+ return "forward (0x200)";
+ }
+ },
+ OFPPS_STP_BLOCK (3 << 8) {
+ public String toString() {
+ return "block-broadcast (0x300)";
+ }
+ },
+ OFPPS_STP_MASK (3 << 8) {
+ public String toString() {
+ return "block-broadcast (0x300)";
+ }
+ };
+
+ protected int value;
+
+ private OFPortState(int value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+ }
+
+ public enum OFPortFeatures {
+ OFPPF_10MB_HD (1 << 0) {
+ public String toString() {
+ return "10mb-hd (0x1)";
+ }
+ },
+ OFPPF_10MB_FD (1 << 1) {
+ public String toString() {
+ return "10mb-fd (0x2)";
+ }
+ },
+ OFPPF_100MB_HD (1 << 2) {
+ public String toString() {
+ return "100mb-hd (0x4)";
+ }
+ },
+ OFPPF_100MB_FD (1 << 3) {
+ public String toString() {
+ return "100mb-fd (0x8)";
+ }
+ },
+ OFPPF_1GB_HD (1 << 4) {
+ public String toString() {
+ return "1gb-hd (0x10)";
+ }
+ },
+ OFPPF_1GB_FD (1 << 5) {
+ public String toString() {
+ return "1gb-fd (0x20)";
+ }
+ },
+ OFPPF_10GB_FD (1 << 6) {
+ public String toString() {
+ return "10gb-fd (0x40)";
+ }
+ },
+ OFPPF_COPPER (1 << 7) {
+ public String toString() {
+ return "copper (0x80)";
+ }
+ },
+ OFPPF_FIBER (1 << 8) {
+ public String toString() {
+ return "fiber (0x100)";
+ }
+ },
+ OFPPF_AUTONEG (1 << 9) {
+ public String toString() {
+ return "autoneg (0x200)";
+ }
+ },
+ OFPPF_PAUSE (1 << 10) {
+ public String toString() {
+ return "pause (0x400)";
+ }
+ },
+ OFPPF_PAUSE_ASYM (1 << 11) {
+ public String toString() {
+ return "pause-asym (0x800)";
+ }
+ };
+
+ protected int value;
+
+ private OFPortFeatures(int value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+ }
+
+ protected short portNumber;
+ protected byte[] hardwareAddress;
+ protected String name;
+ protected int config;
+ protected int state;
+ protected int currentFeatures;
+ protected int advertisedFeatures;
+ protected int supportedFeatures;
+ protected int peerFeatures;
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ /**
+ * @return the hardwareAddress
+ */
+ public byte[] getHardwareAddress() {
+ return hardwareAddress;
+ }
+
+ /**
+ * @param hardwareAddress the hardwareAddress to set
+ */
+ public void setHardwareAddress(byte[] hardwareAddress) {
+ if (hardwareAddress.length != OFP_ETH_ALEN)
+ throw new RuntimeException("Hardware address must have length "
+ + OFP_ETH_ALEN);
+ this.hardwareAddress = hardwareAddress;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the config
+ */
+ public int getConfig() {
+ return config;
+ }
+
+ /**
+ * @param config the config to set
+ */
+ public void setConfig(int config) {
+ this.config = config;
+ }
+
+ /**
+ * @return the state
+ */
+ public int getState() {
+ return state;
+ }
+
+ /**
+ * @param state the state to set
+ */
+ public void setState(int state) {
+ this.state = state;
+ }
+
+ /**
+ * @return the currentFeatures
+ */
+ public int getCurrentFeatures() {
+ return currentFeatures;
+ }
+
+ /**
+ * @param currentFeatures the currentFeatures to set
+ */
+ public void setCurrentFeatures(int currentFeatures) {
+ this.currentFeatures = currentFeatures;
+ }
+
+ /**
+ * @return the advertisedFeatures
+ */
+ public int getAdvertisedFeatures() {
+ return advertisedFeatures;
+ }
+
+ /**
+ * @param advertisedFeatures the advertisedFeatures to set
+ */
+ public void setAdvertisedFeatures(int advertisedFeatures) {
+ this.advertisedFeatures = advertisedFeatures;
+ }
+
+ /**
+ * @return the supportedFeatures
+ */
+ public int getSupportedFeatures() {
+ return supportedFeatures;
+ }
+
+ /**
+ * @param supportedFeatures the supportedFeatures to set
+ */
+ public void setSupportedFeatures(int supportedFeatures) {
+ this.supportedFeatures = supportedFeatures;
+ }
+
+ /**
+ * @return the peerFeatures
+ */
+ public int getPeerFeatures() {
+ return peerFeatures;
+ }
+
+ /**
+ * @param peerFeatures the peerFeatures to set
+ */
+ public void setPeerFeatures(int peerFeatures) {
+ this.peerFeatures = peerFeatures;
+ }
+
+ /**
+ * Read this message off the wire from the specified ByteBuffer
+ * @param data
+ */
+ public void readFrom(ChannelBuffer data) {
+ this.portNumber = data.readShort();
+ if (this.hardwareAddress == null)
+ this.hardwareAddress = new byte[OFP_ETH_ALEN];
+ data.readBytes(this.hardwareAddress);
+ byte[] name = new byte[16];
+ data.readBytes(name);
+ // find the first index of 0
+ int index = 0;
+ for (byte b : name) {
+ if (0 == b)
+ break;
+ ++index;
+ }
+ this.name = new String(Arrays.copyOf(name, index),
+ Charset.forName("ascii"));
+ this.config = data.readInt();
+ this.state = data.readInt();
+ this.currentFeatures = data.readInt();
+ this.advertisedFeatures = data.readInt();
+ this.supportedFeatures = data.readInt();
+ this.peerFeatures = data.readInt();
+ }
+
+ /**
+ * Write this message's binary format to the specified ByteBuffer
+ * @param data
+ */
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(this.portNumber);
+ data.writeBytes(hardwareAddress);
+ try {
+ byte[] name = this.name.getBytes("ASCII");
+ if (name.length < 16) {
+ data.writeBytes(name);
+ for (int i = name.length; i < 16; ++i) {
+ data.writeByte((byte) 0);
+ }
+ } else {
+ data.writeBytes(name, 0, 15);
+ data.writeByte((byte) 0);
+ }
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ data.writeInt(this.config);
+ data.writeInt(this.state);
+ data.writeInt(this.currentFeatures);
+ data.writeInt(this.advertisedFeatures);
+ data.writeInt(this.supportedFeatures);
+ data.writeInt(this.peerFeatures);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 307;
+ int result = 1;
+ result = prime * result + advertisedFeatures;
+ result = prime * result + config;
+ result = prime * result + currentFeatures;
+ result = prime * result + Arrays.hashCode(hardwareAddress);
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + peerFeatures;
+ result = prime * result + portNumber;
+ result = prime * result + state;
+ result = prime * result + supportedFeatures;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFPhysicalPort)) {
+ return false;
+ }
+ OFPhysicalPort other = (OFPhysicalPort) obj;
+ if (advertisedFeatures != other.advertisedFeatures) {
+ return false;
+ }
+ if (config != other.config) {
+ return false;
+ }
+ if (currentFeatures != other.currentFeatures) {
+ return false;
+ }
+ if (!Arrays.equals(hardwareAddress, other.hardwareAddress)) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ if (peerFeatures != other.peerFeatures) {
+ return false;
+ }
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ if (state != other.state) {
+ return false;
+ }
+ if (supportedFeatures != other.supportedFeatures) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+public enum OFPort {
+ OFPP_MAX ((short)0xff00),
+ OFPP_IN_PORT ((short)0xfff8),
+ OFPP_TABLE ((short)0xfff9),
+ OFPP_NORMAL ((short)0xfffa),
+ OFPP_FLOOD ((short)0xfffb),
+ OFPP_ALL ((short)0xfffc),
+ OFPP_CONTROLLER ((short)0xfffd),
+ OFPP_LOCAL ((short)0xfffe),
+ OFPP_NONE ((short)0xffff);
+
+ protected short value;
+
+ private OFPort(short value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value
+ */
+ public short getValue() {
+ return value;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_port_mod message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFPortMod extends OFMessage {
+ public static int MINIMUM_LENGTH = 32;
+
+ protected short portNumber;
+ protected byte[] hardwareAddress;
+ protected int config;
+ protected int mask;
+ protected int advertise;
+
+ public OFPortMod() {
+ super();
+ this.type = OFType.PORT_MOD;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ /**
+ * @return the hardwareAddress
+ */
+ public byte[] getHardwareAddress() {
+ return hardwareAddress;
+ }
+
+ /**
+ * @param hardwareAddress the hardwareAddress to set
+ */
+ public void setHardwareAddress(byte[] hardwareAddress) {
+ if (hardwareAddress.length != OFPhysicalPort.OFP_ETH_ALEN)
+ throw new RuntimeException("Hardware address must have length "
+ + OFPhysicalPort.OFP_ETH_ALEN);
+ this.hardwareAddress = hardwareAddress;
+ }
+
+ /**
+ * @return the config
+ */
+ public int getConfig() {
+ return config;
+ }
+
+ /**
+ * @param config the config to set
+ */
+ public void setConfig(int config) {
+ this.config = config;
+ }
+
+ /**
+ * @return the mask
+ */
+ public int getMask() {
+ return mask;
+ }
+
+ /**
+ * @param mask the mask to set
+ */
+ public void setMask(int mask) {
+ this.mask = mask;
+ }
+
+ /**
+ * @return the advertise
+ */
+ public int getAdvertise() {
+ return advertise;
+ }
+
+ /**
+ * @param advertise the advertise to set
+ */
+ public void setAdvertise(int advertise) {
+ this.advertise = advertise;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.portNumber = data.readShort();
+ if (this.hardwareAddress == null)
+ this.hardwareAddress = new byte[OFPhysicalPort.OFP_ETH_ALEN];
+ data.readBytes(this.hardwareAddress);
+ this.config = data.readInt();
+ this.mask = data.readInt();
+ this.advertise = data.readInt();
+ data.readInt(); // pad
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.portNumber);
+ data.writeBytes(this.hardwareAddress);
+ data.writeInt(this.config);
+ data.writeInt(this.mask);
+ data.writeInt(this.advertise);
+ data.writeInt(0); // pad
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 311;
+ int result = super.hashCode();
+ result = prime * result + advertise;
+ result = prime * result + config;
+ result = prime * result + Arrays.hashCode(hardwareAddress);
+ result = prime * result + mask;
+ result = prime * result + portNumber;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFPortMod)) {
+ return false;
+ }
+ OFPortMod other = (OFPortMod) obj;
+ if (advertise != other.advertise) {
+ return false;
+ }
+ if (config != other.config) {
+ return false;
+ }
+ if (!Arrays.equals(hardwareAddress, other.hardwareAddress)) {
+ return false;
+ }
+ if (mask != other.mask) {
+ return false;
+ }
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_port_status message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFPortStatus extends OFMessage {
+ public static int MINIMUM_LENGTH = 64;
+
+ public enum OFPortReason {
+ OFPPR_ADD,
+ OFPPR_DELETE,
+ OFPPR_MODIFY
+ }
+
+ protected byte reason;
+ protected OFPhysicalPort desc;
+
+ /**
+ * @return the reason
+ */
+ public byte getReason() {
+ return reason;
+ }
+
+ /**
+ * @param reason the reason to set
+ */
+ public void setReason(byte reason) {
+ this.reason = reason;
+ }
+
+ /**
+ * @return the desc
+ */
+ public OFPhysicalPort getDesc() {
+ return desc;
+ }
+
+ /**
+ * @param desc the desc to set
+ */
+ public void setDesc(OFPhysicalPort desc) {
+ this.desc = desc;
+ }
+
+ public OFPortStatus() {
+ super();
+ this.type = OFType.PORT_STATUS;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.reason = data.readByte();
+ data.readerIndex(data.readerIndex() + 7); // skip 7 bytes of padding
+ if (this.desc == null)
+ this.desc = new OFPhysicalPort();
+ this.desc.readFrom(data);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeByte(this.reason);
+ for (int i = 0; i < 7; ++i)
+ data.writeByte((byte) 0);
+ this.desc.writeTo(data);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 313;
+ int result = super.hashCode();
+ result = prime * result + ((desc == null) ? 0 : desc.hashCode());
+ result = prime * result + reason;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFPortStatus)) {
+ return false;
+ }
+ OFPortStatus other = (OFPortStatus) obj;
+ if (desc == null) {
+ if (other.desc != null) {
+ return false;
+ }
+ } else if (!desc.equals(other.desc)) {
+ return false;
+ }
+ if (reason != other.reason) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.protocol;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_queue_get_config_request message
+ * @author Andrew Ferguson (adf@cs.brown.edu)
+ */
+public class OFQueueGetConfigReply extends OFMessage {
+ public static int MINIMUM_LENGTH = 16;
+
+ protected short portNumber;
+ protected List<OFPacketQueue> queues = new ArrayList<OFPacketQueue>();
+
+ public OFQueueGetConfigReply() {
+ super();
+ this.type = OFType.QUEUE_GET_CONFIG_REPLY;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ /**
+ * @return the port's queues
+ */
+ public List<OFPacketQueue> getQueues() {
+ return queues;
+ }
+
+ /**
+ * @param queues the queues to set
+ */
+ public void setQueues(List<OFPacketQueue> queues) {
+ this.queues.clear();
+ this.queues.addAll(queues);
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.portNumber = data.readShort();
+ data.readInt(); // pad
+ data.readShort(); // pad
+
+ int availLength = (this.length - MINIMUM_LENGTH);
+ this.queues.clear();
+
+ while (availLength > 0) {
+ OFPacketQueue queue = new OFPacketQueue();
+ queue.readFrom(data);
+ queues.add(queue);
+ availLength -= queue.getLength();
+ }
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.portNumber);
+ data.writeInt(0); // pad
+ data.writeShort(0); // pad
+
+ for (OFPacketQueue queue : queues) {
+ queue.writeTo(data);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 349;
+ int result = super.hashCode();
+ result = prime * result + portNumber;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFQueueGetConfigReply)) {
+ return false;
+ }
+ OFQueueGetConfigReply other = (OFQueueGetConfigReply) obj;
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_queue_get_config_request message
+ * @author Andrew Ferguson (adf@cs.brown.edu)
+ */
+public class OFQueueGetConfigRequest extends OFMessage {
+ public static int MINIMUM_LENGTH = 12;
+
+ protected short portNumber;
+
+ public OFQueueGetConfigRequest(short portNumber) {
+ super();
+ this.type = OFType.QUEUE_GET_CONFIG_REQUEST;
+ this.length = U16.t(MINIMUM_LENGTH);
+ this.portNumber = portNumber;
+ }
+
+ public OFQueueGetConfigRequest() {
+ this((short) 0);
+ }
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.portNumber = data.readShort();
+ data.readShort(); // pad
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.portNumber);
+ data.writeShort(0); // pad
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 347;
+ int result = super.hashCode();
+ result = prime * result + portNumber;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFQueueGetConfigRequest)) {
+ return false;
+ }
+ OFQueueGetConfigRequest other = (OFQueueGetConfigRequest) obj;
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+public class OFQueueProp {
+ private int NONE_MINIMUM_LENGTH = 8;
+ private int RATE_MINIMUM_LENGTH = 16;
+
+ public enum OFQueuePropType {
+ OFPQT_NONE (0),
+ OFPQT_MIN_RATE (1),
+ OFPQT_MAX_RATE (2);
+
+ protected int value;
+
+ private OFQueuePropType(int value) {
+ this.value = value;
+ }
+
+ /**
+ * @return the value
+ */
+ public int getValue() {
+ return value;
+ }
+
+ public static OFQueuePropType fromShort(short x) {
+ switch (x) {
+ case 0:
+ return OFPQT_NONE;
+ case 1:
+ return OFPQT_MIN_RATE;
+ case 2:
+ return OFPQT_MAX_RATE;
+ }
+ return null;
+ }
+ }
+
+ protected OFQueuePropType type;
+ protected short length;
+ protected short rate = -1; // not valid if type == OFPQT_NONE
+
+ public OFQueueProp() {
+ this.type = OFQueuePropType.OFPQT_NONE;
+ this.length = U16.t(NONE_MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the type
+ */
+ public OFQueuePropType getType() {
+ return type;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(OFQueuePropType type) {
+ this.type = type;
+
+ switch (type) {
+ case OFPQT_NONE:
+ this.length = U16.t(NONE_MINIMUM_LENGTH);
+ break;
+ case OFPQT_MIN_RATE:
+ this.length = U16.t(RATE_MINIMUM_LENGTH);
+ break;
+ case OFPQT_MAX_RATE:
+ this.length = U16.t(RATE_MINIMUM_LENGTH);
+ break;
+ }
+ }
+
+ /**
+ * @return the rate
+ */
+ public short getRate() {
+ return rate;
+ }
+
+ /**
+ * @param rate the rate to set
+ */
+ public void setRate(short rate) {
+ this.rate = rate;
+ }
+
+ /**
+ * @return the length
+ */
+ public short getLength() {
+ return length;
+ }
+
+ public void readFrom(ChannelBuffer data) {
+ this.type = OFQueuePropType.fromShort(data.readShort());
+ this.length = data.readShort();
+ data.readInt(); // pad
+
+ if (this.type == OFQueuePropType.OFPQT_MIN_RATE ||
+ this.type == OFQueuePropType.OFPQT_MAX_RATE) {
+ assert(this.length == RATE_MINIMUM_LENGTH);
+
+ this.rate = data.readShort();
+ data.readInt(); // pad
+ data.readShort(); // pad
+ } else {
+ assert(this.length == NONE_MINIMUM_LENGTH);
+ }
+ }
+
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(this.type.getValue());
+ data.writeShort(this.length);
+ data.writeInt(0); // pad
+
+ if (this.type == OFQueuePropType.OFPQT_MIN_RATE ||
+ this.type == OFQueuePropType.OFPQT_MAX_RATE) {
+ data.writeShort(this.rate);
+ data.writeInt(0); // pad
+ data.writeShort(0); // pad
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 353;
+ int result = super.hashCode();
+ result = prime * result + type.getValue();
+ result = prime * result + rate;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFQueueProp)) {
+ return false;
+ }
+ OFQueueProp other = (OFQueueProp) obj;
+ if (type != other.type) {
+ return false;
+ }
+ if (type == OFQueuePropType.OFPQT_MIN_RATE ||
+ type == OFQueuePropType.OFPQT_MAX_RATE) {
+ if (rate != other.rate) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+/**
+ * Represents an OFPT_SET_CONFIG type message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFSetConfig extends OFSwitchConfig {
+ public OFSetConfig() {
+ super();
+ this.type = OFType.SET_CONFIG;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.factory.OFStatisticsFactory;
+import org.openflow.protocol.factory.OFStatisticsFactoryAware;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.openflow.protocol.statistics.OFStatisticsType;
+
+
+/**
+ * Base class for statistics requests/replies
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 27, 2010
+ */
+public abstract class OFStatisticsMessageBase extends OFMessage implements
+ OFStatisticsFactoryAware {
+ public static int MINIMUM_LENGTH = 12;
+
+ protected OFStatisticsFactory statisticsFactory;
+ protected OFStatisticsType statisticType;
+ protected short flags;
+
+ // TODO: this should be List<? extends OFStatistics>, to
+ // allow for type safe assignments of lists of specific message
+ protected List<? extends OFStatistics> statistics;
+
+ /**
+ * @return the statisticType
+ */
+ public OFStatisticsType getStatisticType() {
+ return statisticType;
+ }
+
+ /**
+ * @param statisticType the statisticType to set
+ */
+ public void setStatisticType(OFStatisticsType statisticType) {
+ this.statisticType = statisticType;
+ }
+
+ /**
+ * @return the flags
+ */
+ public short getFlags() {
+ return flags;
+ }
+
+ /**
+ * @param flags the flags to set
+ */
+ public void setFlags(short flags) {
+ this.flags = flags;
+ }
+
+ /**
+ * @return the statistics
+ */
+ public List<? extends OFStatistics> getStatistics() {
+ return statistics;
+ }
+
+ /**
+ * return the first statistics request in the list of statistics, for
+ * statistics messages that expect exactly one message in their body (e.g.,
+ * flow stats request, port statsrequest)
+ *
+ * @return the first and only element in the list of statistics
+ * @throw IllegalArgumentException if the list does not contain exactly one
+ * element
+ */
+ public OFStatistics getFirstStatistics() {
+ if (statistics == null ) {
+ throw new IllegalArgumentException("Invariant violation: statistics message of type "+statisticType+" is null");
+ }
+ if (statistics.size() != 1) {
+ throw new IllegalArgumentException("Invariant violation: statistics message of type "+statisticType+" contains "+statistics.size() +" statreq/reply messages in its body (should be 1)");
+ }
+
+ return statistics.get(0);
+ }
+
+ /**
+ * @param statistics the statistics to set
+ */
+ public void setStatistics(List<? extends OFStatistics> statistics) {
+ this.statistics = statistics;
+ }
+
+ @Override
+ public void setStatisticsFactory(OFStatisticsFactory statisticsFactory) {
+ this.statisticsFactory = statisticsFactory;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.statisticType = OFStatisticsType.valueOf(data.readShort(), this
+ .getType());
+ this.flags = data.readShort();
+ if (this.statisticsFactory == null)
+ throw new RuntimeException("OFStatisticsFactory not set");
+ this.statistics = statisticsFactory.parseStatistics(this.getType(),
+ this.statisticType, data, super.getLengthU() - MINIMUM_LENGTH);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.statisticType.getTypeValue());
+ data.writeShort(this.flags);
+ if (this.statistics != null) {
+ for (OFStatistics statistic : this.statistics) {
+ statistic.writeTo(data);
+ }
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 317;
+ int result = super.hashCode();
+ result = prime * result + flags;
+ result = prime * result
+ + ((statisticType == null) ? 0 : statisticType.hashCode());
+ result = prime * result
+ + ((statistics == null) ? 0 : statistics.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFStatisticsMessageBase)) {
+ return false;
+ }
+ OFStatisticsMessageBase other = (OFStatisticsMessageBase) obj;
+ if (flags != other.flags) {
+ return false;
+ }
+ if (statisticType == null) {
+ if (other.statisticType != null) {
+ return false;
+ }
+ } else if (!statisticType.equals(other.statisticType)) {
+ return false;
+ }
+ if (statistics == null) {
+ if (other.statistics != null) {
+ return false;
+ }
+ } else if (!statistics.equals(other.statistics)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_stats_reply message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFStatisticsReply extends OFStatisticsMessageBase {
+ public enum OFStatisticsReplyFlags {
+ REPLY_MORE (1 << 0);
+
+ protected short type;
+
+ OFStatisticsReplyFlags(int type) {
+ this.type = (short) type;
+ }
+
+ public short getTypeValue() {
+ return type;
+ }
+ }
+
+ public OFStatisticsReply() {
+ super();
+ this.type = OFType.STATS_REPLY;
+ this.length = U16.t(OFStatisticsMessageBase.MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_stats_request message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFStatisticsRequest extends OFStatisticsMessageBase {
+ public OFStatisticsRequest() {
+ super();
+ this.type = OFType.STATS_REQUEST;
+ this.length = U16.t(OFStatisticsMessageBase.MINIMUM_LENGTH);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Base class representing ofp_switch_config based messages
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public abstract class OFSwitchConfig extends OFMessage {
+ public static int MINIMUM_LENGTH = 12;
+
+ public enum OFConfigFlags {
+ OFPC_FRAG_NORMAL,
+ OFPC_FRAG_DROP,
+ OFPC_FRAG_REASM,
+ OFPC_FRAG_MASK
+ }
+
+ protected short flags;
+ protected short missSendLength;
+
+ public OFSwitchConfig() {
+ super();
+ super.setLengthU(MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the flags
+ */
+ public short getFlags() {
+ return flags;
+ }
+
+ /**
+ * @param flags the flags to set
+ */
+ public OFSwitchConfig setFlags(short flags) {
+ this.flags = flags;
+ return this;
+ }
+
+ /**
+ * @return the missSendLength
+ */
+ public short getMissSendLength() {
+ return missSendLength;
+ }
+
+ /**
+ * @param missSendLength the missSendLength to set
+ */
+ public OFSwitchConfig setMissSendLength(short missSendLength) {
+ this.missSendLength = missSendLength;
+ return this;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.flags = data.readShort();
+ this.missSendLength = data.readShort();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.flags);
+ data.writeShort(this.missSendLength);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 331;
+ int result = super.hashCode();
+ result = prime * result + flags;
+ result = prime * result + missSendLength;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFSwitchConfig)) {
+ return false;
+ }
+ OFSwitchConfig other = (OFSwitchConfig) obj;
+ if (flags != other.flags) {
+ return false;
+ }
+ if (missSendLength != other.missSendLength) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * List of OpenFlow types and mappings to wire protocol value and derived
+ * classes
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ *
+ */
+public enum OFType {
+ HELLO (0, OFHello.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFHello();
+ }}),
+ ERROR (1, OFError.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFError();
+ }}),
+ ECHO_REQUEST (2, OFEchoRequest.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFEchoRequest();
+ }}),
+ ECHO_REPLY (3, OFEchoReply.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFEchoReply();
+ }}),
+ VENDOR (4, OFVendor.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFVendor();
+ }}),
+ FEATURES_REQUEST (5, OFFeaturesRequest.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFFeaturesRequest();
+ }}),
+ FEATURES_REPLY (6, OFFeaturesReply.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFFeaturesReply();
+ }}),
+ GET_CONFIG_REQUEST (7, OFGetConfigRequest.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFGetConfigRequest();
+ }}),
+ GET_CONFIG_REPLY (8, OFGetConfigReply.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFGetConfigReply();
+ }}),
+ SET_CONFIG (9, OFSetConfig.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFSetConfig();
+ }}),
+ PACKET_IN (10, OFPacketIn.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFPacketIn();
+ }}),
+ FLOW_REMOVED (11, OFFlowRemoved.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFFlowRemoved();
+ }}),
+ PORT_STATUS (12, OFPortStatus.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFPortStatus();
+ }}),
+ PACKET_OUT (13, OFPacketOut.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFPacketOut();
+ }}),
+ FLOW_MOD (14, OFFlowMod.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFFlowMod();
+ }}),
+ PORT_MOD (15, OFPortMod.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFPortMod();
+ }}),
+ STATS_REQUEST (16, OFStatisticsRequest.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFStatisticsRequest();
+ }}),
+ STATS_REPLY (17, OFStatisticsReply.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFStatisticsReply();
+ }}),
+ BARRIER_REQUEST (18, OFBarrierRequest.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFBarrierRequest();
+ }}),
+ BARRIER_REPLY (19, OFBarrierReply.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFBarrierReply();
+ }}),
+ QUEUE_GET_CONFIG_REQUEST (20, OFQueueGetConfigRequest.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFQueueGetConfigRequest();
+ }}),
+ QUEUE_GET_CONFIG_REPLY (21, OFQueueGetConfigReply.class, new Instantiable<OFMessage>() {
+ @Override
+ public OFMessage instantiate() {
+ return new OFQueueGetConfigReply();
+ }});
+
+ static OFType[] mapping;
+
+ protected Class<? extends OFMessage> clazz;
+ protected Constructor<? extends OFMessage> constructor;
+ protected Instantiable<OFMessage> instantiable;
+ protected byte type;
+
+ /**
+ * Store some information about the OpenFlow type, including wire protocol
+ * type number, length, and derived class
+ *
+ * @param type Wire protocol number associated with this OFType
+ * @param clazz The Java class corresponding to this type of OpenFlow
+ * message
+ * @param instantiator An Instantiator<OFMessage> implementation that creates an
+ * instance of the specified OFMessage
+ */
+ OFType(int type, Class<? extends OFMessage> clazz, Instantiable<OFMessage> instantiator) {
+ this.type = (byte) type;
+ this.clazz = clazz;
+ this.instantiable = instantiator;
+ try {
+ this.constructor = clazz.getConstructor(new Class[]{});
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failure getting constructor for class: " + clazz, e);
+ }
+ OFType.addMapping(this.type, this);
+ }
+
+ /**
+ * Adds a mapping from type value to OFType enum
+ *
+ * @param i OpenFlow wire protocol type
+ * @param t type
+ */
+ static public void addMapping(byte i, OFType t) {
+ if (mapping == null)
+ mapping = new OFType[32];
+ OFType.mapping[i] = t;
+ }
+
+ /**
+ * Remove a mapping from type value to OFType enum
+ *
+ * @param i OpenFlow wire protocol type
+ */
+ static public void removeMapping(byte i) {
+ OFType.mapping[i] = null;
+ }
+
+ /**
+ * Given a wire protocol OpenFlow type number, return the OFType associated
+ * with it
+ *
+ * @param i wire protocol number
+ * @return OFType enum type
+ */
+
+ static public OFType valueOf(Byte i) {
+ return OFType.mapping[i];
+ }
+
+ /**
+ * @return Returns the wire protocol value corresponding to this OFType
+ */
+ public byte getTypeValue() {
+ return this.type;
+ }
+
+ /**
+ * @return return the OFMessage subclass corresponding to this OFType
+ */
+ public Class<? extends OFMessage> toClass() {
+ return clazz;
+ }
+
+ /**
+ * Returns the no-argument Constructor of the implementation class for
+ * this OFType
+ * @return the constructor
+ */
+ public Constructor<? extends OFMessage> getConstructor() {
+ return constructor;
+ }
+
+ /**
+ * Returns a new instance of the OFMessage represented by this OFType
+ * @return the new object
+ */
+ public OFMessage newInstance() {
+ return instantiable.instantiate();
+ }
+
+ /**
+ * @return the instantiable
+ */
+ public Instantiable<OFMessage> getInstantiable() {
+ return instantiable;
+ }
+
+ /**
+ * @param instantiable the instantiable to set
+ */
+ public void setInstantiable(Instantiable<OFMessage> instantiable) {
+ this.instantiable = instantiable;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+import org.openflow.protocol.factory.OFVendorDataFactory;
+import org.openflow.protocol.factory.OFVendorDataFactoryAware;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Represents ofp_vendor_header
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFVendor extends OFMessage implements OFVendorDataFactoryAware {
+ public static int MINIMUM_LENGTH = 12;
+
+ protected int vendor;
+ protected OFVendorData vendorData;
+ protected OFVendorDataFactory vendorDataFactory;
+
+ public OFVendor() {
+ super();
+ this.type = OFType.VENDOR;
+ this.length = U16.t(MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the vendor
+ */
+ public int getVendor() {
+ return vendor;
+ }
+
+ /**
+ * @param vendor the vendor to set
+ */
+ public void setVendor(int vendor) {
+ this.vendor = vendor;
+ }
+
+ /**
+ * @return the data
+ */
+ public OFVendorData getVendorData() {
+ return vendorData;
+ }
+
+ /**
+ * @param data the data to set
+ */
+ public void setVendorData(OFVendorData vendorData) {
+ this.vendorData = vendorData;
+ }
+
+ @Override
+ public void setVendorDataFactory(OFVendorDataFactory vendorDataFactory) {
+ this.vendorDataFactory = vendorDataFactory;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.vendor = data.readInt();
+ if (vendorDataFactory == null)
+ throw new RuntimeException("OFVendorDataFactory not set");
+
+ this.vendorData = vendorDataFactory.parseVendorData(vendor,
+ data, super.getLengthU() - MINIMUM_LENGTH);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeInt(this.vendor);
+ if (vendorData != null)
+ vendorData.writeTo(data);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 337;
+ int result = super.hashCode();
+ result = prime * result + vendor;
+ if (vendorData != null)
+ result = prime * result + vendorData.hashCode();
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OFVendor other = (OFVendor) obj;
+ if (vendor != other.vendor)
+ return false;
+ if (vendorData == null) {
+ if (other.vendorData != null) {
+ return false;
+ }
+ } else if (!vendorData.equals(other.vendorData)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+ * Copyright 2013, Big Switch Networks, Inc.
+ *
+ * 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 org.openflow.protocol;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * a more user friendly representation of the wildcards bits in an OpenFlow
+ * match. The Wildcards object is
+ * <ul>
+ * <li>immutable (i.e., threadsafe)</li>
+ * <li>instance managed (don't instantiate it yourself), instead call "of"</li>
+ * <ul>
+ * <p>
+ * You can construct a Wildcard object from either its integer representation
+ * </p>
+ * <code>
+ * Wildcard.of(0x3820e0);
+ * </code>
+ * <p>
+ * Or start with either an empty or full wildcard, and select/unselect foo.
+ * </p>
+ * <code>
+ * Wildcard w = Wildcards.NONE
+ * .set(Flag.DL_SRC, Flag. DL_DST, Flag.DL_VLAN_PCP)
+ * .setNwDstMask(8)
+ * .setNwSrcMask(8);
+ * </code>
+ * <p>
+ * <b>Remember:</b> Wildcards objects are immutable. set... operations have
+ * <b>NO EFFECT</b> on the current wildcard object. You HAVE to use the returned
+ * changed object.
+ * </p>
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class Wildcards {
+
+ public final static Wildcards FULL = new Wildcards(OFMatch.OFPFW_ALL_SANITIZED);
+ private static final int FULL_INT = FULL.getInt();
+
+ public final static Wildcards EXACT = new Wildcards(0);
+
+ // floodlight common case: matches on inport + l2
+ public final static int INT_INPORT_L2_MATCH = 0x3820e0;
+ public final static Wildcards INPORT_L2_MATCH = new Wildcards(
+ INT_INPORT_L2_MATCH);
+
+ /**
+ * enum type for the binary flags that can be set in the wildcards field of
+ * an OFMatch. Replaces the unwieldy c-ish int constants in OFMatch.
+ */
+ public static enum Flag {
+ IN_PORT(OFMatch.OFPFW_IN_PORT), /* Switch input port. */
+ DL_VLAN(OFMatch.OFPFW_DL_VLAN), /* VLAN id. */
+ DL_SRC(OFMatch.OFPFW_DL_SRC), /* Ethernet source address. */
+ DL_DST(OFMatch.OFPFW_DL_DST), /* Ethernet destination addr */
+ DL_TYPE(OFMatch.OFPFW_DL_TYPE), /* Ethernet frame type. */
+ NW_PROTO(OFMatch.OFPFW_NW_PROTO), /* IP protocol. */
+ TP_SRC(OFMatch.OFPFW_TP_SRC), /* TCP/UDP source port. */
+ TP_DST(OFMatch.OFPFW_TP_DST), /* TCP/UDP destination port. */
+ DL_VLAN_PCP(OFMatch.OFPFW_DL_VLAN_PCP), /* VLAN priority. */
+ NW_SRC(-1) { /*
+ * virtual NW_SRC flag => translates to the strange 6 bits
+ * in the header
+ */
+ @Override
+ boolean isBolean() {
+ return false;
+ }
+
+ @Override
+ int getInt(int flags) {
+ return ((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT);
+ }
+
+ @Override
+ int setInt(int flags, int srcMask) {
+ return (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | (srcMask << OFMatch.OFPFW_NW_SRC_SHIFT);
+ }
+
+ @Override
+ int wildcard(int flags) {
+ return flags & ~OFMatch.OFPFW_NW_SRC_MASK;
+ }
+
+ @Override
+ int matchOn(int flags) {
+ return flags | OFMatch.OFPFW_NW_SRC_ALL;
+ }
+
+ @Override
+ boolean isPartiallyOn(int flags) {
+ int intValue = getInt(flags);
+ return intValue > 0 && intValue < 32;
+ }
+
+ @Override
+ boolean isFullyOn(int flags) {
+ return getInt(flags) >= 32;
+ }
+
+ },
+ NW_DST(-1) { /*
+ * virtual NW_SRC flag => translates to the strange 6 bits
+ * in the header
+ */
+ @Override
+ boolean isBolean() {
+ return false;
+ }
+
+ @Override
+ int getInt(int flags) {
+ return ((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT);
+ }
+
+ @Override
+ int setInt(int flags, int srcMask) {
+ return (flags & ~OFMatch.OFPFW_NW_DST_MASK) | (srcMask << OFMatch.OFPFW_NW_DST_SHIFT);
+ }
+
+ @Override
+ int wildcard(int flags) {
+ return flags & ~OFMatch.OFPFW_NW_DST_MASK;
+ }
+
+ @Override
+ int matchOn(int flags) {
+ return flags | OFMatch.OFPFW_NW_DST_ALL;
+ }
+
+ @Override
+ boolean isFullyOn(int flags) {
+ return getInt(flags) >= 32;
+ }
+ },
+ NW_TOS(OFMatch.OFPFW_NW_TOS); /* IP ToS (DSCP field, 6 bits). */
+
+ final int bitPosition;
+
+ Flag(int bitPosition) {
+ this.bitPosition = bitPosition;
+ }
+
+ /**
+ * @return a modified OF-1.0 flags field with this flag cleared (match
+ * on this field)
+ */
+ int matchOn(int flags) {
+ return flags & ~this.bitPosition;
+ }
+
+ /**
+ * @return a modified OF-1.0 flags field with this flag set (wildcard
+ * this field)
+ */
+ int wildcard(int flags) {
+ return flags | this.bitPosition;
+ }
+
+ /**
+ * @return true iff this is a true boolean flag that can either be off
+ * or on.True in OF-1.0 for all fields except NW_SRC and NW_DST
+ */
+ boolean isBolean() {
+ return false;
+ }
+
+ /**
+ * @return true iff this wildcard field is currently 'partially on'.
+ * Always false for true Boolean Flags. Can be true in OF-1.0
+ * for NW_SRC, NW_DST.
+ */
+ boolean isPartiallyOn(int flags) {
+ return false;
+ }
+
+ /**
+ * @return true iff this wildcard field currently fully on (fully
+ * wildcarded). Equivalent to the boolean flag being set in the
+ * bitmask for bit flags, and to the wildcarded bit length set
+ * to >=32 for NW_SRC and NW_DST
+ * @param flags
+ * @return
+ */
+ boolean isFullyOn(int flags) {
+ return (flags & this.bitPosition) != 0;
+ }
+
+ /**
+ * set the integer representation of this flag. only for NW_SRC and
+ * NW_DST
+ */
+ int setInt(int flags, int srcMask) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * set the integer representation of this flag. only for NW_SRC and
+ * NW_DST
+ */
+ int getInt(int flags) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ }
+
+ private final int flags;
+
+ /** private constructor. use Wildcard.of() instead */
+ private Wildcards(int flags) {
+ this.flags = flags;
+ }
+
+ /**
+ * return a wildcard object matching the given int flags. May reuse / cache
+ * frequently used wildcard instances. Don't rely on it though (use equals
+ * not ==).
+ *
+ * @param flags
+ * @return
+ */
+ public static Wildcards of(int paramFlags) {
+ int flags = sanitizeInt(paramFlags);
+ switch(flags) {
+ case 0x0000:
+ return EXACT;
+ case OFMatch.OFPFW_ALL_SANITIZED:
+ return FULL;
+ case INT_INPORT_L2_MATCH:
+ return INPORT_L2_MATCH;
+ default:
+ return new Wildcards(flags);
+ }
+ }
+
+ /** convience method return a wildcard for exactly one set flag */
+ public static Wildcards of(Wildcards.Flag setFlag) {
+ return Wildcards.of(setFlag.wildcard(0));
+ }
+
+ /** convience method return a wildcard for exactly two set flags */
+ public static Wildcards of(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
+ return Wildcards.of(setFlag.wildcard(setFlag2.wildcard(0)));
+ }
+
+ /** convience method return a wildcard for an arbitrary number of set flags */
+ public static Wildcards of(Wildcards.Flag... setFlags) {
+ int flags = 0;
+ for (Wildcards.Flag flag : setFlags)
+ flags = flag.wildcard(0);
+ return Wildcards.of(flags);
+ }
+
+ /** convience method return a wildcards for ofmatches that match on one flag */
+ public static Wildcards ofMatches(Wildcards.Flag setFlag) {
+ return Wildcards.of(setFlag.matchOn(FULL_INT));
+ }
+
+ /**
+ * convience method return a wildcard for for an ofmatch that match on two
+ * flags
+ */
+ public static Wildcards ofMatches(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
+ return Wildcards.of(setFlag.matchOn(setFlag2.matchOn(FULL_INT)));
+ }
+
+ /**
+ * convience method return a wildcard for an ofmatch that amtch on an
+ * arbitrary number of set flags
+ */
+ public static Wildcards ofMatches(Wildcards.Flag... setFlags) {
+ int flags = FULL_INT;
+ for (Wildcards.Flag flag : setFlags)
+ flags = flag.matchOn(flags);
+ return Wildcards.of(flags);
+ }
+
+ /**
+ * return a Wildcards object that has the given flags set
+ * <p>
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ */
+ public Wildcards wildcard(Wildcards.Flag flag) {
+ int flags = flag.wildcard(this.flags);
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return a Wildcards object that has the given flags set
+ * <p>
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ */
+ public Wildcards wildcard(Wildcards.Flag flag, Wildcards.Flag flag2) {
+ int flags = flag.wildcard(flag2.wildcard(this.flags));
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return a Wildcards object that has the given flags wildcarded
+ * <p>
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ */
+ public Wildcards wildcard(Wildcards.Flag... setFlags) {
+ int flags = this.flags;
+ for (Wildcards.Flag flag : setFlags)
+ flags = flag.wildcard(flags);
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return a Wildcards object that matches on exactly the given flag
+ * <p>
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ */
+ public Wildcards matchOn(Wildcards.Flag flag) {
+ int flags = flag.matchOn(this.flags);
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return a Wildcards object that matches on exactly the given flags
+ * <p>
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ */
+ public Wildcards matchOn(Wildcards.Flag flag, Wildcards.Flag flag2) {
+ int flags = flag.matchOn(flag2.matchOn(this.flags));
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return a Wildcards object that matches on exactly the given flags
+ * <p>
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ */
+ public Wildcards matchOn(Wildcards.Flag... setFlags) {
+ int flags = this.flags;
+ for (Wildcards.Flag flag : setFlags)
+ flags = flag.matchOn(flags);
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return the nw src mask in normal CIDR style, e.g., 8 means x.x.x.x/8
+ * means 8 bits wildcarded
+ */
+ public int getNwSrcMask() {
+ return Math.max(0, 32 - Flag.NW_SRC.getInt(flags));
+ }
+
+ /**
+ * return the nw dst mask in normal CIDR style, e.g., 8 means x.x.x.x/8
+ * means 8 bits wildcarded
+ */
+ public int getNwDstMask() {
+ return Math.max(0, 32 - Flag.NW_DST.getInt(flags));
+ }
+
+ /**
+ * return a Wildcard object that has the given nwSrcCidrMask set.
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ *
+ * @param srcCidrMask
+ * source mask to set in <b>normal CIDR notation</b>, i.e., 8
+ * means x.x.x.x/8
+ * @return a modified object
+ */
+ public Wildcards withNwSrcMask(int srcCidrMask) {
+ int flags = Flag.NW_SRC.setInt(this.flags, Math.max(0, 32 - srcCidrMask));
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return a Wildcard object that has the given nwDstCidrMask set.
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ *
+ * @param dstCidrMask
+ * dest mask to set in <b>normal CIDR notation</b>, i.e., 8 means
+ * x.x.x.x/8
+ * @return a modified object
+ */
+ public Wildcards withNwDstMask(int dstCidrMask) {
+ int flags = Flag.NW_DST.setInt(this.flags, Math.max(0, 32 - dstCidrMask));
+ if (flags == this.flags)
+ return this;
+ else
+ return new Wildcards(flags);
+ }
+
+ /**
+ * return a Wildcard object that is inverted to this wildcard object.
+ * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
+ * unmodified. </b>
+ * @return a modified object
+ */
+ public Wildcards inverted() {
+ return Wildcards.of(flags ^ OFMatch.OFPFW_ALL_SANITIZED);
+ }
+
+ public boolean isWildcarded(Flag flag) {
+ return flag.isFullyOn(flags);
+ }
+
+ /**
+ * return all wildcard flags that are fully wildcarded as an EnumSet. Do not
+ * modify. Note: some flags (like NW_SRC and NW_DST) that are partially
+ * wildcarded are not returned in this set.
+ *
+ * @return the EnumSet of wildcards
+ */
+ public EnumSet<Wildcards.Flag> getWildcardedFlags() {
+ EnumSet<Wildcards.Flag> res = EnumSet.noneOf(Wildcards.Flag.class);
+ for (Wildcards.Flag flag : Flag.values()) {
+ if (flag.isFullyOn(flags)) {
+ res.add(flag);
+ }
+ }
+ return res;
+ }
+
+ /** return the OpenFlow 'wire' integer representation of these wildcards */
+ public int getInt() {
+ return flags;
+ }
+
+ /**
+ * return the OpenFlow 'wire' integer representation of these wildcards.
+ * Sanitize nw_src and nw_dst to be max. 32 (values > 32 are technically
+ * possible, but don't make semantic sense)
+ */
+ public static int sanitizeInt(int flags) {
+ if (((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT) > 32) {
+ flags = (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | OFMatch.OFPFW_NW_SRC_ALL;
+ }
+ if (((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT) > 32) {
+ flags = (flags & ~OFMatch.OFPFW_NW_DST_MASK) | OFMatch.OFPFW_NW_DST_ALL;
+ }
+ return flags;
+ }
+
+ /**
+ * is this a wildcard set that has all flags set + and full (/0) nw_src and
+ * nw_dst wildcarding ?
+ */
+ public boolean isFull() {
+ return flags == OFMatch.OFPFW_ALL || flags == OFMatch.OFPFW_ALL_SANITIZED;
+ }
+
+ /** is this a wildcard of an exact match */
+ public boolean isExact() {
+ return flags == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + flags;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Wildcards other = (Wildcards) obj;
+ if (flags != other.flags)
+ return false;
+ return true;
+ }
+
+
+
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * The base class for all OpenFlow Actions.
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public class OFAction implements Cloneable {
+ /**
+ * Note the true minimum length for this header is 8 including a pad to 64
+ * bit alignment, however as this base class is used for demuxing an
+ * incoming Action, it is only necessary to read the first 4 bytes. All
+ * Actions extending this class are responsible for reading/writing the
+ * first 8 bytes, including the pad if necessary.
+ */
+ public static int MINIMUM_LENGTH = 4;
+ public static int OFFSET_LENGTH = 2;
+ public static int OFFSET_TYPE = 0;
+
+ protected OFActionType type;
+ protected short length;
+
+ /**
+ * Get the length of this message
+ *
+ * @return
+ */
+ public short getLength() {
+ return length;
+ }
+
+ /**
+ * Get the length of this message, unsigned
+ *
+ * @return
+ */
+ public int getLengthU() {
+ return U16.f(length);
+ }
+
+ /**
+ * Set the length of this message
+ *
+ * @param length
+ */
+ public OFAction setLength(short length) {
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Get the type of this message
+ *
+ * @return OFActionType enum
+ */
+ public OFActionType getType() {
+ return this.type;
+ }
+
+ /**
+ * Set the type of this message
+ *
+ * @param type
+ */
+ public void setType(OFActionType type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns a summary of the message
+ * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid"
+ */
+ public String toString() {
+ return "ofaction" +
+ ";t=" + this.getType() +
+ ";l=" + this.getLength();
+ }
+
+ /**
+ * Given the output from toString(),
+ * create a new OFAction
+ * @param val
+ * @return
+ */
+ public static OFAction fromString(String val) {
+ String tokens[] = val.split(";");
+ if (!tokens[0].equals("ofaction"))
+ throw new IllegalArgumentException("expected 'ofaction' but got '" +
+ tokens[0] + "'");
+ String type_tokens[] = tokens[1].split("=");
+ String len_tokens[] = tokens[2].split("=");
+ OFAction action = new OFAction();
+ action.setLength(Short.valueOf(len_tokens[1]));
+ action.setType(OFActionType.valueOf(type_tokens[1]));
+ return action;
+ }
+
+ public void readFrom(ChannelBuffer data) {
+ this.type = OFActionType.valueOf(data.readShort());
+ this.length = data.readShort();
+ // Note missing PAD, see MINIMUM_LENGTH comment for details
+ }
+
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(type.getTypeValue());
+ data.writeShort(length);
+ // Note missing PAD, see MINIMUM_LENGTH comment for details
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 347;
+ int result = 1;
+ result = prime * result + length;
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFAction)) {
+ return false;
+ }
+ OFAction other = (OFAction) obj;
+ if (length != other.length) {
+ return false;
+ }
+ if (type == null) {
+ if (other.type != null) {
+ return false;
+ }
+ } else if (!type.equals(other.type)) {
+ return false;
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public OFAction clone() throws CloneNotSupportedException {
+ return (OFAction) super.clone();
+ }
+
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+import java.util.Arrays;
+
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFPhysicalPort;
+
+/**
+ * Represents an ofp_action_dl_addr
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public abstract class OFActionDataLayer extends OFAction {
+ public static int MINIMUM_LENGTH = 16;
+
+ protected byte[] dataLayerAddress;
+
+ /**
+ * @return the dataLayerAddress
+ */
+ public byte[] getDataLayerAddress() {
+ return dataLayerAddress;
+ }
+
+ /**
+ * @param dataLayerAddress the dataLayerAddress to set
+ */
+ public void setDataLayerAddress(byte[] dataLayerAddress) {
+ this.dataLayerAddress = dataLayerAddress;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ if (this.dataLayerAddress == null)
+ this.dataLayerAddress = new byte[OFPhysicalPort.OFP_ETH_ALEN];
+ data.readBytes(this.dataLayerAddress);
+ data.readInt();
+ data.readShort();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeBytes(this.dataLayerAddress);
+ data.writeInt(0);
+ data.writeShort((short) 0);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 347;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(dataLayerAddress);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionDataLayer)) {
+ return false;
+ }
+ OFActionDataLayer other = (OFActionDataLayer) obj;
+ if (!Arrays.equals(dataLayerAddress, other.dataLayerAddress)) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFActionDataLayerDestination extends OFActionDataLayer {
+ public OFActionDataLayerDestination() {
+ super();
+ super.setType(OFActionType.SET_DL_DST);
+ super.setLength((short) OFActionDataLayer.MINIMUM_LENGTH);
+ }
+
+ public OFActionDataLayerDestination(byte[] address) {
+ this();
+ this.dataLayerAddress = address;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFActionDataLayerSource extends OFActionDataLayer {
+ public OFActionDataLayerSource() {
+ super();
+ super.setType(OFActionType.SET_DL_SRC);
+ super.setLength((short) OFActionDataLayer.MINIMUM_LENGTH);
+ }
+
+ public OFActionDataLayerSource(byte[] address) {
+ this();
+ this.dataLayerAddress = address;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_action_enqueue
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public class OFActionEnqueue extends OFAction {
+ public static int MINIMUM_LENGTH = 16;
+
+ protected short port;
+ protected int queueId;
+
+ public OFActionEnqueue() {
+ super.setType(OFActionType.OPAQUE_ENQUEUE);
+ super.setLength((short) MINIMUM_LENGTH);
+ }
+
+ public OFActionEnqueue(short port, int queueId) {
+ this();
+ this.port = port;
+ this.queueId = queueId;
+ }
+
+ /**
+ * Get the output port
+ * @return
+ */
+ public short getPort() {
+ return this.port;
+ }
+
+ /**
+ * Set the output port
+ * @param port
+ */
+ public void setPort(short port) {
+ this.port = port;
+ }
+
+ /**
+ * @return the queueId
+ */
+ public int getQueueId() {
+ return queueId;
+ }
+
+ /**
+ * @param queueId the queueId to set
+ */
+ public void setQueueId(int queueId) {
+ this.queueId = queueId;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.port = data.readShort();
+ data.readShort();
+ data.readInt();
+ this.queueId = data.readInt();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.port);
+ data.writeShort((short) 0);
+ data.writeInt(0);
+ data.writeInt(this.queueId);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 349;
+ int result = super.hashCode();
+ result = prime * result + port;
+ result = prime * result + queueId;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionEnqueue)) {
+ return false;
+ }
+ OFActionEnqueue other = (OFActionEnqueue) obj;
+ if (port != other.port) {
+ return false;
+ }
+ if (queueId != other.queueId) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_action_nw_addr
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public abstract class OFActionNetworkLayerAddress extends OFAction {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected int networkAddress;
+
+ /**
+ * @return the networkAddress
+ */
+ public int getNetworkAddress() {
+ return networkAddress;
+ }
+
+ /**
+ * @param networkAddress the networkAddress to set
+ */
+ public void setNetworkAddress(int networkAddress) {
+ this.networkAddress = networkAddress;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.networkAddress = data.readInt();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeInt(this.networkAddress);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 353;
+ int result = super.hashCode();
+ result = prime * result + networkAddress;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionNetworkLayerAddress)) {
+ return false;
+ }
+ OFActionNetworkLayerAddress other = (OFActionNetworkLayerAddress) obj;
+ if (networkAddress != other.networkAddress) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFActionNetworkLayerDestination extends OFActionNetworkLayerAddress {
+ public OFActionNetworkLayerDestination() {
+ super();
+ super.setType(OFActionType.SET_NW_DST);
+ super.setLength((short) OFActionNetworkLayerAddress.MINIMUM_LENGTH);
+ }
+
+ public OFActionNetworkLayerDestination(int ip) {
+ this();
+ this.networkAddress = ip;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFActionNetworkLayerSource extends OFActionNetworkLayerAddress {
+ public OFActionNetworkLayerSource() {
+ super();
+ super.setType(OFActionType.SET_NW_SRC);
+ super.setLength((short) OFActionNetworkLayerAddress.MINIMUM_LENGTH);
+ }
+
+ public OFActionNetworkLayerSource(int ip) {
+ this();
+ this.networkAddress = ip;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_action_enqueue
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public class OFActionNetworkTypeOfService extends OFAction {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected byte networkTypeOfService;
+
+ public OFActionNetworkTypeOfService() {
+ super.setType(OFActionType.SET_NW_TOS);
+ super.setLength((short) MINIMUM_LENGTH);
+ }
+
+ public OFActionNetworkTypeOfService(byte tos) {
+ this();
+ this.networkTypeOfService = tos;
+ }
+
+
+ /**
+ * @return the networkTypeOfService
+ */
+ public byte getNetworkTypeOfService() {
+ return networkTypeOfService;
+ }
+
+ /**
+ * @param networkTypeOfService the networkTypeOfService to set
+ */
+ public void setNetworkTypeOfService(byte networkTypeOfService) {
+ this.networkTypeOfService = networkTypeOfService;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.networkTypeOfService = data.readByte();
+ data.readShort();
+ data.readByte();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeByte(this.networkTypeOfService);
+ data.writeShort((short) 0);
+ data.writeByte((byte) 0);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 359;
+ int result = super.hashCode();
+ result = prime * result + networkTypeOfService;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionNetworkTypeOfService)) {
+ return false;
+ }
+ OFActionNetworkTypeOfService other = (OFActionNetworkTypeOfService) obj;
+ if (networkTypeOfService != other.networkTypeOfService) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+public class OFActionOutput extends OFAction implements Cloneable {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected short port;
+ protected short maxLength;
+
+ public OFActionOutput() {
+ super.setType(OFActionType.OUTPUT);
+ super.setLength((short) MINIMUM_LENGTH);
+ }
+
+ /**
+ * Create an Output Action sending packets out the specified
+ * OpenFlow port.
+ *
+ * This is the most common creation pattern for OFActions.
+ *
+ * @param port
+ */
+
+ public OFActionOutput(short port) {
+ this(port, (short) 65535);
+ }
+
+ /**
+ * Create an Output Action specifying both the port AND
+ * the snaplen of the packet to send out that port.
+ * The length field is only meaningful when port == OFPort.OFPP_CONTROLLER
+ * @param port
+ * @param maxLength The maximum number of bytes of the packet to send.
+ * Most hardware only supports this value for OFPP_CONTROLLER
+ */
+
+ public OFActionOutput(short port, short maxLength) {
+ super();
+ super.setType(OFActionType.OUTPUT);
+ super.setLength((short) MINIMUM_LENGTH);
+ this.port = port;
+ this.maxLength = maxLength;
+ }
+
+ /**
+ * Get the output port
+ * @return
+ */
+ public short getPort() {
+ return this.port;
+ }
+
+ /**
+ * Set the output port
+ * @param port
+ */
+ public OFActionOutput setPort(short port) {
+ this.port = port;
+ return this;
+ }
+
+ /**
+ * Get the max length to send to the controller
+ * @return
+ */
+ public short getMaxLength() {
+ return this.maxLength;
+ }
+
+ /**
+ * Set the max length to send to the controller
+ * @param maxLength
+ */
+ public OFActionOutput setMaxLength(short maxLength) {
+ this.maxLength = maxLength;
+ return this;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.port = data.readShort();
+ this.maxLength = data.readShort();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(port);
+ data.writeShort(maxLength);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 367;
+ int result = super.hashCode();
+ result = prime * result + maxLength;
+ result = prime * result + port;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionOutput)) {
+ return false;
+ }
+ OFActionOutput other = (OFActionOutput) obj;
+ if (maxLength != other.maxLength) {
+ return false;
+ }
+ if (port != other.port) {
+ return false;
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "OFActionOutput [maxLength=" + maxLength + ", port=" + U16.f(port)
+ + ", length=" + length + ", type=" + type + "]";
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+
+/**
+ * Represents an ofp_action_strip_vlan
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public class OFActionStripVirtualLan extends OFAction {
+ public static int MINIMUM_LENGTH = 8;
+
+ public OFActionStripVirtualLan() {
+ super();
+ super.setType(OFActionType.STRIP_VLAN);
+ super.setLength((short) MINIMUM_LENGTH);
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ // PAD
+ data.readInt();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ // PAD
+ data.writeInt(0);
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_action_tp_port
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public abstract class OFActionTransportLayer extends OFAction {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected short transportPort;
+
+ /**
+ * @return the transportPort
+ */
+ public short getTransportPort() {
+ return transportPort;
+ }
+
+ /**
+ * @param transportPort the transportPort to set
+ */
+ public void setTransportPort(short transportPort) {
+ this.transportPort = transportPort;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.transportPort = data.readShort();
+ data.readShort();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.transportPort);
+ data.writeShort((short) 0);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 373;
+ int result = super.hashCode();
+ result = prime * result + transportPort;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionTransportLayer)) {
+ return false;
+ }
+ OFActionTransportLayer other = (OFActionTransportLayer) obj;
+ if (transportPort != other.transportPort) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFActionTransportLayerDestination extends OFActionTransportLayer {
+ public OFActionTransportLayerDestination() {
+ super();
+ super.setType(OFActionType.SET_TP_DST);
+ super.setLength((short) OFActionTransportLayer.MINIMUM_LENGTH);
+ }
+
+ public OFActionTransportLayerDestination(short port) {
+ this();
+ this.transportPort = port;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFActionTransportLayerSource extends OFActionTransportLayer {
+ public OFActionTransportLayerSource() {
+ super();
+ super.setType(OFActionType.SET_TP_SRC);
+ super.setLength((short) OFActionTransportLayer.MINIMUM_LENGTH);
+ }
+
+ public OFActionTransportLayerSource(short port) {
+ this();
+ this.transportPort = port;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+import java.lang.reflect.Constructor;
+
+import org.openflow.protocol.Instantiable;
+
+/**
+ * List of OpenFlow Action types and mappings to wire protocol value and
+ * derived classes
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public enum OFActionType {
+ OUTPUT (0, OFActionOutput.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionOutput();
+ }}),
+ SET_VLAN_ID (1, OFActionVirtualLanIdentifier.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionVirtualLanIdentifier();
+ }}),
+ SET_VLAN_PCP (2, OFActionVirtualLanPriorityCodePoint.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionVirtualLanPriorityCodePoint();
+ }}),
+ STRIP_VLAN (3, OFActionStripVirtualLan.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionStripVirtualLan();
+ }}),
+ SET_DL_SRC (4, OFActionDataLayerSource.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionDataLayerSource();
+ }}),
+ SET_DL_DST (5, OFActionDataLayerDestination.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionDataLayerDestination();
+ }}),
+ SET_NW_SRC (6, OFActionNetworkLayerSource.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionNetworkLayerSource();
+ }}),
+ SET_NW_DST (7, OFActionNetworkLayerDestination.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionNetworkLayerDestination();
+ }}),
+ SET_NW_TOS (8, OFActionNetworkTypeOfService.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionNetworkTypeOfService();
+ }}),
+ SET_TP_SRC (9, OFActionTransportLayerSource.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionTransportLayerSource();
+ }}),
+ SET_TP_DST (10, OFActionTransportLayerDestination.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionTransportLayerDestination();
+ }}),
+ OPAQUE_ENQUEUE (11, OFActionEnqueue.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionEnqueue();
+ }}),
+ VENDOR (0xffff, OFActionVendor.class, new Instantiable<OFAction>() {
+ @Override
+ public OFAction instantiate() {
+ return new OFActionVendorGeneric();
+ }});
+
+ protected static OFActionType[] mapping;
+
+ protected Class<? extends OFAction> clazz;
+ protected Constructor<? extends OFAction> constructor;
+ protected Instantiable<OFAction> instantiable;
+ protected int minLen;
+ protected short type;
+
+ /**
+ * Store some information about the OpenFlow Action type, including wire
+ * protocol type number, length, and derrived class
+ *
+ * @param type Wire protocol number associated with this OFType
+ * @param clazz The Java class corresponding to this type of OpenFlow Action
+ * @param instantiable the instantiable for the OFAction this type represents
+ */
+ OFActionType(int type, Class<? extends OFAction> clazz, Instantiable<OFAction> instantiable) {
+ this.type = (short) type;
+ this.clazz = clazz;
+ this.instantiable = instantiable;
+ try {
+ this.constructor = clazz.getConstructor(new Class[]{});
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failure getting constructor for class: " + clazz, e);
+ }
+ OFActionType.addMapping(this.type, this);
+ }
+
+ /**
+ * Adds a mapping from type value to OFActionType enum
+ *
+ * @param i OpenFlow wire protocol Action type value
+ * @param t type
+ */
+ static public void addMapping(short i, OFActionType t) {
+ if (mapping == null)
+ mapping = new OFActionType[16];
+ // bring higher mappings down to the edge of our array
+ if (i < 0)
+ i = (short) (16 + i);
+ OFActionType.mapping[i] = t;
+ }
+
+ /**
+ * Given a wire protocol OpenFlow type number, return the OFType associated
+ * with it
+ *
+ * @param i wire protocol number
+ * @return OFType enum type
+ */
+
+ static public OFActionType valueOf(short i) {
+ if (i < 0)
+ i = (short) (16+i);
+ return OFActionType.mapping[i];
+ }
+
+ /**
+ * @return Returns the wire protocol value corresponding to this
+ * OFActionType
+ */
+ public short getTypeValue() {
+ return this.type;
+ }
+
+ /**
+ * @return return the OFAction subclass corresponding to this OFActionType
+ */
+ public Class<? extends OFAction> toClass() {
+ return clazz;
+ }
+
+ /**
+ * Returns the no-argument Constructor of the implementation class for
+ * this OFActionType
+ * @return the constructor
+ */
+ public Constructor<? extends OFAction> getConstructor() {
+ return constructor;
+ }
+
+ /**
+ * Returns a new instance of the OFAction represented by this OFActionType
+ * @return the new object
+ */
+ public OFAction newInstance() {
+ return instantiable.instantiate();
+ }
+
+ /**
+ * @return the instantiable
+ */
+ public Instantiable<OFAction> getInstantiable() {
+ return instantiable;
+ }
+
+ /**
+ * @param instantiable the instantiable to set
+ */
+ public void setInstantiable(Instantiable<OFAction> instantiable) {
+ this.instantiable = instantiable;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public abstract class OFActionVendor extends OFAction {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected int vendor;
+
+ public OFActionVendor() {
+ super();
+ super.setType(OFActionType.VENDOR);
+ super.setLength((short) MINIMUM_LENGTH);
+ }
+
+ /**
+ * @return the vendor
+ */
+ public int getVendor() {
+ return vendor;
+ }
+
+ /**
+ * @param vendor the vendor to set
+ */
+ public void setVendor(int vendor) {
+ this.vendor = vendor;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.vendor = data.readInt();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeInt(this.vendor);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 379;
+ int result = super.hashCode();
+ result = prime * result + vendor;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionVendor)) {
+ return false;
+ }
+ OFActionVendor other = (OFActionVendor) obj;
+ if (vendor != other.vendor) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "; vendor=" + vendor;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.action;
+
+
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/** A generic / unparsed vendor action. This action is returned by
+ * BasicFactory.readFromWire if no more specific OFVendorActionFactory
+ * is registered.
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class OFActionVendorGeneric extends OFActionVendor {
+ public static int MINIMUM_LENGTH = 8;
+
+ private final static byte[] EMPTY_ARRAY = new byte[0];
+
+ protected byte[] vendorData;
+
+ public OFActionVendorGeneric() {
+ super();
+ }
+
+ public byte[] getVendorData() {
+ return vendorData;
+ }
+
+ public void setVendorData(byte[] vendorData) {
+ this.vendorData = vendorData;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+
+ int vendorDataLength = this.getLength() - MINIMUM_LENGTH;
+ if (vendorDataLength > 0) {
+ vendorData = new byte[vendorDataLength];
+ data.readBytes(vendorData);
+ } else {
+ vendorData = EMPTY_ARRAY;
+ }
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeInt(this.vendor);
+ data.writeBytes(vendorData);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 379;
+ int result = super.hashCode();
+ result = prime * result + Arrays.hashCode(vendorData);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionVendorGeneric)) {
+ return false;
+ }
+ OFActionVendorGeneric other = (OFActionVendorGeneric) obj;
+ if (!Arrays.equals(vendorData, other.vendorData)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_action_vlan_vid
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public class OFActionVirtualLanIdentifier extends OFAction {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected short virtualLanIdentifier;
+
+ public OFActionVirtualLanIdentifier() {
+ super.setType(OFActionType.SET_VLAN_ID);
+ super.setLength((short) MINIMUM_LENGTH);
+ }
+
+ public OFActionVirtualLanIdentifier(short vlanId) {
+ this();
+ this.virtualLanIdentifier = vlanId;
+ }
+
+ /**
+ * @return the virtualLanIdentifier
+ */
+ public short getVirtualLanIdentifier() {
+ return virtualLanIdentifier;
+ }
+
+ /**
+ * @param virtualLanIdentifier the virtualLanIdentifier to set
+ */
+ public void setVirtualLanIdentifier(short virtualLanIdentifier) {
+ this.virtualLanIdentifier = virtualLanIdentifier;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.virtualLanIdentifier = data.readShort();
+ data.readShort();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.virtualLanIdentifier);
+ data.writeShort((short) 0);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 383;
+ int result = super.hashCode();
+ result = prime * result + virtualLanIdentifier;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionVirtualLanIdentifier)) {
+ return false;
+ }
+ OFActionVirtualLanIdentifier other = (OFActionVirtualLanIdentifier) obj;
+ if (virtualLanIdentifier != other.virtualLanIdentifier) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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.
+**/
+
+/**
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+package org.openflow.protocol.action;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_action_vlan_pcp
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public class OFActionVirtualLanPriorityCodePoint extends OFAction {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected byte virtualLanPriorityCodePoint;
+
+ public OFActionVirtualLanPriorityCodePoint() {
+ super.setType(OFActionType.SET_VLAN_PCP);
+ super.setLength((short) MINIMUM_LENGTH);
+ }
+
+ public OFActionVirtualLanPriorityCodePoint(byte priority) {
+ this();
+ this.virtualLanPriorityCodePoint = priority;
+ }
+
+ /**
+ * @return the virtualLanPriorityCodePoint
+ */
+ public byte getVirtualLanPriorityCodePoint() {
+ return virtualLanPriorityCodePoint;
+ }
+
+ /**
+ * @param virtualLanPriorityCodePoint the virtualLanPriorityCodePoint to set
+ */
+ public void setVirtualLanPriorityCodePoint(byte virtualLanPriorityCodePoint) {
+ this.virtualLanPriorityCodePoint = virtualLanPriorityCodePoint;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+ this.virtualLanPriorityCodePoint = data.readByte();
+ data.readShort(); // pad
+ data.readByte(); // pad
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeByte(this.virtualLanPriorityCodePoint);
+ data.writeShort((short) 0);
+ data.writeByte((byte) 0);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 389;
+ int result = super.hashCode();
+ result = prime * result + virtualLanPriorityCodePoint;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (!(obj instanceof OFActionVirtualLanPriorityCodePoint)) {
+ return false;
+ }
+ OFActionVirtualLanPriorityCodePoint other = (OFActionVirtualLanPriorityCodePoint) obj;
+ if (virtualLanPriorityCodePoint != other.virtualLanPriorityCodePoint) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.factory;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionType;
+import org.openflow.protocol.action.OFActionVendor;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.openflow.protocol.statistics.OFStatisticsType;
+import org.openflow.protocol.statistics.OFVendorStatistics;
+import org.openflow.protocol.vendor.OFByteArrayVendorData;
+import org.openflow.protocol.vendor.OFVendorData;
+import org.openflow.protocol.vendor.OFVendorDataType;
+import org.openflow.protocol.vendor.OFVendorId;
+
+
+/**
+ * A basic OpenFlow factory that supports naive creation of both Messages and
+ * Actions.
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ *
+ */
+public class BasicFactory implements OFMessageFactory, OFActionFactory,
+ OFStatisticsFactory, OFVendorDataFactory {
+
+ private final OFVendorActionRegistry vendorActionRegistry;
+
+ public BasicFactory() {
+ vendorActionRegistry = OFVendorActionRegistry.getInstance();
+ }
+
+ /**
+ * create and return a new instance of a message for OFType t. Also injects
+ * factories for those message types that implement the *FactoryAware
+ * interfaces.
+ *
+ * @return a newly created instance that may be modified / used freely by
+ * the caller
+ */
+ @Override
+ public OFMessage getMessage(OFType t) {
+ OFMessage message = t.newInstance();
+ injectFactories(message);
+ return message;
+ }
+
+ @Override
+ public List<OFMessage> parseMessage(ChannelBuffer data) throws MessageParseException {
+ List<OFMessage> msglist = new ArrayList<OFMessage>();
+ OFMessage msg = null;
+
+ while (data.readableBytes() >= OFMessage.MINIMUM_LENGTH) {
+ data.markReaderIndex();
+ msg = this.parseMessageOne(data);
+ if (msg == null) {
+ data.resetReaderIndex();
+ break;
+ }
+ else {
+ msglist.add(msg);
+ }
+ }
+
+ if (msglist.size() == 0) {
+ return null;
+ }
+ return msglist;
+
+ }
+
+ public OFMessage parseMessageOne(ChannelBuffer data) throws MessageParseException {
+ try {
+ OFMessage demux = new OFMessage();
+ OFMessage ofm = null;
+
+ if (data.readableBytes() < OFMessage.MINIMUM_LENGTH)
+ return ofm;
+
+ data.markReaderIndex();
+ demux.readFrom(data);
+ data.resetReaderIndex();
+
+ if (demux.getLengthU() > data.readableBytes())
+ return ofm;
+
+ ofm = getMessage(demux.getType());
+ if (ofm == null)
+ return null;
+
+ injectFactories(ofm);
+ ofm.readFrom(data);
+ if (OFMessage.class.equals(ofm.getClass())) {
+ // advance the position for un-implemented messages
+ data.readerIndex(data.readerIndex()+(ofm.getLengthU() -
+ OFMessage.MINIMUM_LENGTH));
+ }
+
+ return ofm;
+ } catch (Exception e) {
+ /* Write the offending data along with the error message */
+ data.resetReaderIndex();
+ String msg =
+ "Message Parse Error for packet:" + dumpBuffer(data) +
+ "\nException: " + e.toString();
+ data.resetReaderIndex();
+
+ throw new MessageParseException(msg, e);
+ }
+ }
+
+
+
+
+ private void injectFactories(OFMessage ofm) {
+ if (ofm instanceof OFActionFactoryAware) {
+ ((OFActionFactoryAware)ofm).setActionFactory(this);
+ }
+ if (ofm instanceof OFMessageFactoryAware) {
+ ((OFMessageFactoryAware)ofm).setMessageFactory(this);
+ }
+ if (ofm instanceof OFStatisticsFactoryAware) {
+ ((OFStatisticsFactoryAware)ofm).setStatisticsFactory(this);
+ }
+ if (ofm instanceof OFVendorDataFactoryAware) {
+ ((OFVendorDataFactoryAware)ofm).setVendorDataFactory(this);
+ }
+ }
+
+ @Override
+ public OFAction getAction(OFActionType t) {
+ return t.newInstance();
+ }
+
+ @Override
+ public List<OFAction> parseActions(ChannelBuffer data, int length) {
+ return parseActions(data, length, 0);
+ }
+
+ @Override
+ public List<OFAction> parseActions(ChannelBuffer data, int length, int limit) {
+ List<OFAction> results = new ArrayList<OFAction>();
+ OFAction demux = new OFAction();
+ OFAction ofa;
+ int end = data.readerIndex() + length;
+
+ while (limit == 0 || results.size() <= limit) {
+ if ((data.readableBytes() < OFAction.MINIMUM_LENGTH ||
+ (data.readerIndex() + OFAction.MINIMUM_LENGTH) > end))
+ return results;
+
+ data.markReaderIndex();
+ demux.readFrom(data);
+ data.resetReaderIndex();
+
+ if ((demux.getLengthU() > data.readableBytes() ||
+ (data.readerIndex() + demux.getLengthU()) > end))
+ return results;
+
+ ofa = parseActionOne(demux.getType(), data);
+ results.add(ofa);
+ }
+
+ return results;
+ }
+
+ private OFAction parseActionOne(OFActionType type, ChannelBuffer data) {
+ OFAction ofa;
+ data.markReaderIndex();
+ ofa = getAction(type);
+ ofa.readFrom(data);
+
+ if(type == OFActionType.VENDOR) {
+ OFActionVendor vendorAction = (OFActionVendor) ofa;
+
+ OFVendorActionFactory vendorActionFactory = vendorActionRegistry.get(vendorAction.getVendor());
+
+ if(vendorActionFactory != null) {
+ // if we have a specific vendorActionFactory for this vendor id,
+ // delegate to it for vendor-specific reparsing of the message
+ data.resetReaderIndex();
+ OFActionVendor newAction = vendorActionFactory.readFrom(data);
+ if(newAction != null)
+ ofa = newAction;
+ }
+ }
+
+ if (OFAction.class.equals(ofa.getClass())) {
+ // advance the position for un-implemented messages
+ data.readerIndex(data.readerIndex()+(ofa.getLengthU() -
+ OFAction.MINIMUM_LENGTH));
+ }
+ return ofa;
+ }
+
+ @Override
+ public OFActionFactory getActionFactory() {
+ return this;
+ }
+
+ @Override
+ public OFStatistics getStatistics(OFType t, OFStatisticsType st) {
+ return st.newInstance(t);
+ }
+
+ @Override
+ public List<OFStatistics> parseStatistics(OFType t, OFStatisticsType st,
+ ChannelBuffer data, int length) {
+ return parseStatistics(t, st, data, length, 0);
+ }
+
+ /**
+ * @param t
+ * OFMessage type: should be one of stats_request or stats_reply
+ * @param st
+ * statistics type of this message, e.g., DESC, TABLE
+ * @param data
+ * buffer to read from
+ * @param length
+ * length of statistics
+ * @param limit
+ * number of statistics to grab; 0 == all
+ *
+ * @return list of statistics
+ */
+
+ @Override
+ public List<OFStatistics> parseStatistics(OFType t, OFStatisticsType st,
+ ChannelBuffer data, int length, int limit) {
+ List<OFStatistics> results = new ArrayList<OFStatistics>();
+ OFStatistics statistics = getStatistics(t, st);
+
+ int start = data.readerIndex();
+ int count = 0;
+
+ while (limit == 0 || results.size() <= limit) {
+ // TODO Create a separate MUX/DEMUX path for vendor stats
+ if (statistics instanceof OFVendorStatistics)
+ ((OFVendorStatistics)statistics).setLength(length);
+
+ /**
+ * can't use data.remaining() here, b/c there could be other data
+ * buffered past this message
+ */
+ if ((length - count) >= statistics.getLength()) {
+ if (statistics instanceof OFActionFactoryAware)
+ ((OFActionFactoryAware)statistics).setActionFactory(this);
+ statistics.readFrom(data);
+ results.add(statistics);
+ count += statistics.getLength();
+ statistics = getStatistics(t, st);
+ } else {
+ if (count < length) {
+ /**
+ * Nasty case: partial/incomplete statistic found even
+ * though we have a full message. Found when NOX sent
+ * agg_stats request with wrong agg statistics length (52
+ * instead of 56)
+ *
+ * just throw the rest away, or we will break framing
+ */
+ data.readerIndex(start + length);
+ }
+ return results;
+ }
+ }
+ return results; // empty; no statistics at all
+ }
+
+
+ @Override
+ public OFVendorData getVendorData(OFVendorId vendorId,
+ OFVendorDataType vendorDataType) {
+ if (vendorDataType == null)
+ return null;
+
+ return vendorDataType.newInstance();
+ }
+
+ /**
+ * Attempts to parse and return the OFVendorData contained in the given
+ * ChannelBuffer, beginning right after the vendor id.
+ * @param vendor the vendor id that was parsed from the OFVendor message.
+ * @param data the ChannelBuffer from which to parse the vendor data
+ * @param length the length to the end of the enclosing message.
+ * @return an OFVendorData instance
+ */
+ @Override
+ public OFVendorData parseVendorData(int vendor, ChannelBuffer data,
+ int length) {
+ OFVendorDataType vendorDataType = null;
+ OFVendorId vendorId = OFVendorId.lookupVendorId(vendor);
+ if (vendorId != null) {
+ data.markReaderIndex();
+ vendorDataType = vendorId.parseVendorDataType(data, length);
+ data.resetReaderIndex();
+ }
+
+ OFVendorData vendorData = getVendorData(vendorId, vendorDataType);
+ if (vendorData == null)
+ vendorData = new OFByteArrayVendorData();
+
+ vendorData.readFrom(data, length);
+
+ return vendorData;
+ }
+
+ public static String dumpBuffer(ChannelBuffer data) {
+ // NOTE: Reads all the bytes in buffer from current read offset.
+ // Set/Reset ReaderIndex if you want to read from a different location
+ int len = data.readableBytes();
+ StringBuffer sb = new StringBuffer();
+ for (int i=0 ; i<len; i++) {
+ if (i%32 == 0) sb.append("\n");
+ if (i%4 == 0) sb.append(" ");
+ sb.append(String.format("%02x", data.getUnsignedByte(i)));
+ }
+ return sb.toString();
+ }
+
+}
--- /dev/null
+/**
+ * Copyright 2013, Big Switch Networks, Inc.
+ *
+ * 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 org.openflow.protocol.factory;
+
+/**
+ * Exception thrown when an openflow message fails to parse properly
+ */
+public class MessageParseException extends Exception {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -75893812926304726L;
+
+ public MessageParseException() {
+ super();
+ }
+
+ public MessageParseException(String message, Throwable cause) {
+ super(message, cause);
+ this.setStackTrace(cause.getStackTrace());
+ }
+
+ public MessageParseException(String message) {
+ super(message);
+ }
+
+ public MessageParseException(Throwable cause) {
+ super(cause);
+ this.setStackTrace(cause.getStackTrace());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.factory;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionType;
+
+
+/**
+ * The interface to factories used for retrieving OFAction instances. All
+ * methods are expected to be thread-safe.
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public interface OFActionFactory {
+ /**
+ * Retrieves an OFAction instance corresponding to the specified
+ * OFActionType
+ * @param t the type of the OFAction to be retrieved
+ * @return an OFAction instance
+ */
+ public OFAction getAction(OFActionType t);
+
+ /**
+ * Attempts to parse and return all OFActions contained in the given
+ * ByteBuffer, beginning at the ByteBuffer's position, and ending at
+ * position+length.
+ * @param data the ChannelBuffer to parse for OpenFlow actions
+ * @param length the number of Bytes to examine for OpenFlow actions
+ * @return a list of OFAction instances
+ */
+ public List<OFAction> parseActions(ChannelBuffer data, int length);
+
+ /**
+ * Attempts to parse and return all OFActions contained in the given
+ * ByteBuffer, beginning at the ByteBuffer's position, and ending at
+ * position+length.
+ * @param data the ChannelBuffer to parse for OpenFlow actions
+ * @param length the number of Bytes to examine for OpenFlow actions
+ * @param limit the maximum number of messages to return, 0 means no limit
+ * @return a list of OFAction instances
+ */
+ public List<OFAction> parseActions(ChannelBuffer data, int length, int limit);
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.factory;
+
+/**
+ * Objects implementing this interface are expected to be instantiated with an
+ * instance of an OFActionFactory
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public interface OFActionFactoryAware {
+ /**
+ * Sets the OFActionFactory
+ * @param actionFactory
+ */
+ public void setActionFactory(OFActionFactory actionFactory);
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.factory;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFType;
+
+
+/**
+ * The interface to factories used for retrieving OFMessage instances. All
+ * methods are expected to be thread-safe.
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public interface OFMessageFactory {
+ /**
+ * Retrieves an OFMessage instance corresponding to the specified OFType
+ * @param t the type of the OFMessage to be retrieved
+ * @return an OFMessage instance
+ */
+ public OFMessage getMessage(OFType t);
+
+ /**
+ * Attempts to parse and return a OFMessages contained in the given
+ * ChannelBuffer, beginning at the ChannelBuffer's position, and ending at the
+ * after the first parsed message
+ * @param data the ChannelBuffer to parse for an OpenFlow message
+ * @return a list of OFMessage instances
+ * @throws MessageParseException
+ */
+ public List<OFMessage> parseMessage(ChannelBuffer data) throws MessageParseException;
+
+ /**
+ * Retrieves an OFActionFactory
+ * @return an OFActionFactory
+ */
+ public OFActionFactory getActionFactory();
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.factory;
+
+/**
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ *
+ */
+public interface OFMessageFactoryAware {
+
+ /**
+ * Sets the message factory for this object
+ *
+ * @param factory
+ */
+ void setMessageFactory(OFMessageFactory factory);
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.factory;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.statistics.OFStatistics;
+import org.openflow.protocol.statistics.OFStatisticsType;
+
+
+/**
+ * The interface to factories used for retrieving OFStatistics instances. All
+ * methods are expected to be thread-safe.
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public interface OFStatisticsFactory {
+ /**
+ * Retrieves an OFStatistics instance corresponding to the specified
+ * OFStatisticsType
+ * @param t the type of the containing OFMessage, only accepts statistics
+ * request or reply
+ * @param st the type of the OFStatistics to be retrieved
+ * @return an OFStatistics instance
+ */
+ public OFStatistics getStatistics(OFType t, OFStatisticsType st);
+
+ /**
+ * Attempts to parse and return all OFStatistics contained in the given
+ * ByteBuffer, beginning at the ByteBuffer's position, and ending at
+ * position+length.
+ * @param t the type of the containing OFMessage, only accepts statistics
+ * request or reply
+ * @param st the type of the OFStatistics to be retrieved
+ * @param data the ChannelBuffer to parse for OpenFlow Statistics
+ * @param length the number of Bytes to examine for OpenFlow Statistics
+ * @return a list of OFStatistics instances
+ */
+ public List<OFStatistics> parseStatistics(OFType t,
+ OFStatisticsType st, ChannelBuffer data, int length);
+
+ /**
+ * Attempts to parse and return all OFStatistics contained in the given
+ * ByteBuffer, beginning at the ByteBuffer's position, and ending at
+ * position+length.
+ * @param t the type of the containing OFMessage, only accepts statistics
+ * request or reply
+ * @param st the type of the OFStatistics to be retrieved
+ * @param data the ChannelBuffer to parse for OpenFlow Statistics
+ * @param length the number of Bytes to examine for OpenFlow Statistics
+ * @param limit the maximum number of messages to return, 0 means no limit
+ * @return a list of OFStatistics instances
+ */
+ public List<OFStatistics> parseStatistics(OFType t,
+ OFStatisticsType st, ChannelBuffer data, int length, int limit);
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.factory;
+
+/**
+ * Objects implementing this interface are expected to be instantiated with an
+ * instance of an OFStatisticsFactory
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public interface OFStatisticsFactoryAware {
+ /**
+ * Sets the OFStatisticsFactory
+ * @param statisticsFactory
+ */
+ public void setStatisticsFactory(OFStatisticsFactory statisticsFactory);
+}
--- /dev/null
+/**
+ * Copyright 2013, Big Switch Networks, Inc.
+ *
+ * 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 org.openflow.protocol.factory;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.action.OFActionVendor;
+
+/** Interface contract for an actionfactory that creates vendor-specific actions.
+ * VendorActionFactories are registered with the BasicFactory for a specific
+ * vendor id.
+ * <p>
+ * <b>Note:</b> Implementations are expected to be thread-safe.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public interface OFVendorActionFactory {
+
+ /** parse the data from the wire, create and return a vendor-specific action.
+ *
+ * @param data contains a serialized vendor action at the current readerPosition.
+ * The full message is guaranteed to be available in the buffer.
+ *
+ * @return upon success returns a newly allocated vendor-specific
+ * action instance, and advances the readerPosition in data for the
+ * entire length. Upon failure, returns null and leaves the readerPosition
+ * in data unmodified.
+ */
+ OFActionVendor readFrom(ChannelBuffer data);
+}
--- /dev/null
+/**
+ * Copyright 2013, Big Switch Networks, Inc.
+ *
+ * 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 org.openflow.protocol.factory;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/** Singleton registry object that holds a mapping from vendor ids to vendor-specific
+ * mapping factories. Threadsafe.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class OFVendorActionRegistry {
+ private static class InstanceHolder {
+ private final static OFVendorActionRegistry instance = new OFVendorActionRegistry();
+ }
+
+ public static OFVendorActionRegistry getInstance() {
+ return InstanceHolder.instance;
+ }
+ private final Map <Integer, OFVendorActionFactory> vendorActionFactories;
+
+ public OFVendorActionRegistry() {
+ vendorActionFactories = new ConcurrentHashMap<Integer, OFVendorActionFactory>();
+ }
+
+ public OFVendorActionFactory register(int vendorId, OFVendorActionFactory factory) {
+ return vendorActionFactories.put(vendorId, factory);
+ }
+
+ public OFVendorActionFactory get(int vendorId) {
+ return vendorActionFactories.get(vendorId);
+ }
+
+
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.factory;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.vendor.OFVendorData;
+import org.openflow.protocol.vendor.OFVendorDataType;
+import org.openflow.protocol.vendor.OFVendorId;
+
+/**
+ * The interface to factories used for parsing/creating OFVendorData instances.
+ * All methods are expected to be thread-safe.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public interface OFVendorDataFactory {
+ /**
+ * Retrieves an OFVendorData instance corresponding to the specified
+ * OFVendorId and OFVendorDataType. There are 3 possible cases for
+ * how this will be called:
+ *
+ * 1) If the vendor id in the OFVendor message is an unknown value,
+ * then this method is called with both vendorId and vendorDataType
+ * set to null. In this case typically the factory method should
+ * return an instance of OFGenericVendorData that just contains
+ * the raw byte array of the vendor data.
+ *
+ * 2) If the vendor id is known but no vendor data type has been
+ * registered for the data in the message, then vendorId is set to
+ * the appropriate OFVendorId instance and OFVendorDataType is set
+ * to null. This would typically be handled the same way as #1
+ *
+ * 3) If both the vendor id and and vendor data type are known, then
+ * typically you'd just call the method in OFVendorDataType to
+ * instantiate the appropriate subclass of OFVendorData.
+ *
+ * @param vendorId the vendorId of the containing OFVendor message
+ * @param vendorDataType the type of the OFVendorData to be retrieved
+ * @return an OFVendorData instance
+ */
+ public OFVendorData getVendorData(OFVendorId vendorId,
+ OFVendorDataType vendorDataType);
+
+ /**
+ * Attempts to parse and return the OFVendorData contained in the given
+ * ChannelBuffer, beginning right after the vendor id.
+ * @param vendorId the vendor id that was parsed from the OFVendor message.
+ * @param data the ChannelBuffer from which to parse the vendor data
+ * @param length the length to the end of the enclosing message.
+ * @return an OFVendorData instance
+ */
+ public OFVendorData parseVendorData(int vendorId, ChannelBuffer data,
+ int length);
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.factory;
+
+/**
+ * Classes implementing this interface are expected to be instantiated with an
+ * instance of an OFVendorDataFactory
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public interface OFVendorDataFactoryAware {
+ public void setVendorDataFactory(OFVendorDataFactory vendorDataFactory);
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_aggregate_stats_reply structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFAggregateStatisticsReply implements OFStatistics {
+ protected long packetCount;
+ protected long byteCount;
+ protected int flowCount;
+
+ /**
+ * @return the packetCount
+ */
+ public long getPacketCount() {
+ return packetCount;
+ }
+
+ /**
+ * @param packetCount the packetCount to set
+ */
+ public void setPacketCount(long packetCount) {
+ this.packetCount = packetCount;
+ }
+
+ /**
+ * @return the byteCount
+ */
+ public long getByteCount() {
+ return byteCount;
+ }
+
+ /**
+ * @param byteCount the byteCount to set
+ */
+ public void setByteCount(long byteCount) {
+ this.byteCount = byteCount;
+ }
+
+ /**
+ * @return the flowCount
+ */
+ public int getFlowCount() {
+ return flowCount;
+ }
+
+ /**
+ * @param flowCount the flowCount to set
+ */
+ public void setFlowCount(int flowCount) {
+ this.flowCount = flowCount;
+ }
+
+ @Override
+ public int getLength() {
+ return 24;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.packetCount = data.readLong();
+ this.byteCount = data.readLong();
+ this.flowCount = data.readInt();
+ data.readInt(); // pad
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeLong(this.packetCount);
+ data.writeLong(this.byteCount);
+ data.writeInt(this.flowCount);
+ data.writeInt(0); // pad
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 397;
+ int result = 1;
+ result = prime * result + (int) (byteCount ^ (byteCount >>> 32));
+ result = prime * result + flowCount;
+ result = prime * result + (int) (packetCount ^ (packetCount >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFAggregateStatisticsReply)) {
+ return false;
+ }
+ OFAggregateStatisticsReply other = (OFAggregateStatisticsReply) obj;
+ if (byteCount != other.byteCount) {
+ return false;
+ }
+ if (flowCount != other.flowCount) {
+ return false;
+ }
+ if (packetCount != other.packetCount) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFMatch;
+
+/**
+ * Represents an ofp_aggregate_stats_request structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFAggregateStatisticsRequest implements OFStatistics {
+ protected OFMatch match;
+ protected byte tableId;
+ protected short outPort;
+
+ /**
+ * @return the match
+ */
+ public OFMatch getMatch() {
+ return match;
+ }
+
+ /**
+ * @param match the match to set
+ */
+ public void setMatch(OFMatch match) {
+ this.match = match;
+ }
+
+ /**
+ * @return the tableId
+ */
+ public byte getTableId() {
+ return tableId;
+ }
+
+ /**
+ * @param tableId the tableId to set
+ */
+ public void setTableId(byte tableId) {
+ this.tableId = tableId;
+ }
+
+ /**
+ * @return the outPort
+ */
+ public short getOutPort() {
+ return outPort;
+ }
+
+ /**
+ * @param outPort the outPort to set
+ */
+ public void setOutPort(short outPort) {
+ this.outPort = outPort;
+ }
+
+ @Override
+ public int getLength() {
+ return 44;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ if (this.match == null)
+ this.match = new OFMatch();
+ this.match.readFrom(data);
+ this.tableId = data.readByte();
+ data.readByte(); // pad
+ this.outPort = data.readShort();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ this.match.writeTo(data);
+ data.writeByte(this.tableId);
+ data.writeByte((byte) 0);
+ data.writeShort(this.outPort);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 401;
+ int result = 1;
+ result = prime * result + ((match == null) ? 0 : match.hashCode());
+ result = prime * result + outPort;
+ result = prime * result + tableId;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFAggregateStatisticsRequest)) {
+ return false;
+ }
+ OFAggregateStatisticsRequest other = (OFAggregateStatisticsRequest) obj;
+ if (match == null) {
+ if (other.match != null) {
+ return false;
+ }
+ } else if (!match.equals(other.match)) {
+ return false;
+ }
+ if (outPort != other.outPort) {
+ return false;
+ }
+ if (tableId != other.tableId) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.StringByteSerializer;
+
+/**
+ * Represents an ofp_desc_stats structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFDescriptionStatistics implements OFStatistics {
+ public static int DESCRIPTION_STRING_LENGTH = 256;
+ public static int SERIAL_NUMBER_LENGTH = 32;
+
+ protected String manufacturerDescription;
+ protected String hardwareDescription;
+ protected String softwareDescription;
+ protected String serialNumber;
+ protected String datapathDescription;
+
+ /**
+ * @return the manufacturerDescription
+ */
+ public String getManufacturerDescription() {
+ return manufacturerDescription;
+ }
+
+ /**
+ * @param manufacturerDescription the manufacturerDescription to set
+ */
+ public void setManufacturerDescription(String manufacturerDescription) {
+ this.manufacturerDescription = manufacturerDescription;
+ }
+
+ /**
+ * @return the hardwareDescription
+ */
+ public String getHardwareDescription() {
+ return hardwareDescription;
+ }
+
+ /**
+ * @param hardwareDescription the hardwareDescription to set
+ */
+ public void setHardwareDescription(String hardwareDescription) {
+ this.hardwareDescription = hardwareDescription;
+ }
+
+ /**
+ * @return the softwareDescription
+ */
+ public String getSoftwareDescription() {
+ return softwareDescription;
+ }
+
+ /**
+ * @param softwareDescription the softwareDescription to set
+ */
+ public void setSoftwareDescription(String softwareDescription) {
+ this.softwareDescription = softwareDescription;
+ }
+
+ /**
+ * @return the serialNumber
+ */
+ public String getSerialNumber() {
+ return serialNumber;
+ }
+
+ /**
+ * @param serialNumber the serialNumber to set
+ */
+ public void setSerialNumber(String serialNumber) {
+ this.serialNumber = serialNumber;
+ }
+
+ /**
+ * @return the datapathDescription
+ */
+ public String getDatapathDescription() {
+ return datapathDescription;
+ }
+
+ /**
+ * @param datapathDescription the datapathDescription to set
+ */
+ public void setDatapathDescription(String datapathDescription) {
+ this.datapathDescription = datapathDescription;
+ }
+
+ @Override
+ public int getLength() {
+ return 1056;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.manufacturerDescription = StringByteSerializer.readFrom(data,
+ DESCRIPTION_STRING_LENGTH);
+ this.hardwareDescription = StringByteSerializer.readFrom(data,
+ DESCRIPTION_STRING_LENGTH);
+ this.softwareDescription = StringByteSerializer.readFrom(data,
+ DESCRIPTION_STRING_LENGTH);
+ this.serialNumber = StringByteSerializer.readFrom(data,
+ SERIAL_NUMBER_LENGTH);
+ this.datapathDescription = StringByteSerializer.readFrom(data,
+ DESCRIPTION_STRING_LENGTH);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
+ this.manufacturerDescription);
+ StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
+ this.hardwareDescription);
+ StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
+ this.softwareDescription);
+ StringByteSerializer.writeTo(data, SERIAL_NUMBER_LENGTH,
+ this.serialNumber);
+ StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
+ this.datapathDescription);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 409;
+ int result = 1;
+ result = prime
+ * result
+ + ((datapathDescription == null) ? 0 : datapathDescription
+ .hashCode());
+ result = prime
+ * result
+ + ((hardwareDescription == null) ? 0 : hardwareDescription
+ .hashCode());
+ result = prime
+ * result
+ + ((manufacturerDescription == null) ? 0
+ : manufacturerDescription.hashCode());
+ result = prime * result
+ + ((serialNumber == null) ? 0 : serialNumber.hashCode());
+ result = prime
+ * result
+ + ((softwareDescription == null) ? 0 : softwareDescription
+ .hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFDescriptionStatistics)) {
+ return false;
+ }
+ OFDescriptionStatistics other = (OFDescriptionStatistics) obj;
+ if (datapathDescription == null) {
+ if (other.datapathDescription != null) {
+ return false;
+ }
+ } else if (!datapathDescription.equals(other.datapathDescription)) {
+ return false;
+ }
+ if (hardwareDescription == null) {
+ if (other.hardwareDescription != null) {
+ return false;
+ }
+ } else if (!hardwareDescription.equals(other.hardwareDescription)) {
+ return false;
+ }
+ if (manufacturerDescription == null) {
+ if (other.manufacturerDescription != null) {
+ return false;
+ }
+ } else if (!manufacturerDescription
+ .equals(other.manufacturerDescription)) {
+ return false;
+ }
+ if (serialNumber == null) {
+ if (other.serialNumber != null) {
+ return false;
+ }
+ } else if (!serialNumber.equals(other.serialNumber)) {
+ return false;
+ }
+ if (softwareDescription == null) {
+ if (other.softwareDescription != null) {
+ return false;
+ }
+ } else if (!softwareDescription.equals(other.softwareDescription)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Switch Desc - Vendor: " + manufacturerDescription +
+ " Model: " + hardwareDescription +
+ " Make: " + datapathDescription +
+ " Version: " + softwareDescription +
+ " S/N: " + serialNumber;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.factory.OFActionFactory;
+import org.openflow.protocol.factory.OFActionFactoryAware;
+import org.openflow.util.U16;
+
+/**
+ * Represents an ofp_flow_stats structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFFlowStatisticsReply implements OFStatistics, OFActionFactoryAware {
+ public static int MINIMUM_LENGTH = 88;
+
+ protected OFActionFactory actionFactory;
+ protected short length = (short) MINIMUM_LENGTH;
+ protected byte tableId;
+ protected OFMatch match;
+ protected int durationSeconds;
+ protected int durationNanoseconds;
+ protected short priority;
+ protected short idleTimeout;
+ protected short hardTimeout;
+ protected long cookie;
+ protected long packetCount;
+ protected long byteCount;
+ protected List<OFAction> actions;
+
+ /**
+ * @return the tableId
+ */
+ public byte getTableId() {
+ return tableId;
+ }
+
+ /**
+ * @param tableId the tableId to set
+ */
+ public void setTableId(byte tableId) {
+ this.tableId = tableId;
+ }
+
+ /**
+ * @return the match
+ */
+ public OFMatch getMatch() {
+ return match;
+ }
+
+ /**
+ * @param match the match to set
+ */
+ public void setMatch(OFMatch match) {
+ this.match = match;
+ }
+
+ /**
+ * @return the durationSeconds
+ */
+ public int getDurationSeconds() {
+ return durationSeconds;
+ }
+
+ /**
+ * @param durationSeconds the durationSeconds to set
+ */
+ public void setDurationSeconds(int durationSeconds) {
+ this.durationSeconds = durationSeconds;
+ }
+
+ /**
+ * @return the durationNanoseconds
+ */
+ public int getDurationNanoseconds() {
+ return durationNanoseconds;
+ }
+
+ /**
+ * @param durationNanoseconds the durationNanoseconds to set
+ */
+ public void setDurationNanoseconds(int durationNanoseconds) {
+ this.durationNanoseconds = durationNanoseconds;
+ }
+
+ /**
+ * @return the priority
+ */
+ public short getPriority() {
+ return priority;
+ }
+
+ /**
+ * @param priority the priority to set
+ */
+ public void setPriority(short priority) {
+ this.priority = priority;
+ }
+
+ /**
+ * @return the idleTimeout
+ */
+ public short getIdleTimeout() {
+ return idleTimeout;
+ }
+
+ /**
+ * @param idleTimeout the idleTimeout to set
+ */
+ public void setIdleTimeout(short idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ }
+
+ /**
+ * @return the hardTimeout
+ */
+ public short getHardTimeout() {
+ return hardTimeout;
+ }
+
+ /**
+ * @param hardTimeout the hardTimeout to set
+ */
+ public void setHardTimeout(short hardTimeout) {
+ this.hardTimeout = hardTimeout;
+ }
+
+ /**
+ * @return the cookie
+ */
+ public long getCookie() {
+ return cookie;
+ }
+
+ /**
+ * @param cookie the cookie to set
+ */
+ public void setCookie(long cookie) {
+ this.cookie = cookie;
+ }
+
+ /**
+ * @return the packetCount
+ */
+ public long getPacketCount() {
+ return packetCount;
+ }
+
+ /**
+ * @param packetCount the packetCount to set
+ */
+ public void setPacketCount(long packetCount) {
+ this.packetCount = packetCount;
+ }
+
+ /**
+ * @return the byteCount
+ */
+ public long getByteCount() {
+ return byteCount;
+ }
+
+ /**
+ * @param byteCount the byteCount to set
+ */
+ public void setByteCount(long byteCount) {
+ this.byteCount = byteCount;
+ }
+
+ /**
+ * @param length the length to set
+ */
+ public void setLength(short length) {
+ this.length = length;
+ }
+
+ @Override
+ public int getLength() {
+ return U16.f(length);
+ }
+
+ /**
+ * @param actionFactory the actionFactory to set
+ */
+ @Override
+ public void setActionFactory(OFActionFactory actionFactory) {
+ this.actionFactory = actionFactory;
+ }
+
+ /**
+ * @return the actions
+ */
+ public List<OFAction> getActions() {
+ return actions;
+ }
+
+ /**
+ * @param actions the actions to set
+ */
+ public void setActions(List<OFAction> actions) {
+ this.actions = actions;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.length = data.readShort();
+ this.tableId = data.readByte();
+ data.readByte(); // pad
+ if (this.match == null)
+ this.match = new OFMatch();
+ this.match.readFrom(data);
+ this.durationSeconds = data.readInt();
+ this.durationNanoseconds = data.readInt();
+ this.priority = data.readShort();
+ this.idleTimeout = data.readShort();
+ this.hardTimeout = data.readShort();
+ data.readInt(); // pad
+ data.readShort(); // pad
+ this.cookie = data.readLong();
+ this.packetCount = data.readLong();
+ this.byteCount = data.readLong();
+ if (this.actionFactory == null)
+ throw new RuntimeException("OFActionFactory not set");
+ this.actions = this.actionFactory.parseActions(data, getLength() -
+ MINIMUM_LENGTH);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(this.length);
+ data.writeByte(this.tableId);
+ data.writeByte((byte) 0);
+ this.match.writeTo(data);
+ data.writeInt(this.durationSeconds);
+ data.writeInt(this.durationNanoseconds);
+ data.writeShort(this.priority);
+ data.writeShort(this.idleTimeout);
+ data.writeShort(this.hardTimeout);
+ data.writeInt(0); // pad
+ data.writeShort((short)0); // pad
+ data.writeLong(this.cookie);
+ data.writeLong(this.packetCount);
+ data.writeLong(this.byteCount);
+ if (actions != null) {
+ for (OFAction action : actions) {
+ action.writeTo(data);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ String str = "match=" + this.match;
+ str += " tableId=" + this.tableId;
+ str += " durationSeconds=" + this.durationSeconds;
+ str += " durationNanoseconds=" + this.durationNanoseconds;
+ str += " priority=" + this.priority;
+ str += " idleTimeout=" + this.idleTimeout;
+ str += " hardTimeout=" + this.hardTimeout;
+ str += " cookie=" + this.cookie;
+ str += " packetCount=" + this.packetCount;
+ str += " byteCount=" + this.byteCount;
+ str += " action=" + this.actions;
+
+ return str;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 419;
+ int result = 1;
+ result = prime * result + (int) (byteCount ^ (byteCount >>> 32));
+ result = prime * result + (int) (cookie ^ (cookie >>> 32));
+ result = prime * result + durationNanoseconds;
+ result = prime * result + durationSeconds;
+ result = prime * result + hardTimeout;
+ result = prime * result + idleTimeout;
+ result = prime * result + length;
+ result = prime * result + ((match == null) ? 0 : match.hashCode());
+ result = prime * result + (int) (packetCount ^ (packetCount >>> 32));
+ result = prime * result + priority;
+ result = prime * result + tableId;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFFlowStatisticsReply)) {
+ return false;
+ }
+ OFFlowStatisticsReply other = (OFFlowStatisticsReply) obj;
+ if (byteCount != other.byteCount) {
+ return false;
+ }
+ if (cookie != other.cookie) {
+ return false;
+ }
+ if (durationNanoseconds != other.durationNanoseconds) {
+ return false;
+ }
+ if (durationSeconds != other.durationSeconds) {
+ return false;
+ }
+ if (hardTimeout != other.hardTimeout) {
+ return false;
+ }
+ if (idleTimeout != other.idleTimeout) {
+ return false;
+ }
+ if (length != other.length) {
+ return false;
+ }
+ if (match == null) {
+ if (other.match != null) {
+ return false;
+ }
+ } else if (!match.equals(other.match)) {
+ return false;
+ }
+ if (packetCount != other.packetCount) {
+ return false;
+ }
+ if (priority != other.priority) {
+ return false;
+ }
+ if (tableId != other.tableId) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFMatch;
+
+/**
+ * Represents an ofp_flow_stats_request structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFFlowStatisticsRequest implements OFStatistics {
+ protected OFMatch match;
+ protected byte tableId;
+ protected short outPort;
+
+ /**
+ * @return the match
+ */
+ public OFMatch getMatch() {
+ return match;
+ }
+
+ /**
+ * @param match the match to set
+ */
+ public void setMatch(OFMatch match) {
+ this.match = match;
+ }
+
+ /**
+ * @return the tableId
+ */
+ public byte getTableId() {
+ return tableId;
+ }
+
+ /**
+ * @param tableId the tableId to set
+ */
+ public void setTableId(byte tableId) {
+ this.tableId = tableId;
+ }
+
+ /**
+ * @return the outPort
+ */
+ public short getOutPort() {
+ return outPort;
+ }
+
+ /**
+ * @param outPort the outPort to set
+ */
+ public void setOutPort(short outPort) {
+ this.outPort = outPort;
+ }
+
+ @Override
+ public int getLength() {
+ return 44;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ if (this.match == null)
+ this.match = new OFMatch();
+ this.match.readFrom(data);
+ this.tableId = data.readByte();
+ data.readByte(); // pad
+ this.outPort = data.readShort();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ this.match.writeTo(data);
+ data.writeByte(this.tableId);
+ data.writeByte((byte) 0);
+ data.writeShort(this.outPort);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 421;
+ int result = 1;
+ result = prime * result + ((match == null) ? 0 : match.hashCode());
+ result = prime * result + outPort;
+ result = prime * result + tableId;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFFlowStatisticsRequest)) {
+ return false;
+ }
+ OFFlowStatisticsRequest other = (OFFlowStatisticsRequest) obj;
+ if (match == null) {
+ if (other.match != null) {
+ return false;
+ }
+ } else if (!match.equals(other.match)) {
+ return false;
+ }
+ if (outPort != other.outPort) {
+ return false;
+ }
+ if (tableId != other.tableId) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_port_stats structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFPortStatisticsReply implements OFStatistics {
+ protected short portNumber;
+ protected long receivePackets;
+ protected long transmitPackets;
+ protected long receiveBytes;
+ protected long transmitBytes;
+ protected long receiveDropped;
+ protected long transmitDropped;
+ protected long receiveErrors;
+ protected long transmitErrors;
+ protected long receiveFrameErrors;
+ protected long receiveOverrunErrors;
+ protected long receiveCRCErrors;
+ protected long collisions;
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ /**
+ * @return the receivePackets
+ */
+ public long getreceivePackets() {
+ return receivePackets;
+ }
+
+ /**
+ * @param receivePackets the receivePackets to set
+ */
+ public void setreceivePackets(long receivePackets) {
+ this.receivePackets = receivePackets;
+ }
+
+ /**
+ * @return the transmitPackets
+ */
+ public long getTransmitPackets() {
+ return transmitPackets;
+ }
+
+ /**
+ * @param transmitPackets the transmitPackets to set
+ */
+ public void setTransmitPackets(long transmitPackets) {
+ this.transmitPackets = transmitPackets;
+ }
+
+ /**
+ * @return the receiveBytes
+ */
+ public long getReceiveBytes() {
+ return receiveBytes;
+ }
+
+ /**
+ * @param receiveBytes the receiveBytes to set
+ */
+ public void setReceiveBytes(long receiveBytes) {
+ this.receiveBytes = receiveBytes;
+ }
+
+ /**
+ * @return the transmitBytes
+ */
+ public long getTransmitBytes() {
+ return transmitBytes;
+ }
+
+ /**
+ * @param transmitBytes the transmitBytes to set
+ */
+ public void setTransmitBytes(long transmitBytes) {
+ this.transmitBytes = transmitBytes;
+ }
+
+ /**
+ * @return the receiveDropped
+ */
+ public long getReceiveDropped() {
+ return receiveDropped;
+ }
+
+ /**
+ * @param receiveDropped the receiveDropped to set
+ */
+ public void setReceiveDropped(long receiveDropped) {
+ this.receiveDropped = receiveDropped;
+ }
+
+ /**
+ * @return the transmitDropped
+ */
+ public long getTransmitDropped() {
+ return transmitDropped;
+ }
+
+ /**
+ * @param transmitDropped the transmitDropped to set
+ */
+ public void setTransmitDropped(long transmitDropped) {
+ this.transmitDropped = transmitDropped;
+ }
+
+ /**
+ * @return the receiveErrors
+ */
+ public long getreceiveErrors() {
+ return receiveErrors;
+ }
+
+ /**
+ * @param receiveErrors the receiveErrors to set
+ */
+ public void setreceiveErrors(long receiveErrors) {
+ this.receiveErrors = receiveErrors;
+ }
+
+ /**
+ * @return the transmitErrors
+ */
+ public long getTransmitErrors() {
+ return transmitErrors;
+ }
+
+ /**
+ * @param transmitErrors the transmitErrors to set
+ */
+ public void setTransmitErrors(long transmitErrors) {
+ this.transmitErrors = transmitErrors;
+ }
+
+ /**
+ * @return the receiveFrameErrors
+ */
+ public long getReceiveFrameErrors() {
+ return receiveFrameErrors;
+ }
+
+ /**
+ * @param receiveFrameErrors the receiveFrameErrors to set
+ */
+ public void setReceiveFrameErrors(long receiveFrameErrors) {
+ this.receiveFrameErrors = receiveFrameErrors;
+ }
+
+ /**
+ * @return the receiveOverrunErrors
+ */
+ public long getReceiveOverrunErrors() {
+ return receiveOverrunErrors;
+ }
+
+ /**
+ * @param receiveOverrunErrors the receiveOverrunErrors to set
+ */
+ public void setReceiveOverrunErrors(long receiveOverrunErrors) {
+ this.receiveOverrunErrors = receiveOverrunErrors;
+ }
+
+ /**
+ * @return the receiveCRCErrors
+ */
+ public long getReceiveCRCErrors() {
+ return receiveCRCErrors;
+ }
+
+ /**
+ * @param receiveCRCErrors the receiveCRCErrors to set
+ */
+ public void setReceiveCRCErrors(long receiveCRCErrors) {
+ this.receiveCRCErrors = receiveCRCErrors;
+ }
+
+ /**
+ * @return the collisions
+ */
+ public long getCollisions() {
+ return collisions;
+ }
+
+ /**
+ * @param collisions the collisions to set
+ */
+ public void setCollisions(long collisions) {
+ this.collisions = collisions;
+ }
+
+ @Override
+ public int getLength() {
+ return 104;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.portNumber = data.readShort();
+ data.readShort(); // pad
+ data.readInt(); // pad
+ this.receivePackets = data.readLong();
+ this.transmitPackets = data.readLong();
+ this.receiveBytes = data.readLong();
+ this.transmitBytes = data.readLong();
+ this.receiveDropped = data.readLong();
+ this.transmitDropped = data.readLong();
+ this.receiveErrors = data.readLong();
+ this.transmitErrors = data.readLong();
+ this.receiveFrameErrors = data.readLong();
+ this.receiveOverrunErrors = data.readLong();
+ this.receiveCRCErrors = data.readLong();
+ this.collisions = data.readLong();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(this.portNumber);
+ data.writeShort((short) 0); // pad
+ data.writeInt(0); // pad
+ data.writeLong(this.receivePackets);
+ data.writeLong(this.transmitPackets);
+ data.writeLong(this.receiveBytes);
+ data.writeLong(this.transmitBytes);
+ data.writeLong(this.receiveDropped);
+ data.writeLong(this.transmitDropped);
+ data.writeLong(this.receiveErrors);
+ data.writeLong(this.transmitErrors);
+ data.writeLong(this.receiveFrameErrors);
+ data.writeLong(this.receiveOverrunErrors);
+ data.writeLong(this.receiveCRCErrors);
+ data.writeLong(this.collisions);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 431;
+ int result = 1;
+ result = prime * result + (int) (collisions ^ (collisions >>> 32));
+ result = prime * result + portNumber;
+ result = prime * result
+ + (int) (receivePackets ^ (receivePackets >>> 32));
+ result = prime * result + (int) (receiveBytes ^ (receiveBytes >>> 32));
+ result = prime * result
+ + (int) (receiveCRCErrors ^ (receiveCRCErrors >>> 32));
+ result = prime * result
+ + (int) (receiveDropped ^ (receiveDropped >>> 32));
+ result = prime * result
+ + (int) (receiveFrameErrors ^ (receiveFrameErrors >>> 32));
+ result = prime * result
+ + (int) (receiveOverrunErrors ^ (receiveOverrunErrors >>> 32));
+ result = prime * result
+ + (int) (receiveErrors ^ (receiveErrors >>> 32));
+ result = prime * result
+ + (int) (transmitBytes ^ (transmitBytes >>> 32));
+ result = prime * result
+ + (int) (transmitDropped ^ (transmitDropped >>> 32));
+ result = prime * result
+ + (int) (transmitErrors ^ (transmitErrors >>> 32));
+ result = prime * result
+ + (int) (transmitPackets ^ (transmitPackets >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFPortStatisticsReply)) {
+ return false;
+ }
+ OFPortStatisticsReply other = (OFPortStatisticsReply) obj;
+ if (collisions != other.collisions) {
+ return false;
+ }
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ if (receivePackets != other.receivePackets) {
+ return false;
+ }
+ if (receiveBytes != other.receiveBytes) {
+ return false;
+ }
+ if (receiveCRCErrors != other.receiveCRCErrors) {
+ return false;
+ }
+ if (receiveDropped != other.receiveDropped) {
+ return false;
+ }
+ if (receiveFrameErrors != other.receiveFrameErrors) {
+ return false;
+ }
+ if (receiveOverrunErrors != other.receiveOverrunErrors) {
+ return false;
+ }
+ if (receiveErrors != other.receiveErrors) {
+ return false;
+ }
+ if (transmitBytes != other.transmitBytes) {
+ return false;
+ }
+ if (transmitDropped != other.transmitDropped) {
+ return false;
+ }
+ if (transmitErrors != other.transmitErrors) {
+ return false;
+ }
+ if (transmitPackets != other.transmitPackets) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_port_stats_request structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFPortStatisticsRequest implements OFStatistics {
+ protected short portNumber;
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ @Override
+ public int getLength() {
+ return 8;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.portNumber = data.readShort();
+ data.readShort(); // pad
+ data.readInt(); // pad
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(this.portNumber);
+ data.writeShort((short) 0); // pad
+ data.writeInt(0); // pad
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 433;
+ int result = 1;
+ result = prime * result + portNumber;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFPortStatisticsRequest)) {
+ return false;
+ }
+ OFPortStatisticsRequest other = (OFPortStatisticsRequest) obj;
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_queue_stats structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFQueueStatisticsReply implements OFStatistics {
+ protected short portNumber;
+ protected int queueId;
+ protected long transmitBytes;
+ protected long transmitPackets;
+ protected long transmitErrors;
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ /**
+ * @return the queueId
+ */
+ public int getQueueId() {
+ return queueId;
+ }
+
+ /**
+ * @param queueId the queueId to set
+ */
+ public void setQueueId(int queueId) {
+ this.queueId = queueId;
+ }
+
+ /**
+ * @return the transmitBytes
+ */
+ public long getTransmitBytes() {
+ return transmitBytes;
+ }
+
+ /**
+ * @param transmitBytes the transmitBytes to set
+ */
+ public void setTransmitBytes(long transmitBytes) {
+ this.transmitBytes = transmitBytes;
+ }
+
+ /**
+ * @return the transmitPackets
+ */
+ public long getTransmitPackets() {
+ return transmitPackets;
+ }
+
+ /**
+ * @param transmitPackets the transmitPackets to set
+ */
+ public void setTransmitPackets(long transmitPackets) {
+ this.transmitPackets = transmitPackets;
+ }
+
+ /**
+ * @return the transmitErrors
+ */
+ public long getTransmitErrors() {
+ return transmitErrors;
+ }
+
+ /**
+ * @param transmitErrors the transmitErrors to set
+ */
+ public void setTransmitErrors(long transmitErrors) {
+ this.transmitErrors = transmitErrors;
+ }
+
+ @Override
+ public int getLength() {
+ return 32;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.portNumber = data.readShort();
+ data.readShort(); // pad
+ this.queueId = data.readInt();
+ this.transmitBytes = data.readLong();
+ this.transmitPackets = data.readLong();
+ this.transmitErrors = data.readLong();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(this.portNumber);
+ data.writeShort((short) 0); // pad
+ data.writeInt(this.queueId);
+ data.writeLong(this.transmitBytes);
+ data.writeLong(this.transmitPackets);
+ data.writeLong(this.transmitErrors);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 439;
+ int result = 1;
+ result = prime * result + portNumber;
+ result = prime * result + queueId;
+ result = prime * result
+ + (int) (transmitBytes ^ (transmitBytes >>> 32));
+ result = prime * result
+ + (int) (transmitErrors ^ (transmitErrors >>> 32));
+ result = prime * result
+ + (int) (transmitPackets ^ (transmitPackets >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFQueueStatisticsReply)) {
+ return false;
+ }
+ OFQueueStatisticsReply other = (OFQueueStatisticsReply) obj;
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ if (queueId != other.queueId) {
+ return false;
+ }
+ if (transmitBytes != other.transmitBytes) {
+ return false;
+ }
+ if (transmitErrors != other.transmitErrors) {
+ return false;
+ }
+ if (transmitPackets != other.transmitPackets) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents an ofp_queue_stats_request structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFQueueStatisticsRequest implements OFStatistics {
+ protected short portNumber;
+ protected int queueId;
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param portNumber the portNumber to set
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+ /**
+ * @return the queueId
+ */
+ public int getQueueId() {
+ return queueId;
+ }
+
+ /**
+ * @param queueId the queueId to set
+ */
+ public void setQueueId(int queueId) {
+ this.queueId = queueId;
+ }
+
+ @Override
+ public int getLength() {
+ return 8;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.portNumber = data.readShort();
+ data.readShort(); // pad
+ this.queueId = data.readInt();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeShort(this.portNumber);
+ data.writeShort((short) 0); // pad
+ data.writeInt(this.queueId);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 443;
+ int result = 1;
+ result = prime * result + portNumber;
+ result = prime * result + queueId;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFQueueStatisticsRequest)) {
+ return false;
+ }
+ OFQueueStatisticsRequest other = (OFQueueStatisticsRequest) obj;
+ if (portNumber != other.portNumber) {
+ return false;
+ }
+ if (queueId != other.queueId) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * The base class for all OpenFlow statistics.
+ *
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
+ */
+public interface OFStatistics {
+ /**
+ * Returns the wire length of this message in bytes
+ * @return the length
+ */
+ public int getLength();
+
+ /**
+ * Read this message off the wire from the specified ByteBuffer
+ * @param data
+ */
+ public void readFrom(ChannelBuffer data);
+
+ /**
+ * Write this message's binary format to the specified ByteBuffer
+ * @param data
+ */
+ public void writeTo(ChannelBuffer data);
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+import java.lang.reflect.Constructor;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.OFType;
+
+public enum OFStatisticsType {
+ DESC (0, OFDescriptionStatistics.class, OFDescriptionStatistics.class,
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFDescriptionStatistics();
+ }
+ },
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFDescriptionStatistics();
+ }
+ }),
+ FLOW (1, OFFlowStatisticsRequest.class, OFFlowStatisticsReply.class,
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFFlowStatisticsRequest();
+ }
+ },
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFFlowStatisticsReply();
+ }
+ }),
+ AGGREGATE (2, OFAggregateStatisticsRequest.class, OFAggregateStatisticsReply.class,
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFAggregateStatisticsRequest();
+ }
+ },
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFAggregateStatisticsReply();
+ }
+ }),
+ TABLE (3, OFTableStatistics.class, OFTableStatistics.class,
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFTableStatistics();
+ }
+ },
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFTableStatistics();
+ }
+ }),
+ PORT (4, OFPortStatisticsRequest.class, OFPortStatisticsReply.class,
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFPortStatisticsRequest();
+ }
+ },
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFPortStatisticsReply();
+ }
+ }),
+ QUEUE (5, OFQueueStatisticsRequest.class, OFQueueStatisticsReply.class,
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFQueueStatisticsRequest();
+ }
+ },
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFQueueStatisticsReply();
+ }
+ }),
+ VENDOR (0xffff, OFVendorStatistics.class, OFVendorStatistics.class,
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFVendorStatistics();
+ }
+ },
+ new Instantiable<OFStatistics>() {
+ @Override
+ public OFStatistics instantiate() {
+ return new OFVendorStatistics();
+ }
+ });
+
+ static OFStatisticsType[] requestMapping;
+ static OFStatisticsType[] replyMapping;
+
+ protected Class<? extends OFStatistics> requestClass;
+ protected Constructor<? extends OFStatistics> requestConstructor;
+ protected Instantiable<OFStatistics> requestInstantiable;
+ protected Class<? extends OFStatistics> replyClass;
+ protected Constructor<? extends OFStatistics> replyConstructor;
+ protected Instantiable<OFStatistics> replyInstantiable;
+ protected short type;
+
+ /**
+ * Store some information about the OpenFlow Statistic type, including wire
+ * protocol type number, and derived class
+ *
+ * @param type Wire protocol number associated with this OFStatisticsType
+ * @param requestClass The Statistics Java class to return when the
+ * containing OFType is STATS_REQUEST
+ * @param replyClass The Statistics Java class to return when the
+ * containing OFType is STATS_REPLY
+ */
+ OFStatisticsType(int type, Class<? extends OFStatistics> requestClass,
+ Class<? extends OFStatistics> replyClass,
+ Instantiable<OFStatistics> requestInstantiable,
+ Instantiable<OFStatistics> replyInstantiable) {
+ this.type = (short) type;
+ this.requestClass = requestClass;
+ try {
+ this.requestConstructor = requestClass.getConstructor(new Class[]{});
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failure getting constructor for class: " + requestClass, e);
+ }
+
+ this.replyClass = replyClass;
+ try {
+ this.replyConstructor = replyClass.getConstructor(new Class[]{});
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failure getting constructor for class: " + replyClass, e);
+ }
+ this.requestInstantiable = requestInstantiable;
+ this.replyInstantiable = replyInstantiable;
+ OFStatisticsType.addMapping(this.type, OFType.STATS_REQUEST, this);
+ OFStatisticsType.addMapping(this.type, OFType.STATS_REPLY, this);
+ }
+
+ /**
+ * Adds a mapping from type value to OFStatisticsType enum
+ *
+ * @param i OpenFlow wire protocol type
+ * @param t type of containing OFMessage, only accepts STATS_REQUEST or
+ * STATS_REPLY
+ * @param st type
+ */
+ static public void addMapping(short i, OFType t, OFStatisticsType st) {
+ if (i < 0)
+ i = (short) (16+i);
+ if (t == OFType.STATS_REQUEST) {
+ if (requestMapping == null)
+ requestMapping = new OFStatisticsType[16];
+ OFStatisticsType.requestMapping[i] = st;
+ } else if (t == OFType.STATS_REPLY){
+ if (replyMapping == null)
+ replyMapping = new OFStatisticsType[16];
+ OFStatisticsType.replyMapping[i] = st;
+ } else {
+ throw new RuntimeException(t.toString() + " is an invalid OFType");
+ }
+ }
+
+ /**
+ * Remove a mapping from type value to OFStatisticsType enum
+ *
+ * @param i OpenFlow wire protocol type
+ * @param t type of containing OFMessage, only accepts STATS_REQUEST or
+ * STATS_REPLY
+ */
+ static public void removeMapping(short i, OFType t) {
+ if (i < 0)
+ i = (short) (16+i);
+ if (t == OFType.STATS_REQUEST) {
+ requestMapping[i] = null;
+ } else if (t == OFType.STATS_REPLY){
+ replyMapping[i] = null;
+ } else {
+ throw new RuntimeException(t.toString() + " is an invalid OFType");
+ }
+ }
+
+ /**
+ * Given a wire protocol OpenFlow type number, return the OFStatisticsType
+ * associated with it
+ *
+ * @param i wire protocol number
+ * @param t type of containing OFMessage, only accepts STATS_REQUEST or
+ * STATS_REPLY
+ * @return OFStatisticsType enum type
+ */
+ static public OFStatisticsType valueOf(short i, OFType t) {
+ if (i < 0)
+ i = (short) (16+i);
+ if (t == OFType.STATS_REQUEST) {
+ return requestMapping[i];
+ } else if (t == OFType.STATS_REPLY){
+ return replyMapping[i];
+ } else {
+ throw new RuntimeException(t.toString() + " is an invalid OFType");
+ }
+ }
+
+ /**
+ * @return Returns the wire protocol value corresponding to this
+ * OFStatisticsType
+ */
+ public short getTypeValue() {
+ return this.type;
+ }
+
+ /**
+ * @param t type of containing OFMessage, only accepts STATS_REQUEST or
+ * STATS_REPLY
+ * @return return the OFMessage subclass corresponding to this
+ * OFStatisticsType
+ */
+ public Class<? extends OFStatistics> toClass(OFType t) {
+ if (t == OFType.STATS_REQUEST) {
+ return requestClass;
+ } else if (t == OFType.STATS_REPLY){
+ return replyClass;
+ } else {
+ throw new RuntimeException(t.toString() + " is an invalid OFType");
+ }
+ }
+
+ /**
+ * Returns the no-argument Constructor of the implementation class for
+ * this OFStatisticsType, either request or reply based on the supplied
+ * OFType
+ *
+ * @param t
+ * @return
+ */
+ public Constructor<? extends OFStatistics> getConstructor(OFType t) {
+ if (t == OFType.STATS_REQUEST) {
+ return requestConstructor;
+ } else if (t == OFType.STATS_REPLY) {
+ return replyConstructor;
+ } else {
+ throw new RuntimeException(t.toString() + " is an invalid OFType");
+ }
+ }
+
+ /**
+ * @return the requestInstantiable
+ */
+ public Instantiable<OFStatistics> getRequestInstantiable() {
+ return requestInstantiable;
+ }
+
+ /**
+ * @param requestInstantiable the requestInstantiable to set
+ */
+ public void setRequestInstantiable(
+ Instantiable<OFStatistics> requestInstantiable) {
+ this.requestInstantiable = requestInstantiable;
+ }
+
+ /**
+ * @return the replyInstantiable
+ */
+ public Instantiable<OFStatistics> getReplyInstantiable() {
+ return replyInstantiable;
+ }
+
+ /**
+ * @param replyInstantiable the replyInstantiable to set
+ */
+ public void setReplyInstantiable(Instantiable<OFStatistics> replyInstantiable) {
+ this.replyInstantiable = replyInstantiable;
+ }
+
+ /**
+ * Returns a new instance of the implementation class for
+ * this OFStatisticsType, either request or reply based on the supplied
+ * OFType
+ *
+ * @param t
+ * @return
+ */
+ public OFStatistics newInstance(OFType t) {
+ if (t == OFType.STATS_REQUEST) {
+ return requestInstantiable.instantiate();
+ } else if (t == OFType.STATS_REPLY) {
+ return replyInstantiable.instantiate();
+ } else {
+ throw new RuntimeException(t.toString() + " is an invalid OFType");
+ }
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.StringByteSerializer;
+
+/**
+ * Represents an ofp_table_stats structure
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFTableStatistics implements OFStatistics {
+ public static int MAX_TABLE_NAME_LEN = 32;
+
+ protected byte tableId;
+ protected String name;
+ protected int wildcards;
+ protected int maximumEntries;
+ protected int activeCount;
+ protected long lookupCount;
+ protected long matchedCount;
+
+ /**
+ * @return the tableId
+ */
+ public byte getTableId() {
+ return tableId;
+ }
+
+ /**
+ * @param tableId the tableId to set
+ */
+ public void setTableId(byte tableId) {
+ this.tableId = tableId;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the wildcards
+ */
+ public int getWildcards() {
+ return wildcards;
+ }
+
+ /**
+ * @param wildcards the wildcards to set
+ */
+ public void setWildcards(int wildcards) {
+ this.wildcards = wildcards;
+ }
+
+ /**
+ * @return the maximumEntries
+ */
+ public int getMaximumEntries() {
+ return maximumEntries;
+ }
+
+ /**
+ * @param maximumEntries the maximumEntries to set
+ */
+ public void setMaximumEntries(int maximumEntries) {
+ this.maximumEntries = maximumEntries;
+ }
+
+ /**
+ * @return the activeCount
+ */
+ public int getActiveCount() {
+ return activeCount;
+ }
+
+ /**
+ * @param activeCount the activeCount to set
+ */
+ public void setActiveCount(int activeCount) {
+ this.activeCount = activeCount;
+ }
+
+ /**
+ * @return the lookupCount
+ */
+ public long getLookupCount() {
+ return lookupCount;
+ }
+
+ /**
+ * @param lookupCount the lookupCount to set
+ */
+ public void setLookupCount(long lookupCount) {
+ this.lookupCount = lookupCount;
+ }
+
+ /**
+ * @return the matchedCount
+ */
+ public long getMatchedCount() {
+ return matchedCount;
+ }
+
+ /**
+ * @param matchedCount the matchedCount to set
+ */
+ public void setMatchedCount(long matchedCount) {
+ this.matchedCount = matchedCount;
+ }
+
+ @Override
+ public int getLength() {
+ return 64;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.tableId = data.readByte();
+ data.readByte(); // pad
+ data.readByte(); // pad
+ data.readByte(); // pad
+ this.name = StringByteSerializer.readFrom(data, MAX_TABLE_NAME_LEN);
+ this.wildcards = data.readInt();
+ this.maximumEntries = data.readInt();
+ this.activeCount = data.readInt();
+ this.lookupCount = data.readLong();
+ this.matchedCount = data.readLong();
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeByte(this.tableId);
+ data.writeByte((byte) 0); // pad
+ data.writeByte((byte) 0); // pad
+ data.writeByte((byte) 0); // pad
+ StringByteSerializer.writeTo(data, MAX_TABLE_NAME_LEN, this.name);
+ data.writeInt(this.wildcards);
+ data.writeInt(this.maximumEntries);
+ data.writeInt(this.activeCount);
+ data.writeLong(this.lookupCount);
+ data.writeLong(this.matchedCount);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 449;
+ int result = 1;
+ result = prime * result + activeCount;
+ result = prime * result + (int) (lookupCount ^ (lookupCount >>> 32));
+ result = prime * result + (int) (matchedCount ^ (matchedCount >>> 32));
+ result = prime * result + maximumEntries;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + tableId;
+ result = prime * result + wildcards;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFTableStatistics)) {
+ return false;
+ }
+ OFTableStatistics other = (OFTableStatistics) obj;
+ if (activeCount != other.activeCount) {
+ return false;
+ }
+ if (lookupCount != other.lookupCount) {
+ return false;
+ }
+ if (matchedCount != other.matchedCount) {
+ return false;
+ }
+ if (maximumEntries != other.maximumEntries) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ if (tableId != other.tableId) {
+ return false;
+ }
+ if (wildcards != other.wildcards) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol.statistics;
+
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * The base class for vendor implemented statistics
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+public class OFVendorStatistics implements OFStatistics {
+ protected int vendor;
+ protected byte[] body;
+
+ // non-message fields
+ protected int length = 0;
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ this.vendor = data.readInt();
+ if (body == null)
+ body = new byte[length - 4];
+ data.readBytes(body);
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeInt(this.vendor);
+ if (body != null)
+ data.writeBytes(body);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 457;
+ int result = 1;
+ result = prime * result + vendor;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof OFVendorStatistics)) {
+ return false;
+ }
+ OFVendorStatistics other = (OFVendorStatistics) obj;
+ if (vendor != other.vendor) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int getLength() {
+ return length;
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ }
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.vendor;
+
+import org.openflow.protocol.Instantiable;
+
+/**
+ * Subclass of OFVendorDataType that works with any vendor data format that
+ * begins with a integral value to indicate the format of the remaining data.
+ * It maps from the per-vendor-id integral data type code to the object
+ * used to instantiate the class associated with that vendor data type.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFBasicVendorDataType extends OFVendorDataType {
+
+ /**
+ * The data type value at the beginning of the vendor data.
+ */
+ protected long type;
+
+ /**
+ * Construct an empty (i.e. no specified data type value) vendor data type.
+ */
+ public OFBasicVendorDataType() {
+ super();
+ this.type = 0;
+ }
+
+ /**
+ * Store some information about the vendor data type, including wire protocol
+ * type number, derived class and instantiator.
+ *
+ * @param type Wire protocol number associated with this vendor data type
+ * @param instantiator An Instantiator<OFVendorData> implementation that
+ * creates an instance of an appropriate subclass of OFVendorData.
+ */
+ public OFBasicVendorDataType(long type, Instantiable<OFVendorData> instantiator) {
+ super(instantiator);
+ this.type = type;
+ }
+
+ /**
+ * @return Returns the wire protocol value corresponding to this OFVendorDataType
+ */
+ public long getTypeValue() {
+ return this.type;
+ }
+
+ /**
+ * @param type the wire protocol value for this data type
+ */
+ public void setTypeValue(long type) {
+ this.type = type;
+ }
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.vendor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.Instantiable;
+
+/**
+ * Basic subclass of OFVendorId that works with any vendor data format where
+ * the data begins with an integral data type value.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFBasicVendorId extends OFVendorId {
+
+ /**
+ * The size of the data type value at the beginning of all vendor
+ * data associated with this vendor id. The data type size must be
+ * either 1, 2, 4 or 8.
+ */
+ protected int dataTypeSize;
+
+ /**
+ * Map of the vendor data types that have been registered for this
+ * vendor id.
+ */
+ protected Map<Long, OFBasicVendorDataType> dataTypeMap =
+ new HashMap<Long, OFBasicVendorDataType>();
+
+ /**
+ * Construct an OFVendorId that where the vendor data begins
+ * with a data type value whose size is dataTypeSize.
+ * @param id the id of the vendor, typically the OUI of a vendor
+ * prefixed with 0.
+ * @param dataTypeSize the size of the integral data type value
+ * at the beginning of the vendor data. The value must be the
+ * size of an integeral data type (i.e. either 1,2,4 or 8).
+ */
+ public OFBasicVendorId(int id, int dataTypeSize) {
+ super(id);
+ assert (dataTypeSize == 1) || (dataTypeSize == 2) ||
+ (dataTypeSize == 4) || (dataTypeSize == 8);
+ this.dataTypeSize = dataTypeSize;
+ }
+
+ /**
+ * Get the size of the data type value at the beginning of the vendor
+ * data. OFBasicVendorId assumes that this value is common across all of
+ * the vendor data formats associated with a given vendor id.
+ * @return
+ */
+ public int getDataTypeSize() {
+ return dataTypeSize;
+ }
+
+ /**
+ * Register a vendor data type with this vendor id.
+ * @param vendorDataType
+ */
+ public void registerVendorDataType(OFBasicVendorDataType vendorDataType) {
+ dataTypeMap.put(vendorDataType.getTypeValue(), vendorDataType);
+ }
+
+ /**
+ * Lookup the OFVendorDataType instance that has been registered with
+ * this vendor id.
+ *
+ * @param vendorDataType the integer code that was parsed from the
+ * @return
+ */
+ public OFVendorDataType lookupVendorDataType(int vendorDataType) {
+ return dataTypeMap.get(Long.valueOf(vendorDataType));
+ }
+
+ /**
+ * This function parses enough of the data from the buffer to be able
+ * to determine the appropriate OFVendorDataType for the data. It is meant
+ * to be a reasonably generic implementation that will work for most
+ * formats of vendor extensions. If the vendor data doesn't fit the
+ * assumptions listed below, then this method will need to be overridden
+ * to implement custom parsing.
+ *
+ * This implementation assumes that the vendor data begins with a data
+ * type code that is used to distinguish different formats of vendor
+ * data associated with a particular vendor ID.
+ * The exact format of the data is vendor-defined, so we don't know how
+ * how big the code is (or really even if there is a code). This code
+ * assumes that the common case will be that the data does include
+ * an initial type code (i.e. so that the vendor can have multiple
+ * message/data types) and that the size is either 1, 2 or 4 bytes.
+ * The size of the initial type code is configured by the subclass of
+ * OFVendorId.
+ *
+ * @param data the channel buffer containing the vendor data.
+ * @param length the length to the end of the enclosing message
+ * @return the OFVendorDataType that can be used to instantiate the
+ * appropriate subclass of OFVendorData.
+ */
+ public OFVendorDataType parseVendorDataType(ChannelBuffer data, int length) {
+ OFVendorDataType vendorDataType = null;
+
+ // Parse out the type code from the vendor data.
+ long dataTypeValue = 0;
+ if ((length == 0) || (length >= dataTypeSize)) {
+ switch (dataTypeSize) {
+ case 1:
+ dataTypeValue = data.readByte();
+ break;
+ case 2:
+ dataTypeValue = data.readShort();
+ break;
+ case 4:
+ dataTypeValue = data.readInt();
+ break;
+ case 8:
+ dataTypeValue = data.readLong();
+ break;
+ default:
+ // This would be indicative of a coding error where the
+ // dataTypeSize was specified incorrectly. This should have been
+ // caught in the constructor for OFVendorId.
+ assert false;
+ }
+
+ vendorDataType = dataTypeMap.get(dataTypeValue);
+ }
+
+ // If we weren't able to parse/map the data to a known OFVendorDataType,
+ // then map it to a generic vendor data type.
+ if (vendorDataType == null) {
+ vendorDataType = new OFBasicVendorDataType(dataTypeValue,
+ new Instantiable<OFVendorData>() {
+ @Override
+ public OFVendorData instantiate() {
+ return new OFByteArrayVendorData();
+ }
+ }
+ );
+ }
+
+ return vendorDataType;
+ }
+
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Basic implementation of OFVendorData that just treats the data as a
+ * byte array. This is used if there's an OFVendor message where there's
+ * no registered OFVendorId or no specific OFVendorDataType that can be
+ * determined from the data.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFByteArrayVendorData implements OFVendorData {
+
+ protected byte[] bytes;
+
+ /**
+ * Construct vendor data with an empty byte array.
+ */
+ public OFByteArrayVendorData() {
+ }
+
+ /**
+ * Construct vendor data with the specified byte array.
+ * @param bytes
+ */
+ public OFByteArrayVendorData(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ /**
+ * Get the associated byte array for this vendor data.
+ * @return the byte array containing the raw vendor data.
+ */
+ public byte[] getBytes() {
+ return bytes;
+ }
+
+ /**
+ * Set the byte array for the vendor data.
+ * @param bytes the raw byte array containing the vendor data.
+ */
+ public void setBytes(byte[] bytes) {
+ this.bytes = bytes;
+ }
+
+ /**
+ * Get the length of the vendor data. In this case it's just then length
+ * of the underlying byte array.
+ * @return the length of the vendor data
+ */
+ @Override
+ public int getLength() {
+ return (bytes != null) ? bytes.length : 0;
+ }
+
+ /**
+ * Read the vendor data from the ChannelBuffer into the byte array.
+ * @param data the channel buffer from which we're deserializing
+ * @param length the length to the end of the enclosing message
+ */
+ @Override
+ public void readFrom(ChannelBuffer data, int length) {
+ bytes = new byte[length];
+ data.readBytes(bytes);
+ }
+
+ /**
+ * Write the vendor data bytes to the ChannelBuffer
+ * @param data the channel buffer to which we're serializing
+ */
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ if (bytes != null)
+ data.writeBytes(bytes);
+ }
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.vendor;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * The base class for all vendor data.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public interface OFVendorData {
+ /**
+ * @return length of the data
+ */
+ public int getLength();
+
+ /**
+ * Read the vendor data from the specified ChannelBuffer
+ * @param data
+ */
+ public void readFrom(ChannelBuffer data, int length);
+
+ /**
+ * Write the vendor data to the specified ChannelBuffer
+ * @param data
+ */
+ public void writeTo(ChannelBuffer data);
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.vendor;
+
+import org.openflow.protocol.Instantiable;
+
+/**
+ * Class that represents a specific vendor data type format in an
+ * OFVendor message. Typically the vendor data will begin with an integer
+ * code that determines the format of the rest of the data, but this
+ * class does not assume that. It's basically just a holder for an
+ * instantiator of the appropriate subclass of OFVendorData.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFVendorDataType {
+
+ /**
+ * Object that instantiates the subclass of OFVendorData
+ * associated with this data type.
+ */
+ protected Instantiable<OFVendorData> instantiable;
+
+ /**
+ * Construct an empty vendor data type.
+ */
+ public OFVendorDataType() {
+ super();
+ }
+
+ /**
+ * Construct a vendor data type with the specified instantiable.
+ * @param instantiable object that creates the subclass of OFVendorData
+ * associated with this data type.
+ */
+ public OFVendorDataType(Instantiable<OFVendorData> instantiable) {
+ this.instantiable = instantiable;
+ }
+
+ /**
+ * Returns a new instance of a subclass of OFVendorData associated with
+ * this OFVendorDataType.
+ *
+ * @return the new object
+ */
+ public OFVendorData newInstance() {
+ return instantiable.instantiate();
+ }
+
+ /**
+ * @return the instantiable
+ */
+ public Instantiable<OFVendorData> getInstantiable() {
+ return instantiable;
+ }
+
+ /**
+ * @param instantiable the instantiable to set
+ */
+ public void setInstantiable(Instantiable<OFVendorData> instantiable) {
+ this.instantiable = instantiable;
+ }
+
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.protocol.vendor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Base class for the vendor ID corresponding to vendor extensions from a
+ * given vendor. It is responsible for knowing how to parse out some sort of
+ * data type value from the vendor data in an OFVendor message so that we can
+ * dispatch to the different subclasses of OFVendorData corresponding to the
+ * different formats of data for the vendor extensions.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public abstract class OFVendorId {
+ static Map<Integer, OFVendorId> mapping = new HashMap<Integer, OFVendorId>();
+
+ /**
+ * The vendor id value, typically the OUI of the vendor prefixed with 0.
+ */
+ protected int id;
+
+ /**
+ * Register a new vendor id.
+ * @param vendorId the vendor id to register
+ */
+ public static void registerVendorId(OFVendorId vendorId) {
+ mapping.put(vendorId.getId(), vendorId);
+ }
+
+ /**
+ * Lookup the OFVendorId instance corresponding to the given id value.
+ * @param id the integer vendor id value
+ * @return the corresponding OFVendorId that's been registered for the
+ * given value, or null if there id has not been registered.
+ */
+ public static OFVendorId lookupVendorId(int id) {
+ return mapping.get(id);
+ }
+
+ /**
+ * Create an OFVendorId with the give vendor id value
+ * @param id
+ */
+ public OFVendorId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the vendor id value
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * This function parses enough of the data from the channel buffer to be
+ * able to determine the appropriate OFVendorDataType for the data.
+ *
+ * @param data the channel buffer containing the vendor data.
+ * @param length the length to the end of the enclosing message
+ * @return the OFVendorDataType that can be used to instantiate the
+ * appropriate subclass of OFVendorData.
+ */
+ public abstract OFVendorDataType parseVendorDataType(ChannelBuffer data, int length);
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import java.math.BigInteger;
+
+public class HexString {
+ /**
+ * Convert a string of bytes to a ':' separated hex string
+ * @param bytes
+ * @return "0f:ca:fe:de:ad:be:ef"
+ */
+ public static String toHexString(byte[] bytes) {
+ if (bytes == null) return "";
+ int i;
+ String ret = "";
+ String tmp;
+ for(i=0; i< bytes.length; i++) {
+ if(i> 0)
+ ret += ":";
+ tmp = Integer.toHexString(U8.f(bytes[i]));
+ if (tmp.length() == 1)
+ ret += "0";
+ ret += tmp;
+ }
+ return ret;
+ }
+
+ public static String toHexString(long val, int padTo) {
+ char arr[] = Long.toHexString(val).toCharArray();
+ String ret = "";
+ // prepend the right number of leading zeros
+ int i = 0;
+ for (; i < (padTo * 2 - arr.length); i++) {
+ ret += "0";
+ if ((i % 2) != 0)
+ ret += ":";
+ }
+ for (int j = 0; j < arr.length; j++) {
+ ret += arr[j];
+ if ((((i + j) % 2) != 0) && (j < (arr.length - 1)))
+ ret += ":";
+ }
+ return ret;
+ }
+
+ public static String toHexString(long val) {
+ return toHexString(val, 8);
+ }
+
+
+ /**
+ * Convert a string of hex values into a string of bytes
+ * @param values "0f:ca:fe:de:ad:be:ef"
+ * @return [15, 5 ,2, 5, 17]
+ * @throws NumberFormatException If the string can not be parsed
+ */
+ public static byte[] fromHexString(String values) throws NumberFormatException {
+ String[] octets = values.split(":");
+ byte[] ret = new byte[octets.length];
+
+ for(int i = 0; i < octets.length; i++) {
+ if (octets[i].length() > 2)
+ throw new NumberFormatException("Invalid octet length");
+ ret[i] = Integer.valueOf(octets[i], 16).byteValue();
+ }
+ return ret;
+ }
+
+ public static long toLong(String values) throws NumberFormatException {
+ // Long.parseLong() can't handle HexStrings with MSB set. Sigh.
+ BigInteger bi = new BigInteger(values.replaceAll(":", ""),16);
+ if (bi.bitLength() > 64)
+ throw new NumberFormatException("Input string too big to fit in long: " + values);
+ return bi.longValue();
+ }
+
+}
--- /dev/null
+package org.openflow.util;
+
+public interface IProducer {
+
+ public void registerConsumer(Class<?> iface, Object anObj);
+
+ public void deregisterConsumer(Class<?> iface, Object anObj);
+
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import java.util.LinkedHashMap;
+
+public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
+ private static final long serialVersionUID = -2964986094089626647L;
+ protected int maximumCapacity;
+
+ public LRULinkedHashMap(int initialCapacity, int maximumCapacity) {
+ super(initialCapacity, 0.75f, true);
+ this.maximumCapacity = maximumCapacity;
+ }
+
+ public LRULinkedHashMap(int maximumCapacity) {
+ super(16, 0.75f, true);
+ this.maximumCapacity = maximumCapacity;
+ }
+
+ @Override
+ protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
+ if (this.size() > maximumCapacity)
+ return true;
+ return false;
+ }
+}
--- /dev/null
+package org.openflow.util;
+
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The following implement a producer/consumer design pattern in which both
+ * producers and consumers explicitly employ a centralized registration
+ * mechanism, and java Interfaces are used as contracts.<br>
+ */
+public class ProducerConsumer {
+
+ /*
+ * Class variables
+ */
+ protected static ProducerConsumer singleton;
+
+ /*
+ * Default constructor
+ */
+ protected ProducerConsumer() {
+ producerMap = new Hashtable<Class<?>, Set<IProducer>>();
+ }
+
+ /*
+ * Instance variables
+ */
+
+ // Interface/IProducer map
+ protected Map<Class<?>, Set<IProducer>> producerMap;
+
+ /*
+ * Protected methods
+ */
+
+ protected void _registerConsumer(Object consumer, Class<?>[] interfaces,
+ Set<Class<?>> iSet,
+ Set<Class<?>> iUniqueSet) {
+ // *...Process all interfaces...*/
+ for (Class<?> iface : interfaces) {
+
+ // *...Protect against repeated interfaces...*/
+ if (!iUniqueSet.contains(iface)) {
+ iUniqueSet.add(iface);
+
+ Set<IProducer> producers = producerMap.get(iface);
+
+ if (producers != null) {
+ for (IProducer producer : producers)
+ producer.registerConsumer(iface, consumer);
+ iSet.add(iface);
+ }
+
+ // *...Recurse...*/
+ _registerConsumer(consumer, iface.getInterfaces(), iSet,
+ iUniqueSet);
+ }
+ }
+ }
+
+ protected void _registerConsumer(Object consumer, Class<?> clazz,
+ Set<Class<?>> iSet,
+ Set<Class<?>> iUniqueSet) {
+ if (clazz != null) {
+ // *...Process all interfaces...*/
+ _registerConsumer(consumer, clazz.getInterfaces(), iSet,
+ iUniqueSet);
+
+ // *...Recurse the class hierarchy...*/
+ _registerConsumer(consumer, clazz.getSuperclass(), iSet,
+ iUniqueSet);
+ }
+ }
+
+ protected int _deregisterConsumer(Object consumer,
+ Class<?>[] interfaces,
+ Set<Class<?>> iUniqueSet) {
+ int count = 0;
+
+ // *...Process all interfaces...*/
+ for (Class<?> iface : interfaces) {
+
+ // *...Protect against repeated interfaces...*/
+ if (!iUniqueSet.contains(iface)) {
+ iUniqueSet.add(iface);
+
+ Set<IProducer> producers = producerMap.get(iface);
+
+ if (producers != null) {
+ for (IProducer producer : producers)
+ producer.deregisterConsumer(iface, consumer);
+
+ count++;
+ }
+
+ // *...Recurse...*/
+ count += _deregisterConsumer(consumer,
+ iface.getInterfaces(),
+ iUniqueSet);
+ }
+ }
+
+ return count;
+ }
+
+ protected int _deregisterConsumer(Object consumer, Class<?> clazz,
+ Set<Class<?>> iUniqueSet) {
+ int count = 0;
+
+ if (clazz != null) {
+ // *...Process all interfaces...*/
+ count += _deregisterConsumer(consumer, clazz.getInterfaces(),
+ iUniqueSet);
+
+ // *...Recurse the class hierarchy...*/
+ count += _deregisterConsumer(consumer, clazz.getSuperclass(),
+ iUniqueSet);
+ }
+
+ return count;
+ }
+
+ /*
+ * Singleton API
+ */
+
+ /**
+ * @return singleton ProducerConsumer
+ */
+ public static synchronized ProducerConsumer getSingleton() {
+ if (singleton == null) singleton = new ProducerConsumer();
+
+ return singleton;
+ }
+
+ /*
+ * Producer APIs
+ */
+
+ /**
+ * Producer registration
+ *
+ * @param producer
+ * object that implements IProducer
+ * @param iface
+ * interface supported by the producer
+ * @return whether there was a previously registered producer, or true if
+ * one or more the arguments were invalid
+ */
+ public boolean registerProducer(IProducer producer, Class<?> iface) {
+ if (producer != null && iface != null && iface.isInterface()) {
+ Set<IProducer> producers = producerMap.get(iface);
+
+ if (producers == null) {
+ producers = new HashSet<IProducer>();
+ producerMap.put(iface, producers);
+ }
+
+ return producers.add(producer);
+ } else
+ return true;
+ }
+
+ /**
+ * Producer deregistration
+ *
+ * @param producer
+ * object that implements IProducer
+ * @param iface
+ * interface supported by the producer
+ * @return whether the interface/producer pair was removed, or false if one
+ * or more the arguments were invalid
+ */
+ public boolean deregisterProducer(IProducer producer, Class<?> iface) {
+ if (producer != null && iface != null && iface.isInterface()) {
+ Set<IProducer> producers = producerMap.get(iface);
+
+ if (producers != null) return producers.remove(producer);
+ }
+
+ return false;
+ }
+
+ /*
+ * Consumer APIs
+ */
+
+ /**
+ * Consumer registration
+ *
+ * @param consumer
+ * object that implements producer-specific interfaces
+ * @return set of supported interfaces
+ */
+ public Set<Class<?>> registerConsumer(Object consumer) {
+ Set<Class<?>> iSet = new HashSet<Class<?>>();
+
+ if (consumer != null)
+ _registerConsumer(consumer,
+ consumer.getClass(), iSet,
+ new HashSet<Class<?>>());
+
+ return iSet;
+ }
+
+ /**
+ * Consumer deregistration
+ *
+ * @param consumer
+ * object to deregister
+ * @return number of unregistered interfaces
+ */
+ public int deregisterConsumer(Object consumer) {
+ if (consumer != null)
+ return _deregisterConsumer(consumer, consumer.getClass(),
+ new HashSet<Class<?>>());
+ else
+ return 0;
+ }
+
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public class StringByteSerializer {
+ public static String readFrom(ChannelBuffer data, int length) {
+ byte[] stringBytes = new byte[length];
+ data.readBytes(stringBytes);
+ // find the first index of 0
+ int index = 0;
+ for (byte b : stringBytes) {
+ if (0 == b)
+ break;
+ ++index;
+ }
+ return new String(Arrays.copyOf(stringBytes, index),
+ Charset.forName("ascii"));
+ }
+
+ public static void writeTo(ChannelBuffer data, int length, String value) {
+ try {
+ byte[] name = value.getBytes("ASCII");
+ if (name.length < length) {
+ data.writeBytes(name);
+ for (int i = name.length; i < length; ++i) {
+ data.writeByte((byte) 0);
+ }
+ } else {
+ data.writeBytes(name, 0, length-1);
+ data.writeByte((byte) 0);
+ }
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+public class U16 {
+ public static int f(short i) {
+ return (int)i & 0xffff;
+ }
+
+ public static short t(int l) {
+ return (short) l;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+public class U32 {
+ public static long f(int i) {
+ return (long)i & 0xffffffffL;
+ }
+
+ public static int t(long l) {
+ return (int) l;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import java.math.BigInteger;
+
+public class U64 {
+ public static BigInteger f(long i) {
+ return new BigInteger(Long.toBinaryString(i), 2);
+ }
+
+ public static long t(BigInteger l) {
+ return l.longValue();
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+public class U8 {
+ public static short f(byte i) {
+ return (short) ((short)i & 0xff);
+ }
+
+ public static byte t(short l) {
+ return (byte) l;
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+/*****
+ * A util library class for dealing with the lack of unsigned datatypes in Java
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ */
+
+public class Unsigned {
+ /**
+ * Get an unsigned byte from the current position of the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the byte from
+ * @return an unsigned byte contained in a short
+ */
+ public static short getUnsignedByte(ByteBuffer bb) {
+ return ((short) (bb.get() & (short) 0xff));
+ }
+
+ /**
+ * Get an unsigned byte from the specified offset in the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the byte from
+ * @param offset the offset to get the byte from
+ * @return an unsigned byte contained in a short
+ */
+ public static short getUnsignedByte(ByteBuffer bb, int offset) {
+ return ((short) (bb.get(offset) & (short) 0xff));
+ }
+
+ /**
+ * Put an unsigned byte into the specified ByteBuffer at the current
+ * position
+ *
+ * @param bb ByteBuffer to put the byte into
+ * @param v the short containing the unsigned byte
+ */
+ public static void putUnsignedByte(ByteBuffer bb, short v) {
+ bb.put((byte) (v & 0xff));
+ }
+
+ /**
+ * Put an unsigned byte into the specified ByteBuffer at the specified
+ * offset
+ *
+ * @param bb ByteBuffer to put the byte into
+ * @param v the short containing the unsigned byte
+ * @param offset the offset to insert the unsigned byte at
+ */
+ public static void putUnsignedByte(ByteBuffer bb, short v, int offset) {
+ bb.put(offset, (byte) (v & 0xff));
+ }
+
+ /**
+ * Get an unsigned short from the current position of the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the byte from
+ * @return an unsigned short contained in a int
+ */
+ public static int getUnsignedShort(ByteBuffer bb) {
+ return (bb.getShort() & 0xffff);
+ }
+
+ /**
+ * Get an unsigned short from the specified offset in the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the short from
+ * @param offset the offset to get the short from
+ * @return an unsigned short contained in a int
+ */
+ public static int getUnsignedShort(ByteBuffer bb, int offset) {
+ return (bb.getShort(offset) & 0xffff);
+ }
+
+ /**
+ * Put an unsigned short into the specified ByteBuffer at the current
+ * position
+ *
+ * @param bb ByteBuffer to put the short into
+ * @param v the int containing the unsigned short
+ */
+ public static void putUnsignedShort(ByteBuffer bb, int v) {
+ bb.putShort((short) (v & 0xffff));
+ }
+
+ /**
+ * Put an unsigned short into the specified ByteBuffer at the specified
+ * offset
+ *
+ * @param bb ByteBuffer to put the short into
+ * @param v the int containing the unsigned short
+ * @param offset the offset to insert the unsigned short at
+ */
+ public static void putUnsignedShort(ByteBuffer bb, int v, int offset) {
+ bb.putShort(offset, (short) (v & 0xffff));
+ }
+
+ /**
+ * Get an unsigned int from the current position of the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the int from
+ * @return an unsigned int contained in a long
+ */
+ public static long getUnsignedInt(ByteBuffer bb) {
+ return ((long) bb.getInt() & 0xffffffffL);
+ }
+
+ /**
+ * Get an unsigned int from the specified offset in the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the int from
+ * @param offset the offset to get the int from
+ * @return an unsigned int contained in a long
+ */
+ public static long getUnsignedInt(ByteBuffer bb, int offset) {
+ return ((long) bb.getInt(offset) & 0xffffffffL);
+ }
+
+ /**
+ * Put an unsigned int into the specified ByteBuffer at the current position
+ *
+ * @param bb ByteBuffer to put the int into
+ * @param v the long containing the unsigned int
+ */
+ public static void putUnsignedInt(ByteBuffer bb, long v) {
+ bb.putInt((int) (v & 0xffffffffL));
+ }
+
+ /**
+ * Put an unsigned int into the specified ByteBuffer at the specified offset
+ *
+ * @param bb ByteBuffer to put the int into
+ * @param v the long containing the unsigned int
+ * @param offset the offset to insert the unsigned int at
+ */
+ public static void putUnsignedInt(ByteBuffer bb, long v, int offset) {
+ bb.putInt(offset, (int) (v & 0xffffffffL));
+ }
+
+ /**
+ * Get an unsigned long from the current position of the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the long from
+ * @return an unsigned long contained in a BigInteger
+ */
+ public static BigInteger getUnsignedLong(ByteBuffer bb) {
+ byte[] v = new byte[8];
+ for (int i = 0; i < 8; ++i) {
+ v[i] = bb.get(i);
+ }
+ return new BigInteger(1, v);
+ }
+
+ /**
+ * Get an unsigned long from the specified offset in the ByteBuffer
+ *
+ * @param bb ByteBuffer to get the long from
+ * @param offset the offset to get the long from
+ * @return an unsigned long contained in a BigInteger
+ */
+ public static BigInteger getUnsignedLong(ByteBuffer bb, int offset) {
+ byte[] v = new byte[8];
+ for (int i = 0; i < 8; ++i) {
+ v[i] = bb.get(offset+i);
+ }
+ return new BigInteger(1, v);
+ }
+
+ /**
+ * Put an unsigned long into the specified ByteBuffer at the current
+ * position
+ *
+ * @param bb ByteBuffer to put the long into
+ * @param v the BigInteger containing the unsigned long
+ */
+ public static void putUnsignedLong(ByteBuffer bb, BigInteger v) {
+ bb.putLong(v.longValue());
+ }
+
+ /**
+ * Put an unsigned long into the specified ByteBuffer at the specified
+ * offset
+ *
+ * @param bb ByteBuffer to put the long into
+ * @param v the BigInteger containing the unsigned long
+ * @param offset the offset to insert the unsigned long at
+ */
+ public static void putUnsignedLong(ByteBuffer bb, BigInteger v, int offset) {
+ bb.putLong(offset, v.longValue());
+ }
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.vendor.nicira;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Base class for vendor data corresponding to a Nicira vendor extension.
+ * Nicira vendor data always starts with a 4-byte integer data type value.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFNiciraVendorData implements OFVendorData {
+
+ public static final int NX_VENDOR_ID = 0x00002320;
+ /**
+ * The value of the integer data type at the beginning of the vendor data
+ */
+ protected int dataType;
+
+ /**
+ * Construct empty (i.e. unspecified data type) Nicira vendor data.
+ */
+ public OFNiciraVendorData() {
+ }
+
+ /**
+ * Contruct Nicira vendor data with the specified data type
+ * @param dataType the data type value at the beginning of the vendor data.
+ */
+ public OFNiciraVendorData(int dataType) {
+ this.dataType = dataType;
+ }
+
+ /**
+ * Get the data type value at the beginning of the vendor data
+ * @return the integer data type value
+ */
+ public int getDataType() {
+ return dataType;
+ }
+
+ /**
+ * Set the data type value
+ * @param dataType the integer data type value at the beginning of the
+ * vendor data.
+ */
+ public void setDataType(int dataType) {
+ this.dataType = dataType;
+ }
+
+ /**
+ * Get the length of the vendor data. This implementation will normally
+ * be the superclass for another class that will override this to return
+ * the overall vendor data length. This implementation just returns the
+ * length of the part that includes the 4-byte integer data type value
+ * at the beginning of the vendor data.
+ */
+ @Override
+ public int getLength() {
+ return 4;
+ }
+
+ /**
+ * Read the vendor data from the ChannelBuffer
+ * @param data the channel buffer from which we're deserializing
+ * @param length the length to the end of the enclosing message
+ */
+ @Override
+ public void readFrom(ChannelBuffer data, int length) {
+ dataType = data.readInt();
+ }
+
+ /**
+ * Write the vendor data to the ChannelBuffer
+ * @param data the channel buffer to which we're serializing
+ */
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeInt(dataType);
+ }
+}
--- /dev/null
+package org.openflow.vendor.nicira;
+
+import org.openflow.protocol.vendor.OFBasicVendorDataType;
+import org.openflow.protocol.vendor.OFBasicVendorId;
+import org.openflow.protocol.vendor.OFVendorId;
+
+public class OFNiciraVendorExtensions {
+ private static boolean initialized = false;
+
+ public static synchronized void initialize() {
+ if (initialized)
+ return;
+
+ // Configure openflowj to be able to parse the role request/reply
+ // vendor messages.
+ OFBasicVendorId niciraVendorId =
+ new OFBasicVendorId(OFNiciraVendorData.NX_VENDOR_ID, 4);
+ OFVendorId.registerVendorId(niciraVendorId);
+ OFBasicVendorDataType roleRequestVendorData =
+ new OFBasicVendorDataType(OFRoleRequestVendorData.NXT_ROLE_REQUEST,
+ OFRoleRequestVendorData.getInstantiable());
+ niciraVendorId.registerVendorDataType(roleRequestVendorData);
+ OFBasicVendorDataType roleReplyVendorData =
+ new OFBasicVendorDataType(OFRoleReplyVendorData.NXT_ROLE_REPLY,
+ OFRoleReplyVendorData.getInstantiable());
+ niciraVendorId.registerVendorDataType(roleReplyVendorData);
+
+ initialized = true;
+ }
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.vendor.nicira;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Subclass of OFVendorData representing the vendor data associated with
+ * a role reply vendor extension.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFRoleReplyVendorData extends OFRoleVendorData {
+
+ protected static Instantiable<OFVendorData> instantiable =
+ new Instantiable<OFVendorData>() {
+ public OFVendorData instantiate() {
+ return new OFRoleReplyVendorData();
+ }
+ };
+
+ /**
+ * @return a subclass of Instantiable<OFVendorData> that instantiates
+ * an instance of OFRoleReplyVendorData.
+ */
+ public static Instantiable<OFVendorData> getInstantiable() {
+ return instantiable;
+ }
+
+ /**
+ * The data type value for a role reply
+ */
+ public static final int NXT_ROLE_REPLY = 11;
+
+ /**
+ * Construct a role reply vendor data with an unspecified role value.
+ */
+ public OFRoleReplyVendorData() {
+ super(NXT_ROLE_REPLY);
+ }
+
+ /**
+ * Construct a role reply vendor data with the specified role value.
+ * @param role the role value for the role reply. Should be one of
+ * NX_ROLE_OTHER, NX_ROLE_MASTER or NX_ROLE_SLAVE.
+ */
+ public OFRoleReplyVendorData(int role) {
+ super(NXT_ROLE_REPLY, role);
+ }
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.vendor.nicira;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Subclass of OFVendorData representing the vendor data associated with
+ * a role request vendor extension.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFRoleRequestVendorData extends OFRoleVendorData {
+
+ protected static Instantiable<OFVendorData> instantiable =
+ new Instantiable<OFVendorData>() {
+ public OFVendorData instantiate() {
+ return new OFRoleRequestVendorData();
+ }
+ };
+
+ /**
+ * @return a subclass of Instantiable<OFVendorData> that instantiates
+ * an instance of OFRoleRequestVendorData.
+ */
+ public static Instantiable<OFVendorData> getInstantiable() {
+ return instantiable;
+ }
+
+ /**
+ * The data type value for a role request
+ */
+ public static final int NXT_ROLE_REQUEST = 10;
+
+ /**
+ * Construct a role request vendor data with an unspecified role value.
+ */
+ public OFRoleRequestVendorData() {
+ super(NXT_ROLE_REQUEST);
+ }
+
+ /**
+ * Construct a role request vendor data with the specified role value.
+ * @param role the role value for the role request. Should be one of
+ * NX_ROLE_OTHER, NX_ROLE_MASTER or NX_ROLE_SLAVE.
+ */
+ public OFRoleRequestVendorData(int role) {
+ super(NXT_ROLE_REQUEST, role);
+ }
+}
--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, 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 org.openflow.vendor.nicira;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Class that represents the vendor data in the role request
+ * extension implemented by Open vSwitch to support high availability.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFRoleVendorData extends OFNiciraVendorData {
+
+ /**
+ * Role value indicating that the controller is in the OTHER role.
+ */
+ public static final int NX_ROLE_OTHER = 0;
+
+ /**
+ * Role value indicating that the controller is in the MASTER role.
+ */
+ public static final int NX_ROLE_MASTER = 1;
+
+ /**
+ * Role value indicating that the controller is in the SLAVE role.
+ */
+ public static final int NX_ROLE_SLAVE = 2;
+
+ protected int role;
+
+ /**
+ * Construct an uninitialized OFRoleVendorData
+ */
+ public OFRoleVendorData() {
+ super();
+ }
+
+ /**
+ * Construct an OFRoleVendorData with the specified data type
+ * (i.e. either request or reply) and an unspecified role.
+ * @param dataType
+ */
+ public OFRoleVendorData(int dataType) {
+ super(dataType);
+ }
+
+ /**
+ * Construct an OFRoleVendorData with the specified data type
+ * (i.e. either request or reply) and role (i.e. one of of
+ * master, slave, or other).
+ * @param dataType either role request or role reply data type
+ */
+ public OFRoleVendorData(int dataType, int role) {
+ super(dataType);
+ this.role = role;
+ }
+ /**
+ * @return the role value of the role vendor data
+ */
+ public int getRole() {
+ return role;
+ }
+
+ /**
+ * @param role the role value of the role vendor data
+ */
+ public void setRole(int role) {
+ this.role = role;
+ }
+
+ /**
+ * @return the total length of the role vendor data
+ */
+ @Override
+ public int getLength() {
+ return super.getLength() + 4;
+ }
+
+ /**
+ * Read the role vendor data from the ChannelBuffer
+ * @param data the channel buffer from which we're deserializing
+ * @param length the length to the end of the enclosing message
+ */
+ public void readFrom(ChannelBuffer data, int length) {
+ super.readFrom(data, length);
+ role = data.readInt();
+ }
+
+ /**
+ * Write the role vendor data to the ChannelBuffer
+ * @param data the channel buffer to which we're serializing
+ */
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeInt(role);
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.vendor.openflow;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Base class for vendor data corresponding to extensions to OpenFlow 1.0.
+ * Based on org.openflow.vendor.nicira
+ *
+ * @author Andrew Ferguson (adf@cs.brown.edu)
+ */
+public class OFOpenFlowVendorData implements OFVendorData {
+
+ public static final int OF_VENDOR_ID = 0x000026e1;
+
+ /**
+ * The value of the integer data type at the beginning of the vendor data
+ */
+ protected int dataType;
+
+ /**
+ * Construct empty (i.e. unspecified data type) OpenFlow vendor data.
+ */
+ public OFOpenFlowVendorData() {
+ }
+
+ /**
+ * Construct OpenFlow vendor data with the specified data type
+ * @param dataType the data type value at the beginning of the vendor data.
+ */
+ public OFOpenFlowVendorData(int dataType) {
+ this.dataType = dataType;
+ }
+
+ /**
+ * Get the data type value at the beginning of the vendor data
+ * @return the integer data type value
+ */
+ public int getDataType() {
+ return dataType;
+ }
+
+ /**
+ * Set the data type value
+ * @param dataType the integer data type value at the beginning of the
+ * vendor data.
+ */
+ public void setDataType(int dataType) {
+ this.dataType = dataType;
+ }
+
+ /**
+ * Get the length of the vendor data. This implementation will normally
+ * be the superclass for another class that will override this to return
+ * the overall vendor data length. This implementation just returns the
+ * length of the part that includes the 4-byte integer data type value
+ * at the beginning of the vendor data.
+ */
+ @Override
+ public int getLength() {
+ return 4;
+ }
+
+ /**
+ * Read the vendor data from the ChannelBuffer
+ * @param data the channel buffer from which we're deserializing
+ * @param length the length to the end of the enclosing message
+ */
+ @Override
+ public void readFrom(ChannelBuffer data, int length) {
+ dataType = data.readInt();
+ }
+
+ /**
+ * Write the vendor data to the ChannelBuffer
+ * @param data the channel buffer to which we're serializing
+ */
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ data.writeInt(dataType);
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.vendor.openflow;
+
+import org.openflow.protocol.vendor.OFBasicVendorDataType;
+import org.openflow.protocol.vendor.OFBasicVendorId;
+import org.openflow.protocol.vendor.OFVendorId;
+
+public class OFOpenFlowVendorExtensions {
+ private static boolean initialized = false;
+
+ public static synchronized void initialize() {
+ if (initialized)
+ return;
+
+ // Configure openflowj to be able to parse the OpenFlow extensions.
+ OFBasicVendorId openflowVendorId =
+ new OFBasicVendorId(OFOpenFlowVendorData.OF_VENDOR_ID, 4);
+ OFVendorId.registerVendorId(openflowVendorId);
+
+ OFBasicVendorDataType queueModifyVendorData =
+ new OFBasicVendorDataType(OFQueueModifyVendorData.OFP_EXT_QUEUE_MODIFY,
+ OFQueueModifyVendorData.getInstantiable());
+ openflowVendorId.registerVendorDataType(queueModifyVendorData);
+
+ OFBasicVendorDataType queueDeleteVendorData =
+ new OFBasicVendorDataType(OFQueueDeleteVendorData.OFP_EXT_QUEUE_DELETE,
+ OFQueueModifyVendorData.getInstantiable());
+ openflowVendorId.registerVendorDataType(queueDeleteVendorData);
+
+ initialized = true;
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.vendor.openflow;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Class that represents the vendor data in the queue delete request
+ *
+ * @author Andrew Ferguson (adf@cs.brown.edu)
+ */
+public class OFQueueDeleteVendorData extends OFQueueVendorData {
+
+ protected static Instantiable<OFVendorData> instantiable =
+ new Instantiable<OFVendorData>() {
+ public OFVendorData instantiate() {
+ return new OFQueueDeleteVendorData();
+ }
+ };
+
+ /**
+ * @return a subclass of Instantiable<OFVendorData> that instantiates
+ * an instance of OFQueueDeleteVendorData.
+ */
+ public static Instantiable<OFVendorData> getInstantiable() {
+ return instantiable;
+ }
+
+ /**
+ * The data type value for a queue delete request
+ */
+ public static final int OFP_EXT_QUEUE_DELETE = 1;
+
+ public OFQueueDeleteVendorData() {
+ super(OFP_EXT_QUEUE_DELETE);
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.vendor.openflow;
+
+import org.openflow.protocol.Instantiable;
+import org.openflow.protocol.vendor.OFVendorData;
+
+/**
+ * Class that represents the vendor data in the queue modify request
+ *
+ * @author Andrew Ferguson (adf@cs.brown.edu)
+ */
+public class OFQueueModifyVendorData extends OFQueueVendorData {
+
+ protected static Instantiable<OFVendorData> instantiable =
+ new Instantiable<OFVendorData>() {
+ public OFVendorData instantiate() {
+ return new OFQueueModifyVendorData();
+ }
+ };
+
+ /**
+ * @return a subclass of Instantiable<OFVendorData> that instantiates
+ * an instance of OFQueueModifyVendorData.
+ */
+ public static Instantiable<OFVendorData> getInstantiable() {
+ return instantiable;
+ }
+
+ /**
+ * The data type value for a queue modify request
+ */
+ public static final int OFP_EXT_QUEUE_MODIFY = 0;
+
+ public OFQueueModifyVendorData() {
+ super(OFP_EXT_QUEUE_MODIFY);
+ }
+}
--- /dev/null
+/**
+* Copyright 2012, Andrew Ferguson, Brown 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 org.openflow.vendor.openflow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.OFPacketQueue;
+
+/**
+ * Class that represents the vendor data in a queue modify or delete request
+ *
+ * @author Andrew Ferguson (adf@cs.brown.edu)
+ */
+public class OFQueueVendorData extends OFOpenFlowVendorData {
+ public static int MINIMUM_LENGTH = 8;
+
+ protected short portNumber;
+ protected List<OFPacketQueue> queues = new ArrayList<OFPacketQueue>();
+
+ public OFQueueVendorData(int dataType) {
+ super(dataType);
+ }
+
+ /**
+ * @return the portNumber
+ */
+ public short getPortNumber() {
+ return portNumber;
+ }
+
+ /**
+ * @param port the port on which the queue is
+ */
+ public void setPortNumber(short portNumber) {
+ this.portNumber = portNumber;
+ }
+
+
+ /**
+ * @return the queues
+ */
+ public List<OFPacketQueue> getQueues() {
+ return queues;
+ }
+
+ /**
+ * @param queues the queues to modify or delete
+ */
+ public void setQueues(List<OFPacketQueue> queues) {
+ this.queues = queues;
+ }
+
+ /**
+ * @return the total length of the queue modify or delete msg
+ */
+ @Override
+ public int getLength() {
+ int queuesLength = 0;
+
+ for (OFPacketQueue queue : queues) {
+ queuesLength += queue.getLength();
+ }
+
+ return super.getLength() + MINIMUM_LENGTH + queuesLength;
+ }
+
+ /**
+ * Read the queue message data from the ChannelBuffer
+ * @param data the channel buffer from which we're deserializing
+ * @param length the length to the end of the enclosing message
+ */
+ public void readFrom(ChannelBuffer data, int length) {
+ super.readFrom(data, length);
+ portNumber = data.readShort();
+ data.readInt(); // pad
+ data.readShort(); // pad
+
+ int availLength = (length - MINIMUM_LENGTH);
+ this.queues.clear();
+
+ while (availLength > 0) {
+ OFPacketQueue queue = new OFPacketQueue();
+ queue.readFrom(data);
+ queues.add(queue);
+ availLength -= queue.getLength();
+ }
+ }
+
+ /**
+ * Write the queue message data to the ChannelBuffer
+ * @param data the channel buffer to which we're serializing
+ */
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(this.portNumber);
+ data.writeInt(0); // pad
+ data.writeShort(0); // pad
+
+ for (OFPacketQueue queue : queues) {
+ queue.writeTo(data);
+ }
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.action.MockVendorAction;
+import org.openflow.protocol.action.MockVendorActionFactory;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionVendorGeneric;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.MessageParseException;
+import org.openflow.protocol.factory.OFVendorActionRegistry;
+import org.openflow.util.U16;
+
+public class BasicFactoryTest extends TestCase {
+
+ public void testCreateAndParse() throws MessageParseException {
+ BasicFactory factory = new BasicFactory();
+ OFMessage m = factory.getMessage(OFType.HELLO);
+ m.setVersion((byte) 1);
+ m.setType(OFType.ECHO_REQUEST);
+ m.setLength(U16.t(8));
+ m.setXid(0xdeadbeef);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ ChannelBuffer bb2 = ChannelBuffers.dynamicBuffer();
+ m.writeTo(bb);
+ bb2.writeBytes(bb, bb.readableBytes()-1);
+ TestCase.assertNull(factory.parseMessage(bb2));
+ bb2.writeByte(bb.readByte());
+ List<OFMessage> message = factory.parseMessage(bb2);
+ TestCase.assertNotNull(message);
+ TestCase.assertEquals(message.size(), 1);
+ TestCase.assertTrue(message.get(0).getType() == OFType.ECHO_REQUEST);
+ }
+
+ public void testInvalidMsgParse() throws MessageParseException {
+ BasicFactory factory = new BasicFactory();
+ OFMessage m = factory.getMessage(OFType.HELLO);
+ m.setVersion((byte) 1);
+ m.setType(OFType.ECHO_REQUEST);
+ m.setLength(U16.t(16));
+ m.setXid(0xdeadbeef);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ m.writeTo(bb);
+ List<OFMessage> message = factory.parseMessage(bb);
+ TestCase.assertNull(message);
+ }
+
+ public void testCurrouptedMsgParse() throws MessageParseException {
+ BasicFactory factory = new BasicFactory();
+ OFMessage m = factory.getMessage(OFType.HELLO);
+ m.setVersion((byte) 1);
+ m.setType(OFType.ERROR);
+ m.setLength(U16.t(8));
+ m.setXid(0xdeadbeef);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ m.writeTo(bb);
+ try {
+ factory.parseMessage(bb);
+ }
+ catch(Exception e) {
+ TestCase.assertEquals(MessageParseException.class, e.getClass());
+ }
+ }
+
+ public void testCustomVendorAction() throws MessageParseException {
+ BasicFactory factory = new BasicFactory();
+ OFVendorActionRegistry.getInstance().register(
+ MockVendorAction.VENDOR_ID, new MockVendorActionFactory());
+
+
+ byte[] deadBeefMessage = {
+ (byte) 0xff, (byte) 0xff, // action vendor
+ 0x00, 0x10, // length
+ (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte)0xef, // deadbeaf
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08 // pad
+ };
+
+ ChannelBuffer buf = ChannelBuffers.copiedBuffer(deadBeefMessage);
+
+ List<OFAction> actions = factory.parseActions(buf,deadBeefMessage.length);
+ assertEquals(1, actions.size());
+ OFAction ofAction = actions.get(0);
+ assertTrue("Action should be MockVendorAction, but is "+ofAction.getClass(), ofAction instanceof MockVendorAction);
+ assertArrayEquals( new byte[] { 1,2,3,4,5,6,7,8}, ((MockVendorAction)ofAction).getMockData());
+
+
+ }
+
+ public void testGenericVendorAction() throws MessageParseException {
+ byte[] nonDeadBeefMessage = {
+ (byte) 0xff, (byte) 0xff, // action vendor
+ 0x00, 0x10, // length
+ (byte) 0x7e, (byte) 0xe7, (byte) 0xbe, (byte)0xef, // deadbeaf
+ 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08 // pad
+ };
+
+ BasicFactory factory = new BasicFactory();
+ OFVendorActionRegistry.getInstance().register(
+ MockVendorAction.VENDOR_ID, new MockVendorActionFactory());
+
+ ChannelBuffer buf = ChannelBuffers.copiedBuffer(nonDeadBeefMessage);
+
+ List<OFAction> actions = factory.parseActions(buf,nonDeadBeefMessage.length);
+ assertEquals(1, actions.size());
+ OFAction ofAction = actions.get(0);
+ assertTrue("Action should be OFActionVendorGeneric, but is "+ofAction.getClass(), ofAction instanceof OFActionVendorGeneric);
+ }
+
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import org.junit.Test;
+import org.openflow.protocol.action.OFActionType;
+
+import junit.framework.TestCase;
+
+
+public class OFActionTypeTest extends TestCase {
+ @Test
+ public void testMapping() throws Exception {
+ TestCase.assertEquals(OFActionType.OUTPUT,
+ OFActionType.valueOf((short) 0));
+ TestCase.assertEquals(OFActionType.OPAQUE_ENQUEUE,
+ OFActionType.valueOf((short) 11));
+ TestCase.assertEquals(OFActionType.VENDOR,
+ OFActionType.valueOf((short) 0xffff));
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.util.OFTestCase;
+
+public class OFBarrierReplyTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFBarrierReply msg = (OFBarrierReply) messageFactory
+ .getMessage(OFType.BARRIER_REPLY);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.BARRIER_REPLY, msg.getType());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.util.OFTestCase;
+
+public class OFBarrierRequestTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFBarrierRequest msg = (OFBarrierRequest) messageFactory
+ .getMessage(OFType.BARRIER_REQUEST);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.BARRIER_REQUEST, msg.getType());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.OFError.OFErrorType;
+import org.openflow.protocol.OFError.OFHelloFailedCode;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.MessageParseException;
+import org.openflow.protocol.factory.OFMessageFactory;
+import org.openflow.util.OFTestCase;
+
+public class OFErrorTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFError msg = (OFError) messageFactory.getMessage(OFType.ERROR);
+ msg.setMessageFactory(messageFactory);
+ msg.setErrorType((short) OFErrorType.OFPET_HELLO_FAILED.getValue());
+ msg.setErrorCode((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE
+ .ordinal());
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals((short) OFErrorType.OFPET_HELLO_FAILED.getValue(),
+ msg.getErrorType());
+ TestCase.assertEquals((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE
+ .ordinal(), msg.getErrorType());
+ TestCase.assertNull(msg.getOffendingMsg());
+
+ msg.setOffendingMsg(new OFHello());
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals((short) OFErrorType.OFPET_HELLO_FAILED.getValue(),
+ msg.getErrorType());
+ TestCase.assertEquals((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE
+ .ordinal(), msg.getErrorType());
+ TestCase.assertNotNull(msg.getOffendingMsg());
+ TestCase.assertEquals(OFHello.MINIMUM_LENGTH,
+ msg.getOffendingMsg().length);
+ }
+
+ public void testGarbageAtEnd() throws MessageParseException {
+ // This is a OFError msg (12 bytes), that encaps a OFVendor msg (24
+ // bytes)
+ // AND some zeros at the end (40 bytes) for a total of 76 bytes
+ // THIS is what an NEC sends in reply to Nox's VENDOR request
+ byte[] oferrorRaw = { 0x01, 0x01, 0x00, 0x4c, 0x00, 0x00, 0x10,
+ (byte) 0xcc, 0x00, 0x01, 0x00, 0x01, 0x01, 0x04, 0x00, 0x18,
+ 0x00, 0x00, 0x10, (byte) 0xcc, 0x00, 0x00, 0x23, 0x20, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00 };
+ OFMessageFactory factory = new BasicFactory();
+ ChannelBuffer oferrorBuf =
+ ChannelBuffers.wrappedBuffer(oferrorRaw);
+ List<OFMessage> msg = factory.parseMessage(oferrorBuf);
+ TestCase.assertNotNull(msg);
+ TestCase.assertEquals(msg.size(), 1);
+ TestCase.assertEquals(76, msg.get(0).getLengthU());
+ ChannelBuffer out = ChannelBuffers.dynamicBuffer();
+ msg.get(0).writeTo(out);
+ TestCase.assertEquals(76, out.readableBytes());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.util.OFTestCase;
+
+
+public class OFFeaturesReplyTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFFeaturesReply ofr = (OFFeaturesReply) messageFactory
+ .getMessage(OFType.FEATURES_REPLY);
+ List<OFPhysicalPort> ports = new ArrayList<OFPhysicalPort>();
+ OFPhysicalPort port = new OFPhysicalPort();
+ port.setHardwareAddress(new byte[6]);
+ port.setName("eth0");
+ ports.add(port);
+ ofr.setPorts(ports);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ ofr.writeTo(bb);
+ ofr.readFrom(bb);
+ TestCase.assertEquals(1, ofr.getPorts().size());
+ TestCase.assertEquals("eth0", ofr.getPorts().get(0).getName());
+
+ // test a 15 character name
+ ofr.getPorts().get(0).setName("012345678901234");
+ bb.clear();
+ ofr.writeTo(bb);
+ ofr.readFrom(bb);
+ TestCase.assertEquals("012345678901234", ofr.getPorts().get(0).getName());
+
+ // test a 16 character name getting truncated
+ ofr.getPorts().get(0).setName("0123456789012345");
+ bb.clear();
+ ofr.writeTo(bb);
+ ofr.readFrom(bb);
+ TestCase.assertEquals("012345678901234", ofr.getPorts().get(0).getName());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.OFFlowRemoved.OFFlowRemovedReason;
+import org.openflow.util.OFTestCase;
+
+public class OFFlowRemovedTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFFlowRemoved msg = (OFFlowRemoved) messageFactory
+ .getMessage(OFType.FLOW_REMOVED);
+ msg.setMatch(new OFMatch());
+ byte[] hwAddr = new byte[6];
+ msg.getMatch().setDataLayerDestination(hwAddr);
+ msg.getMatch().setDataLayerSource(hwAddr);
+ msg.setReason(OFFlowRemovedReason.OFPRR_DELETE);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.FLOW_REMOVED, msg.getType());
+ TestCase.assertEquals(OFFlowRemovedReason.OFPRR_DELETE, msg.getReason());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.util.OFTestCase;
+
+public class OFGetConfigReplyTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFSetConfig msg = (OFSetConfig) messageFactory
+ .getMessage(OFType.SET_CONFIG);
+ msg.setFlags((short) 1);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.SET_CONFIG, msg.getType());
+ TestCase.assertEquals((short)1, msg.getFlags());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.util.OFTestCase;
+
+public class OFGetConfigRequestTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFGetConfigRequest msg = (OFGetConfigRequest) messageFactory
+ .getMessage(OFType.GET_CONFIG_REQUEST);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.GET_CONFIG_REQUEST, msg.getType());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+public class OFMatchTest extends TestCase {
+ public void testFromString() {
+ OFMatch correct = new OFMatch();
+ OFMatch tester = new OFMatch();
+
+ // Various combinations of "all"/"any"
+ tester.fromString("OFMatch[]");
+ // correct is already wildcarded
+ TestCase.assertEquals(correct, tester);
+ tester.fromString("all");
+ TestCase.assertEquals(correct, tester);
+ tester.fromString("ANY");
+ TestCase.assertEquals(correct, tester);
+ tester.fromString("");
+ TestCase.assertEquals(correct, tester);
+ tester.fromString("[]");
+ TestCase.assertEquals(correct, tester);
+
+ // ip_src
+ correct.setWildcards(~OFMatch.OFPFW_NW_SRC_MASK);
+ correct.setNetworkSource(0x01010203);
+ tester.fromString("nw_src=1.1.2.3");
+ TestCase.assertEquals(correct.getNetworkSourceMaskLen(), tester
+ .getNetworkSourceMaskLen());
+ TestCase.assertEquals(correct, tester);
+ tester.fromString("IP_sRc=1.1.2.3");
+ TestCase.assertEquals(correct.getNetworkSourceMaskLen(), tester
+ .getNetworkSourceMaskLen());
+ TestCase.assertEquals(correct, tester);
+
+ // 0xVlan
+ correct = new OFMatch();
+ correct.setDataLayerVirtualLan((short)65535);
+ correct.setWildcards(~OFMatch.OFPFW_DL_VLAN);
+ tester = new OFMatch();
+ tester.fromString("dl_vlan=0xffff");
+ TestCase.assertEquals(correct, tester);
+ }
+
+ public void testToString() {
+ OFMatch match = new OFMatch();
+ match.fromString("nw_dst=3.4.5.6/8");
+ TestCase.assertEquals(8, match.getNetworkDestinationMaskLen());
+ String correct = "OFMatch[nw_dst=3.0.0.0/8]";
+ String tester = match.toString();
+
+ TestCase.assertEquals(correct, tester);
+ tester = "OFMatch[dl_type=35020]";
+ correct = "OFMatch[dl_type=0x88cc]";
+ match = new OFMatch();
+ match.fromString(tester);
+ TestCase.assertEquals(correct, match.toString());
+ OFMatch match2 = new OFMatch();
+ match2.fromString(correct);
+ TestCase.assertEquals(match, match2);
+ }
+
+ public void testClone() {
+ OFMatch match1 = new OFMatch();
+ OFMatch match2 = match1.clone();
+ TestCase.assertEquals(match1, match2);
+ match2.setNetworkProtocol((byte) 4);
+ match2.setWildcards(match2.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
+ TestCase.assertNotSame(match1, match2);
+ }
+
+ public void testIpToString() {
+ String test = OFMatch.ipToString(-1);
+ TestCase.assertEquals("255.255.255.255", test);
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+public class OFMessageContextStoreTest extends TestCase {
+ public void testStoreAndGet() {
+ OFMessage msg = new OFMessage();
+ OFMessageContextStore<String> store = new OFMessageContextStore<String>(msg, this.getName());
+ String key = "mykey";
+ String value = "myvalue";
+ store.put(key, value);
+ TestCase.assertEquals(value, store.get(key));
+ }
+}
--- /dev/null
+package org.openflow.protocol;
+
+import org.junit.Test;
+
+public class OFPacketOutTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testBothBufferIdAndPayloadSet() {
+ OFPacketOut packetOut = new OFPacketOut();
+ packetOut.setBufferId(12);
+ packetOut.setPacketData(new byte[] { 1, 2, 3 });
+ }
+
+ @Test
+ public void testOnlyBufferIdSet() {
+ OFPacketOut packetOut = new OFPacketOut();
+ packetOut.setBufferId(12);
+ packetOut.setPacketData(null);
+ packetOut.setPacketData(new byte[] {});
+ packetOut.validate();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNeitherBufferIdNorPayloadSet() {
+ OFPacketOut packetOut = new OFPacketOut();
+ packetOut.setBufferId(OFPacketOut.BUFFER_ID_NONE);
+ packetOut.setPacketData(null);
+ packetOut.validate();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNeitherBufferIdNorPayloadSet2() {
+ OFPacketOut packetOut = new OFPacketOut();
+ packetOut.setBufferId(OFPacketOut.BUFFER_ID_NONE);
+ packetOut.setPacketData(new byte[] {});
+ packetOut.validate();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNeitherBufferIdNorPayloadSet3() {
+ OFPacketOut packetOut = new OFPacketOut();
+ packetOut.validate();
+ }
+
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.util.OFTestCase;
+
+public class OFPortConfigTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFPortMod msg = (OFPortMod) messageFactory
+ .getMessage(OFType.PORT_MOD);
+ msg.setHardwareAddress(new byte[6]);
+ msg.portNumber = 1;
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.PORT_MOD, msg.getType());
+ TestCase.assertEquals(1, msg.getPortNumber());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.OFPortStatus.OFPortReason;
+import org.openflow.util.OFTestCase;
+
+public class OFPortStatusTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFPortStatus msg = (OFPortStatus) messageFactory
+ .getMessage(OFType.PORT_STATUS);
+ msg.setDesc(new OFPhysicalPort());
+ msg.getDesc().setHardwareAddress(new byte[6]);
+ msg.getDesc().setName("eth0");
+ msg.setReason((byte) OFPortReason.OFPPR_ADD.ordinal());
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.PORT_STATUS, msg.getType());
+ TestCase.assertEquals((byte) OFPortReason.OFPPR_ADD.ordinal(), msg
+ .getReason());
+ TestCase.assertNotNull(msg.getDesc());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.util.OFTestCase;
+
+public class OFSetConfigTest extends OFTestCase {
+ public void testWriteRead() throws Exception {
+ OFGetConfigReply msg = (OFGetConfigReply) messageFactory
+ .getMessage(OFType.GET_CONFIG_REPLY);
+ msg.setFlags((short) 1);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(OFType.GET_CONFIG_REPLY, msg.getType());
+ TestCase.assertEquals((short)1, msg.getFlags());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.OFMessageFactory;
+import org.openflow.protocol.statistics.OFStatisticsType;
+import org.openflow.util.OFTestCase;
+
+public class OFStatisticsReplyTest extends OFTestCase {
+ public void testOFFlowStatisticsReply() throws Exception {
+ byte[] packet = new byte[] { 0x01, 0x11, 0x01, 0x2c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, (byte) 0xff,
+ (byte) 0xff, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, (byte) 0xa6,
+ (byte) 0xa6, 0x00, (byte) 0xff, (byte) 0xff, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ (byte) 0xc4, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x08, 0x06,
+ 0x00, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3b, 0x2f, (byte) 0xfa, 0x40, (byte) 0xff, (byte) 0xff, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, (byte) 0xff, (byte) 0xff, 0x00, 0x62, 0x08,
+ 0x00, 0x00, 0x01, 0x62, 0x37, 0x0a, 0x00, 0x00, 0x02, 0x0a,
+ 0x00, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3a, (byte) 0xc5, 0x2a, (byte) 0x80, (byte) 0xff,
+ (byte) 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xc4, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x00 };
+
+ OFMessageFactory factory = new BasicFactory();
+ ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet);
+ List<OFMessage> msg = factory.parseMessage(packetBuf);
+ TestCase.assertNotNull(msg);
+ TestCase.assertEquals(msg.size(), 1);
+ TestCase.assertTrue(msg.get(0) instanceof OFStatisticsReply);
+ OFStatisticsReply sr = (OFStatisticsReply) msg.get(0);
+ TestCase.assertEquals(OFStatisticsType.FLOW, sr.getStatisticType());
+ TestCase.assertEquals(3, sr.getStatistics().size());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.OFMessageFactory;
+import org.openflow.protocol.statistics.OFFlowStatisticsRequest;
+import org.openflow.protocol.statistics.OFStatisticsType;
+import org.openflow.protocol.statistics.OFVendorStatistics;
+import org.openflow.util.OFTestCase;
+
+public class OFStatisticsRequestTest extends OFTestCase {
+ public void testOFFlowStatisticsRequest() throws Exception {
+ byte[] packet = new byte[] { 0x01, 0x10, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x16, 0x00, 0x01, 0x00, 0x00, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ (byte) 0xff, 0x00, (byte) 0xff, (byte) 0xff };
+
+ OFMessageFactory factory = new BasicFactory();
+ ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet);
+ List<OFMessage> msg = factory.parseMessage(packetBuf);
+ TestCase.assertNotNull(msg);
+ TestCase.assertEquals(msg.size(), 1);
+ TestCase.assertTrue(msg.get(0) instanceof OFStatisticsRequest);
+ OFStatisticsRequest sr = (OFStatisticsRequest) msg.get(0);
+ TestCase.assertEquals(OFStatisticsType.FLOW, sr.getStatisticType());
+ TestCase.assertEquals(1, sr.getStatistics().size());
+ TestCase.assertTrue(sr.getStatistics().get(0) instanceof OFFlowStatisticsRequest);
+ }
+
+ public void testOFStatisticsRequestVendor() throws Exception {
+ byte[] packet = new byte[] { 0x01, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x63, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x4c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20,
+ (byte) 0xe0, 0x00, 0x11, 0x00, 0x0c, 0x29, (byte) 0xc5,
+ (byte) 0x95, 0x57, 0x02, 0x25, 0x5c, (byte) 0xca, 0x00, 0x02,
+ (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x50, 0x04,
+ 0x00, 0x00, 0x00, 0x00, (byte) 0xff, 0x00, 0x00, 0x00,
+ (byte) 0xff, (byte) 0xff, 0x4e, 0x20 };
+
+ OFMessageFactory factory = new BasicFactory();
+ ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet);
+ List<OFMessage> msg = factory.parseMessage(packetBuf);
+ TestCase.assertNotNull(msg);
+ TestCase.assertEquals(msg.size(), 1);
+ TestCase.assertTrue(msg.get(0) instanceof OFStatisticsRequest);
+ OFStatisticsRequest sr = (OFStatisticsRequest) msg.get(0);
+ TestCase.assertEquals(OFStatisticsType.VENDOR, sr.getStatisticType());
+ TestCase.assertEquals(1, sr.getStatistics().size());
+ TestCase.assertTrue(sr.getStatistics().get(0) instanceof OFVendorStatistics);
+ TestCase.assertEquals(68, ((OFVendorStatistics)sr.getStatistics().get(0)).getLength());
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+import org.openflow.protocol.statistics.OFStatisticsType;
+
+
+public class OFStatisticsTypeTest extends TestCase {
+ @Test
+ public void testMapping() throws Exception {
+ TestCase.assertEquals(OFStatisticsType.DESC,
+ OFStatisticsType.valueOf((short) 0, OFType.STATS_REQUEST));
+ TestCase.assertEquals(OFStatisticsType.QUEUE,
+ OFStatisticsType.valueOf((short) 5, OFType.STATS_REQUEST));
+ TestCase.assertEquals(OFStatisticsType.VENDOR,
+ OFStatisticsType.valueOf((short) 0xffff, OFType.STATS_REQUEST));
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+
+
+public class OFTypeTest extends TestCase {
+
+ public void testOFTypeCreate() throws Exception {
+ OFType foo = OFType.HELLO;
+ Class<? extends OFMessage> c = foo.toClass();
+ TestCase.assertEquals(c, OFHello.class);
+ }
+
+ @Test
+ public void testMapping() throws Exception {
+ TestCase.assertEquals(OFType.HELLO, OFType.valueOf((byte) 0));
+ TestCase.assertEquals(OFType.BARRIER_REPLY, OFType.valueOf((byte) 19));
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.protocol;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.vendor.OFByteArrayVendorData;
+import org.openflow.protocol.vendor.OFBasicVendorDataType;
+import org.openflow.protocol.vendor.OFBasicVendorId;
+import org.openflow.protocol.vendor.OFVendorData;
+import org.openflow.protocol.vendor.OFVendorId;
+import org.openflow.util.OFTestCase;
+
+public class OFVendorTest extends OFTestCase {
+
+ public static int ACME_VENDOR_ID = 0x00112233;
+
+ static class AcmeVendorData implements OFVendorData {
+ protected int dataType;
+
+ public int getLength() {
+ return 4;
+ }
+
+ public void readFrom(ChannelBuffer data, int length) {
+ dataType = data.readInt();
+ }
+
+ public void writeTo(ChannelBuffer data) {
+ data.writeInt(dataType);
+ }
+ }
+
+ static class AcmeVendorData1 extends AcmeVendorData {
+ public short flags;
+ public short value;
+
+ public static int DATA_TYPE = 1;
+
+ public AcmeVendorData1() {
+ }
+
+ public AcmeVendorData1(short flags, short value) {
+ this.dataType = DATA_TYPE;
+ this.flags = flags;
+ this.value = value;
+ }
+
+ public short getFlags() {
+ return flags;
+ }
+
+ public short getValue() {
+ return value;
+ }
+
+ public int getLength() {
+ return 8;
+ }
+
+ public void readFrom(ChannelBuffer data, int length) {
+ super.readFrom(data, length);
+ flags = data.readShort();
+ value = data.readShort();
+
+ }
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(flags);
+ data.writeShort(value);
+ }
+
+ public static Instantiable<OFVendorData> getInstantiable() {
+ return new Instantiable<OFVendorData>() {
+ public OFVendorData instantiate() {
+ return new AcmeVendorData1();
+ }
+ };
+ }
+ }
+
+ static class AcmeVendorData2 extends AcmeVendorData {
+ public int type;
+ public int subtype;
+
+ public static int DATA_TYPE = 2;
+
+ public AcmeVendorData2() {
+ }
+
+ public AcmeVendorData2(int type, int subtype) {
+ this.dataType = DATA_TYPE;
+ this.type = type;
+ this.subtype = subtype;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public int getSubtype() {
+ return subtype;
+ }
+
+ public int getLength() {
+ return 12;
+ }
+
+ public void readFrom(ChannelBuffer data, int length) {
+ super.readFrom(data, length);
+ type = data.readShort();
+ subtype = data.readShort();
+
+ }
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeShort(type);
+ data.writeShort(subtype);
+ }
+
+ public static Instantiable<OFVendorData> getInstantiable() {
+ return new Instantiable<OFVendorData>() {
+ public OFVendorData instantiate() {
+ return new AcmeVendorData2();
+ }
+ };
+ }
+ }
+
+ {
+ OFBasicVendorId acmeVendorId = new OFBasicVendorId(ACME_VENDOR_ID, 4);
+ OFVendorId.registerVendorId(acmeVendorId);
+ OFBasicVendorDataType acmeVendorData1 = new OFBasicVendorDataType(
+ AcmeVendorData1.DATA_TYPE, AcmeVendorData1.getInstantiable());
+ acmeVendorId.registerVendorDataType(acmeVendorData1);
+ OFBasicVendorDataType acmeVendorData2 = new OFBasicVendorDataType(
+ AcmeVendorData2.DATA_TYPE, AcmeVendorData2.getInstantiable());
+ acmeVendorId.registerVendorDataType(acmeVendorData2);
+ }
+
+ private OFVendor makeVendorMessage(int vendor) {
+ OFVendor msg = (OFVendor) messageFactory.getMessage(OFType.VENDOR);
+ msg.setVendorDataFactory(new BasicFactory());
+ msg.setVendor(vendor);
+ return msg;
+ }
+
+ public void testWriteRead() throws Exception {
+ OFVendor msg = makeVendorMessage(1);
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ TestCase.assertEquals(1, msg.getVendor());
+ }
+
+ public void testVendorData() throws Exception {
+ OFVendor msg = makeVendorMessage(ACME_VENDOR_ID);
+ OFVendorData vendorData = new AcmeVendorData1((short)11, (short)22);
+ msg.setVendorData(vendorData);
+ msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength());
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ assertEquals(ACME_VENDOR_ID, msg.getVendor());
+ AcmeVendorData1 vendorData1 = (AcmeVendorData1) msg.getVendorData();
+ assertEquals(11, vendorData1.getFlags());
+ assertEquals(22, vendorData1.getValue());
+
+ vendorData = new AcmeVendorData2(33, 44);
+ msg.setVendorData(vendorData);
+ msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength());
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ assertEquals(ACME_VENDOR_ID, msg.getVendor());
+ AcmeVendorData2 vendorData2 = (AcmeVendorData2) msg.getVendorData();
+ assertEquals(33, vendorData2.getType());
+ assertEquals(44, vendorData2.getSubtype());
+
+ final int DUMMY_VENDOR_ID = 55;
+ msg.setVendor(DUMMY_VENDOR_ID);
+ byte[] genericVendorDataBytes = new byte[] {0x55, 0x66};
+ vendorData = new OFByteArrayVendorData(genericVendorDataBytes);
+ msg.setVendorData(vendorData);
+ msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength());
+ bb.clear();
+ msg.writeTo(bb);
+ msg.readFrom(bb);
+ assertEquals(DUMMY_VENDOR_ID, msg.getVendor());
+ OFByteArrayVendorData genericVendorData = (OFByteArrayVendorData) msg.getVendorData();
+ assertTrue(Arrays.equals(genericVendorDataBytes, genericVendorData.getBytes()));
+ }
+}
--- /dev/null
+package org.openflow.protocol;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.EnumSet;
+
+import org.junit.Test;
+import org.openflow.protocol.Wildcards.Flag;
+
+public class WildcardsTest {
+
+ @Test
+ public void testBasic() {
+ int[] intMasks = { 0, 0x3820e0, OFMatch.OFPFW_ALL_SANITIZED };
+ for (int i : intMasks) {
+ Wildcards w = Wildcards.of(i);
+ assertEquals(i, w.getInt());
+ }
+ }
+
+ @Test
+ public void testAllSanitize() {
+ Wildcards w = Wildcards.of(OFMatch.OFPFW_ALL);
+ assertEquals(OFMatch.OFPFW_ALL_SANITIZED, w.getInt());
+ assertTrue(w.isFull());
+ assertFalse(w.isExact());
+ }
+
+ @Test
+ public void testAll() {
+ Wildcards all = Wildcards.FULL;
+ assertTrue(all.isFull());
+ assertFalse(all.isExact());
+ assertEquals(0, all.getNwDstMask());
+ assertEquals(0, all.getNwSrcMask());
+
+ // unsetting flags from NONE is a no-op
+ Wildcards stillAll = all.wildcard(Flag.IN_PORT);
+ assertTrue(stillAll.isFull());
+ assertEquals(all, stillAll);
+
+ // so is setting a >= 32 netmask
+
+ stillAll = all.withNwSrcMask(0);
+ assertTrue(stillAll.isFull());
+ assertEquals(all, stillAll);
+
+ stillAll = all.withNwDstMask(0);
+ assertTrue(stillAll.isFull());
+ assertEquals(all, stillAll);
+ }
+
+ @Test
+ public void testNone() {
+ Wildcards none = Wildcards.EXACT;
+ assertTrue(none.isExact());
+ assertEquals(32, none.getNwDstMask());
+ assertEquals(32, none.getNwSrcMask());
+
+ // unsetting flags from NONE is a no-op
+ Wildcards stillNone = none.matchOn(Flag.IN_PORT);
+ assertTrue(stillNone.isExact());
+ assertEquals(none, stillNone);
+
+ // so is setting a >= 32 netmask
+ stillNone = none.withNwSrcMask(32);
+ assertTrue(stillNone.isExact());
+ assertEquals(none, stillNone);
+
+ stillNone = none.withNwDstMask(32);
+ assertTrue(stillNone.isExact());
+ assertEquals(none, stillNone);
+ }
+
+ @Test
+ public void testSetOneFlag() {
+ Wildcards none = Wildcards.EXACT;
+ assertTrue(none.isExact());
+ assertFalse(none.isWildcarded(Flag.DL_SRC));
+ Wildcards one = none.wildcard(Flag.DL_SRC);
+ assertFalse(one.isExact());
+ assertTrue(one.isWildcarded(Flag.DL_SRC));
+ assertEquals(OFMatch.OFPFW_DL_SRC, one.getInt());
+ assertEquals(EnumSet.of(Flag.DL_SRC), one.getWildcardedFlags());
+ }
+
+ @Test
+ public void testSetTwoFlags() {
+ Wildcards none = Wildcards.EXACT;
+
+ // set two flags
+ Wildcards two = none.wildcard(Flag.DL_SRC, Flag.DL_DST);
+ assertFalse(two.isExact());
+ assertTrue(two.isWildcarded(Flag.DL_SRC));
+ assertTrue(two.isWildcarded(Flag.DL_DST));
+ assertEquals(OFMatch.OFPFW_DL_SRC | OFMatch.OFPFW_DL_DST, two.getInt());
+ assertEquals(EnumSet.of(Flag.DL_SRC, Flag.DL_DST), two.getWildcardedFlags());
+
+ // unset dl_dst
+ Wildcards gone = two.matchOn(Flag.DL_DST);
+ assertFalse(gone.isExact());
+ assertTrue(gone.isWildcarded(Flag.DL_SRC));
+ assertFalse(gone.isWildcarded(Flag.DL_DST));
+ assertEquals(OFMatch.OFPFW_DL_SRC, gone.getInt());
+ assertEquals(EnumSet.of(Flag.DL_SRC), gone.getWildcardedFlags());
+ }
+
+ @Test
+ public void testSetNwSrc() {
+ Wildcards none = Wildcards.EXACT;
+ assertEquals(32, none.getNwSrcMask());
+
+ // unsetting flags from NONE is a no-op
+ Wildcards nwSet = none.withNwSrcMask(8);
+ assertFalse(nwSet.isExact());
+ assertEquals(EnumSet.noneOf(Flag.class), nwSet.getWildcardedFlags());
+ assertEquals(8, nwSet.getNwSrcMask());
+ assertEquals((32 - 8) << OFMatch.OFPFW_NW_SRC_SHIFT, nwSet.getInt());
+ }
+
+ @Test
+ public void testSetNwDst() {
+ Wildcards none = Wildcards.EXACT;
+ assertEquals(32, none.getNwDstMask());
+
+ // unsetting flags from NONE is a no-op
+ Wildcards nwSet = none.withNwDstMask(8);
+ assertFalse(nwSet.isExact());
+ assertEquals(EnumSet.noneOf(Flag.class), nwSet.getWildcardedFlags());
+ assertEquals(8, nwSet.getNwDstMask());
+ assertEquals((32 - 8) << OFMatch.OFPFW_NW_DST_SHIFT, nwSet.getInt());
+ }
+
+ @Test
+ public void testToString() {
+ String s = Wildcards.FULL.toString();
+ assertNotNull(s);
+ assertTrue(s.length() > 0);
+ }
+
+ @Test
+ public void testInvert() {
+ assertEquals(Wildcards.FULL, Wildcards.EXACT.inverted());
+
+ Wildcards some = Wildcards.of(Flag.DL_VLAN, Flag.DL_VLAN_PCP);
+ Wildcards inv = some.inverted();
+
+ for(Flag f : Flag.values()) {
+ boolean shouldBeSet = (f == Flag.DL_VLAN || f == Flag.DL_VLAN_PCP);
+
+ assertEquals("Flag " + f + " "
+ + (shouldBeSet ? "should be set " : "should not be set"),
+ shouldBeSet, some.isWildcarded(f));
+ assertEquals(!(f == Flag.DL_VLAN || f == Flag.DL_VLAN_PCP), inv.isWildcarded(f));
+ }
+ assertEquals(0, inv.getNwDstMask());
+ assertEquals(0, inv.getNwSrcMask());
+ }
+}
--- /dev/null
+package org.openflow.protocol.action;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+
+public class MockVendorAction extends OFActionVendor {
+ public static final int VENDOR_ID = 0xdeadbeef;
+
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ private byte[] mockData;
+
+ public byte[] getMockData() {
+ return mockData;
+ }
+
+ public void setMockData(byte[] mockData) {
+ this.mockData = mockData;
+ }
+
+ @Override
+ public void readFrom(ChannelBuffer data) {
+ super.readFrom(data);
+
+ int dataLength = getLength() - MINIMUM_LENGTH;
+ if(dataLength > 0) {
+ mockData = new byte[dataLength];
+ data.readBytes(mockData);
+ } else {
+ mockData = EMPTY_BYTE_ARRAY;
+ }
+
+ }
+
+ @Override
+ public void writeTo(ChannelBuffer data) {
+ super.writeTo(data);
+ data.writeBytes(mockData);
+ }
+
+
+}
--- /dev/null
+package org.openflow.protocol.action;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.factory.OFVendorActionFactory;
+
+public class MockVendorActionFactory implements OFVendorActionFactory {
+
+ @Override
+ public OFActionVendor readFrom(ChannelBuffer data) {
+ MockVendorAction action = new MockVendorAction();
+ action.readFrom(data);
+ return action;
+ }
+
+}
--- /dev/null
+package org.openflow.protocol.action;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.openflow.protocol.factory.OFVendorActionRegistry;
+
+public class OFVendorActionRegistryTest {
+
+ @Test
+ public void test() {
+ MockVendorActionFactory factory = new MockVendorActionFactory();
+ OFVendorActionRegistry.getInstance().register(MockVendorAction.VENDOR_ID, factory);
+ assertEquals(factory, OFVendorActionRegistry.getInstance().get(MockVendorAction.VENDOR_ID));
+ }
+
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+/**
+ * Does hexstring conversion work?
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ *
+ */
+
+public class HexStringTest extends TestCase {
+
+ @Test
+ public void testMarshalling() throws Exception {
+ String dpidStr = "00:00:00:23:20:2d:16:71";
+ long dpid = HexString.toLong(dpidStr);
+ String testStr = HexString.toHexString(dpid);
+ TestCase.assertEquals(dpidStr, testStr);
+ }
+
+ @Test
+ public void testToLong() {
+ String dpidStr = "3e:1f:01:fc:72:8c:63:31";
+ long valid = 0x3e1f01fc728c6331L;
+ long testLong = HexString.toLong(dpidStr);
+ TestCase.assertEquals(valid, testLong);
+ }
+
+ @Test
+ public void testToLongMSB() {
+ String dpidStr = "ca:7c:5e:d1:64:7a:95:9b";
+ long valid = -3856102927509056101L;
+ long testLong = HexString.toLong(dpidStr);
+ TestCase.assertEquals(valid, testLong);
+ }
+
+ @Test
+ public void testToLongError() {
+ String dpidStr = "09:08:07:06:05:04:03:02:01";
+ try {
+ HexString.toLong(dpidStr);
+ fail("HexString.toLong() should have thrown a NumberFormatException");
+ }
+ catch (NumberFormatException expected) {
+ // do nothing
+ }
+ }
+
+ @Test
+ public void testToStringBytes() {
+ byte[] dpid = { 0, 0, 0, 0, 0, 0, 0, -1 };
+ String valid = "00:00:00:00:00:00:00:ff";
+ String testString = HexString.toHexString(dpid);
+ TestCase.assertEquals(valid, testString);
+ }
+
+ @Test
+ public void testFromHexStringError() {
+ String invalidStr = "00:00:00:00:00:00:ffff";
+ try {
+ HexString.fromHexString(invalidStr);
+ fail("HexString.fromHexString() should have thrown a NumberFormatException");
+ }
+ catch (NumberFormatException expected) {
+ // do nothing
+ }
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.OFMessageFactory;
+
+import junit.framework.TestCase;
+
+public class OFTestCase extends TestCase {
+ public OFMessageFactory messageFactory;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ messageFactory = new BasicFactory();
+ }
+
+ public void test() throws Exception {
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import junit.framework.TestCase;
+
+public class U16Test extends TestCase {
+ /**
+ * Tests that we correctly translate unsigned values in and out of a short
+ * @throws Exception
+ */
+ public void test() throws Exception {
+ int val = 0xffff;
+ TestCase.assertEquals((short)-1, U16.t(val));
+ TestCase.assertEquals((short)32767, U16.t(0x7fff));
+ TestCase.assertEquals(val, U16.f((short)-1));
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import junit.framework.TestCase;
+
+public class U32Test extends TestCase {
+ /**
+ * Tests that we correctly translate unsigned values in and out of an int
+ * @throws Exception
+ */
+ public void test() throws Exception {
+ long val = 0xffffffffL;
+ TestCase.assertEquals(-1, U32.t(val));
+ TestCase.assertEquals(val, U32.f(-1));
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+
+public class U64Test extends TestCase {
+ /**
+ * Tests that we correctly translate unsigned values in and out of a long
+ * @throws Exception
+ */
+ public void test() throws Exception {
+ BigInteger val = new BigInteger("ffffffffffffffff", 16);
+ TestCase.assertEquals(-1, U64.t(val));
+ TestCase.assertEquals(val, U64.f(-1));
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import junit.framework.TestCase;
+
+public class U8Test extends TestCase {
+ /**
+ * Tests that we correctly translate unsigned values in and out of a byte
+ * @throws Exception
+ */
+ public void test() throws Exception {
+ short val = 0xff;
+ TestCase.assertEquals(-1, U8.t(val));
+ TestCase.assertEquals(val, U8.f((byte)-1));
+ }
+}
--- /dev/null
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* 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 org.openflow.util;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+import junit.framework.TestCase;
+
+public class UnsignedTest extends TestCase {
+ public static String ULONG_MAX = "18446744073709551615";
+
+ /**
+ * Tests that we correctly extract an unsigned long into a BigInteger
+ * @throws Exception
+ */
+ public void testGetUnsignedLong() throws Exception {
+ ByteBuffer bb = ByteBuffer.allocate(8);
+ bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
+ bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
+ bb.position(0);
+ bb.limit(8);
+ BigInteger bi = Unsigned.getUnsignedLong(bb);
+ BigInteger uLongMax = new BigInteger(ULONG_MAX);
+ for (int i = 0; i < uLongMax.bitCount(); ++i) {
+ TestCase.assertTrue("Bit: " + i + " should be: " + uLongMax.testBit(i),
+ uLongMax.testBit(i) == bi.testBit(i));
+ }
+ TestCase.assertEquals(ULONG_MAX, bi.toString());
+
+ bb = ByteBuffer.allocate(10);
+ bb.put((byte)0x00);
+ bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
+ bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
+ bb.put((byte)0x00);
+ bb.position(0);
+ bb.limit(10);
+ bi = Unsigned.getUnsignedLong(bb, 1);
+ uLongMax = new BigInteger(ULONG_MAX);
+ for (int i = 0; i < uLongMax.bitCount(); ++i) {
+ TestCase.assertTrue("Bit: " + i + " should be: " + uLongMax.testBit(i),
+ uLongMax.testBit(i) == bi.testBit(i));
+ }
+ TestCase.assertEquals(ULONG_MAX, bi.toString());
+ }
+
+ /**
+ * Tests that we correctly put an unsigned long into a ByteBuffer
+ * @throws Exception
+ */
+ public void testPutUnsignedLong() throws Exception {
+ ByteBuffer bb = ByteBuffer.allocate(8);
+ BigInteger uLongMax = new BigInteger(ULONG_MAX);
+ Unsigned.putUnsignedLong(bb, uLongMax);
+ for (int i = 0; i < 8; ++i) {
+ TestCase.assertTrue("Byte: " + i + " should be 0xff, was: " + bb.get(i),
+ (bb.get(i) & (short)0xff) == 0xff);
+ }
+
+ bb = ByteBuffer.allocate(10);
+ Unsigned.putUnsignedLong(bb, uLongMax, 1);
+ int offset = 1;
+ for (int i = 0; i < 8; ++i) {
+ TestCase.assertTrue("Byte: " + i + " should be 0xff, was: " +
+ bb.get(offset+i), (bb.get(offset+i) & (short)0xff) == 0xff);
+ }
+ }
+}