/**
* 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();
}
}