blob: d18e238872babc39a1e253b8858473b1df72f522 [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;
Jian Li631e62a2016-08-03 22:42:00 +090041 private final byte maskLength;
42 private final LispMapReplyAction action;
43 private final boolean authoritative;
44 private final short mapVersionNumber;
45 private final LispAfiAddress eidPrefixAfi;
Jian Li47671902016-08-11 01:18:18 +090046 private final List<LispLocatorRecord> locatorRecords;
Jian Li10a09062016-07-26 23:58:50 +090047
Yoonseon Hanca814bf2016-09-12 11:37:48 -070048 static final MapRecordWriter WRITER;
49 static {
50 WRITER = new MapRecordWriter();
51 }
52
Jian Li631e62a2016-08-03 22:42:00 +090053 /**
54 * A private constructor that protects object instantiation from external.
55 *
56 * @param recordTtl record time-to-live value
Jian Li631e62a2016-08-03 22:42:00 +090057 * @param maskLength mask length
58 * @param action lisp map reply action
59 * @param authoritative authoritative flag
60 * @param mapVersionNumber map version number
61 * @param eidPrefixAfi EID prefix AFI address
62 */
Jian Li42b3e432016-08-31 01:05:20 +090063 private DefaultLispMapRecord(int recordTtl, byte maskLength,
Jian Li631e62a2016-08-03 22:42:00 +090064 LispMapReplyAction action, boolean authoritative,
Jian Li47671902016-08-11 01:18:18 +090065 short mapVersionNumber, LispAfiAddress eidPrefixAfi,
66 List<LispLocatorRecord> locatorRecords) {
Jian Li631e62a2016-08-03 22:42:00 +090067 this.recordTtl = recordTtl;
Jian Li631e62a2016-08-03 22:42:00 +090068 this.maskLength = maskLength;
69 this.action = action;
70 this.authoritative = authoritative;
71 this.mapVersionNumber = mapVersionNumber;
72 this.eidPrefixAfi = eidPrefixAfi;
Jian Li47671902016-08-11 01:18:18 +090073 this.locatorRecords = locatorRecords;
Jian Li631e62a2016-08-03 22:42:00 +090074 }
75
76 @Override
Jian Li10a09062016-07-26 23:58:50 +090077 public int getRecordTtl() {
78 return recordTtl;
79 }
80
Jian Li631e62a2016-08-03 22:42:00 +090081 @Override
Jian Li10a09062016-07-26 23:58:50 +090082 public int getLocatorCount() {
Jian Li42b3e432016-08-31 01:05:20 +090083 return locatorRecords.size();
Jian Li10a09062016-07-26 23:58:50 +090084 }
85
Jian Li631e62a2016-08-03 22:42:00 +090086 @Override
Jian Li10a09062016-07-26 23:58:50 +090087 public byte getMaskLength() {
88 return maskLength;
89 }
90
Jian Li631e62a2016-08-03 22:42:00 +090091 @Override
Jian Li10a09062016-07-26 23:58:50 +090092 public LispMapReplyAction getAction() {
93 return action;
94 }
95
Jian Li631e62a2016-08-03 22:42:00 +090096 @Override
Jian Li10a09062016-07-26 23:58:50 +090097 public boolean isAuthoritative() {
98 return authoritative;
99 }
100
Jian Li631e62a2016-08-03 22:42:00 +0900101 @Override
Jian Li10a09062016-07-26 23:58:50 +0900102 public short getMapVersionNumber() {
103 return mapVersionNumber;
104 }
105
Jian Li631e62a2016-08-03 22:42:00 +0900106 @Override
Jian Li10a09062016-07-26 23:58:50 +0900107 public LispAfiAddress getEidPrefixAfi() {
108 return eidPrefixAfi;
109 }
110
Jian Li18f3bce2016-08-04 17:36:41 +0900111 @Override
Jian Li47671902016-08-11 01:18:18 +0900112 public List<LispLocatorRecord> getLocators() {
113 return ImmutableList.copyOf(locatorRecords);
114 }
115
116 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -0700117 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
118 WRITER.writeTo(byteBuf, this);
Jian Li47671902016-08-11 01:18:18 +0900119 }
120
121 @Override
Jian Li18f3bce2016-08-04 17:36:41 +0900122 public String toString() {
123 return toStringHelper(this)
124 .add("record TTL", recordTtl)
Jian Li18f3bce2016-08-04 17:36:41 +0900125 .add("maskLength", maskLength)
126 .add("action", action)
127 .add("authoritative", authoritative)
128 .add("mapVersionNumber", mapVersionNumber)
Jian Li47671902016-08-11 01:18:18 +0900129 .add("EID prefix AFI address", eidPrefixAfi)
130 .add("locator records", locatorRecords).toString();
131
Jian Li18f3bce2016-08-04 17:36:41 +0900132 }
133
134 @Override
135 public boolean equals(Object o) {
136 if (this == o) {
137 return true;
138 }
139 if (o == null || getClass() != o.getClass()) {
140 return false;
141 }
142 DefaultLispMapRecord that = (DefaultLispMapRecord) o;
143 return Objects.equal(recordTtl, that.recordTtl) &&
Jian Li18f3bce2016-08-04 17:36:41 +0900144 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() {
Jian Li42b3e432016-08-31 01:05:20 +0900154 return Objects.hashCode(recordTtl, 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;
Jian Li631e62a2016-08-03 22:42:00 +0900161 private byte maskLength;
162 private LispMapReplyAction action;
163 private boolean authoritative;
164 private short mapVersionNumber;
165 private LispAfiAddress eidPrefixAfi;
Jian Lid4e63702016-08-30 18:29:20 +0900166 private List<LispLocatorRecord> locatorRecords = Lists.newArrayList();
Jian Li631e62a2016-08-03 22:42:00 +0900167
Jian Li10a09062016-07-26 23:58:50 +0900168 @Override
169 public MapRecordBuilder withRecordTtl(int recordTtl) {
Jian Li631e62a2016-08-03 22:42:00 +0900170 this.recordTtl = recordTtl;
171 return this;
Jian Li10a09062016-07-26 23:58:50 +0900172 }
173
174 @Override
Jian Li10a09062016-07-26 23:58:50 +0900175 public MapRecordBuilder withMaskLength(byte maskLength) {
Jian Li631e62a2016-08-03 22:42:00 +0900176 this.maskLength = maskLength;
177 return this;
Jian Li10a09062016-07-26 23:58:50 +0900178 }
179
180 @Override
181 public MapRecordBuilder withAction(LispMapReplyAction action) {
Jian Li631e62a2016-08-03 22:42:00 +0900182 this.action = action;
183 return this;
Jian Li10a09062016-07-26 23:58:50 +0900184 }
185
186 @Override
187 public MapRecordBuilder withAuthoritative(boolean authoritative) {
Jian Li631e62a2016-08-03 22:42:00 +0900188 this.authoritative = authoritative;
189 return this;
Jian Li10a09062016-07-26 23:58:50 +0900190 }
191
192 @Override
193 public MapRecordBuilder withMapVersionNumber(short mapVersionNumber) {
Jian Li631e62a2016-08-03 22:42:00 +0900194 this.mapVersionNumber = mapVersionNumber;
195 return this;
Jian Li10a09062016-07-26 23:58:50 +0900196 }
197
198 @Override
199 public MapRecordBuilder withEidPrefixAfi(LispAfiAddress prefix) {
Jian Li631e62a2016-08-03 22:42:00 +0900200 this.eidPrefixAfi = prefix;
201 return this;
202 }
203
204 @Override
Jian Li47671902016-08-11 01:18:18 +0900205 public MapRecordBuilder withLocators(List<LispLocatorRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900206 if (records != null) {
207 this.locatorRecords = ImmutableList.copyOf(records);
Jian Lie4ba2a42016-08-29 20:24:15 +0900208 }
Jian Li47671902016-08-11 01:18:18 +0900209 return this;
210 }
211
212 @Override
Jian Li631e62a2016-08-03 22:42:00 +0900213 public LispMapRecord build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900214
Jian Lid4e63702016-08-30 18:29:20 +0900215 checkNotNull(eidPrefixAfi, "Must specify an EID prefix");
Jian Lie4ba2a42016-08-29 20:24:15 +0900216
Jian Li42b3e432016-08-31 01:05:20 +0900217 return new DefaultLispMapRecord(recordTtl, maskLength, action,
218 authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
Jian Li10a09062016-07-26 23:58:50 +0900219 }
220 }
Jian Li26069e22016-08-10 22:00:52 +0900221
222 /**
Jian Li47671902016-08-11 01:18:18 +0900223 * A LISP message reader for MapRecord portion.
Jian Li26069e22016-08-10 22:00:52 +0900224 */
Jian Li47671902016-08-11 01:18:18 +0900225 public static final class MapRecordReader implements LispMessageReader<LispMapRecord> {
226
227 private static final int AUTHORITATIVE_INDEX = 4;
228 private static final int RESERVED_SKIP_LENGTH = 1;
Jian Li26069e22016-08-10 22:00:52 +0900229
Jian Lie4ba2a42016-08-29 20:24:15 +0900230 private static final int REPLY_ACTION_SHIFT_BIT = 5;
231
Jian Li26069e22016-08-10 22:00:52 +0900232 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900233 public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900234
235 // Record TTL -> 32 bits
236 int recordTtl = byteBuf.readInt();
237
238 // Locator count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900239 int locatorCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900240
241 // EID mask length -> 8 bits
242 byte maskLength = (byte) byteBuf.readUnsignedByte();
243
Jian Lie4ba2a42016-08-29 20:24:15 +0900244 byte actionWithFlag = (byte) byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900245
Jian Lie4ba2a42016-08-29 20:24:15 +0900246 // action -> 3 bit
247 int actionByte = actionWithFlag >> REPLY_ACTION_SHIFT_BIT;
248 LispMapReplyAction action = LispMapReplyAction.valueOf(actionByte);
249 if (action == null) {
250 action = LispMapReplyAction.NoAction;
251 }
Jian Li47671902016-08-11 01:18:18 +0900252
253 // authoritative flag -> 1 bit
Jian Lie4ba2a42016-08-29 20:24:15 +0900254 boolean authoritative = ByteOperator.getBit((byte) (actionWithFlag >> AUTHORITATIVE_INDEX), 0);
Jian Li47671902016-08-11 01:18:18 +0900255
256 // let's skip the reserved field
257 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
258
259 // Map version number -> 12 bits, we treat Rsvd field is all zero
260 short mapVersionNumber = (short) byteBuf.readUnsignedShort();
261
Jian Lia7b394d2016-08-21 23:11:46 +0900262 LispAfiAddress eidPrefixAfi = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900263
264 List<LispLocatorRecord> locators = Lists.newArrayList();
265 for (int i = 0; i < locatorCount; i++) {
266 locators.add(new DefaultLispLocatorRecord.LocatorRecordReader().readFrom(byteBuf));
267 }
268
269 return new DefaultMapRecordBuilder()
270 .withRecordTtl(recordTtl)
Jian Li47671902016-08-11 01:18:18 +0900271 .withMaskLength(maskLength)
Jian Lie4ba2a42016-08-29 20:24:15 +0900272 .withAction(action)
Jian Li47671902016-08-11 01:18:18 +0900273 .withAuthoritative(authoritative)
274 .withMapVersionNumber(mapVersionNumber)
275 .withLocators(locators)
Jian Lia7b394d2016-08-21 23:11:46 +0900276 .withEidPrefixAfi(eidPrefixAfi)
Jian Li47671902016-08-11 01:18:18 +0900277 .build();
Jian Li26069e22016-08-10 22:00:52 +0900278 }
279 }
Jian Liedc5db12016-08-23 17:30:19 +0900280
281 /**
282 * A LISP message writer for MapRecord portion.
283 */
284 public static final class MapRecordWriter implements LispMessageWriter<LispMapRecord> {
285
286 private static final int REPLY_ACTION_SHIFT_BIT = 5;
287 private static final int AUTHORITATIVE_FLAG_SHIFT_BIT = 4;
288
289 private static final int ENABLE_BIT = 1;
290 private static final int DISABLE_BIT = 0;
291
292 @Override
293 public void writeTo(ByteBuf byteBuf, LispMapRecord message) throws LispWriterException {
294
295 // record TTL
296 byteBuf.writeInt(message.getRecordTtl());
297
298 // locator count
Jian Li42b3e432016-08-31 01:05:20 +0900299 byteBuf.writeByte((byte) message.getLocators().size());
Jian Liedc5db12016-08-23 17:30:19 +0900300
301 // EID mask length
302 byteBuf.writeByte(message.getMaskLength());
303
304 // reply action
305 byte action = (byte) (message.getAction().getAction() << REPLY_ACTION_SHIFT_BIT);
306
307 // authoritative bit
308 byte authoritative = DISABLE_BIT;
309 if (message.isAuthoritative()) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900310 authoritative = ENABLE_BIT << AUTHORITATIVE_FLAG_SHIFT_BIT;
Jian Liedc5db12016-08-23 17:30:19 +0900311 }
Jian Liedc5db12016-08-23 17:30:19 +0900312
313 byteBuf.writeByte((byte) (action + authoritative));
314
315 // fill zero into reserved field
316 byteBuf.writeByte((short) 0);
317
318 // map version number
319 byteBuf.writeShort(message.getMapVersionNumber());
320
321 // EID prefix AFI with EID prefix
322 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
323 afiAddressWriter.writeTo(byteBuf, message.getEidPrefixAfi());
324
325 // serialize locator
326 LocatorRecordWriter recordWriter = new LocatorRecordWriter();
327 List<LispLocatorRecord> locators = message.getLocators();
328 for (int i = 0; i < locators.size(); i++) {
329 recordWriter.writeTo(byteBuf, locators.get(i));
330 }
331 }
332 }
Jian Li10a09062016-07-26 23:58:50 +0900333}