blob: 49c8c4e09eb8620023b4b07e123b396a51cedc3b [file] [log] [blame]
Yotam Harchola11f38b2013-09-26 15:38:17 -07001package org.projectfloodlight.openflow.types;
2
Yotam Harchola11f38b2013-09-26 15:38:17 -07003
Andreas Wundsam28c99752013-10-22 16:51:25 -07004/** User-facing object representing a bitmap of ports that can be matched on.
5 * This is implemented by the custom BSN OXM type of_oxm_bsn_in_ports_182.
6 *
7 * You can call set() on the builder for all the Ports you want to match on
8 * and unset to exclude the port.
9 *
10 * <b>Implementation note:</b> to comply with the matching semantics of OXM (which is a logical "AND" not "OR")
11 * the underlying match uses a data format which is very unintuitive. The value is always
12 * 0, and the mask has the bits set for the ports that should <b>NOT</b> be included in the
13 * range.
14 *
15 * For the curious: We transformed the bitmap (a logical OR) problem into a logical
16 * AND NOT problem.
17 *
18 * We logically mean: Inport is 1 OR 3
19 * We technically say: Inport IS NOT 2 AND IS NOT 4 AND IS NOT 5 AND IS NOT ....
20 * The second term cannot be represented in OXM, the second can.
21 *
22 * That said, all that craziness is hidden from the user of this object.
23 * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
24 */
Andreas Wundsam9667a162013-10-21 12:58:16 -070025public class OFPortBitMap extends Masked<OFBitMask128> {
Yotam Harchola11f38b2013-09-26 15:38:17 -070026
Andreas Wundsam9667a162013-10-21 12:58:16 -070027 private OFPortBitMap(OFBitMask128 mask) {
Yotam Harchol2c535582013-10-01 15:50:20 -070028 super(OFBitMask128.NONE, mask);
Yotam Harchola11f38b2013-09-26 15:38:17 -070029 }
30
Andreas Wundsam28c99752013-10-22 16:51:25 -070031 /** @return whether or not the given port is logically included in the
32 * match, i.e., whether a packet from in-port <emph>port</emph> be matched by
33 * this OXM.
34 */
Yotam Harchola11f38b2013-09-26 15:38:17 -070035 public boolean isOn(OFPort port) {
Andreas Wundsam28c99752013-10-22 16:51:25 -070036 // see the implementation note above about the logical inversion of the mask
Yotam Harchol2c535582013-10-01 15:50:20 -070037 return !(this.mask.isOn(port.getPortNumber()));
Yotam Harchola11f38b2013-09-26 15:38:17 -070038 }
39
Andreas Wundsam9667a162013-10-21 12:58:16 -070040 public static OFPortBitMap ofPorts(OFPort... ports) {
Yotam Harchola11f38b2013-09-26 15:38:17 -070041 Builder builder = new Builder();
42 for (OFPort port: ports) {
43 builder.set(port);
44 }
45 return builder.build();
46 }
47
48 @Override
Yotam Harchol595c6442013-09-27 16:29:08 -070049 public boolean equals(Object obj) {
Andreas Wundsam9667a162013-10-21 12:58:16 -070050 if (!(obj instanceof OFPortBitMap))
Yotam Harchol595c6442013-09-27 16:29:08 -070051 return false;
Andreas Wundsam9667a162013-10-21 12:58:16 -070052 OFPortBitMap other = (OFPortBitMap)obj;
Yotam Harchol595c6442013-09-27 16:29:08 -070053 return (other.value.equals(this.value) && other.mask.equals(this.mask));
54 }
55
56 @Override
57 public int hashCode() {
58 return 619 * mask.hashCode() + 257 * value.hashCode();
Yotam Harchola11f38b2013-09-26 15:38:17 -070059 }
60
61 public static class Builder {
Yotam Harchol2c535582013-10-01 15:50:20 -070062 private long raw1 = -1, raw2 = -1;
Yotam Harchola11f38b2013-09-26 15:38:17 -070063
64 public Builder() {
65
66 }
67
Andreas Wundsam28c99752013-10-22 16:51:25 -070068 /** @return whether or not the given port is logically included in the
69 * match, i.e., whether a packet from in-port <emph>port</emph> be matched by
70 * this OXM.
71 */
Yotam Harchola11f38b2013-09-26 15:38:17 -070072 public boolean isOn(OFPort port) {
Andreas Wundsam28c99752013-10-22 16:51:25 -070073 // see the implementation note above about the logical inversion of the mask
Yotam Harchol2c535582013-10-01 15:50:20 -070074 return !(OFBitMask128.isBitOn(raw1, raw2, port.getPortNumber()));
Yotam Harchola11f38b2013-09-26 15:38:17 -070075 }
76
Andreas Wundsam28c99752013-10-22 16:51:25 -070077 /** remove this port from the match, i.e., packets from this in-port
78 * will NOT be matched.
79 */
Yotam Harchol2c535582013-10-01 15:50:20 -070080 public Builder unset(OFPort port) {
Andreas Wundsam28c99752013-10-22 16:51:25 -070081 // see the implementation note above about the logical inversion of the mask
Yotam Harchola11f38b2013-09-26 15:38:17 -070082 int bit = port.getPortNumber();
Andreas Wundsam28c99752013-10-22 16:51:25 -070083 if (bit < 0 || bit > 127)
Yotam Harchola11f38b2013-09-26 15:38:17 -070084 throw new IndexOutOfBoundsException("Port number is out of bounds");
Andreas Wundsam28c99752013-10-22 16:51:25 -070085 else if (bit == 127)
86 // the highest order bit in the bitmask is reserved. The switch will
87 // set that bit for all ports >= 127. The reason is that we don't want
88 // the OFPortMap to match all ports out of its range (i.e., a packet
89 // coming in on port 181 would match *any* OFPortMap).
90 throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
91 else if (bit < 64) {
Yotam Harchol595c6442013-09-27 16:29:08 -070092 raw2 |= ((long)1 << bit);
Yotam Harchola11f38b2013-09-26 15:38:17 -070093 } else {
Yotam Harchol595c6442013-09-27 16:29:08 -070094 raw1 |= ((long)1 << (bit - 64));
Yotam Harchola11f38b2013-09-26 15:38:17 -070095 }
96 return this;
97 }
98
Andreas Wundsam28c99752013-10-22 16:51:25 -070099 /** add this port from the match, i.e., packets from this in-port
100 * will NOT be matched.
101 */
Yotam Harchol2c535582013-10-01 15:50:20 -0700102 public Builder set(OFPort port) {
Andreas Wundsam28c99752013-10-22 16:51:25 -0700103 // see the implementation note above about the logical inversion of the mask
Yotam Harchola11f38b2013-09-26 15:38:17 -0700104 int bit = port.getPortNumber();
Andreas Wundsam28c99752013-10-22 16:51:25 -0700105 if (bit < 0 || bit > 127)
Yotam Harchola11f38b2013-09-26 15:38:17 -0700106 throw new IndexOutOfBoundsException("Port number is out of bounds");
Andreas Wundsam28c99752013-10-22 16:51:25 -0700107 else if (bit == 127)
108 // the highest order bit in the bitmask is reserved. The switch will
109 // set that bit for all ports >= 127. The reason is that we don't want
110 // the OFPortMap to match all ports out of its range (i.e., a packet
111 // coming in on port 181 would match *any* OFPortMap).
112 throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
113 else if (bit < 64) {
Yotam Harchol595c6442013-09-27 16:29:08 -0700114 raw2 &= ~((long)1 << bit);
Yotam Harchola11f38b2013-09-26 15:38:17 -0700115 } else {
Yotam Harchol595c6442013-09-27 16:29:08 -0700116 raw1 &= ~((long)1 << (bit - 64));
Yotam Harchola11f38b2013-09-26 15:38:17 -0700117 }
118 return this;
119 }
120
Andreas Wundsam9667a162013-10-21 12:58:16 -0700121 public OFPortBitMap build() {
122 return new OFPortBitMap(OFBitMask128.of(raw1, raw2));
Yotam Harchola11f38b2013-09-26 15:38:17 -0700123 }
124 }
125
126}