fbda8586ab25c106cf7991cab6c4f328bfd9712b
[controller.git] / third-party / openflowj_netty / src / main / java / org / openflow / protocol / Wildcards.java
1 /**
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
17 package org.openflow.protocol;
18
19 import java.util.ArrayList;
20 import java.util.EnumSet;
21 import java.util.Iterator;
22 import java.util.List;
23
24
25 /**
26  * a more user friendly representation of the wildcards bits in an OpenFlow
27  * match. The Wildcards object is
28  * <ul>
29  * <li>immutable (i.e., threadsafe)</li>
30  * <li>instance managed (don't instantiate it yourself), instead call "of"</li>
31  * <ul>
32  * <p>
33  * You can construct a Wildcard object from either its integer representation
34  * </p>
35  * <code>
36  *    Wildcard.of(0x3820e0);
37  *  </code>
38  * <p>
39  * Or start with either an empty or full wildcard, and select/unselect foo.
40  * </p>
41  * <code>
42  *  Wildcard w = Wildcards.NONE
43  *                .set(Flag.DL_SRC, Flag. DL_DST, Flag.DL_VLAN_PCP)
44  *                .setNwDstMask(8)
45  *                .setNwSrcMask(8);
46  *  </code>
47  * <p>
48  * <b>Remember:</b> Wildcards objects are immutable. set... operations have
49  * <b>NO EFFECT</b> on the current wildcard object. You HAVE to use the returned
50  * changed object.
51  * </p>
52  *
53  * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
54  */
55 public class Wildcards {
56
57     public final static Wildcards FULL = new Wildcards(OFMatch.OFPFW_ALL_SANITIZED);
58     private static final int FULL_INT = FULL.getInt();
59
60     public final static Wildcards EXACT = new Wildcards(0);
61
62     // floodlight common case: matches on inport + l2
63     public final static int INT_INPORT_L2_MATCH = 0x3820e0;
64     public final static Wildcards INPORT_L2_MATCH = new Wildcards(
65             INT_INPORT_L2_MATCH);
66
67     /**
68      * enum type for the binary flags that can be set in the wildcards field of
69      * an OFMatch. Replaces the unwieldy c-ish int constants in OFMatch.
70      */
71     public static enum Flag {
72         IN_PORT(OFMatch.OFPFW_IN_PORT),  /* Switch input port. */
73         DL_VLAN(OFMatch.OFPFW_DL_VLAN), /* VLAN id. */
74         DL_SRC(OFMatch.OFPFW_DL_SRC), /* Ethernet source address. */
75         DL_DST(OFMatch.OFPFW_DL_DST), /* Ethernet destination addr */
76         DL_TYPE(OFMatch.OFPFW_DL_TYPE), /* Ethernet frame type. */
77         NW_PROTO(OFMatch.OFPFW_NW_PROTO), /* IP protocol. */
78         TP_SRC(OFMatch.OFPFW_TP_SRC), /* TCP/UDP source port. */
79         TP_DST(OFMatch.OFPFW_TP_DST), /* TCP/UDP destination port. */
80         DL_VLAN_PCP(OFMatch.OFPFW_DL_VLAN_PCP), /* VLAN priority. */
81         NW_SRC(-1) { /*
82                       * virtual NW_SRC flag => translates to the strange 6 bits
83                       * in the header
84                       */
85             @Override
86             boolean isBolean() {
87                 return false;
88             }
89
90             @Override
91             int getInt(int flags) {
92                 return ((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT);
93             }
94
95             @Override
96             int setInt(int flags, int srcMask) {
97                 return (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | (srcMask << OFMatch.OFPFW_NW_SRC_SHIFT);
98             }
99
100             @Override
101             int wildcard(int flags) {
102                 return flags & ~OFMatch.OFPFW_NW_SRC_MASK;
103             }
104
105             @Override
106             int matchOn(int flags) {
107                 return flags | OFMatch.OFPFW_NW_SRC_ALL;
108             }
109
110             @Override
111             boolean isPartiallyOn(int flags) {
112                 int intValue = getInt(flags);
113                 return intValue > 0 && intValue < 32;
114             }
115
116             @Override
117             boolean isFullyOn(int flags) {
118                 return getInt(flags) >= 32;
119             }
120
121         },
122         NW_DST(-1) { /*
123                       * virtual NW_SRC flag => translates to the strange 6 bits
124                       * in the header
125                       */
126             @Override
127             boolean isBolean() {
128                 return false;
129             }
130
131             @Override
132             int getInt(int flags) {
133                 return ((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT);
134             }
135
136             @Override
137             int setInt(int flags, int srcMask) {
138                 return (flags & ~OFMatch.OFPFW_NW_DST_MASK) | (srcMask << OFMatch.OFPFW_NW_DST_SHIFT);
139             }
140
141             @Override
142             int wildcard(int flags) {
143                 return flags & ~OFMatch.OFPFW_NW_DST_MASK;
144             }
145
146             @Override
147             int matchOn(int flags) {
148                 return flags | OFMatch.OFPFW_NW_DST_ALL;
149             }
150
151             @Override
152             boolean isFullyOn(int flags) {
153                 return getInt(flags) >= 32;
154             }
155         },
156         NW_TOS(OFMatch.OFPFW_NW_TOS); /* IP ToS (DSCP field, 6 bits). */
157
158         final int bitPosition;
159
160         Flag(int bitPosition) {
161             this.bitPosition = bitPosition;
162         }
163
164         /**
165          * @return a modified OF-1.0 flags field with this flag cleared (match
166          *         on this field)
167          */
168         int matchOn(int flags) {
169             return flags & ~this.bitPosition;
170         }
171
172         /**
173          * @return a modified OF-1.0 flags field with this flag set (wildcard
174          *         this field)
175          */
176         int wildcard(int flags) {
177             return flags | this.bitPosition;
178         }
179
180         /**
181          * @return true iff this is a true boolean flag that can either be off
182          *         or on.True in OF-1.0 for all fields except NW_SRC and NW_DST
183          */
184         boolean isBolean() {
185             return false;
186         }
187
188         /**
189          * @return true iff this wildcard field is currently 'partially on'.
190          *         Always false for true Boolean Flags. Can be true in OF-1.0
191          *         for NW_SRC, NW_DST.
192          */
193         boolean isPartiallyOn(int flags) {
194             return false;
195         }
196
197         /**
198          * @return true iff this wildcard field currently fully on (fully
199          *         wildcarded). Equivalent to the boolean flag being set in the
200          *         bitmask for bit flags, and to the wildcarded bit length set
201          *         to >=32 for NW_SRC and NW_DST
202          * @param flags
203          * @return
204          */
205         boolean isFullyOn(int flags) {
206             return (flags & this.bitPosition) != 0;
207         }
208
209         /**
210          * set the integer representation of this flag. only for NW_SRC and
211          * NW_DST
212          */
213         int setInt(int flags, int srcMask) {
214             throw new UnsupportedOperationException();
215         }
216
217         /**
218          * set the integer representation of this flag. only for NW_SRC and
219          * NW_DST
220          */
221         int getInt(int flags) {
222             throw new UnsupportedOperationException();
223         }
224
225
226     }
227
228     private final int flags;
229
230     /** private constructor. use Wildcard.of() instead */
231     private Wildcards(int flags) {
232         this.flags = flags;
233     }
234
235     /**
236      * return a wildcard object matching the given int flags. May reuse / cache
237      * frequently used wildcard instances. Don't rely on it though (use equals
238      * not ==).
239      *
240      * @param flags
241      * @return
242      */
243     public static Wildcards of(int paramFlags) {
244         int flags = sanitizeInt(paramFlags);
245         switch(flags) {
246             case 0x0000:
247                 return EXACT;
248             case OFMatch.OFPFW_ALL_SANITIZED:
249                 return FULL;
250             case INT_INPORT_L2_MATCH:
251                 return INPORT_L2_MATCH;
252             default:
253                 return new Wildcards(flags);
254         }
255     }
256
257     /** convience method return a wildcard for exactly one set flag */
258     public static Wildcards of(Wildcards.Flag setFlag) {
259         return Wildcards.of(setFlag.wildcard(0));
260     }
261
262     /** convience method return a wildcard for exactly two set flags */
263     public static Wildcards of(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
264         return Wildcards.of(setFlag.wildcard(setFlag2.wildcard(0)));
265     }
266
267     /** convience method return a wildcard for an arbitrary number of set flags */
268     public static Wildcards of(Wildcards.Flag... setFlags) {
269         int flags = 0;
270         for (Wildcards.Flag flag : setFlags)
271             flags = flag.wildcard(0);
272         return Wildcards.of(flags);
273     }
274
275     /** convience method return a wildcards for ofmatches that match on one flag */
276     public static Wildcards ofMatches(Wildcards.Flag setFlag) {
277         return Wildcards.of(setFlag.matchOn(FULL_INT));
278     }
279
280     /**
281      * convience method return a wildcard for for an ofmatch that match on two
282      * flags
283      */
284     public static Wildcards ofMatches(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
285         return Wildcards.of(setFlag.matchOn(setFlag2.matchOn(FULL_INT)));
286     }
287
288     /**
289      * convience method return a wildcard for an ofmatch that amtch on an
290      * arbitrary number of set flags
291      */
292     public static Wildcards ofMatches(Wildcards.Flag... setFlags) {
293         int flags = FULL_INT;
294         for (Wildcards.Flag flag : setFlags)
295            flags = flag.matchOn(flags);
296         return Wildcards.of(flags);
297     }
298
299     /**
300      * return a Wildcards object that has the given flags set
301      * <p>
302      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
303      * unmodified. </b>
304      */
305     public Wildcards wildcard(Wildcards.Flag flag) {
306         int flags = flag.wildcard(this.flags);
307         if (flags == this.flags)
308             return this;
309         else
310             return new Wildcards(flags);
311     }
312
313     /**
314      * return a Wildcards object that has the given flags set
315      * <p>
316      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
317      * unmodified. </b>
318      */
319     public Wildcards wildcard(Wildcards.Flag flag, Wildcards.Flag flag2) {
320         int flags = flag.wildcard(flag2.wildcard(this.flags));
321         if (flags == this.flags)
322             return this;
323         else
324             return new Wildcards(flags);
325     }
326
327     /**
328      * return a Wildcards object that has the given flags wildcarded
329      * <p>
330      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
331      * unmodified. </b>
332      */
333     public Wildcards wildcard(Wildcards.Flag... setFlags) {
334         int flags = this.flags;
335         for (Wildcards.Flag flag : setFlags)
336             flags = flag.wildcard(flags);
337         if (flags == this.flags)
338             return this;
339         else
340             return new Wildcards(flags);
341     }
342
343     /**
344      * return a Wildcards object that matches on exactly the given flag
345      * <p>
346      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
347      * unmodified. </b>
348      */
349     public Wildcards matchOn(Wildcards.Flag flag) {
350         int flags = flag.matchOn(this.flags);
351         if (flags == this.flags)
352             return this;
353         else
354             return new Wildcards(flags);
355     }
356
357     /**
358      * return a Wildcards object that matches on exactly the given flags
359      * <p>
360      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
361      * unmodified. </b>
362      */
363     public Wildcards matchOn(Wildcards.Flag flag, Wildcards.Flag flag2) {
364         int flags = flag.matchOn(flag2.matchOn(this.flags));
365         if (flags == this.flags)
366             return this;
367         else
368             return new Wildcards(flags);
369     }
370
371     /**
372      * return a Wildcards object that matches on exactly the given flags
373      * <p>
374      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
375      * unmodified. </b>
376      */
377     public Wildcards matchOn(Wildcards.Flag... setFlags) {
378         int flags = this.flags;
379         for (Wildcards.Flag flag : setFlags)
380             flags = flag.matchOn(flags);
381         if (flags == this.flags)
382             return this;
383         else
384             return new Wildcards(flags);
385     }
386
387     /**
388      * return the nw src mask in normal CIDR style, e.g., 8 means x.x.x.x/8
389      * means 8 bits wildcarded
390      */
391     public int getNwSrcMask() {
392         return Math.max(0, 32 - Flag.NW_SRC.getInt(flags));
393     }
394
395     /**
396      * return the nw dst mask in normal CIDR style, e.g., 8 means x.x.x.x/8
397      * means 8 bits wildcarded
398      */
399     public int getNwDstMask() {
400         return Math.max(0, 32 - Flag.NW_DST.getInt(flags));
401     }
402
403     /**
404      * return a Wildcard object that has the given nwSrcCidrMask set.
405      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
406      * unmodified. </b>
407      *
408      * @param srcCidrMask
409      *            source mask to set in <b>normal CIDR notation</b>, i.e., 8
410      *            means x.x.x.x/8
411      * @return a modified object
412      */
413     public Wildcards withNwSrcMask(int srcCidrMask) {
414         int flags = Flag.NW_SRC.setInt(this.flags, Math.max(0, 32 - srcCidrMask));
415         if (flags == this.flags)
416             return this;
417         else
418             return new Wildcards(flags);
419     }
420
421     /**
422      * return a Wildcard object that has the given nwDstCidrMask set.
423      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
424      * unmodified. </b>
425      *
426      * @param dstCidrMask
427      *            dest mask to set in <b>normal CIDR notation</b>, i.e., 8 means
428      *            x.x.x.x/8
429      * @return a modified object
430      */
431     public Wildcards withNwDstMask(int dstCidrMask) {
432         int flags = Flag.NW_DST.setInt(this.flags, Math.max(0, 32 - dstCidrMask));
433         if (flags == this.flags)
434             return this;
435         else
436             return new Wildcards(flags);
437     }
438
439     /**
440      * return a Wildcard object that is inverted to this wildcard object.
441      * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
442      * unmodified. </b>
443      * @return a modified object
444      */
445     public Wildcards inverted() {
446         return Wildcards.of(flags ^ OFMatch.OFPFW_ALL_SANITIZED);
447     }
448
449     public boolean isWildcarded(Flag flag) {
450         return flag.isFullyOn(flags);
451     }
452
453     /**
454      * return all wildcard flags that are fully wildcarded as an EnumSet. Do not
455      * modify. Note: some flags (like NW_SRC and NW_DST) that are partially
456      * wildcarded are not returned in this set.
457      *
458      * @return the EnumSet of wildcards
459      */
460     public EnumSet<Wildcards.Flag> getWildcardedFlags() {
461         EnumSet<Wildcards.Flag> res = EnumSet.noneOf(Wildcards.Flag.class);
462         for (Wildcards.Flag flag : Flag.values()) {
463             if (flag.isFullyOn(flags)) {
464                 res.add(flag);
465             }
466         }
467         return res;
468     }
469
470     /** return the OpenFlow 'wire' integer representation of these wildcards */
471     public int getInt() {
472         return flags;
473     }
474
475     /**
476      * return the OpenFlow 'wire' integer representation of these wildcards.
477      * Sanitize nw_src and nw_dst to be max. 32 (values > 32 are technically
478      * possible, but don't make semantic sense)
479      */
480     public static int sanitizeInt(int flags) {
481         if (((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT) > 32) {
482             flags = (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | OFMatch.OFPFW_NW_SRC_ALL;
483         }
484         if (((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT) > 32) {
485             flags = (flags & ~OFMatch.OFPFW_NW_DST_MASK) | OFMatch.OFPFW_NW_DST_ALL;
486         }
487         return flags;
488     }
489
490     /**
491      * is this a wildcard set that has all flags set + and full (/0) nw_src and
492      * nw_dst wildcarding ?
493      */
494     public boolean isFull() {
495         return flags == OFMatch.OFPFW_ALL || flags == OFMatch.OFPFW_ALL_SANITIZED;
496     }
497
498     /** is this a wildcard of an exact match */
499     public boolean isExact() {
500         return flags == 0;
501     }
502
503     @Override
504     public int hashCode() {
505         final int prime = 31;
506         int result = 1;
507         result = prime * result + flags;
508         return result;
509     }
510
511     @Override
512     public boolean equals(Object obj) {
513         if (this == obj)
514             return true;
515         if (obj == null)
516             return false;
517         if (getClass() != obj.getClass())
518             return false;
519         Wildcards other = (Wildcards) obj;
520         if (flags != other.flags)
521             return false;
522         return true;
523     }
524
525
526
527 }