blob: ced730640940bf1161a6a9d0d0c35b8784df9d5c [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 Li5e505c62016-12-05 02:44:24 +090024import org.onosproject.lisp.msg.protocols.DefaultLispLocatorRecord.LocatorRecordReader;
25import org.onosproject.lisp.msg.types.LispAfiAddress;
Jian Lia7b394d2016-08-21 23:11:46 +090026import org.onosproject.lisp.msg.exceptions.LispReaderException;
Jian Liedc5db12016-08-23 17:30:19 +090027import org.onosproject.lisp.msg.exceptions.LispWriterException;
Jian Li5e505c62016-12-05 02:44:24 +090028import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
Jian Li10a09062016-07-26 23:58:50 +090029
Jian Li47671902016-08-11 01:18:18 +090030import java.util.List;
31
Jian Li18f3bce2016-08-04 17:36:41 +090032import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lid4e63702016-08-30 18:29:20 +090033import static com.google.common.base.Preconditions.checkNotNull;
Jian Liedc5db12016-08-23 17:30:19 +090034import static org.onosproject.lisp.msg.protocols.DefaultLispLocatorRecord.LocatorRecordWriter;
Jian Li18f3bce2016-08-04 17:36:41 +090035
Jian Li10a09062016-07-26 23:58:50 +090036/**
37 * Default implementation of LispMapRecord.
38 */
Jian Li631e62a2016-08-03 22:42:00 +090039public final class DefaultLispMapRecord implements LispMapRecord {
Jian Li10a09062016-07-26 23:58:50 +090040
Jian Li631e62a2016-08-03 22:42:00 +090041 private final int recordTtl;
Jian Li631e62a2016-08-03 22:42:00 +090042 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
Yoonseon Hanca814bf2016-09-12 11:37:48 -070049 static final MapRecordWriter WRITER;
50 static {
51 WRITER = new MapRecordWriter();
52 }
53
Jian Li631e62a2016-08-03 22:42:00 +090054 /**
55 * A private constructor that protects object instantiation from external.
56 *
57 * @param recordTtl record time-to-live value
Jian Li631e62a2016-08-03 22:42:00 +090058 * @param maskLength mask length
59 * @param action lisp map reply action
60 * @param authoritative authoritative flag
61 * @param mapVersionNumber map version number
62 * @param eidPrefixAfi EID prefix AFI address
63 */
Jian Li42b3e432016-08-31 01:05:20 +090064 private DefaultLispMapRecord(int recordTtl, byte maskLength,
Jian Li631e62a2016-08-03 22:42:00 +090065 LispMapReplyAction action, boolean authoritative,
Jian Li47671902016-08-11 01:18:18 +090066 short mapVersionNumber, LispAfiAddress eidPrefixAfi,
67 List<LispLocatorRecord> locatorRecords) {
Jian Li631e62a2016-08-03 22:42:00 +090068 this.recordTtl = recordTtl;
Jian Li631e62a2016-08-03 22:42:00 +090069 this.maskLength = maskLength;
70 this.action = action;
71 this.authoritative = authoritative;
72 this.mapVersionNumber = mapVersionNumber;
73 this.eidPrefixAfi = eidPrefixAfi;
Jian Li47671902016-08-11 01:18:18 +090074 this.locatorRecords = locatorRecords;
Jian Li631e62a2016-08-03 22:42:00 +090075 }
76
77 @Override
Jian Li10a09062016-07-26 23:58:50 +090078 public int getRecordTtl() {
79 return recordTtl;
80 }
81
Jian Li631e62a2016-08-03 22:42:00 +090082 @Override
Jian Li10a09062016-07-26 23:58:50 +090083 public int getLocatorCount() {
Jian Li42b3e432016-08-31 01:05:20 +090084 return locatorRecords.size();
Jian Li10a09062016-07-26 23:58:50 +090085 }
86
Jian Li631e62a2016-08-03 22:42:00 +090087 @Override
Jian Li10a09062016-07-26 23:58:50 +090088 public byte getMaskLength() {
89 return maskLength;
90 }
91
Jian Li631e62a2016-08-03 22:42:00 +090092 @Override
Jian Li10a09062016-07-26 23:58:50 +090093 public LispMapReplyAction getAction() {
94 return action;
95 }
96
Jian Li631e62a2016-08-03 22:42:00 +090097 @Override
Jian Li10a09062016-07-26 23:58:50 +090098 public boolean isAuthoritative() {
99 return authoritative;
100 }
101
Jian Li631e62a2016-08-03 22:42:00 +0900102 @Override
Jian Li10a09062016-07-26 23:58:50 +0900103 public short getMapVersionNumber() {
104 return mapVersionNumber;
105 }
106
Jian Li631e62a2016-08-03 22:42:00 +0900107 @Override
Jian Li10a09062016-07-26 23:58:50 +0900108 public LispAfiAddress getEidPrefixAfi() {
109 return eidPrefixAfi;
110 }
111
Jian Li18f3bce2016-08-04 17:36:41 +0900112 @Override
Jian Li47671902016-08-11 01:18:18 +0900113 public List<LispLocatorRecord> getLocators() {
114 return ImmutableList.copyOf(locatorRecords);
115 }
116
117 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -0700118 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
119 WRITER.writeTo(byteBuf, this);
Jian Li47671902016-08-11 01:18:18 +0900120 }
121
122 @Override
Jian Li18f3bce2016-08-04 17:36:41 +0900123 public String toString() {
124 return toStringHelper(this)
125 .add("record TTL", recordTtl)
Jian Li18f3bce2016-08-04 17:36:41 +0900126 .add("maskLength", maskLength)
127 .add("action", action)
128 .add("authoritative", authoritative)
129 .add("mapVersionNumber", mapVersionNumber)
Jian Li47671902016-08-11 01:18:18 +0900130 .add("EID prefix AFI address", eidPrefixAfi)
131 .add("locator records", locatorRecords).toString();
132
Jian Li18f3bce2016-08-04 17:36:41 +0900133 }
134
135 @Override
136 public boolean equals(Object o) {
137 if (this == o) {
138 return true;
139 }
140 if (o == null || getClass() != o.getClass()) {
141 return false;
142 }
143 DefaultLispMapRecord that = (DefaultLispMapRecord) o;
144 return Objects.equal(recordTtl, that.recordTtl) &&
Jian Li18f3bce2016-08-04 17:36:41 +0900145 Objects.equal(maskLength, that.maskLength) &&
146 Objects.equal(action, that.action) &&
147 Objects.equal(authoritative, that.authoritative) &&
148 Objects.equal(mapVersionNumber, that.mapVersionNumber) &&
Jian Li47671902016-08-11 01:18:18 +0900149 Objects.equal(eidPrefixAfi, that.eidPrefixAfi) &&
150 Objects.equal(locatorRecords, that.locatorRecords);
Jian Li18f3bce2016-08-04 17:36:41 +0900151 }
152
153 @Override
154 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900155 return Objects.hashCode(recordTtl, maskLength, action,
Jian Li47671902016-08-11 01:18:18 +0900156 authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
Jian Li18f3bce2016-08-04 17:36:41 +0900157 }
158
Jian Li10a09062016-07-26 23:58:50 +0900159 public static final class DefaultMapRecordBuilder implements MapRecordBuilder {
160
Jian Li631e62a2016-08-03 22:42:00 +0900161 private int recordTtl;
Jian Li631e62a2016-08-03 22:42:00 +0900162 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
Jian Li10a09062016-07-26 23:58:50 +0900176 public MapRecordBuilder withMaskLength(byte maskLength) {
Jian Li631e62a2016-08-03 22:42:00 +0900177 this.maskLength = maskLength;
178 return this;
Jian Li10a09062016-07-26 23:58:50 +0900179 }
180
181 @Override
182 public MapRecordBuilder withAction(LispMapReplyAction action) {
Jian Li631e62a2016-08-03 22:42:00 +0900183 this.action = action;
184 return this;
Jian Li10a09062016-07-26 23:58:50 +0900185 }
186
187 @Override
188 public MapRecordBuilder withAuthoritative(boolean authoritative) {
Jian Li631e62a2016-08-03 22:42:00 +0900189 this.authoritative = authoritative;
190 return this;
Jian Li10a09062016-07-26 23:58:50 +0900191 }
192
193 @Override
194 public MapRecordBuilder withMapVersionNumber(short mapVersionNumber) {
Jian Li631e62a2016-08-03 22:42:00 +0900195 this.mapVersionNumber = mapVersionNumber;
196 return this;
Jian Li10a09062016-07-26 23:58:50 +0900197 }
198
199 @Override
200 public MapRecordBuilder withEidPrefixAfi(LispAfiAddress prefix) {
Jian Li631e62a2016-08-03 22:42:00 +0900201 this.eidPrefixAfi = prefix;
202 return this;
203 }
204
205 @Override
Jian Li47671902016-08-11 01:18:18 +0900206 public MapRecordBuilder withLocators(List<LispLocatorRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900207 if (records != null) {
208 this.locatorRecords = ImmutableList.copyOf(records);
Jian Lie4ba2a42016-08-29 20:24:15 +0900209 }
Jian Li47671902016-08-11 01:18:18 +0900210 return this;
211 }
212
213 @Override
Jian Li631e62a2016-08-03 22:42:00 +0900214 public LispMapRecord build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900215
Jian Lid4e63702016-08-30 18:29:20 +0900216 checkNotNull(eidPrefixAfi, "Must specify an EID prefix");
Jian Lie4ba2a42016-08-29 20:24:15 +0900217
Jian Li42b3e432016-08-31 01:05:20 +0900218 return new DefaultLispMapRecord(recordTtl, maskLength, action,
219 authoritative, mapVersionNumber, eidPrefixAfi, locatorRecords);
Jian Li10a09062016-07-26 23:58:50 +0900220 }
221 }
Jian Li26069e22016-08-10 22:00:52 +0900222
223 /**
Jian Li47671902016-08-11 01:18:18 +0900224 * A LISP message reader for MapRecord portion.
Jian Li26069e22016-08-10 22:00:52 +0900225 */
Jian Li47671902016-08-11 01:18:18 +0900226 public static final class MapRecordReader implements LispMessageReader<LispMapRecord> {
227
228 private static final int AUTHORITATIVE_INDEX = 4;
229 private static final int RESERVED_SKIP_LENGTH = 1;
Jian Li26069e22016-08-10 22:00:52 +0900230
Jian Lie4ba2a42016-08-29 20:24:15 +0900231 private static final int REPLY_ACTION_SHIFT_BIT = 5;
232
Jian Li26069e22016-08-10 22:00:52 +0900233 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900234 public LispMapRecord readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900235
236 // Record TTL -> 32 bits
237 int recordTtl = byteBuf.readInt();
238
239 // Locator count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900240 int locatorCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900241
242 // EID mask length -> 8 bits
243 byte maskLength = (byte) byteBuf.readUnsignedByte();
244
Jian Lie4ba2a42016-08-29 20:24:15 +0900245 byte actionWithFlag = (byte) byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900246
Jian Lie4ba2a42016-08-29 20:24:15 +0900247 // action -> 3 bit
248 int actionByte = actionWithFlag >> REPLY_ACTION_SHIFT_BIT;
249 LispMapReplyAction action = LispMapReplyAction.valueOf(actionByte);
250 if (action == null) {
251 action = LispMapReplyAction.NoAction;
252 }
Jian Li47671902016-08-11 01:18:18 +0900253
254 // authoritative flag -> 1 bit
Jian Lie4ba2a42016-08-29 20:24:15 +0900255 boolean authoritative = ByteOperator.getBit((byte) (actionWithFlag >> AUTHORITATIVE_INDEX), 0);
Jian Li47671902016-08-11 01:18:18 +0900256
257 // let's skip the reserved field
258 byteBuf.skipBytes(RESERVED_SKIP_LENGTH);
259
260 // Map version number -> 12 bits, we treat Rsvd field is all zero
261 short mapVersionNumber = (short) byteBuf.readUnsignedShort();
262
Jian Lia7b394d2016-08-21 23:11:46 +0900263 LispAfiAddress eidPrefixAfi = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900264
265 List<LispLocatorRecord> locators = Lists.newArrayList();
266 for (int i = 0; i < locatorCount; i++) {
Jian Li5e505c62016-12-05 02:44:24 +0900267 locators.add(new LocatorRecordReader().readFrom(byteBuf));
Jian Li47671902016-08-11 01:18:18 +0900268 }
269
270 return new DefaultMapRecordBuilder()
271 .withRecordTtl(recordTtl)
Jian Li47671902016-08-11 01:18:18 +0900272 .withMaskLength(maskLength)
Jian Lie4ba2a42016-08-29 20:24:15 +0900273 .withAction(action)
Jian Li47671902016-08-11 01:18:18 +0900274 .withAuthoritative(authoritative)
275 .withMapVersionNumber(mapVersionNumber)
276 .withLocators(locators)
Jian Lia7b394d2016-08-21 23:11:46 +0900277 .withEidPrefixAfi(eidPrefixAfi)
Jian Li47671902016-08-11 01:18:18 +0900278 .build();
Jian Li26069e22016-08-10 22:00:52 +0900279 }
280 }
Jian Liedc5db12016-08-23 17:30:19 +0900281
282 /**
283 * A LISP message writer for MapRecord portion.
284 */
285 public static final class MapRecordWriter implements LispMessageWriter<LispMapRecord> {
286
287 private static final int REPLY_ACTION_SHIFT_BIT = 5;
288 private static final int AUTHORITATIVE_FLAG_SHIFT_BIT = 4;
289
290 private static final int ENABLE_BIT = 1;
291 private static final int DISABLE_BIT = 0;
292
293 @Override
294 public void writeTo(ByteBuf byteBuf, LispMapRecord message) throws LispWriterException {
295
296 // record TTL
297 byteBuf.writeInt(message.getRecordTtl());
298
299 // locator count
Jian Li42b3e432016-08-31 01:05:20 +0900300 byteBuf.writeByte((byte) message.getLocators().size());
Jian Liedc5db12016-08-23 17:30:19 +0900301
302 // EID mask length
303 byteBuf.writeByte(message.getMaskLength());
304
305 // reply action
306 byte action = (byte) (message.getAction().getAction() << REPLY_ACTION_SHIFT_BIT);
307
308 // authoritative bit
309 byte authoritative = DISABLE_BIT;
310 if (message.isAuthoritative()) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900311 authoritative = ENABLE_BIT << AUTHORITATIVE_FLAG_SHIFT_BIT;
Jian Liedc5db12016-08-23 17:30:19 +0900312 }
Jian Liedc5db12016-08-23 17:30:19 +0900313
314 byteBuf.writeByte((byte) (action + authoritative));
315
316 // fill zero into reserved field
317 byteBuf.writeByte((short) 0);
318
319 // map version number
320 byteBuf.writeShort(message.getMapVersionNumber());
321
322 // EID prefix AFI with EID prefix
323 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
324 afiAddressWriter.writeTo(byteBuf, message.getEidPrefixAfi());
325
326 // serialize locator
327 LocatorRecordWriter recordWriter = new LocatorRecordWriter();
328 List<LispLocatorRecord> locators = message.getLocators();
329 for (int i = 0; i < locators.size(); i++) {
330 recordWriter.writeTo(byteBuf, locators.get(i));
331 }
332 }
333 }
Jian Li10a09062016-07-26 23:58:50 +0900334}