Merge into master from pull request #258:
java_gen: Hash-related functions for U64, renamed OFChecksum128 to U128 (https://github.com/floodlight/loxigen/pull/258)
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 452ac58..471f1a8 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -311,6 +311,10 @@
u64 = JType('U64', 'long') \
.op(read='U64.ofRaw(bb.readLong())', write='bb.writeLong($name.getValue())', default="U64.ZERO", pub_type=True) \
.op(read='bb.readLong()', write='bb.writeLong($name)', pub_type=False)
+u128 = JType("U128") \
+ .op(read='U128.read16Bytes(bb)',
+ write='$name.write16Bytes(bb)',
+ default='U128.ZERO')
of_port = JType("OFPort") \
.op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFPort.ANY") \
.op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFPort.ANY")
@@ -491,10 +495,6 @@
.op(version=ANY, read="ClassId.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="ClassId.NONE")
boolean_value = JType('OFBooleanValue', 'OFBooleanValue') \
.op(read='OFBooleanValue.of(bb.readByte() != 0)', write='bb.writeByte($name.getInt())', default="OFBooleanValue.FALSE")
-checksum = JType("OFChecksum128") \
- .op(read='OFChecksum128.read16Bytes(bb)',
- write='$name.write16Bytes(bb)',
- default='OFChecksum128.ZERO')
gen_table_id = JType("GenTableId") \
.op(read='GenTableId.read2Bytes(bb)',
write='$name.write2Bytes(bb)',
@@ -536,7 +536,7 @@
'of_oxm_t': oxm,
'of_meter_features_t': meter_features,
'of_bitmap_128_t': port_bitmap,
- 'of_checksum_128_t': checksum,
+ 'of_checksum_128_t': u128,
'of_bsn_vport_t': bsn_vport,
}
diff --git a/java_gen/pre-written/pom.xml b/java_gen/pre-written/pom.xml
index b4e81cc..e1c0630 100644
--- a/java_gen/pre-written/pom.xml
+++ b/java_gen/pre-written/pom.xml
@@ -10,7 +10,7 @@
<groupId>org.projectfloodlight</groupId>
<artifactId>openflowj</artifactId>
- <version>0.3.4-SNAPSHOT</version>
+ <version>0.3.5-SNAPSHOT</version>
<packaging>jar</packaging>
<name>OpenFlowJ-Loxi</name>
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashFunc.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashFunc.java
new file mode 100644
index 0000000..f7648d7
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashFunc.java
@@ -0,0 +1,14 @@
+package org.projectfloodlight.openflow.types;
+
+/** A hash function that can hash a {@link PrimitiveSinkable}.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ * @param <H> - the hash.
+ */
+public interface HashFunc<H extends HashValue<H>> {
+ /** Hash the PrimitivateSinkable with this hash function and return the result */
+ public H hash(PrimitiveSinkable v);
+
+ /** Provide a defined null-hash */
+ public H nullHash();
+}
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashValue.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
new file mode 100644
index 0000000..1dd55d5
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
@@ -0,0 +1,54 @@
+package org.projectfloodlight.openflow.types;
+
+import javax.annotation.concurrent.Immutable;
+
+/** a hash value that supports bit-wise combinations, mainly to calculate hash values for
+ * reconciliation operations.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ *
+ * @param <H> - this type, for return type safety.
+ */
+@Immutable
+public interface HashValue<H extends HashValue<H>> {
+ /** return the "numBits" highest-order bits of the hash.
+ * @param numBits number of higest-order bits to return [0-32].
+ * @return a numberic value of the 0-32 highest-order bits.
+ */
+ int prefixBits(int numBits);
+
+ /** @return the bitwise inverse of this value */
+ H inverse();
+
+ /** or this value with another value value of the same type */
+ H or(H other);
+
+ /** and this value with another value value of the same type */
+ H and(H other);
+
+ /** xor this value with another value value of the same type */
+ H xor(H other);
+
+ /** calculate a combined hash value of this hash value (the <b>Key</b>) and the hash value
+ * specified as a parameter (the <b>Value</b>).
+ * <p>
+ * The value is constructed as follows:
+ * <ul>
+ * <li>the first keyBits bits are taken only from the Key
+ * <li>the other bits are taken from key xor value.
+ * </ul>
+ * The overall result looks like this:
+ * <pre>
+ * MSB LSB
+ * +---------+--------------+
+ * | key | key ^ value |
+ * +---------+--------------+
+ * |-keyBits-|
+ * </pre>
+ *
+ * @param value - hash value to be compared with this value (the key)
+ * @param keyBits number of prefix bits that are just taken from key
+ * @return the combined value.
+ */
+ H combineWithValue(H value, int keyBits);
+}
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashValueUtils.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashValueUtils.java
new file mode 100644
index 0000000..15f8a9b
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/HashValueUtils.java
@@ -0,0 +1,29 @@
+package org.projectfloodlight.openflow.types;
+
+import com.google.common.base.Preconditions;
+
+public class HashValueUtils {
+ private HashValueUtils() { }
+
+ public static long combineWithValue(long key, long value, int keyBits) {
+ Preconditions.checkArgument(keyBits >= 0 && keyBits <= 64, "keyBits must be [0,64]");
+
+ int valueBits = 64 - keyBits;
+ long valueMask = valueBits == 64 ? 0xFFFFFFFFFFFFFFFFL : (1L << valueBits) - 1;
+
+ return key ^ (value & valueMask);
+ }
+
+ public static int prefixBits(long raw1, int numBits) {
+ Preconditions.checkArgument(numBits >= 0 && numBits <= 32,
+ "numBits must be in range [0, 32]");
+
+ if(numBits == 0)
+ return 0;
+
+ final int shiftDown = 64 - numBits;
+
+ return (int) (raw1 >>> shiftDown);
+ }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFChecksum128.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFChecksum128.java
deleted file mode 100644
index 7578dc6..0000000
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFChecksum128.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package org.projectfloodlight.openflow.types;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-import com.google.common.hash.PrimitiveSink;
-
-public class OFChecksum128 implements OFValueType<OFChecksum128> {
-
- static final int LENGTH = 16;
-
- private final long raw1; // MSBs
- private final long raw2; // LSBs
-
- public static final OFChecksum128 ZERO = new OFChecksum128(0, 0);
-
- private OFChecksum128(long raw1, long raw2) {
- this.raw1 = raw1;
- this.raw2 = raw2;
- }
-
- public static OFChecksum128 of(long raw1, long raw2) {
- if (raw1 == 0 && raw2 == 0)
- return ZERO;
- return new OFChecksum128(raw1, raw2);
- }
-
- @Override
- public int getLength() {
- return LENGTH;
- }
-
- @Override
- public OFChecksum128 applyMask(OFChecksum128 mask) {
- return of(this.raw1 & mask.raw1, this.raw2 & mask.raw2);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof OFChecksum128))
- return false;
- OFChecksum128 other = (OFChecksum128)obj;
- return (other.raw1 == this.raw1 && other.raw2 == this.raw2);
- }
-
- @Override
- public int hashCode() {
- return (int)(31 * raw1 + raw2);
- }
-
- public void write16Bytes(ChannelBuffer cb) {
- cb.writeLong(raw1);
- cb.writeLong(raw2);
- }
-
- public static OFChecksum128 read16Bytes(ChannelBuffer cb) {
- long raw1 = cb.readLong();
- long raw2 = cb.readLong();
- return of(raw1, raw2);
- }
-
- @Override
- public String toString() {
- return String.format("0x%016x%016x", raw1, raw2);
- }
-
- @Override
- public int compareTo(OFChecksum128 o) {
- long c = this.raw1 - o.raw1;
- if (c != 0)
- return Long.signum(c);
- return Long.signum(this.raw2 - o.raw2);
- }
-
- @Override
- public void putTo(PrimitiveSink sink) {
- sink.putLong(raw1);
- sink.putLong(raw2);
- }
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U128.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U128.java
new file mode 100644
index 0000000..35ef846
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U128.java
@@ -0,0 +1,137 @@
+package org.projectfloodlight.openflow.types;
+
+import javax.annotation.Nonnull;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.UnsignedLongs;
+
+public class U128 implements OFValueType<U128>, HashValue<U128> {
+
+ static final int LENGTH = 16;
+
+ private final long raw1; // MSBs
+ private final long raw2; // LSBs
+
+ public static final U128 ZERO = new U128(0, 0);
+
+ private U128(long raw1, long raw2) {
+ this.raw1 = raw1;
+ this.raw2 = raw2;
+ }
+
+ public static U128 of(long raw1, long raw2) {
+ if (raw1 == 0 && raw2 == 0)
+ return ZERO;
+ return new U128(raw1, raw2);
+ }
+
+ @Override
+ public int getLength() {
+ return LENGTH;
+ }
+
+
+ public long getMsb() {
+ return raw1;
+ }
+
+ public long getLsb() {
+ return raw2;
+ }
+
+ @Override
+ public U128 applyMask(U128 mask) {
+ return and(mask);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
+ result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ U128 other = (U128) obj;
+ if (raw1 != other.raw1)
+ return false;
+ if (raw2 != other.raw2)
+ return false;
+ return true;
+ }
+
+ public void write16Bytes(ChannelBuffer cb) {
+ cb.writeLong(raw1);
+ cb.writeLong(raw2);
+ }
+
+ public static U128 read16Bytes(ChannelBuffer cb) {
+ long raw1 = cb.readLong();
+ long raw2 = cb.readLong();
+ return of(raw1, raw2);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("0x%016x%016x", raw1, raw2);
+ }
+
+ @Override
+ public int compareTo(@Nonnull U128 o) {
+ int msb = UnsignedLongs.compare(this.raw1, o.raw1);
+ if(msb != 0)
+ return msb;
+ else
+ return UnsignedLongs.compare(this.raw2, o.raw2);
+ }
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putLong(raw1);
+ sink.putLong(raw2);
+ }
+
+ @Override
+ public U128 inverse() {
+ return U128.of(~raw1, ~raw2);
+ }
+
+ @Override
+ public U128 or(U128 other) {
+ return U128.of(raw1 | other.raw1, raw2 | other.raw2);
+ }
+
+ @Override
+ public U128 and(U128 other) {
+ return U128.of(raw1 & other.raw1, raw2 & other.raw2);
+ }
+
+ @Override
+ public U128 xor(U128 other) {
+ return U128.of(raw1 ^ other.raw1, raw2 ^ other.raw2);
+ }
+
+ @Override
+ public int prefixBits(int numBits) {
+ return HashValueUtils.prefixBits(this.raw1, numBits);
+ }
+
+ @Override
+ public U128 combineWithValue(U128 value, int keyBits) {
+ return U128.of(
+ HashValueUtils.combineWithValue(this.raw1, value.raw1, Math.min(64, keyBits)),
+ HashValueUtils.combineWithValue(this.raw2, value.raw2, Math.max(0,keyBits-64))
+ );
+ }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
index f480c47..9001eb8 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
@@ -27,7 +27,7 @@
import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedLongs;
-public class U64 implements Writeable, OFValueType<U64> {
+public class U64 implements Writeable, OFValueType<U64>, HashValue<U64> {
private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
private final static long ZERO_VAL = 0;
public final static U64 ZERO = new U64(ZERO_VAL);
@@ -110,7 +110,7 @@
@Override
public U64 applyMask(U64 mask) {
- return ofRaw(raw & mask.raw);
+ return and(mask);
}
@Override
@@ -128,6 +128,39 @@
sink.putLong(raw);
}
+ @Override
+ public U64 inverse() {
+ return U64.of(~raw);
+ }
+
+ @Override
+ public U64 or(U64 other) {
+ return U64.of(raw | other.raw);
+ }
+
+ @Override
+ public U64 and(U64 other) {
+ return ofRaw(raw & other.raw);
+ }
+ @Override
+ public U64 xor(U64 other) {
+ return U64.of(raw ^ other.raw);
+ }
+
+ /** return the "numBits" highest-order bits of the hash.
+ * @param numBits number of higest-order bits to return [0-32].
+ * @return a numberic value of the 0-32 highest-order bits.
+ */
+ @Override
+ public int prefixBits(int numBits) {
+ return HashValueUtils.prefixBits(raw, numBits);
+ }
+
+ @Override
+ public U64 combineWithValue(U64 value, int keyBits) {
+ return U64.of(HashValueUtils.combineWithValue(this.raw, value.raw, keyBits));
+ }
+
public final static Reader READER = new Reader();
private static class Reader implements OFMessageReader<U64> {
@@ -136,4 +169,6 @@
return U64.ofRaw(bb.readLong());
}
}
+
+
}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/HashValueUtilsTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/HashValueUtilsTest.java
new file mode 100644
index 0000000..1fe36ac
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/HashValueUtilsTest.java
@@ -0,0 +1,23 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+public class HashValueUtilsTest {
+ @Test
+ public void testBasic() {
+ long key = 0x1234_5678_1234_5678L;
+ long value = 0x8765_4321_8765_4321L;
+ long firstword = 0xFFFF_FFFF_0000_0000L;
+ long secondword = 0x0000_0000_FFFF_FFFFL;
+ long xor = key ^ value;
+
+ assertThat(HashValueUtils.combineWithValue(key, value, 0), equalTo(xor));
+ assertThat(HashValueUtils.combineWithValue(key, value, 64), equalTo(key));
+ assertThat(HashValueUtils.combineWithValue(key, value, 32), equalTo(key & firstword | xor & secondword ));
+ assertThat(HashValueUtils.combineWithValue(key, value, 8), equalTo(0x1251_1559_9551_1559L));
+ }
+
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U128Test.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
new file mode 100644
index 0000000..fb5cd23
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
@@ -0,0 +1,182 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+public class U128Test {
+ @Test
+ public void testPositiveRaws() {
+ assertThat(U128.of(0, 0).getMsb(), equalTo(0L));
+ assertThat(U128.of(0, 0).getLsb(), equalTo(0L));
+
+ assertThat(U128.of(1, 2).getMsb(), equalTo(1L));
+ assertThat(U128.of(1, 2).getLsb(), equalTo(2L));
+ }
+
+ @Test
+ public void testPutTo() {
+ U128 h = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+ U128 hSame = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+
+ U128 hBothDiff = U128.of(0x1234_5678_90ab_cdefL,0x1234_5678_90ab_cdefL);
+ U128 hMsbDiff = U128.of(0x0234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+ U128 hLsbDiff = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeeeL);
+
+ assertThat(hash(h), equalTo(hash(hSame)));
+ assertThat(hash(h), not(hash(hBothDiff)));
+ assertThat(hash(h), not(hash(hMsbDiff)));
+ assertThat(hash(h), not(hash(hLsbDiff)));
+ }
+
+ private HashCode hash(U128 f) {
+ Hasher hash = Hashing.murmur3_128().newHasher();
+ f.putTo(hash);
+ return hash.hash();
+
+ }
+
+ @Test
+ public void testEqualHashCode() {
+ U128 h1 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ U128 h2 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ U128 h3 = U128.of(0xeeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ U128 h3_2 = U128.of(0xdeafbeefdeadbeefL, 0xeeafbeefdeadbeefL);
+
+ assertTrue(h1.equals(h1));
+ assertTrue(h1.equals(h2));
+ assertFalse(h1.equals(h3));
+ assertFalse(h1.equals(h3_2));
+ assertTrue(h2.equals(h1));
+
+ assertEquals(h1.hashCode(), h2.hashCode());
+ assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+ assertNotEquals(h1.hashCode(), h3_2.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+ }
+
+ @Test
+ public void testXor() {
+ U128 hNull = U128.of(0, 0);
+ U128 hDeadBeef = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ assertThat(hNull.xor(hNull), equalTo(hNull));
+ assertThat(hNull.xor(hDeadBeef), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hNull), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hDeadBeef), equalTo(hNull));
+
+
+ U128 h1_0 = U128.of(1L, 0);
+ U128 h8_0 = U128.of(0x8000000000000000L, 0);
+ U128 h81_0 = U128.of(0x8000000000000001L, 0);
+ assertThat(h1_0.xor(h8_0), equalTo(h81_0));
+
+ U128 h0_1 = U128.of(0, 1L);
+ U128 h0_8 = U128.of(0, 0x8000000000000000L);
+ U128 h0_81 = U128.of(0, 0x8000000000000001L);
+ assertThat(h0_1.xor(h0_8), equalTo(h0_81));
+ }
+
+ @Test
+ public void testKeyBits() {
+ U128 zeroU = U128.of(0,0);
+ assertThat(zeroU.prefixBits(0), equalTo(0));
+ assertThat(zeroU.prefixBits(16), equalTo(0));
+ assertThat(zeroU.prefixBits(32), equalTo(0));
+
+ checkInvalidKeyBitSize(zeroU, 33);
+ checkInvalidKeyBitSize(zeroU, 64);
+ assertThat(zeroU.prefixBits(3), equalTo(0));
+
+ U128 positiveU = U128.of(0x1234_5678_1234_5678L, 0x1234_5678_1234_5678L);
+ assertThat(positiveU.prefixBits(0), equalTo(0));
+ assertThat(positiveU.prefixBits(16), equalTo(0x1234));
+ assertThat(positiveU.prefixBits(32), equalTo(0x12345678));
+ checkInvalidKeyBitSize(positiveU, 33);
+ checkInvalidKeyBitSize(positiveU, 64);
+
+ U128 signedBitU = U128.of(0x8765_4321_8765_4321L, 0x1234_5678_1234_5678L);
+ assertThat(signedBitU.prefixBits(0), equalTo(0));
+ assertThat(signedBitU.prefixBits(16), equalTo(0x8765));
+ assertThat(signedBitU.prefixBits(32), equalTo(0x8765_4321));
+ checkInvalidKeyBitSize(signedBitU, 33);
+ checkInvalidKeyBitSize(signedBitU, 64);
+ }
+
+ private void
+ checkInvalidKeyBitSize(U128 u, int prefixBit) {
+ try {
+ u.prefixBits(prefixBit);
+ fail("Expected exception not thrown for "+prefixBit + " bits");
+ } catch(IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+
+ @Test
+ public void testCompare() {
+ U128 u0_0 = U128.of(0, 0);
+ U128 u0_1 = U128.of(0, 1);
+ U128 u0_8 = U128.of(0, 0x8765_4321_8765_4321L);
+ U128 u1_0 = U128.of(0x1234_5678_1234_5678L, 0);
+ U128 u8_0 = U128.of(0x8765_4321_8765_4321L, 0);
+ U128 uf_0 = U128.of(0xFFFF_FFFF_FFFF_FFFFL, 0);
+
+ U128[] us = new U128[] { u0_0, u0_1, u0_8, u1_0, u8_0, uf_0 };
+
+ for(int i = 0; i< us.length; i++) {
+ U128 u_base = us[i];
+ assertThat(
+ String.format("%s should be equal to itself (compareTo)", u_base),
+ u_base.compareTo(u_base), equalTo(0));
+ assertThat(
+ String.format("%s should be equal to itself (equals)", u_base),
+ u_base.equals(u_base), equalTo(true));
+ assertThat(
+ String.format("%s should be equal to itself (equals, by value)", u_base),
+ u_base.equals(U128.of(u_base.getMsb(), u_base.getLsb())), equalTo(true));
+
+ for(int j = i+1; j< us.length; j++) {
+ U128 u_greater = us[j];
+ assertThat(
+ String.format("%s should not be equal to %s", u_base, u_greater),
+ u_base.equals(u_base), equalTo(true));
+ assertThat(
+ String.format("%s should be smaller than %s", u_base, u_greater),
+ u_base.compareTo(u_greater), Matchers.lessThan(0));
+ assertThat(
+ String.format("%s should be greater than %s", u_greater, u_base),
+ u_greater.compareTo(u_base), Matchers.greaterThan(0));
+ }
+ }
+ }
+
+ @Test
+ public void testCombine() {
+ long key = 0x1234567890abcdefL;
+ long val = 0xdeafbeefdeadbeefL;
+ U128 hkey = U128.of(key, key*2);
+ U128 hVal = U128.of(val, val/2);
+
+ assertThat(hkey.combineWithValue(hVal, 0), equalTo(hkey.xor(hVal)));
+ assertThat(hkey.combineWithValue(hVal, 64), equalTo(U128.of(hkey.getMsb(), hkey.getLsb() ^ hVal.getLsb())));
+ assertThat(hkey.combineWithValue(hVal, 128), equalTo(hkey));
+
+ long mask8 = 0xFF00_0000_0000_0000L;
+
+ assertThat(hkey.combineWithValue(hVal, 8), equalTo(U128.of(hkey.getMsb() & mask8 | hkey.getMsb() ^ hVal.getMsb() & ~mask8,
+ hkey.getLsb() ^ hVal.getLsb() )));
+ }
+
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
index e45e8a0..b0cca23 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
@@ -1,6 +1,12 @@
package org.projectfloodlight.openflow.types;
+import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.math.BigInteger;
@@ -18,9 +24,95 @@
@Test
public void testNegativeRaws() {
- long minus_1 = 0xFFffFFffFFffFFffL;
+ long minus_1 = 0xFFFF_FFFF_FFFF_FFFFL;
assertEquals(minus_1, U64.ofRaw(minus_1).getValue());
- assertEquals(new BigInteger("FFffFFffFFffFFff", 16), U64.ofRaw(minus_1).getBigInteger());
+ assertEquals(new BigInteger("FFFF_FFFF_FFFF_FFFF".replace("_", ""), 16), U64.ofRaw(minus_1).getBigInteger());
assertEquals(new BigInteger("18446744073709551615"), U64.ofRaw(minus_1).getBigInteger());
}
+
+ @Test
+ public void testEqualHashCode() {
+ U64 h1 = U64.of(0xdeafbeefdeadbeefL);
+ U64 h2 = U64.of(0xdeafbeefdeadbeefL);
+ U64 h3 = U64.of(0xeeafbeefdeadbeefL);
+
+ assertTrue(h1.equals(h1));
+ assertTrue(h1.equals(h2));
+ assertFalse(h1.equals(h3));
+ assertTrue(h2.equals(h1));
+
+ assertEquals(h1.hashCode(), h2.hashCode());
+ assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+ }
+
+ @Test
+ public void testXor() {
+ U64 hNull = U64.of(0);
+ U64 hDeadBeef = U64.of(0xdeafbeefdeadbeefL);
+ assertThat(hNull.xor(hNull), equalTo(hNull));
+ assertThat(hNull.xor(hDeadBeef), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hNull), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hDeadBeef), equalTo(hNull));
+
+
+ U64 h1 = U64.of(1L);
+ U64 h8 = U64.of(0x8000000000000000L);
+ U64 h81 = U64.of(0x8000000000000001L);
+ assertThat(h1.xor(h8), equalTo(h81));
+ }
+
+ @Test
+ public void testCombine() {
+ long key = 0x1234567890abcdefL;
+ long val = 0xdeafbeefdeadbeefL;
+ U64 hkey = U64.of(key);
+ U64 hVal = U64.of(val);
+
+ assertThat(hkey.combineWithValue(hVal, 0), equalTo(hkey.xor(hVal)));
+ assertThat(hkey.combineWithValue(hVal, 64), equalTo(hkey));
+ long mask32 = 0x00000000FFFFFFFFL;
+ assertThat(hkey.combineWithValue(hVal, 32),
+ equalTo(U64.of(key & ~mask32| (key ^ val) & mask32)));
+
+ long tenMask = 0x003FFFFFFFFFFFFFL;
+ assertThat(hkey.combineWithValue(hVal, 10),
+ equalTo(U64.of(key & ~tenMask | (key ^ val) & tenMask)));
+ }
+
+ @Test
+ public void testKeyBits() {
+ U64 zeroU = U64.of(0);
+ assertThat(zeroU.prefixBits(0), equalTo(0));
+ assertThat(zeroU.prefixBits(16), equalTo(0));
+ assertThat(zeroU.prefixBits(32), equalTo(0));
+
+ checkInvalidKeyBitSize(zeroU, 33);
+ checkInvalidKeyBitSize(zeroU, 64);
+ assertThat(zeroU.prefixBits(3), equalTo(0));
+
+ U64 positiveU = U64.of(0x1234_5678_1234_5678L);
+ assertThat(positiveU.prefixBits(0), equalTo(0));
+ assertThat(positiveU.prefixBits(16), equalTo(0x1234));
+ assertThat(positiveU.prefixBits(32), equalTo(0x12345678));
+ checkInvalidKeyBitSize(positiveU, 33);
+ checkInvalidKeyBitSize(positiveU, 64);
+
+ U64 signedBitU = U64.of(0x8765_4321_8765_4321L);
+ assertThat(signedBitU.prefixBits(0), equalTo(0));
+ assertThat(signedBitU.prefixBits(16), equalTo(0x8765));
+ assertThat(signedBitU.prefixBits(32), equalTo(0x8765_4321));
+ checkInvalidKeyBitSize(signedBitU, 33);
+ checkInvalidKeyBitSize(signedBitU, 64);
+ }
+
+ private void
+ checkInvalidKeyBitSize(U64 u, int prefixBit) {
+ try {
+ u.prefixBits(prefixBit);
+ fail("Expected exception not thrown for "+prefixBit + " bits");
+ } catch(IllegalArgumentException e) {
+ // expected
+ }
+ }
+
}
diff --git a/test_data/of13/bsn_gentable_bucket_stats_reply.data b/test_data/of13/bsn_gentable_bucket_stats_reply.data
index 8e0772f..84a36a6 100644
--- a/test_data/of13/bsn_gentable_bucket_stats_reply.data
+++ b/test_data/of13/bsn_gentable_bucket_stats_reply.data
@@ -22,8 +22,8 @@
builder.setXid(0x12345678)
.setEntries(
ImmutableList.<OFBsnGentableBucketStatsEntry>of(
- factory.bsnGentableBucketStatsEntry(OFChecksum128.of(0x8877665544332211L, 0xFFEEDDCCBBAA9988L)),
- factory.bsnGentableBucketStatsEntry(OFChecksum128.of(0x1234234534564567L, 0x56786789789A89ABL))
+ factory.bsnGentableBucketStatsEntry(U128.of(0x8877665544332211L, 0xFFEEDDCCBBAA9988L)),
+ factory.bsnGentableBucketStatsEntry(U128.of(0x1234234534564567L, 0x56786789789A89ABL))
)
)
-- c
diff --git a/test_data/of13/bsn_gentable_clear_request.data b/test_data/of13/bsn_gentable_clear_request.data
index 847af3c..853d463 100644
--- a/test_data/of13/bsn_gentable_clear_request.data
+++ b/test_data/of13/bsn_gentable_clear_request.data
@@ -16,8 +16,8 @@
checksum_mask=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000)
-- java
builder.setXid(0x12345678)
- .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA990000L))
- .setChecksumMask(OFChecksum128.of(0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFF0000L))
+ .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA990000L))
+ .setChecksumMask(U128.of(0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFF0000L))
.setTableId(GenTableId.of(20))
-- c
obj = of_bsn_gentable_clear_request_new(OF_VERSION_1_3);
diff --git a/test_data/of13/bsn_gentable_entry_add.data b/test_data/of13/bsn_gentable_entry_add.data
index 02c2bb4..f813dcd 100644
--- a/test_data/of13/bsn_gentable_entry_add.data
+++ b/test_data/of13/bsn_gentable_entry_add.data
@@ -38,7 +38,7 @@
])
-- java
builder.setXid(0x12345678)
- .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998877L))
+ .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998877L))
.setTableId(GenTableId.of(20))
.setKey(
ImmutableList.<OFBsnTlv>of(
diff --git a/test_data/of13/bsn_gentable_entry_desc_stats_reply.data b/test_data/of13/bsn_gentable_entry_desc_stats_reply.data
index 4035f4c..21291ed 100644
--- a/test_data/of13/bsn_gentable_entry_desc_stats_reply.data
+++ b/test_data/of13/bsn_gentable_entry_desc_stats_reply.data
@@ -55,7 +55,7 @@
.setEntries(
ImmutableList.<OFBsnGentableEntryDescStatsEntry>of(
factory.buildBsnGentableEntryDescStatsEntry()
- .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998800L))
+ .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998800L))
.setKey(ImmutableList.<OFBsnTlv>of(
factory.bsnTlvs().port(OFPort.of(5))
))
@@ -64,7 +64,7 @@
))
.build(),
factory.buildBsnGentableEntryDescStatsEntry()
- .setChecksum(OFChecksum128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998801L))
+ .setChecksum(U128.of(0xFEDCBA9876543210L, 0xFFEECCBBAA998801L))
.setKey(ImmutableList.<OFBsnTlv>of(
factory.bsnTlvs().port(OFPort.of(6))
))