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