Updated the implementation of IpAddress:
* Added new static methods IpAddress.makeMaskPrefix and IpAddress.makeMaskedAddress * Cleanup Also, removed obsoleted Javadoc comments in Ip4Prefix and Ip6Prefix classes
Showing
3 changed files
with
99 additions
and
61 deletions
... | @@ -101,20 +101,6 @@ public final class Ip4Prefix { | ... | @@ -101,20 +101,6 @@ public final class Ip4Prefix { |
101 | return this.address.toString() + "/" + this.prefixLen; | 101 | return this.address.toString() + "/" + this.prefixLen; |
102 | } | 102 | } |
103 | 103 | ||
104 | - /** | ||
105 | - * Compares the value of two Ip4Prefix objects. | ||
106 | - * <p/> | ||
107 | - * Note the value of the IPv4 address is compared directly between the | ||
108 | - * objects, and must match exactly for the objects to be considered equal. | ||
109 | - * This may result in objects which represent the same IP prefix being | ||
110 | - * classified as unequal, because the unsignificant bits of the address | ||
111 | - * field don't match (the bits to the right of the prefix length). | ||
112 | - * <p/> | ||
113 | - * TODO Change this behavior so that objects that represent the same prefix | ||
114 | - * are classified as equal according to this equals method. | ||
115 | - * | ||
116 | - * @see Object#equals(Object) | ||
117 | - */ | ||
118 | @Override | 104 | @Override |
119 | public boolean equals(Object other) { | 105 | public boolean equals(Object other) { |
120 | if (other == this) { | 106 | if (other == this) { | ... | ... |
... | @@ -101,20 +101,6 @@ public final class Ip6Prefix { | ... | @@ -101,20 +101,6 @@ public final class Ip6Prefix { |
101 | return this.address.toString() + "/" + this.prefixLen; | 101 | return this.address.toString() + "/" + this.prefixLen; |
102 | } | 102 | } |
103 | 103 | ||
104 | - /** | ||
105 | - * Compares the value of two Ip6Prefix objects. | ||
106 | - * <p/> | ||
107 | - * Note the value of the IPv6 address is compared directly between the | ||
108 | - * objects, and must match exactly for the objects to be considered equal. | ||
109 | - * This may result in objects which represent the same IP prefix being | ||
110 | - * classified as unequal, because the unsignificant bits of the address | ||
111 | - * field don't match (the bits to the right of the prefix length). | ||
112 | - * <p/> | ||
113 | - * TODO Change this behavior so that objects that represent the same prefix | ||
114 | - * are classified as equal according to this equals method. | ||
115 | - * | ||
116 | - * @see Object#equals(Object) | ||
117 | - */ | ||
118 | @Override | 104 | @Override |
119 | public boolean equals(Object other) { | 105 | public boolean equals(Object other) { |
120 | if (other == this) { | 106 | if (other == this) { | ... | ... |
... | @@ -17,6 +17,8 @@ package org.onlab.packet; | ... | @@ -17,6 +17,8 @@ package org.onlab.packet; |
17 | 17 | ||
18 | import java.nio.ByteBuffer; | 18 | import java.nio.ByteBuffer; |
19 | import java.util.Arrays; | 19 | import java.util.Arrays; |
20 | +import java.util.Objects; | ||
21 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
20 | 22 | ||
21 | /** | 23 | /** |
22 | * A class representing an IPv4 address. | 24 | * A class representing an IPv4 address. |
... | @@ -37,35 +39,68 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -37,35 +39,68 @@ public final class IpAddress implements Comparable<IpAddress> { |
37 | /** | 39 | /** |
38 | * Constructor for given IP address version and address octets. | 40 | * Constructor for given IP address version and address octets. |
39 | * | 41 | * |
40 | - * @param ver the IP address version | 42 | + * @param value the IP address value stored in network byte order |
41 | - * @param octets the IP address octets | 43 | + * (i.e., the most significant byte first) |
44 | + * @param value the IP address value | ||
42 | */ | 45 | */ |
43 | - private IpAddress(Version ver, byte[] octets) { | 46 | + private IpAddress(Version version, byte[] value) { |
44 | - this.version = ver; | 47 | + checkNotNull(value); |
45 | - this.octets = Arrays.copyOf(octets, INET_BYTE_LENGTH); | 48 | + |
49 | + this.version = version; | ||
50 | + this.octets = Arrays.copyOf(value, INET_BYTE_LENGTH); | ||
51 | + } | ||
52 | + | ||
53 | + /** | ||
54 | + * Converts an integer into an IPv4 address. | ||
55 | + * | ||
56 | + * @param value an integer representing an IPv4 value | ||
57 | + * @return an IP address | ||
58 | + */ | ||
59 | + public static IpAddress valueOf(int value) { | ||
60 | + byte[] bytes = | ||
61 | + ByteBuffer.allocate(INET_BYTE_LENGTH).putInt(value).array(); | ||
62 | + return new IpAddress(Version.INET, bytes); | ||
46 | } | 63 | } |
47 | 64 | ||
48 | /** | 65 | /** |
49 | * Converts a byte array into an IP address. | 66 | * Converts a byte array into an IP address. |
50 | * | 67 | * |
51 | - * @param address the IP address value stored in network byte order | 68 | + * @param value the IP address value stored in network byte order |
52 | * (i.e., the most significant byte first) | 69 | * (i.e., the most significant byte first) |
53 | * @return an IP address | 70 | * @return an IP address |
54 | */ | 71 | */ |
55 | - public static IpAddress valueOf(byte[] address) { | 72 | + public static IpAddress valueOf(byte[] value) { |
56 | - return new IpAddress(Version.INET, address); | 73 | + return new IpAddress(Version.INET, value); |
57 | } | 74 | } |
58 | 75 | ||
59 | /** | 76 | /** |
60 | - * Converts an integer into an IPv4 address. | 77 | + * Converts a byte array and a given offset from the beginning of the |
78 | + * array into an IP address. | ||
79 | + * <p/> | ||
80 | + * The IP address is stored in network byte order (i.e., the most | ||
81 | + * significant byte first). | ||
61 | * | 82 | * |
62 | - * @param address an integer representing an IPv4 value | 83 | + * @param value the value to use |
84 | + * @param offset the offset in bytes from the beginning of the byte array | ||
63 | * @return an IP address | 85 | * @return an IP address |
64 | */ | 86 | */ |
65 | - public static IpAddress valueOf(int address) { | 87 | + public static IpAddress valueOf(byte[] value, int offset) { |
66 | - byte[] bytes = | 88 | + // Verify the arguments |
67 | - ByteBuffer.allocate(INET_BYTE_LENGTH).putInt(address).array(); | 89 | + if ((offset < 0) || (offset + INET_BYTE_LENGTH > value.length)) { |
68 | - return new IpAddress(Version.INET, bytes); | 90 | + String msg; |
91 | + if (value.length < INET_BYTE_LENGTH) { | ||
92 | + msg = "Invalid IPv4 address array: array length: " + | ||
93 | + value.length + ". Must be at least " + INET_BYTE_LENGTH; | ||
94 | + } else { | ||
95 | + msg = "Invalid IPv4 address array: array offset: " + | ||
96 | + offset + ". Must be in the interval [0, " + | ||
97 | + (value.length - INET_BYTE_LENGTH) + "]"; | ||
98 | + } | ||
99 | + throw new IllegalArgumentException(msg); | ||
100 | + } | ||
101 | + | ||
102 | + byte[] bc = Arrays.copyOfRange(value, offset, value.length); | ||
103 | + return IpAddress.valueOf(bc); | ||
69 | } | 104 | } |
70 | 105 | ||
71 | /** | 106 | /** |
... | @@ -77,8 +112,9 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -77,8 +112,9 @@ public final class IpAddress implements Comparable<IpAddress> { |
77 | public static IpAddress valueOf(String address) { | 112 | public static IpAddress valueOf(String address) { |
78 | final String[] net = address.split("\\."); | 113 | final String[] net = address.split("\\."); |
79 | if (net.length != INET_BYTE_LENGTH) { | 114 | if (net.length != INET_BYTE_LENGTH) { |
80 | - throw new IllegalArgumentException("Malformed IP address string; " | 115 | + String msg = "Malformed IPv4 address string; " + |
81 | - + "Address must have four decimal values separated by dots (.)"); | 116 | + "Address must have four decimal values separated by dots (.)"; |
117 | + throw new IllegalArgumentException(msg); | ||
82 | } | 118 | } |
83 | final byte[] bytes = new byte[INET_BYTE_LENGTH]; | 119 | final byte[] bytes = new byte[INET_BYTE_LENGTH]; |
84 | for (int i = 0; i < INET_BYTE_LENGTH; i++) { | 120 | for (int i = 0; i < INET_BYTE_LENGTH; i++) { |
... | @@ -115,6 +151,48 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -115,6 +151,48 @@ public final class IpAddress implements Comparable<IpAddress> { |
115 | return bb.getInt(); | 151 | return bb.getInt(); |
116 | } | 152 | } |
117 | 153 | ||
154 | + /** | ||
155 | + * Creates an IP network mask prefix. | ||
156 | + * | ||
157 | + * @param prefixLen the length of the mask prefix. Must be in the interval | ||
158 | + * [0, 32] for IPv4 | ||
159 | + * @return a new IP address that contains a mask prefix of the | ||
160 | + * specified length | ||
161 | + */ | ||
162 | + public static IpAddress makeMaskPrefix(int prefixLen) { | ||
163 | + // Verify the prefix length | ||
164 | + if ((prefixLen < 0) || (prefixLen > INET_BIT_LENGTH)) { | ||
165 | + final String msg = "Invalid IPv4 prefix length: " + prefixLen + | ||
166 | + ". Must be in the interval [0, 32]."; | ||
167 | + throw new IllegalArgumentException(msg); | ||
168 | + } | ||
169 | + | ||
170 | + long v = (0xffffffffL << (INET_BIT_LENGTH - prefixLen)) & 0xffffffffL; | ||
171 | + return IpAddress.valueOf((int) v); | ||
172 | + } | ||
173 | + | ||
174 | + /** | ||
175 | + * Creates an IP address by masking it with a network mask of given | ||
176 | + * mask length. | ||
177 | + * | ||
178 | + * @param addr the address to mask | ||
179 | + * @param prefixLen the length of the mask prefix. Must be in the interval | ||
180 | + * [0, 32] for IPv4 | ||
181 | + * @return a new IP address that is masked with a mask prefix of the | ||
182 | + * specified length | ||
183 | + */ | ||
184 | + public static IpAddress makeMaskedAddress(final IpAddress addr, | ||
185 | + int prefixLen) { | ||
186 | + IpAddress mask = IpAddress.makeMaskPrefix(prefixLen); | ||
187 | + byte[] net = new byte[INET_BYTE_LENGTH]; | ||
188 | + | ||
189 | + // Mask each byte | ||
190 | + for (int i = 0; i < INET_BYTE_LENGTH; i++) { | ||
191 | + net[i] = (byte) (addr.octets[i] & mask.octets[i]); | ||
192 | + } | ||
193 | + return IpAddress.valueOf(net); | ||
194 | + } | ||
195 | + | ||
118 | @Override | 196 | @Override |
119 | public int compareTo(IpAddress o) { | 197 | public int compareTo(IpAddress o) { |
120 | Long lv = ((long) this.toInt()) & 0xffffffffL; | 198 | Long lv = ((long) this.toInt()) & 0xffffffffL; |
... | @@ -124,32 +202,20 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -124,32 +202,20 @@ public final class IpAddress implements Comparable<IpAddress> { |
124 | 202 | ||
125 | @Override | 203 | @Override |
126 | public int hashCode() { | 204 | public int hashCode() { |
127 | - final int prime = 31; | 205 | + return Objects.hash(version, octets); |
128 | - int result = 1; | ||
129 | - result = prime * result + Arrays.hashCode(octets); | ||
130 | - result = prime * result + ((version == null) ? 0 : version.hashCode()); | ||
131 | - return result; | ||
132 | } | 206 | } |
133 | 207 | ||
134 | @Override | 208 | @Override |
135 | public boolean equals(Object obj) { | 209 | public boolean equals(Object obj) { |
136 | - if (this == obj) { | 210 | + if (obj == this) { |
137 | return true; | 211 | return true; |
138 | } | 212 | } |
139 | - if (obj == null) { | 213 | + if ((obj == null) || (getClass() != obj.getClass())) { |
140 | - return false; | ||
141 | - } | ||
142 | - if (getClass() != obj.getClass()) { | ||
143 | return false; | 214 | return false; |
144 | } | 215 | } |
145 | IpAddress other = (IpAddress) obj; | 216 | IpAddress other = (IpAddress) obj; |
146 | - if (!Arrays.equals(octets, other.octets)) { | 217 | + return (version == other.version) && |
147 | - return false; | 218 | + Arrays.equals(octets, other.octets); |
148 | - } | ||
149 | - if (version != other.version) { | ||
150 | - return false; | ||
151 | - } | ||
152 | - return true; | ||
153 | } | 219 | } |
154 | 220 | ||
155 | @Override | 221 | @Override | ... | ... |
-
Please register or login to post a comment