blob: 56ff2f2f378a2cb83ff0ad5ba2b7ae7917246580 [file] [log] [blame]
Jian Lic7e20a52016-07-18 19:03:49 +09001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.lisp.msg.types;
17
Jian Li115d8602016-08-15 20:21:53 +090018import io.netty.buffer.ByteBuf;
19import org.onosproject.lisp.msg.exceptions.LispParseError;
20import org.onosproject.lisp.msg.exceptions.LispReaderException;
GUNiba871702016-08-22 21:06:02 +090021import org.onosproject.lisp.msg.exceptions.LispWriterException;
Jian Li115d8602016-08-15 20:21:53 +090022
23import java.nio.ByteBuffer;
Jian Li76ea0572016-08-29 12:41:16 +090024import java.util.Arrays;
Jian Lic7e20a52016-07-18 19:03:49 +090025import java.util.Objects;
26
27import static com.google.common.base.MoreObjects.toStringHelper;
28
29/**
30 * Application data type LCAF address class.
Jian Li8fc2d2f2016-08-08 14:43:53 +090031 * <p>
Jian Lic7e20a52016-07-18 19:03:49 +090032 * Application data type is defined in draft-ietf-lisp-lcaf-13
33 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-13#page-26
34 *
Jian Li8fc2d2f2016-08-08 14:43:53 +090035 * <pre>
36 * {@literal
Jian Lic7e20a52016-07-18 19:03:49 +090037 * 0 1 2 3
38 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * | AFI = 16387 | Rsvd1 | Flags |
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 * | Type = 4 | Rsvd2 | 12 + n |
43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * | IP TOS, IPv6 TC, or Flow Label | Protocol |
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * | Local Port (lower-range) | Local Port (upper-range) |
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 * | Remote Port (lower-range) | Remote Port (upper-range) |
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 * | AFI = x | Address ... |
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jian Li8fc2d2f2016-08-08 14:43:53 +090052 * }</pre>
Jian Lic7e20a52016-07-18 19:03:49 +090053 */
Jian Li115d8602016-08-15 20:21:53 +090054public final class LispAppDataLcafAddress extends LispLcafAddress {
Jian Lic7e20a52016-07-18 19:03:49 +090055
56 private final byte protocol;
57 private final int ipTos;
Jian Li115d8602016-08-15 20:21:53 +090058 private final short localPortLow;
59 private final short localPortHigh;
60 private final short remotePortLow;
61 private final short remotePortHigh;
Jian Lic7e20a52016-07-18 19:03:49 +090062 private LispAfiAddress address;
63
64 /**
Jian Lia7b394d2016-08-21 23:11:46 +090065 * Initializes application data type LCAF address.
66 *
Jian Li115d8602016-08-15 20:21:53 +090067 * @param protocol protocol number
68 * @param ipTos IP type of service
69 * @param localPortLow low-ranged local port number
70 * @param localPortHigh high-ranged local port number
71 * @param remotePortLow low-ranged remote port number
72 * @param remotePortHigh high-ranged remote port number
73 * @param address address
Jian Lic7e20a52016-07-18 19:03:49 +090074 */
Jian Li115d8602016-08-15 20:21:53 +090075 private LispAppDataLcafAddress(byte protocol, int ipTos, short localPortLow,
76 short localPortHigh, short remotePortLow,
77 short remotePortHigh, LispAfiAddress address) {
Jian Lic7e20a52016-07-18 19:03:49 +090078 super(LispCanonicalAddressFormatEnum.APPLICATION_DATA);
79 this.protocol = protocol;
80 this.ipTos = ipTos;
Jian Li115d8602016-08-15 20:21:53 +090081 this.localPortLow = localPortLow;
82 this.localPortHigh = localPortHigh;
83 this.remotePortLow = remotePortLow;
84 this.remotePortHigh = remotePortHigh;
Jian Lic7e20a52016-07-18 19:03:49 +090085 this.address = address;
86 }
87
88 /**
Jian Lia7b394d2016-08-21 23:11:46 +090089 * Initializes application data type LCAF address.
90 *
91 * @param reserved1 reserved1
92 * @param reserved2 reserved2
93 * @param flag flag
94 * @param length length
95 * @param protocol protocol number
96 * @param ipTos IP type of service
97 * @param localPortLow low-ranged local port number
98 * @param localPortHigh high-ranged local port number
99 * @param remotePortLow low-ranged remote port number
100 * @param remotePortHigh high-ranged remote port number
101 * @param address address
102 */
103 private LispAppDataLcafAddress(byte reserved1, byte reserved2, byte flag, short length,
104 byte protocol, int ipTos, short localPortLow,
105 short localPortHigh, short remotePortLow,
106 short remotePortHigh, LispAfiAddress address) {
107 super(LispCanonicalAddressFormatEnum.APPLICATION_DATA, reserved1, reserved2, flag, length);
108 this.protocol = protocol;
109 this.ipTos = ipTos;
110 this.localPortLow = localPortLow;
111 this.localPortHigh = localPortHigh;
112 this.remotePortLow = remotePortLow;
113 this.remotePortHigh = remotePortHigh;
114 this.address = address;
115 }
116
117 /**
Jian Lic7e20a52016-07-18 19:03:49 +0900118 * Obtains protocol number.
119 *
120 * @return protocol number
121 */
122 public byte getProtocol() {
123 return protocol;
124 }
125
126 /**
127 * Obtains IP type of service.
128 *
129 * @return IP type of service
130 */
131 public int getIpTos() {
132 return ipTos;
133 }
134
135 /**
Jian Li115d8602016-08-15 20:21:53 +0900136 * Obtains low-ranged local port number.
Jian Lic7e20a52016-07-18 19:03:49 +0900137 *
Jian Li115d8602016-08-15 20:21:53 +0900138 * @return low-ranged local port number
Jian Lic7e20a52016-07-18 19:03:49 +0900139 */
Jian Li115d8602016-08-15 20:21:53 +0900140 public short getLocalPortLow() {
141 return localPortLow;
Jian Lic7e20a52016-07-18 19:03:49 +0900142 }
143
144 /**
Jian Li115d8602016-08-15 20:21:53 +0900145 * Obtains high-ranged local port number.
Jian Lic7e20a52016-07-18 19:03:49 +0900146 *
Jian Li115d8602016-08-15 20:21:53 +0900147 * @return high-ranged local port number
Jian Lic7e20a52016-07-18 19:03:49 +0900148 */
Jian Li115d8602016-08-15 20:21:53 +0900149 public short getLocalPortHigh() {
150 return localPortHigh;
151 }
152
153 /**
154 * Obtains low-ranged remote port number.
155 *
156 * @return low-ranged remote port number
157 */
158 public short getRemotePortLow() {
159 return remotePortLow;
160 }
161
162 /**
163 * Obtains high-ranged remote port number.
164 *
165 * @return high-ranged remote port number
166 */
167 public short getRemotePortHigh() {
168 return remotePortHigh;
Jian Lic7e20a52016-07-18 19:03:49 +0900169 }
170
171 /**
172 * Obtains address.
173 *
174 * @return address
175 */
176 public LispAfiAddress getAddress() {
177 return address;
178 }
179
180 @Override
181 public int hashCode() {
Jian Li115d8602016-08-15 20:21:53 +0900182 return Objects.hash(address, protocol, ipTos, localPortLow,
183 localPortHigh, remotePortLow, remotePortHigh);
Jian Lic7e20a52016-07-18 19:03:49 +0900184 }
185
186 @Override
187 public boolean equals(Object obj) {
188 if (this == obj) {
189 return true;
190 }
191
192 if (obj instanceof LispAppDataLcafAddress) {
193 final LispAppDataLcafAddress other = (LispAppDataLcafAddress) obj;
194 return Objects.equals(this.address, other.address) &&
195 Objects.equals(this.protocol, other.protocol) &&
196 Objects.equals(this.ipTos, other.ipTos) &&
Jian Li115d8602016-08-15 20:21:53 +0900197 Objects.equals(this.localPortLow, other.localPortLow) &&
198 Objects.equals(this.localPortHigh, other.localPortHigh) &&
199 Objects.equals(this.remotePortLow, other.remotePortLow) &&
200 Objects.equals(this.remotePortHigh, other.remotePortHigh);
Jian Lic7e20a52016-07-18 19:03:49 +0900201 }
202 return false;
203 }
204
205 @Override
206 public String toString() {
207 return toStringHelper(this)
208 .add("address", address)
209 .add("protocol", protocol)
210 .add("ip type of service", ipTos)
Jian Li115d8602016-08-15 20:21:53 +0900211 .add("low-ranged local port number", localPortLow)
212 .add("high-ranged local port number", localPortHigh)
213 .add("low-ranged remote port number", remotePortLow)
214 .add("high-ranged remote port number", remotePortHigh)
Jian Lic7e20a52016-07-18 19:03:49 +0900215 .toString();
216 }
Jian Li115d8602016-08-15 20:21:53 +0900217
Jian Lia7b394d2016-08-21 23:11:46 +0900218 public static final class AppDataAddressBuilder
219 extends LcafAddressBuilder<AppDataAddressBuilder> {
Jian Li115d8602016-08-15 20:21:53 +0900220 private byte protocol;
221 private int ipTos;
222 private short localPortLow;
223 private short localPortHigh;
224 private short remotePortLow;
225 private short remotePortHigh;
226 private LispAfiAddress address;
227
228 /**
229 * Sets protocol number.
230 *
231 * @param protocol protocol number
232 * @return AppDataAddressBuilder object
233 */
Jian Lia7b394d2016-08-21 23:11:46 +0900234 public AppDataAddressBuilder withProtocol(byte protocol) {
Jian Li115d8602016-08-15 20:21:53 +0900235 this.protocol = protocol;
236 return this;
237 }
238
239 /**
240 * Sets IP type of service.
241 *
242 * @param ipTos IP type of service
243 * @return AppDataAddressBuilder object
244 */
Jian Lia7b394d2016-08-21 23:11:46 +0900245 public AppDataAddressBuilder withIpTos(int ipTos) {
Jian Li115d8602016-08-15 20:21:53 +0900246 this.ipTos = ipTos;
247 return this;
248 }
249
250 /**
251 * Sets low-ranged local port number.
252 *
253 * @param localPortLow low-ranged local port number
254 * @return AppDataAddressBuilder object
255 */
Jian Lia7b394d2016-08-21 23:11:46 +0900256 public AppDataAddressBuilder withLocalPortLow(short localPortLow) {
Jian Li115d8602016-08-15 20:21:53 +0900257 this.localPortLow = localPortLow;
258 return this;
259 }
260
261 /**
262 * Sets high-ranged local port number.
263 *
264 * @param localPortHigh high-ranged local port number
265 * @return AppDataAddressBuilder object
266 */
Jian Lia7b394d2016-08-21 23:11:46 +0900267 public AppDataAddressBuilder withLocalPortHigh(short localPortHigh) {
Jian Li115d8602016-08-15 20:21:53 +0900268 this.localPortHigh = localPortHigh;
269 return this;
270 }
271
272 /**
273 * Sets low-ranged remote port number.
274 *
275 * @param remotePortLow low-ranged remote port number
276 * @return AppDataAddressBuilder object
277 */
Jian Lia7b394d2016-08-21 23:11:46 +0900278 public AppDataAddressBuilder withRemotePortLow(short remotePortLow) {
Jian Li115d8602016-08-15 20:21:53 +0900279 this.remotePortLow = remotePortLow;
280 return this;
281 }
282
283 /**
284 * Sets high-ranged remote port number.
285 *
286 * @param remotePortHigh high-ranged remote port number
287 * @return AppDataAddressBuilder object
288 */
Jian Lia7b394d2016-08-21 23:11:46 +0900289 public AppDataAddressBuilder withRemotePortHigh(short remotePortHigh) {
Jian Li115d8602016-08-15 20:21:53 +0900290 this.remotePortHigh = remotePortHigh;
291 return this;
292 }
293
294 /**
295 * Sets AFI address.
296 *
297 * @param address AFI address
298 * @return AppDataAddressBuilder object
299 */
Jian Lia7b394d2016-08-21 23:11:46 +0900300 public AppDataAddressBuilder withAddress(LispAfiAddress address) {
Jian Li115d8602016-08-15 20:21:53 +0900301 this.address = address;
302 return this;
303 }
304
305 /**
306 * Builds LispAppDataLcafAddress instance.
307 *
308 * @return LispAddDataLcafAddress instance
309 */
Jian Lia7b394d2016-08-21 23:11:46 +0900310 public LispAppDataLcafAddress build() {
311 return new LispAppDataLcafAddress(reserved1, reserved2, flag, length,
312 protocol, ipTos, localPortLow, localPortHigh, remotePortLow,
313 remotePortHigh, address);
Jian Li115d8602016-08-15 20:21:53 +0900314 }
315 }
316
317 /**
318 * Application data LCAF address reader class.
319 */
320 public static class AppDataLcafAddressReader
321 implements LispAddressReader<LispAppDataLcafAddress> {
322
323 @Override
324 public LispAppDataLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
325
Jian Lia7b394d2016-08-21 23:11:46 +0900326 LispLcafAddress lcafAddress = LispLcafAddress.deserializeCommon(byteBuf);
327
Jian Li115d8602016-08-15 20:21:53 +0900328 byte[] ipTosByte = new byte[3];
329 byteBuf.readBytes(ipTosByte);
330
331 byte protocol = (byte) byteBuf.readUnsignedByte();
332 int ipTos = getPartialInt(ipTosByte);
333 short localPortLow = (short) byteBuf.readUnsignedShort();
334 short localPortHigh = (short) byteBuf.readUnsignedShort();
335 short remotePortLow = (short) byteBuf.readUnsignedShort();
336 short remotePortHigh = (short) byteBuf.readUnsignedShort();
337
Jian Lia7b394d2016-08-21 23:11:46 +0900338 LispAfiAddress address = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li115d8602016-08-15 20:21:53 +0900339
340 return new AppDataAddressBuilder()
Jian Lia7b394d2016-08-21 23:11:46 +0900341 .withReserved1(lcafAddress.getReserved1())
342 .withReserved2(lcafAddress.getReserved2())
343 .withFlag(lcafAddress.getFlag())
344 .withLength(lcafAddress.getLength())
345 .withProtocol(protocol)
346 .withIpTos(ipTos)
347 .withLocalPortLow(localPortLow)
348 .withLocalPortHigh(localPortHigh)
349 .withRemotePortLow(remotePortLow)
350 .withRemotePortHigh(remotePortHigh)
351 .withAddress(address)
352 .build();
Jian Li115d8602016-08-15 20:21:53 +0900353 }
354
355 /**
Jian Li76ea0572016-08-29 12:41:16 +0900356 * An utility function that obtains the partial int value from byte arrays.
Jian Li115d8602016-08-15 20:21:53 +0900357 *
358 * @param bytes an array of bytes
359 * @return converted integer
360 */
361 public static int getPartialInt(byte[] bytes) {
362 ByteBuffer buffer = ByteBuffer.allocate(4);
363 buffer.position(4 - bytes.length);
364 buffer.put(bytes);
365 buffer.position(0);
366 return buffer.getInt();
367 }
368 }
GUNiba871702016-08-22 21:06:02 +0900369
370 /**
371 * Application data LCAF address writer class.
372 */
373 public static class AppDataLcafAddressWriter
374 implements LispAddressWriter<LispAppDataLcafAddress> {
375
376 @Override
377 public void writeTo(ByteBuf byteBuf, LispAppDataLcafAddress address)
378 throws LispWriterException {
379
380 LispLcafAddress.serializeCommon(byteBuf, address);
381
Jian Li76ea0572016-08-29 12:41:16 +0900382 byte[] tos = getPartialByteArray(address.getIpTos());
383 byteBuf.writeBytes(tos);
GUNiba871702016-08-22 21:06:02 +0900384 byteBuf.writeByte(address.getProtocol());
385 byteBuf.writeShort(address.getLocalPortLow());
386 byteBuf.writeShort(address.getLocalPortHigh());
387 byteBuf.writeShort(address.getRemotePortLow());
388 byteBuf.writeShort(address.getRemotePortHigh());
389
390 AfiAddressWriter writer = new LispAfiAddress.AfiAddressWriter();
391 writer.writeTo(byteBuf, address.getAddress());
392 }
Jian Li76ea0572016-08-29 12:41:16 +0900393
394 /**
395 * An utility function that obtains byte array from partial int value.
396 *
397 * @param value integer value
398 * @return an array of bytes
399 */
400 public static byte[] getPartialByteArray(int value) {
401 ByteBuffer buffer = ByteBuffer.allocate(4);
402 byte[] array = buffer.putInt(value).array();
403 return Arrays.copyOfRange(array, 1, 4);
404 }
GUNiba871702016-08-22 21:06:02 +0900405 }
Jian Lic7e20a52016-07-18 19:03:49 +0900406}