fixing loxi output
upgrade to 0.3.8
agrregate pom for of-lib
Change-Id: Ie75d75b708c30934bbca235e68c50de656d84ad4
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
index f103230..78e6075 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
@@ -232,6 +232,9 @@
public final static MatchField<U16> BSN_TCP_FLAGS =
new MatchField<U16>("bsn_tcp_flags", MatchFields.BSN_TCP_FLAGS);
+ public final static MatchField<ClassId> BSN_VLAN_XLATE_PORT_GROUP_ID =
+ new MatchField<ClassId>("bsn_vlan_xlate_port_group_id", MatchFields.BSN_VLAN_XLATE_PORT_GROUP_ID);
+
public String getName() {
return name;
}
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
index 354a528..863634e 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
@@ -56,4 +56,5 @@
BSN_UDF6,
BSN_UDF7,
BSN_TCP_FLAGS,
+ BSN_VLAN_XLATE_PORT_GROUP_ID,
}
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
index 1dd55d5..3030e3e 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/HashValue.java
@@ -17,6 +17,23 @@
*/
int prefixBits(int numBits);
+ /** perform an arithmetic addition of this value and other. Wraps around on
+ * overflow of the defined word size.
+ *
+ * @param other
+ * @return this + other
+ */
+ H add(H other);
+
+ /**
+ * arithmetically substract the given 'other' value from this value.
+ * around on overflow.
+ *
+ * @param other
+ * @return this - other
+ */
+ H subtract(H other);
+
/** @return the bitwise inverse of this value */
H inverse();
@@ -29,26 +46,57 @@
/** 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>
+ /** create and return a builder */
+ Builder<H> builder();
+
+ /** a mutator for HashValues. Allows perfomring a series of
+ * operations on a hashv value without the associated cost of object
+ * reallocation.
*
- * @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.
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ *
+ * @param <H> - the hashvalue
*/
- H combineWithValue(H value, int keyBits);
+ public interface Builder<H> {
+ /** perform an arithmetic addition of this value and other. Wraps around on
+ * overflow of the defined word size.
+ *
+ * @param other
+ * @return this mutator
+ */
+ Builder<H> add(H other);
+
+ /**
+ * arithmetically substract the given 'other' value from the value stored in this mutator.
+ * around on overflow.
+ *
+ * @param other
+ * @return this mutator
+ */
+ Builder<H> subtract(H other);
+
+ /** bitwise invert the value stored in this mutator
+ *
+ * @return this mutator
+ */
+ Builder<H> invert();
+
+ /** or the value stored in this mutator with another value value of the same type
+ * @return this mutator
+ */
+ Builder<H> or(H other);
+
+ /** and the value stored in this mutator with another value value of the same type
+ * @return this mutator
+ */
+ Builder<H> and(H other);
+
+ /** xor the value stored in this mutator with another value value of the same type
+ * @return this mutator
+ */
+ Builder<H> xor(H other);
+
+ /** @return the hash value */
+ public H build();
+ }
}
\ No newline at end of file
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
index 5e4e818..cee9ad1 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddress.java
@@ -10,6 +10,11 @@
public abstract class IPAddress<F extends IPAddress<F>> implements OFValueType<F> {
+ /**
+ * Returns the Internet Protocol (IP) version of this object
+ *
+ * @return the Internet Protocol (IP) version of this object
+ */
public abstract IPVersion getIpVersion();
/**
@@ -55,6 +60,52 @@
*/
public abstract F not();
+ /**
+ * Returns an {@code IPAddressWithMask<F>} object that represents this
+ * IP address masked by the given IP address mask.
+ *
+ * @param mask the {@code F} object that represents the mask
+ * @return an {@code IPAddressWithMask<F>} object that represents this
+ * IP address masked by the given mask
+ * @throws NullPointerException if the given mask was {@code null}
+ */
+ @Nonnull
+ public abstract IPAddressWithMask<F> withMask(@Nonnull final F mask);
+
+ /**
+ * Returns an {@code IPAddressWithMask<F>} object that represents this
+ * IP address masked by the CIDR subnet mask of the given prefix length.
+ *
+ * @param cidrMaskLength the prefix length of the CIDR subnet mask
+ * (i.e. the number of leading one-bits),
+ * where <code>
+ * 0 <= cidrMaskLength <= (F.getLength() * 8)
+ * </code>
+ * @return an {@code IPAddressWithMask<F>} object that
+ * represents this IP address masked by the CIDR
+ * subnet mask of the given prefix length
+ * @throws IllegalArgumentException if the given prefix length was invalid
+ * @see #ofCidrMaskLength(int)
+ */
+ @Nonnull
+ public abstract IPAddressWithMask<F> withMaskOfLength(
+ final int cidrMaskLength);
+
+ /**
+ * Returns the raw IP address of this {@code IPAddress} object. The result
+ * is in network byte order: the highest order byte of the address is in
+ * {@code getBytes()[0]}.
+ * <p>
+ * Similar to {@link InetAddress#getAddress()}
+ *
+ * @return the raw IP address of this object
+ * @see InetAddress#getAddress()
+ */
+ public abstract byte[] getBytes();
+
+ @Override
+ public abstract String toString();
+
@Override
public abstract boolean equals(Object other);
@@ -88,14 +139,26 @@
* @throws NullPointerException if address is null
*/
@Nonnull
- public static IPAddress<?> fromInetAddress(@Nonnull InetAddress address) {
+ public static IPAddress<?> of(@Nonnull InetAddress address) {
Preconditions.checkNotNull(address, "address must not be null");
- byte [] bytes = address.getAddress();
if(address instanceof Inet4Address)
- return IPv4Address.of(bytes);
+ return IPv4Address.of((Inet4Address) address);
else if (address instanceof Inet6Address)
- return IPv6Address.of(bytes);
+ return IPv6Address.of((Inet6Address) address);
else
return IPAddress.of(address.getHostAddress());
}
+
+ /**
+ * Factory function for InetAddress values.
+ * @param address the InetAddress you wish to parse into an IPAddress object.
+ * @return the IPAddress object.
+ * @throws NullPointerException if address is null
+ * @deprecated replaced by {@link #of(InetAddress)}
+ */
+ @Deprecated
+ @Nonnull
+ public static IPAddress<?> fromInetAddress(@Nonnull InetAddress address) {
+ return of(address);
+ }
}
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
index ba7eb93..7cd8099 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPAddressWithMask.java
@@ -1,5 +1,7 @@
package org.projectfloodlight.openflow.types;
+import com.google.common.base.Preconditions;
+
public abstract class IPAddressWithMask<F extends IPAddress<F>> extends Masked<F> {
@@ -8,6 +10,8 @@
}
public abstract IPVersion getIpVersion();
+
+ public abstract boolean contains(IPAddress<?> ip);
public F getSubnetBroadcastAddress() {
if (!mask.isCidrMask()) {
@@ -22,9 +26,8 @@
}
public static IPAddressWithMask<?> of(String ip) {
- if (ip == null) {
- throw new NullPointerException("String ip must not be null");
- }
+ Preconditions.checkNotNull(ip, "string ip must not be null");
+
if (ip.indexOf('.') != -1)
return IPv4AddressWithMask.of(ip);
else if (ip.indexOf(':') != -1)
@@ -49,5 +52,4 @@
return res.toString();
}
-
}
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
index 865fb79..3a1b15e 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
@@ -1,11 +1,14 @@
package org.projectfloodlight.openflow.types;
+import java.net.Inet4Address;
+import java.net.InetAddress;
import java.util.Arrays;
import javax.annotation.Nonnull;
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.base.Preconditions;
import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
@@ -78,19 +81,17 @@
@Override
public IPv4Address and(IPv4Address other) {
- if (other == null) {
- throw new NullPointerException("Other IP Address must not be null");
- }
- IPv4Address otherIp = (IPv4Address) other;
+ Preconditions.checkNotNull(other, "other must not be null");
+
+ IPv4Address otherIp = other;
return IPv4Address.of(rawValue & otherIp.rawValue);
}
@Override
public IPv4Address or(IPv4Address other) {
- if (other == null) {
- throw new NullPointerException("Other IP Address must not be null");
- }
- IPv4Address otherIp = (IPv4Address) other;
+ Preconditions.checkNotNull(other, "other must not be null");
+
+ IPv4Address otherIp = other;
return IPv4Address.of(rawValue | otherIp.rawValue);
}
@@ -99,13 +100,30 @@
return IPv4Address.of(~rawValue);
}
- public static IPv4Address of(final byte[] address) {
- if (address == null) {
- throw new NullPointerException("Address must not be null");
- }
+ /**
+ * Returns an {@code IPv4Address} object that represents the given
+ * IP address. The argument is in network byte order: the highest
+ * order byte of the address is in {@code address[0]}.
+ * <p>
+ * The address byte array must be 4 bytes long (32 bits long).
+ * <p>
+ * Similar to {@link InetAddress#getByAddress(byte[])}.
+ *
+ * @param address the raw IP address in network byte order
+ * @return an {@code IPv4Address} object that represents the given
+ * raw IP address
+ * @throws NullPointerException if the given address was {@code null}
+ * @throws IllegalArgumentException if the given address was of an invalid
+ * byte array length
+ * @see InetAddress#getByAddress(byte[])
+ */
+ @Nonnull
+ public static IPv4Address of(@Nonnull final byte[] address) {
+ Preconditions.checkNotNull(address, "address must not be null");
+
if (address.length != LENGTH) {
throw new IllegalArgumentException(
- "Invalid byte array length for IPv4Address address: " + address.length);
+ "Invalid byte array length for IPv4 address: " + address.length);
}
int raw =
@@ -114,30 +132,37 @@
return IPv4Address.of(raw);
}
- /** construct an IPv4Address from a 32-bit integer value.
+ /**
+ * Returns an {@code IPv4Address} object that represents the given
+ * IP address.
*
- * @param raw the IPAdress represented as a 32-bit integer
- * @return the constructed IPv4Address
+ * @param raw the raw IP address represented as a 32-bit integer
+ * @return an {@code IPv4Address} object that represents the given
+ * raw IP address
*/
+ @Nonnull
public static IPv4Address of(final int raw) {
if(raw == NONE_VAL)
return NONE;
return new IPv4Address(raw);
}
- /** parse an IPv4Address from the canonical dotted-quad representation
- * (1.2.3.4).
+ /**
+ * Returns an {@code IPv4Address} object that represents the given
+ * IP address. The argument is in the canonical quad-dotted notation.
+ * For example, {@code 1.2.3.4}.
*
- * @param string an IPv4 address in dotted-quad representation
- * @return the parsed IPv4 address
- * @throws NullPointerException if string is null
- * @throws IllegalArgumentException if string is not a valid IPv4Address
+ * @param string the IP address in the canonical quad-dotted notation
+ * @return an {@code IPv4Address} object that represents the given
+ * IP address
+ * @throws NullPointerException if the given string was {@code null}
+ * @throws IllegalArgumentException if the given string was not a valid
+ * IPv4 address
*/
@Nonnull
public static IPv4Address of(@Nonnull final String string) throws IllegalArgumentException {
- if (string == null) {
- throw new NullPointerException("String must not be null");
- }
+ Preconditions.checkNotNull(string, "string must not be null");
+
int start = 0;
int shift = 24;
@@ -161,12 +186,90 @@
return IPv4Address.of(raw);
}
+ /**
+ * Returns an {@code IPv4Address} object that represents the given
+ * IP address. The argument is given as an {@code Inet4Address} object.
+ *
+ * @param address the IP address as an {@code Inet4Address} object
+ * @return an {@code IPv4Address} object that represents the
+ * given IP address
+ * @throws NullPointerException if the given {@code Inet4Address} was
+ * {@code null}
+ */
+ @Nonnull
+ public static IPv4Address of(@Nonnull final Inet4Address address) {
+ Preconditions.checkNotNull(address, "address must not be null");
+ return IPv4Address.of(address.getAddress());
+ }
+
+ /**
+ * Returns an {@code IPv4Address} object that represents the
+ * CIDR subnet mask of the given prefix length.
+ *
+ * @param cidrMaskLength the prefix length of the CIDR subnet mask
+ * (i.e. the number of leading one-bits),
+ * where {@code 0 <= cidrMaskLength <= 32}
+ * @return an {@code IPv4Address} object that represents the
+ * CIDR subnet mask of the given prefix length
+ * @throws IllegalArgumentException if the given prefix length was invalid
+ */
+ @Nonnull
+ public static IPv4Address ofCidrMaskLength(final int cidrMaskLength) {
+ Preconditions.checkArgument(
+ cidrMaskLength >= 0 && cidrMaskLength <= 32,
+ "Invalid IPv4 CIDR mask length: %s", cidrMaskLength);
+
+ if (cidrMaskLength == 32) {
+ return IPv4Address.NO_MASK;
+ } else if (cidrMaskLength == 0) {
+ return IPv4Address.FULL_MASK;
+ } else {
+ int mask = (-1) << (32 - cidrMaskLength);
+ return IPv4Address.of(mask);
+ }
+ }
+
+ /**
+ * Returns an {@code IPv4AddressWithMask} object that represents this
+ * IP address masked by the given IP address mask.
+ *
+ * @param mask the {@code IPv4Address} object that represents the mask
+ * @return an {@code IPv4AddressWithMask} object that represents this
+ * IP address masked by the given mask
+ * @throws NullPointerException if the given mask was {@code null}
+ */
+ @Nonnull
+ @Override
+ public IPv4AddressWithMask withMask(@Nonnull final IPv4Address mask) {
+ return IPv4AddressWithMask.of(this, mask);
+ }
+
+ /**
+ * Returns an {@code IPv4AddressWithMask} object that represents this
+ * IP address masked by the CIDR subnet mask of the given prefix length.
+ *
+ * @param cidrMaskLength the prefix length of the CIDR subnet mask
+ * (i.e. the number of leading one-bits),
+ * where {@code 0 <= cidrMaskLength <= 32}
+ * @return an {@code IPv4AddressWithMask} object that
+ * represents this IP address masked by the CIDR
+ * subnet mask of the given prefix length
+ * @throws IllegalArgumentException if the given prefix length was invalid
+ * @see #ofCidrMaskLength(int)
+ */
+ @Nonnull
+ @Override
+ public IPv4AddressWithMask withMaskOfLength(final int cidrMaskLength) {
+ return this.withMask(IPv4Address.ofCidrMaskLength(cidrMaskLength));
+ }
+
public int getInt() {
return rawValue;
}
private volatile byte[] bytesCache = null;
+ @Override
public byte[] getBytes() {
if (bytesCache == null) {
synchronized (this) {
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
index 9b60c6a..b6dc1b9 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
@@ -1,5 +1,9 @@
package org.projectfloodlight.openflow.types;
+import javax.annotation.Nonnull;
+
+import com.google.common.base.Preconditions;
+
public class IPv4AddressWithMask extends IPAddressWithMask<IPv4Address> {
public final static IPv4AddressWithMask NONE = of(IPv4Address.NONE, IPv4Address.NONE);
@@ -17,27 +21,77 @@
return IPVersion.IPv4;
}
- public static IPv4AddressWithMask of(int rawValue, int rawMask) {
+ /**
+ * Returns an {@code IPv4AddressWithMask} object that represents the given
+ * raw IP address masked by the given raw IP address mask.
+ *
+ * @param rawValue the raw IP address to be masked
+ * @param rawMask the raw IP address mask
+ * @return an {@code IPv4AddressWithMask} object that represents
+ * the given raw IP address masked by the given raw IP
+ * address mask
+ * @deprecated replaced by {@link IPv4Address#of(int)} and
+ * {@link IPv4Address#withMask(IPv4Address), e.g. <code>
+ * IPv4Address.of(int).withMask(IPv4Address.of(int))
+ * </code>
+ */
+ @Nonnull
+ @Deprecated
+ public static IPv4AddressWithMask of(final int rawValue, final int rawMask) {
return new IPv4AddressWithMask(rawValue, rawMask);
}
- public static IPv4AddressWithMask of(IPv4Address value, IPv4Address mask) {
- if (value == null) {
- throw new NullPointerException("Value must not be null");
- }
- if (mask == null) {
- throw new NullPointerException("Mask must not be null");
- }
+ /**
+ * Returns an {@code IPv4AddressWithMask} object that represents the given
+ * IP address masked by the given IP address mask. Both arguments are given
+ * as {@code IPv4Address} objects.
+ *
+ * @param value the IP address to be masked
+ * @param mask the IP address mask
+ * @return an {@code IPv4AddressWithMask} object that represents
+ * the given IP address masked by the given IP address mask
+ * @throws NullPointerException if any of the given {@code IPv4Address}
+ * objects were {@code null}
+ */
+ @Nonnull
+ public static IPv4AddressWithMask of(
+ @Nonnull final IPv4Address value,
+ @Nonnull final IPv4Address mask) {
+ Preconditions.checkNotNull(value, "value must not be null");
+ Preconditions.checkNotNull(mask, "mask must not be null");
+
return new IPv4AddressWithMask(value, mask);
}
- public static IPv4AddressWithMask of(final String string) {
- if (string == null) {
- throw new NullPointerException("String must not be null");
- }
+ /**
+ * Returns an {@code IPv4AddressWithMask} object that corresponds to
+ * the given string in CIDR notation or other acceptable notations.
+ * <p>
+ * The following notations are accepted.
+ * <table><tr>
+ * <th>Notation</th><th>Example</th><th>Notes</th>
+ * </tr><tr>
+ * <td>IPv4 address only</td><td>{@code 1.2.3.4}</td><td>The subnet mask of
+ * prefix length 32 (i.e. {@code 255.255.255.255}) is assumed.</td>
+ * </tr><tr>
+ * <td>IPv4 address/mask</td><td>{@code 1.2.3.4/255.255.255.0}</td>
+ * </tr><tr>
+ * <td>CIDR notation</td><td>{@code 1.2.3.4/24}</td>
+ * </tr></table>
+ *
+ * @param string the string in acceptable notations
+ * @return an {@code IPv4AddressWithMask} object that corresponds to
+ * the given string in acceptable notations
+ * @throws NullPointerException if the given string was {@code null}
+ * @throws IllegalArgumentException if the given string was malformed
+ */
+ @Nonnull
+ public static IPv4AddressWithMask of(@Nonnull final String string) {
+ Preconditions.checkNotNull(string, "string must not be null");
+
int slashPos;
String ip = string;
- int maskBits = 32;
+ int cidrMaskLength = 32;
IPv4Address maskAddress = null;
// Read mask suffix
@@ -52,14 +106,11 @@
maskAddress = IPv4Address.of(suffix);
} else {
// CIDR Suffix
- maskBits = Integer.parseInt(suffix);
+ cidrMaskLength = Integer.parseInt(suffix);
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("IP Address not well formed: " + string);
}
- if (maskBits < 0 || maskBits > 32) {
- throw new IllegalArgumentException("IP Address not well formed: " + string);
- }
}
// Read IP
@@ -68,17 +119,21 @@
if (maskAddress != null) {
// Full address mask
return IPv4AddressWithMask.of(ipv4, maskAddress);
- } else if (maskBits == 32) {
- // No mask
- return IPv4AddressWithMask.of(ipv4, IPv4Address.NO_MASK);
- } else if (maskBits == 0) {
- // No mask
- return IPv4AddressWithMask.of(ipv4, IPv4Address.FULL_MASK);
} else {
- // With mask
- int mask = (-1) << (32 - maskBits);
- return IPv4AddressWithMask.of(ipv4, IPv4Address.of(mask));
+ return IPv4AddressWithMask.of(
+ ipv4, IPv4Address.ofCidrMaskLength(cidrMaskLength));
}
}
+ @Override
+ public boolean contains(IPAddress<?> ip) {
+ Preconditions.checkNotNull(ip, "ip must not be null");
+
+ if(ip.getIpVersion() == IPVersion.IPv4) {
+ IPv4Address ipv4 = (IPv4Address) ip;
+ return this.matches(ipv4);
+ }
+
+ return false;
+ }
}
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
index 83fb31a..471d0fb 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
@@ -1,5 +1,7 @@
package org.projectfloodlight.openflow.types;
+import java.net.Inet6Address;
+import java.net.InetAddress;
import java.util.Arrays;
import java.util.regex.Pattern;
@@ -8,6 +10,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.base.Preconditions;
import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Longs;
@@ -102,19 +105,17 @@
@Override
public IPv6Address and(IPv6Address other) {
- if (other == null) {
- throw new NullPointerException("Other IP Address must not be null");
- }
- IPv6Address otherIp = (IPv6Address) other;
+ Preconditions.checkNotNull(other, "other must not be null");
+
+ IPv6Address otherIp = other;
return IPv6Address.of((raw1 & otherIp.raw1), (raw2 & otherIp.raw2));
}
@Override
public IPv6Address or(IPv6Address other) {
- if (other == null) {
- throw new NullPointerException("Other IP Address must not be null");
- }
- IPv6Address otherIp = (IPv6Address) other;
+ Preconditions.checkNotNull(other, "other must not be null");
+
+ IPv6Address otherIp = other;
return IPv6Address.of((raw1 | otherIp.raw1), (raw2 | otherIp.raw2));
}
@@ -123,10 +124,27 @@
return IPv6Address.of(~raw1, ~raw2);
}
- public static IPv6Address of(final byte[] address) {
- if (address == null) {
- throw new NullPointerException("Address must not be null");
- }
+ /**
+ * Returns an {@code IPv6Address} object that represents the given
+ * IP address. The argument is in network byte order: the highest
+ * order byte of the address is in {@code address[0]}.
+ * <p>
+ * The address byte array must be 16 bytes long (128 bits long).
+ * <p>
+ * Similar to {@link InetAddress#getByAddress(byte[])}.
+ *
+ * @param address the raw IP address in network byte order
+ * @return an {@code IPv6Address} object that represents the given
+ * raw IP address
+ * @throws NullPointerException if the given address was {@code null}
+ * @throws IllegalArgumentException if the given address was of an invalid
+ * byte array length
+ * @see InetAddress#getByAddress(byte[])
+ */
+ @Nonnull
+ public static IPv6Address of(@Nonnull final byte[] address) {
+ Preconditions.checkNotNull(address, "address must not be null");
+
if (address.length != LENGTH) {
throw new IllegalArgumentException(
"Invalid byte array length for IPv6 address: " + address.length);
@@ -171,25 +189,30 @@
private final static Pattern colonPattern = Pattern.compile(":");
- /** parse an IPv6Address from its conventional string representation.
- * <p>
- * Expects up to 8 groups of 16-bit hex words seperated by colons
- * (e.g., 2001:db8:85a3:8d3:1319:8a2e:370:7348).
- * <p>
- * Supports zero compression (e.g., 2001:db8::7348).
- * Does <b>not</b> currently support embedding a dotted-quad IPv4 address
- * into the IPv6 address (e.g., 2001:db8::192.168.0.1).
+ /**
+ * Returns an {@code IPv6Address} object that represents the given
+ * IP address. The argument is in the conventional string representation
+ * of IPv6 addresses.
+ * <p>
+ * Expects up to 8 groups of 16-bit hex words seperated by colons
+ * (e.g., 2001:db8:85a3:8d3:1319:8a2e:370:7348).
+ * <p>
+ * Supports zero compression (e.g., 2001:db8::7348).
+ * Does <b>not</b> currently support embedding a dotted-quad IPv4 address
+ * into the IPv6 address (e.g., 2001:db8::192.168.0.1).
*
- * @param string a string representation of an IPv6 address
- * @return the parsed IPv6 address
- * @throws NullPointerException if string is null
- * @throws IllegalArgumentException if string is not a valid IPv6Address
+ * @param string the IP address in the conventional string representation
+ * of IPv6 addresses
+ * @return an {@code IPv6Address} object that represents the given
+ * IP address
+ * @throws NullPointerException if the given string was {@code null}
+ * @throws IllegalArgumentException if the given string was not a valid
+ * IPv6 address
*/
@Nonnull
public static IPv6Address of(@Nonnull final String string) throws IllegalArgumentException {
- if (string == null) {
- throw new NullPointerException("String must not be null");
- }
+ Preconditions.checkNotNull(string, "string must not be null");
+
IPv6Builder builder = new IPv6Builder();
String[] parts = colonPattern.split(string, -1);
@@ -242,19 +265,104 @@
return builder.getIPv6();
}
- /** construct an IPv6 adress from two 64 bit integers representing the first and
- * second 8-byte blocks of the address.
+ /**
+ * Returns an {@code IPv6Address} object that represents the given
+ * IP address. The arguments are the two 64-bit integers representing
+ * the first (higher-order) and second (lower-order) 64-bit blocks
+ * of the IP address.
*
- * @param raw1 - the first 8 byte block of the address
- * @param raw2 - the second 8 byte block of the address
- * @return the constructed IPv6Address
+ * @param raw1 the first (higher-order) 64-bit block of the IP address
+ * @param raw2 the second (lower-order) 64-bit block of the IP address
+ * @return an {@code IPv6Address} object that represents the given
+ * raw IP address
*/
+ @Nonnull
public static IPv6Address of(final long raw1, final long raw2) {
if(raw1==NONE_VAL1 && raw2 == NONE_VAL2)
return NONE;
return new IPv6Address(raw1, raw2);
}
+ /**
+ * Returns an {@code IPv6Address} object that represents the given
+ * IP address. The argument is given as an {@code Inet6Address} object.
+ *
+ * @param address the IP address as an {@code Inet6Address} object
+ * @return an {@code IPv6Address} object that represents the
+ * given IP address
+ * @throws NullPointerException if the given {@code Inet6Address} was
+ * {@code null}
+ */
+ @Nonnull
+ public static IPv6Address of(@Nonnull final Inet6Address address) {
+ Preconditions.checkNotNull(address, "address must not be null");
+ return IPv6Address.of(address.getAddress());
+ }
+
+ /**
+ * Returns an {@code IPv6Address} object that represents the
+ * CIDR subnet mask of the given prefix length.
+ *
+ * @param cidrMaskLength the prefix length of the CIDR subnet mask
+ * (i.e. the number of leading one-bits),
+ * where {@code 0 <= cidrMaskLength <= 128}
+ * @return an {@code IPv6Address} object that represents the
+ * CIDR subnet mask of the given prefix length
+ * @throws IllegalArgumentException if the given prefix length was invalid
+ */
+ @Nonnull
+ public static IPv6Address ofCidrMaskLength(final int cidrMaskLength) {
+ Preconditions.checkArgument(
+ cidrMaskLength >= 0 && cidrMaskLength <= 128,
+ "Invalid IPv6 CIDR mask length: %s", cidrMaskLength);
+
+ if (cidrMaskLength == 128) {
+ return IPv6Address.NO_MASK;
+ } else if (cidrMaskLength == 0) {
+ return IPv6Address.FULL_MASK;
+ } else {
+ int shift1 = Math.min(cidrMaskLength, 64);
+ long raw1 = shift1 == 0 ? 0 : -1L << (64 - shift1);
+ int shift2 = Math.max(cidrMaskLength - 64, 0);
+ long raw2 = shift2 == 0 ? 0 : -1L << (64 - shift2);
+ return IPv6Address.of(raw1, raw2);
+ }
+ }
+
+ /**
+ * Returns an {@code IPv6AddressWithMask} object that represents this
+ * IP address masked by the given IP address mask.
+ *
+ * @param mask the {@code IPv6Address} object that represents the mask
+ * @return an {@code IPv6AddressWithMask} object that represents this
+ * IP address masked by the given mask
+ * @throws NullPointerException if the given mask was {@code null}
+ */
+ @Nonnull
+ @Override
+ public IPv6AddressWithMask withMask(@Nonnull final IPv6Address mask) {
+ return IPv6AddressWithMask.of(this, mask);
+ }
+
+ /**
+ * Returns an {@code IPv6AddressWithMask} object that represents this
+ * IP address masked by the CIDR subnet mask of the given prefix length.
+ *
+ * @param cidrMaskLength the prefix length of the CIDR subnet mask
+ * (i.e. the number of leading one-bits),
+ * where {@code 0 <= cidrMaskLength <= 128}
+ * @return an {@code IPv6AddressWithMask} object that
+ * represents this IP address masked by the CIDR
+ * subnet mask of the given prefix length
+ * @throws IllegalArgumentException if the given prefix length was invalid
+ * @see #ofCidrMaskLength(int)
+ */
+ @Nonnull
+ @Override
+ public IPv6AddressWithMask withMaskOfLength(final int cidrMaskLength) {
+ return this.withMask(IPv6Address.ofCidrMaskLength(cidrMaskLength));
+ }
+
private volatile byte[] bytesCache = null;
public byte[] getBytes() {
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
index 7259c7f..ee34923 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
@@ -1,7 +1,6 @@
package org.projectfloodlight.openflow.types;
-import java.math.BigInteger;
-import java.util.Arrays;
+import com.google.common.base.Preconditions;
public class IPv6AddressWithMask extends IPAddressWithMask<IPv6Address> {
public final static IPv6AddressWithMask NONE = of(IPv6Address.NONE, IPv6Address.NONE);
@@ -16,23 +15,17 @@
}
public static IPv6AddressWithMask of(IPv6Address value, IPv6Address mask) {
- if (value == null) {
- throw new NullPointerException("Value must not be null");
- }
- if (mask == null) {
- throw new NullPointerException("Mask must not be null");
- }
+ Preconditions.checkNotNull(value, "value must not be null");
+ Preconditions.checkNotNull(mask, "mask must not be null");
return new IPv6AddressWithMask(value, mask);
}
-
public static IPv6AddressWithMask of(final String string) {
- if (string == null) {
- throw new NullPointerException("String must not be null");
- }
+ Preconditions.checkNotNull(string, "string must not be null");
+
int slashPos;
String ip = string;
- int maskBits = 128;
+ int cidrMaskLength = 128;
IPv6Address maskAddress = null;
// Read mask suffix
@@ -47,14 +40,11 @@
maskAddress = IPv6Address.of(suffix);
} else {
// CIDR Suffix
- maskBits = Integer.parseInt(suffix);
+ cidrMaskLength = Integer.parseInt(suffix);
}
} catch (NumberFormatException e) {
throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
}
- if (maskBits < 0 || maskBits > 128) {
- throw new IllegalArgumentException("IPv6 Address not well formed: " + string);
- }
}
// Read IP
@@ -63,30 +53,21 @@
if (maskAddress != null) {
// Full address mask
return IPv6AddressWithMask.of(ipv6, maskAddress);
- } else if (maskBits == 128) {
- // No mask
- return IPv6AddressWithMask.of(ipv6, IPv6Address.NO_MASK);
- } else if (maskBits == 0) {
- // Entirely masked out
- return IPv6AddressWithMask.of(ipv6, IPv6Address.FULL_MASK);
- }else {
- // With mask
- BigInteger mask = BigInteger.ONE.negate().shiftLeft(128 - maskBits);
- byte[] maskBytesTemp = mask.toByteArray();
- byte[] maskBytes;
- if (maskBytesTemp.length < 16) {
- maskBytes = new byte[16];
- System.arraycopy(maskBytesTemp, 0, maskBytes, 16 - maskBytesTemp.length, maskBytesTemp.length);
- Arrays.fill(maskBytes, 0, 16 - maskBytesTemp.length, (byte)(0xFF));
- } else if (maskBytesTemp.length > 16) {
- maskBytes = new byte[16];
- System.arraycopy(maskBytesTemp, 0, maskBytes, 0, maskBytes.length);
- } else {
- maskBytes = maskBytesTemp;
- }
- return IPv6AddressWithMask.of(ipv6, IPv6Address.of(maskBytes));
+ } else {
+ return IPv6AddressWithMask.of(ipv6,
+ IPv6Address.ofCidrMaskLength(cidrMaskLength));
}
}
+ @Override
+ public boolean contains(IPAddress<?> ip) {
+ Preconditions.checkNotNull(ip, "ip must not be null");
+ if(ip.getIpVersion() == IPVersion.IPv6) {
+ IPv6Address ipv6 = (IPv6Address) ip;
+ return this.matches(ipv6);
+ }
+
+ return false;
+ }
}
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java
index 35ef846..ddf4faa 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U128.java
@@ -123,15 +123,100 @@
}
@Override
+ public U128 add(U128 other) {
+ long newRaw2 = this.raw2 + other.raw2;
+ long newRaw1 = this.raw1 + other.raw1;
+ if(UnsignedLongs.compare(newRaw2, this.raw2) < 0) {
+ // raw2 overflow
+ newRaw1+=1;
+ }
+ return U128.of(newRaw1, newRaw2);
+ }
+
+ @Override
+ public U128 subtract(U128 other) {
+ long newRaw2 = this.raw2 - other.raw2;
+ long newRaw1 = this.raw1 - other.raw1;
+ if(UnsignedLongs.compare(this.raw2, other.raw2) < 0) {
+ newRaw1 -= 1;
+ }
+ return U128.of(newRaw1, newRaw2);
+ }
+ @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))
- );
+ public HashValue.Builder<U128> builder() {
+ return new U128Builder(raw1, raw2);
}
+
+ static class U128Builder implements HashValue.Builder<U128> {
+ private long raw1, raw2;
+
+ public U128Builder(long raw1, long raw2) {
+ this.raw1 = raw1;
+ this.raw2 = raw2;
+ }
+
+ @Override
+ public Builder<U128> add(U128 other) {
+ raw2 += other.raw2;
+ raw1 += other.raw1;
+ if(UnsignedLongs.compare(raw2, other.raw2) < 0) {
+ // raw2 overflow
+ raw1+=1;
+ }
+ return this;
+ }
+
+ @Override
+ public Builder<U128> subtract(
+ U128 other) {
+ if(UnsignedLongs.compare(this.raw2, other.raw2) >= 0) {
+ raw2 -= other.raw2;
+ raw1 -= other.raw1;
+ } else {
+ // raw2 overflow
+ raw2 -= other.raw2;
+ raw1 = this.raw1 - other.raw1 - 1;
+ }
+ return this;
+ }
+
+ @Override
+ public Builder<U128> invert() {
+ raw1 = ~raw1;
+ raw2 = ~raw2;
+ return this;
+ }
+
+ @Override
+ public Builder<U128> or(U128 other) {
+ raw1 |= other.raw1;
+ raw2 |= other.raw2;
+ return this;
+ }
+
+ @Override
+ public Builder<U128> and(U128 other) {
+ raw1 &= other.raw1;
+ raw2 &= other.raw2;
+ return this;
+ }
+
+ @Override
+ public Builder<U128> xor(U128 other) {
+ raw1 ^= other.raw1;
+ raw2 ^= other.raw2;
+ return this;
+ }
+
+ @Override
+ public U128 build() {
+ return U128.of(raw1, raw2);
+ }
+ }
+
}
diff --git a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java
index 1353b42..f15544f 100644
--- a/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java
+++ b/of/lib/src/main/java/org/projectfloodlight/openflow/types/U64.java
@@ -151,6 +151,16 @@
return U64.of(raw ^ other.raw);
}
+ @Override
+ public U64 add(U64 other) {
+ return U64.of(this.raw + other.raw);
+ }
+
+ @Override
+ public U64 subtract(U64 other) {
+ return U64.of(this.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.
@@ -160,11 +170,6 @@
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> {
@@ -174,5 +179,59 @@
}
}
+ @Override
+ public HashValue.Builder<U64> builder() {
+ return new U64Builder(raw);
+ }
+
+ static class U64Builder implements Builder<U64> {
+ long raw;
+
+ public U64Builder(long raw) {
+ this.raw = raw;
+ }
+
+ @Override
+ public Builder<U64> add(U64 other) {
+ raw += other.raw;
+ return this;
+ }
+
+ @Override
+ public Builder<U64> subtract(
+ U64 other) {
+ raw -= other.raw;
+ return this;
+ }
+
+ @Override
+ public Builder<U64> invert() {
+ raw = ~raw;
+ return this;
+ }
+
+ @Override
+ public Builder<U64> or(U64 other) {
+ raw |= other.raw;
+ return this;
+ }
+
+ @Override
+ public Builder<U64> and(U64 other) {
+ raw &= other.raw;
+ return this;
+ }
+
+ @Override
+ public Builder<U64> xor(U64 other) {
+ raw ^= other.raw;
+ return this;
+ }
+
+ @Override
+ public U64 build() {
+ return U64.of(raw);
+ }
+ }
}
diff --git a/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java b/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
index 865df75..2ba4528 100644
--- a/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
+++ b/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
@@ -1,8 +1,12 @@
package org.projectfloodlight.openflow.types;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.net.InetAddress;
import java.net.UnknownHostException;
import org.junit.Test;
@@ -29,7 +33,7 @@
// expected
}
try {
- IPAddress.of(null);
+ IPAddress.of((String) null);
fail("Should have thrown NullPointerException");
} catch (NullPointerException e) {
assertNotNull(e.getMessage());
@@ -41,7 +45,7 @@
assertNotNull(e.getMessage());
}
try {
- IPAddress.of(null);
+ IPAddress.of((String) null);
fail("Should have thrown NullPointerException");
} catch (NullPointerException e) {
assertNotNull(e.getMessage());
@@ -55,6 +59,29 @@
}
@Test
+ public void testOfString() {
+ IPAddress<?> ip0 = IPAddress.of("1.2.3.4");
+ IPAddress<?> ip1 = IPAddress.of("abcd::1234");
+ assertTrue(ip0 instanceof IPv4Address);
+ assertTrue(ip1 instanceof IPv6Address);
+ assertEquals(ip0, IPv4Address.of("1.2.3.4"));
+ assertEquals(ip1, IPv6Address.of("abcd::1234"));
+ }
+
+ @Test
+ public void testOfInetAddress() throws Exception {
+ InetAddress ia0 = InetAddress.getByName("192.168.1.123");
+ InetAddress ia1 = InetAddress.getByName("fd00::4321");
+ IPAddress<?> ip0 = IPAddress.of(ia0);
+ IPAddress<?> ip1 = IPAddress.of(ia1);
+ assertTrue(ip0 instanceof IPv4Address);
+ assertTrue(ip1 instanceof IPv6Address);
+ assertEquals(ip0, IPv4Address.of(ia0));
+ assertEquals(ip1, IPv6Address.of(ia1));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
public void testFromInetAddressException() throws UnknownHostException {
try {
IPAddress.fromInetAddress(null);
@@ -64,4 +91,43 @@
}
}
+ @Test
+ public void testContains() {
+
+ // Test IPv4 Mask
+ IPAddressWithMask<?> mask = IPAddressWithMask.of("1.2.3.4/24");
+
+ IPAddress<?> validIp = IPAddress.of("1.2.3.5");
+ assertTrue(mask.contains(validIp));
+
+ IPAddress<?> invalidIp = IPAddress.of("1.2.5.5");
+ assertFalse(mask.contains(invalidIp));
+
+ IPAddress<?> invalidIpv6 = IPAddress.of("10:10::ffff");
+ assertFalse(mask.contains(invalidIpv6));
+
+ // Test IPv6 Mask
+ mask = IPAddressWithMask.of("10:10::1/112");
+
+ validIp = IPAddress.of("10:10::f");
+ assertTrue(mask.contains(validIp));
+
+ invalidIp = IPAddress.of("11:10::f");
+ assertFalse(mask.contains(invalidIp));
+
+ IPAddress<?> invalidIpv4 = IPAddress.of("10.0.0.1");
+ assertFalse(mask.contains(invalidIpv4));
+ }
+
+ @Test
+ public void testContainsException() {
+ try {
+ IPAddressWithMask<?> mask = IPAddressWithMask.of("1.2.3.4/24");
+ mask.contains(null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
}
diff --git a/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java b/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
index a57b42a..0716b50 100644
--- a/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
+++ b/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
@@ -9,6 +9,9 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+
import org.hamcrest.CoreMatchers;
import org.jboss.netty.buffer.ChannelBuffers;
import org.junit.Test;
@@ -224,6 +227,83 @@
}
@Test
+ public void testOfCidrMaskLength() {
+ for (int i = 0; i <= 32; i++) {
+ assertEquals(IPv4Address.ofCidrMaskLength(i).asCidrMaskLength(), i);
+ }
+
+ assertEquals(IPv4Address.ofCidrMaskLength(0).getInt(), 0x0000_0000);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(1).getInt(), 0x8000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(2).getInt(), 0xC000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(3).getInt(), 0xE000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(4).getInt(), 0xF000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(5).getInt(), 0xF800_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(6).getInt(), 0xFC00_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(7).getInt(), 0xFE00_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(8).getInt(), 0xFF00_0000);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(9).getInt(), 0xFF80_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(10).getInt(), 0xFFC0_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(11).getInt(), 0xFFE0_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(12).getInt(), 0xFFF0_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(13).getInt(), 0xFFF8_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(14).getInt(), 0xFFFC_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(15).getInt(), 0xFFFE_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(16).getInt(), 0xFFFF_0000);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(17).getInt(), 0xFFFF_8000);
+ assertEquals(IPv4Address.ofCidrMaskLength(18).getInt(), 0xFFFF_C000);
+ assertEquals(IPv4Address.ofCidrMaskLength(19).getInt(), 0xFFFF_E000);
+ assertEquals(IPv4Address.ofCidrMaskLength(20).getInt(), 0xFFFF_F000);
+ assertEquals(IPv4Address.ofCidrMaskLength(21).getInt(), 0xFFFF_F800);
+ assertEquals(IPv4Address.ofCidrMaskLength(22).getInt(), 0xFFFF_FC00);
+ assertEquals(IPv4Address.ofCidrMaskLength(23).getInt(), 0xFFFF_FE00);
+ assertEquals(IPv4Address.ofCidrMaskLength(24).getInt(), 0xFFFF_FF00);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(25).getInt(), 0xFFFF_FF80);
+ assertEquals(IPv4Address.ofCidrMaskLength(26).getInt(), 0xFFFF_FFC0);
+ assertEquals(IPv4Address.ofCidrMaskLength(27).getInt(), 0xFFFF_FFE0);
+ assertEquals(IPv4Address.ofCidrMaskLength(28).getInt(), 0xFFFF_FFF0);
+ assertEquals(IPv4Address.ofCidrMaskLength(29).getInt(), 0xFFFF_FFF8);
+ assertEquals(IPv4Address.ofCidrMaskLength(30).getInt(), 0xFFFF_FFFC);
+ assertEquals(IPv4Address.ofCidrMaskLength(31).getInt(), 0xFFFF_FFFE);
+ assertEquals(IPv4Address.ofCidrMaskLength(32).getInt(), 0xFFFF_FFFF);
+ }
+
+ @Test
+ public void testWithMask() throws Exception {
+ // Sanity tests for the withMask*() syntactic sugars
+
+ IPv4Address original = IPv4Address.of("192.168.1.101");
+ IPv4Address expectedValue = IPv4Address.of("192.168.1.0");
+ IPv4Address expectedMask = IPv4Address.of("255.255.255.0");
+
+ IPv4AddressWithMask v;
+
+ v = original.withMask(IPv4Address.of(new byte[] {-1, -1, -1, 0}));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv4Address.of(0xFFFF_FF00));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv4Address.of("255.255.255.0"));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ Inet4Address i4a = (Inet4Address) InetAddress.getByName("255.255.255.0");
+ v = original.withMask(IPv4Address.of(i4a));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMaskOfLength(24);
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+ }
+
+ @Test
public void testReadFrom() throws OFParseError {
for(int i=0; i < testAddresses.length; i++ ) {
IPv4Address ip = IPv4Address.read4Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
@@ -367,5 +447,17 @@
} catch (IllegalArgumentException e) {
assertNotNull(e.getMessage());
}
+ try {
+ IPv4Address.ofCidrMaskLength(-1);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv4Address.ofCidrMaskLength(33);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
}
}
diff --git a/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java b/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
index 6963c21..a397c2a 100644
--- a/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
+++ b/of/lib/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
@@ -198,6 +198,79 @@
}
}
+ private static void testOfCidrMaskLengthHelper(
+ int cidrMaskLength, String ipStr) throws UnknownHostException {
+ byte[] ba0 = IPv6Address.ofCidrMaskLength(cidrMaskLength).getBytes();
+ byte[] ba1 = Inet6Address.getByName(ipStr).getAddress();
+ assertArrayEquals(ba0, ba1);
+ }
+
+ @Test
+ public void testOfCidrMaskLength() throws UnknownHostException {
+ for (int i = 0; i <= 128; i++) {
+ assertTrue(IPv6Address.ofCidrMaskLength(i).isCidrMask());
+ assertEquals(IPv6Address.ofCidrMaskLength(i).asCidrMaskLength(), i);
+ }
+ testOfCidrMaskLengthHelper(0, "::");
+ testOfCidrMaskLengthHelper(1, "8000::");
+ testOfCidrMaskLengthHelper(2, "c000::");
+ testOfCidrMaskLengthHelper(8, "ff00::");
+ testOfCidrMaskLengthHelper(16, "ffff::");
+ testOfCidrMaskLengthHelper(17, "ffff:8000::");
+ testOfCidrMaskLengthHelper(31, "ffff:fffe::");
+ testOfCidrMaskLengthHelper(32, "ffff:ffff::");
+ testOfCidrMaskLengthHelper(33, "ffff:ffff:8000::");
+ testOfCidrMaskLengthHelper(46, "ffff:ffff:fffc::");
+ testOfCidrMaskLengthHelper(48, "ffff:ffff:ffff::");
+ testOfCidrMaskLengthHelper(55, "ffff:ffff:ffff:fe00::");
+ testOfCidrMaskLengthHelper(56, "ffff:ffff:ffff:ff00::");
+ testOfCidrMaskLengthHelper(59, "ffff:ffff:ffff:ffe0::");
+ testOfCidrMaskLengthHelper(63, "ffff:ffff:ffff:fffe::");
+ testOfCidrMaskLengthHelper(64, "ffff:ffff:ffff:ffff::");
+ testOfCidrMaskLengthHelper(65, "ffff:ffff:ffff:ffff:8000::");
+ testOfCidrMaskLengthHelper(67, "ffff:ffff:ffff:ffff:e000::");
+ testOfCidrMaskLengthHelper(100, "ffff:ffff:ffff:ffff:ffff:ffff:f000::");
+ testOfCidrMaskLengthHelper(101, "ffff:ffff:ffff:ffff:ffff:ffff:f800::");
+ testOfCidrMaskLengthHelper(126, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
+ testOfCidrMaskLengthHelper(127, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe");
+ testOfCidrMaskLengthHelper(128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ }
+
+ @Test
+ public void testWithMask() throws Exception {
+ // Sanity tests for the withMask*() syntactic sugars
+
+ IPv6Address original = IPv6Address.of("fd12:3456:ABCD:7890::1");
+ IPv6Address expectedValue = IPv6Address.of("fd12:3456:ABCD::");
+ IPv6Address expectedMask = IPv6Address.of("ffff:ffff:ffff::");
+
+ IPv6AddressWithMask v;
+
+ v = original.withMask(IPv6Address.of(new byte[] {
+ -1, -1, -1, -1, -1, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv6Address.of(
+ 0xFFFF_FFFF_FFFF_0000L, 0x0000_0000_0000_0000L));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv6Address.of("ffff:ffff:ffff::"));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ Inet6Address i6a = (Inet6Address) InetAddress.getByName("ffff:ffff:ffff::");
+ v = original.withMask(IPv6Address.of(i6a));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMaskOfLength(48);
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+ }
+
@Test
public void testReadFrom() throws OFParseError, UnknownHostException {
for(int i=0; i < testStrings.length; i++ ) {
@@ -313,5 +386,17 @@
} catch (IllegalArgumentException e) {
assertNotNull(e.getMessage());
}
+ try {
+ IPv6Address.ofCidrMaskLength(-1);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv6Address.ofCidrMaskLength(129);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
}
}
diff --git a/of/lib/src/test/java/org/projectfloodlight/openflow/types/U128Test.java b/of/lib/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
index fb5cd23..81d9d7f 100644
--- a/of/lib/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
+++ b/of/lib/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
@@ -9,7 +9,12 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.text.MessageFormat;
+
import org.hamcrest.Matchers;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Before;
import org.junit.Test;
import com.google.common.hash.HashCode;
@@ -17,6 +22,9 @@
import com.google.common.hash.Hashing;
public class U128Test {
+ private Triple[] triples;
+
+
@Test
public void testPositiveRaws() {
assertThat(U128.of(0, 0).getMsb(), equalTo(0L));
@@ -27,6 +35,22 @@
}
@Test
+ public void testReadBytes() {
+ ChannelBuffer empty = ChannelBuffers.wrappedBuffer(new byte[16]);
+ U128 uEmpty = U128.read16Bytes(empty);
+ assertThat(uEmpty.getMsb(), equalTo(0L));
+ assertThat(uEmpty.getLsb(), equalTo(0L));
+
+ ChannelBuffer value = ChannelBuffers.wrappedBuffer(
+ new byte[] { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88,
+ (byte) 0x99, (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd,
+ (byte) 0xee, (byte) 0xff, 0x11 });
+ U128 uValue = U128.read16Bytes(value);
+ assertThat(uValue.getMsb(), equalTo(0x1122334455667788L));
+ assertThat(uValue.getLsb(), equalTo(0x99aabbccddeeff11L));
+ }
+
+ @Test
public void testPutTo() {
U128 h = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
U128 hSame = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
@@ -123,6 +147,80 @@
}
}
+ public static class Triple {
+ U128 a, b, c;
+
+ public Triple(U128 a, U128 b, U128 c) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ public static Triple of(U128 a, U128 b, U128 c) {
+ return new Triple(a, b, c);
+ }
+
+ public String msg(String string) {
+ return MessageFormat.format(string, a,b,c);
+ }
+ }
+
+ @Before
+ public void setup() {
+ U128 u0_0 = U128.of(0, 0);
+ U128 u0_1 = U128.of(0, 1);
+ U128 u1_0 = U128.of(1, 0);
+ U128 u1_1 = U128.of(1, 1);
+
+ U128 u0_2 = U128.of(0, 2);
+ U128 u2_0 = U128.of(2, 0);
+
+ U128 u0_f = U128.of(0, -1L);
+ U128 uf_0 = U128.of(-1L, 0);
+
+ triples = new Triple[] {
+ Triple.of(u0_0, u0_0, u0_0),
+ Triple.of(u0_0, u0_1, u0_1),
+ Triple.of(u0_0, u1_0, u1_0),
+ Triple.of(u0_1, u1_0, u1_1),
+
+ Triple.of(u0_1, u0_1, u0_2),
+ Triple.of(u1_0, u1_0, u2_0),
+
+ Triple.of(u0_1, u0_f, u1_0),
+
+ Triple.of(u0_1, u0_f, u1_0),
+ Triple.of(u0_f, u0_f, U128.of(1, 0xffff_ffff_ffff_fffeL)),
+ Triple.of(uf_0, u0_f, U128.of(-1, -1)),
+ Triple.of(uf_0, u1_0, U128.ZERO),
+
+ Triple.of(U128.of(0x1234_5678_9abc_def1L, 0x1234_5678_9abc_def1L),
+ U128.of(0xedcb_a987_6543_210eL, 0xedcb_a987_6543_210fL),
+ U128.ZERO)
+ };
+ }
+
+ @Test
+ public void testAddSubtract() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.add(t.b), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.add(t.a), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.subtract(t.a), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.subtract(t.b), equalTo(t.a));
+ }
+ }
+
+ @Test
+ public void testAddSubtractBuilder() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.builder().add(t.b).build(), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.builder().add(t.a).build(), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.builder().subtract(t.a).build(), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.builder().subtract(t.b).build(), equalTo(t.a));
+ }
+ }
@Test
public void testCompare() {
@@ -163,20 +261,25 @@
}
@Test
- public void testCombine() {
- long key = 0x1234567890abcdefL;
- long val = 0xdeafbeefdeadbeefL;
- U128 hkey = U128.of(key, key*2);
- U128 hVal = U128.of(val, val/2);
+ public void testBitwiseOperators() {
+ U128 one = U128.of(0x5, 0x8);
+ U128 two = U128.of(0x7, 0x3);
- 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));
+ assertThat(one.inverse(), equalTo(U128.of(0xfffffffffffffffaL, 0xfffffffffffffff7L)));
+ assertThat(one.and(two), equalTo(U128.of(0x5L, 0x0L)));
+ assertThat(one.or(two), equalTo(U128.of(0x7L, 0xbL)));
+ assertThat(one.xor(two), equalTo(U128.of(0x2L, 0xbL)));
+ }
- long mask8 = 0xFF00_0000_0000_0000L;
+ @Test
+ public void testBitwiseOperatorsBuilder() {
+ U128 one = U128.of(0x5, 0x8);
+ U128 two = U128.of(0x7, 0x3);
- assertThat(hkey.combineWithValue(hVal, 8), equalTo(U128.of(hkey.getMsb() & mask8 | hkey.getMsb() ^ hVal.getMsb() & ~mask8,
- hkey.getLsb() ^ hVal.getLsb() )));
+ assertThat(one.builder().invert().build(), equalTo(U128.of(0xfffffffffffffffaL, 0xfffffffffffffff7L)));
+ assertThat(one.builder().and(two).build(), equalTo(U128.of(0x5L, 0x0L)));
+ assertThat(one.builder().or(two).build(), equalTo(U128.of(0x7L, 0xbL)));
+ assertThat(one.builder().xor(two).build(), equalTo(U128.of(0x2L, 0xbL)));
}
}
diff --git a/of/lib/src/test/java/org/projectfloodlight/openflow/types/U64Test.java b/of/lib/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
index b0cca23..4066bf8 100644
--- a/of/lib/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
+++ b/of/lib/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
@@ -9,11 +9,15 @@
import static org.junit.Assert.fail;
import java.math.BigInteger;
+import java.text.MessageFormat;
+import org.junit.Before;
import org.junit.Test;
public class U64Test {
+ private Triple[] triples;
+
@Test
public void testPositiveRaws() {
for(long positive: new long[] { 0, 1, 100, Long.MAX_VALUE }) {
@@ -24,10 +28,10 @@
@Test
public void testNegativeRaws() {
- long minus_1 = 0xFFFF_FFFF_FFFF_FFFFL;
- assertEquals(minus_1, U64.ofRaw(minus_1).getValue());
- assertEquals(new BigInteger("FFFF_FFFF_FFFF_FFFF".replace("_", ""), 16), U64.ofRaw(minus_1).getBigInteger());
- assertEquals(new BigInteger("18446744073709551615"), U64.ofRaw(minus_1).getBigInteger());
+ long minu1 = 0xFFFF_FFFF_FFFF_FFFFL;
+ assertEquals(minu1, U64.ofRaw(minu1).getValue());
+ assertEquals(new BigInteger("FFFF_FFFF_FFFF_FFFF".replace("_", ""), 16), U64.ofRaw(minu1).getBigInteger());
+ assertEquals(new BigInteger("18446744073709551615"), U64.ofRaw(minu1).getBigInteger());
}
@Test
@@ -62,24 +66,6 @@
}
@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));
@@ -105,6 +91,76 @@
checkInvalidKeyBitSize(signedBitU, 64);
}
+ public static class Triple {
+ U64 a, b, c;
+
+ public Triple(U64 a, U64 b, U64 c) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ public static Triple of(U64 a, U64 b, U64 c) {
+ return new Triple(a, b, c);
+ }
+
+ public String msg(String string) {
+ return MessageFormat.format(string, a,b,c);
+ }
+ }
+
+ @Before
+ public void setup() {
+ U64 u0 = U64.of(0);
+ U64 u1 = U64.of(1);
+
+ U64 u2 = U64.of(2);
+ U64 u7f = U64.of(0x7fff_ffff_ffff_ffffL);
+ U64 u8 = U64.of(0x8000_0000_0000_0000L);
+
+ U64 uf = U64.of(-1L);
+
+ triples = new Triple[] {
+ Triple.of(u0, u0, u0),
+ Triple.of(u0, u1, u1),
+
+ Triple.of(u1, u1, u2),
+
+ Triple.of(u1, uf, u0),
+
+ Triple.of(uf, uf, U64.of(0xffff_ffff_ffff_fffeL)),
+ Triple.of(u0, uf, uf),
+
+ Triple.of(u7f, u1, u8),
+
+ Triple.of(U64.of(0x1234_5678_9abc_def1L),
+ U64.of(0xedcb_a987_6543_210fL),
+ U64.ZERO)
+ };
+ }
+
+ @Test
+ public void testAddSubtract() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.add(t.b), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.add(t.a), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.subtract(t.a), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.subtract(t.b), equalTo(t.a));
+ }
+ }
+
+ @Test
+ public void testAddSubtractBuilder() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.builder().add(t.b).build(), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.builder().add(t.a).build(), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.builder().subtract(t.a).build(), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.builder().subtract(t.b).build(), equalTo(t.a));
+ }
+ }
+
private void
checkInvalidKeyBitSize(U64 u, int prefixBit) {
try {
@@ -115,4 +171,25 @@
}
}
+ @Test
+ public void testBitwiseOperators() {
+ U64 notPi = U64.of(0x3141_5926_5358_9793L);
+ U64 notE = U64.of(0x2718_2818_8459_4523L);
+
+ assertThat(notPi.inverse(), equalTo(U64.of(0xcebe_a6d9_aca7_686cL)));
+ assertThat(notPi.and(notE), equalTo(U64.of(0x2100_0800_0058_0503L)));
+ assertThat(notPi.or(notE), equalTo(U64.of(0x3759_793e_d759_d7b3L)));
+ assertThat(notPi.xor(notE), equalTo(U64.of(0x1659_713e_d701_d2b0L)));
+ }
+
+ @Test
+ public void testBitwiseOperatorsBuilder() {
+ U64 notPi = U64.of(0x3141_5926_5358_9793L);
+ U64 notE = U64.of(0x2718_2818_8459_4523L);
+
+ assertThat(notPi.builder().invert().build(), equalTo(U64.of(0xcebe_a6d9_aca7_686cL)));
+ assertThat(notPi.builder().and(notE).build(), equalTo(U64.of(0x2100_0800_0058_0503L)));
+ assertThat(notPi.builder().or(notE).build(), equalTo(U64.of(0x3759_793e_d759_d7b3L)));
+ assertThat(notPi.builder().xor(notE).build(), equalTo(U64.of(0x1659_713e_d701_d2b0L)));
+ }
}