blob: 9055e409a3c258f120a10dd344a5c20cd7795d3c [file] [log] [blame]
Jian Li451175e2016-07-19 23:22:20 +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 Li20850d32016-08-04 02:15:57 +090018import com.google.common.base.Objects;
Jian Lif59c0ad2016-08-02 18:11:30 +090019import com.google.common.collect.ImmutableList;
20import com.google.common.collect.Lists;
Jian Li451175e2016-07-19 23:22:20 +090021import io.netty.buffer.ByteBuf;
Jian Li47671902016-08-11 01:18:18 +090022import org.onlab.util.ByteOperator;
Jian Li5e505c62016-12-05 02:44:24 +090023import org.onosproject.lisp.msg.protocols.LispEidRecord.EidRecordReader;
24import org.onosproject.lisp.msg.types.LispAfiAddress;
Jian Li26069e22016-08-10 22:00:52 +090025import org.onosproject.lisp.msg.exceptions.LispParseError;
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.AfiAddressReader;
29import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter;
Jian Li719b3bf2016-07-22 00:38:29 +090030
31import java.util.List;
Jian Li451175e2016-07-19 23:22:20 +090032
Jian Li20850d32016-08-04 02:15:57 +090033import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lie4ba2a42016-08-29 20:24:15 +090034import static com.google.common.base.Preconditions.checkArgument;
Jian Liedc5db12016-08-23 17:30:19 +090035import static org.onosproject.lisp.msg.protocols.LispEidRecord.EidRecordWriter;
Jian Li20850d32016-08-04 02:15:57 +090036
Jian Li451175e2016-07-19 23:22:20 +090037/**
38 * Default LISP map request message class.
39 */
Jian Liafe2d3f2016-11-01 02:49:07 +090040public final class DefaultLispMapRequest extends AbstractLispMessage
41 implements LispMapRequest {
Jian Lif59c0ad2016-08-02 18:11:30 +090042
43 private final long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090044 private final LispAfiAddress sourceEid;
45 private final List<LispAfiAddress> itrRlocs;
46 private final List<LispEidRecord> eidRecords;
47 private final boolean authoritative;
48 private final boolean mapDataPresent;
49 private final boolean probe;
50 private final boolean smr;
51 private final boolean pitr;
52 private final boolean smrInvoked;
53
Yoonseon Hanca814bf2016-09-12 11:37:48 -070054 static final RequestWriter WRITER;
55 static {
56 WRITER = new RequestWriter();
57 }
58
Jian Lif59c0ad2016-08-02 18:11:30 +090059 /**
60 * A private constructor that protects object instantiation from external.
61 *
62 * @param nonce nonce
Jian Lif59c0ad2016-08-02 18:11:30 +090063 * @param sourceEid source EID address
64 * @param itrRlocs a collection of ITR RLOCs
65 * @param eidRecords a collection of EID records
66 * @param authoritative authoritative flag
67 * @param mapDataPresent map data present flag
68 * @param probe probe flag
69 * @param smr smr flag
70 * @param pitr pitr flag
71 * @param smrInvoked smrInvoked flag
72 */
Jian Li42b3e432016-08-31 01:05:20 +090073 private DefaultLispMapRequest(long nonce, LispAfiAddress sourceEid,
Jian Lif59c0ad2016-08-02 18:11:30 +090074 List<LispAfiAddress> itrRlocs, List<LispEidRecord> eidRecords,
75 boolean authoritative, boolean mapDataPresent, boolean probe,
76 boolean smr, boolean pitr, boolean smrInvoked) {
77 this.nonce = nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +090078 this.sourceEid = sourceEid;
79 this.itrRlocs = itrRlocs;
80 this.eidRecords = eidRecords;
81 this.authoritative = authoritative;
82 this.mapDataPresent = mapDataPresent;
83 this.probe = probe;
84 this.smr = smr;
85 this.pitr = pitr;
86 this.smrInvoked = smrInvoked;
87 }
88
Jian Li451175e2016-07-19 23:22:20 +090089 @Override
90 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +090091 return LispType.LISP_MAP_REQUEST;
Jian Li451175e2016-07-19 23:22:20 +090092 }
93
94 @Override
Yoonseon Hanca814bf2016-09-12 11:37:48 -070095 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
96 WRITER.writeTo(byteBuf, this);
Jian Li451175e2016-07-19 23:22:20 +090097 }
98
99 @Override
100 public Builder createBuilder() {
Jian Li525fded2016-08-04 01:15:33 +0900101 return new DefaultRequestBuilder();
Jian Li451175e2016-07-19 23:22:20 +0900102 }
Jian Li719b3bf2016-07-22 00:38:29 +0900103
104 @Override
105 public boolean isAuthoritative() {
Jian Liedc5db12016-08-23 17:30:19 +0900106 return authoritative;
Jian Lif59c0ad2016-08-02 18:11:30 +0900107 }
108
109 @Override
110 public boolean isMapDataPresent() {
Jian Liedc5db12016-08-23 17:30:19 +0900111 return mapDataPresent;
Jian Li719b3bf2016-07-22 00:38:29 +0900112 }
113
114 @Override
115 public boolean isProbe() {
Jian Liedc5db12016-08-23 17:30:19 +0900116 return probe;
Jian Li719b3bf2016-07-22 00:38:29 +0900117 }
118
119 @Override
120 public boolean isSmr() {
Jian Liedc5db12016-08-23 17:30:19 +0900121 return smr;
Jian Li719b3bf2016-07-22 00:38:29 +0900122 }
123
124 @Override
125 public boolean isPitr() {
Jian Liedc5db12016-08-23 17:30:19 +0900126 return pitr;
Jian Li719b3bf2016-07-22 00:38:29 +0900127 }
128
129 @Override
130 public boolean isSmrInvoked() {
Jian Liedc5db12016-08-23 17:30:19 +0900131 return smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900132 }
133
134 @Override
Jian Li42b3e432016-08-31 01:05:20 +0900135 public int getRecordCount() {
136 return eidRecords.size();
Jian Li719b3bf2016-07-22 00:38:29 +0900137 }
138
139 @Override
140 public long getNonce() {
Jian Liedc5db12016-08-23 17:30:19 +0900141 return nonce;
Jian Li719b3bf2016-07-22 00:38:29 +0900142 }
143
144 @Override
145 public LispAfiAddress getSourceEid() {
Jian Liedc5db12016-08-23 17:30:19 +0900146 return sourceEid;
Jian Li719b3bf2016-07-22 00:38:29 +0900147 }
148
149 @Override
150 public List<LispAfiAddress> getItrRlocs() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900151 return ImmutableList.copyOf(itrRlocs);
Jian Li719b3bf2016-07-22 00:38:29 +0900152 }
153
154 @Override
Jian Li10a09062016-07-26 23:58:50 +0900155 public List<LispEidRecord> getEids() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900156 return ImmutableList.copyOf(eidRecords);
Jian Li719b3bf2016-07-22 00:38:29 +0900157 }
158
Jian Li20850d32016-08-04 02:15:57 +0900159 @Override
160 public String toString() {
161 return toStringHelper(this)
162 .add("type", getType())
163 .add("nonce", nonce)
Jian Li20850d32016-08-04 02:15:57 +0900164 .add("source EID", sourceEid)
165 .add("ITR rlocs", itrRlocs)
166 .add("EID records", eidRecords)
167 .add("authoritative", authoritative)
168 .add("mapDataPresent", mapDataPresent)
169 .add("probe", probe)
170 .add("SMR", smr)
171 .add("Proxy ITR", pitr)
172 .add("SMR Invoked", smrInvoked).toString();
173 }
174
175 @Override
176 public boolean equals(Object o) {
177 if (this == o) {
178 return true;
179 }
180 if (o == null || getClass() != o.getClass()) {
181 return false;
182 }
183 DefaultLispMapRequest that = (DefaultLispMapRequest) o;
184 return Objects.equal(nonce, that.nonce) &&
Jian Li20850d32016-08-04 02:15:57 +0900185 Objects.equal(sourceEid, that.sourceEid) &&
Jian Li20850d32016-08-04 02:15:57 +0900186 Objects.equal(authoritative, that.authoritative) &&
187 Objects.equal(mapDataPresent, that.mapDataPresent) &&
188 Objects.equal(probe, that.probe) &&
189 Objects.equal(smr, that.smr) &&
190 Objects.equal(pitr, that.pitr) &&
191 Objects.equal(smrInvoked, that.smrInvoked);
192 }
193
194 @Override
195 public int hashCode() {
Jian Li42b3e432016-08-31 01:05:20 +0900196 return Objects.hashCode(nonce, sourceEid, authoritative,
Jian Lie4ba2a42016-08-29 20:24:15 +0900197 mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li20850d32016-08-04 02:15:57 +0900198 }
199
Jian Li719b3bf2016-07-22 00:38:29 +0900200 public static final class DefaultRequestBuilder implements RequestBuilder {
201
Jian Lif59c0ad2016-08-02 18:11:30 +0900202 private long nonce;
Jian Lif59c0ad2016-08-02 18:11:30 +0900203 private LispAfiAddress sourceEid;
204 private List<LispAfiAddress> itrRlocs = Lists.newArrayList();
205 private List<LispEidRecord> eidRecords = Lists.newArrayList();
206 private boolean authoritative;
207 private boolean mapDataPresent;
208 private boolean probe;
209 private boolean smr;
210 private boolean pitr;
211 private boolean smrInvoked;
Jian Li719b3bf2016-07-22 00:38:29 +0900212
213 @Override
214 public LispType getType() {
Jian Lif59c0ad2016-08-02 18:11:30 +0900215 return LispType.LISP_MAP_REQUEST;
Jian Li719b3bf2016-07-22 00:38:29 +0900216 }
217
218 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900219 public RequestBuilder withIsAuthoritative(boolean authoritative) {
220 this.authoritative = authoritative;
221 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900222 }
223
224 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900225 public RequestBuilder withIsProbe(boolean probe) {
226 this.probe = probe;
227 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900228 }
229
230 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900231 public RequestBuilder withIsMapDataPresent(boolean mapDataPresent) {
232 this.mapDataPresent = mapDataPresent;
233 return this;
234 }
235
Jian Lif59c0ad2016-08-02 18:11:30 +0900236 @Override
237 public RequestBuilder withIsSmr(boolean smr) {
238 this.smr = smr;
239 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900240 }
241
242 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900243 public RequestBuilder withIsPitr(boolean pitr) {
244 this.pitr = pitr;
245 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900246 }
247
248 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900249 public RequestBuilder withIsSmrInvoked(boolean smrInvoked) {
250 this.smrInvoked = smrInvoked;
251 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900252 }
253
254 @Override
Jian Li719b3bf2016-07-22 00:38:29 +0900255 public RequestBuilder withNonce(long nonce) {
Jian Lif59c0ad2016-08-02 18:11:30 +0900256 this.nonce = nonce;
257 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900258 }
259
260 @Override
Jian Lif59c0ad2016-08-02 18:11:30 +0900261 public RequestBuilder withSourceEid(LispAfiAddress sourceEid) {
262 this.sourceEid = sourceEid;
263 return this;
264 }
265
266 @Override
Jian Li47671902016-08-11 01:18:18 +0900267 public RequestBuilder withItrRlocs(List<LispAfiAddress> itrRlocs) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900268 if (itrRlocs != null) {
269 this.itrRlocs = ImmutableList.copyOf(itrRlocs);
Jian Lie4ba2a42016-08-29 20:24:15 +0900270 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900271 return this;
Jian Li719b3bf2016-07-22 00:38:29 +0900272 }
273
274 @Override
Jian Li47671902016-08-11 01:18:18 +0900275 public RequestBuilder withEidRecords(List<LispEidRecord> records) {
Jian Lie4ba2a42016-08-29 20:24:15 +0900276 if (records != null) {
277 this.eidRecords = ImmutableList.copyOf(records);
Jian Lie4ba2a42016-08-29 20:24:15 +0900278 }
Jian Lif59c0ad2016-08-02 18:11:30 +0900279 return this;
280 }
281
282 @Override
Jian Li525fded2016-08-04 01:15:33 +0900283 public LispMapRequest build() {
Jian Lie4ba2a42016-08-29 20:24:15 +0900284
Jian Lie4ba2a42016-08-29 20:24:15 +0900285 checkArgument((itrRlocs != null) && (itrRlocs.size() > 0), "Must have an ITR RLOC entry");
286
Jian Li42b3e432016-08-31 01:05:20 +0900287 return new DefaultLispMapRequest(nonce, sourceEid, itrRlocs, eidRecords,
288 authoritative, mapDataPresent, probe, smr, pitr, smrInvoked);
Jian Li719b3bf2016-07-22 00:38:29 +0900289 }
290 }
Jian Li26069e22016-08-10 22:00:52 +0900291
292 /**
Jian Liedc5db12016-08-23 17:30:19 +0900293 * A LISP message reader for MapRequest message.
Jian Li26069e22016-08-10 22:00:52 +0900294 */
Jian Liedc5db12016-08-23 17:30:19 +0900295 public static final class RequestReader implements LispMessageReader<LispMapRequest> {
Jian Li26069e22016-08-10 22:00:52 +0900296
Jian Li47671902016-08-11 01:18:18 +0900297 private static final int AUTHORITATIVE_INDEX = 3;
298 private static final int MAP_DATA_PRESENT_INDEX = 2;
299 private static final int PROBE_INDEX = 1;
300 private static final int SMR_INDEX = 0;
301 private static final int PITR_INDEX = 7;
302 private static final int SMR_INVOKED_INDEX = 6;
303
Jian Li26069e22016-08-10 22:00:52 +0900304 @Override
Jian Lia7b394d2016-08-21 23:11:46 +0900305 public LispMapRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li47671902016-08-11 01:18:18 +0900306
307 if (byteBuf.readerIndex() != 0) {
308 return null;
309 }
310
311 byte typeWithFlags = byteBuf.readByte();
312
313 // authoritative -> 1 bit
314 boolean authoritative = ByteOperator.getBit(typeWithFlags, AUTHORITATIVE_INDEX);
315
316 // mapDataPresent -> 1 bit
317 boolean mapDataPresent = ByteOperator.getBit(typeWithFlags, MAP_DATA_PRESENT_INDEX);
318
319 // probe -> 1 bit
320 boolean probe = ByteOperator.getBit(typeWithFlags, PROBE_INDEX);
321
322 // smr -> 1 bit
323 boolean smr = ByteOperator.getBit(typeWithFlags, SMR_INDEX);
324
325 byte reservedWithFlags = byteBuf.readByte();
326
327 // pitr -> 1 bit
328 boolean pitr = ByteOperator.getBit(reservedWithFlags, PITR_INDEX);
329
330 // smrInvoked -> 1 bit
331 boolean smrInvoked = ByteOperator.getBit(reservedWithFlags, SMR_INVOKED_INDEX);
332
333 // let's skip reserved field, only obtains ITR counter value
334 // assume that first 3 bits are all set as 0,
335 // remain 5 bits represent Itr Rloc Counter (IRC)
Jian Lie4ba2a42016-08-29 20:24:15 +0900336 int irc = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900337
338 // record count -> 8 bits
Jian Lie4ba2a42016-08-29 20:24:15 +0900339 int recordCount = byteBuf.readUnsignedByte();
Jian Li47671902016-08-11 01:18:18 +0900340
341 // nonce -> 64 bits
342 long nonce = byteBuf.readLong();
343
Jian Li5e505c62016-12-05 02:44:24 +0900344 LispAfiAddress sourceEid = new AfiAddressReader().readFrom(byteBuf);
Jian Li47671902016-08-11 01:18:18 +0900345
Jian Lia7b394d2016-08-21 23:11:46 +0900346 // deserialize a collection of RLOC addresses
347 List<LispAfiAddress> itrRlocs = Lists.newArrayList();
Jian Lif11594a2016-10-31 18:16:02 +0900348 for (int i = 0; i < irc + 1; i++) {
Jian Li5e505c62016-12-05 02:44:24 +0900349 itrRlocs.add(new AfiAddressReader().readFrom(byteBuf));
Jian Lia7b394d2016-08-21 23:11:46 +0900350 }
Jian Li47671902016-08-11 01:18:18 +0900351
Jian Lia7b394d2016-08-21 23:11:46 +0900352 // deserialize a collection of EID records
353 List<LispEidRecord> eidRecords = Lists.newArrayList();
354 for (int i = 0; i < recordCount; i++) {
Jian Li5e505c62016-12-05 02:44:24 +0900355 eidRecords.add(new EidRecordReader().readFrom(byteBuf));
Jian Lia7b394d2016-08-21 23:11:46 +0900356 }
Jian Li47671902016-08-11 01:18:18 +0900357
358 return new DefaultRequestBuilder()
359 .withIsAuthoritative(authoritative)
360 .withIsMapDataPresent(mapDataPresent)
361 .withIsProbe(probe)
362 .withIsSmr(smr)
363 .withIsPitr(pitr)
364 .withIsSmrInvoked(smrInvoked)
365 .withNonce(nonce)
Jian Lia7b394d2016-08-21 23:11:46 +0900366 .withSourceEid(sourceEid)
367 .withEidRecords(eidRecords)
368 .withItrRlocs(itrRlocs)
Jian Li47671902016-08-11 01:18:18 +0900369 .build();
Jian Li26069e22016-08-10 22:00:52 +0900370 }
371 }
Jian Liedc5db12016-08-23 17:30:19 +0900372
373 /**
374 * A LISP message writer for MapRequest message.
375 */
376 public static final class RequestWriter implements LispMessageWriter<LispMapRequest> {
377
Jian Liedc5db12016-08-23 17:30:19 +0900378 private static final int REQUEST_SHIFT_BIT = 4;
379
380 private static final int AUTHORITATIVE_SHIFT_BIT = 3;
381 private static final int MAP_DATA_PRESENT_SHIFT_BIT = 2;
382 private static final int PROBE_SHIFT_BIT = 1;
383
384 private static final int PITR_SHIFT_BIT = 7;
385 private static final int SMR_INVOKED_SHIFT_BIT = 6;
386
387 private static final int ENABLE_BIT = 1;
388 private static final int DISABLE_BIT = 0;
389
Jian Liedc5db12016-08-23 17:30:19 +0900390 @Override
391 public void writeTo(ByteBuf byteBuf, LispMapRequest message) throws LispWriterException {
392
393 // specify LISP message type
Jian Licbc57e32016-09-14 09:06:54 +0900394 byte msgType = (byte) (LispType.LISP_MAP_REQUEST.getTypeCode() << REQUEST_SHIFT_BIT);
Jian Liedc5db12016-08-23 17:30:19 +0900395
396 // authoritative flag
397 byte authoritative = DISABLE_BIT;
398 if (message.isAuthoritative()) {
399 authoritative = (byte) (ENABLE_BIT << AUTHORITATIVE_SHIFT_BIT);
400 }
401
402 // map data present flag
403 byte mapDataPresent = DISABLE_BIT;
404 if (message.isMapDataPresent()) {
405 mapDataPresent = (byte) (ENABLE_BIT << MAP_DATA_PRESENT_SHIFT_BIT);
406 }
407
408 // probe flag
409 byte probe = DISABLE_BIT;
410 if (message.isProbe()) {
411 probe = (byte) (ENABLE_BIT << PROBE_SHIFT_BIT);
412 }
413
414 // SMR flag
415 byte smr = DISABLE_BIT;
416 if (message.isSmr()) {
417 smr = (byte) ENABLE_BIT;
418 }
419
420 byteBuf.writeByte((byte) (msgType + authoritative + mapDataPresent + probe + smr));
421
422 // PITR flag bit
423 byte pitr = DISABLE_BIT;
424 if (message.isPitr()) {
425 pitr = (byte) (ENABLE_BIT << PITR_SHIFT_BIT);
426 }
427
428 // SMR invoked flag bit
429 byte smrInvoked = DISABLE_BIT;
430 if (message.isSmrInvoked()) {
431 smrInvoked = (byte) (ENABLE_BIT << SMR_INVOKED_SHIFT_BIT);
432 }
433
434 byteBuf.writeByte((byte) (pitr + smrInvoked));
435
Jian Lie4ba2a42016-08-29 20:24:15 +0900436 // ITR Rloc count
Jian Lif11594a2016-10-31 18:16:02 +0900437 byteBuf.writeByte((byte) message.getItrRlocs().size() - 1);
Jian Liedc5db12016-08-23 17:30:19 +0900438
439 // record count
Jian Li42b3e432016-08-31 01:05:20 +0900440 byteBuf.writeByte(message.getEids().size());
Jian Liedc5db12016-08-23 17:30:19 +0900441
442 // nonce
443 byteBuf.writeLong(message.getNonce());
444
445 // Source EID AFI with Source EID address
446 AfiAddressWriter afiAddressWriter = new AfiAddressWriter();
447 afiAddressWriter.writeTo(byteBuf, message.getSourceEid());
448
449 // ITR RLOCs
450 List<LispAfiAddress> rlocs = message.getItrRlocs();
451 for (int i = 0; i < rlocs.size(); i++) {
452 afiAddressWriter.writeTo(byteBuf, rlocs.get(i));
453 }
454
455 // EID records
456 EidRecordWriter recordWriter = new EidRecordWriter();
457 List<LispEidRecord> records = message.getEids();
458
459 for (int i = 0; i < records.size(); i++) {
460 recordWriter.writeTo(byteBuf, records.get(i));
461 }
462
463 // TODO: handle Map-Reply record
464 }
465 }
Jian Li451175e2016-07-19 23:22:20 +0900466}