blob: f53d04dea489cf42a6e7b7697ea7b5786d02e017 [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 Liedc5db12016-08-23 17:30:19 +090031import static org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
32import static org.onosproject.lisp.msg.protocols.DefaultLispLocatorRecord.LocatorRecordWriter;
Jian Li18f3bce2016-08-04 17:36:41 +090033
Jian Li10a09062016-07-26 23:58:50 +090034/**
35 * Default implementation of LispMapRecord.
36 */
Jian Li631e62a2016-08-03 22:42:00 +090037public final class DefaultLispMapRecord implements LispMapRecord {
Jian Li10a09062016-07-26 23:58:50 +090038
Jian Li631e62a2016-08-03 22:42:00 +090039 private final int recordTtl;
40 private final int locatorCount;
41 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
Jian Li631e62a2016-08-03 22:42:00 +090048 /**
49 * A private constructor that protects object instantiation from external.
50 *
51 * @param recordTtl record time-to-live value
52 * @param locatorCount locator's count number
53 * @param maskLength mask length
54 * @param action lisp map reply action
55 * @param authoritative authoritative flag
56 * @param mapVersionNumber map version number
57 * @param eidPrefixAfi EID prefix AFI address
58 */
59 private DefaultLispMapRecord(int recordTtl, int locatorCount, byte maskLength,
60 LispMapReplyAction action, boolean authoritative,
Jian Li47671902016-08-11 01:18:18 +090061 short mapVersionNumber, LispAfiAddress eidPrefixAfi,
62 List<LispLocatorRecord> locatorRecords) {
Jian Li631e62a2016-08-03 22:42:00 +090063 this.recordTtl = recordTtl;
64 this.locatorCount = locatorCount;
65 this.maskLength = maskLength;
66 this.action = action;
67 this.authoritative = authoritative;
68 this.mapVersionNumber = mapVersionNumber;
69 this.eidPrefixAfi = eidPrefixAfi;
Jian Li47671902016-08-11 01:18:18 +090070 this.locatorRecords = locatorRecords;
Jian Li631e62a2016-08-03 22:42:00 +090071 }
72
73 @Override
Jian Li10a09062016-07-26 23:58:50 +090074 public int getRecordTtl() {
75 return recordTtl;
76 }
77
Jian Li631e62a2016-08-03 22:42:00 +090078 @Override
Jian Li10a09062016-07-26 23:58:50 +090079 public int getLocatorCount() {
80 return locatorCount;
81 }
82
Jian Li631e62a2016-08-03 22:42:00 +090083 @Override
Jian Li10a09062016-07-26 23:58:50 +090084 public byte getMaskLength() {
85 return maskLength;
86 }
87
Jian Li631e62a2016-08-03 22:42:00 +090088 @Override
Jian Li10a09062016-07-26 23:58:50 +090089 public LispMapReplyAction getAction() {
90 return action;
91 }
92
Jian Li631e62a2016-08-03 22:42:00 +090093 @Override
Jian Li10a09062016-07-26 23:58:50 +090094 public boolean isAuthoritative() {
95 return authoritative;
96 }
97
Jian Li631e62a2016-08-03 22:42:00 +090098 @Override
Jian Li10a09062016-07-26 23:58:50 +090099 public short getMapVersionNumber() {
100 return mapVersionNumber;
101 }
102
Jian Li631e62a2016-08-03 22:42:00 +0900103 @Override
Jian Li10a09062016-07-26 23:58:50 +0900104 public LispAfiAddress getEidPrefixAfi() {
105 return eidPrefixAfi;
106 }
107
Jian Li18f3bce2016-08-04 17:36:41 +0900108 @Override
Jian Li47671902016-08-11 01:18:18 +0900109 public List<LispLocatorRecord> getLocators() {
110 return ImmutableList.copyOf(locatorRecords);
111 }
112
113 @Override
114 public void writeTo(ByteBuf byteBuf) {
115
116 }
117
118 @Override
Jian Li18f3bce2016-08-04 17:36:41 +0900119 public String toString() {
120 return toStringHelper(this)
121 .add("record TTL", recordTtl)
122 .add("locatorCount", locatorCount)
123 .add("maskLength", maskLength)
124 .add("action", action)
125 .add("authoritative", authoritative)
126 .add("mapVersionNumber", mapVersionNumber)
Jian Li47671902016-08-11 01:18:18 +0900127 .add("EID prefix AFI address", eidPrefixAfi)
128 .add("locator records", locatorRecords).toString();
129
Jian Li18f3bce2016-08-04 17:36:41 +0900130 }
131
132 @Override
133 public boolean equals(Object o) {
134 if (this == o) {
135 return true;
136 }
137 if (o == null || getClass() != o.getClass()) {
138 return false;
139 }
140 DefaultLispMapRecord that = (DefaultLispMapRecord) o;
141 return Objects.equal(recordTtl, that.recordTtl) &&
142 Objects.equal(locatorCount, that.locatorCount) &&
143 Objects.equal(maskLength, that.maskLength) &&
144 Objects.equal(action, that.action) &&
145 Objects.equal(authoritative, that.authoritative) &&
146 Objects.equal(mapVersionNumber, that.mapVersionNumber) &&
Jian Li47671902016-08-11 01:18:18 +0900147 Objects.equal(eidPrefixAfi, that.eidPrefixAfi) &&
148 Objects.equal(locatorRecords, that.locatorRecords);
Jian Li18f3bce2016-08-04 17:36:41 +0900149 }
150
151 @Override
152 public int hashCode() {
153 return Objects.hashCode(recordTtl, locatorCount, maskLength, action,
Jian Li47671902016-08-11 01:18:18 +0900154 authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
Jian Li18f3bce2016-08-04 17:36:41 +0900155 }
156
Jian Li10a09062016-07-26 23:58:50 +0900157 public static final class DefaultMapRecordBuilder implements MapRecordBuilder {
158
Jian Li631e62a2016-08-03 22:42:00 +0900159 private int recordTtl;
160 private int locatorCount;
161 private byte maskLength;
162 private LispMapReplyAction action;
163 private boolean authoritative;
164 private short mapVersionNumber;
165 private LispAfiAddress eidPrefixAfi;
Jian Li47671902016-08-11 01:18:18 +0900166 private List<LispLocatorRecord> locatorRecords;
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
175 public MapRecordBuilder withLocatorCount(int locatorCount) {
Jian Li631e62a2016-08-03 22:42:00 +0900176 this.locatorCount = locatorCount;
177 return this;
Jian Li10a09062016-07-26 23:58:50 +0900178 }
179
180 @Override
181 public MapRecordBuilder withMaskLength(byte maskLength) {
Jian Li631e62a2016-08-03 22:42:00 +0900182 this.maskLength = maskLength;
183 return this;
Jian Li10a09062016-07-26 23:58:50 +0900184 }
185
186 @Override
187 public MapRecordBuilder withAction(LispMapReplyAction action) {
Jian Li631e62a2016-08-03 22:42:00 +0900188 this.action = action;
189 return this;
Jian Li10a09062016-07-26 23:58:50 +0900190 }
191
192 @Override
193 public MapRecordBuilder withAuthoritative(boolean authoritative) {
Jian Li631e62a2016-08-03 22:42:00 +0900194 this.authoritative = authoritative;
195 return this;
Jian Li10a09062016-07-26 23:58:50 +0900196 }
197
198 @Override
199 public MapRecordBuilder withMapVersionNumber(short mapVersionNumber) {
Jian Li631e62a2016-08-03 22:42:00 +0900200 this.mapVersionNumber = mapVersionNumber;
201 return this;
Jian Li10a09062016-07-26 23:58:50 +0900202 }
203
204 @Override
205 public MapRecordBuilder withEidPrefixAfi(LispAfiAddress prefix) {
Jian Li631e62a2016-08-03 22:42:00 +0900206 this.eidPrefixAfi = prefix;
207 return this;
208 }
209
210 @Override
Jian Li47671902016-08-11 01:18:18 +0900211 public MapRecordBuilder withLocators(List<LispLocatorRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900212 if (records != null) {
213 this.locatorRecords = ImmutableList.copyOf(records);
214 } else {
215 this.locatorRecords = Lists.newArrayList();
216 }
Jian Li47671902016-08-11 01:18:18 +0900217 return this;
218 }
219
220 @Override
Jian Li631e62a2016-08-03 22:42:00 +0900221 public LispMapRecord build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900222
223 if (locatorRecords == null) {
224 locatorRecords = Lists.newArrayList();
225 }
226
Jian Li631e62a2016-08-03 22:42:00 +0900227 return new DefaultLispMapRecord(recordTtl, locatorCount, maskLength,
Jian Li47671902016-08-11 01:18:18 +0900228 action, authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
Jian Li10a09062016-07-26 23:58:50 +0900229 }
230 }
Jian Li26069e22016-08-10 22:00:52 +0900231
232 /**
Jian Li47671902016-08-11 01:18:18 +0900233 * A LISP message reader for MapRecord portion.
Jian Li26069e22016-08-10 22:00:52 +0900234 */
Jian Li47671902016-08-11 01:18:18 +0900235 public static final class MapRecordReader implements LispMessageReader<LispMapRecord> {
236
237 private static final int AUTHORITATIVE_INDEX = 4;
238 private static final int RESERVED_SKIP_LENGTH = 1;
Jian Li26069e22016-08-10 22:00:52 +0900239
Jian Lie4ba2a42016-08-29 20:24:15 +0900240 private static final int REPLY_ACTION_SHIFT_BIT = 5;
241
Jian Li26069e22016-08-10 22:00:52 +0900242 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900243 public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900244
245 // Record TTL -> 32 bits
246 int recordTtl = byteBuf.readInt();
247
248 // Locator count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900249 int locatorCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900250
251 // EID mask length -> 8 bits
252 byte maskLength = (byte) byteBuf.readUnsignedByte();
253
Jian Lie4ba2a42016-08-29 20:24:15 +0900254 byte actionWithFlag = (byte) byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900255
Jian Lie4ba2a42016-08-29 20:24:15 +0900256 // action -> 3 bit
257 int actionByte = actionWithFlag >> REPLY_ACTION_SHIFT_BIT;
258 LispMapReplyAction action = LispMapReplyAction.valueOf(actionByte);
259 if (action == null) {
260 action = LispMapReplyAction.NoAction;
261 }
Jian Li47671902016-08-11 01:18:18 +0900262
263 // authoritative flag -> 1 bit
Jian Lie4ba2a42016-08-29 20:24:15 +0900264 boolean authoritative = ByteOperator.getBit((byte) (actionWithFlag >> AUTHORITATIVE_INDEX), 0);
Jian Li47671902016-08-11 01:18:18 +0900265
266 // let's skip the reserved field
267 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
268
269 // Map version number -> 12 bits, we treat Rsvd field is all zero
270 short mapVersionNumber = (short) byteBuf.readUnsignedShort();
271
Jian Lia7b394d2016-08-21 23:11:46 +0900272 LispAfiAddress eidPrefixAfi = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900273
274 List<LispLocatorRecord> locators = Lists.newArrayList();
275 for (int i = 0; i < locatorCount; i++) {
276 locators.add(new DefaultLispLocatorRecord.LocatorRecordReader().readFrom(byteBuf));
277 }
278
279 return new DefaultMapRecordBuilder()
280 .withRecordTtl(recordTtl)
281 .withLocatorCount(locatorCount)
282 .withMaskLength(maskLength)
Jian Lie4ba2a42016-08-29 20:24:15 +0900283 .withAction(action)
Jian Li47671902016-08-11 01:18:18 +0900284 .withAuthoritative(authoritative)
285 .withMapVersionNumber(mapVersionNumber)
286 .withLocators(locators)
Jian Lia7b394d2016-08-21 23:11:46 +0900287 .withEidPrefixAfi(eidPrefixAfi)
Jian Li47671902016-08-11 01:18:18 +0900288 .build();
Jian Li26069e22016-08-10 22:00:52 +0900289 }
290 }
Jian Liedc5db12016-08-23 17:30:19 +0900291
292 /**
293 * A LISP message writer for MapRecord portion.
294 */
295 public static final class MapRecordWriter implements LispMessageWriter<LispMapRecord> {
296
297 private static final int REPLY_ACTION_SHIFT_BIT = 5;
298 private static final int AUTHORITATIVE_FLAG_SHIFT_BIT = 4;
299
300 private static final int ENABLE_BIT = 1;
301 private static final int DISABLE_BIT = 0;
302
303 @Override
304 public void writeTo(ByteBuf byteBuf, LispMapRecord message) throws LispWriterException {
305
306 // record TTL
307 byteBuf.writeInt(message.getRecordTtl());
308
309 // locator count
310 byteBuf.writeByte((byte) message.getLocatorCount());
311
312 // EID mask length
313 byteBuf.writeByte(message.getMaskLength());
314
315 // reply action
316 byte action = (byte) (message.getAction().getAction() << REPLY_ACTION_SHIFT_BIT);
317
318 // authoritative bit
319 byte authoritative = DISABLE_BIT;
320 if (message.isAuthoritative()) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900321 authoritative = ENABLE_BIT << AUTHORITATIVE_FLAG_SHIFT_BIT;
Jian Liedc5db12016-08-23 17:30:19 +0900322 }
Jian Liedc5db12016-08-23 17:30:19 +0900323
324 byteBuf.writeByte((byte) (action + authoritative));
325
326 // fill zero into reserved field
327 byteBuf.writeByte((short) 0);
328
329 // map version number
330 byteBuf.writeShort(message.getMapVersionNumber());
331
332 // EID prefix AFI with EID prefix
333 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
334 afiAddressWriter.writeTo(byteBuf, message.getEidPrefixAfi());
335
336 // serialize locator
337 LocatorRecordWriter recordWriter = new LocatorRecordWriter();
338 List<LispLocatorRecord> locators = message.getLocators();
339 for (int i = 0; i < locators.size(); i++) {
340 recordWriter.writeTo(byteBuf, locators.get(i));
341 }
342 }
343 }
Jian Li10a09062016-07-26 23:58:50 +0900344}