blob: b4e51396b6951e8c8c4462b15be22d243769c337 [file] [log] [blame]
Jian Li10a09062016-07-26 23:58:50 +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.protocols;
17
Jian Li18f3bce2016-08-04 17:36:41 +090018import com.google.common.base.Objects;
Jian Li47671902016-08-11 01:18:18 +090019import com.google.common.collect.ImmutableList;
20import com.google.common.collect.Lists;
Jian Li26069e22016-08-10 22:00:52 +090021import io.netty.buffer.ByteBuf;
Jian Li47671902016-08-11 01:18:18 +090022import org.onlab.util.ByteOperator;
Jian Li26069e22016-08-10 22:00:52 +090023import org.onosproject.lisp.msg.exceptions.LispParseError;
Jian Lia7b394d2016-08-21 23:11:46 +090024import org.onosproject.lisp.msg.exceptions.LispReaderException;
Jian Liedc5db12016-08-23 17:30:19 +090025import org.onosproject.lisp.msg.exceptions.LispWriterException;
Jian Li10a09062016-07-26 23:58:50 +090026import org.onosproject.lisp.msg.types.LispAfiAddress;
27
Jian Li47671902016-08-11 01:18:18 +090028import java.util.List;
29
Jian Li18f3bce2016-08-04 17:36:41 +090030import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lid4e63702016-08-30 18:29:20 +090031import static com.google.common.base.Preconditions.checkNotNull;
Jian Liedc5db12016-08-23 17:30:19 +090032import static org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
33import static org.onosproject.lisp.msg.protocols.DefaultLispLocatorRecord.LocatorRecordWriter;
Jian Li18f3bce2016-08-04 17:36:41 +090034
Jian Li10a09062016-07-26 23:58:50 +090035/**
36 * Default implementation of LispMapRecord.
37 */
Jian Li631e62a2016-08-03 22:42:00 +090038public final class DefaultLispMapRecord implements LispMapRecord {
Jian Li10a09062016-07-26 23:58:50 +090039
Jian Li631e62a2016-08-03 22:42:00 +090040 private final int recordTtl;
41 private final int locatorCount;
42 private final byte maskLength;
43 private final LispMapReplyAction action;
44 private final boolean authoritative;
45 private final short mapVersionNumber;
46 private final LispAfiAddress eidPrefixAfi;
Jian Li47671902016-08-11 01:18:18 +090047 private final List<LispLocatorRecord> locatorRecords;
Jian Li10a09062016-07-26 23:58:50 +090048
Jian Li631e62a2016-08-03 22:42:00 +090049 /**
50 * A private constructor that protects object instantiation from external.
51 *
52 * @param recordTtl record time-to-live value
53 * @param locatorCount locator's count number
54 * @param maskLength mask length
55 * @param action lisp map reply action
56 * @param authoritative authoritative flag
57 * @param mapVersionNumber map version number
58 * @param eidPrefixAfi EID prefix AFI address
59 */
60 private DefaultLispMapRecord(int recordTtl, int locatorCount, byte maskLength,
61 LispMapReplyAction action, boolean authoritative,
Jian Li47671902016-08-11 01:18:18 +090062 short mapVersionNumber, LispAfiAddress eidPrefixAfi,
63 List<LispLocatorRecord> locatorRecords) {
Jian Li631e62a2016-08-03 22:42:00 +090064 this.recordTtl = recordTtl;
65 this.locatorCount = locatorCount;
66 this.maskLength = maskLength;
67 this.action = action;
68 this.authoritative = authoritative;
69 this.mapVersionNumber = mapVersionNumber;
70 this.eidPrefixAfi = eidPrefixAfi;
Jian Li47671902016-08-11 01:18:18 +090071 this.locatorRecords = locatorRecords;
Jian Li631e62a2016-08-03 22:42:00 +090072 }
73
74 @Override
Jian Li10a09062016-07-26 23:58:50 +090075 public int getRecordTtl() {
76 return recordTtl;
77 }
78
Jian Li631e62a2016-08-03 22:42:00 +090079 @Override
Jian Li10a09062016-07-26 23:58:50 +090080 public int getLocatorCount() {
81 return locatorCount;
82 }
83
Jian Li631e62a2016-08-03 22:42:00 +090084 @Override
Jian Li10a09062016-07-26 23:58:50 +090085 public byte getMaskLength() {
86 return maskLength;
87 }
88
Jian Li631e62a2016-08-03 22:42:00 +090089 @Override
Jian Li10a09062016-07-26 23:58:50 +090090 public LispMapReplyAction getAction() {
91 return action;
92 }
93
Jian Li631e62a2016-08-03 22:42:00 +090094 @Override
Jian Li10a09062016-07-26 23:58:50 +090095 public boolean isAuthoritative() {
96 return authoritative;
97 }
98
Jian Li631e62a2016-08-03 22:42:00 +090099 @Override
Jian Li10a09062016-07-26 23:58:50 +0900100 public short getMapVersionNumber() {
101 return mapVersionNumber;
102 }
103
Jian Li631e62a2016-08-03 22:42:00 +0900104 @Override
Jian Li10a09062016-07-26 23:58:50 +0900105 public LispAfiAddress getEidPrefixAfi() {
106 return eidPrefixAfi;
107 }
108
Jian Li18f3bce2016-08-04 17:36:41 +0900109 @Override
Jian Li47671902016-08-11 01:18:18 +0900110 public List<LispLocatorRecord> getLocators() {
111 return ImmutableList.copyOf(locatorRecords);
112 }
113
114 @Override
115 public void writeTo(ByteBuf byteBuf) {
116
117 }
118
119 @Override
Jian Li18f3bce2016-08-04 17:36:41 +0900120 public String toString() {
121 return toStringHelper(this)
122 .add("record TTL", recordTtl)
123 .add("locatorCount", locatorCount)
124 .add("maskLength", maskLength)
125 .add("action", action)
126 .add("authoritative", authoritative)
127 .add("mapVersionNumber", mapVersionNumber)
Jian Li47671902016-08-11 01:18:18 +0900128 .add("EID prefix AFI address", eidPrefixAfi)
129 .add("locator records", locatorRecords).toString();
130
Jian Li18f3bce2016-08-04 17:36:41 +0900131 }
132
133 @Override
134 public boolean equals(Object o) {
135 if (this == o) {
136 return true;
137 }
138 if (o == null || getClass() != o.getClass()) {
139 return false;
140 }
141 DefaultLispMapRecord that = (DefaultLispMapRecord) o;
142 return Objects.equal(recordTtl, that.recordTtl) &&
143 Objects.equal(locatorCount, that.locatorCount) &&
144 Objects.equal(maskLength, that.maskLength) &&
145 Objects.equal(action, that.action) &&
146 Objects.equal(authoritative, that.authoritative) &&
147 Objects.equal(mapVersionNumber, that.mapVersionNumber) &&
Jian Li47671902016-08-11 01:18:18 +0900148 Objects.equal(eidPrefixAfi, that.eidPrefixAfi) &&
149 Objects.equal(locatorRecords, that.locatorRecords);
Jian Li18f3bce2016-08-04 17:36:41 +0900150 }
151
152 @Override
153 public int hashCode() {
154 return Objects.hashCode(recordTtl, locatorCount, maskLength, action,
Jian Li47671902016-08-11 01:18:18 +0900155 authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
Jian Li18f3bce2016-08-04 17:36:41 +0900156 }
157
Jian Li10a09062016-07-26 23:58:50 +0900158 public static final class DefaultMapRecordBuilder implements MapRecordBuilder {
159
Jian Li631e62a2016-08-03 22:42:00 +0900160 private int recordTtl;
161 private int locatorCount;
162 private byte maskLength;
163 private LispMapReplyAction action;
164 private boolean authoritative;
165 private short mapVersionNumber;
166 private LispAfiAddress eidPrefixAfi;
Jian Lid4e63702016-08-30 18:29:20 +0900167 private List<LispLocatorRecord> locatorRecords = Lists.newArrayList();
Jian Li631e62a2016-08-03 22:42:00 +0900168
Jian Li10a09062016-07-26 23:58:50 +0900169 @Override
170 public MapRecordBuilder withRecordTtl(int recordTtl) {
Jian Li631e62a2016-08-03 22:42:00 +0900171 this.recordTtl = recordTtl;
172 return this;
Jian Li10a09062016-07-26 23:58:50 +0900173 }
174
175 @Override
176 public MapRecordBuilder withLocatorCount(int locatorCount) {
Jian Li631e62a2016-08-03 22:42:00 +0900177 this.locatorCount = locatorCount;
178 return this;
Jian Li10a09062016-07-26 23:58:50 +0900179 }
180
181 @Override
182 public MapRecordBuilder withMaskLength(byte maskLength) {
Jian Li631e62a2016-08-03 22:42:00 +0900183 this.maskLength = maskLength;
184 return this;
Jian Li10a09062016-07-26 23:58:50 +0900185 }
186
187 @Override
188 public MapRecordBuilder withAction(LispMapReplyAction action) {
Jian Li631e62a2016-08-03 22:42:00 +0900189 this.action = action;
190 return this;
Jian Li10a09062016-07-26 23:58:50 +0900191 }
192
193 @Override
194 public MapRecordBuilder withAuthoritative(boolean authoritative) {
Jian Li631e62a2016-08-03 22:42:00 +0900195 this.authoritative = authoritative;
196 return this;
Jian Li10a09062016-07-26 23:58:50 +0900197 }
198
199 @Override
200 public MapRecordBuilder withMapVersionNumber(short mapVersionNumber) {
Jian Li631e62a2016-08-03 22:42:00 +0900201 this.mapVersionNumber = mapVersionNumber;
202 return this;
Jian Li10a09062016-07-26 23:58:50 +0900203 }
204
205 @Override
206 public MapRecordBuilder withEidPrefixAfi(LispAfiAddress prefix) {
Jian Li631e62a2016-08-03 22:42:00 +0900207 this.eidPrefixAfi = prefix;
208 return this;
209 }
210
211 @Override
Jian Li47671902016-08-11 01:18:18 +0900212 public MapRecordBuilder withLocators(List<LispLocatorRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900213 if (records != null) {
214 this.locatorRecords = ImmutableList.copyOf(records);
Jian Lie4ba2a42016-08-29 20:24:15 +0900215 }
Jian Li47671902016-08-11 01:18:18 +0900216 return this;
217 }
218
219 @Override
Jian Li631e62a2016-08-03 22:42:00 +0900220 public LispMapRecord build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900221
Jian Lid4e63702016-08-30 18:29:20 +0900222 checkNotNull(eidPrefixAfi, "Must specify an EID prefix");
Jian Lie4ba2a42016-08-29 20:24:15 +0900223
Jian Li631e62a2016-08-03 22:42:00 +0900224 return new DefaultLispMapRecord(recordTtl, locatorCount, maskLength,
Jian Li47671902016-08-11 01:18:18 +0900225 action, authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
Jian Li10a09062016-07-26 23:58:50 +0900226 }
227 }
Jian Li26069e22016-08-10 22:00:52 +0900228
229 /**
Jian Li47671902016-08-11 01:18:18 +0900230 * A LISP message reader for MapRecord portion.
Jian Li26069e22016-08-10 22:00:52 +0900231 */
Jian Li47671902016-08-11 01:18:18 +0900232 public static final class MapRecordReader implements LispMessageReader<LispMapRecord> {
233
234 private static final int AUTHORITATIVE_INDEX = 4;
235 private static final int RESERVED_SKIP_LENGTH = 1;
Jian Li26069e22016-08-10 22:00:52 +0900236
Jian Lie4ba2a42016-08-29 20:24:15 +0900237 private static final int REPLY_ACTION_SHIFT_BIT = 5;
238
Jian Li26069e22016-08-10 22:00:52 +0900239 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900240 public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900241
242 // Record TTL -> 32 bits
243 int recordTtl = byteBuf.readInt();
244
245 // Locator count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900246 int locatorCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900247
248 // EID mask length -> 8 bits
249 byte maskLength = (byte) byteBuf.readUnsignedByte();
250
Jian Lie4ba2a42016-08-29 20:24:15 +0900251 byte actionWithFlag = (byte) byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900252
Jian Lie4ba2a42016-08-29 20:24:15 +0900253 // action -> 3 bit
254 int actionByte = actionWithFlag >> REPLY_ACTION_SHIFT_BIT;
255 LispMapReplyAction action = LispMapReplyAction.valueOf(actionByte);
256 if (action == null) {
257 action = LispMapReplyAction.NoAction;
258 }
Jian Li47671902016-08-11 01:18:18 +0900259
260 // authoritative flag -> 1 bit
Jian Lie4ba2a42016-08-29 20:24:15 +0900261 boolean authoritative = ByteOperator.getBit((byte) (actionWithFlag >> AUTHORITATIVE_INDEX), 0);
Jian Li47671902016-08-11 01:18:18 +0900262
263 // let's skip the reserved field
264 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
265
266 // Map version number -> 12 bits, we treat Rsvd field is all zero
267 short mapVersionNumber = (short) byteBuf.readUnsignedShort();
268
Jian Lia7b394d2016-08-21 23:11:46 +0900269 LispAfiAddress eidPrefixAfi = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900270
271 List<LispLocatorRecord> locators = Lists.newArrayList();
272 for (int i = 0; i < locatorCount; i++) {
273 locators.add(new DefaultLispLocatorRecord.LocatorRecordReader().readFrom(byteBuf));
274 }
275
276 return new DefaultMapRecordBuilder()
277 .withRecordTtl(recordTtl)
278 .withLocatorCount(locatorCount)
279 .withMaskLength(maskLength)
Jian Lie4ba2a42016-08-29 20:24:15 +0900280 .withAction(action)
Jian Li47671902016-08-11 01:18:18 +0900281 .withAuthoritative(authoritative)
282 .withMapVersionNumber(mapVersionNumber)
283 .withLocators(locators)
Jian Lia7b394d2016-08-21 23:11:46 +0900284 .withEidPrefixAfi(eidPrefixAfi)
Jian Li47671902016-08-11 01:18:18 +0900285 .build();
Jian Li26069e22016-08-10 22:00:52 +0900286 }
287 }
Jian Liedc5db12016-08-23 17:30:19 +0900288
289 /**
290 * A LISP message writer for MapRecord portion.
291 */
292 public static final class MapRecordWriter implements LispMessageWriter<LispMapRecord> {
293
294 private static final int REPLY_ACTION_SHIFT_BIT = 5;
295 private static final int AUTHORITATIVE_FLAG_SHIFT_BIT = 4;
296
297 private static final int ENABLE_BIT = 1;
298 private static final int DISABLE_BIT = 0;
299
300 @Override
301 public void writeTo(ByteBuf byteBuf, LispMapRecord message) throws LispWriterException {
302
303 // record TTL
304 byteBuf.writeInt(message.getRecordTtl());
305
306 // locator count
307 byteBuf.writeByte((byte) message.getLocatorCount());
308
309 // EID mask length
310 byteBuf.writeByte(message.getMaskLength());
311
312 // reply action
313 byte action = (byte) (message.getAction().getAction() << REPLY_ACTION_SHIFT_BIT);
314
315 // authoritative bit
316 byte authoritative = DISABLE_BIT;
317 if (message.isAuthoritative()) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900318 authoritative = ENABLE_BIT << AUTHORITATIVE_FLAG_SHIFT_BIT;
Jian Liedc5db12016-08-23 17:30:19 +0900319 }
Jian Liedc5db12016-08-23 17:30:19 +0900320
321 byteBuf.writeByte((byte) (action + authoritative));
322
323 // fill zero into reserved field
324 byteBuf.writeByte((short) 0);
325
326 // map version number
327 byteBuf.writeShort(message.getMapVersionNumber());
328
329 // EID prefix AFI with EID prefix
330 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
331 afiAddressWriter.writeTo(byteBuf, message.getEidPrefixAfi());
332
333 // serialize locator
334 LocatorRecordWriter recordWriter = new LocatorRecordWriter();
335 List<LispLocatorRecord> locators = message.getLocators();
336 for (int i = 0; i < locators.size(); i++) {
337 recordWriter.writeTo(byteBuf, locators.get(i));
338 }
339 }
340 }
Jian Li10a09062016-07-26 23:58:50 +0900341}