2 * Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
5 * Licensed under the Apache License, Version 2.0 (the "License"); you may
6 * not use this file except in compliance with the License. You may obtain
7 * a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations
18 package org.openflow.protocol;
20 import java.util.Arrays;
21 import java.util.List;
23 import org.jboss.netty.buffer.ChannelBuffer;
24 import org.openflow.protocol.action.OFAction;
25 import org.openflow.protocol.factory.OFActionFactory;
26 import org.openflow.protocol.factory.OFActionFactoryAware;
27 import org.openflow.util.HexString;
28 import org.openflow.util.U16;
31 * Represents an ofp_packet_out message
33 * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 12, 2010
35 public class OFPacketOut extends OFMessage implements OFActionFactoryAware {
36 public static int MINIMUM_LENGTH = 16;
37 public static int BUFFER_ID_NONE = 0xffffffff;
39 protected OFActionFactory actionFactory;
40 protected int bufferId;
41 protected short inPort;
42 protected short actionsLength;
43 protected List<OFAction> actions;
44 protected byte[] packetData;
46 public OFPacketOut() {
48 this.type = OFType.PACKET_OUT;
49 this.length = U16.t(MINIMUM_LENGTH);
50 this.bufferId = BUFFER_ID_NONE;
57 public int getBufferId() {
65 public OFPacketOut setBufferId(int bufferId) {
66 if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) {
67 throw new IllegalArgumentException(
68 "PacketOut should not have both bufferId and packetData set");
70 this.bufferId = bufferId;
75 * Returns the packet data
78 public byte[] getPacketData() {
79 return this.packetData;
83 * Sets the packet data
86 public OFPacketOut setPacketData(byte[] packetData) {
87 if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) {
88 throw new IllegalArgumentException(
89 "PacketOut should not have both bufferId and packetData set");
91 this.packetData = packetData;
99 public short getInPort() {
107 public OFPacketOut setInPort(short inPort) {
108 this.inPort = inPort;
113 * Set in_port. Convenience method using OFPort enum.
116 public OFPacketOut setInPort(OFPort inPort) {
117 this.inPort = inPort.getValue();
125 public short getActionsLength() {
126 return this.actionsLength;
130 * Get actions_len, unsigned
133 public int getActionsLengthU() {
134 return U16.f(this.actionsLength);
139 * @param actionsLength
141 public OFPacketOut setActionsLength(short actionsLength) {
142 this.actionsLength = actionsLength;
147 * Returns the actions contained in this message
148 * @return a list of ordered OFAction objects
150 public List<OFAction> getActions() {
155 * Sets the list of actions on this message
156 * @param actions a list of ordered OFAction objects
158 public OFPacketOut setActions(List<OFAction> actions) {
159 this.actions = actions;
164 public void setActionFactory(OFActionFactory actionFactory) {
165 this.actionFactory = actionFactory;
169 public void readFrom(ChannelBuffer data) {
170 super.readFrom(data);
171 this.bufferId = data.readInt();
172 this.inPort = data.readShort();
173 this.actionsLength = data.readShort();
174 if ( this.actionFactory == null)
175 throw new RuntimeException("ActionFactory not set");
176 this.actions = this.actionFactory.parseActions(data, getActionsLengthU());
177 this.packetData = new byte[getLengthU() - MINIMUM_LENGTH - getActionsLengthU()];
178 data.readBytes(this.packetData);
183 public void writeTo(ChannelBuffer data) {
186 data.writeInt(bufferId);
187 data.writeShort(inPort);
188 data.writeShort(actionsLength);
189 for (OFAction action : actions) {
190 action.writeTo(data);
192 if (this.packetData != null)
193 data.writeBytes(this.packetData);
196 /** validate the invariants of this OFMessage hold */
197 public void validate() {
198 if (!((bufferId != BUFFER_ID_NONE) ^ (packetData != null && packetData.length > 0))) {
199 throw new IllegalStateException(
200 "OFPacketOut must have exactly one of (bufferId, packetData) set (not one, not both)");
205 public int hashCode() {
206 final int prime = 293;
207 int result = super.hashCode();
208 result = prime * result + ((actions == null) ? 0 : actions.hashCode());
209 result = prime * result + actionsLength;
210 result = prime * result + bufferId;
211 result = prime * result + inPort;
212 result = prime * result + Arrays.hashCode(packetData);
217 public boolean equals(Object obj) {
221 if (!super.equals(obj)) {
224 if (!(obj instanceof OFPacketOut)) {
227 OFPacketOut other = (OFPacketOut) obj;
228 if (actions == null) {
229 if (other.actions != null) {
232 } else if (!actions.equals(other.actions)) {
235 if (actionsLength != other.actionsLength) {
238 if (bufferId != other.bufferId) {
241 if (inPort != other.inPort) {
244 if (!Arrays.equals(packetData, other.packetData)) {
251 * @see java.lang.Object#toString()
254 public String toString() {
255 return "OFPacketOut [actionFactory=" + actionFactory + ", actions="
256 + actions + ", actionsLength=" + actionsLength + ", bufferId=0x"
257 + Integer.toHexString(bufferId) + ", inPort=" + inPort + ", packetData="
258 + HexString.toHexString(packetData) + "]";