Replaced IPv6 toString with more efficient local helper.
Change-Id: Ib53d7bdf64354efcace7facad740981fce19447c
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
index 5da34b4..5b39286 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
@@ -18,21 +18,20 @@
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
-import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Objects;
-
import com.google.common.net.InetAddresses;
import com.google.common.primitives.UnsignedBytes;
-import static com.google.common.base.Preconditions.checkState;
/**
* A class representing an IP address.
* This class is immutable.
*/
public class IpAddress implements Comparable<IpAddress> {
+ private static final int BIT_MASK = 0x000000ff;
+
// IP Versions
public enum Version { INET, INET6 };
@@ -353,20 +352,12 @@
switch (version) {
case INET:
return String.format("%d.%d.%d.%d", octets[0] & 0xff,
- octets[1] & 0xff,
- octets[2] & 0xff,
- octets[3] & 0xff);
+ octets[1] & 0xff,
+ octets[2] & 0xff,
+ octets[3] & 0xff);
case INET6:
default:
- InetAddress inetAddr = null;
- try {
- inetAddr = InetAddress.getByAddress(octets);
- } catch (UnknownHostException e) {
- // Should never happen
- checkState(false, "Internal error: Ip6Address.toString()");
- return "[Invalid IP Address]";
- }
- return InetAddresses.toAddrString(inetAddr);
+ return ipv6ToStringHelper();
}
}
@@ -494,4 +485,66 @@
}
return net;
}
+
+ /**
+ * Creates a string based on the IPv6 recommendations for canonical representations found here:
+ * https://tools.ietf.org/html/rfc5952#section-1.
+ * @return A properly formatted IPv6 canonical representation.
+ */
+ private String ipv6ToStringHelper() {
+ //Populate a buffer with the string of the full address with leading zeros stripped
+ StringBuffer buff = new StringBuffer();
+ buff.append(String.format("%x:%x:%x:%x:%x:%x:%x:%x",
+ (((octets[0] & BIT_MASK) << 8) | (octets[1] & BIT_MASK)),
+ (((octets[2] & BIT_MASK) << 8) | (octets[3] & BIT_MASK)),
+ (((octets[4] & BIT_MASK) << 8) | (octets[5] & BIT_MASK)),
+ (((octets[6] & BIT_MASK) << 8) | (octets[7] & BIT_MASK)),
+ (((octets[8] & BIT_MASK) << 8) | (octets[9] & BIT_MASK)),
+ (((octets[10] & BIT_MASK) << 8) | (octets[11] & BIT_MASK)),
+ (((octets[12] & BIT_MASK) << 8) | (octets[13] & BIT_MASK)),
+ (((octets[14] & BIT_MASK) << 8) | (octets[15] & BIT_MASK))));
+ //Initialize variables for tracking longest zero subsequence, tiebreaking by first occurence
+ int longestSeqStart, longestSeqLen, currSeqStart, currSeqLen;
+ longestSeqStart = 0;
+ longestSeqLen = 0;
+ currSeqStart = 0;
+ currSeqLen = 0;
+
+ for (int index = 0; index < buff.length(); index++) {
+ if (buff.charAt(index) == ':') {
+ if (currSeqLen != 0 && buff.charAt(index + 1) == '0') {
+ currSeqLen += 1;
+ }
+ } else if (buff.charAt(index) == '0' && ((index == 0) || (buff.charAt(index - 1) == ':'))) {
+ if (currSeqLen == 0) {
+ currSeqStart = index;
+ }
+ currSeqLen += 1;
+ } else {
+ if (currSeqLen > longestSeqLen) {
+ longestSeqStart = currSeqStart;
+ longestSeqLen = currSeqLen;
+ }
+ currSeqLen = 0;
+ }
+ }
+
+ if (currSeqLen > longestSeqLen) {
+ longestSeqLen = currSeqLen;
+ longestSeqStart = currSeqStart;
+ }
+ if (longestSeqLen > 1) {
+ if (buff.length() == (longestSeqStart + longestSeqLen)) {
+ buff.append(':');
+ }
+
+ buff.delete(longestSeqStart, longestSeqStart + longestSeqLen);
+
+ if (longestSeqStart == 0) {
+ buff.insert(0, ':');
+ }
+ }
+
+ return buff.toString();
+ }
}
diff --git a/utils/misc/src/test/java/org/onlab/packet/IpAddressTest.java b/utils/misc/src/test/java/org/onlab/packet/IpAddressTest.java
index 7a18ec5..003982a 100644
--- a/utils/misc/src/test/java/org/onlab/packet/IpAddressTest.java
+++ b/utils/misc/src/test/java/org/onlab/packet/IpAddressTest.java
@@ -896,5 +896,40 @@
IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
assertThat(ipAddress.toString(),
is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+
+ ipAddress =
+ IpAddress.valueOf("::1111:2222");
+ assertThat(ipAddress.toString(),
+ is("::1111:2222"));
+
+ ipAddress =
+ IpAddress.valueOf("1:0:0:1:0:0:2:3");
+ assertThat(ipAddress.toString(),
+ is("1::1:0:0:2:3"));
+
+ ipAddress =
+ IpAddress.valueOf("::0123:0004");
+ assertThat(ipAddress.toString(),
+ is("::123:4"));
+
+ ipAddress =
+ IpAddress.valueOf("0:0:1:1:0:0:1:1");
+ assertThat(ipAddress.toString(),
+ is("::1:1:0:0:1:1"));
+
+ ipAddress =
+ IpAddress.valueOf("1:1a2b::");
+ assertThat(ipAddress.toString(),
+ is("1:1a2b::"));
+
+ ipAddress =
+ IpAddress.valueOf("0:0:00:00:0000:00:00:000");
+ assertThat(ipAddress.toString(),
+ is("::"));
+
+ ipAddress =
+ IpAddress.valueOf("0:0:0:1:0:0:0:0");
+ assertThat(ipAddress.toString(),
+ is("0:0:0:1::"));
}
}