Merge into master from pull request #401:
Add 512-bit variation of OFPortBigMap (https://github.com/floodlight/loxigen/pull/401)
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap512.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap512.java
new file mode 100644
index 0000000..c85c750
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap512.java
@@ -0,0 +1,192 @@
+package org.projectfloodlight.openflow.types;
+
+import java.util.ArrayList;
+
+import javax.annotation.concurrent.Immutable;
+
+
+/** User-facing object representing a bitmap of ports that can be matched on.
+ * This is implemented by the custom BSN OXM type of_oxm_bsn_in_ports_512.
+ *
+ * You can call set() on the builder for all the Ports you want to match on
+ * and unset to exclude the port.
+ *
+ * <b>Implementation note:</b> to comply with the matching semantics of OXM (which is a logical "AND" not "OR")
+ * the underlying match uses a data format which is very unintuitive. The value is always
+ * 0, and the mask has the bits set for the ports that should <b>NOT</b> be included in the
+ * range.
+ *
+ * For the curious: We transformed the bitmap (a logical OR) problem into a logical
+ * AND NOT problem.
+ *
+ * We logically mean: Inport is 1 OR 3
+ * We technically say: Inport IS NOT 2 AND IS NOT 4 AND IS NOT 5 AND IS NOT ....
+ * The second term cannot be represented in OXM, the second can.
+ *
+ * That said, all that craziness is hidden from the user of this object.
+ *
+ * <h2>Usage</h2>
+ * OFPortBitmap is meant to be used with MatchField <tt>BSN_IN_PORTS_512</tt> in place
+ * of the raw type Masked<OFBitMask512>.
+ *
+ * <h3>Example:</h3>:
+ * <pre>
+ * OFPortBitMap portBitMap;
+ * Match.Builder matchBuilder;
+ * // initialize
+ * matchBuilder.setMasked(MatchField.BSN_IN_PORTS_512, portBitmap);
+ * </pre>
+ *
+ * @author Andreas Wundsam {@literal <}andreas.wundsam@bigswitch.com{@literal >}
+ */
+@Immutable
+public class OFPortBitMap512 extends Masked<OFBitMask512> {
+
+ private OFPortBitMap512(OFBitMask512 mask) {
+ super(OFBitMask512.NONE, mask);
+ }
+
+ /** @return whether or not the given port is logically included in the
+ * match, i.e., whether a packet from in-port <em>port</em> be matched by
+ * this OXM.
+ */
+ public boolean isOn(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ return !(this.mask.isOn(port.getPortNumber()));
+ }
+
+ public static OFPortBitMap512 ofPorts(OFPort... ports) {
+ Builder builder = new Builder();
+ for (OFPort port: ports) {
+ builder.set(port);
+ }
+ return builder.build();
+ }
+
+ /** @return an OFPortBitmap based on the 'mask' part of an OFBitMask512, as, e.g., returned
+ * by the switch.
+ **/
+ public static OFPortBitMap512 of(OFBitMask512 mask) {
+ return new OFPortBitMap512(mask);
+ }
+
+ /** @return iterating over all ports that are logically included in the
+ * match, i.e., whether a packet from in-port <em>port</em> be matched by
+ * this OXM.
+ */
+ public Iterable<OFPort> getOnPorts() {
+ ArrayList<OFPort> ports = new ArrayList<>();
+ for(int i=0; i < 511; i++) {
+ if(!(this.mask.isOn(i))) {
+ ports.add(OFPort.of(i));
+ }
+ }
+ return ports;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof OFPortBitMap512))
+ return false;
+ OFPortBitMap512 other = (OFPortBitMap512)obj;
+ return (other.value.equals(this.value) && other.mask.equals(this.mask));
+ }
+
+ @Override
+ public int hashCode() {
+ return 619 * mask.hashCode() + 257 * value.hashCode();
+ }
+
+ public static class Builder {
+ private long raw1 = -1, raw2 = -1, raw3 = -1, raw4 = -1,
+ raw5 = -1, raw6 = -1, raw7 = -1, raw8 = -1;
+
+ public Builder() {
+
+ }
+
+ /** @return whether or not the given port is logically included in the
+ * match, i.e., whether a packet from in-port <em>port</em> be matched by
+ * this OXM.
+ */
+ public boolean isOn(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ return !(OFBitMask512.isBitOn(raw1, raw2, raw3, raw4,
+ raw5, raw6, raw7, raw8, port.getPortNumber()));
+ }
+
+ /** remove this port from the match, i.e., packets from this in-port
+ * will NOT be matched.
+ */
+ public Builder unset(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ int bit = port.getPortNumber();
+ if (bit < 0 || bit > 511)
+ throw new IndexOutOfBoundsException("Port number is out of bounds");
+ else if (bit == 511)
+ // the highest order bit in the bitmask is reserved. The switch will
+ // set that bit for all ports >= 511. The reason is that we don't want
+ // the OFPortMap to match all ports out of its range (i.e., a packet
+ // coming in on port 581 would match *any* OFPortMap).
+ throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
+ else if (bit < 64) {
+ raw8 |= ((long)1 << bit);
+ } else if (bit < 128) {
+ raw7 |= ((long)1 << bit - 64);
+ } else if (bit < 192) {
+ raw6 |= ((long)1 << bit - 128);
+ } else if (bit < 256) {
+ raw5 |= ((long)1 << bit - 192);
+ } else if (bit < 320) {
+ raw4 |= ((long)1 << bit - 256);
+ } else if (bit < 384) {
+ raw3 |= ((long)1 << bit - 320);
+ } else if (bit < 448) {
+ raw2 |= ((long)1 << bit - 384);
+ } else {
+ raw1 |= ((long)1 << (bit - 448));
+ }
+ return this;
+ }
+
+ /** add this port from the match, i.e., packets from this in-port
+ * will NOT be matched.
+ */
+ public Builder set(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ int bit = port.getPortNumber();
+ if (bit < 0 || bit > 511)
+ throw new IndexOutOfBoundsException("Port number is out of bounds");
+ else if (bit == 511)
+ // the highest order bit in the bitmask is reserved. The switch will
+ // set that bit for all ports >= 511. The reason is that we don't want
+ // the OFPortMap to match all ports out of its range (i.e., a packet
+ // coming in on port 581 would match *any* OFPortMap).
+ throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
+ else if (bit < 64) {
+ raw8 &= ~((long)1 << bit);
+ } else if (bit < 128) {
+ raw7 &= ~((long)1 << bit - 64);
+ } else if (bit < 192) {
+ raw6 &= ~((long)1 << bit - 128);
+ } else if (bit < 256) {
+ raw5 &= ~((long)1 << bit - 192);
+ } else if (bit < 320) {
+ raw4 &= ~((long)1 << bit - 256);
+ } else if (bit < 384) {
+ raw3 &= ~((long)1 << bit - 320);
+ } else if (bit < 448) {
+ raw2 &= ~((long)1 << bit - 384);
+ } else {
+ raw1 &= ~((long)1 << (bit - 448));
+ }
+ return this;
+ }
+
+ public OFPortBitMap512 build() {
+ return new OFPortBitMap512(OFBitMask512.of(raw1, raw2, raw3, raw4,
+ raw5, raw6, raw7, raw8));
+ }
+ }
+
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
index 4db84f1..f5b1a91 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
@@ -8,6 +8,10 @@
import org.junit.Test;
public class OFPortBitMapTest extends TestCase {
+
+ /**
+ * 128 Bit variation
+ */
@Test
public void testCreateAndIterate() {
OFPortBitMap map = OFPortBitMap.ofPorts(OFPort.of(1), OFPort.of(2), OFPort.of(5));
@@ -68,4 +72,70 @@
}
assertArrayEquals(on, actual);
}
+
+ /**
+ * 512 Bit variation
+ */
+ @Test
+ public void testCreateAndIterate512() {
+ OFPortBitMap512 map = OFPortBitMap512.ofPorts(OFPort.of(1), OFPort.of(2), OFPort.of(5));
+
+ assertThat(map.getOnPorts(), contains(OFPort.of(1), OFPort.of(2), OFPort.of(5)));
+ }
+
+ @Test
+ public void testOFBitMap512() {
+ OFBitMask512 bitmap = OFBitMask512.of(0xFFFF_FFFF_FFFF_FFFFL, 0xFFFF_FFFF_FFFF_FFFFL,
+ 0xFFFF_FFFF_FFFF_FFFFL, 0xFFFF_FFFF_FFFF_FFFFL, 0xFFFF_FFFF_FFFF_FFFFL,
+ 0xFFFF_FFFF_FFFF_FFFFL, 0xFFFF_FFFF_FFFF_FFFFL, 0xFFFF_FFFF_FFFF_FFD9L);
+
+ OFPortBitMap512 map = OFPortBitMap512.of(bitmap);
+
+ assertThat(map.getOnPorts(), contains(OFPort.of(1), OFPort.of(2), OFPort.of(5)));
+ }
+
+ @Test
+ public void testOFPortBitMap512() {
+ Boolean[] on = new Boolean[511];
+ for (int i = 0; i < 511; i++) {
+ on[i] = false;
+ }
+
+ OFPortBitMap512.Builder builder = new OFPortBitMap512.Builder();
+
+ for (int i = 0; i < 511; i += 3) {
+ OFPort p = OFPort.of(i);
+ builder.set(p);
+ on[p.getPortNumber()] = true;
+ }
+
+ // Test that all ports that were added are actually on, and all other ports are off
+ OFPortBitMap512 portmap = builder.build();
+ //System.out.println(portmap);
+ Boolean[] actual = new Boolean[511];
+ for (int i = 0; i < 511; i++) {
+ actual[i] = false;
+ }
+ for (int i = 0; i < 511; i++) {
+ actual[i] = portmap.isOn(OFPort.of(i));
+ }
+ assertArrayEquals(on, actual);
+
+ // Turn some ports off
+ for (int i = 0; i < 511; i += 7) {
+ on[i] = false;
+ builder.unset(OFPort.of(i));
+ }
+
+ // Test again
+ portmap = builder.build();
+ actual = new Boolean[511];
+ for (int i = 0; i < 511; i++) {
+ actual[i] = false;
+ }
+ for (int i = 0; i < 511; i++) {
+ actual[i] = portmap.isOn(OFPort.of(i));
+ }
+ assertArrayEquals(on, actual);
+ }
}