Committed by
Gerrit Code Review
Replaced IPv6 toString with more efficient local helper.
Change-Id: Ib53d7bdf64354efcace7facad740981fce19447c
Showing
2 changed files
with
103 additions
and
15 deletions
... | @@ -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 | } | ... | ... |
-
Please register or login to post a comment