ef4aa61f1b0e86a245bc6dd5ba9aa55c0ba2557d
[controller.git] / third-party / openflowj_netty / src / main / java / org / openflow / protocol / OFPacketOut.java
1 /**
2 *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
3 *    University
4 *
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
8 *
9 *         http://www.apache.org/licenses/LICENSE-2.0
10 *
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
15 *    under the License.
16 **/
17
18 package org.openflow.protocol;
19
20 import java.util.Arrays;
21 import java.util.List;
22
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;
29
30 /**
31  * Represents an ofp_packet_out message
32  *
33  * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 12, 2010
34  */
35 public class OFPacketOut extends OFMessage implements OFActionFactoryAware {
36     public static int MINIMUM_LENGTH = 16;
37     public static int BUFFER_ID_NONE = 0xffffffff;
38
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;
45
46     public OFPacketOut() {
47         super();
48         this.type = OFType.PACKET_OUT;
49         this.length = U16.t(MINIMUM_LENGTH);
50         this.bufferId = BUFFER_ID_NONE;
51     }
52
53     /**
54      * Get buffer_id
55      * @return
56      */
57     public int getBufferId() {
58         return this.bufferId;
59     }
60
61     /**
62      * Set buffer_id
63      * @param bufferId
64      */
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");
69         }
70         this.bufferId = bufferId;
71         return this;
72     }
73
74     /**
75      * Returns the packet data
76      * @return
77      */
78     public byte[] getPacketData() {
79         return this.packetData;
80     }
81
82     /**
83      * Sets the packet data
84      * @param packetData
85      */
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");
90         }
91         this.packetData = packetData;
92         return this;
93     }
94
95     /**
96      * Get in_port
97      * @return
98      */
99     public short getInPort() {
100         return this.inPort;
101     }
102
103     /**
104      * Set in_port
105      * @param inPort
106      */
107     public OFPacketOut setInPort(short inPort) {
108         this.inPort = inPort;
109         return this;
110     }
111
112     /**
113      * Set in_port. Convenience method using OFPort enum.
114      * @param inPort
115      */
116     public OFPacketOut setInPort(OFPort inPort) {
117         this.inPort = inPort.getValue();
118         return this;
119     }
120
121     /**
122      * Get actions_len
123      * @return
124      */
125     public short getActionsLength() {
126         return this.actionsLength;
127     }
128
129     /**
130      * Get actions_len, unsigned
131      * @return
132      */
133     public int getActionsLengthU() {
134         return U16.f(this.actionsLength);
135     }
136
137     /**
138      * Set actions_len
139      * @param actionsLength
140      */
141     public OFPacketOut setActionsLength(short actionsLength) {
142         this.actionsLength = actionsLength;
143         return this;
144     }
145
146     /**
147      * Returns the actions contained in this message
148      * @return a list of ordered OFAction objects
149      */
150     public List<OFAction> getActions() {
151         return this.actions;
152     }
153
154     /**
155      * Sets the list of actions on this message
156      * @param actions a list of ordered OFAction objects
157      */
158     public OFPacketOut setActions(List<OFAction> actions) {
159         this.actions = actions;
160         return this;
161     }
162
163     @Override
164     public void setActionFactory(OFActionFactory actionFactory) {
165         this.actionFactory = actionFactory;
166     }
167
168     @Override
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);
179         validate();
180     }
181
182     @Override
183     public void writeTo(ChannelBuffer data) {
184         validate();
185         super.writeTo(data);
186         data.writeInt(bufferId);
187         data.writeShort(inPort);
188         data.writeShort(actionsLength);
189         for (OFAction action : actions) {
190             action.writeTo(data);
191         }
192         if (this.packetData != null)
193             data.writeBytes(this.packetData);
194     }
195
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)");
201         }
202     }
203
204     @Override
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);
213         return result;
214     }
215
216     @Override
217     public boolean equals(Object obj) {
218         if (this == obj) {
219             return true;
220         }
221         if (!super.equals(obj)) {
222             return false;
223         }
224         if (!(obj instanceof OFPacketOut)) {
225             return false;
226         }
227         OFPacketOut other = (OFPacketOut) obj;
228         if (actions == null) {
229             if (other.actions != null) {
230                 return false;
231             }
232         } else if (!actions.equals(other.actions)) {
233             return false;
234         }
235         if (actionsLength != other.actionsLength) {
236             return false;
237         }
238         if (bufferId != other.bufferId) {
239             return false;
240         }
241         if (inPort != other.inPort) {
242             return false;
243         }
244         if (!Arrays.equals(packetData, other.packetData)) {
245             return false;
246         }
247         return true;
248     }
249
250     /* (non-Javadoc)
251      * @see java.lang.Object#toString()
252      */
253     @Override
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) + "]";
259     }
260 }