Pavlin Radoslavov

Reimplementation of classes Ip4Address/Ip6Address/Ip4Prefix/Ip6Prefix

and the corresponding unit tests.

* Reimplemented classes Ip4Address and Ip6Address by inheriting from
  class IpAddress
* Reimplemented classes Ip4Prefix and Ip6Prefix by inheriting from
  class IpPrefix
* Reimplemented the unit tests Ip4AddressTest and Ip6AddressTest to
  match the corresponding IpAddressTest unit tests
* Reimplemented the unit tests Ip4PrefixTest and Ip6PrefixTest to
  match the corresponding IpPrefixTest unit tests
* Minor refactoring/cleanup of classes IpAddress and IpPrefix
...@@ -15,110 +15,90 @@ ...@@ -15,110 +15,90 @@
15 */ 15 */
16 package org.onlab.packet; 16 package org.onlab.packet;
17 17
18 -import java.util.Objects;
19 -
20 /** 18 /**
21 * The class representing an IPv4 network address. 19 * The class representing an IPv4 network address.
22 * This class is immutable. 20 * This class is immutable.
23 */ 21 */
24 -public final class Ip4Prefix { 22 +public final class Ip4Prefix extends IpPrefix {
25 - private final Ip4Address address; // The IPv4 address 23 + public static final IpAddress.Version VERSION = IpAddress.Version.INET;
26 - private final short prefixLen; // The prefix length 24 + // Maximum network mask length
25 + public static final int MAX_MASK_LENGTH = IpPrefix.MAX_INET_MASK_LENGTH;
27 26
28 /** 27 /**
29 - * Default constructor. 28 + * Constructor for given IPv4 address, and a prefix length.
30 - */
31 - public Ip4Prefix() {
32 - this.address = new Ip4Address();
33 - this.prefixLen = 0;
34 - }
35 -
36 - /**
37 - * Copy constructor.
38 * 29 *
39 - * @param other the object to copy from 30 + * @param address the IPv4 address
31 + * @param prefixLength the prefix length
32 + * @throws IllegalArgumentException if the prefix length value is invalid
40 */ 33 */
41 - public Ip4Prefix(Ip4Prefix other) { 34 + private Ip4Prefix(Ip4Address address, int prefixLength) {
42 - this.address = new Ip4Address(other.address); 35 + super(address, prefixLength);
43 - this.prefixLen = other.prefixLen;
44 } 36 }
45 37
46 /** 38 /**
47 - * Constructor for a given address and prefix length. 39 + * Returns the IPv4 address value of the prefix.
48 * 40 *
49 - * @param address the address to use 41 + * @return the IPv4 address value of the prefix
50 - * @param prefixLen the prefix length to use
51 */ 42 */
52 - public Ip4Prefix(Ip4Address address, short prefixLen) { 43 + public Ip4Address address() {
53 - this.address = Ip4Address.makeMaskedAddress(address, prefixLen); 44 + IpAddress a = super.address();
54 - this.prefixLen = prefixLen; 45 + return (Ip4Address) a;
55 } 46 }
56 47
57 /** 48 /**
58 - * Constructs an IPv4 prefix from a string representation of the 49 + * Converts an integer and a prefix length into an IPv4 prefix.
59 - * prefix.
60 - *<p>
61 - * Example: "1.2.0.0/16"
62 * 50 *
63 - * @param value the value to use 51 + * @param address an integer representing the IPv4 address
52 + * @param prefixLength the prefix length
53 + * @return an IPv4 prefix
54 + * @throws IllegalArgumentException if the prefix length value is invalid
64 */ 55 */
65 - public Ip4Prefix(String value) { 56 + public static Ip4Prefix valueOf(int address, int prefixLength) {
66 - String[] splits = value.split("/"); 57 + return new Ip4Prefix(Ip4Address.valueOf(address), prefixLength);
67 - if (splits.length != 2) {
68 - throw new IllegalArgumentException("Specified IPv4 prefix must contain an IPv4 " +
69 - "address and a prefix length separated by '/'");
70 - }
71 - this.prefixLen = Short.decode(splits[1]);
72 - this.address = Ip4Address.makeMaskedAddress(new Ip4Address(splits[0]),
73 - this.prefixLen);
74 } 58 }
75 59
76 /** 60 /**
77 - * Gets the address value of the IPv4 prefix. 61 + * Converts a byte array and a prefix length into an IPv4 prefix.
78 * 62 *
79 - * @return the address value of the IPv4 prefix 63 + * @param address the IPv4 address value stored in network byte order
64 + * @param prefixLength the prefix length
65 + * @return an IPv4 prefix
66 + * @throws IllegalArgumentException if the prefix length value is invalid
80 */ 67 */
81 - public Ip4Address getAddress() { 68 + public static Ip4Prefix valueOf(byte[] address, int prefixLength) {
82 - return address; 69 + return new Ip4Prefix(Ip4Address.valueOf(address), prefixLength);
83 } 70 }
84 71
85 /** 72 /**
86 - * Gets the prefix length value of the IPv4 prefix. 73 + * Converts an IPv4 address and a prefix length into an IPv4 prefix.
87 * 74 *
88 - * @return the prefix length value of the IPv4 prefix 75 + * @param address the IPv4 address
76 + * @param prefixLength the prefix length
77 + * @return an IPv4 prefix
78 + * @throws IllegalArgumentException if the prefix length value is invalid
89 */ 79 */
90 - public short getPrefixLen() { 80 + public static Ip4Prefix valueOf(Ip4Address address, int prefixLength) {
91 - return prefixLen; 81 + return new Ip4Prefix(address, prefixLength);
92 } 82 }
93 83
94 /** 84 /**
95 - * Converts the IPv4 prefix value to an "address/prefixLen" string. 85 + * Converts a CIDR (slash) notation string (e.g., "10.1.0.0/16")
86 + * into an IPv4 prefix.
96 * 87 *
97 - * @return the IPv4 prefix value as an "address/prefixLen" string 88 + * @param address an IP prefix in string form (e.g., "10.1.0.0/16")
89 + * @return an IPv4 prefix
90 + * @throws IllegalArgumentException if the arguments are invalid
98 */ 91 */
99 - @Override 92 + public static Ip4Prefix valueOf(String address) {
100 - public String toString() { 93 + final String[] parts = address.split("/");
101 - return this.address.toString() + "/" + this.prefixLen; 94 + if (parts.length != 2) {
102 - } 95 + String msg = "Malformed IPv4 prefix string: " + address + "." +
103 - 96 + "Address must take form \"x.x.x.x/y\"";
104 - @Override 97 + throw new IllegalArgumentException(msg);
105 - public boolean equals(Object other) {
106 - if (other == this) {
107 - return true;
108 - }
109 -
110 - if (!(other instanceof Ip4Prefix)) {
111 - return false;
112 - }
113 -
114 - Ip4Prefix otherIp4Prefix = (Ip4Prefix) other;
115 -
116 - return Objects.equals(this.address, otherIp4Prefix.address)
117 - && this.prefixLen == otherIp4Prefix.prefixLen;
118 } 98 }
99 + Ip4Address ipAddress = Ip4Address.valueOf(parts[0]);
100 + int prefixLength = Integer.parseInt(parts[1]);
119 101
120 - @Override 102 + return new Ip4Prefix(ipAddress, prefixLength);
121 - public int hashCode() {
122 - return Objects.hash(address, prefixLen);
123 } 103 }
124 } 104 }
......
...@@ -15,110 +15,79 @@ ...@@ -15,110 +15,79 @@
15 */ 15 */
16 package org.onlab.packet; 16 package org.onlab.packet;
17 17
18 -import java.util.Objects;
19 -
20 /** 18 /**
21 * The class representing an IPv6 network address. 19 * The class representing an IPv6 network address.
22 * This class is immutable. 20 * This class is immutable.
23 */ 21 */
24 -public final class Ip6Prefix { 22 +public final class Ip6Prefix extends IpPrefix {
25 - private final Ip6Address address; // The IPv6 address 23 + public static final IpAddress.Version VERSION = IpAddress.Version.INET6;
26 - private final short prefixLen; // The prefix length 24 + // Maximum network mask length
27 - 25 + public static final int MAX_MASK_LENGTH = IpPrefix.MAX_INET6_MASK_LENGTH;
28 - /**
29 - * Default constructor.
30 - */
31 - public Ip6Prefix() {
32 - this.address = new Ip6Address();
33 - this.prefixLen = 0;
34 - }
35 -
36 - /**
37 - * Copy constructor.
38 - *
39 - * @param other the object to copy from
40 - */
41 - public Ip6Prefix(Ip6Prefix other) {
42 - this.address = new Ip6Address(other.address);
43 - this.prefixLen = other.prefixLen;
44 - }
45 26
46 /** 27 /**
47 - * Constructor for a given address and prefix length. 28 + * Constructor for given IPv6 address, and a prefix length.
48 * 29 *
49 - * @param address the address to use 30 + * @param address the IPv6 address
50 - * @param prefixLen the prefix length to use 31 + * @param prefixLength the prefix length
32 + * @throws IllegalArgumentException if the prefix length value is invalid
51 */ 33 */
52 - public Ip6Prefix(Ip6Address address, short prefixLen) { 34 + private Ip6Prefix(Ip6Address address, int prefixLength) {
53 - this.address = Ip6Address.makeMaskedAddress(address, prefixLen); 35 + super(address, prefixLength);
54 - this.prefixLen = prefixLen;
55 } 36 }
56 37
57 /** 38 /**
58 - * Constructs an IPv6 prefix from a string representation of the 39 + * Returns the IPv6 address value of the prefix.
59 - * prefix.
60 - *<p>
61 - * Example: "1111:2222::/32"
62 * 40 *
63 - * @param value the value to use 41 + * @return the IPv6 address value of the prefix
64 */ 42 */
65 - public Ip6Prefix(String value) { 43 + public Ip6Address address() {
66 - String[] splits = value.split("/"); 44 + IpAddress a = super.address();
67 - if (splits.length != 2) { 45 + return (Ip6Address) a;
68 - throw new IllegalArgumentException("Specified IPv6 prefix must contain an IPv6 " +
69 - "address and a prefix length separated by '/'");
70 - }
71 - this.prefixLen = Short.decode(splits[1]);
72 - this.address = Ip6Address.makeMaskedAddress(new Ip6Address(splits[0]),
73 - this.prefixLen);
74 } 46 }
75 47
76 /** 48 /**
77 - * Gets the address value of the IPv6 prefix. 49 + * Converts a byte array and a prefix length into an IPv6 prefix.
78 * 50 *
79 - * @return the address value of the IPv6 prefix 51 + * @param address the IPv6 address value stored in network byte order
52 + * @param prefixLength the prefix length
53 + * @return an IPv6 prefix
54 + * @throws IllegalArgumentException if the prefix length value is invalid
80 */ 55 */
81 - public Ip6Address getAddress() { 56 + public static Ip6Prefix valueOf(byte[] address, int prefixLength) {
82 - return address; 57 + return new Ip6Prefix(Ip6Address.valueOf(address), prefixLength);
83 } 58 }
84 59
85 /** 60 /**
86 - * Gets the prefix length value of the IPv6 prefix. 61 + * Converts an IPv6 address and a prefix length into an IPv6 prefix.
87 * 62 *
88 - * @return the prefix length value of the IPv6 prefix 63 + * @param address the IPv6 address
64 + * @param prefixLength the prefix length
65 + * @return an IPv6 prefix
66 + * @throws IllegalArgumentException if the prefix length value is invalid
89 */ 67 */
90 - public short getPrefixLen() { 68 + public static Ip6Prefix valueOf(Ip6Address address, int prefixLength) {
91 - return prefixLen; 69 + return new Ip6Prefix(address, prefixLength);
92 } 70 }
93 71
94 /** 72 /**
95 - * Converts the IPv6 prefix value to an "address/prefixLen" string. 73 + * Converts a CIDR (slash) notation string (e.g., "1111:2222::/64")
74 + * into an IPv6 prefix.
96 * 75 *
97 - * @return the IPv6 prefix value as an "address/prefixLen" string 76 + * @param address an IP prefix in string form (e.g.,"1111:2222::/64")
77 + * @return an IPv6 prefix
78 + * @throws IllegalArgumentException if the arguments are invalid
98 */ 79 */
99 - @Override 80 + public static Ip6Prefix valueOf(String address) {
100 - public String toString() { 81 + final String[] parts = address.split("/");
101 - return this.address.toString() + "/" + this.prefixLen; 82 + if (parts.length != 2) {
102 - } 83 + String msg = "Malformed IPv6 prefix string: " + address + "." +
103 - 84 + "Address must take form " +
104 - @Override 85 + "\"xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/y\"";
105 - public boolean equals(Object other) { 86 + throw new IllegalArgumentException(msg);
106 - if (other == this) {
107 - return true;
108 - }
109 -
110 - if (!(other instanceof Ip6Prefix)) {
111 - return false;
112 - }
113 -
114 - Ip6Prefix otherIp6Prefix = (Ip6Prefix) other;
115 -
116 - return Objects.equals(this.address, otherIp6Prefix.address)
117 - && this.prefixLen == otherIp6Prefix.prefixLen;
118 } 87 }
88 + Ip6Address ipAddress = Ip6Address.valueOf(parts[0]);
89 + int prefixLength = Integer.parseInt(parts[1]);
119 90
120 - @Override 91 + return new Ip6Prefix(ipAddress, prefixLength);
121 - public int hashCode() {
122 - return Objects.hash(address, prefixLen);
123 } 92 }
124 } 93 }
......
...@@ -30,8 +30,9 @@ import static com.google.common.base.Preconditions.checkState; ...@@ -30,8 +30,9 @@ import static com.google.common.base.Preconditions.checkState;
30 30
31 /** 31 /**
32 * A class representing an IP address. 32 * A class representing an IP address.
33 + * This class is immutable.
33 */ 34 */
34 -public final class IpAddress implements Comparable<IpAddress> { 35 +public class IpAddress implements Comparable<IpAddress> {
35 // IP Versions 36 // IP Versions
36 public enum Version { INET, INET6 }; 37 public enum Version { INET, INET6 };
37 38
...@@ -52,7 +53,7 @@ public final class IpAddress implements Comparable<IpAddress> { ...@@ -52,7 +53,7 @@ public final class IpAddress implements Comparable<IpAddress> {
52 * (i.e., the most significant byte first) 53 * (i.e., the most significant byte first)
53 * @throws IllegalArgumentException if the arguments are invalid 54 * @throws IllegalArgumentException if the arguments are invalid
54 */ 55 */
55 - private IpAddress(Version version, byte[] value) { 56 + protected IpAddress(Version version, byte[] value) {
56 checkArguments(version, value, 0); 57 checkArguments(version, value, 0);
57 this.version = version; 58 this.version = version;
58 switch (version) { 59 switch (version) {
...@@ -88,7 +89,7 @@ public final class IpAddress implements Comparable<IpAddress> { ...@@ -88,7 +89,7 @@ public final class IpAddress implements Comparable<IpAddress> {
88 } 89 }
89 90
90 /** 91 /**
91 - * Returns the integral value of this IP address. 92 + * Returns the integer value of this IP address.
92 * TODO: This method should be moved to Ip4Address. 93 * TODO: This method should be moved to Ip4Address.
93 * 94 *
94 * @return the IP address's value as an integer 95 * @return the IP address's value as an integer
...@@ -219,31 +220,7 @@ public final class IpAddress implements Comparable<IpAddress> { ...@@ -219,31 +220,7 @@ public final class IpAddress implements Comparable<IpAddress> {
219 * @throws IllegalArgumentException if the arguments are invalid 220 * @throws IllegalArgumentException if the arguments are invalid
220 */ 221 */
221 public static IpAddress makeMaskPrefix(Version version, int prefixLength) { 222 public static IpAddress makeMaskPrefix(Version version, int prefixLength) {
222 - int addrByteLength = byteLength(version); 223 + byte[] mask = makeMaskPrefixArray(version, prefixLength);
223 - int addrBitLength = addrByteLength * Byte.SIZE;
224 -
225 - // Verify the prefix length
226 - if ((prefixLength < 0) || (prefixLength > addrBitLength)) {
227 - final String msg = "Invalid IP prefix length: " + prefixLength +
228 - ". Must be in the interval [0, " + addrBitLength + "].";
229 - throw new IllegalArgumentException(msg);
230 - }
231 -
232 - // Number of bytes and extra bits that should be all 1s
233 - int maskBytes = prefixLength / Byte.SIZE;
234 - int maskBits = prefixLength % Byte.SIZE;
235 - byte[] mask = new byte[addrByteLength];
236 -
237 - // Set the bytes and extra bits to 1s
238 - for (int i = 0; i < maskBytes; i++) {
239 - mask[i] = (byte) 0xff; // Set mask bytes to 1s
240 - }
241 - for (int i = maskBytes; i < addrByteLength; i++) {
242 - mask[i] = 0; // Set remaining bytes to 0s
243 - }
244 - if (maskBits > 0) {
245 - mask[maskBytes] = (byte) (0xff << (Byte.SIZE - maskBits));
246 - }
247 return new IpAddress(version, mask); 224 return new IpAddress(version, mask);
248 } 225 }
249 226
...@@ -251,24 +228,26 @@ public final class IpAddress implements Comparable<IpAddress> { ...@@ -251,24 +228,26 @@ public final class IpAddress implements Comparable<IpAddress> {
251 * Creates an IP address by masking it with a network mask of given 228 * Creates an IP address by masking it with a network mask of given
252 * mask length. 229 * mask length.
253 * 230 *
254 - * @param addr the address to mask 231 + * @param address the address to mask
255 * @param prefixLength the length of the mask prefix. Must be in the 232 * @param prefixLength the length of the mask prefix. Must be in the
256 * interval [0, 32] for IPv4, or [0, 128] for IPv6 233 * interval [0, 32] for IPv4, or [0, 128] for IPv6
257 * @return a new IP address that is masked with a mask prefix of the 234 * @return a new IP address that is masked with a mask prefix of the
258 * specified length 235 * specified length
259 * @throws IllegalArgumentException if the prefix length is invalid 236 * @throws IllegalArgumentException if the prefix length is invalid
260 */ 237 */
261 - public static IpAddress makeMaskedAddress(final IpAddress addr, 238 + public static IpAddress makeMaskedAddress(final IpAddress address,
262 int prefixLength) { 239 int prefixLength) {
263 - IpAddress mask = IpAddress.makeMaskPrefix(addr.version(), 240 + // TODO: The code below should go away and replaced with generics
264 - prefixLength); 241 + if (address instanceof Ip4Address) {
265 - byte[] net = new byte[mask.octets.length]; 242 + Ip4Address ip4a = (Ip4Address) address;
266 - 243 + return Ip4Address.makeMaskedAddress(ip4a, prefixLength);
267 - // Mask each byte 244 + } else if (address instanceof Ip6Address) {
268 - for (int i = 0; i < net.length; i++) { 245 + Ip6Address ip6a = (Ip6Address) address;
269 - net[i] = (byte) (addr.octets[i] & mask.octets[i]); 246 + return Ip6Address.makeMaskedAddress(ip6a, prefixLength);
247 + } else {
248 + byte[] net = makeMaskedAddressArray(address, prefixLength);
249 + return IpAddress.valueOf(address.version(), net);
270 } 250 }
271 - return IpAddress.valueOf(addr.version(), net);
272 } 251 }
273 252
274 @Override 253 @Override
...@@ -352,8 +331,7 @@ public final class IpAddress implements Comparable<IpAddress> { ...@@ -352,8 +331,7 @@ public final class IpAddress implements Comparable<IpAddress> {
352 * array with the address 331 * array with the address
353 * @throws IllegalArgumentException if any of the arguments is invalid 332 * @throws IllegalArgumentException if any of the arguments is invalid
354 */ 333 */
355 - private static void checkArguments(Version version, byte[] value, 334 + static void checkArguments(Version version, byte[] value, int offset) {
356 - int offset) {
357 // Check the offset and byte array length 335 // Check the offset and byte array length
358 int addrByteLength = byteLength(version); 336 int addrByteLength = byteLength(version);
359 if ((offset < 0) || (offset + addrByteLength > value.length)) { 337 if ((offset < 0) || (offset + addrByteLength > value.length)) {
...@@ -371,4 +349,67 @@ public final class IpAddress implements Comparable<IpAddress> { ...@@ -371,4 +349,67 @@ public final class IpAddress implements Comparable<IpAddress> {
371 throw new IllegalArgumentException(msg); 349 throw new IllegalArgumentException(msg);
372 } 350 }
373 } 351 }
352 +
353 + /**
354 + * Creates a byte array for IP network mask prefix.
355 + *
356 + * @param version the IP address version
357 + * @param prefixLength the length of the mask prefix. Must be in the
358 + * interval [0, 32] for IPv4, or [0, 128] for IPv6
359 + * @return a byte array that contains a mask prefix of the
360 + * specified length
361 + * @throws IllegalArgumentException if the arguments are invalid
362 + */
363 + static byte[] makeMaskPrefixArray(Version version, int prefixLength) {
364 + int addrByteLength = byteLength(version);
365 + int addrBitLength = addrByteLength * Byte.SIZE;
366 +
367 + // Verify the prefix length
368 + if ((prefixLength < 0) || (prefixLength > addrBitLength)) {
369 + final String msg = "Invalid IP prefix length: " + prefixLength +
370 + ". Must be in the interval [0, " + addrBitLength + "].";
371 + throw new IllegalArgumentException(msg);
372 + }
373 +
374 + // Number of bytes and extra bits that should be all 1s
375 + int maskBytes = prefixLength / Byte.SIZE;
376 + int maskBits = prefixLength % Byte.SIZE;
377 + byte[] mask = new byte[addrByteLength];
378 +
379 + // Set the bytes and extra bits to 1s
380 + for (int i = 0; i < maskBytes; i++) {
381 + mask[i] = (byte) 0xff; // Set mask bytes to 1s
382 + }
383 + for (int i = maskBytes; i < addrByteLength; i++) {
384 + mask[i] = 0; // Set remaining bytes to 0s
385 + }
386 + if (maskBits > 0) {
387 + mask[maskBytes] = (byte) (0xff << (Byte.SIZE - maskBits));
388 + }
389 + return mask;
390 + }
391 +
392 + /**
393 + * Creates a byte array that represents an IP address masked with
394 + * a network mask of given mask length.
395 + *
396 + * @param addr the address to mask
397 + * @param prefixLength the length of the mask prefix. Must be in the
398 + * interval [0, 32] for IPv4, or [0, 128] for IPv6
399 + * @return a byte array that represents the IP address masked with
400 + * a mask prefix of the specified length
401 + * @throws IllegalArgumentException if the prefix length is invalid
402 + */
403 + static byte[] makeMaskedAddressArray(final IpAddress addr,
404 + int prefixLength) {
405 + byte[] mask = IpAddress.makeMaskPrefixArray(addr.version(),
406 + prefixLength);
407 + byte[] net = new byte[mask.length];
408 +
409 + // Mask each byte
410 + for (int i = 0; i < net.length; i++) {
411 + net[i] = (byte) (addr.octets[i] & mask[i]);
412 + }
413 + return net;
414 + }
374 } 415 }
......
...@@ -20,12 +20,13 @@ import java.util.Objects; ...@@ -20,12 +20,13 @@ import java.util.Objects;
20 /** 20 /**
21 * A class representing an IP prefix. A prefix consists of an IP address and 21 * A class representing an IP prefix. A prefix consists of an IP address and
22 * a subnet mask. 22 * a subnet mask.
23 + * This class is immutable.
23 * <p> 24 * <p>
24 * NOTE: The stored IP address in the result IP prefix is masked to 25 * NOTE: The stored IP address in the result IP prefix is masked to
25 * contain zeroes in all bits after the prefix length. 26 * contain zeroes in all bits after the prefix length.
26 * </p> 27 * </p>
27 */ 28 */
28 -public final class IpPrefix { 29 +public class IpPrefix {
29 // Maximum network mask length 30 // Maximum network mask length
30 public static final int MAX_INET_MASK_LENGTH = IpAddress.INET_BIT_LENGTH; 31 public static final int MAX_INET_MASK_LENGTH = IpAddress.INET_BIT_LENGTH;
31 public static final int MAX_INET6_MASK_LENGTH = IpAddress.INET6_BIT_LENGTH; 32 public static final int MAX_INET6_MASK_LENGTH = IpAddress.INET6_BIT_LENGTH;
...@@ -40,7 +41,7 @@ public final class IpPrefix { ...@@ -40,7 +41,7 @@ public final class IpPrefix {
40 * @param prefixLength the prefix length 41 * @param prefixLength the prefix length
41 * @throws IllegalArgumentException if the prefix length value is invalid 42 * @throws IllegalArgumentException if the prefix length value is invalid
42 */ 43 */
43 - private IpPrefix(IpAddress address, int prefixLength) { 44 + protected IpPrefix(IpAddress address, int prefixLength) {
44 checkPrefixLength(address.version(), prefixLength); 45 checkPrefixLength(address.version(), prefixLength);
45 this.address = IpAddress.makeMaskedAddress(address, prefixLength); 46 this.address = IpAddress.makeMaskedAddress(address, prefixLength);
46 this.prefixLength = (short) prefixLength; 47 this.prefixLength = (short) prefixLength;
...@@ -100,7 +101,7 @@ public final class IpPrefix { ...@@ -100,7 +101,7 @@ public final class IpPrefix {
100 } 101 }
101 102
102 /** 103 /**
103 - * Converts an IP address and a prefix length into IP prefix. 104 + * Converts an IP address and a prefix length into an IP prefix.
104 * 105 *
105 * @param address the IP address 106 * @param address the IP address
106 * @param prefixLength the prefix length 107 * @param prefixLength the prefix length
...@@ -112,10 +113,11 @@ public final class IpPrefix { ...@@ -112,10 +113,11 @@ public final class IpPrefix {
112 } 113 }
113 114
114 /** 115 /**
115 - * Converts a CIDR (slash) notation string (e.g., "10.1.0.0/16") into an 116 + * Converts a CIDR (slash) notation string (e.g., "10.1.0.0/16" or
116 - * IP prefix. 117 + * "1111:2222::/64") into an IP prefix.
117 * 118 *
118 - * @param address an IP prefix in string form, e.g. "10.1.0.0/16" 119 + * @param address an IP prefix in string form (e.g. "10.1.0.0/16" or
120 + * "1111:2222::/64")
119 * @return an IP prefix 121 * @return an IP prefix
120 * @throws IllegalArgumentException if the arguments are invalid 122 * @throws IllegalArgumentException if the arguments are invalid
121 */ 123 */
...@@ -123,7 +125,8 @@ public final class IpPrefix { ...@@ -123,7 +125,8 @@ public final class IpPrefix {
123 final String[] parts = address.split("/"); 125 final String[] parts = address.split("/");
124 if (parts.length != 2) { 126 if (parts.length != 2) {
125 String msg = "Malformed IP prefix string: " + address + "." + 127 String msg = "Malformed IP prefix string: " + address + "." +
126 - "Address must take form \"x.x.x.x/y\""; 128 + "Address must take form \"x.x.x.x/y\" or " +
129 + "\"xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/y\"";
127 throw new IllegalArgumentException(msg); 130 throw new IllegalArgumentException(msg);
128 } 131 }
129 IpAddress ipAddress = IpAddress.valueOf(parts[0]); 132 IpAddress ipAddress = IpAddress.valueOf(parts[0]);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onlab.packet; 16 package org.onlab.packet;
17 17
18 import com.google.common.testing.EqualsTester; 18 import com.google.common.testing.EqualsTester;
19 +import org.junit.Ignore;
19 import org.junit.Test; 20 import org.junit.Test;
20 21
21 import static org.hamcrest.Matchers.equalTo; 22 import static org.hamcrest.Matchers.equalTo;
...@@ -32,6 +33,7 @@ public class IpPrefixTest { ...@@ -32,6 +33,7 @@ public class IpPrefixTest {
32 /** 33 /**
33 * Tests the immutability of {@link IpPrefix}. 34 * Tests the immutability of {@link IpPrefix}.
34 */ 35 */
36 + @Ignore("The class is not pure immutable, because it is not 'final'")
35 @Test 37 @Test
36 public void testImmutable() { 38 public void testImmutable() {
37 assertThatClassIsImmutable(IpPrefix.class); 39 assertThatClassIsImmutable(IpPrefix.class);
......