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