Aaron Kruglikov
Committed by Gerrit Code Review

Replaced IPv6 toString with more efficient local helper.

Change-Id: Ib53d7bdf64354efcace7facad740981fce19447c
...@@ -18,21 +18,20 @@ package org.onlab.packet; ...@@ -18,21 +18,20 @@ package org.onlab.packet;
18 import java.net.InetAddress; 18 import java.net.InetAddress;
19 import java.net.Inet4Address; 19 import java.net.Inet4Address;
20 import java.net.Inet6Address; 20 import java.net.Inet6Address;
21 -import java.net.UnknownHostException;
22 import java.nio.ByteBuffer; 21 import java.nio.ByteBuffer;
23 import java.util.Arrays; 22 import java.util.Arrays;
24 import java.util.Objects; 23 import java.util.Objects;
25 -
26 import com.google.common.net.InetAddresses; 24 import com.google.common.net.InetAddresses;
27 import com.google.common.primitives.UnsignedBytes; 25 import com.google.common.primitives.UnsignedBytes;
28 26
29 -import static com.google.common.base.Preconditions.checkState;
30 27
31 /** 28 /**
32 * A class representing an IP address. 29 * A class representing an IP address.
33 * This class is immutable. 30 * This class is immutable.
34 */ 31 */
35 public class IpAddress implements Comparable<IpAddress> { 32 public class IpAddress implements Comparable<IpAddress> {
33 + private static final int BIT_MASK = 0x000000ff;
34 +
36 // IP Versions 35 // IP Versions
37 public enum Version { INET, INET6 }; 36 public enum Version { INET, INET6 };
38 37
...@@ -353,20 +352,12 @@ public class IpAddress implements Comparable<IpAddress> { ...@@ -353,20 +352,12 @@ public class IpAddress implements Comparable<IpAddress> {
353 switch (version) { 352 switch (version) {
354 case INET: 353 case INET:
355 return String.format("%d.%d.%d.%d", octets[0] & 0xff, 354 return String.format("%d.%d.%d.%d", octets[0] & 0xff,
356 - octets[1] & 0xff, 355 + octets[1] & 0xff,
357 - octets[2] & 0xff, 356 + octets[2] & 0xff,
358 - octets[3] & 0xff); 357 + octets[3] & 0xff);
359 case INET6: 358 case INET6:
360 default: 359 default:
361 - InetAddress inetAddr = null; 360 + return ipv6ToStringHelper();
362 - try {
363 - inetAddr = InetAddress.getByAddress(octets);
364 - } catch (UnknownHostException e) {
365 - // Should never happen
366 - checkState(false, "Internal error: Ip6Address.toString()");
367 - return "[Invalid IP Address]";
368 - }
369 - return InetAddresses.toAddrString(inetAddr);
370 } 361 }
371 } 362 }
372 363
...@@ -494,4 +485,66 @@ public class IpAddress implements Comparable<IpAddress> { ...@@ -494,4 +485,66 @@ public class IpAddress implements Comparable<IpAddress> {
494 } 485 }
495 return net; 486 return net;
496 } 487 }
488 +
489 + /**
490 + * Creates a string based on the IPv6 recommendations for canonical representations found here:
491 + * https://tools.ietf.org/html/rfc5952#section-1.
492 + * @return A properly formatted IPv6 canonical representation.
493 + */
494 + private String ipv6ToStringHelper() {
495 + //Populate a buffer with the string of the full address with leading zeros stripped
496 + StringBuffer buff = new StringBuffer();
497 + buff.append(String.format("%x:%x:%x:%x:%x:%x:%x:%x",
498 + (((octets[0] & BIT_MASK) << 8) | (octets[1] & BIT_MASK)),
499 + (((octets[2] & BIT_MASK) << 8) | (octets[3] & BIT_MASK)),
500 + (((octets[4] & BIT_MASK) << 8) | (octets[5] & BIT_MASK)),
501 + (((octets[6] & BIT_MASK) << 8) | (octets[7] & BIT_MASK)),
502 + (((octets[8] & BIT_MASK) << 8) | (octets[9] & BIT_MASK)),
503 + (((octets[10] & BIT_MASK) << 8) | (octets[11] & BIT_MASK)),
504 + (((octets[12] & BIT_MASK) << 8) | (octets[13] & BIT_MASK)),
505 + (((octets[14] & BIT_MASK) << 8) | (octets[15] & BIT_MASK))));
506 + //Initialize variables for tracking longest zero subsequence, tiebreaking by first occurence
507 + int longestSeqStart, longestSeqLen, currSeqStart, currSeqLen;
508 + longestSeqStart = 0;
509 + longestSeqLen = 0;
510 + currSeqStart = 0;
511 + currSeqLen = 0;
512 +
513 + for (int index = 0; index < buff.length(); index++) {
514 + if (buff.charAt(index) == ':') {
515 + if (currSeqLen != 0 && buff.charAt(index + 1) == '0') {
516 + currSeqLen += 1;
517 + }
518 + } else if (buff.charAt(index) == '0' && ((index == 0) || (buff.charAt(index - 1) == ':'))) {
519 + if (currSeqLen == 0) {
520 + currSeqStart = index;
521 + }
522 + currSeqLen += 1;
523 + } else {
524 + if (currSeqLen > longestSeqLen) {
525 + longestSeqStart = currSeqStart;
526 + longestSeqLen = currSeqLen;
527 + }
528 + currSeqLen = 0;
529 + }
530 + }
531 +
532 + if (currSeqLen > longestSeqLen) {
533 + longestSeqLen = currSeqLen;
534 + longestSeqStart = currSeqStart;
535 + }
536 + if (longestSeqLen > 1) {
537 + if (buff.length() == (longestSeqStart + longestSeqLen)) {
538 + buff.append(':');
539 + }
540 +
541 + buff.delete(longestSeqStart, longestSeqStart + longestSeqLen);
542 +
543 + if (longestSeqStart == 0) {
544 + buff.insert(0, ':');
545 + }
546 + }
547 +
548 + return buff.toString();
549 + }
497 } 550 }
......
...@@ -896,5 +896,40 @@ public class IpAddressTest { ...@@ -896,5 +896,40 @@ public class IpAddressTest {
896 IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); 896 IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
897 assertThat(ipAddress.toString(), 897 assertThat(ipAddress.toString(),
898 is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); 898 is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
899 +
900 + ipAddress =
901 + IpAddress.valueOf("::1111:2222");
902 + assertThat(ipAddress.toString(),
903 + is("::1111:2222"));
904 +
905 + ipAddress =
906 + IpAddress.valueOf("1:0:0:1:0:0:2:3");
907 + assertThat(ipAddress.toString(),
908 + is("1::1:0:0:2:3"));
909 +
910 + ipAddress =
911 + IpAddress.valueOf("::0123:0004");
912 + assertThat(ipAddress.toString(),
913 + is("::123:4"));
914 +
915 + ipAddress =
916 + IpAddress.valueOf("0:0:1:1:0:0:1:1");
917 + assertThat(ipAddress.toString(),
918 + is("::1:1:0:0:1:1"));
919 +
920 + ipAddress =
921 + IpAddress.valueOf("1:1a2b::");
922 + assertThat(ipAddress.toString(),
923 + is("1:1a2b::"));
924 +
925 + ipAddress =
926 + IpAddress.valueOf("0:0:00:00:0000:00:00:000");
927 + assertThat(ipAddress.toString(),
928 + is("::"));
929 +
930 + ipAddress =
931 + IpAddress.valueOf("0:0:0:1:0:0:0:0");
932 + assertThat(ipAddress.toString(),
933 + is("0:0:0:1::"));
899 } 934 }
900 } 935 }
......