blob: 3272660a5eef69697f01b2e0c1e3df5e20b48f53 [file] [log] [blame]
Andreas Wundsam40e14f72013-05-06 14:49:08 -07001package org.openflow.types;
2
Yotam Harchol161a5d52013-07-25 17:17:48 -07003import org.jboss.netty.buffer.ChannelBuffer;
Andreas Wundsam40e14f72013-05-06 14:49:08 -07004import org.openflow.annotations.Immutable;
Yotam Harchol161a5d52013-07-25 17:17:48 -07005import org.openflow.exceptions.OFParseError;
Andreas Wundsam40e14f72013-05-06 14:49:08 -07006
7/**
8 * Abstraction of an logical / OpenFlow switch port (ofp_port_no) in OpenFlow.
9 * Immutable. Note: Switch port numbers were changed in OpenFlow 1.1 from uint16
10 * to uint32. This class uses a 32 bit representation internally. Port numbers
11 * are converted from/to uint16 when constructed / getPortNumberasShort is
12 * called. If this port is not representable in OpenFlow 1.0, an
13 * IllegalStateException is raised.
14 *
15 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
16 */
17@Immutable
Yotam Harchol161a5d52013-07-25 17:17:48 -070018public class OFPort implements OFValueType {
19 static final int LENGTH = 4;
20
Andreas Wundsam40e14f72013-05-06 14:49:08 -070021 // private int constants (OF1.1+) to avoid duplication in the code
22 // should not have to use these outside this class
23 private static final int OFPP_ANY_INT = 0xFFffFFff;
24 private static final int OFPP_LOCAL_INT = 0xFFffFFfe;
25 private static final int OFPP_CONTROLLER_INT = 0xFFffFFfd;
26 private static final int OFPP_ALL_INT = 0xFFffFFfc;
27 private static final int OFPP_FLOOD_INT = 0xFFffFFfb;
28 private static final int OFPP_NORMAL_INT = 0xFFffFFfa;
29 private static final int OFPP_TABLE_INT = 0xFFffFFf9;
30 private static final int OFPP_MAX_INT = 0xFFffFF00;
31 private static final int OFPP_IN_PORT_INT = 0xFFffFFf8;
32
33 // private short constants (OF1.0) to avoid duplication in the code
34 // should not have to use these outside this class
35 private static final short OFPP_ANY_SHORT = (short) 0xFFff;
36 private static final short OFPP_LOCAL_SHORT = (short) 0xFFfe;
37 private static final short OFPP_CONTROLLER_SHORT = (short) 0xFFfd;
38 private static final short OFPP_ALL_SHORT = (short) 0xFFfc;
39 private static final short OFPP_FLOOD_SHORT = (short) 0xFFfb;
40 private static final short OFPP_NORMAL_SHORT = (short) 0xFFfa;
41 private static final short OFPP_TABLE_SHORT = (short) 0xFFf9;
42 private static final short OFPP_IN_PORT_SHORT = (short) 0xFFf8;
43 private static final short OFPP_MAX_SHORT = (short) 0xFF00;
44 private static final int OFPP_MAX_SHORT_UNSIGNED = 0xFF00;
45
46 // ////////////// public constants - use to access well known OpenFlow ports
47
48 /** Maximum number of physical and logical switch ports. */
49 public final static OFPort MAX = new NamedPort(OFPP_MAX_INT, "max");
50
51 /**
52 * Send the packet out the input port. This reserved port must be explicitly
53 * used in order to send back out of the input port.
54 */
55 public final static OFPort IN_PORT = new NamedPort(OFPP_IN_PORT_INT, "in_port");
56
57 /**
58 * Submit the packet to the first flow table NB: This destination port can
59 * only be used in packet-out messages.
60 */
61 public final static OFPort TABLE = new NamedPort(OFPP_TABLE_INT, "table");
62
63 /** Process with normal L2/L3 switching. */
64 public final static OFPort NORMAL = new NamedPort(OFPP_NORMAL_INT, "normal");
65
66 /**
67 * All physical ports in VLAN, except input port and those blocked or link
68 * down
69 */
70 public final static OFPort FLOOD = new NamedPort(OFPP_FLOOD_INT, "flood");
71
72 /** All physical ports except input port */
73 public final static OFPort ALL = new NamedPort(OFPP_ALL_INT, "all");
74
75 /** Send to controller */
76 public final static OFPort CONTROLLER =
77 new NamedPort(OFPP_CONTROLLER_INT, "controller");
78
79 /** local openflow "port" */
80 public final static OFPort LOCAL = new NamedPort(OFPP_LOCAL_INT, "local");
81
82 /**
83 * Wildcard port used only for flow mod (delete) and flow stats requests.
84 * Selects all flows regardless of output port (including flows with no
85 * output port). NOTE: OpenFlow 1.0 calls this 'NONE'
86 */
87 public final static OFPort ANY = new NamedPort(OFPP_ANY_INT, "any");
88
89 /** cache of frequently used ports */
90 private static class PrecachedPort {
91 private final static OFPort p1 = new OFPort(1);
92 private final static OFPort p2 = new OFPort(2);
93 private final static OFPort p3 = new OFPort(3);
94 private final static OFPort p4 = new OFPort(4);
95 private final static OFPort p5 = new OFPort(5);
96 private final static OFPort p6 = new OFPort(6);
97 private final static OFPort p7 = new OFPort(7);
98 private final static OFPort p8 = new OFPort(8);
99 private final static OFPort p9 = new OFPort(9);
100 private final static OFPort p10 = new OFPort(10);
101 private final static OFPort p11 = new OFPort(11);
102 private final static OFPort p12 = new OFPort(12);
103 private final static OFPort p13 = new OFPort(13);
104 private final static OFPort p14 = new OFPort(14);
105 private final static OFPort p15 = new OFPort(15);
106 private final static OFPort p16 = new OFPort(16);
107 private final static OFPort p17 = new OFPort(17);
108 private final static OFPort p18 = new OFPort(18);
109 private final static OFPort p19 = new OFPort(19);
110 private final static OFPort p20 = new OFPort(20);
111 private final static OFPort p21 = new OFPort(21);
112 private final static OFPort p22 = new OFPort(22);
113 private final static OFPort p23 = new OFPort(23);
114 private final static OFPort p24 = new OFPort(24);
115 private final static OFPort p25 = new OFPort(25);
116 private final static OFPort p26 = new OFPort(26);
117 private final static OFPort p27 = new OFPort(27);
118 private final static OFPort p28 = new OFPort(28);
119 private final static OFPort p29 = new OFPort(29);
120 private final static OFPort p31 = new OFPort(31);
121 private final static OFPort p32 = new OFPort(32);
122 private final static OFPort p33 = new OFPort(33);
123 private final static OFPort p34 = new OFPort(34);
124 private final static OFPort p35 = new OFPort(35);
125 private final static OFPort p36 = new OFPort(36);
126 private final static OFPort p37 = new OFPort(37);
127 private final static OFPort p38 = new OFPort(38);
128 private final static OFPort p39 = new OFPort(39);
129 private final static OFPort p40 = new OFPort(40);
130 private final static OFPort p41 = new OFPort(41);
131 private final static OFPort p42 = new OFPort(42);
132 private final static OFPort p43 = new OFPort(43);
133 private final static OFPort p44 = new OFPort(44);
134 private final static OFPort p45 = new OFPort(45);
135 private final static OFPort p46 = new OFPort(46);
136 private final static OFPort p47 = new OFPort(47);
137 private final static OFPort p48 = new OFPort(48);
138 }
139
140 /** raw openflow port number as a signed 32 bit integer */
141 private final int portNumber;
142
143 /** private constructor. use of*-Factory methods instead */
144 private OFPort(final int portNumber) {
145 this.portNumber = portNumber;
146 }
147
148 /**
149 * get an OFPort object corresponding to a raw 32-bit integer port number.
150 * NOTE: The port object may either be newly allocated or cached. Do not
151 * rely on either behavior.
152 *
153 * @param portNumber
154 * @return a corresponding OFPort
155 */
156 public static OFPort ofInt(final int portNumber) {
157 switch (portNumber) {
158 case 1:
159 return PrecachedPort.p1;
160 case 2:
161 return PrecachedPort.p2;
162 case 3:
163 return PrecachedPort.p3;
164 case 4:
165 return PrecachedPort.p4;
166 case 5:
167 return PrecachedPort.p5;
168 case 6:
169 return PrecachedPort.p6;
170 case 7:
171 return PrecachedPort.p7;
172 case 8:
173 return PrecachedPort.p8;
174 case 9:
175 return PrecachedPort.p9;
176 case 10:
177 return PrecachedPort.p10;
178 case 11:
179 return PrecachedPort.p11;
180 case 12:
181 return PrecachedPort.p12;
182 case 13:
183 return PrecachedPort.p13;
184 case 14:
185 return PrecachedPort.p14;
186 case 15:
187 return PrecachedPort.p15;
188 case 16:
189 return PrecachedPort.p16;
190 case 17:
191 return PrecachedPort.p17;
192 case 18:
193 return PrecachedPort.p18;
194 case 19:
195 return PrecachedPort.p19;
196 case 20:
197 return PrecachedPort.p20;
198 case 21:
199 return PrecachedPort.p21;
200 case 22:
201 return PrecachedPort.p22;
202 case 23:
203 return PrecachedPort.p23;
204 case 24:
205 return PrecachedPort.p24;
206 case 25:
207 return PrecachedPort.p25;
208 case 26:
209 return PrecachedPort.p26;
210 case 27:
211 return PrecachedPort.p27;
212 case 28:
213 return PrecachedPort.p28;
214 case 29:
215 return PrecachedPort.p29;
216 case 31:
217 return PrecachedPort.p31;
218 case 32:
219 return PrecachedPort.p32;
220 case 33:
221 return PrecachedPort.p33;
222 case 34:
223 return PrecachedPort.p34;
224 case 35:
225 return PrecachedPort.p35;
226 case 36:
227 return PrecachedPort.p36;
228 case 37:
229 return PrecachedPort.p37;
230 case 38:
231 return PrecachedPort.p38;
232 case 39:
233 return PrecachedPort.p39;
234 case 40:
235 return PrecachedPort.p40;
236 case 41:
237 return PrecachedPort.p41;
238 case 42:
239 return PrecachedPort.p42;
240 case 43:
241 return PrecachedPort.p43;
242 case 44:
243 return PrecachedPort.p44;
244 case 45:
245 return PrecachedPort.p45;
246 case 46:
247 return PrecachedPort.p46;
248 case 47:
249 return PrecachedPort.p47;
250 case 48:
251 return PrecachedPort.p48;
252 case OFPP_MAX_INT:
253 return MAX;
254 case OFPP_IN_PORT_INT:
255 return IN_PORT;
256 case OFPP_TABLE_INT:
257 return TABLE;
258 case OFPP_NORMAL_INT:
259 return NORMAL;
260 case OFPP_FLOOD_INT:
261 return FLOOD;
262 case OFPP_ALL_INT:
263 return ALL;
264 case OFPP_CONTROLLER_INT:
265 return CONTROLLER;
266 case OFPP_LOCAL_INT:
267 return LOCAL;
268 case OFPP_ANY_INT:
269 return ANY;
270 default:
271 // note: This means effectively : portNumber > OFPP_MAX_SHORT
272 // accounting for
273 // signedness of both portNumber and OFPP_MAX_INT(which is
274 // -256).
275 // Any unsigned integer value > OFPP_MAX_INT will be ]-256:0[
276 // when read signed
277 if (portNumber < 0 && portNumber > OFPP_MAX_INT)
278 throw new IllegalArgumentException("Unknown special port number: "
279 + portNumber);
280 return new OFPort(portNumber);
281 }
282 }
283
284 /** convenience function: delegates to ofInt */
285 public static OFPort of(final int portNumber) {
286 return ofInt(portNumber);
287 }
288
289 /**
290 * get an OFPort object corresponding to a raw signed 16-bit integer port
291 * number (OF1.0). Note that the port returned will have the corresponding
292 * 32-bit integer value allocated as its port number. NOTE: The port object
293 * may either be newly allocated or cached. Do not rely on either behavior.
294 *
295 * @param portNumber
296 * @return a corresponding OFPort
297 */
298 public static OFPort ofShort(final short portNumber) {
299 switch (portNumber) {
300 case 1:
301 return PrecachedPort.p1;
302 case 2:
303 return PrecachedPort.p2;
304 case 3:
305 return PrecachedPort.p3;
306 case 4:
307 return PrecachedPort.p4;
308 case 5:
309 return PrecachedPort.p5;
310 case 6:
311 return PrecachedPort.p6;
312 case 7:
313 return PrecachedPort.p7;
314 case 8:
315 return PrecachedPort.p8;
316 case 9:
317 return PrecachedPort.p9;
318 case 10:
319 return PrecachedPort.p10;
320 case 11:
321 return PrecachedPort.p11;
322 case 12:
323 return PrecachedPort.p12;
324 case 13:
325 return PrecachedPort.p13;
326 case 14:
327 return PrecachedPort.p14;
328 case 15:
329 return PrecachedPort.p15;
330 case 16:
331 return PrecachedPort.p16;
332 case 17:
333 return PrecachedPort.p17;
334 case 18:
335 return PrecachedPort.p18;
336 case 19:
337 return PrecachedPort.p19;
338 case 20:
339 return PrecachedPort.p20;
340 case 21:
341 return PrecachedPort.p21;
342 case 22:
343 return PrecachedPort.p22;
344 case 23:
345 return PrecachedPort.p23;
346 case 24:
347 return PrecachedPort.p24;
348 case 25:
349 return PrecachedPort.p25;
350 case 26:
351 return PrecachedPort.p26;
352 case 27:
353 return PrecachedPort.p27;
354 case 28:
355 return PrecachedPort.p28;
356 case 29:
357 return PrecachedPort.p29;
358 case 31:
359 return PrecachedPort.p31;
360 case 32:
361 return PrecachedPort.p32;
362 case 33:
363 return PrecachedPort.p33;
364 case 34:
365 return PrecachedPort.p34;
366 case 35:
367 return PrecachedPort.p35;
368 case 36:
369 return PrecachedPort.p36;
370 case 37:
371 return PrecachedPort.p37;
372 case 38:
373 return PrecachedPort.p38;
374 case 39:
375 return PrecachedPort.p39;
376 case 40:
377 return PrecachedPort.p40;
378 case 41:
379 return PrecachedPort.p41;
380 case 42:
381 return PrecachedPort.p42;
382 case 43:
383 return PrecachedPort.p43;
384 case 44:
385 return PrecachedPort.p44;
386 case 45:
387 return PrecachedPort.p45;
388 case 46:
389 return PrecachedPort.p46;
390 case 47:
391 return PrecachedPort.p47;
392 case 48:
393 return PrecachedPort.p48;
394 case OFPP_MAX_SHORT:
395 return MAX;
396 case OFPP_IN_PORT_SHORT:
397 return IN_PORT;
398 case OFPP_TABLE_SHORT:
399 return TABLE;
400 case OFPP_NORMAL_SHORT:
401 return NORMAL;
402 case OFPP_FLOOD_SHORT:
403 return FLOOD;
404 case OFPP_ALL_SHORT:
405 return ALL;
406 case OFPP_CONTROLLER_SHORT:
407 return CONTROLLER;
408 case OFPP_LOCAL_SHORT:
409 return LOCAL;
410 case OFPP_ANY_SHORT:
411 return ANY;
412 default:
413 // note: This means effectively : portNumber > OFPP_MAX_SHORT
414 // accounting for
415 // signedness of both portNumber and OFPP_MAX_SHORT (which is
416 // -256).
417 // Any unsigned integer value > OFPP_MAX_SHORT will be ]-256:0[
418 // when read signed
419 if (portNumber < 0 && portNumber > OFPP_MAX_SHORT)
420 throw new IllegalArgumentException("Unknown special port number: "
421 + portNumber);
422 return new OFPort(portNumber);
423 }
424 }
425
426 /** return the port number as a int32 */
427 public int getPortNumber() {
428 return portNumber;
429 }
430
431 /**
432 * return the port number as int16. Special ports as defined by the OpenFlow
433 * spec will be converted to their OpenFlow 1.0 equivalent. port numbers >=
434 * FF00 will cause a IllegalArgumentException to be thrown
435 *
436 * @throws IllegalArgumentException
437 * if a regular port number exceeds the maximum value in OF1.0
438 **/
439 public short getShortPortNumber() {
440
441 switch (portNumber) {
442 case OFPP_MAX_INT:
443 return OFPP_MAX_SHORT;
444 case OFPP_IN_PORT_INT:
445 return OFPP_IN_PORT_SHORT;
446 case OFPP_TABLE_INT:
447 return OFPP_TABLE_SHORT;
448 case OFPP_NORMAL_INT:
449 return OFPP_NORMAL_SHORT;
450 case OFPP_FLOOD_INT:
451 return OFPP_FLOOD_SHORT;
452 case OFPP_ALL_INT:
453 return OFPP_ALL_SHORT;
454 case OFPP_CONTROLLER_INT:
455 return OFPP_CONTROLLER_SHORT;
456 case OFPP_LOCAL_INT:
457 return OFPP_LOCAL_SHORT;
458 case OFPP_ANY_INT:
459 return OFPP_ANY_SHORT;
460
461 default:
462 if (portNumber >= OFPP_MAX_SHORT_UNSIGNED || portNumber < 0)
463 throw new IllegalArgumentException("32bit Port number "
464 + U32.f(portNumber)
465 + " cannot be represented as uint16 (OF1.0)");
466
467 return (short) portNumber;
468 }
469 }
470
471 @Override
472 public String toString() {
473 return Long.toString(U32.f(portNumber));
474 }
475
476 /** Extension of OFPort for named ports */
477 static class NamedPort extends OFPort {
478 private final String name;
479
480 NamedPort(final int portNo, final String name) {
481 super(portNo);
482 this.name = name;
483 }
484
485 public String getName() {
486 return name;
487 }
488
489 @Override
490 public String toString() {
491 return name;
492 }
493 }
494
Yotam Harchol161a5d52013-07-25 17:17:48 -0700495 @Override
496 public int getLength() {
497 return LENGTH;
498 }
499
Yotam Harchol161a5d52013-07-25 17:17:48 -0700500 @Override
501 public boolean equals(Object obj) {
502 if (!(obj instanceof OFPort))
503 return false;
504 OFPort other = (OFPort)obj;
505 if (other.portNumber != this.portNumber)
506 return false;
507 return true;
508 }
509
510 @Override
511 public int hashCode() {
512 final int prime = 53;
513 int result = 1;
514 result = prime * result + portNumber;
515 return result;
516 }
517
Yotam Harchold7b84202013-07-26 16:08:10 -0700518 public void write2Bytes(ChannelBuffer c) {
519 c.writeShort(this.portNumber);
Yotam Harchol161a5d52013-07-25 17:17:48 -0700520 }
521
Yotam Harchold7b84202013-07-26 16:08:10 -0700522 public static OFPort read2Bytes(ChannelBuffer c) throws OFParseError {
523 return OFPort.of((c.readUnsignedShort() & 0x0FFFF));
524 }
Yotam Harchol161a5d52013-07-25 17:17:48 -0700525
Yotam Harchold7b84202013-07-26 16:08:10 -0700526 public void write4Bytes(ChannelBuffer c) {
527 c.writeInt(this.portNumber);
528 }
Yotam Harchol161a5d52013-07-25 17:17:48 -0700529
Yotam Harchold7b84202013-07-26 16:08:10 -0700530 public static OFPort read4Bytes(ChannelBuffer c) throws OFParseError {
531 return OFPort.of((int)(c.readUnsignedInt() & 0xFFFFFFFF));
Yotam Harchol161a5d52013-07-25 17:17:48 -0700532 }
Andreas Wundsam40e14f72013-05-06 14:49:08 -0700533}