aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java')
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java303
1 files changed, 303 insertions, 0 deletions
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
new file mode 100644
index 00000000..14d07fed
--- /dev/null
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onlab.packet;
+
+import java.util.Objects;
+
+/**
+ * A class representing an IP prefix. A prefix consists of an IP address and
+ * a subnet mask.
+ * This class is immutable.
+ * <p>
+ * NOTE: The stored IP address in the result IP prefix is masked to
+ * contain zeroes in all bits after the prefix length.
+ * </p>
+ */
+public class IpPrefix {
+ // Maximum network mask length
+ public static final int MAX_INET_MASK_LENGTH = IpAddress.INET_BIT_LENGTH;
+ public static final int MAX_INET6_MASK_LENGTH = IpAddress.INET6_BIT_LENGTH;
+
+ private final IpAddress address;
+ private final short prefixLength;
+
+ /**
+ * Constructor for given IP address, and a prefix length.
+ *
+ * @param address the IP address
+ * @param prefixLength the prefix length
+ * @throws IllegalArgumentException if the prefix length value is invalid
+ */
+ protected IpPrefix(IpAddress address, int prefixLength) {
+ checkPrefixLength(address.version(), prefixLength);
+ this.address = IpAddress.makeMaskedAddress(address, prefixLength);
+ this.prefixLength = (short) prefixLength;
+ }
+
+ /**
+ * Returns the IP version of the prefix.
+ *
+ * @return the IP version of the prefix
+ */
+ public IpAddress.Version version() {
+ return address.version();
+ }
+
+ /**
+ * Tests whether the IP version of this prefix is IPv4.
+ *
+ * @return true if the IP version of this prefix is IPv4, otherwise false.
+ */
+ public boolean isIp4() {
+ return address.isIp4();
+ }
+
+ /**
+ * Tests whether the IP version of this prefix is IPv6.
+ *
+ * @return true if the IP version of this prefix is IPv6, otherwise false.
+ */
+ public boolean isIp6() {
+ return address.isIp6();
+ }
+
+ /**
+ * Returns the IP address value of the prefix.
+ *
+ * @return the IP address value of the prefix
+ */
+ public IpAddress address() {
+ return address;
+ }
+
+ /**
+ * Returns the IP address prefix length.
+ *
+ * @return the IP address prefix length
+ */
+ public int prefixLength() {
+ return prefixLength;
+ }
+
+ /**
+ * Gets the {@link Ip4Prefix} view of the IP prefix.
+ *
+ * @return the {@link Ip4Prefix} view of the IP prefix if it is IPv4,
+ * otherwise null
+ */
+ public Ip4Prefix getIp4Prefix() {
+ if (!isIp4()) {
+ return null;
+ }
+
+ // Return this object itself if it is already instance of Ip4Prefix
+ if (this instanceof Ip4Prefix) {
+ return (Ip4Prefix) this;
+ }
+ return Ip4Prefix.valueOf(address.getIp4Address(), prefixLength);
+ }
+
+ /**
+ * Gets the {@link Ip6Prefix} view of the IP prefix.
+ *
+ * @return the {@link Ip6Prefix} view of the IP prefix if it is IPv6,
+ * otherwise null
+ */
+ public Ip6Prefix getIp6Prefix() {
+ if (!isIp6()) {
+ return null;
+ }
+
+ // Return this object itself if it is already instance of Ip6Prefix
+ if (this instanceof Ip6Prefix) {
+ return (Ip6Prefix) this;
+ }
+ return Ip6Prefix.valueOf(address.getIp6Address(), prefixLength);
+ }
+
+ /**
+ * Converts an integer and a prefix length into an IPv4 prefix.
+ *
+ * @param address an integer representing the IPv4 address
+ * @param prefixLength the prefix length
+ * @return an IP prefix
+ * @throws IllegalArgumentException if the prefix length value is invalid
+ */
+ public static IpPrefix valueOf(int address, int prefixLength) {
+ return new IpPrefix(IpAddress.valueOf(address), prefixLength);
+ }
+
+ /**
+ * Converts a byte array and a prefix length into an IP prefix.
+ *
+ * @param version the IP address version
+ * @param address the IP address value stored in network byte order
+ * @param prefixLength the prefix length
+ * @return an IP prefix
+ * @throws IllegalArgumentException if the prefix length value is invalid
+ */
+ public static IpPrefix valueOf(IpAddress.Version version, byte[] address,
+ int prefixLength) {
+ return new IpPrefix(IpAddress.valueOf(version, address), prefixLength);
+ }
+
+ /**
+ * Converts an IP address and a prefix length into an IP prefix.
+ *
+ * @param address the IP address
+ * @param prefixLength the prefix length
+ * @return an IP prefix
+ * @throws IllegalArgumentException if the prefix length value is invalid
+ */
+ public static IpPrefix valueOf(IpAddress address, int prefixLength) {
+ return new IpPrefix(address, prefixLength);
+ }
+
+ /**
+ * Converts a CIDR (slash) notation string (e.g., "10.1.0.0/16" or
+ * "1111:2222::/64") into an IP prefix.
+ *
+ * @param address an IP prefix in string form (e.g. "10.1.0.0/16" or
+ * "1111:2222::/64")
+ * @return an IP prefix
+ * @throws IllegalArgumentException if the arguments are invalid
+ */
+ public static IpPrefix valueOf(String address) {
+ final String[] parts = address.split("/");
+ if (parts.length != 2) {
+ String msg = "Malformed IP prefix string: " + address + ". " +
+ "Address must take form \"x.x.x.x/y\" or " +
+ "\"xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/y\"";
+ throw new IllegalArgumentException(msg);
+ }
+ IpAddress ipAddress = IpAddress.valueOf(parts[0]);
+ int prefixLength = Integer.parseInt(parts[1]);
+
+ return new IpPrefix(ipAddress, prefixLength);
+ }
+
+ /**
+ * Determines whether a given IP prefix is contained within this prefix.
+ *
+ * @param other the IP prefix to test
+ * @return true if the other IP prefix is contained in this prefix,
+ * otherwise false
+ */
+ public boolean contains(IpPrefix other) {
+ if (version() != other.version()) {
+ return false;
+ }
+
+ if (this.prefixLength > other.prefixLength) {
+ return false; // This prefix has smaller prefix size
+ }
+
+ //
+ // Mask the other address with my prefix length.
+ // If the other prefix is within this prefix, the masked address must
+ // be same as the address of this prefix.
+ //
+ IpAddress maskedAddr =
+ IpAddress.makeMaskedAddress(other.address, this.prefixLength);
+ return this.address.equals(maskedAddr);
+ }
+
+ /**
+ * Determines whether a given IP address is contained within this prefix.
+ *
+ * @param other the IP address to test
+ * @return true if the IP address is contained in this prefix, otherwise
+ * false
+ */
+ public boolean contains(IpAddress other) {
+ if (version() != other.version()) {
+ return false;
+ }
+
+ //
+ // Mask the other address with my prefix length.
+ // If the other prefix is within this prefix, the masked address must
+ // be same as the address of this prefix.
+ //
+ IpAddress maskedAddr =
+ IpAddress.makeMaskedAddress(other, this.prefixLength);
+ return this.address.equals(maskedAddr);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address, prefixLength);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if ((obj == null) || (!(obj instanceof IpPrefix))) {
+ return false;
+ }
+ IpPrefix other = (IpPrefix) obj;
+ return ((prefixLength == other.prefixLength) &&
+ address.equals(other.address));
+ }
+
+ @Override
+ /*
+ * (non-Javadoc)
+ * The format is "x.x.x.x/y" for IPv4 prefixes.
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append(address.toString());
+ builder.append("/");
+ builder.append(String.format("%d", prefixLength));
+ return builder.toString();
+ }
+
+ /**
+ * Checks whether the prefix length is valid.
+ *
+ * @param version the IP address version
+ * @param prefixLength the prefix length value to check
+ * @throws IllegalArgumentException if the prefix length value is invalid
+ */
+ private static void checkPrefixLength(IpAddress.Version version,
+ int prefixLength) {
+ int maxPrefixLen = 0;
+
+ switch (version) {
+ case INET:
+ maxPrefixLen = MAX_INET_MASK_LENGTH;
+ break;
+ case INET6:
+ maxPrefixLen = MAX_INET6_MASK_LENGTH;
+ break;
+ default:
+ String msg = "Invalid IP version " + version;
+ throw new IllegalArgumentException(msg);
+ }
+
+ if ((prefixLength < 0) || (prefixLength > maxPrefixLen)) {
+ String msg = "Invalid prefix length " + prefixLength + ". " +
+ "The value must be in the interval [0, " +
+ maxPrefixLen + "]";
+ throw new IllegalArgumentException(msg);
+ }
+ }
+}