blob: 7ea69a7ef921334a5bce1bd18ac53b28ed1d6384 [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/**
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
18package org.openflow.protocol;
19
20import java.text.DateFormat;
21import java.text.SimpleDateFormat;
22import java.util.Date;
23import java.util.concurrent.ConcurrentHashMap;
24
25import net.floodlightcontroller.core.FloodlightContext;
26import net.floodlightcontroller.core.IFloodlightProviderService;
27import net.floodlightcontroller.core.IOFSwitch;
28import net.floodlightcontroller.packet.Ethernet;
29
30import org.jboss.netty.buffer.ChannelBuffer;
31import org.openflow.util.HexString;
32import org.openflow.util.U16;
33import org.openflow.util.U32;
34import org.openflow.util.U8;
35
36/**
37 * The base class for all OpenFlow protocol messages. This class contains the
38 * equivalent of the ofp_header which is present in all OpenFlow messages.
39 *
40 * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 3, 2010
41 * @author Rob Sherwood (rob.sherwood@stanford.edu) - Feb 3, 2010
42 */
43public class OFMessage {
44 public static byte OFP_VERSION = 0x01;
45 public static int MINIMUM_LENGTH = 8;
46
47 protected byte version;
48 protected OFType type;
49 protected short length;
50 protected int xid;
51
52 private ConcurrentHashMap<String, Object> storage;
53
54 public OFMessage() {
55 storage = null;
56 this.version = OFP_VERSION;
57 }
58
59 protected synchronized ConcurrentHashMap<String, Object> getMessageStore() {
60 if (storage == null) {
61 storage = new ConcurrentHashMap<String, Object>();;
62 }
63 return storage;
64 }
65
66 /**
67 * Get the length of this message
68 *
69 * @return
70 */
71 public short getLength() {
72 return length;
73 }
74
75 /**
76 * Get the length of this message, unsigned
77 *
78 * @return
79 */
80 public int getLengthU() {
81 return U16.f(length);
82 }
83
84 /**
85 * Set the length of this message
86 *
87 * @param length
88 */
89 public OFMessage setLength(short length) {
90 this.length = length;
91 return this;
92 }
93
94 /**
95 * Set the length of this message, unsigned
96 *
97 * @param length
98 */
99 public OFMessage setLengthU(int length) {
100 this.length = U16.t(length);
101 return this;
102 }
103
104 /**
105 * Get the type of this message
106 *
107 * @return
108 */
109 public OFType getType() {
110 return type;
111 }
112
113 /**
114 * Set the type of this message
115 *
116 * @param type
117 */
118 public void setType(OFType type) {
119 this.type = type;
120 }
121
122 /**
123 * Get the OpenFlow version of this message
124 *
125 * @return
126 */
127 public byte getVersion() {
128 return version;
129 }
130
131 /**
132 * Set the OpenFlow version of this message
133 *
134 * @param version
135 */
136 public void setVersion(byte version) {
137 this.version = version;
138 }
139
140 /**
141 * Get the transaction id of this message
142 *
143 * @return
144 */
145 public int getXid() {
146 return xid;
147 }
148
149 /**
150 * Set the transaction id of this message
151 *
152 * @param xid
153 */
154 public void setXid(int xid) {
155 this.xid = xid;
156 }
157
158 /**
159 * Read this message off the wire from the specified ByteBuffer
160 * @param data
161 */
162 public void readFrom(ChannelBuffer data) {
163 this.version = data.readByte();
164 this.type = OFType.valueOf(data.readByte());
165 this.length = data.readShort();
166 this.xid = data.readInt();
167 }
168
169 /**
170 * Write this message's binary format to the specified ByteBuffer
171 * @param data
172 */
173 public void writeTo(ChannelBuffer data) {
174 data.writeByte(version);
175 data.writeByte(type.getTypeValue());
176 data.writeShort(length);
177 data.writeInt(xid);
178 }
179
180 /**
181 * Returns a summary of the message
182 * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid"
183 */
184 public String toString() {
185 return "ofmsg" +
186 ":v=" + U8.f(this.getVersion()) +
187 ";t=" + this.getType() +
188 ";l=" + this.getLengthU() +
189 ";x=" + U32.f(this.getXid());
190 }
191
192 @Override
193 public int hashCode() {
194 final int prime = 97;
195 int result = 1;
196 result = prime * result + length;
197 result = prime * result + ((type == null) ? 0 : type.hashCode());
198 result = prime * result + version;
199 result = prime * result + xid;
200 return result;
201 }
202
203 @Override
204 public boolean equals(Object obj) {
205 if (this == obj) {
206 return true;
207 }
208 if (obj == null) {
209 return false;
210 }
211 if (!(obj instanceof OFMessage)) {
212 return false;
213 }
214 OFMessage other = (OFMessage) obj;
215 if (length != other.length) {
216 return false;
217 }
218 if (type == null) {
219 if (other.type != null) {
220 return false;
221 }
222 } else if (!type.equals(other.type)) {
223 return false;
224 }
225 if (version != other.version) {
226 return false;
227 }
228 if (xid != other.xid) {
229 return false;
230 }
231 return true;
232 }
233
234 public static String getDataAsString(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
235
236 Ethernet eth;
237 StringBuffer sb = new StringBuffer("");
238
239 DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
240 Date date = new Date();
241
242 sb.append(dateFormat.format(date));
243 sb.append(" ");
244
245 switch (msg.getType()) {
246 case PACKET_IN:
247 OFPacketIn pktIn = (OFPacketIn) msg;
248 sb.append("packet_in [ ");
249 sb.append(sw.getStringId());
250 sb.append(" -> Controller");
251 sb.append(" ]");
252
253 sb.append("\ntotal length: ");
254 sb.append(pktIn.getTotalLength());
255 sb.append("\nin_port: ");
256 sb.append(pktIn.getInPort());
257 sb.append("\ndata_length: ");
258 sb.append(pktIn.getTotalLength() - OFPacketIn.MINIMUM_LENGTH);
259 sb.append("\nbuffer: ");
260 sb.append(pktIn.getBufferId());
261
262 // If the conext is not set by floodlight, then ignore.
263 if (cntx != null) {
264 // packet type icmp, arp, etc.
265 eth = IFloodlightProviderService.bcStore.get(cntx,
266 IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
267 if (eth != null)
268 sb.append(eth.toString());
269 }
270 break;
271
272 case PACKET_OUT:
273 OFPacketOut pktOut = (OFPacketOut) msg;
274 sb.append("packet_out [ ");
275 sb.append("Controller -> ");
276 sb.append(HexString.toHexString(sw.getId()));
277 sb.append(" ]");
278
279 sb.append("\nin_port: ");
280 sb.append(pktOut.getInPort());
281 sb.append("\nactions_len: ");
282 sb.append(pktOut.getActionsLength());
283 if (pktOut.getActions() != null) {
284 sb.append("\nactions: ");
285 sb.append(pktOut.getActions().toString());
286 }
287 break;
288
289 case FLOW_MOD:
290 OFFlowMod fm = (OFFlowMod) msg;
291 sb.append("flow_mod [ ");
292 sb.append("Controller -> ");
293 sb.append(HexString.toHexString(sw.getId()));
294 sb.append(" ]");
295
296 // If the conext is not set by floodlight, then ignore.
297 if (cntx != null) {
298 eth = IFloodlightProviderService.bcStore.get(cntx,
299 IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
300 if (eth != null)
301 sb.append(eth.toString());
302 }
303
304 sb.append("\nADD: cookie: ");
305 sb.append(fm.getCookie());
306 sb.append(" idle: ");
307 sb.append(fm.getIdleTimeout());
308 sb.append(" hard: ");
309 sb.append(fm.getHardTimeout());
310 sb.append(" pri: ");
311 sb.append(fm.getPriority());
312 sb.append(" buf: ");
313 sb.append(fm.getBufferId());
314 sb.append(" flg: ");
315 sb.append(fm.getFlags());
316 if (fm.getActions() != null) {
317 sb.append("\nactions: ");
318 sb.append(fm.getActions().toString());
319 }
320 break;
321
322 default:
323 sb.append("[Unknown Packet]");
324 }
325
326 sb.append("\n\n");
327 return sb.toString();
328
329 }
330
331 public static byte[] getData(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
332 return OFMessage.getDataAsString(sw, msg, cntx).getBytes();
333 }
334}