blob: 2268ce6f490af7ba94c41538d02bc891ad80137a [file] [log] [blame]
Yotam Harcholf3f11152013-09-05 16:47:16 -07001/**
2 * Copyright 2013, Big Switch Networks, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may
5 * not use this file except in compliance with the License. You may obtain
6 * a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 **/
16
17package org.projectfloodlight.openflow.protocol;
18
19import java.util.ArrayList;
20import java.util.EnumSet;
21import java.util.Iterator;
22import java.util.List;
23import java.util.Set;
24
25import com.google.common.base.Joiner;
26
27/**
28 * a more user friendly representation of the wildcards bits in an OpenFlow
29 * match. The Wildcards object is
30 * <ul>
31 * <li>immutable (i.e., threadsafe)</li>
32 * <li>instance managed (don't instantiate it yourself), instead call "of"</li>
33 * <ul>
34 * <p>
35 * You can construct a Wildcard object from either its integer representation
36 * </p>
37 * <code>
38 * Wildcard.of(0x3820e0);
39 * </code>
40 * <p>
41 * Or start with either an empty or full wildcard, and select/unselect foo.
42 * </p>
43 * <code>
44 * Wildcard w = Wildcards.NONE
45 * .set(Flag.DL_SRC, Flag. DL_DST, Flag.DL_VLAN_PCP)
46 * .setNwDstMask(8)
47 * .setNwSrcMask(8);
48 * </code>
49 * <p>
50 * <b>Remember:</b> Wildcards objects are immutable. set... operations have
51 * <b>NO EFFECT</b> on the current wildcard object. You HAVE to use the returned
52 * changed object.
53 * </p>
54 *
55 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
56 */
57public class Wildcards {
58 public class OFWildcardFlags {
59 final public static int OFPFW_ALL = ((1 << 22) - 1);
60
61 final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
62 final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
63 final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
64 final public static int OFPFW_DL_DST = 1 << 3; /*
65 * Ethernet destination
66 * address.
67 */
68 final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
69 final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
70 final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
71 final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
72
73 /*
74 * IP source address wildcard bit count. 0 is exact match, 1 ignores the
75 * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
76 * the entire field. This is the *opposite* of the usual convention where
77 * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
78 */
79 final public static int OFPFW_NW_SRC_SHIFT = 8;
80 final public static int OFPFW_NW_SRC_BITS = 6;
81 final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
82 final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
83
84 /* IP destination address wildcard bit count. Same format as source. */
85 final public static int OFPFW_NW_DST_SHIFT = 14;
86 final public static int OFPFW_NW_DST_BITS = 6;
87 final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
88 final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
89
90 final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
91 final public static int OFPFW_NW_TOS = 1 << 21; /*
92 * IP ToS (DSCP field, 6
93 * bits).
94 */
95
96 final public static int OFPFW_ALL_SANITIZED = (((1 << 22) - 1)
97 & ~OFPFW_NW_SRC_MASK & ~OFPFW_NW_DST_MASK)
98 | OFPFW_NW_SRC_ALL
99 | OFPFW_NW_DST_ALL;
100
101
102 }
103
104 public final static Wildcards FULL = new Wildcards(OFWildcardFlags.OFPFW_ALL_SANITIZED);
105 private static final int FULL_INT = FULL.getInt();
106
107 public final static Wildcards EXACT = new Wildcards(0);
108
109 // floodlight common case: matches on inport + l2
110 public final static int INT_INPORT_L2_MATCH = 0x3820e0;
111 public final static Wildcards INPORT_L2_MATCH = new Wildcards(
112 INT_INPORT_L2_MATCH);
113
114 /**
115 * enum type for the binary flags that can be set in the wildcards field of
116 * an OFWildcardFlags. Replaces the unwieldy c-ish int constants in OFWildcardFlags.
117 */
118 public static enum Flag {
119 IN_PORT(OFWildcardFlags.OFPFW_IN_PORT), /* Switch input port. */
120 DL_VLAN(OFWildcardFlags.OFPFW_DL_VLAN), /* VLAN id. */
121 DL_SRC(OFWildcardFlags.OFPFW_DL_SRC), /* Ethernet source address. */
122 DL_DST(OFWildcardFlags.OFPFW_DL_DST), /* Ethernet destination addr */
123 DL_TYPE(OFWildcardFlags.OFPFW_DL_TYPE), /* Ethernet frame type. */
124 NW_PROTO(OFWildcardFlags.OFPFW_NW_PROTO), /* IP protocol. */
125 TP_SRC(OFWildcardFlags.OFPFW_TP_SRC), /* TCP/UDP source port. */
126 TP_DST(OFWildcardFlags.OFPFW_TP_DST), /* TCP/UDP destination port. */
127 DL_VLAN_PCP(OFWildcardFlags.OFPFW_DL_VLAN_PCP), /* VLAN priority. */
128 NW_SRC(-1) { /*
129 * virtual NW_SRC flag => translates to the strange 6 bits
130 * in the header
131 */
132 @Override
133 boolean isBolean() {
134 return false;
135 }
136
137 @Override
138 int getInt(int flags) {
139 return ((flags & OFWildcardFlags.OFPFW_NW_SRC_MASK) >> OFWildcardFlags.OFPFW_NW_SRC_SHIFT);
140 }
141
142 @Override
143 int setInt(int flags, int srcMask) {
144 return (flags & ~OFWildcardFlags.OFPFW_NW_SRC_MASK) | (srcMask << OFWildcardFlags.OFPFW_NW_SRC_SHIFT);
145 }
146
147 @Override
148 int wildcard(int flags) {
149 return flags & ~OFWildcardFlags.OFPFW_NW_SRC_MASK;
150 }
151
152 @Override
153 int matchOn(int flags) {
154 return flags | OFWildcardFlags.OFPFW_NW_SRC_ALL;
155 }
156
157 @Override
158 boolean isPartiallyOn(int flags) {
159 int intValue = getInt(flags);
160 return intValue > 0 && intValue < 32;
161 }
162
163 @Override
164 boolean isFullyOn(int flags) {
165 return getInt(flags) >= 32;
166 }
167
168 },
169 NW_DST(-1) { /*
170 * virtual NW_SRC flag => translates to the strange 6 bits
171 * in the header
172 */
173 @Override
174 boolean isBolean() {
175 return false;
176 }
177
178 @Override
179 int getInt(int flags) {
180 return ((flags & OFWildcardFlags.OFPFW_NW_DST_MASK) >> OFWildcardFlags.OFPFW_NW_DST_SHIFT);
181 }
182
183 @Override
184 int setInt(int flags, int srcMask) {
185 return (flags & ~OFWildcardFlags.OFPFW_NW_DST_MASK) | (srcMask << OFWildcardFlags.OFPFW_NW_DST_SHIFT);
186 }
187
188 @Override
189 int wildcard(int flags) {
190 return flags & ~OFWildcardFlags.OFPFW_NW_DST_MASK;
191 }
192
193 @Override
194 int matchOn(int flags) {
195 return flags | OFWildcardFlags.OFPFW_NW_DST_ALL;
196 }
197
198 @Override
199 boolean isFullyOn(int flags) {
200 return getInt(flags) >= 32;
201 }
202 },
203 NW_TOS(OFWildcardFlags.OFPFW_NW_TOS); /* IP ToS (DSCP field, 6 bits). */
204
205 final int bitPosition;
206
207 Flag(int bitPosition) {
208 this.bitPosition = bitPosition;
209 }
210
211 /**
212 * @return a modified OF-1.0 flags field with this flag cleared (match
213 * on this field)
214 */
215 int matchOn(int flags) {
216 return flags & ~this.bitPosition;
217 }
218
219 /**
220 * @return a modified OF-1.0 flags field with this flag set (wildcard
221 * this field)
222 */
223 int wildcard(int flags) {
224 return flags | this.bitPosition;
225 }
226
227 /**
228 * @return true iff this is a true boolean flag that can either be off
229 * or on.True in OF-1.0 for all fields except NW_SRC and NW_DST
230 */
231 boolean isBolean() {
232 return false;
233 }
234
235 /**
236 * @return true iff this wildcard field is currently 'partially on'.
237 * Always false for true Boolean Flags. Can be true in OF-1.0
238 * for NW_SRC, NW_DST.
239 */
240 boolean isPartiallyOn(int flags) {
241 return false;
242 }
243
244 /**
245 * @return true iff this wildcard field currently fully on (fully
246 * wildcarded). Equivalent to the boolean flag being set in the
247 * bitmask for bit flags, and to the wildcarded bit length set
248 * to >=32 for NW_SRC and NW_DST
249 * @param flags
250 * @return
251 */
252 boolean isFullyOn(int flags) {
253 return (flags & this.bitPosition) != 0;
254 }
255
256 /**
257 * set the integer representation of this flag. only for NW_SRC and
258 * NW_DST
259 */
260 int setInt(int flags, int srcMask) {
261 throw new UnsupportedOperationException();
262 }
263
264 /**
265 * set the integer representation of this flag. only for NW_SRC and
266 * NW_DST
267 */
268 int getInt(int flags) {
269 throw new UnsupportedOperationException();
270 }
271
272
273 }
274
275 private final int flags;
276
277 /** private constructor. use Wildcard.of() instead */
278 private Wildcards(int flags) {
279 this.flags = flags;
280 }
281
282 /**
283 * return a wildcard object matching the given int flags. May reuse / cache
284 * frequently used wildcard instances. Don't rely on it though (use equals
285 * not ==).
286 *
287 * @param flags
288 * @return
289 */
290 public static Wildcards of(int paramFlags) {
291 int flags = paramFlags; //sanitizeInt(paramFlags);
292 switch(flags) {
293 case 0x0000:
294 return EXACT;
295 case OFWildcardFlags.OFPFW_ALL_SANITIZED:
296 return FULL;
297 case INT_INPORT_L2_MATCH:
298 return INPORT_L2_MATCH;
299 default:
300 return new Wildcards(flags);
301 }
302 }
303
304 /** convience method return a wildcard for exactly one set flag */
305 public static Wildcards of(Wildcards.Flag setFlag) {
306 return Wildcards.of(setFlag.wildcard(0));
307 }
308
309 /** convience method return a wildcard for exactly two set flags */
310 public static Wildcards of(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
311 return Wildcards.of(setFlag.wildcard(setFlag2.wildcard(0)));
312 }
313
314 /** convience method return a wildcard for an arbitrary number of set flags */
315 public static Wildcards of(Wildcards.Flag... setFlags) {
316 int flags = 0;
317 for (Wildcards.Flag flag : setFlags)
318 flags = flag.wildcard(0);
319 return Wildcards.of(flags);
320 }
321
322 /** convience method return a wildcards for ofmatches that match on one flag */
323 public static Wildcards ofMatches(Wildcards.Flag setFlag) {
324 return Wildcards.of(setFlag.matchOn(FULL_INT));
325 }
326
327 /**
328 * convience method return a wildcard for for an ofmatch that match on two
329 * flags
330 */
331 public static Wildcards ofMatches(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
332 return Wildcards.of(setFlag.matchOn(setFlag2.matchOn(FULL_INT)));
333 }
334
335 /**
336 * convience method return a wildcard for an ofmatch that amtch on an
337 * arbitrary number of set flags
338 */
339 public static Wildcards ofMatches(Wildcards.Flag... setFlags) {
340 int flags = FULL_INT;
341 for (Wildcards.Flag flag : setFlags)
342 flags = flag.matchOn(flags);
343 return Wildcards.of(flags);
344 }
345
346 public static Wildcards ofMatches(Set<Wildcards.Flag> wSet) {
347 int flags = FULL_INT;
348 for (Wildcards.Flag flag : wSet)
349 flags = flag.matchOn(flags);
350 return Wildcards.of(flags);
351 }
352
353 /**
354 * return a Wildcards object that has the given flags set
355 * <p>
356 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
357 * unmodified. </b>
358 */
359 public Wildcards wildcard(Wildcards.Flag flag) {
360 int flags = flag.wildcard(this.flags);
361 if (flags == this.flags)
362 return this;
363 else
364 return new Wildcards(flags);
365 }
366
367 /**
368 * return a Wildcards object that has the given flags set
369 * <p>
370 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
371 * unmodified. </b>
372 */
373 public Wildcards wildcard(Wildcards.Flag flag, Wildcards.Flag flag2) {
374 int flags = flag.wildcard(flag2.wildcard(this.flags));
375 if (flags == this.flags)
376 return this;
377 else
378 return new Wildcards(flags);
379 }
380
381 /**
382 * return a Wildcards object that has the given flags wildcarded
383 * <p>
384 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
385 * unmodified. </b>
386 */
387 public Wildcards wildcard(Wildcards.Flag... setFlags) {
388 int flags = this.flags;
389 for (Wildcards.Flag flag : setFlags)
390 flags = flag.wildcard(flags);
391 if (flags == this.flags)
392 return this;
393 else
394 return new Wildcards(flags);
395 }
396
397 /**
398 * return a Wildcards object that matches on exactly the given flag
399 * <p>
400 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
401 * unmodified. </b>
402 */
403 public Wildcards matchOn(Wildcards.Flag flag) {
404 int flags = flag.matchOn(this.flags);
405 if (flags == this.flags)
406 return this;
407 else
408 return new Wildcards(flags);
409 }
410
411 /**
412 * return a Wildcards object that matches on exactly the given flags
413 * <p>
414 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
415 * unmodified. </b>
416 */
417 public Wildcards matchOn(Wildcards.Flag flag, Wildcards.Flag flag2) {
418 int flags = flag.matchOn(flag2.matchOn(this.flags));
419 if (flags == this.flags)
420 return this;
421 else
422 return new Wildcards(flags);
423 }
424
425 /**
426 * return a Wildcards object that matches on exactly the given flags
427 * <p>
428 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
429 * unmodified. </b>
430 */
431 public Wildcards matchOn(Wildcards.Flag... setFlags) {
432 int flags = this.flags;
433 for (Wildcards.Flag flag : setFlags)
434 flags = flag.matchOn(flags);
435 if (flags == this.flags)
436 return this;
437 else
438 return new Wildcards(flags);
439 }
440
441 /**
442 * return the nw src mask in normal CIDR style, e.g., 8 means x.x.x.x/8
443 * means 8 bits wildcarded
444 */
445 public int getNwSrcMask() {
446 return Math.max(0, 32 - Flag.NW_SRC.getInt(flags));
447 }
448
449 /**
450 * return the nw dst mask in normal CIDR style, e.g., 8 means x.x.x.x/8
451 * means 8 bits wildcarded
452 */
453 public int getNwDstMask() {
454 return Math.max(0, 32 - Flag.NW_DST.getInt(flags));
455 }
456
457 /**
458 * return a Wildcard object that has the given nwSrcCidrMask set.
459 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
460 * unmodified. </b>
461 *
462 * @param srcCidrMask
463 * source mask to set in <b>normal CIDR notation</b>, i.e., 8
464 * means x.x.x.x/8
465 * @return a modified object
466 */
467 public Wildcards withNwSrcMask(int srcCidrMask) {
468 int flags = Flag.NW_SRC.setInt(this.flags, Math.max(0, 32 - srcCidrMask));
469 if (flags == this.flags)
470 return this;
471 else
472 return new Wildcards(flags);
473 }
474
475 /**
476 * return a Wildcard object that has the given nwDstCidrMask set.
477 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
478 * unmodified. </b>
479 *
480 * @param dstCidrMask
481 * dest mask to set in <b>normal CIDR notation</b>, i.e., 8 means
482 * x.x.x.x/8
483 * @return a modified object
484 */
485 public Wildcards withNwDstMask(int dstCidrMask) {
486 int flags = Flag.NW_DST.setInt(this.flags, Math.max(0, 32 - dstCidrMask));
487 if (flags == this.flags)
488 return this;
489 else
490 return new Wildcards(flags);
491 }
492
493 /**
494 * return a Wildcard object that is inverted to this wildcard object.
495 * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
496 * unmodified. </b>
497 * @return a modified object
498 */
499 public Wildcards inverted() {
500 return Wildcards.of(flags ^ OFWildcardFlags.OFPFW_ALL_SANITIZED);
501 }
502
503 public boolean isWildcarded(Flag flag) {
504 return flag.isFullyOn(flags);
505 }
506
507 /**
508 * return all wildcard flags that are fully wildcarded as an EnumSet. Do not
509 * modify. Note: some flags (like NW_SRC and NW_DST) that are partially
510 * wildcarded are not returned in this set.
511 *
512 * @return the EnumSet of wildcards
513 */
514 public EnumSet<Wildcards.Flag> getWildcardedFlags() {
515 EnumSet<Wildcards.Flag> res = EnumSet.noneOf(Wildcards.Flag.class);
516 for (Wildcards.Flag flag : Flag.values()) {
517 if (flag.isFullyOn(flags)) {
518 res.add(flag);
519 }
520 }
521 return res;
522 }
523
524 /** return the OpenFlow 'wire' integer representation of these wildcards */
525 public int getInt() {
526 return flags;
527 }
528
529 /**
530 * return the OpenFlow 'wire' integer representation of these wildcards.
531 * Sanitize nw_src and nw_dst to be max. 32 (values > 32 are technically
532 * possible, but don't make semantic sense)
533 */
534 public static int sanitizeInt(int flags) {
535 if (((flags & OFWildcardFlags.OFPFW_NW_SRC_MASK) >> OFWildcardFlags.OFPFW_NW_SRC_SHIFT) > 32) {
536 flags = (flags & ~OFWildcardFlags.OFPFW_NW_SRC_MASK) | OFWildcardFlags.OFPFW_NW_SRC_ALL;
537 }
538 if (((flags & OFWildcardFlags.OFPFW_NW_DST_MASK) >> OFWildcardFlags.OFPFW_NW_DST_SHIFT) > 32) {
539 flags = (flags & ~OFWildcardFlags.OFPFW_NW_DST_MASK) | OFWildcardFlags.OFPFW_NW_DST_ALL;
540 }
541 return flags;
542 }
543
544 /**
545 * is this a wildcard set that has all flags set + and full (/0) nw_src and
546 * nw_dst wildcarding ?
547 */
548 public boolean isFull() {
549 return flags == OFWildcardFlags.OFPFW_ALL || flags == OFWildcardFlags.OFPFW_ALL_SANITIZED;
550 }
551
552 /** is this a wildcard of an exact match */
553 public boolean isExact() {
554 return flags == 0;
555 }
556
557 @Override
558 public int hashCode() {
559 final int prime = 31;
560 int result = 1;
561 result = prime * result + flags;
562 return result;
563 }
564
565 @Override
566 public boolean equals(Object obj) {
567 if (this == obj)
568 return true;
569 if (obj == null)
570 return false;
571 if (getClass() != obj.getClass())
572 return false;
573 Wildcards other = (Wildcards) obj;
574 if (flags != other.flags)
575 return false;
576 return true;
577 }
578
579 private final static Joiner pipeJoiner = Joiner.on("|");
580
581 @Override
582 public String toString() {
583 List<String> res = new ArrayList<String>();
584 for (Wildcards.Flag flag : Flag.values()) {
585 if (flag.isFullyOn(flags)) {
586 res.add(flag.name().toLowerCase());
587 }
588 }
589
590 if (Flag.NW_SRC.isPartiallyOn(flags)) {
591 res.add("nw_src(/" + getNwSrcMask() + ")");
592 }
593
594 if (Flag.NW_DST.isPartiallyOn(flags)) {
595 res.add("nw_dst(/" + getNwDstMask() + ")");
596 }
597
598 return pipeJoiner.join(res);
599 }
600
601 private final static Joiner commaJoiner = Joiner.on(", ");
602
603 /** a Java expression that constructs 'this' wildcards set */
604 public String toJava() {
605 if(isFull()) {
606 return "Wildcards.FULL";
607 } else if (isExact()){
608 return "Wildcards.EXACT";
609 }
610
611 StringBuilder b = new StringBuilder();
612
613 EnumSet<Flag> myFlags = getWildcardedFlags();
614 if (myFlags.size() < 3) {
615 // default to start with empty
616 b.append("Wildcards.of("
617 + commaJoiner.join(prefix("Flag.", myFlags.iterator())) + ")");
618 } else {
619 // too many - start with full
620
621 EnumSet<Flag> invFlags = inverted().getWildcardedFlags();
622 b.append("Wildcards.ofMatches("
623 + commaJoiner.join(prefix("Flag.", invFlags.iterator())) + ")");
624 }
625 if (Flag.NW_SRC.isPartiallyOn(flags)) {
626 b.append(".setNwSrcMask(" + getNwSrcMask() + ")");
627 }
628 if (Flag.NW_DST.isPartiallyOn(flags)) {
629 b.append(".setNwDstMask(" + getNwDstMask() + ")");
630 }
631 return b.toString();
632 }
633
634 private Iterator<String> prefix(final String prefix, final Iterator<?> i) {
635 return new Iterator<String>() {
636
637 @Override
638 public boolean hasNext() {
639 return i.hasNext();
640 }
641
642 @Override
643 public String next() {
644 Object next = i.next();
645 return next == null ? null : prefix + next.toString();
646 }
647
648 @Override
649 public void remove() {
650 i.remove();
651 }
652 };
653 }
654
655
656}