blob: 97e47527b12d44d972367bbc84d93facc43572e2 [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 */
16package org.onosproject.lisp.msg.types;
17
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 Lid4e63702016-08-30 18:29:20 +090022import org.slf4j.Logger;
23import org.slf4j.LoggerFactory;
Jian Lia7b394d2016-08-21 23:11:46 +090024
Jian Li09596002016-07-15 17:46:49 +090025import java.util.Objects;
26
27import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lia7b394d2016-08-21 23:11:46 +090028import static org.onosproject.lisp.msg.types.LispCanonicalAddressFormatEnum.*;
Jian Li09596002016-07-15 17:46:49 +090029
30/**
31 * LISP Canonical Address Formatted address class.
Jian Lib9e1ac72016-11-07 21:15:17 +090032 * <p>
Jian Li8fc2d2f2016-08-08 14:43:53 +090033 * <pre>
34 * {@literal
Jian Lic7e20a52016-07-18 19:03:49 +090035 * 0 1 2 3
36 * 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
37 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 * | AFI = 16387 | Rsvd1 | Flags |
39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * | Type | Rsvd2 | Length |
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Jian Li8fc2d2f2016-08-08 14:43:53 +090042 * }</pre>
Jian Li09596002016-07-15 17:46:49 +090043 */
44public class LispLcafAddress extends LispAfiAddress {
45
Jian Lid4e63702016-08-30 18:29:20 +090046 private static final Logger log = LoggerFactory.getLogger(LispLcafAddress.class);
47
Jian Lia7b394d2016-08-21 23:11:46 +090048 private final LispCanonicalAddressFormatEnum lcafType;
49 private final byte reserved1;
50 private final byte reserved2;
51 private final byte flag;
52 private final short length;
Jian Li09596002016-07-15 17:46:49 +090053
Jian Lib9e1ac72016-11-07 21:15:17 +090054 private static final int LCAF_AFI_CODE_BYTE_LENGTH = 2;
55
Jian Lief0f7232016-11-15 19:55:46 +090056 private static final int LENGTH_FIELD_INDEX = 7;
57 public static final int COMMON_HEADER_SIZE = 8;
58
Jian Li09596002016-07-15 17:46:49 +090059 /**
60 * Initializes LCAF address.
61 *
Jian Lib9e1ac72016-11-07 21:15:17 +090062 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +090063 * @param reserved1 reserved1 field
64 * @param reserved2 reserved2 field
Jian Lib9e1ac72016-11-07 21:15:17 +090065 * @param flag flag field
66 * @param length length field
Jian Li09596002016-07-15 17:46:49 +090067 */
Jian Lic7e20a52016-07-18 19:03:49 +090068 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
Jian Lia7b394d2016-08-21 23:11:46 +090069 byte reserved1, byte reserved2, byte flag, short length) {
Jian Li09596002016-07-15 17:46:49 +090070 super(AddressFamilyIdentifierEnum.LCAF);
71 this.lcafType = lcafType;
Jian Lic7e20a52016-07-18 19:03:49 +090072 this.reserved1 = reserved1;
73 this.reserved2 = reserved2;
74 this.flag = flag;
75 this.length = length;
76 }
77
78 /**
79 * Initializes LCAF address.
80 *
Jian Lib9e1ac72016-11-07 21:15:17 +090081 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +090082 * @param reserved2 reserved2 field
Jian Lib9e1ac72016-11-07 21:15:17 +090083 * @param flag flag field
84 * @param length length field
Jian Lic7e20a52016-07-18 19:03:49 +090085 */
86 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
Jian Lia7b394d2016-08-21 23:11:46 +090087 byte reserved2, byte flag, short length) {
Jian Lic7e20a52016-07-18 19:03:49 +090088 super(AddressFamilyIdentifierEnum.LCAF);
89 this.lcafType = lcafType;
90 this.reserved2 = reserved2;
91 this.flag = flag;
92 this.length = length;
93 this.reserved1 = 0;
94 }
95
96 /**
97 * Initializes LCAF address.
98 *
Jian Lib9e1ac72016-11-07 21:15:17 +090099 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +0900100 * @param reserved2 reserved2 field
Jian Lib9e1ac72016-11-07 21:15:17 +0900101 * @param length length field
Jian Lic7e20a52016-07-18 19:03:49 +0900102 */
103 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType,
Jian Lia7b394d2016-08-21 23:11:46 +0900104 byte reserved2, short length) {
Jian Lic7e20a52016-07-18 19:03:49 +0900105 super(AddressFamilyIdentifierEnum.LCAF);
106 this.lcafType = lcafType;
107 this.reserved2 = reserved2;
108 this.length = length;
109 this.reserved1 = 0;
110 this.flag = 0;
111 }
112
113 /**
114 * Initializes LCAF address.
115 *
Jian Lib9e1ac72016-11-07 21:15:17 +0900116 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +0900117 * @param reserved2 reserved2 field
118 */
119 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, byte reserved2) {
120 super(AddressFamilyIdentifierEnum.LCAF);
121 this.lcafType = lcafType;
122 this.reserved2 = reserved2;
123 this.reserved1 = 0;
124 this.flag = 0;
125 this.length = 0;
126 }
127
128 /**
129 * Initializes LCAF address.
130 *
131 * @param lcafType LCAF type
Jian Lib9e1ac72016-11-07 21:15:17 +0900132 * @param length length field
Jian Lia7b394d2016-08-21 23:11:46 +0900133 */
134 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType, short length) {
135 super(AddressFamilyIdentifierEnum.LCAF);
136 this.lcafType = lcafType;
137 this.reserved1 = 0;
138 this.reserved2 = 0;
139 this.flag = 0;
140 this.length = length;
141 }
142
143 /**
144 * Initializes LCAF address.
145 *
146 * @param lcafType LCAF type
Jian Lic7e20a52016-07-18 19:03:49 +0900147 */
148 protected LispLcafAddress(LispCanonicalAddressFormatEnum lcafType) {
149 super(AddressFamilyIdentifierEnum.LCAF);
150 this.lcafType = lcafType;
151 this.reserved1 = 0;
152 this.reserved2 = 0;
153 this.flag = 0;
154 this.length = 0;
Jian Li09596002016-07-15 17:46:49 +0900155 }
156
157 /**
158 * Obtains LCAF type.
159 *
160 * @return LCAF type
161 */
162 public LispCanonicalAddressFormatEnum getType() {
163 return lcafType;
164 }
165
166 /**
Jian Lic7e20a52016-07-18 19:03:49 +0900167 * Obtains LCAF reserved1 value.
Jian Li09596002016-07-15 17:46:49 +0900168 *
Jian Lic7e20a52016-07-18 19:03:49 +0900169 * @return LCAF reserved1 value
Jian Li09596002016-07-15 17:46:49 +0900170 */
Jian Lic7e20a52016-07-18 19:03:49 +0900171 public byte getReserved1() {
172 return reserved1;
173 }
174
175 /**
176 * Obtains LCAF reserved2 value.
177 *
178 * @return LCAF reserved2 value
179 */
180 public byte getReserved2() {
181 return reserved2;
182 }
183
184 /**
185 * Obtains LCAF flag value.
186 *
187 * @return LCAF flag value
188 */
189 public byte getFlag() {
190 return flag;
191 }
192
193 /**
194 * Obtains LCAF length value.
195 *
196 * @return LCAF length value
197 */
Jian Lia7b394d2016-08-21 23:11:46 +0900198 public short getLength() {
Jian Lic7e20a52016-07-18 19:03:49 +0900199 return length;
Jian Li09596002016-07-15 17:46:49 +0900200 }
201
Jian Lia7b394d2016-08-21 23:11:46 +0900202 /**
203 * Deserializes common fields from byte buffer.
204 *
205 * @param byteBuf byte buffer
206 * @return LispLcafAddress with filled common data fields
207 */
208 public static LispLcafAddress deserializeCommon(ByteBuf byteBuf) {
209
Jian Lib9e1ac72016-11-07 21:15:17 +0900210 // let's skip first and second two bytes
,
211 // because it represents LCAF AFI code
212 byteBuf.skipBytes(LCAF_AFI_CODE_BYTE_LENGTH);
213
Jian Lia7b394d2016-08-21 23:11:46 +0900214 // reserved1 -> 8 bits
215 byte reserved1 = (byte) byteBuf.readUnsignedByte();
216
217 // flags -> 8 bits
218 byte flag = (byte) byteBuf.readUnsignedByte();
219
220 // LCAF type -> 8 bits
221 byte lcafType = (byte) byteBuf.readUnsignedByte();
222
223 // reserved2 -> 8bits
224 byte reserved2 = (byte) byteBuf.readUnsignedByte();
225
226 // length -> 16 bits
227 short length = (short) byteBuf.readUnsignedShort();
228
229 return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
Jian Lib9e1ac72016-11-07 21:15:17 +0900230 reserved1, reserved2, flag, length);
Jian Lia7b394d2016-08-21 23:11:46 +0900231 }
232
GUNiba871702016-08-22 21:06:02 +0900233 /**
Jian Lief0f7232016-11-15 19:55:46 +0900234 * Updates the header length field value based on the size of LISP header.
235 *
236 * @param lcafIndex the index of LCAF address, because LCAF address is
237 * contained inside LISP control message, so to correctly
238 * find the right LCAF length index, we need to know the
239 * absolute lcaf index inside LISP control message byte buf
240 * @param byteBuf netty byte buffer
241 */
242 public static void updateLength(int lcafIndex, ByteBuf byteBuf) {
243 byteBuf.setByte(lcafIndex + LENGTH_FIELD_INDEX, byteBuf.writerIndex() - COMMON_HEADER_SIZE);
244 }
245
246 /**
GUNiba871702016-08-22 21:06:02 +0900247 * Serializes common fields to byte buffer.
248 *
249 * @param byteBuf byte buffer
250 * @param address LISP LCAF address instance
251 */
252 public static void serializeCommon(ByteBuf byteBuf, LispLcafAddress address) {
Jian Lief0f7232016-11-15 19:55:46 +0900253
Jian Lib9e1ac72016-11-07 21:15:17 +0900254 byteBuf.writeShort(AddressFamilyIdentifierEnum.LCAF.getIanaCode());
GUNiba871702016-08-22 21:06:02 +0900255 byteBuf.writeByte(address.getReserved1());
256 byteBuf.writeByte(address.getFlag());
257 byteBuf.writeByte(address.getType().getLispCode());
258 byteBuf.writeByte(address.getReserved2());
259 byteBuf.writeShort(address.getLength());
260 }
261
Jian Li09596002016-07-15 17:46:49 +0900262 @Override
263 public int hashCode() {
Jian Lid56f97e2016-07-19 15:48:15 +0900264 return Objects.hash(lcafType, reserved1, reserved2, flag, length);
Jian Li09596002016-07-15 17:46:49 +0900265 }
266
267 @Override
268 public boolean equals(Object obj) {
269 if (this == obj) {
270 return true;
271 }
272
273 if (obj instanceof LispLcafAddress) {
274 final LispLcafAddress other = (LispLcafAddress) obj;
275 return Objects.equals(this.lcafType, other.lcafType) &&
Jian Lib9e1ac72016-11-07 21:15:17 +0900276 Objects.equals(this.reserved1, other.reserved1) &&
277 Objects.equals(this.reserved2, other.reserved2) &&
278 Objects.equals(this.flag, other.flag) &&
279 Objects.equals(this.length, other.length);
Jian Li09596002016-07-15 17:46:49 +0900280 }
281 return false;
282 }
283
284 @Override
285 public String toString() {
286 return toStringHelper(this)
287 .add("lcafType", lcafType)
Jian Lic7e20a52016-07-18 19:03:49 +0900288 .add("reserved1", reserved1)
289 .add("reserved2", reserved2)
290 .add("flag", flag)
291 .add("length", length)
Jian Li09596002016-07-15 17:46:49 +0900292 .toString();
293 }
Jian Lia7b394d2016-08-21 23:11:46 +0900294
295 protected static class LcafAddressBuilder<T> {
296
297 protected byte reserved1;
298 protected byte flag;
299 protected byte lcafType;
300 protected byte reserved2;
301 protected short length;
302
303 /**
304 * Sets reserved1 value.
305 *
306 * @param reserved1 reserved1 value
307 * @return LcafAddressBuilder object
308 */
309 public T withReserved1(byte reserved1) {
310 this.reserved1 = reserved1;
311 return (T) this;
312 }
313
314 /**
315 * Sets flag.
316 *
317 * @param flag flag boolean
318 * @return LcafAddressBuilder object
319 */
320 public T withFlag(byte flag) {
321 this.flag = flag;
322 return (T) this;
323 }
324
325 /**
326 * Sets LCAF type.
327 *
328 * @param lcafType LCAF type
329 * @return LcafAddressBuilder object
330 */
331 public T withLcafType(byte lcafType) {
332 this.lcafType = lcafType;
333 return (T) this;
334 }
335
336 /**
337 * Sets reserved2 value.
338 *
339 * @param reserved2 reserved2 value
340 * @return LcafAddressBuilder object
341 */
342 public T withReserved2(byte reserved2) {
343 this.reserved2 = reserved2;
344 return (T) this;
345 }
346
347 /**
348 * Sets length value.
349 *
350 * @param length length value
351 * @return LcafAddressBuilder object
352 */
353 public T withLength(short length) {
354 this.length = length;
355 return (T) this;
356 }
357
358 /**
359 * Builds LispLcafAddress object.
360 *
361 * @return LispLcafAddress instance
362 */
363 public LispLcafAddress build() {
364 return new LispLcafAddress(LispCanonicalAddressFormatEnum.valueOf(lcafType),
Jian Lib9e1ac72016-11-07 21:15:17 +0900365 reserved1, reserved2, flag, length);
Jian Lia7b394d2016-08-21 23:11:46 +0900366 }
367 }
368
GUNiba871702016-08-22 21:06:02 +0900369 /**
370 * LISP LCAF reader class.
371 */
Jian Lia7b394d2016-08-21 23:11:46 +0900372 public static class LcafAddressReader implements LispAddressReader<LispLcafAddress> {
373
374 private static final int LCAF_TYPE_FIELD_INDEX = 4;
375
376 @Override
377 public LispLcafAddress readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
378
379 int index = byteBuf.readerIndex();
380
381 // LCAF type -> 8 bits
382 byte lcafType = (byte) byteBuf.getUnsignedByte(index + LCAF_TYPE_FIELD_INDEX);
383
384 if (lcafType == APPLICATION_DATA.getLispCode()) {
385 return new LispAppDataLcafAddress.AppDataLcafAddressReader().readFrom(byteBuf);
386 }
387
388 if (lcafType == LIST.getLispCode()) {
389 return new LispListLcafAddress.ListLcafAddressReader().readFrom(byteBuf);
390 }
391
392 if (lcafType == SEGMENT.getLispCode()) {
393 return new LispSegmentLcafAddress.SegmentLcafAddressReader().readFrom(byteBuf);
394 }
395
396 if (lcafType == SOURCE_DEST.getLispCode()) {
397 return new LispSourceDestLcafAddress.SourceDestLcafAddressReader().readFrom(byteBuf);
398 }
399
Jian Li99f83ef2016-11-03 19:14:25 +0100400 if (lcafType == TRAFFIC_ENGINEERING.getLispCode()) {
Jian Lief0f7232016-11-15 19:55:46 +0900401 return new LispTeLcafAddress.TeLcafAddressReader().readFrom(byteBuf);
Jian Li99f83ef2016-11-03 19:14:25 +0100402 }
403
Jian Lid4e63702016-08-30 18:29:20 +0900404 log.warn("Unsupported LCAF type, please specify a correct LCAF type");
405
Jian Lia7b394d2016-08-21 23:11:46 +0900406 return null;
407 }
408 }
GUNiba871702016-08-22 21:06:02 +0900409
410 /**
411 * LISP LCAF address writer class.
412 */
413 public static class LcafAddressWriter implements LispAddressWriter<LispLcafAddress> {
414
415 @Override
416 public void writeTo(ByteBuf byteBuf, LispLcafAddress address) throws LispWriterException {
417 switch (address.getType()) {
418 case APPLICATION_DATA:
419 new LispAppDataLcafAddress.AppDataLcafAddressWriter().writeTo(byteBuf,
420 (LispAppDataLcafAddress) address);
421 break;
422 case LIST:
423 new LispListLcafAddress.ListLcafAddressWriter().writeTo(byteBuf,
424 (LispListLcafAddress) address);
425 break;
426 case SEGMENT:
427 new LispSegmentLcafAddress.SegmentLcafAddressWriter().writeTo(byteBuf,
428 (LispSegmentLcafAddress) address);
429 break;
430 case SOURCE_DEST:
431 new LispSourceDestLcafAddress.SourceDestLcafAddressWriter().writeTo(byteBuf,
432 (LispSourceDestLcafAddress) address);
433 break;
Jian Li99f83ef2016-11-03 19:14:25 +0100434 case TRAFFIC_ENGINEERING:
Jian Lief0f7232016-11-15 19:55:46 +0900435 new LispTeLcafAddress.TeLcafAddressWriter().writeTo(byteBuf,
Jian Li99f83ef2016-11-03 19:14:25 +0100436 (LispTeLcafAddress) address);
437 break;
Jian Lid4e63702016-08-30 18:29:20 +0900438 default:
439 log.warn("Unsupported LCAF type, please specify a correct LCAF type");
440 break;
GUNiba871702016-08-22 21:06:02 +0900441 }
442 }
443 }
Jian Li09596002016-07-15 17:46:49 +0900444}