blob: a6b5d46c83e443f487ec737ad4bafc7a872dfd46 [file] [log] [blame]
Jian Li09596002016-07-15 17:46: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 */
Jian Lif31019a2017-02-05 07:57:46 +090016package org.onosproject.lisp.msg.types.lcaf;
Jian Li09596002016-07-15 17:46:49 +090017
Jian Lia7b394d2016-08-21 23:11:46 +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 Lif31019a2017-02-05 07:57:46 +090022import org.onosproject.lisp.msg.types.AddressFamilyIdentifierEnum;
23import org.onosproject.lisp.msg.types.LispAddressReader;
24import org.onosproject.lisp.msg.types.LispAddressWriter;
25import org.onosproject.lisp.msg.types.LispAfiAddress;
Jian Lid4e63702016-08-30 18:29:20 +090026import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
Jian Lia7b394d2016-08-21 23:11:46 +090028
Jian Li09596002016-07-15 17:46:49 +090029import java.util.Objects;
30
31import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lif31019a2017-02-05 07:57:46 +090032import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.APPLICATION_DATA;
33import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.LIST;
34import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.NAT;
35import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.SEGMENT;
36import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.SOURCE_DEST;
37import static org.onosproject.lisp.msg.types.lcaf.LispCanonicalAddressFormatEnum.TRAFFIC_ENGINEERING;
Jian Li55ddcdb2016-11-21 17:04:01 +090038
Jian Li09596002016-07-15 17:46:49 +090039
40/**
41 * LISP Canonical Address Formatted address class.
Jian Lib9e1ac72016-11-07 21:15:17 +090042 * <p>
Jian Li8fc2d2f2016-08-08 14:43:53 +090043 * <pre>
44 * {@literal
Jian Lic7e20a52016-07-18 19:03:49 +090045 * 0 1 2 3
46 * 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
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 * | AFI = 16387 | Rsvd1 | Flags |
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 * | Type | Rsvd2 | Length |
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jian Li8fc2d2f2016-08-08 14:43:53 +090052 * }</pre>
Jian Li09596002016-07-15 17:46:49 +090053 */
54public class LispLcafAddress extends LispAfiAddress {
55
Jian Lid4e63702016-08-30 18:29:20 +090056 private static final Logger log = LoggerFactory.getLogger(LispLcafAddress.class);
57
Jian Lia7b394d2016-08-21 23:11:46 +090058 private final LispCanonicalAddressFormatEnum lcafType;
59 private final byte reserved1;
60 private final byte reserved2;
61 private final byte flag;
62 private final short length;
Jian Li09596002016-07-15 17:46:49 +090063
Jian Lib9e1ac72016-11-07 21:15:17 +090064 private static final int LCAF_AFI_CODE_BYTE_LENGTH = 2;
65
Jian Lief0f7232016-11-15 19:55:46 +090066 private static final int LENGTH_FIELD_INDEX = 7;
67 public static final int COMMON_HEADER_SIZE = 8;
68
Jian Li09596002016-07-15 17:46:49 +090069 /**
70 * Initializes LCAF address.
71 *
Jian Lib9e1ac72016-11-07 21:15:17 +090072 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +090073 * @param reserved1 reserved1 field
74 * @param reserved2 reserved2 field
Jian Lib9e1ac72016-11-07 21:15:17 +090075 * @param flag flag field
76 * @param length length field
Jian Li09596002016-07-15 17:46:49 +090077 */
Jian Lic7e20a52016-07-18 19:03:49 +090078 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
Jian Lia7b394d2016-08-21 23:11:46 +090079 byte reserved1, byte reserved2, byte flag, short length) {
Jian Li09596002016-07-15 17:46:49 +090080 super(AddressFamilyIdentifierEnum.LCAF);
81 this.lcafType = lcafType;
Jian Lic7e20a52016-07-18 19:03:49 +090082 this.reserved1 = reserved1;
83 this.reserved2 = reserved2;
84 this.flag = flag;
85 this.length = length;
86 }
87
88 /**
89 * Initializes LCAF address.
90 *
Jian Lib9e1ac72016-11-07 21:15:17 +090091 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +090092 * @param reserved2 reserved2 field
Jian Lib9e1ac72016-11-07 21:15:17 +090093 * @param flag flag field
94 * @param length length field
Jian Lic7e20a52016-07-18 19:03:49 +090095 */
96 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
Jian Lia7b394d2016-08-21 23:11:46 +090097 byte reserved2, byte flag, short length) {
Jian Lic7e20a52016-07-18 19:03:49 +090098 super(AddressFamilyIdentifierEnum.LCAF);
99 this.lcafType = lcafType;
100 this.reserved2 = reserved2;
101 this.flag = flag;
102 this.length = length;
103 this.reserved1 = 0;
104 }
105
106 /**
107 * Initializes LCAF address.
108 *
Jian Lib9e1ac72016-11-07 21:15:17 +0900109 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +0900110 * @param reserved2 reserved2 field
Jian Lib9e1ac72016-11-07 21:15:17 +0900111 * @param length length field
Jian Lic7e20a52016-07-18 19:03:49 +0900112 */
113 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
Jian Lia7b394d2016-08-21 23:11:46 +0900114 byte reserved2, short length) {
Jian Lic7e20a52016-07-18 19:03:49 +0900115 super(AddressFamilyIdentifierEnum.LCAF);
116 this.lcafType = lcafType;
117 this.reserved2 = reserved2;
118 this.length = length;
119 this.reserved1 = 0;
120 this.flag = 0;
121 }
122
123 /**
124 * Initializes LCAF address.
125 *
Jian Lib9e1ac72016-11-07 21:15:17 +0900126 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +0900127 * @param reserved2 reserved2 field
128 */
129 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, byte reserved2) {
130 super(AddressFamilyIdentifierEnum.LCAF);
131 this.lcafType = lcafType;
132 this.reserved2 = reserved2;
133 this.reserved1 = 0;
134 this.flag = 0;
135 this.length = 0;
136 }
137
138 /**
139 * Initializes LCAF address.
140 *
141 * @param lcafType LCAF type
Jian Lib9e1ac72016-11-07 21:15:17 +0900142 * @param length length field
Jian Lia7b394d2016-08-21 23:11:46 +0900143 */
144 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, short length) {
145 super(AddressFamilyIdentifierEnum.LCAF);
146 this.lcafType = lcafType;
147 this.reserved1 = 0;
148 this.reserved2 = 0;
149 this.flag = 0;
150 this.length = length;
151 }
152
153 /**
154 * Initializes LCAF address.
155 *
156 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +0900157 */
158 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType) {
159 super(AddressFamilyIdentifierEnum.LCAF);
160 this.lcafType = lcafType;
161 this.reserved1 = 0;
162 this.reserved2 = 0;
163 this.flag = 0;
164 this.length = 0;
Jian Li09596002016-07-15 17:46:49 +0900165 }
166
167 /**
168 * Obtains LCAF type.
169 *
170 * @return LCAF type
171 */
172 public LispCanonicalAddressFormatEnum getType() {
173 return lcafType;
174 }
175
176 /**
Jian Lic7e20a52016-07-18 19:03:49 +0900177 * Obtains LCAF reserved1 value.
Jian Li09596002016-07-15 17:46:49 +0900178 *
Jian Lic7e20a52016-07-18 19:03:49 +0900179 * @return LCAF reserved1 value
Jian Li09596002016-07-15 17:46:49 +0900180 */
Jian Lic7e20a52016-07-18 19:03:49 +0900181 public byte getReserved1() {
182 return reserved1;
183 }
184
185 /**
186 * Obtains LCAF reserved2 value.
187 *
188 * @return LCAF reserved2 value
189 */
190 public byte getReserved2() {
191 return reserved2;
192 }
193
194 /**
195 * Obtains LCAF flag value.
196 *
197 * @return LCAF flag value
198 */
199 public byte getFlag() {
200 return flag;
201 }
202
203 /**
204 * Obtains LCAF length value.
205 *
206 * @return LCAF length value
207 */
Jian Lia7b394d2016-08-21 23:11:46 +0900208 public short getLength() {
Jian Lic7e20a52016-07-18 19:03:49 +0900209 return length;
Jian Li09596002016-07-15 17:46:49 +0900210 }
211
Jian Lia7b394d2016-08-21 23:11:46 +0900212 /**
213 * Deserializes common fields from byte buffer.
214 *
215 * @param byteBuf byte buffer
216 * @return LispLcafAddress with filled common data fields
217 */
218 public static LispLcafAddress deserializeCommon(ByteBuf byteBuf) {
219
Jian Lib9e1ac72016-11-07 21:15:17 +0900220 // let's skip first and second two bytes
,
221 // because it represents LCAF AFI code
222 byteBuf.skipBytes(LCAF_AFI_CODE_BYTE_LENGTH);
223
Jian Lia7b394d2016-08-21 23:11:46 +0900224 // reserved1 -> 8 bits
225 byte reserved1 = (byte) byteBuf.readUnsignedByte();
226
227 // flags -> 8 bits
228 byte flag = (byte) byteBuf.readUnsignedByte();
229
230 // LCAF type -> 8 bits
231 byte lcafType = (byte) byteBuf.readUnsignedByte();
232
233 // reserved2 -> 8bits
234 byte reserved2 = (byte) byteBuf.readUnsignedByte();
235
236 // length -> 16 bits
237 short length = (short) byteBuf.readUnsignedShort();
238
239 return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
Jian Lib9e1ac72016-11-07 21:15:17 +0900240 reserved1, reserved2, flag, length);
Jian Lia7b394d2016-08-21 23:11:46 +0900241 }
242
GUNiba871702016-08-22 21:06:02 +0900243 /**
Jian Lief0f7232016-11-15 19:55:46 +0900244 * Updates the header length field value based on the size of LISP header.
245 *
246 * @param lcafIndex the index of LCAF address, because LCAF address is
247 * contained inside LISP control message, so to correctly
248 * find the right LCAF length index, we need to know the
249 * absolute lcaf index inside LISP control message byte buf
250 * @param byteBuf netty byte buffer
251 */
252 public static void updateLength(int lcafIndex, ByteBuf byteBuf) {
yoonseon980cd7c2016-11-18 14:18:46 -0800253 byteBuf.setByte(lcafIndex + LENGTH_FIELD_INDEX,
254 byteBuf.writerIndex() - COMMON_HEADER_SIZE - lcafIndex);
Jian Lief0f7232016-11-15 19:55:46 +0900255 }
256
257 /**
GUNiba871702016-08-22 21:06:02 +0900258 * Serializes common fields to byte buffer.
259 *
260 * @param byteBuf byte buffer
261 * @param address LISP LCAF address instance
262 */
263 public static void serializeCommon(ByteBuf byteBuf, LispLcafAddress address) {
Jian Lief0f7232016-11-15 19:55:46 +0900264
Jian Lib9e1ac72016-11-07 21:15:17 +0900265 byteBuf.writeShort(AddressFamilyIdentifierEnum.LCAF.getIanaCode());
GUNiba871702016-08-22 21:06:02 +0900266 byteBuf.writeByte(address.getReserved1());
267 byteBuf.writeByte(address.getFlag());
268 byteBuf.writeByte(address.getType().getLispCode());
269 byteBuf.writeByte(address.getReserved2());
270 byteBuf.writeShort(address.getLength());
271 }
272
Jian Li09596002016-07-15 17:46:49 +0900273 @Override
274 public int hashCode() {
Jian Lid56f97e2016-07-19 15:48:15 +0900275 return Objects.hash(lcafType, reserved1, reserved2, flag, length);
Jian Li09596002016-07-15 17:46:49 +0900276 }
277
278 @Override
279 public boolean equals(Object obj) {
280 if (this == obj) {
281 return true;
282 }
283
284 if (obj instanceof LispLcafAddress) {
285 final LispLcafAddress other = (LispLcafAddress) obj;
286 return Objects.equals(this.lcafType, other.lcafType) &&
Jian Lib9e1ac72016-11-07 21:15:17 +0900287 Objects.equals(this.reserved1, other.reserved1) &&
288 Objects.equals(this.reserved2, other.reserved2) &&
289 Objects.equals(this.flag, other.flag) &&
290 Objects.equals(this.length, other.length);
Jian Li09596002016-07-15 17:46:49 +0900291 }
292 return false;
293 }
294
295 @Override
296 public String toString() {
297 return toStringHelper(this)
298 .add("lcafType", lcafType)
Jian Lic7e20a52016-07-18 19:03:49 +0900299 .add("reserved1", reserved1)
300 .add("reserved2", reserved2)
301 .add("flag", flag)
302 .add("length", length)
Jian Li09596002016-07-15 17:46:49 +0900303 .toString();
304 }
Jian Lia7b394d2016-08-21 23:11:46 +0900305
306 protected static class LcafAddressBuilder<T> {
307
308 protected byte reserved1;
309 protected byte flag;
310 protected byte lcafType;
311 protected byte reserved2;
312 protected short length;
313
314 /**
315 * Sets reserved1 value.
316 *
317 * @param reserved1 reserved1 value
318 * @return LcafAddressBuilder object
319 */
320 public T withReserved1(byte reserved1) {
321 this.reserved1 = reserved1;
322 return (T) this;
323 }
324
325 /**
326 * Sets flag.
327 *
328 * @param flag flag boolean
329 * @return LcafAddressBuilder object
330 */
331 public T withFlag(byte flag) {
332 this.flag = flag;
333 return (T) this;
334 }
335
336 /**
337 * Sets LCAF type.
338 *
339 * @param lcafType LCAF type
340 * @return LcafAddressBuilder object
341 */
342 public T withLcafType(byte lcafType) {
343 this.lcafType = lcafType;
344 return (T) this;
345 }
346
347 /**
348 * Sets reserved2 value.
349 *
350 * @param reserved2 reserved2 value
351 * @return LcafAddressBuilder object
352 */
353 public T withReserved2(byte reserved2) {
354 this.reserved2 = reserved2;
355 return (T) this;
356 }
357
358 /**
359 * Sets length value.
360 *
361 * @param length length value
362 * @return LcafAddressBuilder object
363 */
364 public T withLength(short length) {
365 this.length = length;
366 return (T) this;
367 }
368
369 /**
370 * Builds LispLcafAddress object.
371 *
372 * @return LispLcafAddress instance
373 */
374 public LispLcafAddress build() {
yoonseon980cd7c2016-11-18 14:18:46 -0800375 return new LispLcafAddress(LispCanonicalAddressFormatEnum
376 .valueOf(lcafType),
377 reserved1, reserved2, flag, length);
Jian Lia7b394d2016-08-21 23:11:46 +0900378 }
379 }
380
GUNiba871702016-08-22 21:06:02 +0900381 /**
382 * LISP LCAF reader class.
383 */
yoonseon980cd7c2016-11-18 14:18:46 -0800384 public static class LcafAddressReader
385 implements LispAddressReader<LispLcafAddress> {
Jian Lia7b394d2016-08-21 23:11:46 +0900386
387 private static final int LCAF_TYPE_FIELD_INDEX = 4;
388
389 @Override
yoonseon980cd7c2016-11-18 14:18:46 -0800390 public LispLcafAddress readFrom(ByteBuf byteBuf)
391 throws LispParseError, LispReaderException {
Jian Lia7b394d2016-08-21 23:11:46 +0900392
393 int index = byteBuf.readerIndex();
394
395 // LCAF type -> 8 bits
Jian Li55ddcdb2016-11-21 17:04:01 +0900396 byte lcafType = (byte) byteBuf.getUnsignedByte(index + LCAF_TYPE_FIELD_INDEX);
Jian Lia7b394d2016-08-21 23:11:46 +0900397
398 if (lcafType == APPLICATION_DATA.getLispCode()) {
Jian Lif31019a2017-02-05 07:57:46 +0900399 return new LispAppDataLcafAddress.AppDataLcafAddressReader().readFrom(byteBuf);
Jian Li55ddcdb2016-11-21 17:04:01 +0900400 }
401
402 if (lcafType == NAT.getLispCode()) {
Jian Lif31019a2017-02-05 07:57:46 +0900403 return new LispNatLcafAddress.NatLcafAddressReader().readFrom(byteBuf);
Jian Lia7b394d2016-08-21 23:11:46 +0900404 }
405
406 if (lcafType == LIST.getLispCode()) {
Jian Lif31019a2017-02-05 07:57:46 +0900407 return new LispListLcafAddress.ListLcafAddressReader().readFrom(byteBuf);
Jian Lia7b394d2016-08-21 23:11:46 +0900408 }
409
410 if (lcafType == SEGMENT.getLispCode()) {
Jian Lif31019a2017-02-05 07:57:46 +0900411 return new LispSegmentLcafAddress.SegmentLcafAddressReader().readFrom(byteBuf);
Jian Lia7b394d2016-08-21 23:11:46 +0900412 }
413
414 if (lcafType == SOURCE_DEST.getLispCode()) {
Jian Lif31019a2017-02-05 07:57:46 +0900415 return new LispSourceDestLcafAddress.SourceDestLcafAddressReader().readFrom(byteBuf);
Jian Lia7b394d2016-08-21 23:11:46 +0900416 }
417
Jian Li99f83ef2016-11-03 19:14:25 +0100418 if (lcafType == TRAFFIC_ENGINEERING.getLispCode()) {
Jian Lif31019a2017-02-05 07:57:46 +0900419 return new LispTeLcafAddress.TeLcafAddressReader().readFrom(byteBuf);
Jian Li99f83ef2016-11-03 19:14:25 +0100420 }
421
Jian Lid4e63702016-08-30 18:29:20 +0900422 log.warn("Unsupported LCAF type, please specify a correct LCAF type");
423
Jian Lia7b394d2016-08-21 23:11:46 +0900424 return null;
425 }
426 }
GUNiba871702016-08-22 21:06:02 +0900427
428 /**
429 * LISP LCAF address writer class.
430 */
yoonseon980cd7c2016-11-18 14:18:46 -0800431 public static class LcafAddressWriter
432 implements LispAddressWriter<LispLcafAddress> {
GUNiba871702016-08-22 21:06:02 +0900433
434 @Override
yoonseon980cd7c2016-11-18 14:18:46 -0800435 public void writeTo(ByteBuf byteBuf, LispLcafAddress address)
436 throws LispWriterException {
GUNiba871702016-08-22 21:06:02 +0900437 switch (address.getType()) {
438 case APPLICATION_DATA:
Jian Lif31019a2017-02-05 07:57:46 +0900439 new LispAppDataLcafAddress.AppDataLcafAddressWriter().writeTo(byteBuf,
Jian Li55ddcdb2016-11-21 17:04:01 +0900440 (LispAppDataLcafAddress) address);
441 break;
442 case NAT:
Jian Lif31019a2017-02-05 07:57:46 +0900443 new LispNatLcafAddress.NatLcafAddressWriter().writeTo(byteBuf,
Jian Li55ddcdb2016-11-21 17:04:01 +0900444 (LispNatLcafAddress) address);
GUNiba871702016-08-22 21:06:02 +0900445 break;
446 case LIST:
Jian Lif31019a2017-02-05 07:57:46 +0900447 new LispListLcafAddress.ListLcafAddressWriter().writeTo(byteBuf,
GUNiba871702016-08-22 21:06:02 +0900448 (LispListLcafAddress) address);
449 break;
450 case SEGMENT:
Jian Lif31019a2017-02-05 07:57:46 +0900451 new LispSegmentLcafAddress.SegmentLcafAddressWriter().writeTo(byteBuf,
Jian Li55ddcdb2016-11-21 17:04:01 +0900452 (LispSegmentLcafAddress) address);
GUNiba871702016-08-22 21:06:02 +0900453 break;
454 case SOURCE_DEST:
Jian Lif31019a2017-02-05 07:57:46 +0900455 new LispSourceDestLcafAddress.SourceDestLcafAddressWriter().writeTo(byteBuf,
Jian Li55ddcdb2016-11-21 17:04:01 +0900456 (LispSourceDestLcafAddress) address);
GUNiba871702016-08-22 21:06:02 +0900457 break;
Jian Li99f83ef2016-11-03 19:14:25 +0100458 case TRAFFIC_ENGINEERING:
Jian Lif31019a2017-02-05 07:57:46 +0900459 new LispTeLcafAddress.TeLcafAddressWriter().writeTo(byteBuf,
Jian Li99f83ef2016-11-03 19:14:25 +0100460 (LispTeLcafAddress) address);
461 break;
Jian Lid4e63702016-08-30 18:29:20 +0900462 default:
463 log.warn("Unsupported LCAF type, please specify a correct LCAF type");
464 break;
GUNiba871702016-08-22 21:06:02 +0900465 }
466 }
467 }
Jian Li09596002016-07-15 17:46:49 +0900468}