blob: 49d594d5438df729fe4b787045c76e0f9c27ea68 [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;
Jian Lid4e63702016-08-30 18:29:20 +090028import static com.google.common.base.Preconditions.checkNotNull;
Jian Lic7e20a52016-07-18 19:03:49 +090029
30/**
31 * Application data type LCAF address class.
Jian Li8fc2d2f2016-08-08 14:43:53 +090032 * <p>
Jian Lid6483cc2016-12-12 02:26:13 +090033 * Application data type is defined in draft-ietf-lisp-lcaf-22
34 * https://tools.ietf.org/html/draft-ietf-lisp-lcaf-22#page-27
Jian Lic7e20a52016-07-18 19:03:49 +090035 *
Jian Li8fc2d2f2016-08-08 14:43:53 +090036 * <pre>
37 * {@literal
Jian Lic7e20a52016-07-18 19:03:49 +090038 * 0 1 2 3
39 * 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
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | AFI = 16387 | Rsvd1 | Flags |
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jian Li89c9ca92016-11-11 04:09:02 +090043 * | Type = 4 | Rsvd2 | Length |
Jian Lic7e20a52016-07-18 19:03:49 +090044 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | IP TOS, IPv6 TC, or Flow Label | Protocol |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * | Local Port (lower-range) | Local Port (upper-range) |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * | Remote Port (lower-range) | Remote Port (upper-range) |
50 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 * | AFI = x | Address ... |
52 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jian Li8fc2d2f2016-08-08 14:43:53 +090053 * }</pre>
Jian Lic7e20a52016-07-18 19:03:49 +090054 */
Jian Li115d8602016-08-15 20:21:53 +090055public final class LispAppDataLcafAddress extends LispLcafAddress {
Jian Lic7e20a52016-07-18 19:03:49 +090056
57 private final byte protocol;
58 private final int ipTos;
Jian Li115d8602016-08-15 20:21:53 +090059 private final short localPortLow;
60 private final short localPortHigh;
61 private final short remotePortLow;
62 private final short remotePortHigh;
Jian Lic7e20a52016-07-18 19:03:49 +090063 private LispAfiAddress address;
64
65 /**
Jian Lia7b394d2016-08-21 23:11:46 +090066 * Initializes application data type LCAF address.
67 *
Jian Li115d8602016-08-15 20:21:53 +090068 * @param protocol protocol number
69 * @param ipTos IP type of service
70 * @param localPortLow low-ranged local port number
71 * @param localPortHigh high-ranged local port number
72 * @param remotePortLow low-ranged remote port number
73 * @param remotePortHigh high-ranged remote port number
74 * @param address address
Jian Lic7e20a52016-07-18 19:03:49 +090075 */
Jian Li115d8602016-08-15 20:21:53 +090076 private LispAppDataLcafAddress(byte protocol, int ipTos, short localPortLow,
77 short localPortHigh, short remotePortLow,
78 short remotePortHigh, LispAfiAddress address) {
Jian Lic7e20a52016-07-18 19:03:49 +090079 super(LispCanonicalAddressFormatEnum.APPLICATION_DATA);
80 this.protocol = protocol;
81 this.ipTos = ipTos;
Jian Li115d8602016-08-15 20:21:53 +090082 this.localPortLow = localPortLow;
83 this.localPortHigh = localPortHigh;
84 this.remotePortLow = remotePortLow;
85 this.remotePortHigh = remotePortHigh;
Jian Lic7e20a52016-07-18 19:03:49 +090086 this.address = address;
87 }
88
89 /**
Jian Lia7b394d2016-08-21 23:11:46 +090090 * Initializes application data type LCAF address.
91 *
92 * @param reserved1 reserved1
93 * @param reserved2 reserved2
94 * @param flag flag
95 * @param length length
96 * @param protocol protocol number
97 * @param ipTos IP type of service
98 * @param localPortLow low-ranged local port number
99 * @param localPortHigh high-ranged local port number
100 * @param remotePortLow low-ranged remote port number
101 * @param remotePortHigh high-ranged remote port number
102 * @param address address
103 */
104 private LispAppDataLcafAddress(byte reserved1, byte reserved2, byte flag, short length,
105 byte protocol, int ipTos, short localPortLow,
106 short localPortHigh, short remotePortLow,
107 short remotePortHigh, LispAfiAddress address) {
108 super(LispCanonicalAddressFormatEnum.APPLICATION_DATA, reserved1, reserved2, flag, length);
109 this.protocol = protocol;
110 this.ipTos = ipTos;
111 this.localPortLow = localPortLow;
112 this.localPortHigh = localPortHigh;
113 this.remotePortLow = remotePortLow;
114 this.remotePortHigh = remotePortHigh;
115 this.address = address;
116 }
117
118 /**
Jian Lic7e20a52016-07-18 19:03:49 +0900119 * Obtains protocol number.
120 *
121 * @return protocol number
122 */
123 public byte getProtocol() {
124 return protocol;
125 }
126
127 /**
128 * Obtains IP type of service.
129 *
130 * @return IP type of service
131 */
132 public int getIpTos() {
133 return ipTos;
134 }
135
136 /**
Jian Li115d8602016-08-15 20:21:53 +0900137 * Obtains low-ranged local port number.
Jian Lic7e20a52016-07-18 19:03:49 +0900138 *
Jian Li115d8602016-08-15 20:21:53 +0900139 * @return low-ranged local port number
Jian Lic7e20a52016-07-18 19:03:49 +0900140 */
Jian Li115d8602016-08-15 20:21:53 +0900141 public short getLocalPortLow() {
142 return localPortLow;
Jian Lic7e20a52016-07-18 19:03:49 +0900143 }
144
145 /**
Jian Li115d8602016-08-15 20:21:53 +0900146 * Obtains high-ranged local port number.
Jian Lic7e20a52016-07-18 19:03:49 +0900147 *
Jian Li115d8602016-08-15 20:21:53 +0900148 * @return high-ranged local port number
Jian Lic7e20a52016-07-18 19:03:49 +0900149 */
Jian Li115d8602016-08-15 20:21:53 +0900150 public short getLocalPortHigh() {
151 return localPortHigh;
152 }
153
154 /**
155 * Obtains low-ranged remote port number.
156 *
157 * @return low-ranged remote port number
158 */
159 public short getRemotePortLow() {
160 return remotePortLow;
161 }
162
163 /**
164 * Obtains high-ranged remote port number.
165 *
166 * @return high-ranged remote port number
167 */
168 public short getRemotePortHigh() {
169 return remotePortHigh;
Jian Lic7e20a52016-07-18 19:03:49 +0900170 }
171
172 /**
173 * Obtains address.
174 *
175 * @return address
176 */
177 public LispAfiAddress getAddress() {
178 return address;
179 }
180
181 @Override
182 public int hashCode() {
Jian Li115d8602016-08-15 20:21:53 +0900183 return Objects.hash(address, protocol, ipTos, localPortLow,
184 localPortHigh, remotePortLow, remotePortHigh);
Jian Lic7e20a52016-07-18 19:03:49 +0900185 }
186
187 @Override
188 public boolean equals(Object obj) {
189 if (this == obj) {
190 return true;
191 }
192
193 if (obj instanceof LispAppDataLcafAddress) {
194 final LispAppDataLcafAddress other = (LispAppDataLcafAddress) obj;
195 return Objects.equals(this.address, other.address) &&
196 Objects.equals(this.protocol, other.protocol) &&
197 Objects.equals(this.ipTos, other.ipTos) &&
Jian Li115d8602016-08-15 20:21:53 +0900198 Objects.equals(this.localPortLow, other.localPortLow) &&
199 Objects.equals(this.localPortHigh, other.localPortHigh) &&
200 Objects.equals(this.remotePortLow, other.remotePortLow) &&
201 Objects.equals(this.remotePortHigh, other.remotePortHigh);
Jian Lic7e20a52016-07-18 19:03:49 +0900202 }
203 return false;
204 }
205
206 @Override
207 public String toString() {
208 return toStringHelper(this)
209 .add("address", address)
210 .add("protocol", protocol)
211 .add("ip type of service", ipTos)
Jian Li115d8602016-08-15 20:21:53 +0900212 .add("low-ranged local port number", localPortLow)
213 .add("high-ranged local port number", localPortHigh)
214 .add("low-ranged remote port number", remotePortLow)
215 .add("high-ranged remote port number", remotePortHigh)
Jian Lic7e20a52016-07-18 19:03:49 +0900216 .toString();
217 }
Jian Li115d8602016-08-15 20:21:53 +0900218
Jian Lia7b394d2016-08-21 23:11:46 +0900219 public static final class AppDataAddressBuilder
220 extends LcafAddressBuilder<AppDataAddressBuilder> {
Jian Li115d8602016-08-15 20:21:53 +0900221 private byte protocol;
222 private int ipTos;
223 private short localPortLow;
224 private short localPortHigh;
225 private short remotePortLow;
226 private short remotePortHigh;
227 private LispAfiAddress address;
228
229 /**
230 * Sets protocol number.
231 *
232 * @param protocol protocol number
233 * @return AppDataAddressBuilder object
234 */
Jian Lia7b394d2016-08-21 23:11:46 +0900235 public AppDataAddressBuilder withProtocol(byte protocol) {
Jian Li115d8602016-08-15 20:21:53 +0900236 this.protocol = protocol;
237 return this;
238 }
239
240 /**
241 * Sets IP type of service.
242 *
243 * @param ipTos IP type of service
244 * @return AppDataAddressBuilder object
245 */
Jian Lia7b394d2016-08-21 23:11:46 +0900246 public AppDataAddressBuilder withIpTos(int ipTos) {
Jian Li115d8602016-08-15 20:21:53 +0900247 this.ipTos = ipTos;
248 return this;
249 }
250
251 /**
252 * Sets low-ranged local port number.
253 *
254 * @param localPortLow low-ranged local port number
255 * @return AppDataAddressBuilder object
256 */
Jian Lia7b394d2016-08-21 23:11:46 +0900257 public AppDataAddressBuilder withLocalPortLow(short localPortLow) {
Jian Li115d8602016-08-15 20:21:53 +0900258 this.localPortLow = localPortLow;
259 return this;
260 }
261
262 /**
263 * Sets high-ranged local port number.
264 *
265 * @param localPortHigh high-ranged local port number
266 * @return AppDataAddressBuilder object
267 */
Jian Lia7b394d2016-08-21 23:11:46 +0900268 public AppDataAddressBuilder withLocalPortHigh(short localPortHigh) {
Jian Li115d8602016-08-15 20:21:53 +0900269 this.localPortHigh = localPortHigh;
270 return this;
271 }
272
273 /**
274 * Sets low-ranged remote port number.
275 *
276 * @param remotePortLow low-ranged remote port number
277 * @return AppDataAddressBuilder object
278 */
Jian Lia7b394d2016-08-21 23:11:46 +0900279 public AppDataAddressBuilder withRemotePortLow(short remotePortLow) {
Jian Li115d8602016-08-15 20:21:53 +0900280 this.remotePortLow = remotePortLow;
281 return this;
282 }
283
284 /**
285 * Sets high-ranged remote port number.
286 *
287 * @param remotePortHigh high-ranged remote port number
288 * @return AppDataAddressBuilder object
289 */
Jian Lia7b394d2016-08-21 23:11:46 +0900290 public AppDataAddressBuilder withRemotePortHigh(short remotePortHigh) {
Jian Li115d8602016-08-15 20:21:53 +0900291 this.remotePortHigh = remotePortHigh;
292 return this;
293 }
294
295 /**
296 * Sets AFI address.
297 *
298 * @param address AFI address
299 * @return AppDataAddressBuilder object
300 */
Jian Lia7b394d2016-08-21 23:11:46 +0900301 public AppDataAddressBuilder withAddress(LispAfiAddress address) {
Jian Li115d8602016-08-15 20:21:53 +0900302 this.address = address;
303 return this;
304 }
305
306 /**
307 * Builds LispAppDataLcafAddress instance.
308 *
309 * @return LispAddDataLcafAddress instance
310 */
Jian Lia7b394d2016-08-21 23:11:46 +0900311 public LispAppDataLcafAddress build() {
Jian Lid4e63702016-08-30 18:29:20 +0900312
313 checkNotNull(address, "Must specify an address");
314
Jian Lia7b394d2016-08-21 23:11:46 +0900315 return new LispAppDataLcafAddress(reserved1, reserved2, flag, length,
316 protocol, ipTos, localPortLow, localPortHigh, remotePortLow,
317 remotePortHigh, address);
Jian Li115d8602016-08-15 20:21:53 +0900318 }
319 }
320
321 /**
322 * Application data LCAF address reader class.
323 */
324 public static class AppDataLcafAddressReader
325 implements LispAddressReader<LispAppDataLcafAddress> {
326
327 @Override
328 public LispAppDataLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
329
Jian Li3a99e712016-12-16 21:23:16 +0900330 LispLcafAddress.deserializeCommon(byteBuf);
Jian Lia7b394d2016-08-21 23:11:46 +0900331
Jian Li115d8602016-08-15 20:21:53 +0900332 byte[] ipTosByte = new byte[3];
333 byteBuf.readBytes(ipTosByte);
334
335 byte protocol = (byte) byteBuf.readUnsignedByte();
336 int ipTos = getPartialInt(ipTosByte);
337 short localPortLow = (short) byteBuf.readUnsignedShort();
338 short localPortHigh = (short) byteBuf.readUnsignedShort();
339 short remotePortLow = (short) byteBuf.readUnsignedShort();
340 short remotePortHigh = (short) byteBuf.readUnsignedShort();
341
Jian Lia7b394d2016-08-21 23:11:46 +0900342 LispAfiAddress address = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li115d8602016-08-15 20:21:53 +0900343
344 return new AppDataAddressBuilder()
Jian Lia7b394d2016-08-21 23:11:46 +0900345 .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
Jian Lief0f7232016-11-15 19:55:46 +0900380 int lcafIndex = byteBuf.writerIndex();
GUNiba871702016-08-22 21:06:02 +0900381 LispLcafAddress.serializeCommon(byteBuf, address);
382
Jian Li76ea0572016-08-29 12:41:16 +0900383 byte[] tos = getPartialByteArray(address.getIpTos());
384 byteBuf.writeBytes(tos);
GUNiba871702016-08-22 21:06:02 +0900385 byteBuf.writeByte(address.getProtocol());
386 byteBuf.writeShort(address.getLocalPortLow());
387 byteBuf.writeShort(address.getLocalPortHigh());
388 byteBuf.writeShort(address.getRemotePortLow());
389 byteBuf.writeShort(address.getRemotePortHigh());
390
391 AfiAddressWriter writer = new LispAfiAddress.AfiAddressWriter();
392 writer.writeTo(byteBuf, address.getAddress());
Jian Lief0f7232016-11-15 19:55:46 +0900393
394 LispLcafAddress.updateLength(lcafIndex, byteBuf);
GUNiba871702016-08-22 21:06:02 +0900395 }
Jian Li76ea0572016-08-29 12:41:16 +0900396
397 /**
398 * An utility function that obtains byte array from partial int value.
399 *
400 * @param value integer value
401 * @return an array of bytes
402 */
403 public static byte[] getPartialByteArray(int value) {
404 ByteBuffer buffer = ByteBuffer.allocate(4);
405 byte[] array = buffer.putInt(value).array();
406 return Arrays.copyOfRange(array, 1, 4);
407 }
GUNiba871702016-08-22 21:06:02 +0900408 }
Jian Lic7e20a52016-07-18 19:03:49 +0900409}