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